firefox插件webextensionsMozilla Web扩展:插入UI组件到页面



我正在为Firefox编写一个Web扩展,需要在使用某些url检索的页面中插入大量的附加功能。

由于Mozilla网站上的教程,我能够快速创建一个内容脚本,每当打开某个页面时就会调用该脚本,但现在我被困在实际插入html片段到页面中。

我已经做了好几个小时了,但是毫无效果。以下是我考虑并尝试过的方法:
  1. iframe没有工作,显然一些安全策略不允许使用iframe指向本地资源,这里的最后一个评论甚至告诉我应该使用panel而不是iframe
  2. 使用面板不适合我有两个原因:
    • 我找不到使用我自己的自定义代码打开面板的方法(上面链接的示例与ReferenceError: require is not defined失败)
    • 我猜我只能通过使用bowserAction在Web扩展中打开面板,但这会将按钮放在工具栏上,而我需要它在页面本身
    • 根据文档,我只能在整个浏览器中打开一个Panel实例,它会在与任何其他浏览器元素交互时自动关闭
  3. 最后我想只是加载html从一个资源文件打包到扩展和喂养它到使用innerHTML的页面,但我找不到任何API加载文本从资源
  4. 只是使用DOM API不适合我,因为它需要永远的代码创建所有的元素

我不敢相信我这么长时间都没有注意到它,但我终于把它全部按我需要的工作了。在这样做的时候,我甚至想到了另一种方法,所以在这里。

但首先,这是我放弃所有其他可能的方法的主要原因,除了使用iframe:

  • 我需要通过扩展添加的UI元素来使用自己的UI样式,并希望利用现代框架(例如jQuery和Bootstrap),我不想在以后遇到冲突CSS和JavsScript的问题。我注意到,在页面的CSS中,我嵌入到do override Bootstrap样式。
  • 最好我也不想影响我嵌入的页面的世纪标记。

选项A -带有外部源文件的IFRAME

最后证明,我唯一缺少的是manifest.json中的web_accessible_resources设置。一旦我将用作iframe源的html文件添加到该列表中,它就开始工作了。

// manifest.json:
{
    "manifest_version": 2,
    ...
    "web_accessible_resources": [
        "data/my.html"
    ],
    "content_scripts": [
        {
            "matches": ["*://*"],
            "js": ["js/my.js"]
        }
    ]
}
// js/my.js
var addonFrame = document.createElement ("IFRAME");
addonFrame.style = "position: absolute; bottom: 0; right: 0; width: 150px; height: 38px;";
addonFrame.frameBorder = "0";
addonFrame.src = chrome.extension.getURL ("data/my.html");
document.body.appendChild (addonFrame);

选项B - IFRAME与JS中的内联HTML

在我最终使第一种方法工作之前,我的实验使我采用了另一种工作方法-在内容脚本中直接将HTML插入iframe

// js/my.js
var addonFrame = document.createElement ("IFRAME");
addonFrame.style = "position: absolute; bottom: 0; right: 0; width: 150px; height: 38px;";
addonFrame.frameBorder = "0";
var addonHtml = "<!DOCTYPE html>n
<html>n
    <head>n
        <meta charset='UTF-8'>n
        <title>Title of the document</title>n
    </head>n
    <body>n
        ...n
    </body>n
</html>";
addonFrame.src = 'data:text/html;charset=utf-8,' + encodeURI (addonHtml);
document.body.appendChild (addonFrame);

尽管我最终使用了选项A,让我概述一些利弊:

  1. 选项A显然更经典:视图(html)与行为(js)明显分开,所有文件都有适合其类型的内容(除了在js中构建iframe元素的小例外)。所以应该更容易支持前进。
  2. 选项A不允许在框架中使用内联脚本(https://developer.chrome.com/extensions/contentSecurityPolicy)。这使得原型制作更加困难,但最终应该是一个加分项。
  3. 由于某些原因,我仍然不清楚,我不能在选项b中插入的html中使用#
  4. 选项B使得从附加框架到原始服务器的ajax调用更容易,因为框架源被认为来自与原始网页相同的域。在选项A中,我必须在框架中使用Window.postMessage,以便要求插入到原始页面中的内容脚本进行ajax请求并给我返回响应(第二部分尤其困难,因为那里没有jQuery或Prototype可用)。

最新更新