无法在后台页面中加载iframe(状态=取消) [英] Impossible to load an iframe inside the background page (status=canceled)

查看:511
本文介绍了无法在后台页面中加载iframe(状态=取消)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想动态注入并在背景页面中加载一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