Mozilla Web 扩展:将 UI 组件插入页面
Mozilla Web Extensions: Insert UI component into page
我正在为 Firefox 编写一个 Web 扩展,它需要在使用某些 URL 检索的页面中插入大量附加功能。
借助 Mozilla 网站上的教程,我能够快速创建一个内容脚本,只要打开某个页面就会调用该脚本,但现在我无法真正将 html 片段插入页面.
我已经研究了几个小时了,但无济于事。这是我考虑和尝试过的:
iframe
不起作用,因为显然某些安全策略不允许使用指向本地资源的 iframe,最后一条评论 here 甚至告诉我应该使用 panel
而不是 iframe
- 使用 Panel 对我不起作用有两个原因:
- 我找不到使用我自己的自定义代码打开面板的方法(上面 link 的示例因
ReferenceError: require is not defined
而失败)
- 我猜我只能通过使用 bowserAction 在 Web 扩展中打开一个面板,但是当我在页面本身需要它时,这会将按钮放在工具栏上
- 根据文档,我只能为整个浏览器打开一个 Panel 实例,它会在与任何其他浏览器元素交互时自动关闭
- 最后我想过从打包到扩展中的资源文件中加载 html 并使用
innerHTML
将其送入页面,但我找不到要加载的任何 API来自资源的文本
- 仅使用 DOM API 对我不起作用,因为用代码创建所有元素需要很长时间
真不敢相信我这么久都没有注意到它,但我终于让它按照我的需要工作了。在这样做的同时,我什至想出了一个替代方法,所以这里开始。
但首先这是我拒绝使用 iframe
之外所有其他可能方法的主要原因:
- 我需要通过扩展添加的 UI 元素来使用它们自己的 UI 样式,并且想利用现代框架(例如 jQuery 和 Bootstrap)并且我不想 运行 陷入 CSS 和 JavsScript 冲突的问题。
我实际上很早就注意到我要嵌入的页面中的 CSS 会覆盖 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 - 在 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,但让我概述一些利弊:
- 选项 A 显然更规范:视图 (html) 与行为 (js) 明显分开,所有文件都有适合其类型的内容(除了构建
iframe
元素的小例外在 JS 中)。
所以应该更容易支持前进。
- 选项 A 不允许在框架中使用内联脚本 (https://developer.chrome.com/extensions/contentSecurityPolicy)。这使得原型制作更加困难,但最终应该是一个加号。
- 出于某种我仍然不清楚的原因,我无法在选项 B 中插入的 html 中使用
#
。
- 选项 B 使得从附加框架到原始服务器的 ajax 调用更容易,因为框架源被认为来自与原始网页相同的域。
在选项 A 中,我不得不在框架中使用
Window.postMessage
来要求插入原始页面的内容脚本发出 ajax 请求并返回响应(第二部分特别难因为那里没有 jQuery 或 Prototype 之类的东西。
我正在为 Firefox 编写一个 Web 扩展,它需要在使用某些 URL 检索的页面中插入大量附加功能。
借助 Mozilla 网站上的教程,我能够快速创建一个内容脚本,只要打开某个页面就会调用该脚本,但现在我无法真正将 html 片段插入页面.
我已经研究了几个小时了,但无济于事。这是我考虑和尝试过的:
iframe
不起作用,因为显然某些安全策略不允许使用指向本地资源的 iframe,最后一条评论 here 甚至告诉我应该使用panel
而不是iframe
- 使用 Panel 对我不起作用有两个原因:
- 我找不到使用我自己的自定义代码打开面板的方法(上面 link 的示例因
ReferenceError: require is not defined
而失败) - 我猜我只能通过使用 bowserAction 在 Web 扩展中打开一个面板,但是当我在页面本身需要它时,这会将按钮放在工具栏上
- 根据文档,我只能为整个浏览器打开一个 Panel 实例,它会在与任何其他浏览器元素交互时自动关闭
- 我找不到使用我自己的自定义代码打开面板的方法(上面 link 的示例因
- 最后我想过从打包到扩展中的资源文件中加载 html 并使用
innerHTML
将其送入页面,但我找不到要加载的任何 API来自资源的文本 - 仅使用 DOM API 对我不起作用,因为用代码创建所有元素需要很长时间
真不敢相信我这么久都没有注意到它,但我终于让它按照我的需要工作了。在这样做的同时,我什至想出了一个替代方法,所以这里开始。
但首先这是我拒绝使用 iframe
之外所有其他可能方法的主要原因:
- 我需要通过扩展添加的 UI 元素来使用它们自己的 UI 样式,并且想利用现代框架(例如 jQuery 和 Bootstrap)并且我不想 运行 陷入 CSS 和 JavsScript 冲突的问题。 我实际上很早就注意到我要嵌入的页面中的 CSS 会覆盖 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 - 在 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,但让我概述一些利弊:
- 选项 A 显然更规范:视图 (html) 与行为 (js) 明显分开,所有文件都有适合其类型的内容(除了构建
iframe
元素的小例外在 JS 中)。 所以应该更容易支持前进。 - 选项 A 不允许在框架中使用内联脚本 (https://developer.chrome.com/extensions/contentSecurityPolicy)。这使得原型制作更加困难,但最终应该是一个加号。
- 出于某种我仍然不清楚的原因,我无法在选项 B 中插入的 html 中使用
#
。 - 选项 B 使得从附加框架到原始服务器的 ajax 调用更容易,因为框架源被认为来自与原始网页相同的域。
在选项 A 中,我不得不在框架中使用
Window.postMessage
来要求插入原始页面的内容脚本发出 ajax 请求并返回响应(第二部分特别难因为那里没有 jQuery 或 Prototype 之类的东西。