Reputation: 520
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"]);
Upvotes: 0
Views: 206
Reputation: 443
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};
}
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
Upvotes: 1