簡體   English   中英

Firefox 引導擴展:獲取瀏覽器窗口的本機 HWND 句柄

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

我有一個外部應用程序,我希望它在瀏覽器窗口頂部顯示一些信息。 我的引導擴展需要將瀏覽器窗口句柄(本機 HWND)以及有關窗口的其他一些有用信息傳遞給我的應用程序。 我能夠在它們之間進行通信,唯一缺少的是獲取 Firefox 窗口的本機 HWND 的方法。

我閱讀了很多關於它的內容,雖然我相信這是可能的,但我找不到可行的解決方案。 這是我迄今為止嘗試過的:

這個應該給我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);

上面的代碼在論壇上廣泛傳播,但我無法讓它為我工作。

另一個似乎不太准確,因為它根據窗口的類和標題獲取 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);

任何幫助,將不勝感激。

window必須是 root 一個(即ChromeWindow一個實例)

下面的代碼應該工作

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;

問題是我從xul-window-registered觀察者的subject參數中查詢了錯誤的接口。 我需要一個nsIDOMWindow而不是nsIXULWindow以便我的問題中提到的第一個代碼有效。 所以現在我正在執行以下操作,並建議使用一些代碼 @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;
}

它有效!

非常感謝您的幫助。

我也剛遇到這個,它可能很好:

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*/

用戶 'paa'回答中的代碼一直工作到 Firefox 69 版。如果您在 Firefox 70 中執行它,您將收到一個異常:

TypeError: win.QueryInterface is not a function

這很奇怪,因為變量win在 Firefox 69 和 70 中具有相同的內容。

當我執行alert(win)我在兩個瀏覽器中都得到: "[object ChromeWindow]"

並且alert(win.document.title)在兩個瀏覽器中正確顯示文檔的標題。

我下載了兩個 Firefox 版本的源代碼來比較它們並可能找到原因。 但是 Firefox 的源代碼很大(2 GB)並且幾乎完全沒有注釋。 我發現我正在浪費時間使用這種方法。

理解 Firefox 的源代碼是極其困難的,它運行在多個相互通信的進程中。 似乎變量win的內容對應於 C++ 類mozIDOMWindowProxynsChromeOuterWindowProxy 但這些似乎只是其他類的包裝類。 最后我放棄了理解 Firefox 源代碼的嘗試。

但是玩了幾個小時,我終於通過嘗試和錯誤找到了解決方案。

它甚至更簡單:

var baseWindow = win.docShell
                    .treeOwner
                    .nsIBaseWindow; 

它適用於 Firefox 70 到 79(目前是最新版本)。 但是,此新代碼不能在 Firefox 版本 <= 62 上運行。在 Firefox 62 或更早版本上,您會收到錯誤消息

TypeError: win.docShell is undefined

所以從 63 到 69 的 Firefox 允許兩個版本的代碼。 也許在版本 70 中QueryInterface()已被刪除,因為它不再需要並且已成為遺留?

注意:在 Firefox 68 中,他們進行了另一項更改。 現在有 2 個本機窗口:頂級'MozillaWindowClass'現在有一個子窗口'MozillaCompositorWindowClass ”,它在另一個進程中運行並繪制 Web 內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM