簡體   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