我正在尝试创建一些与某些网页的DOM一起使用的扩展程序。
我有一个代码:
document.getElementById("appcontent").addEventListener("DOMContentLoaded", function(e) {
_this._onPageLoad(e);
}, true);
但是在_onPageLoad函数中,我的全局上下文是全局窗口(ChromeWindow),而不是我的网页窗口。如何使用触发事件的窗口的全局上下文(网页)运行_onPageLoad并在此处传递参数?
谢谢。
答案 0 :(得分:1)
好吧,叠加脚本在顶级窗口的上下文中运行,即ChromeWindow
。
但是,你有点模拟另一个上下文。
_this._onPageLoad = function(window, document, e) {
// Called as .call(window, window, window.document, e);
// this === window === <content window>
// document === <content document>
};
document.getElementById("appcontent").addEventListener("DOMContentLoaded", function(e) {
let win = e.originalTarget;
if (win.ownerDocument) {
win = win.ownerDocument;
}
if (win.defaultView) {
win = win.defaultView;
}
_this._onPageLoad.call(win, win, win.document, e);
}, true);
这会通过属于该事件指示加载的文档的_onPageLoad
,this
和window
来调用您的document
。
但是,此方案不会真正重置全局,因此addEventListener
仍然会引用顶级窗口。此外,该脚本不会在沙箱中运行,并且仍具有完全权限。所以最后,这只会增加一些便利性。
也可以设置和使用真实Sandbox
,但这有点复杂。
基本思想是选择适当的主体(完全特权或内容特权),构建沙箱并将内容窗口作为sandboxPrototype
和调用.evalInSandbox(...)
提供。这或多或少是SDK
内部脚本内部所做的...但是,除非您需要一个真实且适当的安全边界(例如需要执行用户提供的或远程脚本),否则这通常是过度的。
答案 1 :(得分:0)
我的解决方案:
Lpr2.prototype._evalInSandbox = function(script, doc, data) {
var sandbox = new Components.utils.Sandbox(doc.defaultView);
sandbox.unsafeWindow = doc.defaultView.window.wrappedJSObject;
sandbox.window = doc.defaultView.window;
sandbox.document = sandbox.window.document;
sandbox.__proto__ = sandbox.window;
var functionName = 'execute_' + script.name;
var functionText = 'function ' + functionName + script.run.toString().substring(8);
functionText += '; window.lpr2data = ' + JSON.stringify(data) + '; ' + functionName + '(window, document, Zepto);';
Services.scriptloader.loadSubScript('chrome://*/content/lib/zepto.min.js', sandbox, 'UTF–8');
Components.utils.evalInSandbox(functionText, sandbox);
}
不好,但这对我来说只是一个有用的解决方案。