我正在为Firefox编写一个Web扩展,需要在使用某些url检索的页面中插入大量的附加功能。
由于Mozilla网站上的教程,我能够快速创建一个内容脚本,每当打开某个页面时就会调用该脚本,但现在我被困在实际插入html片段到页面中。
我已经做了好几个小时了,但是毫无效果。以下是我考虑并尝试过的方法:-
iframe
没有工作,显然一些安全策略不允许使用iframe指向本地资源,这里的最后一个评论甚至告诉我应该使用panel
而不是iframe
- 使用面板不适合我有两个原因:
- 我找不到使用我自己的自定义代码打开面板的方法(上面链接的示例与
ReferenceError: require is not defined
失败) - 我猜我只能通过使用bowserAction在Web扩展中打开面板,但这会将按钮放在工具栏上,而我需要它在页面本身
- 根据文档,我只能在整个浏览器中打开一个Panel实例,它会在与任何其他浏览器元素交互时自动关闭
- 我找不到使用我自己的自定义代码打开面板的方法(上面链接的示例与
- 最后我想只是加载html从一个资源文件打包到扩展和喂养它到使用
innerHTML
的页面,但我找不到任何API加载文本从资源 - 只是使用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,让我概述一些利弊:
- 选项A显然更经典:视图(html)与行为(js)明显分开,所有文件都有适合其类型的内容(除了在js中构建
iframe
元素的小例外)。所以应该更容易支持前进。 - 选项A不允许在框架中使用内联脚本(https://developer.chrome.com/extensions/contentSecurityPolicy)。这使得原型制作更加困难,但最终应该是一个加分项。
- 由于某些原因,我仍然不清楚,我不能在选项b中插入的html中使用
#
。 - 选项B使得从附加框架到原始服务器的ajax调用更容易,因为框架源被认为来自与原始网页相同的域。在选项A中,我必须在框架中使用
Window.postMessage
,以便要求插入到原始页面中的内容脚本进行ajax请求并给我返回响应(第二部分尤其困难,因为那里没有jQuery或Prototype可用)。