Chrome 扩展 - 未捕获的 DOMException:阻止具有源的框架访问跨域框架

Posted

技术标签:

【中文标题】Chrome 扩展 - 未捕获的 DOMException:阻止具有源的框架访问跨域框架【英文标题】:Chrome Extension - Uncaught DOMException: Blocked a frame with origin from accessing a cross-origin frame 【发布时间】: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);

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

https://pastebin.com/Yrs68zAB

【问题讨论】:

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 标签正常加载。 【参考方案1】:

您可以尝试将该代码、您想要的 iframe 上的内容上传到网络服务器,然后设置标头。

'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

【讨论】:

【参考方案2】:

对于 Chrome——我在 iframe 中包含了一个脚本标签。然后我可以在 iframe 加载的脚本中使用<button element>.addEventListener("click", function() 。对于帧到主机的通信,我使用了window.parent.postMessage 和其他此类方法。为了加载 iframe,我在manifest.json 中添加了以下内容:

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

【讨论】:

以上是关于Chrome 扩展 - 未捕获的 DOMException:阻止具有源的框架访问跨域框架的主要内容,如果未能解决你的问题,请参考以下文章

Chrome 扩展 - 未捕获的 DOMException:阻止具有源的框架访问跨域框架

chrome.runtime.sendMessage 引发“未捕获的类型错误:无法调用未定义的方法‘sendMessage’”

使用 chrome 扩展记录/捕获推送通知

用于收听和捕获流式音频的 Chrome 扩展程序

Chrome 中的“未捕获的 TypeError:非法调用”

javascript chrome扩展 - 捕获关闭窗口#chrome #extensions #windows #close