3

我正在研究引导扩展。查看其中一些扩展的代码,我看到了很多变量、常量和函数声明。

它们都在窗口对象中声明吗?命名空间污染/冲突没有问题吗?

我将每一件事都包装在我所做的覆盖扩展中的一个对象/命名空间中。自举扩展在这方面有什么不同吗?

我注意到所有这些都bootstrapped.js使用相同/标准的函数名称。这是否意味着引导扩展是沙盒或封闭的?

4

1 回答 1

3

bootstrap.js范围_

它们都在窗口对象中声明吗?命名空间污染/冲突没有问题吗?

...

我注意到所有 bootstrapped.js 都使用相同/标准的函数名称。这是否意味着引导扩展是沙盒或封闭的?

扩展@paa 评论:bootstrap.js确实有它自己的范围。

AddonManager将为每个 bootstrap.js 创建一个新范围(或“命名空间”,如果您愿意)。现在实现使用Components.utils.Sandbox,但这是一个实现细节。

这意味着没有window对象。bootstrap.js将在每个 Firefox 进程中加载​​一次并且没有window对象。这与覆盖脚本非常不同,覆盖脚本将在每个新窗口中加载一次,并window与 Firefox 代码和来自其他附加组件的覆盖脚本共享一个公共范围(对象本身)。

这也意味着引导加载项可以在其范围内(他们的个人沙盒)自由选择他们喜欢的任何名称,而不必担心与其他加载项发生冲突,只要这些名称通常在 Javascript 中有效。

唯一的例外是

  • 入口点函数名称插件必须实现插件管理器将调用的名称,因此具有特殊含义(startup, shutdown, install, uninstall),
  • Sandbox( Components, 和 Javascript 内置插件 (如Object, String, Array,Map等)附带的预定义内容)
  • AddonManager将注入的东西(如__SCRIPT_URI_SPEC__, ADDON_*,APP_*常量)。

从 Firefox 30 开始的预定义名称的完整列表:

Components.utils.reportError(Object.getOwnPropertyNames(this).join(", "));

// Object, Function, eval, Components, XPCNativeWrapper, dump, debug,
// importFunction, IDBCursor, IDBCursorWithValue, EventTarget, IDBDatabase,
// IDBFactory, FileHandle, IDBFileHandle, IDBIndex, IDBKeyRange,
// IDBObjectStore, IDBRequest, IDBOpenDBRequest, IDBTransaction, Event,
// IDBVersionChangeEvent, indexedDB, APP_STARTUP, APP_SHUTDOWN, ADDON_ENABLE,
// ADDON_DISABLE, ADDON_INSTALL, ADDON_UNINSTALL, ADDON_UPGRADE,
// ADDON_DOWNGRADE, Worker, ChromeWorker, __SCRIPT_URI_SPEC__, undefined,
// Array, Boolean, JSON, Date, Math, isNaN, isFinite, parseFloat, parseInt,
// NaN, Infinity, Number, String, escape, unescape, uneval, decodeURI,
// encodeURI, decodeURIComponent, encodeURIComponent, RegExp, Error,
// InternalError, EvalError, RangeError, ReferenceError, SyntaxError,
// TypeError, URIError, Iterator, StopIteration, Int8Array, Uint8Array,
// Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array,
// Float64Array, Uint8ClampedArray, DataView, ArrayBuffer, Proxy, WeakMap,
// Map, Set, Intl

操作其他范围

但是,bootstrap add-on 在与其他作用域交互时仍然需要考虑周到,避免发生冲突,例如 windows、JS 代码模块、其他 add-on bootstrap 作用域等。操作其他范围也可能导致附加引导范围的泄漏。

例如

Cu.import("resource://gre/modules/Services.jsm");
Services.foo = "bar";

这将为共享代码模块中的对象添加一个foo属性。所有其他附加组件和浏览器代码也会看到,因此可能会导致冲突,并且通常不会污染共享命名空间- 规则适用。ServicesServices.jsmServices.foo

此外,当您的附加组件获取时,shutdown您必须再次删除Services.foo,否则Services.jsm范围将保留对它的引用,并且由于foo(string "bar") 的值存在于您的引导隔间内,因此它将保持引导隔间的活动,因为该引用并有效地造成内存泄漏(在 mozilla 俚语中称为Zombie 隔间)。

或者

// Get the most recent browser window
var browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
browserWindow.doSomething = function() {
  browserWindow.alert("hello world");
};

这相当于有一个覆盖脚本:

function doSomething() {
  alert("hello world");
}

两者都会doSomething向浏览器窗口范围添加一个新名称,因此该名称可能会与其他加载项发生冲突并且不会污染共享命名空间- 规则适用。同样,这可能会以与上一个示例相同的方式泄漏,因此引导加载项必须shutdown再次删除属性以避免这种情况。

于 2014-06-25T22:07:55.860 回答