web-dev-qa-db-ja.com

バックグラウンドページを使用したクロスドメインXMLHttpRequest

Chrome拡張機能で、options.htmlページをGoogleのOpenIdAPIなどと通信させたいです。これをシームレスに行うために、オプションページにiframeを非表示にして、Googleアカウントのログインページをポップアップします(OpenIdインタラクションシーケンスなどに従います)。

私の問題は、オプションページからiframeに通信できないことです(iframeの原点は私が制御するものですが、私のchromeと同じではありません拡張)window.postMessage経由。この問題の迅速な回避策があるかどうか疑問に思っていました。

ない場合は、options.htmlにページのレイアウトとロジックを格納するiframeを含めるようにします。

15
yuzeh

Iframeをいじる必要はありません。バックグラウンドページを使用して、クロスドメインXMLHttpRequestsを実行することが可能です。 Chrome 13なので、コンテンツスクリプトからクロスサイトリクエストを行うことができます。ただし、ページに制限付きのコンテンツセキュリティポリシーヘッダーが提供されている場合、リクエストは失敗する可能性があります connect-src

コンテンツスクリプトではなくnexyメソッドを選択する別の理由は、httpサイトへのリクエストにより、混合コンテンツの警告が発生することです(「https:// ...のページにhttp:// ...の安全でないコンテンツが表示されました」)。

リクエストをバックグラウンドページに委任するもう1つの理由は、file://スキームのページで実行されていない限り、コンテンツスクリプトをfile:から読み取ることができないため、file://からリソースを取得する場合です。


クロスオリジンリクエストを有効にするには、マニフェストファイルのpermissions配列を使用して、拡張機能に権限を明示的に付与する必要があります。

バックグラウンドスクリプトを使用したクロスサイトリクエスト。

コンテンツスクリプトは messaging 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
    }
}
37
Rob W

私は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" ]
  }
4
kishoreballa