在 Firefox Add-on SDK 扩展中使用 chrome://myAddon/content/ URL
Use a chrome://myAddon/content/ URL in Firefox Add-on SDK extension
我正在尝试按照此 tutorial:
加载框架脚本
mm.loadFrameScript("chrome://myextension/content/content.js", true);
我的扩展是 Add-on SDK 类型。教程说我需要先在 chrome.manifest
中指定 content
。我什至没有那个文件(只有 package.json
和 index.js
)。所以我用一行创建了 myextension/chrome.manifest
:
content content.js
并创建了一个文件 myextension/content/content.js
:
console.log("content script executed");
问题是,当 mm.loadFrameScript("chrome://myextension/content/content.js", true);
在 index.js
中执行时,出现错误:
No chrome package registered for chrome://myextension/content/content.js
我猜是因为manifest文件错误或者没有一起注册?但是我在 chrome registration 页面上找不到任何关于我的问题的线索。
该教程通常针对 XUL or restartless/bootstrap add-ons. A more appropriate tutorial in that hierarchy is: Multiprocess Firefox and the SDK. The gist of that page is that if you stay with the Add-on SDK APIs your extension should just work in multiprocess Firefox, and that if it doesn't then it is a bug in the Add-on SDK。
一般来说,Add-on SDK 扩展会使用 High Level APIs to load content scripts. The primary APIs which would be used are tabs and page-mod, but there are others (e.g. context-menu and page-worker). There are also the Low-Level APIs of remote/parent and remote/child which deal with processes and frames 之一。
但是,如果您愿意,可以使用 frame scripts。附加 SDK 扩展实际上是 restartless/bootstrapped 由附加 SDK 包装的扩展。因此,如果您 真的 想要这样做,您可以在附加 SDK 扩展中完成大多数可以在 bootstrapped 扩展中完成的事情。但是,最好留在附加 SDK 提供的 API 中。如果您绕过这些 API,那么您将失去附加 SDK 为您提供的一些优势(例如,将实际实现隐藏在不打算更改的 API 后面)。
框架脚本和内容脚本的存在是为了执行相同的功能:访问已加载到可能受不同进程 (e10s) 控制的区域的内容(例如 HTML 页面)。在很大程度上,这两个不同名称所指的事物非常相似。但是,您几乎只会看到术语 "frame scripts" 仅用于 XUL 和 bootstrap 扩展,而 "content scripts" 几乎总是指附加 SDK 脚本。
同样,您最好使用附加 SDK API 来加载您正在使用的脚本,以访问可能在另一个进程中的内容。
附加SDK:使用data
目录:
对于 Add-on SDK 扩展,使用 chrome://
URL 更合适的是 [add-on base directory]/data/ 目录并使用 sdk/self
API 获取对文件的 URL 引用。你会这样做:
var self = require("sdk/self");
let frameScriptUrl = self.data.url("content.js")
那么您的 loadFrameScript()
行将是:
mm.loadFrameScript(frameScriptUrl, true);
使用chrome.manifest:
content
行:
chrome.manifest 文件的 content
行是:
content packagename uri/to/files/ [flags]
这是至少 3 个由空格分隔的字段,以及 flags 的一个或多个可选附加字段。
第一个字段是 content
,表示这是定义如何解析 chrome://packagename/content
URL 的行。
第二个字段是 packagename
。这是您自己创建的名称,不能与 Firefox 已经使用的其他包名称或其他扩展添加的包名称冲突。 通常,这将是您用于附加组件的 name
,或者 name
或 id
的某些排列,如果使用多个 content
行。您的 Add-on SDK 的名称和 ID 通常是 name
and id
properties you included in your package.json file, but may be somewhat different 的值。 packagename
不需要是您的 name
或 ID,它只需要对加载到 Firefox 中的所有内容都是唯一的。
第三个字段是 URL 到包含您要引用的文件的目录。这个 URL 可以是绝对的,也可以是相对于 chrome.manifest 文件的位置。此 URL 必须以 /
.
结尾
Firefox 在您的加载项的基本目录中查找 chrome.manifest 文件(与 package.json 位于)。虽然可以使用 manifest
关键字获得额外的 chrome.manifest 文件,但这并不常见。
原型附加组件 chrome.manifest 将包含如下一行:
content packagename chrome/content
当在你的 chrome.manifest 中使用 chrome URL 由 content
行生效时,你会使用一些东西喜欢 chrome://packagename/content/myScriptFile.js
。这将引用 [add-on base directory]/chrome/content/ 目录中名为 myScriptFile.js
的文件。
又如:
chrome.manifest:
content myAddOnName my/special/directory/
在这种情况下,chrome://myAddOnName/content/myScriptFile.js
将引用文件 [add-on base directory]/my/special/directory/myScriptFile.js.
您的具体问题:
虽然您说您正在关注 tutorial, you did not actually do so for the contents of your chrome.manifest file. Nor when you changed what that file contained did you follow the description of what the content
line should contain. However, even if you had followed the tutorial exactly, you would not have ended up with a functioning add-on because the tutorial was incorrect as to what should be in that file. The line in the tutorial was actually invalid. I have corrected that line in the MDN documentation.
您需要在 chrome.manifest 行中使用什么取决于您希望用于扩展的目录结构。
如果您希望 content.js 存在于目录 [add-on base directory]/chrome/content/ 并被 chrome://myAddOnName/content/content.js
引用,那么 chrome.manifest 的 content
行将是:
content myAddOnName chrome/content/
注意:即使您在问题中(仅在 chrome://
URL 中)为 packagename
使用了 myextension
,我也没有在这里尝试使用它更清楚地表明 packagename
应该是您选择的名称,该名称对于您的附加组件是唯一的。我不清楚您在问题中使用 myextension
作为您在扩展中实际使用的内容的占位符。如果这是您使用的实际文本而不是您问题的占位符,那么我会提醒您包名 myextension
不是很独特并且有合理的机会存在于其他一些随机扩展中。如果是这样,它可能会也可能不会导致您的一个或两个扩展出现故障。
SDK 为框架脚本和进程脚本提供了抽象(除了页面-mod 和选项卡附加机制,这些机制也依赖于幕后的框架脚本),remote/parent and remote/child mod规则。您可以使用 remote_require
加载流程脚本,然后在流程脚本中使用 remote/child 来枚举框架脚本全局对象的 sdk 包装器。
我正在尝试按照此 tutorial:
加载框架脚本mm.loadFrameScript("chrome://myextension/content/content.js", true);
我的扩展是 Add-on SDK 类型。教程说我需要先在 chrome.manifest
中指定 content
。我什至没有那个文件(只有 package.json
和 index.js
)。所以我用一行创建了 myextension/chrome.manifest
:
content content.js
并创建了一个文件 myextension/content/content.js
:
console.log("content script executed");
问题是,当 mm.loadFrameScript("chrome://myextension/content/content.js", true);
在 index.js
中执行时,出现错误:
No chrome package registered for chrome://myextension/content/content.js
我猜是因为manifest文件错误或者没有一起注册?但是我在 chrome registration 页面上找不到任何关于我的问题的线索。
该教程通常针对 XUL or restartless/bootstrap add-ons. A more appropriate tutorial in that hierarchy is: Multiprocess Firefox and the SDK. The gist of that page is that if you stay with the Add-on SDK APIs your extension should just work in multiprocess Firefox, and that if it doesn't then it is a bug in the Add-on SDK。
一般来说,Add-on SDK 扩展会使用 High Level APIs to load content scripts. The primary APIs which would be used are tabs and page-mod, but there are others (e.g. context-menu and page-worker). There are also the Low-Level APIs of remote/parent and remote/child which deal with processes and frames 之一。
但是,如果您愿意,可以使用 frame scripts。附加 SDK 扩展实际上是 restartless/bootstrapped 由附加 SDK 包装的扩展。因此,如果您 真的 想要这样做,您可以在附加 SDK 扩展中完成大多数可以在 bootstrapped 扩展中完成的事情。但是,最好留在附加 SDK 提供的 API 中。如果您绕过这些 API,那么您将失去附加 SDK 为您提供的一些优势(例如,将实际实现隐藏在不打算更改的 API 后面)。
框架脚本和内容脚本的存在是为了执行相同的功能:访问已加载到可能受不同进程 (e10s) 控制的区域的内容(例如 HTML 页面)。在很大程度上,这两个不同名称所指的事物非常相似。但是,您几乎只会看到术语 "frame scripts" 仅用于 XUL 和 bootstrap 扩展,而 "content scripts" 几乎总是指附加 SDK 脚本。
同样,您最好使用附加 SDK API 来加载您正在使用的脚本,以访问可能在另一个进程中的内容。
附加SDK:使用data
目录:
对于 Add-on SDK 扩展,使用 chrome://
URL 更合适的是 [add-on base directory]/data/ 目录并使用 sdk/self
API 获取对文件的 URL 引用。你会这样做:
var self = require("sdk/self");
let frameScriptUrl = self.data.url("content.js")
那么您的 loadFrameScript()
行将是:
mm.loadFrameScript(frameScriptUrl, true);
使用chrome.manifest:
content
行:
chrome.manifest 文件的 content
行是:
content packagename uri/to/files/ [flags]
这是至少 3 个由空格分隔的字段,以及 flags 的一个或多个可选附加字段。
第一个字段是 content
,表示这是定义如何解析 chrome://packagename/content
URL 的行。
第二个字段是 packagename
。这是您自己创建的名称,不能与 Firefox 已经使用的其他包名称或其他扩展添加的包名称冲突。 通常,这将是您用于附加组件的 name
,或者 name
或 id
的某些排列,如果使用多个 content
行。您的 Add-on SDK 的名称和 ID 通常是 name
and id
properties you included in your package.json file, but may be somewhat different 的值。 packagename
不需要是您的 name
或 ID,它只需要对加载到 Firefox 中的所有内容都是唯一的。
第三个字段是 URL 到包含您要引用的文件的目录。这个 URL 可以是绝对的,也可以是相对于 chrome.manifest 文件的位置。此 URL 必须以 /
.
Firefox 在您的加载项的基本目录中查找 chrome.manifest 文件(与 package.json 位于)。虽然可以使用 manifest
关键字获得额外的 chrome.manifest 文件,但这并不常见。
原型附加组件 chrome.manifest 将包含如下一行:
content packagename chrome/content
当在你的 chrome.manifest 中使用 chrome URL 由 content
行生效时,你会使用一些东西喜欢 chrome://packagename/content/myScriptFile.js
。这将引用 [add-on base directory]/chrome/content/ 目录中名为 myScriptFile.js
的文件。
又如:
chrome.manifest:
content myAddOnName my/special/directory/
在这种情况下,chrome://myAddOnName/content/myScriptFile.js
将引用文件 [add-on base directory]/my/special/directory/myScriptFile.js.
您的具体问题:
虽然您说您正在关注 tutorial, you did not actually do so for the contents of your chrome.manifest file. Nor when you changed what that file contained did you follow the description of what the content
line should contain. However, even if you had followed the tutorial exactly, you would not have ended up with a functioning add-on because the tutorial was incorrect as to what should be in that file. The line in the tutorial was actually invalid. I have corrected that line in the MDN documentation.
您需要在 chrome.manifest 行中使用什么取决于您希望用于扩展的目录结构。
如果您希望 content.js 存在于目录 [add-on base directory]/chrome/content/ 并被 chrome://myAddOnName/content/content.js
引用,那么 chrome.manifest 的 content
行将是:
content myAddOnName chrome/content/
注意:即使您在问题中(仅在 chrome://
URL 中)为 packagename
使用了 myextension
,我也没有在这里尝试使用它更清楚地表明 packagename
应该是您选择的名称,该名称对于您的附加组件是唯一的。我不清楚您在问题中使用 myextension
作为您在扩展中实际使用的内容的占位符。如果这是您使用的实际文本而不是您问题的占位符,那么我会提醒您包名 myextension
不是很独特并且有合理的机会存在于其他一些随机扩展中。如果是这样,它可能会也可能不会导致您的一个或两个扩展出现故障。
SDK 为框架脚本和进程脚本提供了抽象(除了页面-mod 和选项卡附加机制,这些机制也依赖于幕后的框架脚本),remote/parent and remote/child mod规则。您可以使用 remote_require
加载流程脚本,然后在流程脚本中使用 remote/child 来枚举框架脚本全局对象的 sdk 包装器。