Firefox Add-on SDK上下文菜单与page-mod加载的内容脚本进行通信

时间:2016-06-15 14:54:03

标签: firefox firefox-addon firefox-addon-sdk

我正在使用Firefox Add-on SDK创建一个Firefox附加组件。这个附加组件做了两件事:

  1. 使用sdk/page-mod将内容脚本注入每个页面。
  2. 使用sdk/context-menu添加上下文菜单项。
  3. 我希望当用户单击上下文菜单项时,加载项将调用由PageMod()加载的内容脚本中的函数。

1 个答案:

答案 0 :(得分:1)

除非您的page-mod脚本正在执行其他操作,否则使用context-menu contentScript or contentScriptFile属性加载它可能更合适。或者,使用此方法加载上下文菜单所需的部分。如何最好地分割您正在使用的脚本取决于您实际在做什么。如果没有您的更多信息,很难提供具体的建议。

在不同时间或通过不同方法加载的内容脚本之间进行通信:

没有直接做你想要的方法。未通过相同方法同时加载的内容脚本被加载到不同的上下文中。他们无法直接调用它们之间的功能。同时加载的多个内容脚本和相同的方法共享相同的上下文/范围,可以直接调用它们之间的函数。

但是,你可以communicate between content scripts。如果他们加载到同一页面,那么您需要使用主加载项脚本从一个内容脚本与另一个内容脚本进行通信,以便首先从一个内容脚本接收消息。然后,您的主要附加脚本将需要向第二个内容脚本发送第二条消息(可能包含完全相同的数据)。换句话说,您的主要附加代码需要在两个内容脚本之间中继消息。

对于通过不同方法加载到同一页面的内容脚本(例如,一个使用page-mod,另一个作为上下文菜单项 - 您感兴趣的情况),您可以使用{{ 3}}或DOM postMessage() API。两者都可用于在两个脚本之间发送您想要的任何JSON可序列化数据。 DOM postMessage()API提供了更高的安全性,但有点复杂。有了它,您还必须过滤掉随机代码在其上发送的任何其他"message"事件。如果要根据消息内容在已发布的附加执行函数中包含代码,则应该使用它。这是一个安全问题,具体取决于您对消息的处理方式。

实施例

以下代码会将page-mod脚本加载到与"*.mozilla.org"匹配的每个页面中。它还在链接上显示的相同页面中创建上下文菜单项。单击上下文菜单项将从上下文菜单内容脚本发送一个事件,其中包含显示上下文菜单的URL的数据。 page-mod脚本将接收自定义事件。然后,page-mod脚本将发出一个警告,其中包含该链接的URL。

var pageMod = require("sdk/page-mod");

pageMod.PageMod({
  include: "*.mozilla.org",
  contentScript: 'function contextMenuAlert(href) {'
               + '    window.alert("The context menu click on a link with URL:\\n" + href);'
               + '};'
               + 'window.addEventListener("myAddonId-contextMenu-clicked",'
               + '    function(event){contextMenuAlert(event.detail);});'
});

//Context menu
let cm = require("sdk/context-menu");
cm.Item({
    label: "Alert link URL",
    context: [
        cm.URLContext(["*.mozilla.org"]),
        cm.SelectorContext("a[href]")
    ],
    contentScript: 'self.on("click", function (node, data) {'
                 + '    var event = new CustomEvent("myAddonId-contextMenu-clicked",'
                 + '                                {detail:node.href});'
                 + '    window.dispatchEvent(event);'
                 + '});'
});

上面的代码生成一个上下文菜单,如下所示:
CustomEvent

单击时,页面模式添加的内容脚本会启动以下警报:
context menu

使用发送的消息从多个不同的功能中进行选择:

可以扩展通过事件传递的信息,以允许根据内容调用多个不同的函数。执行此操作的一种方法是将对象作为消息发送。对象的一个​​属性可以是期望的功能,另一个属性可以是在该功能中使用的数据。我对以下问题的回答包含了这样做的例子:

  • page-mod alert:此答案的代码使用相同的传递消息来指示在上下文菜单项上进行了单击并传递了单击上下文菜单项的URL,或者告诉主要将要显示上下文菜单的脚本,以便对其进行修改。
  • Add menu item created with the sdk/context-menu API to the top of the context menu:这个答案显示发送一条消息,该消息将导致调用各种不同函数之一并将数据传递给被调用的函数。它被实现为一种使用console工作的console.log("message")方法的方法。如果我今天这样做,我会对此编码有所不同,但它的工作原理和演示概念。

因为关于MDN(How to console.log from ChromeWorker (alternative to dump)here)的文档在内容脚本到内容脚本通信方面不是很清楚,所以我更新了我在其上讨论的页面。我还添加了上面的代码作为示例。