【问题标题】:Firefox Add-on SDK context-menu communicate with a content script loaded by page-modFirefox Add-on SDK 上下文菜单与 page-mod 加载的内容脚本通信
【发布时间】:2016-06-16 13:07:33
【问题描述】:

我正在使用 Firefox 插件 SDK 创建一个 Firefox 插件。这个插件做了两件事:

  1. 使用sdk/page-mod 将内容脚本注入每个页面。
  2. 使用sdk/context-menu 添加上下文菜单项。

我希望当用户单击上下文菜单项时,插件将调用 PageMod() 加载的内容脚本中的函数。

【问题讨论】:

  • 你已经尝试过什么代码?
  • 听起来您已经有了代码,至少可以设置您想要的大部分内容。您尚未在问题中包含此代码。因此,您将开始帮助您的门槛设置得很高。为了向您展示经过测试的解决方案,有人必须重新创建所有代码来设置情况。即使那样,它也可能不会复制您的情况。 ,让人们更容易帮助您,并在您的问题中添加minimal reproducible example
  • @Makyen 谢谢你的建议。

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


【解决方案1】:

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

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

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

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

对于通过不同方法加载到同一页面的内容脚本(例如,一个使用 page-mod,另一个作为上下文菜单项 - 您感兴趣的情况),您可以使用 @987654324 在它们之间直接通信@ 或 CustomEvent。两者都可用于在两个脚本之间发送您想要的任何 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);'
                 + '});'
});

以上代码生成的上下文菜单如下所示:

点击后,页面模块添加内容脚本会启动以下警报:

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

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

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

因为 MDN 上的文档(herehere)对内容脚本到内容脚本的通信不是很清楚,所以我更新了我找到的讨论它的页面。我还添加了上面的代码作为示例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-27
    • 1970-01-01
    相关资源
    最近更新 更多