Chrome 扩展程序 - 未捕获的 DOMException:阻止具有源的帧访问跨源帧

Chrome Extension - Uncaught DOMException: Blocked a frame with origin from accessing a cross-origin frame

提问人:Foobar 提问时间:5/4/2018 更新时间:10/8/2023 访问量:11877

问:

在有人将此帖子标记为另一篇帖子的副本之前,例如: SecurityError:阻止具有源的帧访问跨域帧 这篇文章是不同的,因为它是关于在 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 扩展中使用 API 和命名空间,是因为我使用了 Mozilla 提供的 polyfill,它允许我使用 promise 和命名空间。Promisebrowserbrowser

以下是单击扩展工具栏图标时显示的弹出窗口的代码:

//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);
}

最后,这里是内容脚本的完整代码:

https://pastebin.com/Yrs68zAB

javascript iframe google-chrome-extension 同源策略

评论

0赞 wOxxOm 5/4/2018
Chrome 似乎不记得 iframe 是由您的内容脚本创建的。无论是错误还是 WAI(按预期工作),我不知道。尝试使用旧的便携式 Chrome 和新的 Chrome Canary。如果行为相同,则很可能是 WAI。否则,请考虑报告 crbug.com
0赞 Foobar 5/4/2018
有没有办法将 iFrame 添加到我的 manifest.json 中,以便它被识别?
0赞 wOxxOm 5/4/2018
不可以,但您可以重新编写代码并在 iframe 中使用 DOM 侦听器,然后使用从 chrome.tabs.getCurrent 获取的选项卡 ID 调用 chrome.tabs.sendMessage。内容脚本将在其 chrome.runtime.onMessage 中接收它。
0赞 Foobar 5/8/2018
您能否发布一个关于如何在 iFrame 中使用 DOM 侦听器的示例作为答案?另外,这真的有效吗?问题不在于检测 iFrame 何时加载,而是我无法从 iFrame 内部获取按钮对象,因为它会导致异常。
0赞 wOxxOm 5/8/2018
iframe 包含您自己的页面,因此无需检测任何内容,只需将代码放在 js 文件中并使用 iframe.html 中的脚本标签正常加载即可。

答:

0赞 Alberto Perez 2/5/2019 #1

您可以尝试将该代码(您想要在 iframe 上的内容)上传到 Web 服务器,并设置标头。

'Access-Control-Allow-Origin: *'

Firefox通常可以更好地处理本地文件,这可以解释您的错误

origin "http://example.com" from accessing a cross-origin frame. at file:///C:/Users/vroy1/Documents/Programming/web-extension-summarizer/src/inject-content/inject.js
0赞 Foobar 2/5/2019 #2

对于 Chrome,我在 iframe 中包含了一个脚本标签。然后,我可以在 iframe 加载的脚本内部使用。对于帧到主机的通信,我使用了等方法。为了加载 iframe,我将以下内容添加到我的:<button element>.addEventListener("click", function() {}window.parent.postMessagemanifest.json

  "web_accessible_resources": [
    "inject-content/inject.html",
    "inject-content/cleanslate.css"
  ]