3

目標: HTML および JavaScript ファイルがロードされる前にそれらを検出する Firefox Webextension (Chrome 拡張機能に類似) を開発したいと考えています。これらのファイルに特定のコンテンツがある場合はブロックされ、そうでない場合は通過が許可されます。

問題: Access-Control-Allow-Origin ヘッダーが見つからないため、"Cross-Origin" エラーがスローされるため、異なるドメインを持つファイル コンテンツを収集できません。

私はこの問題について多くのことを読みましたが、Webextension マニフェストでアクセス許可が設定されている場合、Access-Control-Allow-Origin ヘッダーは必要ないとドキュメントに書かれています。Mozilla Docの引用は次のとおりです。

アクセス許可キーを使用して、拡張機能の特別な権限を要求します。[...] キーには 3 種類の権限を含めることができます: [...] ホスト権限 [...] ホスト権限は一致パターンとして指定され、各パターンは拡張機能が追加の権限を要求している URL のグループを識別します。 . 追加の権限には、次のものが含まれます。これらのオリジンへのXHR アクセス [...]

私のmanifest.json:

{
  [...],    
  "permissions": [
    "tabs",
    "*://*/*",
    "webRequest",
    "webRequestBlocking",
    "<all_urls>"
  ],    
  "background": {
    "scripts": ["backgroundscript.js"]
  },    
  "content_scripts": [
    {
      "matches": ["*://*/*"],
      "js": ["/lib/jquery-2.2.4.min.js", "/contentscript.js"],
      "run_at": "document_start"
    }
  ]
}

ここでは、パーミッション キーに"*://*/*"が含まれています。これは、各 Web リソースにパーミッションが必要であり、クロス オリジン エラーが発生しないことを意味します。それとも私が間違っていますか?エラーが発生する理由、またはエラーを回避する方法を誰か教えてもらえますか?

私のbackgroundscript.js:

chrome.webRequest.onBeforeRequest.addListener(
    logURL,
    {urls: ["<all_urls>"], types: ["main_frame", "script"]},
    ["blocking"]
);

function logURL(requestDetails) {
    chrome.tabs.sendMessage(
        requestDetails.tabId,
        {action: "getContentByURL", url: requestDetails.url, type: requestDetails.type},
        function(response) {
            console.log(response);
        }
    );
    if(requestDetails.type == 'script') {
        // here will be the conditions, based on the content of the files,
        // if they will be canceled or allowed to pass
        // actually, there is just a dummy "false"
        return {cancel: false};
    }
}

私の contentscript.js:

chrome.runtime.onMessage.addListener(
    function(message, sender, sendResponse) {
        var contentAll = [];
        if(message.action == 'getContentByURL') {
            var pageContent = getContentByURL(message.url);
            contentAll.push(pageContent);
            sendResponse({"content" : contentAll});
        }
    }
);
function getContentByURL(url) {
    $(document).ready(function() {
        $.get(url, function(data) {
            console.log(data);
        });
    });
}

contentscript.js では、jQuery の$.getメソッドを使用して Web サイトのコンテンツにアクセスします。また、 dataType jsonp で $.ajax を試しましが、この場合、無限のアクセス チェーンが得られ、スクリプトはリソースを無制限に読み込もうとします。新しい接続が発生した場合にアクセスされる chrome.webRequest.onBeforeRequest リスナーを使用している可能性があります。この場合、無限ループに陥りますか?

私が読んだMozilla Docでは、chrome.webRequest.onBeforeRequest に requestBody というパラメーターがあります。

HTTP 要求本文データが含まれます。[...] 1. Firefox は「requestBody」オプションをサポートしていません。

  1. このソリューションが最適です => しかし、利用できません
  2. 許可パターンで $.get を試しました => Cross-Origin エラーが発生します
  3. jsonp と同じ許可パターンで $.ajax を試しました => 無限ループが発生します

もう一度質問します:ドメイン名が開いている場合 ("*://*/*" のようなパターン)、クロスオリジン エラーなしで別のドメインのファイルのコンテンツにアクセスするにはどうすればよいですか?

4

1 に答える 1

4

最後に、contentscript.js の次のコードで問題を解決できました。

chrome.runtime.onMessage.addListener(
    function(message, sender, sendResponse) {
        if(message.action == 'getContentByURL') {
            getContentByURL(message.url, function(result) {
                sendResponse({"content" : result});
            });
        } else {
            sendResponse('error');
        }
        return true;
    }
);

function getContentByURL(url, callback) {
    var req = new XMLHttpRequest();
    if(req) {
        req.open('GET', url, true);
        req.onreadystatechange =  function() {
            if (req.readyState == 4) {
                callback(req.responseText);
            }
        };
        req.send();
    }
}

重要な変更の 1 つは、jQuery メソッドの代わりに XMLHttpRequest() オブジェクトを使用することです。これは、私の場合の質問に対する解決策でした。以前にこれを試しましたが、req.onreadystatechange でチェックを逃したため、間違っていました。req.onloadでも試してみましたが、これもうまくいきます!

サンプルを実行するには、もう 2 つの重要なポイントがあります。

まず、コールバックを使用してコンテンツ (req.responseText) をスローする必要があります。これにより、コンテンツ スクリプトからバックグラウンド スクリプトに応答を返すことができます。

次に、応答メッセージが非同期であるため、return on true を設定する必要があります。これは、応答を待機するバックグラウンド スクリプト メッセージ リスナーへの通知です。これがないと、Web サイトのコンテンツを含む応答メッセージがバックグラウンド スクリプトで配信されません。

最後に、これは直接問題の一部ではない「一般的な」問題につながります。backgroundscript.js の chrome.webRequest.onBeforeRequest では、読み込まれた URL をブロックする意思決定のために、「キャンセル」の戻り値 (true/false) の同期処理が必要です。しかし、コンテンツをロードするには、常に非同期リクエストが必要になるため、この問題は修正できませんか? 解決策が見つかったら、この回答を更新します。

この回答が他の人にも役立つことを願っています。

于 2016-05-27T23:24:57.143 に答える