Междоменный XMLHttpRequest с использованием фоновых страниц - PullRequest
14 голосов
/ 09 октября 2011

В моем расширении Chrome я хочу, чтобы моя страница options.html общалась с чем-то вроде API Google OpenId.Чтобы сделать это незаметно, у меня есть скрытая iframe на странице параметров, которая откроет страницу входа в учетные записи Google (после последовательности взаимодействия OpenId и т. Д.).

Моя проблема заключается в том, что яне могу связаться со страницы параметров с iframe (происхождение iframe - это то, что я контролирую, но не совпадает с моим расширением chrome) через window.postMessage.Мне было интересно, есть ли быстрый способ обойти эту проблему.

Если нет, я собираюсь сделать так, чтобы options.html содержал iframe, который содержит макет и логику страницы.

Ответы [ 2 ]

37 голосов
/ 09 октября 2011

Вам не нужно связываться с фреймами. Можно выполнять междоменный XMLHttpRequests, используя фоновые страницы. Начиная с Chrome 13, межсайтовые запросы могут быть сделаны из скрипта контента. Тем не менее, запросы могут по-прежнему не выполняться, если страница обслуживается заголовком политики безопасности содержимого с ограничением connect-src.

Еще одна причина выбора метода nexy вместо сценариев содержимого заключается в том, что запросы к сайтам http будут вызывать смешанное предупреждение о содержимом («На странице https: // ... отображается небезопасный контент с http: // ...») .

Еще одна причина для делегирования запроса на фоновую страницу - это когда вы хотите получить ресурс из file://, потому что скрипт содержимого не может прочитать из file:, если он не запущен на странице в file:// схема.

Примечание
Чтобы включить запросы между источниками, вы должны явно предоставить разрешения вашему расширению, используя массив 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
    }
}
4 голосов
/ 23 сентября 2016

Я реализовал то же самое, используя 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" ]
  }
...