Javascript 使用背景页的跨域XMLHttpRequest
在我的Chrome扩展中,我想让我的Javascript 使用背景页的跨域XMLHttpRequest,javascript,google-chrome,google-chrome-extension,xmlhttprequest,cross-domain,Javascript,Google Chrome,Google Chrome Extension,Xmlhttprequest,Cross Domain,在我的Chrome扩展中,我想让我的options.html页面与Google的OpenIDAPI之类的东西进行通信。为了无缝地实现这一点,我在选项页面上有一个隐藏的iframe,它将弹出Google帐户登录页面(遵循OpenId交互顺序,等等) 我的问题是,我无法通过window.postMessage从选项页面与iframe进行通信(iframe的来源由我控制,但与我的chrome扩展不同)。我想知道是否有一个快速解决这个问题的方法 如果没有,我将使options.html包含包含页面布局和
options.html
页面与Google的OpenIDAPI之类的东西进行通信。为了无缝地实现这一点,我在选项页面上有一个隐藏的iframe
,它将弹出Google帐户登录页面(遵循OpenId交互顺序,等等)
我的问题是,我无法通过window.postMessage
从选项页面与iframe
进行通信(iframe的来源由我控制,但与我的chrome扩展不同)。我想知道是否有一个快速解决这个问题的方法
如果没有,我将使
options.html
包含包含页面布局和逻辑的iframe
。您不必弄乱iframe。可以使用后台页面执行跨域XMLHttpRequests。自Chrome13以来,可以通过内容脚本进行跨站点请求。但是,如果为页面提供带有限制的内容安全策略标头,则请求仍可能失败
选择nexy方法而不是内容脚本的另一个原因是,对http站点的请求将导致混合内容警告(“位于https://... 显示来自的不安全内容http://..."
将请求委托给后台页面的另一个原因是当您希望从文件://
获取资源时,因为内容脚本无法从文件:
读取,除非它在文件://
方案的页面上运行
注意要启用跨源请求,您必须使用清单文件中的
permissions
数组显式授予扩展名权限
使用后台脚本的跨站点请求。
内容脚本将通过API从后台请求功能。下面是一个发送和获取请求响应的非常简单的方法的示例
chrome.runtime.sendMessage({
方法:“POST”,
动作:“xhttp”,
网址:'http://www.stackoverflow.com/search',
数据:“q=某物”
},函数(responseText){
警报(responseText);
/*回调函数来处理响应*/
});
/页:
/**
*请求的可能参数:
*操作:“xhttp”用于跨源HTTP请求
*方法:默认的“获取”
*url:必需,但未验证
*数据:在POST请求中发送的数据
*
*在请求完成时调用回调函数*/
chrome.runtime.onMessage.addListener(函数(请求、发送方、回调){
如果(request.action==“xhttp”){
var xhttp=newXMLHttpRequest();
var method=request.method?request.method.toUpperCase():'GET';
xhttp.onload=函数(){
回调(xhttp.responseText);
};
xhttp.onerror=函数(){
//在出现错误时,可以执行任何操作。不要忘记调用
//回调以清理通信端口。
回调();
};
open(方法,request.url,true);
如果(方法=='POST'){
setRequestHeader('Content-Type','application/x-www-form-urlencoded');
}
xhttp.send(请求.数据);
return true;//防止在返回时过早调用回调
}
});
备注:消息传递API已多次重命名。如果您的目标浏览器不是最新的Chrome版本,请退出
为了完整起见,这里有一个文件来试用我的演示:
{
“名称”:“X域测试”,
“清单版本”:2,
“权限”:[
"http://www.stackoverflow.com/search*"
],
“内容脚本”:{
“js”:[“contentscript.js”],
“匹配项”:[“http://www.example.com/*"]
},
“背景”:{
“脚本”:[“background.js”],
“持续”:假
}
}
我使用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" ]
}
感谢您的帮助,但是您可能需要更新它,因为您的背景事件页面有一些问题。xhttp.open()必须放在POST setRequestHeader之前,否则会出错。此外,也没有理由设置内容长度,因为它将被拒绝。有没有建议在此基础上添加一个超时/重试,这将适用于异步性质,可能会同时运行多个查询?@JeffG您能说得更具体一点吗?有时候XMLHttpRequest会挂起,因为没有设置超时。所以我在寻找一种设置超时的方法,然后重试最多3次。我刚刚发现:这可能会有帮助,但不能确定每个请求中的尝试次数,因为它不能是一个外部变量,因为它是异步的。@jeff如果您从弹出窗口调用
chrome.runtime.sendMessage
,然后在收到HTTP响应之前检查后台页面(导致弹出窗口关闭),当弹出上下文关闭时,sendResponse
确实会失败。