简体   繁体   English

Firefox 引导扩展:获取浏览器窗口的本机 HWND 句柄

[英]Firefox bootstrapped extension: Get native HWND handle of the browser window

I have an external application and I want it to display some information on top of the browser window.我有一个外部应用程序,我希望它在浏览器窗口顶部显示一些信息。 My bootstrapped extension needs to pass the browser window handle (native HWND) to my application, along with some other useful information about the window.我的引导扩展需要将浏览器窗口句柄(本机 HWND)以及有关窗口的其他一些有用信息传递给我的应用程序。 I'm able to do the communication between them, the only thing that is missing is a way to get the native HWND of the Firefox window.我能够在它们之间进行通信,唯一缺少的是获取 Firefox 窗口的本机 HWND 的方法。

I read a lot about it and although I belive it's possible, I couldn't find a working solution.我阅读了很多关于它的内容,虽然我相信这是可能的,但我找不到可行的解决方案。 Here's what I've tried so far:这是我迄今为止尝试过的:

This one should give me nsIBaseWindow , so I could get nsIBaseWindow.nativeHandle or nsIBaseWindow.ParentNativeWindow , but no success:这个应该给我nsIBaseWindow ,所以我可以获得nsIBaseWindow.nativeHandlensIBaseWindow.ParentNativeWindow ,但没有成功:

var window = SomeDOMWindow; // Informative
var baseWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                        .getInterface(Components.interfaces.nsIWebNavigation)
                        .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
                        .treeOwner
                        .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                        .getInterface(Components.interfaces.nsIXULWindow)
                        .docShell
                        .QueryInterface(Components.interfaces.nsIBaseWindow);

The above code is widely spread on forums, but I couldn't get it to work for me.上面的代码在论坛上广泛传播,但我无法让它为我工作。

The other one does not seem to be much accurate since it gets the HWND based on the window's class and title, which can lead to wrong results:另一个似乎不太准确,因为它根据窗口的类和标题获取 HWND,这可能会导致错误的结果:

Components.utils.import("resource://gre/modules/ctypes.jsm");
var lib = ctypes.open("user32.dll");
var fww = lib.declare("FindWindowW", ctypes.winapi_abi,
  ctypes.voidptr_t, ctypes.jschar.ptr, ctypes.jschar.ptr);
var sfw = lib.declare("SetForegroundWindow", ctypes.winapi_abi,
  ctypes.int32_t, ctypes.voidptr_t);
var hwnd = fww("MozillaWindowClass", document.title);
setTimeout(function() {
  sfw(hwnd);
  lib.close();
}, 3000);

Any help would be appreciated.任何帮助,将不胜感激。

window must be a root one (ie an instance of ChromeWindow ) window必须是 root 一个(即ChromeWindow一个实例)

The following code should work下面的代码应该工作

var win = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator).getMostRecentWindow("navigator:browser");
var basewindow = win.QueryInterface(Ci.nsIInterfaceRequestor)
                 .getInterface(Ci.nsIWebNavigation)
                 .QueryInterface(Ci.nsIDocShellTreeItem)
                 .treeOwner
                 .QueryInterface(Ci.nsIInterfaceRequestor)
                 .nsIBaseWindow;
var nativehandle = basewindow.nativeHandle;

The problem was that I was querying the wrong interface from the subject param in the xul-window-registered observer.问题是我从xul-window-registered观察者的subject参数中查询了错误的接口。 I need to get an nsIDOMWindow instead of an nsIXULWindow so the first code mentioned in my question works.我需要一个nsIDOMWindow而不是nsIXULWindow以便我的问题中提到的第一个代码有效。 So now I'm doing the following, with some piece of code @Noit suggested:所以现在我正在执行以下操作,并建议使用一些代码 @Noit:

observe: function(subject, topic, data) {
    var newWindow  = subject.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
    var basewindow = newWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                     .getInterface(Ci.nsIWebNavigation)
                     .QueryInterface(Ci.nsIDocShellTreeItem)
                     .treeOwner
                     .QueryInterface(Ci.nsIInterfaceRequestor)
                     .nsIBaseWindow;
    var nativehandle = basewindow.nativeHandle;
}

And it works!它有效!

Thank you very much for your help.非常感谢您的帮助。

