Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/371.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用背景页的跨域XMLHttpRequest_Javascript_Google Chrome_Google Chrome Extension_Xmlhttprequest_Cross Domain - Fatal编程技术网

Javascript 使用背景页的跨域XMLHttpRequest

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包含包含页面布局和

在我的Chrome扩展中,我想让我的
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
确实会失败。