【发布时间】:2018-05-03 20:51:33
【问题描述】:
在我的一生中,我无法让 Chrome 扩展程序显示带有远程 URL 的 iframe。
我在控制台中看到以下消息 -
拒绝框架“https://www.example.com/”,因为它违反了以下内容安全策略指令:“child-src 'self'”。请注意,'frame-src' 没有显式设置,因此 'child-src' 用作后备。
我在这里 (Injecting iframe into page with restrictive Content Security Policy) 找到了一个解决方案,它需要注入一个本地 iframe,然后再将另一个 iframe 引用到远程 url。这应该绕过sontent安全策略。但由于某种原因,它似乎不适用于我的情况。是我遗漏了什么还是 chrome 安全政策发生了变化?
以下是与此问题相关的我的扩展部分。注意 - 这段代码不是最漂亮的,因为我一直在尝试让它工作。
目前的工作方式是 background.js 向 inject.js 发送消息。 inject.js 插入第一个 iframe,引用本地文件 infobar.html。该页面是我们的主要用户界面,我们希望将远程 html 页面显示在 iframe 中作为该页面的一部分。然后 infobar.js 插入一个引用本地文件 frame.html 的 iframe。最后,frame.html 有一个 iframe 硬编码到我们的远程 url。
根据之前的答案,只有第一个 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>
【问题讨论】:
-
如果你在 infobar.js 中插入外部 iframe 会发生什么,即两级深度?
-
同样的问题。在inject.js 中,我可以将行frameUrl: chrome.runtime.getURL("src/inject/frame.html") 更改为frameUrl: chrome.runtime.getURL("example.com/page.html") 我看到相同的“拒绝帧”错误。
-
getURL 仅适用于本地页面。对外部站点使用普通的 http url。
-
你是对的,对不起。我手动输入了该评论。实际代码只是一个字符串 url。
标签: google-chrome-extension content-security-policy