我开始构建一个不会重启的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")
成功创建一个标准警报,在当前打开的每个窗口上说“文本”。
但是,我找不到任何可以在新窗口中执行操作的代码。即在脚本运行后创建的那些。什么是处理新窗口并获得对它们的控制权的正确方法,以至于我可以在创建新窗口时从另一个窗口收到“文本”警报?
编辑:使用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块中也不会出现错误警报。我可以确认onOpenWindow实际上是在输入的;如果将aServices.prompt.alert()
放在onOpenWindow的开头,则在创建新窗口时会收到警报。不幸的是,我收到了无限的警报循环,我也不知道为什么。
但是,我找不到任何可以在新窗口中执行操作的代码。即在脚本运行后创建的那些。什么是处理新窗口并获得对它们的控制权的正确方法,以至于我可以在创建新窗口时从另一个窗口收到“文本”警报?
行动打开时每个窗口上正确的方法是使用addListener()
从nsIWindowMediator。下面的示例代码执行此操作。nsIWindowMediator包含在Services.jsm中,可通过访问Services.wm.addListener(WindowListener)
。为了使用窗口侦听器,您必须向其传递nsIWindowMediatorListener(ref2)对象。一个nsIWindowMediatorListener包含三个按键:onOpenWindow
,onCloseWindow
,和onWindowTitleChange
。每个都应定义为一个函数,当发生适当的事件时将调用该函数。
MDN文档“如何在第9步:bootstrap.js ”中将覆盖扩展名转换为不重启,包含一个基本bootstrap.js的示例,它将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)
以及内的UI上unloadFromWindow(window)
。但是,应该注意的是,您应该只添加/删除一次的某些UI元素(例如,澳大利亚小部件,如按钮),而其他元素(例如,直接更改Firefox DOM)则必须在每个窗口中添加一次。
不幸的是,我收到了无限的警报循环,我也不知道为什么。
此示例与当前使用的示例之间的重大区别之一是测试已打开的窗口的类型。这样做是为了使我们仅在新打开的窗口(即浏览器窗口)上起作用,而不是在所有新打开的窗口上起作用:
if (window.document.documentElement.getAttribute("windowtype") == "navigator:browser")
loadIntoWindow(window);
您描述的出现alert()
弹出式窗口无限循环的问题是由于未检查确保仅在浏览器窗口上执行操作而引起的。在alert()
弹出的窗口。因此,您在调用打开的alert()
每个alert()
窗口,当然,只打开了另一个alert()
要调用的窗口alert()
。这是您的无限循环。
其他参考:
1.在Chrome代码中使用Windows
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句