您首先使用的可能原因executionContext
是,否则内容将直接定义在 上content
,这可能与网站、其他附加组件冲突和/或泄漏到网站。所以最好在你加载你的东西的窗口周围有一个包装器。
我刚刚编写了一个基于框架脚本的最小“内容脚本”加载器。没什么,但应该完成工作。我在 FX 24 上验证了 jquery 可以在其中工作,并且这些内容不会泄漏到内容窗口中。
// Frame scripts share a scope, so better not mess them up ;)
(function() {
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
const utils = {};
try {
throw new Error();
}
catch (ex) {
let url = ex.fileName.replace(/\/[^\/]*?$/, "/");
const ssm = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
Object.defineProperties(utils, {
"url": {
enumerable: true,
value: function(fn) {
return url + fn;
}
},
"mayLoad": {
enumerable: true,
value: function(o) {
let node = (o.document || o);
let window = (o.ownerDocument || o).defaultView || o;
try {
return window.location != "about:blank" &&
!ssm.isSystemPrincipal(node.nodePrincipal);
}
catch (ex) {
Cu.reportError(ex);
return false;
}
}
},
});
Object.freeze(utils);
}
try {
const loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader);
// Create a context object for each window that get's loaded.
// Or use DOMWindowCreated, like the add-on manager does to install
// the InstallTrigger.
addEventListener("DOMContentLoaded", function(e) {
let window = e.target.defaultView;
if (!utils.mayLoad(window)) {
// Refuse to load in chrome (system) pages.
return;
}
// Need to create our context in the window scope (compartment).
// The reason to create a wrapper/context it in the first place
// is to avoid clashes with other add-ons, the website itself,
// etc.
let executionContext = Cu.createObjectIn(window);
// Wire up the window to be the prototype.
executionContext.__proto__ = window;
// Add some useful stuff you want the "content scripts" to have
// access to.
Object.defineProperties(executionContext, {
"sendAsyncMessage": {
enumerable: true,
value: sendAsyncMessage.bind(null)
},
"reportError": {
enumerable: true,
value: Cu.reportError.bind(Cu)
},
"doSomething": {
enumerable: true,
value: function(arg) {
Cu.reportError("did something " + arg);
}
},
"loadScript": {
enumerable: true,
value: function(fn) {
loader.loadSubScript(utils.url(fn), executionContext);
}
}
});
// Normalize the properties, i.e. move them over to the correct
// window scope (compartment);
Cu.makeObjectPropsNormal(executionContext);
// Load initial scripts
executionContext.loadScript("test.js");
});
}
catch (ex) {
content.console.error(ex);
}
})();
关键点是:
- 用于
Cu.createObjectIn(window)
获得正确的范围(Spidermonkey 中的隔间)并避免NS_ERROR_XPC_BAD_OP_ON_WN_PROTO
异常。
Cu.makeObjectPropsNormal()
如果您在上下文中定义其他内容,请使用。
- 不要试图将东西注入 chrome 特权窗口 (
utils.mayLoad
)。
throw new Error()
try-catch 只是获取当前 URI ( ) 的可靠技巧,以便ex.fileName
以后在加载脚本时允许指定相对路径。