使用Chrome扩展程序注入远程iframe

时间:2017-11-20 15:22:04

标签: google-chrome-extension content-security-policy

对于我的生活,我无法让我的Chrome扩展程序显示带有远程网址的iframe。

我在控制台中看到以下消息 -

  

拒绝框架'https://www.example.com/',因为它违反了以下内容安全政策指令:“child-src'self'”。请注意,'frame-src'未明确设置,因此'child-src'用作后备。

我在这里找到了一个解决方案(Injecting iframe into page with restrictive Content Security Policy),这需要注入一个本地iframe,然后comatins另一个引用远程网址的iframe。这应该绕过声音安全策略。但由于某种原因,它似乎不适用于我的情况。我错过了什么或改变了镀铬安全政策吗?

以下是我的扩展程序中与此问题相关的部分内容。注意 - 这段代码并不是最漂亮的,因为我一直在努力让它发挥作用。

现在这种方式的工作方式是background.js向inject.js发送消息。 inject.js插入第一个iframe,引用本地文件infobar.html。此页面是我们的主要用户界面,我们希望将iframe中显示的远程html页面作为此页面的一部分。然后infobar.js插入一个引用本地文件frame.html的iframe。最后,frame.html将iframe硬编码到我们的远程网址。

根据之前的回答,只有第一个iframe应该受内容安全策略的约束。但是,这似乎并非如此,因为引用example.com的实际上是3个iframe深度。

的manifest.json

{
...
  "content_security_policy": "script-src 'self'; object-src 'self'; frame-src https://www.example.com; child-src https://www.example.com",
  "background": {
    "scripts": [
      "js/jquery/jquery.min.js",
      "src/bg/background.min.js"
    ],
    "persistent": true
  },
...
  "content_scripts": [
    {
      ...
      "css": [
        ...
        "src/inject/inject.min.css"
      ],
      "js": [
        ...
        "src/inject/inject.min.js"
      ]
    }
  ],
  "externally_connectable": {
    "matches": [
      "*://localhost/*",
      "*://*.example.com/*
    ]
  },
  "web_accessible_resources": [
    "src/inject/inject.html",
    "src/inject/infobar.html",
    "src/inject/infobar.min.js",
    "src/inject/frame.html"
  ],
  "sandbox": {
    "pages": [
      "src/inject/infobar.html",
      "src/inject/frame.html"
    ]
  }
}

inject.js

var iframe = document.createElement("iframe");
iframe.scrolling = "no";
iframe.style.cssText = "display:none;";
...
$(iframe).load(function () {
    var message = {
        command: "render-frame",
        context: data,
        frameUrl: chrome.runtime.getURL("src/inject/frame.html")
    };
    iframe.contentWindow.postMessage(message, '*');
    iframe.style.cssText = "border: 0px; overflow: visible; padding: 0px; right: auto; width: 100%; height: " + toolbarHeight + "px; top: 0px; left: 0px; z-index: 2147483647; box-shadow: rgba(0, 0, 0, 0.498039) 0px 3px 10px; position: fixed; display: none;";
});
...
iframe.src = chrome.runtime.getURL("src/inject/infobar.html");      
...     
document.documentElement.appendChild(iframe);  

infobar.html

简单的HTML页面。没有任何相关的东西。参考信息infobar.js。

infobar.js

window.addEventListener("message", function (event) {
    var command = event.data.command;
    switch (command) {
        case "render-frame":
            var frame = document.createElement("iframe");
            frame.scrolling = "no";
            frame.src = event.data.frameUrl;
            document.getElementById("content").appendChild(frame); 
...
            break;
    }
});

frame.html

<html>
<head>
    <style>
        html, body, iframe, h2 {
            margin: 0;
            border: 0;
            padding: 0;
            display: block;
            width: 100vw;
            height: 100vh;
            background: white;
            color: black;
        }
    </style>
</head>
<body>
<iframe src="https://www.example.com/page.html"></iframe>
</body>
</html>

1 个答案:

答案 0 :(得分:0)

正确的方法是在后台脚本中使用chrome.webRequest API并拦​​截HTTP响应。

然后,您可以覆盖响应标头以修改Content-Security-Policy标头。您还可以修改X-Frame-Options标题(如果需要)。

文档:chrome.webRequest