繁体   English   中英

使用后台页面的跨域XMLHttpRequest

[英]Cross-domain XMLHttpRequest using background pages

在我的Chrome扩展程序中,我想让我的options.html页面与Google的OpenId API进行通信。 为了无缝地执行此操作,我在选项页面上有一个隐藏的iframe ,它会弹出Google帐户登录页面(遵循OpenId交互顺序等)。

我的问题是,我无法从选项页的沟通iframe (的起源iframe是我控制,但由于我的Chrome扩展不一样的)通过window.postMessage 我想知道这个问题是否有快速的解决方法。

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

你不必搞乱iframe。 可以使用后台页面执行跨域XMLHttpRequests。 从Chrome 13开始,可以从内容脚本中进行跨站点请求。 但是,如果页面是使用带有限制connect-src的Content Security Policy标头提供的,则请求仍然可能失败。

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

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

注意
要启用跨源请求,您必须使用清单文件中的permissions数组显式授予扩展permissions

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

内容脚本将通过消息传递 API从后台请求功能。 以下是发送和获取请求响应的一种非常简单的方法示例。

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" ]
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM