javascript - 使用后台页面的跨域XMLHttpRequest

标签 javascript google-chrome google-chrome-extension xmlhttprequest cross-domain

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

我的问题是我无法从选项页面与 iframe 通信(iframe 的来源是我控制的,但与我的不同chrome 扩展)通过 window.postMessage。我想知道这个问题是否有快速解决方法。

如果没有,我会让 options.html 包含一个 iframe 来容纳页面的布局和逻辑。

最佳答案

您不必乱用 iframe。可以使用后台页面执行跨域 XMLHttpRequests。从 Chrome 13 开始,可以从内容脚本发出跨站请求。但是,如果页面使用带有限制性 connect-src 的内容安全策略 header 提供,请求仍然会失败。 .

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

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

Note
To enable cross-origin requests, you have to explicitly grant permissions to your extension using the permissions array in your manifest file.

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

内容脚本将通过 messaging 从后台请求功能应用程序接口(interface)。这是发送和获取请求响应的非常简单的方法的示例。

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*/
});

Background/event页:

/**
 * 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 版本,请查看 this answer .

为了完整起见,这里有一个 manifest文件来试用我的演示:

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

关于javascript - 使用后台页面的跨域XMLHttpRequest,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7699615/

相关文章:

javascript - 如何从 Protractor 测试发出 POST 请求?

javascript - 推送到空数组,即使它被称为全局数组并且在我的本地主机上工作,但不在服务器上

javascript - jQuery 工具提示在 .click 上而不是在 Chrome 扩展中悬停

linux - 如何从 Google Chrome for Linux(Fedora) 的代理中排除某些域或 IP 地址?

javascript - Chrome Extension : window. innerWidth = 0 ?//bonus: 最大化窗口

javascript - 如何让 chrome 扩展在页面加载时在后台执行功能?

javascript - 如何将指定选项卡导航到新网址

javascript - 无法理解如何使用 javascript 和 jquery 代码来做到这一点

javascript - 我如何执行此行一次?

javascript - Fancybox3 与 iFrame - 防止关闭覆盖点击