使用后台页面的跨域XMLHttpRequest

在我的Chrome扩展中,我想让我的options.html页面与Google的OpenId API进行通信。 为了做到这一点,我在选项页面上隐藏了一个iframe ,它将popupGoogle帐户login页面(遵循OpenId交互序列等)。

我的问题是,我不能通过window.postMessage从选项页面到iframeiframe的起源是我控制的,但不是我的铬扩展)。 我想知道是否有一个快速解决这个问题。

如果没有,我将使options.html包含一个iframe ,其中包含页面的布局和逻辑。

你不必乱用iframe。 使用后台页面可以执行跨域XMLHttpRequests。 自Chrome 13以来,可以通过内容脚本进行跨站点请求。 但是,如果页面的内容安全策略头带有限制的connect-src ,则请求仍可能失败。

select内容脚本的nexy方法的另一个原因是,对http站点的请求将导致混合内容警告(“http:// …中的页面显示来自http:// …的不安全内容”)。

将请求委托给后台页面的另一个原因是当你想从file://获取资源时,因为内容脚本不能从file:读取,除非它在file://scheme的页面上运行。

注意
要启用交叉源请求,必须使用清单文件中的permissions数组明确授予您的扩展permissions

使用后台脚本的跨站点请求。

内容脚本将通过消息传递 API从后台请求function。 下面是一个非常简单的发送和获取请求响应的例子。

 chrome.runtime.sendMessage({ method: 'POST', action: 'xhttp', url: 'http://www.stackoverflow.com/search', data: 'q=something' }, function(responseText) { alert(responseText); /*Callback function to deal with the response*/ }); 

背景 / 活动页面:

 /** * Possible parameters for request: * action: "xhttp" for a cross-origin HTTP request * method: Default "GET" * url : required, but not validated * data : data to send in a POST request * * The callback function is called upon completion of the request */ chrome.runtime.onMessage.addListener(function(request, sender, callback) { if (request.action == "xhttp") { var xhttp = new XMLHttpRequest(); var method = request.method ? request.method.toUpperCase() : 'GET'; xhttp.onload = function() { callback(xhttp.responseText); }; xhttp.onerror = function() { // Do whatever you want on error. Don't forget to invoke the // callback to clean up the communication port. callback(); }; xhttp.open(method, request.url, true); if (method == 'POST') { xhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); } xhttp.send(request.data); return true; // prevents the callback from being called too early on return } }); 

备注:消息传递API已多次重命名。 如果您的目标浏览器不是最新的Chrome版本,请查看此答案 。

为了完整起见,下面是一个清单文件来试用我的演示:

 { "name": "X-domain test", "manifest_version": 2, "permissions": [ "http://www.stackoverflow.com/search*" ], "content_scripts": { "js": ["contentscript.js"], "matches": ["http://www.example.com/*"] }, "background": { "scripts": ["background.js"], "persistent": false } } 

我用jQuery实现了同样的事情,它更简单,而且工作也很棒。

background.js

 chrome.runtime.onMessage.addListener(function(request, sender, callback) { if (request.action == "xhttp") { $.ajax({ type: request.method, url: request.url, data: request.data, success: function(responseText){ callback(responseText); }, error: function(XMLHttpRequest, textStatus, errorThrown) { //if required, do some error handling callback(); } }); return true; // prevents the callback from being called too early on return } }); 

contentscript.js

 chrome.runtime.sendMessage({ method: 'POST', action: 'xhttp', url: 'http://example-url.com/page.php', data: "key=value" }, function(reponseText) { alert(responseText); }); 

但要确保manifest.json文件具有所需的权限和jquery js文件

  "permissions": [ "tabs", "activeTab", "http://example-url.com/*" ], "content_scripts": [ { "js": [ "jquery-3.1.0.min.js", "contentscript.js" ], "matches": [ "https://example-ssl-site.com/*" ] }], "background": { "scripts": [ "jquery-3.1.0.min.js", "background.js" ] }