I also just came across this, it might be nice:我也刚遇到这个,它可能很好:

Cu.import("resource://gre/modules/ctypes.jsm");

/*start getcursorpos*/
var lib = ctypes.open("user32.dll");

/*foreground window stuff*/
var FindWindowA = lib.declare('FindWindowA', ctypes.winapi_abi, ctypes.uint32_t, ctypes.jschar.ptr, ctypes.jschar.ptr)
var GetForegroundWindow = lib.declare('GetForegroundWindow', ctypes.winapi_abi, ctypes.uint32_t)
function doFindWindow() {
    var wm = Cc['@mozilla.org/appshell/window-mediator;1'].getService(Ci.nsIWindowMediator);
    var title = wm.getMostRecentWindow('navigator:browser').gBrowser.contentDocument.title;
    Cu.reportError('title=' + title)
    var ret = FindWindowA('', title + ' - Mozilla Firefox');
    //var ret = GetForegroundWindow();

    Cu.reportError(ret);
}
/*end foreground window stuff*/

The code in the answer of user 'paa' worked until Firefox version 69. If you execute it in Firefox 70 you will get an exception:用户 'paa'回答中的代码一直工作到 Firefox 69 版。如果您在 Firefox 70 中执行它,您将收到一个异常:

TypeError: win.QueryInterface is not a function

This is strange because the variable win has the same content in Firefox 69 and 70.这很奇怪,因为变量win在 Firefox 69 和 70 中具有相同的内容。

When I execute alert(win) I get: "[object ChromeWindow]" in both browsers.当我执行alert(win)我在两个浏览器中都得到: "[object ChromeWindow]"

And alert(win.document.title) displays correctly the title of the document in both browsers.并且alert(win.document.title)在两个浏览器中正确显示文档的标题。

I downloaded the sourcecode of both Firefox versions to compare them and possibly find the cause.我下载了两个 Firefox 版本的源代码来比较它们并可能找到原因。 But the source code of Firefox is huge (2 Gigabyte) and nearly completely free of comments.但是 Firefox 的源代码很大(2 GB)并且几乎完全没有注释。 I found that I'm wasting my time with that approach.我发现我正在浪费时间使用这种方法。

It is extremely difficult to understand sourcecode of Firefox which runs spread over multiple processes which communicate with each other.理解 Firefox 的源代码是极其困难的,它运行在多个相互通信的进程中。 It seems that the content of the variable win corresponds to the C++ class mozIDOMWindowProxy or nsChromeOuterWindowProxy .似乎变量win的内容对应于 C++ 类mozIDOMWindowProxynsChromeOuterWindowProxy But these seem to be only wrapper classes for other classes.但这些似乎只是其他类的包装类。 Finally I gave up trying to understand Firefox sourcecode.最后我放弃了理解 Firefox 源代码的尝试。

But playing around for some hours I finally found a solution by try and error.但是玩了几个小时,我终于通过尝试和错误找到了解决方案。

It is even simpler:它甚至更简单:

var baseWindow = win.docShell
                    .treeOwner
                    .nsIBaseWindow; 

It works on Firefox 70 up to 79 (which is currently the latest version).它适用于 Firefox 70 到 79(目前是最新版本)。 However this new code does not run on Firefox versions <= 62. On Firefox 62 or older you get the error但是,此新代码不能在 Firefox 版本 <= 62 上运行。在 Firefox 62 或更早版本上,您会收到错误消息

TypeError: win.docShell is undefined

So the Firefoxes from 63 to 69 allow both versions of code.所以从 63 到 69 的 Firefox 允许两个版本的代码。 Maybe in version 70 the QueryInterface() has been removed because it is not needed anymore and has become legacy?也许在版本 70 中QueryInterface()已被删除,因为它不再需要并且已成为遗留?

NOTE: In Firefox 68 they made another change.注意:在 Firefox 68 中,他们进行了另一项更改。 Now there are 2 native windows: The toplevel 'MozillaWindowClass' now has a child window 'MozillaCompositorWindowClass ' which runs in another process and draws the web content.现在有 2 个本机窗口:顶级'MozillaWindowClass'现在有一个子窗口'MozillaCompositorWindowClass ”,它在另一个进程中运行并绘制 Web 内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM