0

In my Chrome extension, I check each web request under a specific domain. If the URL matches a specific condition, and there's an existing open tab that matches another URL, I'd like to return {cancel: true}, which means the request is blocked.

So my code works this way: if the requested URL matches my condition, check all open tabs. If one of the open tabs matches my (second) condition, I want to return {cancel: true} from my initial (outer) function.

The Problem: The return from the outer function fires before all of the tabs are checked (= before all the forEach loops are executed), therefore it always returns {cancel: false}.

[I know there are many questions related to this, and one of the main solutions includes callback functions, but specifically in my case I haven't yet succeeded in making this work.]

Code:

function onBeforeRequestHandler (details) {
    var cancel = false;
    var url = details.url;
    // condition 1
    if (url.indexOf("condition_1") > -1){

        // check all open windows/tabs
        chrome.windows.getAll({populate:true}, function(windows){
            windows.forEach(function(single_window){
                single_window.tabs.forEach(function(tab){
                    // condition 2
                    if (tab.url.indexOf("condition_2") > -1){
                        cancel = true;
                        // this is less important - updating the tab works
                        chrome.tabs.update(tab.id, {url: url});
                    }
                });
            });
        });
        // always getting cancel = false here because it fires too quickly
        return {cancel: cancel};
    }
    else
        return {cancel: false};
}

chrome.webRequest.onBeforeRequest.addListener(onBeforeRequestHandler, {urls: ["some_domain"]}, ["blocking"]);
9
  • 1
    Possible duplicate of How do I return the response from an asynchronous call? Commented Jun 25, 2018 at 5:08
  • @teemu this won't really help here. Commented Jun 25, 2018 at 5:10
  • 1
    What you are trying to achieve is impossible. You cannot cancel something now if you get to know if you shouod cancel it in a few seconds. Instead you would have to cancel the action, and then if the check fails restart it. Commented Jun 25, 2018 at 5:12
  • 1
    You can't, thats the thing. Commented Jun 25, 2018 at 5:17
  • 1
    The listener must return the value synchronously but your code runs asynchronous API. These are hard facts which you can't magically change to accommodate to your needs. Instead, maintain an array of windows and tabs preemptively using chrome.tabs and chrome.windows events. Commented Jun 25, 2018 at 5:42

1 Answer 1

1

Currently, you can't cancel the request based on asynchronous function in the Google Chrome.

In the Firefox, it already supported asynchronous function with Promise, you can implement that like following code.

function onBeforeRequestHandler (details) {
   var cancel = false;
   var url = details.url;
   // condition 1
   if (url.indexOf("condition_1") > -1){
       // check all open windows/tabs
       // return Promise which will be resolved after populate windows/tabs
       return browser.windows.getAll({populate:true})
           .then(function(windows) {
               windows.forEach(function(single_window) {
                   single_window.tabs.forEach(function(tab) {
                   // condition 2
                   if (tab.url.indexOf("condition_2") > -1) {
                       // this is less important - updating the tab works
                       browser.tabs.update(tab.id, {url: url});
                       return { cancel: true }
                   }
               });
           });
         })
   }
   else
       return {cancel: false};
}

history / references

According to webRequest.onBeforeRequest in MDN.

From Firefox 52 onwards, instead of returning BlockingResponse, the listener can return a Promise which is resolved with a BlockingResponse. This enables the listener to process the request asynchronously. https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/webRequest/onBeforeRequest

Already reported feature request on the Chrome like the Firefox, but this ticket has NOT been closed. https://bugs.chromium.org/p/chromium/issues/detail?id=625860

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.