0

I am attempting to create a chrome extension that queries an external source as a reference to block or allow through a particular page. The following is part of my code. I am new to javascript, and scope always seems to be something that screws me up.

chrome.webRequest.onBeforeRequest.addListener(
    function(details) {

        var http = new XMLHttpRequest();
        var url = "http://xxx.xx.xxxx";
        var params = "urlCheck="+encodeString_(details.url);
        http.open("POST", url, true);
        //Send the proper header information along with the request
        http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

        http.onreadystatechange = function() {
            if(http.readyState == 4 && http.status == 200) {
                guilt = 0;
                console.log(guilt);
            }else if(http.readyState == 4 && http.status == 404){
                guilt = 1;
                console.log(guilt);
            }
        }
        http.send(params);

    if(guilt == 1){
        return {cancel: true};
        }else{
        return {cancel: false};
        }

    },
    {urls: ["<all_urls>"],
     types:["main_frame"]
    },
    ["blocking"]
    );

Any help would be greatly appreciated! Thanks.

Joe M
  • 17
  • 6

1 Answers1

1

You can't do that.

Your code does not work as expected because XHR is asynchronous; your onreadystatechange is executed after the whole outer function finishes. So guilt will be undefined or, worse, stale (from the last request).

For more information, see this canonical question: Why is my variable unaltered after I modify it inside of a function?

However, if you try to fix this, you'll notice that you can't return a response from within the async handler.

This is intentional: there is no function to pass and then call later (like sendResponse in Messaging API), because Chrome will not wait for you. You are expected to respond to a blocking call in a deterministic and fast way.

If the optional opt_extraInfoSpec array contains the string 'blocking' (only allowed for specific events), the callback function is handled synchronously. That means that the request is blocked until the callback function returns.

You could try to bypass it by using synchronous XHR calls. That is not a very good idea in general, since loading a remote response takes a long time, and synchronous XHR is considered deprecated. Even though you limited your queries to "main_frame" requests, this still adds an uncertain delay to each load.

A proper way to do that would be to load a set of rules from a server and update it periodically, and when a request occurs validate it against this local copy of rules. This is the approach extensions like AdBlock use.

Community
  • 1
  • 1
Xan
  • 74,770
  • 16
  • 179
  • 206