【发布时间】:2018-10-14 01:26:43
【问题描述】:
在有人将此帖子标记为另一个帖子的重复之前,例如:SecurityError: Blocked a frame with origin from accessing a cross-origin frame 此帖子不同,因为它是关于在 Chrome 网络扩展程序的上下文中避免此错误,这意味着可能有独特的解决方案。
我正在将 Firefox Quantum 扩展移植到 Chrome。该扩展将 iFrame 注入用户的当前网页。目前,该扩展在 Firefox Quantum 中运行没有问题,您可以在这里找到它:https://addons.mozilla.org/en-US/firefox/addon/tl-dr-auto-summarizer/?src=search
iFrame 的来源是一个名为“inject.html”的 HTML 文件,它捆绑在扩展程序中。
这是注入 iFrame 的缩短(以避免使帖子过长)代码。此代码位于用户当前选项卡的内容脚本中:
var iFrame = document.createElement("iFrame");
iFrame.id = "contentFrame";
iFrame.classList.add("cleanslate");
iFrame.style.cssText = "width: 100% !important; height: 100% !important; border: none !important;";
iFrame.src = browser.extension.getURL("inject-content/inject.html");
document.body.appendChild(iFrame);
这里是 manifest.json
{
"manifest_version": 2,
"name": "TL;DR - Summarizer",
"version": "3.0",
"description": "Summarizes webpages",
"permissions": [
"activeTab",
"tabs",
"*://*.smmry.com/*"
],
"icons":
{
"48": "icons/border-48.png"
},
"browser_action":
{
"browser_style": true,
"default_popup": "popup/choose_length_page.html",
"default_icon":
{
"16": "icons/summarizer-icon-16.png",
"32": "icons/summarizer-icon-32.png"
}
},
"web_accessible_resources": [
"inject-content/inject.html",
"inject-content/cleanslate.css"
],
"content_security_policy": "script-src 'self' 'sha256-AeZmmPP/9ueCrodQPplotiV3Pw0YW4QqifjUL7NE248='; object-src 'self'"
}
注入 iFrame 后,我在 iFrame 加载后为 iFrame 中的按钮设置“点击”侦听器。我使用以下代码示例执行此操作。但是,虽然以下代码在 Firefox Quantum 中有效,但在 Chrome 中会引发异常。
iFrame.onload = () => {
//The error occurs on the following line.
var closeButton = iFrame.contentWindow.document.getElementById("close-btn");
closeButton.addEventListener("click", () => {
//Do Stuff
});
var copyButton = iFrame.contentWindow.document.getElementById("copy-btn");
copyButton.addEventListener("click", () => {
//Do stuff
});
}
我得到以下异常:
未捕获的 DOMException:阻止具有源“http://example.com”的框架访问跨域框架。 在 HTMLIFrameElement.iFrame.onload (file:///C:/Users/vroy1/Documents/Programming/web-extension-summarizer/src/inject-content/inject.js:58:56)
我怎样才能避免这个错误?
如果有人想知道,我之所以能够在 Chrome 扩展中使用 Promise API 和 browser 命名空间,是因为我使用的是 Mozilla 提供的 polyfill,它允许我使用 Promise 和browser 命名空间。
这是扩展程序在单击其工具栏图标时显示的弹出窗口的代码:
//Enable the polyfill for the content script and execute it in the current tab
browser.tabs.executeScript({ file: "/polyfills/browser-polyfill.js" }).then(loadContentScript).catch((error) => logError(error));
function loadContentScript() {
browser.tabs.executeScript({ file: "/inject-content/inject.js" }).then(listenForClicks).catch((error) => logError(error));
}
function listenForClicks() {
document.addEventListener('click', e => {
if (!e.target.classList.contains('btn')) {
return;
} else {
browser.tabs.query({ active: true, currentWindow: true })
.then(tabs => {
browser.tabs.sendMessage(tabs[0].id, { summaryLength: e.target.id, targetURL: tabs[0].url });
});
}
});
}
function logError(error) {
console.log(error);
}
最后,这里是内容脚本的完整代码:
【问题讨论】:
-
Chrome 似乎不记得 iframe 是由您的内容脚本创建的。无论是错误还是 WAI(按预期工作),我都不知道。在旧的便携式 Chrome 和新的 Chrome Canary 中尝试。如果行为相同,则可能是 WAI。否则考虑报告crbug.com
-
有没有办法将 iFrame 添加到我的 manifest.json 以便它被识别?
-
否,但您可以重新编写代码并在 iframe 中使用 DOM 侦听器,然后使用从 chrome.tabs.getCurrent 获得的标签 ID 调用 chrome.tabs.sendMessage。内容脚本将在其 chrome.runtime.onMessage 中接收它。
-
您能否发布一个示例,说明如何在 iFrame 中使用 DOM 侦听器作为答案?另外,这真的有用吗?问题不是检测 iFrame 何时加载,而是我无法从 iFrame 内部获取按钮对象,因为它会导致异常。
-
iframe 包含你自己的页面,所以不需要检测任何东西,只需将代码放入 js 文件中,并在 iframe.html 中使用 script 标签正常加载。
标签: javascript iframe google-chrome-extension same-origin-policy