1

Цель: Я хочу разработать веб-расширение Firefox (аналогично расширениям Chrome), которое обнаруживает файлы HTML и JavaScript, прежде чем они будут загружены. Если в этих файлах есть определенный контент, они будут заблокированы, иначе им будет разрешено пройти.Как выполнить кросс-доменный запрос XHR с правильными разрешениями в Webextension?

Задача: Содержимое файла, имеющего другой домен, не может быть собрано, потому что они вызывают ошибку «Перекрестное происхождение», поскольку заголовок Access-Control-Allow-Origin отсутствует.

Я прочитал много статей об этой проблеме, и в документации говорится, что заголовок Access-Control-Allow-Origin не понадобится, если разрешения установлены в манифесте Webextension. Здесь котировки в Mozilla Doc:

Используйте разрешения ключевого запросить специальные полномочия для расширения. [...] Ключ может содержать три вида разрешений: [...] хост разрешений [...] Разрешения хоста указаны как шаблоны соответствия, , и каждый шаблон идентифицирует группу 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" 
    } 
    ] 
} 

Вот, у меня есть «*: // */* " в ключе разрешений, что означает, что каждый веб-ресурс должен иметь разрешения и ошибка Cross-Origin не должна возникать? Или я ошибаюсь? Может кто-нибудь сказать мне, почему я получаю ошибку или как я могу избежать этого?

Моего 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, я использую $ .get метода JQuery, чтобы получить доступ к содержимому сайта , Я также попробовал $ .ajax с dataType jsonp, но в этом случае я получаю цепочку доступа бесконечности, и скрипт пытается загрузить ресурсы неограниченного времени. Я вообще этого не понимаю, почему это происходит, может быть, потому, что я использую chrome.webRequest.onBeforeRequest Listener, к которому будет обращаться, если произойдет новое соединение, и в этом случае он запускается в бесконечный цикл?

В Mozilla Doc я прочитал, что chrome.webRequest.onBeforeRequest имеет параметр, requestBody:

содержит данные тела запроса HTTP. [...] 1. Firefox не поддерживает параметр requestBody.

  1. Это решение будет лучшим => но он не доступен
  2. Я попытался $.получить с разрешения шаблон => я получаю Cross-Origin ошибку
  3. Я попытался $ .ajax с JSONP и той же схеме разрешения => я получаю бесконечный цикл

Так что вопрос снова: Как я могу получить доступ к содержимое файлов другого домена без ошибки Cross-Origin, где доменное имя открыто (например, «*: // */*»)?

+0

У меня такая же проблема. Я нашел эту страницу https://developer.mozilla.org/en-US/Add-ons/SDK/Guides/Content_Scripts/Cross_Domain_Content_Scripts, которая рассказывает о пакете.json с определенным ключом «разрешений», называемым междоменным контентом, но еще не выяснили, какова связь между этим явлением. json. – Sharun

+0

@Sharun Это о модели дополнения Firefox, а не модели WebExtensions. – Xan

+0

Ваши разрешения правильно настроены; это не должно вызывать ошибки CORS из кода сценария содержимого. Обратите внимание, что ваш 'getContentByURL' ничего не возвращает, поскольку' get' является асинхронным. – Xan

ответ

1

Наконец я мог бы исправить мою проблему с помощью следующего кода в 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(); 
    } 
} 

Одним из важных изменений является использование объекта XMLHttpRequest() вместо методов JQuery. Это решение для моего заданного вопроса в моем случае. Я пробовал это раньше, но пропустил чек на req.onreadystatechange, поэтому я сделал это неправильно. Я попробовал это также с req.onload, это тоже работает для меня!

Чтобы запустить пример, есть еще два важных момента.

Во-первых, мне нужно вернуть содержимое (req.responseText) обратно с обратным вызовом, поэтому я могу отправить ответ обратно из сценария содержимого в фоновый скрипт.

Во-вторых, поскольку ответное сообщение является асинхронным, мне нужно установить return on true. Это уведомление для прослушивателя сообщений фонового сценария, чтобы ждать ответа. Если этого не хватает, ответное сообщение с содержимым веб-сайта никогда не будет поставляться в фоновом скрипте.

И, наконец, это приводит к «общей» проблеме, которая не является непосредственно частью вопроса. chrome.webRequest.onBeforeRequest в backgroundscript.js требует обработки синхронизации для возвращаемых значений отмены (true/false) для принятия решения, чтобы заблокировать загруженные URL-адреса. Но для загрузки содержимого всегда будет нужен асинхронный запрос, поэтому эта проблема не может быть исправлена? Если я найду решение, я обновлю этот ответ.

Я надеюсь, что этот ответ поможет другим.

Смежные вопросы