使用chrome://myAddon/content/Firefox插件SDK扩展中的URL



我正试图按照本教程加载一个框架脚本:

mm.loadFrameScript("chrome://myextension/content/content.js", true);

我的扩展是一个插件SDK类型。教程说我需要先在chrome.manifest中指定content。我甚至没有那个文件(只有package.jsonindex.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

我想是因为清单文件错误还是没有一起注册?但我在chrome注册页面上找不到任何关于我问题的线索。

该教程通常针对XUL或restartless/bootstrap插件。该层次结构中更合适的教程是:多进程Firefox和SDK。该页面的要点是,如果您继续使用Add-on SDK API,那么您的扩展应该只在多进程Firefox中工作,如果它不工作,那么它就是Add-on SDK中的一个错误。

通常,插件SDK扩展将使用其中一个高级API来加载内容脚本。将使用的主要API是选项卡和页面模式,但也有其他API(例如上下文菜单和页面工作者)。还有远程/父级和远程/子级的低级别API,用于处理进程和帧。

但是,如果你愿意,你可以使用框架脚本。插件SDK扩展实际上是由插件SDK包装的无重启/引导的扩展。因此,如果真的想做的话,你可以在插件SDK扩展中的自举扩展中做大多数事情。但是,最好留在插件SDK提供的API中。如果你绕过这些API,那么你就会失去插件SDK为你提供的一些优势(例如,将实际实现隐藏在不改变的API后面)。

框架脚本和内容脚本的存在是为了执行相同的功能:访问已加载到可能处于不同进程(e10s)控制下的区域中的内容(例如HTML页面)。在很大程度上,这两个不同的名字所指的事物非常相似。然而,您几乎只会看到"框架脚本"一词仅用于XUL和引导程序扩展,而"内容脚本"几乎总是指插件SDK脚本。

同样,您可能最好使用Add-on SDK API来加载用于访问可能在另一个进程中的内容的脚本。

插件SDK:使用data目录:

对于Add-on SDK扩展,不使用chrome://URL,更适合使用[加载项基本目录]/data/目录,并使用sdk/selfAPI获取文件的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个由空格分隔的字段,其中包含一个或多个可选的附加字段作为标志。

第一个字段是content,表示这是一行定义了如何解析chrome://packagename/contentURL。

第二个字段是packagename。这是一个由您创建的名称,它不能与Firefox已经使用的其他包名称或其他扩展添加的包名称冲突通常,这将是您用于插件的name,或者如果使用多个content行,则是nameid的一些排列。插件SDK的名称和ID通常是package.json文件中包含的nameid属性的值,但可能有所不同。packagename不需要是您的name或ID,它只需要对加载到Firefox中的所有内容都是唯一的。

第三个字段是包含要引用的文件的目录的URL。此URL可以是绝对的,也可以是相对于chrome.manifest文件的位置。此URL必须以/结尾。

Firefox在插件的基本目录(package.json所在的目录)中查找chrome.manifest文件。虽然使用manifest关键字可以有其他chrome.manifest文件,但这是不寻常的。

原型插件chrome.manifest将包含一行,如:

content packagename chrome/content

当使用chrome.manifestcontent行使之有效的chrome URL时,您将使用类似chrome://packagename/content/myScriptFile.js的内容。这将引用一个名为myScriptFile.js的文件,该文件位于[附加基本目录]/chrome/content/目录中。

另一个例子:
chrome.manifest:

content myAddOnName my/special/directory/

在这种情况下,chrome://myAddOnName/content/myScriptFile.js将引用文件[附加基本目录]/my/special/directory/myScriptFile.js.

您的具体问题:
虽然您表示正在遵循教程,但实际上您并没有针对chrome.manifest文件的内容这样做。当您更改该文件包含的内容时,也没有遵循content行应该包含的内容的描述。然而,即使您完全遵循了教程,您也不会得到一个正常工作的附加组件,因为教程对该文件中应该包含的内容不正确。教程中的行实际上是无效的。我已经更正了MDN文档中的那一行。

您需要在chrome.manifest.中使用什么作为行取决于您希望用于扩展的目录结构。

如果您希望content.js存在于目录[add-on base directory]/chrome/content/中并被chrome://myAddOnName/content/content.js引用,则chrome.manifestcontent行将为:

content myAddOnName chrome/content/

注意:尽管您在问题中使用了myextension(仅在chrome://URL中)作为packagename,但我在这里并没有使用它来更清楚地表明packagename应该是您选择的一个名称,它对您的插件是唯一的。我不清楚你在问题中使用myextension作为你在扩展中真正使用的占位符。如果这是你正在使用的实际文本,而不是你问题的占位符,那么我要提醒你,包名myextension不是很唯一,并且有合理的机会存在于其他随机扩展中。如果真的发生了,它可能会,也可能不会,导致您的一个或两个扩展出现故障。

SDK为框架脚本和进程脚本(除了页面mod和选项卡附加机制之外,这些机制也依赖于框架脚本)、远程/父模块和远程/子模块提供了抽象。您可以使用remote_require加载流程脚本,然后在流程脚本中使用remote/child来枚举框架脚本全局对象的sdk包装器。

最新更新