Mozilla Web扩展:将UI组件插入页面

时间:2016-09-28 22:40:53

标签: firefox-webextensions

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

由于Mozilla网站上的教程,我能够快速创建一个在打开某个页面时调用的内容脚本,但现在我仍然坚持在页面中插入html片段。

我已经好几个小时了,但无济于事。这是我考虑过并尝试过的:

  1. iframe无效,因为显然某些安全政策不允许使用指向本地资源的iframe,而最后一条评论here甚至告诉我应该使用panel而不是iframe
  2. 使用Panel对我不起作用有两个原因:
    • 我找不到使用我自己的自定义代码打开Panel的方法(上面链接的示例失败了ReferenceError: require is not defined
    • 我猜我只能使用bowserAction在Web扩展中打开一个面板,但是当我在页面本身需要它时,它会将按钮放在工具栏上
    • 根据文档,我只能为整个浏览器打开一个Panel实例,它会在与任何其他浏览器元素交互时自动关闭
  3. 最后我想到只是从包含在扩展程序中的资源文件中加载html并使用innerHTML将其提供给页面但是我找不到任何用于从资源加载文本的API
  4. 仅仅使用DOM API对我来说不起作用,因为编写所有元素的代码将花费很长时间

1 个答案:

答案 0 :(得分:1)

我无法相信我没有注意到这么久,但我终于在我需要的时候完成了所有工作。虽然这样做我甚至提出了另一种方法,所以这里就是。

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

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

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

最后我发现我唯一缺少的是web_accessible_resources中的manifest.json设置。一旦我将用作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 - 在JS中使用内联HTML的IFRAME

在我第一次使用第一种方法之前,我的实验让我采用了另一种工作方法 - 直接在内容脚本中将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显然更具佳能:view(html)与行为(js)明确分开,所有文件都有适合其类型的内容(除了JS中构建iframe元素的小例外)。 所以今后应该更容易支持。
  2. 选项A不允许在框架中使用内联脚本(https://developer.chrome.com/extensions/contentSecurityPolicy)。这使原型设计变得更难,但最终应该是一个优势。
  3. 由于某些原因,我仍然不清楚,我无法在选项B中插入的html中使用#
  4. 选项B使得从附加帧到原始服务器的ajax调用更容易,因为帧源被认为来自与原始网页相同的域。 在选项A中,我不得不在框架中使用Window.postMessage,以便让我插入原始页面的内容脚本发出ajax请求并给我回复响应(第二部分特别难,因为没有什么比这更好的了那里有jQuery或Prototype)。