无法在后台页面中加载iframe(状态=取消) [英] Impossible to load an iframe inside the background page (status=canceled)
问题描述
我想动态注入并在背景页面中加载一个iframe。但每次请求都会被取消。
http://i.imgur.com/Puto33c.png
过去一星期前工作。我不知道我错在哪里。
为了重现此问题,我创建了一个小扩展:
manifest.js:
$ b
{
name:iframe background,
version:1.0.0,
manifest_version:2,
browser_action:{
default_title:iframe
} ,
background:{
persistent:false,
scripts:[background.js]
}
}
background.js:
chrome.browserAction.onClicked.addListener(function(){
var iframe = document.createElement('iframe');
iframe.src ='http:// localhost:3000 /';
iframe.onload = function(){
console.log(iframe.contentDocument); //返回null
};
document.body.appendChild(iframe);
});
要加载的页面不会被X-Frame-Options SAMEORIGIN阻止。
我试图将iframe直接放在HTML背景页面中,但没有运气。 我还尝试添加一个content_security_policy:
content_security_policy:script-src'self'; object-src'self '; frame-src'self'http:// localhost:3000 /
但iframe仍然无法加载。 p>
有人对此问题有解决方法吗?
Chrome 58.0.3014.0 默认为站点隔离扩展,使得iframe可以在不同的渲染器进程中加载,并由单独的chrome.exe操作系统进程处理。
已取消消息表示扩展程序的chrome.exe进程取消了请求,并由另一个隐藏的chrome.exe进程处理。
正确的方法是声明一个内容脚本,该脚本将自动在iframe URL上运行并与后台页面进行通信。注意:只能传递JSON-fiable数据,换句话说,可以传递innerHTML而不传递DOM元素。这很容易通过DOMParser处理。
manifest.json添加:
content_scripts:[{
matches:[http:// localhost:3000 / *],
js:[iframe。 js],
run_at:document_end,
all_frames:true
}],
iframe.js:
var port = chrome .runtime.connect();
//立即发送一些东西
port.postMessage({html:document.documentElement.innerHTML});
//处理来自后台页面的更多消息
port.onMessage.addListener(msg => {
............. 。
//回覆
port.postMessage(anyJSONfiableObject); //不是DOM元素!
});
background.js:
var iframePort;
chrome.browserAction.onClicked.addListener(()=> {
document.body.insertAdjacentHTML('beforeend',
'< iframe src =http:/ / localhost:3000 />< / iframe>');
});
chrome.runtime.onConnect.addListener(port => {
//保存在一个全局变量中以便稍后从其他函数中访问它
iframePort = port;
port.onMessage.addListener(msg => {
if(msg.html){
const doc = new DOMParser()。parseFromString(msg.html,'text / html' );
console.log(doc);
alert('从iframe中接收到HTML,请参阅控制台');
}
});
}) ;
另请参阅类似的质量检查:从Chrome扩展程序弹出框中的iframe中的content.js
I want to dynamicaly inject and load an iframe inside the background page. But every time, the request is canceled.
http://i.imgur.com/Puto33c.png
That used to work a week ago. I don't know where I'm wrong.
To reproduce this issue, I created a small extension :
manifest.js :
{
"name": "iframe background",
"version": "1.0.0",
"manifest_version": 2,
"browser_action": {
"default_title": "iframe"
},
"background": {
"persistent": false,
"scripts": ["background.js"]
}
}
background.js :
chrome.browserAction.onClicked.addListener(function() {
var iframe = document.createElement('iframe');
iframe.src = 'http://localhost:3000/';
iframe.onload = function() {
console.log(iframe.contentDocument); // return null
};
document.body.appendChild(iframe);
});
The page to load is not blocked by X-Frame-Options SAMEORIGIN.
I tried to put the iframe directly within a HTML background page with no luck.
I also tried to add an content_security_policy :
"content_security_policy": "script-src 'self'; object-src 'self'; frame-src 'self' http://localhost:3000/"
But the iframe still doesn't load.
Does someone has a workaround or a solution to this problem?
Thanks !
Chrome 58.0.3014.0 enables Site Isolation for extensions by default that makes the iframe load in a different renderer process handled by a separate chrome.exe OS process.
The 'canceled' message means that the extension's chrome.exe process canceled the request and it was handled by a different hidden chrome.exe process.
The correct approach is to declare a content script that will automatically run on the iframe URL and communicate to the background page. Note: only JSON-fiable data may be passed, in other words, you can pass innerHTML but not DOM elements. This is easy to handle though via DOMParser.
manifest.json additions:
"content_scripts": [{
"matches": ["http://localhost:3000/*"],
"js": ["iframe.js"],
"run_at": "document_end",
"all_frames": true
}],
iframe.js:
var port = chrome.runtime.connect();
// send something immediately
port.postMessage({html: document.documentElement.innerHTML});
// process any further messages from the background page
port.onMessage.addListener(msg => {
..............
// reply
port.postMessage(anyJSONfiableObject); // not DOM elements!
});
background.js:
var iframePort;
chrome.browserAction.onClicked.addListener(() => {
document.body.insertAdjacentHTML('beforeend',
'<iframe src="http://localhost:3000/"></iframe>');
});
chrome.runtime.onConnect.addListener(port => {
// save in a global variable to access it later from other functions
iframePort = port;
port.onMessage.addListener(msg => {
if (msg.html) {
const doc = new DOMParser().parseFromString(msg.html, 'text/html');
console.log(doc);
alert('Received HTML from the iframe, see the console');
}
});
});
See also a similar QA: content.js in iframe from chrome-extension popup
这篇关于无法在后台页面中加载iframe(状态=取消)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!