Cross-domain XMLHttpRequest using background pages

前端 未结 2 1185
礼貌的吻别
礼貌的吻别 2020-11-28 21:29

In my Chrome extension, I want to have my options.html page communicate with something like Google\'s OpenId API. In order to do this seamlessly, I have a hidde

相关标签:
2条回答
  • 2020-11-28 22:01

    You don't have to mess with iframes. It's possible to perform cross-domain XMLHttpRequests, using background pages. Since Chrome 13, cross-site requests can be made from the content script. However, requests can still fail if the page is served with a Content Security Policy header with a restricting connect-src.

    Another reason for choosing the nexy method over content scripts is that requests to http sites will cause a mixed content warning ("The page at https://... displayed insecure content from http://...").

    Yet another reason for delegating the request to the background page is when you want to get a resource from the file://, because a content script cannot read from file:, unless it is running on a page at the file:// scheme.

    Note
    To enable cross-origin requests, you have to explicitly grant permissions to your extension using the permissions array in your manifest file.

    Cross-site request using background script.

    The content script would request the functionality from the background via the messaging API. Here is an example of a very simple way of sending and getting the response of a request.

    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*/
    });
    

    Background / event page:

    /**
     * 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
        }
    });
    

    Remark: The messaging APIs have been renamed several times. If your target browser is not the latest Chrome version, check out this answer.

    For completeness, here's a manifest file to try out my demo:

    {
        "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
        }
    }
    
    0 讨论(0)
  • 2020-11-28 22:04

    I implemented the same thing using jquery its much simpler and it worked great too..

    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);
        }); 
    

    But make sure manifest.json file has required permissions and jquery js file

      "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" ]
      }
    
    0 讨论(0)
提交回复
热议问题