gpt4 book ai didi

javascript - 在 Firefox 无重启附加组件中,如何在新窗口打开时运行代码(监听窗口打开)?

转载 作者:行者123 更新时间:2023-11-29 18:09:02 25 4
gpt4 key购买 nike

我开始构建一个无需重新启动的 Firefox 附加组件,但我在设置 bootstrap.js 时遇到了问题。每个人似乎都同意 bootstrap.js 的核心是相当多的样板代码,大致如下:

const Cc = Components.classes;
const Ci = Components.interfaces;

function startup() {
let wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
let windows = wm.getEnumerator("navigator:browser");
while (windows.hasMoreElements()) {
let domWindow = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
// then can control what happens with domWindow.document
}
}
function shutdown() {}
function install() {}
function uninstall() {}

此代码有效,我可以控制现有窗口中的内容。例如,domWindow.alert("text") 成功地在当前打开的每个窗口上创建了一个标准的提示“text”。

但是,我找不到任何允许我在新窗口中执行操作的代码;即在脚本运行后创建的那些。处理新窗口的创建并获得对它们的控制权的正确方法是什么,以至于我可以在创建新窗口时从一个窗口获得另一个“文本”警报?

编辑:使用 nsWindowMediator 类和来自 MDN 的代码示例,我现在有这个:

var windowListener = {
onOpenWindow: function (aWindow) {
try {
let domWindow = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
domWindow.addEventListener("load", function () {
domWindow.removeEventListener("load", arguments.callee, false);
//window has now loaded now do stuff to it
domWindow.alert("text");
}, false);
} catch (err) {
Services.prompt.alert(null, "Error", err);
}
},
onCloseWindow: function (aWindow) {},
onWindowTitleChange: function (aWindow, aTitle) {}
};

function startup(aData, aReason) {
// Load into any existing windows
try {
let wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
let windows = wm.getEnumerator("navigator:browser");
while (windows.hasMoreElements()) {
let domWindow = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
loadIntoWindow(domWindow);
}
} catch (err) {
Services.prompt.alert(null, "Error", err);
}

Services.wm.addListener(windowListener);
}

但是,onOpenWindow 调用仍然没有输出——“文本”警报没有出现,catch block 中的错误警报也没有出现。我可以确认实际上正在输入 onOpenWindow;如果我将 Services.prompt.alert() 放在 onOpenWindow 的开头,我会在创建新窗口时收到警报。不幸的是,我收到无限循环的警报,我不知道为什么。

最佳答案

However, I can't find any code that will allow me to do things in new windows; i.e. those created after the script runs. What is the correct way to handle the creation of new windows and gain control over them, to the point where I could get another "text" alert from one when it is created?

打开每个窗口时对其进行操作的正确方法是使用 addListener()来自 nsIWindowMediator .下面的示例代码就是这样做的。 nsIWindowMediator 包含在 Services.jsm 中并通过 Services.wm.addListener(WindowListener) 访问。为了使用窗口监听器,你必须传递给它一个nsIWindowMediatorListener。 ( ref2 ) 对象。 nsIWindowMediatorListener 包含三个键:onOpenWindowonCloseWindowonWindowTitleChange。每个都应定义为一个函数,当适当的事件发生时将调用该函数。

MDN 文档 How to convert an overlay extension to restartless在“Step 9: bootstrap.js”中包含一个基本的例子 bootstrap.js这将为每个当前打开的 browser 窗口和将来打开的任何 browser 窗口运行函数 loadIntoWindow(window) 中的代码。我在几个不同的附加组件中使用了由此修改的代码。该示例与您已经使用的代码非常相似。例子是(稍作修改):

const Ci = Components.interfaces;

Components.utils.import("resource://gre/modules/Services.jsm");

function startup(data,reason) {
// Load this add-ons module(s):
Components.utils.import("chrome://myAddon/content/myModule.jsm");
// Do whatever initial startup stuff is needed for this add-on.
// Code is in module just loaded.
myModule.startup();

// Make changes to the Firefox UI to hook in this add-on
forEachOpenWindow(loadIntoWindow);
// Listen for any windows that open in the future
Services.wm.addListener(WindowListener);
}

function shutdown(data,reason) {
if (reason == APP_SHUTDOWN)
return;

// Unload the UI from each window
forEachOpenWindow(unloadFromWindow);
// Stop listening for new windows to open.
Services.wm.removeListener(WindowListener);

// Do whatever shutdown stuff you need to do on add-on disable
myModule.shutdown();

// Unload the module(s) loaded specific to this extension.
// Use the same URL for your module(s) as when loaded:
Components.utils.unload("chrome://myAddon/content/myModule.jsm");

// HACK WARNING: The Addon Manager does not properly clear all add-on related caches
// on update. In order to fully update images and locales, their
// caches need clearing here.
Services.obs.notifyObservers(null, "chrome-flush-caches", null);
}

function install(data,reason) { }

function uninstall(data,reason) { }

function loadIntoWindow(window) {
/* call/move your UI construction function here */
}

function unloadFromWindow(window) {
/* call/move your UI tear down function here */
}

function forEachOpenWindow(todo) {
// Apply a function to all open browser windows
var windows = Services.wm.getEnumerator("navigator:browser");
while (windows.hasMoreElements())
todo(windows.getNext().QueryInterface(Ci.nsIDOMWindow));
}

var WindowListener = {
onOpenWindow: function(xulWindow) {
var window = xulWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
function onWindowLoad() {
window.removeEventListener("load",onWindowLoad);
// Only add UI changes if this is a browser window
if (window.document.documentElement.getAttribute("windowtype")
== "navigator:browser")
loadIntoWindow(window);
}
window.addEventListener("load",onWindowLoad);
},
onCloseWindow: function(xulWindow) { },
onWindowTitleChange: function(xulWindow, newTitle) { }
};

虽然您可能想在 bootstrap.js 代码中做更多的事情,但上面的代码组织得相当好,并且将所有代码都加载到 Firefox UI 中 loadIntoWindow(window) 并在 unloadFromWindow(window) 中卸载 UI。但是,应该注意的是,一些 UI 元素您应该只添加/删除一次(例如 australis 小部件,如按钮)和其他元素(例如直接更改 Firefox DOM)必须在每个窗口中添加一次。

Unfortunately, I get an infinite loop of alerts and I have no idea why.

此示例与您当前使用的示例之间的显着差异之一是对已打开窗口类型的测试。这样做是为了让我们只作用于新打开的窗口,即 浏览器 窗口,而不是所有新打开的窗口:

if (window.document.documentElement.getAttribute("windowtype") == "navigator:browser")
loadIntoWindow(window);

您描述的无限循环 alert() 弹出窗口的问题是由于未检查以确保您仅在浏览器 窗口上操作所致。 alert() 弹出窗口是一个窗口。因此,您正在为您打开的每个 alert() 窗口调用 alert(),当然,这只会打开另一个 alert() 窗口你称之为 alert()。这是你的无限循环。

其他引用资料:
1. Working with windows in chrome code

关于javascript - 在 Firefox 无重启附加组件中,如何在新窗口打开时运行代码(监听窗口打开)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29178158/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com