Javascript 使用后台页面的跨域 XMLHttpRequest
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7699615/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cross-domain XMLHttpRequest using background pages
提问by yuzeh
In my Chrome extension, I want to have my options.htmlpage communicate with something like Google's OpenId API. In order to do this seamlessly, I have a hidden iframeon the options page which will pop-up the Google Accounts login page (following the OpenId interaction sequence, etc.).
在我的 Chrome 扩展程序中,我想让我的options.html页面与 Google 的 OpenId API 之类的东西进行通信。为了无缝地做到这一点,我iframe在选项页面上有一个隐藏,它将弹出 Google 帐户登录页面(遵循 OpenId 交互序列等)。
My issue is that I can't communicate from the options page to the iframe(the origin of the iframeis something I control, but not the same as my chrome extension) via window.postMessage. I was wondering if there is a quick workaround to this issue.
我的问题是,我无法从选项页传达给iframe(的起源iframe经是我控制,但由于我的Chrome扩展不一样的)window.postMessage。我想知道是否有解决此问题的快速解决方法。
If there isn't, I'm going to make options.htmlcontain an iframethat houses the layout and logic of the page.
如果没有,我将创建options.html一个包含iframe页面布局和逻辑的内容。
回答by Rob W
You don't have to mess with iframes. It's possible to perform cross-domain XMLHttpRequests, using background pages. Since Chrome 13, cross-site requests can be made from the content script. However, requests can still fail if the page is served with a Content Security Policy header with a restricting connect-src.
您不必弄乱 iframe。可以使用后台页面执行跨域 XMLHttpRequests。从 Chrome 13 开始,可以从内容脚本发出跨站点请求。但是,如果页面使用带有限制connect-src.
Another reason for choosing the nexy method over content scripts is that requests to http sites will cause a mixed content warning ("The page at https://... displayed insecure content from http://...").
选择 nexy 方法而不是内容脚本的另一个原因是对 http 站点的请求将导致混合内容警告(“https://... 上的页面显示来自 http://... 的不安全内容”)。
Yet another reason for delegating the request to the background page is when you want to get a resource from the file://, because a content script cannot read from file:, unless it is running on a page at the file://scheme.
将请求委托给后台页面的另一个原因是当您想要从 获取资源时file://,因为内容脚本无法从 读取file:,除非它在该file://方案的页面上运行。
Note
To enable cross-origin requests, you have to explicitly grant permissions to your extension using thepermissionsarray in your manifest file.
注意
要启用跨域请求,您必须使用permissions清单文件中的数组明确授予扩展程序权限。
Cross-site request using background script.
使用后台脚本的跨站点请求。
The content script would request the functionality from the background via the messagingAPI. Here is an example of a very simple way of sending and getting the response of a request.
内容脚本将通过消息传递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*/
});
Background/ eventpage:
/**
* 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
}
});
Remark: The messaging APIs have been renamed several times. If your target browser is not the latest Chrome version, check out this answer.
备注:消息 API 已多次重命名。如果您的目标浏览器不是最新的 Chrome 版本,请查看此答案。
For completeness, here's a manifestfile to try out my demo:
为了完整起见,这里有一个清单文件来试用我的演示:
{
"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
}
}
回答by kishoreballa
I implemented the same thing using jquery its much simpler and it worked great too..
我使用 jquery 实现了同样的事情,它更简单,而且效果很好。
background.js
背景.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
内容脚本.js
chrome.runtime.sendMessage({
method: 'POST',
action: 'xhttp',
url: 'http://example-url.com/page.php',
data: "key=value"
}, function(reponseText) {
alert(responseText);
});
But make sure manifest.json file has required permissions and jquery js file
但请确保 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" ]
}

