Skip to content

Support Promise as return value from webRequest.onAuthRequired #490

@Rob--W

Description

@Rob--W

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions