The webRequest.onAuthRequired event is the only webRequest event that can block a request asynchronously in Chrome (In Firefox, all webRequest events can be async; Safari does not support any blocking webRequest API).
Firefox and Chrome have an interoperable API when an extension wants to return the result synchronously from the event handler function of webRequest.onAuthRequired. But for asynchronous results, there is currently a large discrepancy, as I elaborated at mdn/content#30188 (review) (The permission aspect is out-of-scope for this issue, that's part of #264).
Chrome and Firefox support this syntax to handle an event synchronously:
// In Chrome: use chrome. instead of browser.
browser.webRequest.onAuthRequired.addListener(
function (details) {
return { /* BlockingResponse here*/ };
},
{ urls: ["*://example.com/*"] },
["blocking"]
);
Firefox also supports asynchronous results through a Promise. In the above example, replace "function (details) {" with "async function (details) {`, and it would be effectively the same as the following. Note that the event registration looks identical to before:
browser.webRequest.onAuthRequired.addListener(
function () {
// Does NOT work in Chrome!
return new Promise(resolve => {
resolve({ /* BlockingResponse here*/ });
});
},
{ urls: ["*://example.com/*"] },
["blocking"]
);
Chrome does not support Promise as return value. Instead, it requires a different way to register the listener, and passing the result via a callback:
chrome.webRequest.onAuthRequired.addListener(
function (details, asyncCallback) { // listener receives "asyncCallback" parameter.
asyncCallback({ /* BlockingResponse here*/ });
// Note: any return value is ignored.
},
{ urls: ["*://example.com/*"] },
["asyncBlocking"] // "asyncBlocking" instead of "blocking"
);
I propose to update Chrome's implementation to support Promise, with the following remarks:
- Preserve backcompat: Currently, when
asyncBlocking is used, the return value is ignored. This should continue, in case extensions use async function and still call asyncCallback asynchronously after the Promise resolves.
- "blocking" is currently documented to not support anything else than an object. Chrome could support Promise as a return value like Firefox, without concerns about backwards-compatibility (because Chrome extensions can currently not expect meaningful behavior when a
Promise is returned).
- For completeness: An alternative is to introduce yet a new extraInfoSpec enum value, e.g. "asyncBlockingPromise". I see no point in doing this.
The
webRequest.onAuthRequiredevent is the only webRequest event that can block a request asynchronously in Chrome (In Firefox, all webRequest events can be async; Safari does not support any blocking webRequest API).Firefox and Chrome have an interoperable API when an extension wants to return the result synchronously from the event handler function of
webRequest.onAuthRequired. But for asynchronous results, there is currently a large discrepancy, as I elaborated at mdn/content#30188 (review) (The permission aspect is out-of-scope for this issue, that's part of #264).Chrome and Firefox support this syntax to handle an event synchronously:
Firefox also supports asynchronous results through a Promise. In the above example, replace "function (details) {" with "async function (details) {`, and it would be effectively the same as the following. Note that the event registration looks identical to before:
Chrome does not support
Promiseas return value. Instead, it requires a different way to register the listener, and passing the result via a callback:I propose to update Chrome's implementation to support
Promise, with the following remarks:asyncBlockingis used, the return value is ignored. This should continue, in case extensions useasync functionand still callasyncCallbackasynchronously after the Promise resolves.Promiseis returned).