在后台页面加载远程网页:Chrome扩展程序

10

使用Chrome扩展程序,是否可能将远程网页加载到后台页面中?

"background": {
    "page": "local.html"
  }

可以正常工作,但是

"background": {
    "page": "http://...."
  }

以下错误导致失败:

Could not load background page http://....
1个回答

13
不行,这是不可能的。自从Chrome 22版本开始就可以这样做了-请查看答案底部。您可以在清单文件中白名单https:资源,以便手动构建您的后台脚本。请确保在扩展中包含后备资源,以防网络故障: (参考链接)
<!-- ... doctype etc ... (background.html) -->
<script src="https://..../external_bg.js"></script>
<script src="bg.js"></script>

由于 内容安全策略(CSP) 的限制,您无法运行内联JavaScript代码,因此必须使用外部JS文件。bg.js 可以如下所示:

if (!window.namespace_of_external_bg) {
    // Fallback, by defining fallback methods or injecting a new script:
    document.write('<script src="fallback_bg.js"></script>');
}
如果您想动态构建一个页面,请避免使用类似于eval的方法,因为这些方法也被CSP禁止。您可以编写一个模板,并请求外部值来填充您的模板。localStorage可用于缓存变量。有关缓存外部资源的示例,请参见Chrome扩展向当前页面的HTML添加外部JavaScript。此答案提到了内容脚本,因此无法使用确切的方法来启用缓存脚本(因为您需要使用eval来加载脚本)。但是,仍然可以使用缓存技术。
我还尝试了以下方法,但是不起作用(包含在此答案中,以便您无需自己尝试):
从AJAX响应创建一个Blob,然后使用webkitURL.createObjectURL创建临时URL来加载资源。
// Modification of https://dev59.com/8mkv5IYBdhLWcg3w4kp2#10371025
// Instead of `chrome.tabs.executeScript`, use 
// x.responseText  or  x.response (eg when using x.responseType='arraybuffer')
var blob = new Blob([x.responseText], {type: 'application/javascript'});
var url = (window.URL || window.webkitURL).createObjectURL(blob);
var s = document.createElement('script');
s.src = url;
document.head.appendChild(s);

以下代码会产生如下错误:

拒绝加载脚本“blob:chrome-extension%3A//damgmplfpicjkeogacmlgiceidmilllf/96356d24-3680-4188-812e-5661d23e81df”,因为它违反了以下内容安全策略指令:“script-src 'self' chrome-extension-resource:”。

在后台页面加载外部资源

自从Chrome 22版本以后,使用unsafe-eval CSP政策技术上就可以在后台页面中加载非https资源。这显然不推荐,因为存在安全问题(例如容易受到中间人攻击)。

这里有一个示例,可以加载任意资源并在后台脚本的上下文中运行它。

function loadScript(url) {
    var x = new XMLHttpRequest();
    x.onload = function() {
        eval(x.responseText); // <---- !!!
    };
    x.open('GET', url);
    x.send();
}
// Usage:
loadScript('http://badpractic.es/insecure.js');
  • unsafe-eval CSP策略必须被指定。
  • 通常情况下,要进行跨域请求,URL必须在清单文件的permissions部分中列入白名单,或者服务器必须启用CORS

因此,清单文件至少应包含:

"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
"permissions": ["http://badpractic.es/insecure.js"],
"background": {"scripts": ["background.js"] }

非常感谢您提供如此详细的答案。我尝试过另一种方法,即在 local.html 中嵌入外部网站的 iframe。它可以加载,但是由于同源策略,我无法调用 iframe 内的 JavaScript 函数。我将尝试您提供的解决方案。 - Anirudh Ramanathan
如果您可以控制外部页面,则可以实现window.postMessage (reference_to_frame.contentWindow.postMessage)与框架进行通信。 - Rob W
很遗憾,我无法控制外部页面。 - Anirudh Ramanathan
@Cthulhu技术已经发展,我已经更新了我的答案。 - Rob W
非常酷。我最终重新设计了我的解决方案。虽然我认为这不应该是首选方案。 - Anirudh Ramanathan
谢谢!这太完美了!我一直卡在非HTTP JS上;幸运的是它只能在我们公司的局域网内才能访问。 - Stefan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接