无法在后台页面中加载iframe(状态=已取消)

时间:2017-03-15 18:03:17

标签: iframe google-chrome-extension

我想动态地在后台页面中注入并加载iframe。但每次都会取消请求。

http://i.imgur.com/Puto33c.png

一周以前曾经工作过。我不知道我哪里错了。

要重现此问题,我创建了一个小扩展程序:

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);
});

要加载的页面未被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仍然无法加载。

有人有解决方法或解决此问题吗?

谢谢!

1 个答案:

答案 0 :(得分:2)

Chrome 58.0.3014.0 enables Site Isolation for extensions by default,它会在不同的渲染器进程中加载​​iframe,并由单独的chrome.exe操作系统进程处理。

'取消' message表示扩展程序的chrome.exe进程取消了该请求,它由另一个隐藏的chrome.exe进程处理。

正确的方法是声明一个内容脚本,该脚本将自动在iframe URL上运行并与后台页面进行通信。注意:只能传递JSON可用数据,换句话说,您可以传递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();
// 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');
        }
    });
});

另见类似的质量检查:content.js in iframe from chrome-extension popup