Blocking requests and removal of XMLHttpRequest

719 views
Skip to first unread message

JC

unread,
Nov 10, 2021, 8:09:28 AM11/10/21
to Chromium Extensions
Say you use webRequest in a manifest v3, policy-installed, enterprise extension. Each request is either canceled, redirected, or allowed, but the decision has to be made based on the result of an API request, which you then cache for similar requests in the future.

chrome.webRequest.onBeforeRequest.addListener(
(details) => mustBeSynchronous(details), { urls: [ '<all_urls>'] }, ["blocking"]
);

mustBeSynchronous(details) : chrome.webRequest.BlockingResponse {
// Must use async fetch, cannot use sync XMLHttpRequest
fetch('https://our.api.endpoint/param?uuid='+ourLookup)
.then(response => response.json())
.then(data => {
//This returns a promise anyway, not a chrome.webRequest.BlockingResponse
return makeDecisionsAbout(data);
});
// Returns as soon as fetch is sent, before promise resolves.
// tooLate cannot depend on makeDecisionsAbout()
return tooLate;
}


Without a synchronous request, the page will load before a decision can be made. On subsequent requests a cached result can be used synchronously and locally to make the decision, but the first load of any page will bypass our logic.

I understand that asynchronous requests are better for performance, but in this instance we speciically need a synchronous request for exactly the reason it's shunned; we need to hold things up. I understand discouraging the use of synchronous requests, but banning the function entirely seems a bit Procrustean.

wOxxOm

unread,
Nov 10, 2021, 9:20:35 AM11/10/21
to Chromium Extensions, JC
This is yet another use case that shows what a poor fit a service worker is for an extension's background script. Since it's highly improbable that XMLHttpRequest will be added to service workers as well as any other synchronous analog for `fetch`, your options are: 1) use/write a proxy or 2) open a separate tab/window with an html file from your extension, which will use a synchronous XMLHttpRequest. You'll use `beforeunload` event to prevent users from accidentally closing this window. This is pretty retarded, though, given the fact that the users can trivially circumvent your extension by closing this window despite the warning and manage to send the request in the small time frame before you automatically re-open it in a new tab/window.

Cuyler Stuwe

unread,
Nov 10, 2021, 9:26:22 AM11/10/21
to wOxxOm, Chromium Extensions, JC
Google seems to be stubbornly willing to die on this hill, unfortunately.

The “use cases not well served by service workers” issue on the WECG group is exploding with scenarios, despite how obscure it is.

Might as well add your case to the list:

--
You received this message because you are subscribed to the Google Groups "Chromium Extensions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extens...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-extensions/d02b7376-2088-4e13-9153-b5dd2928d0aan%40chromium.org.

JC

unread,
Nov 10, 2021, 10:32:35 AM11/10/21
to Chromium Extensions, salem...@gmail.com, Chromium Extensions, JC, wOxxOm
onAuthRequired allows asyncBlocking, so that the blocking function is asynchronous with a callback. If the hook accepts a return of Promise<chrome.webRequest.BlockingResponse> and is smart enough to wait for it to resolve, then I could simply use async/await in my decision logic. But I need this on onBeforeRequest, which does not accept asyncBlocking.

It's difficult to ask that they make any improvement to an API they're clearly trying to phase out. The migration guide says they'll keep webRequest for force-installed extension in MV3, but can I stake my product's future on that? I've experimented with using declarativeNetRequest, but it's even worse since you can't access the details of the original request to make decisions anyway.

I'm considering redirecting all pages that aren't cached to an interstitial page that has the logic I need, but even then I'd need to pass the original request URL as a URL parameter to the interstitial page. Doable with webRequest, but not with declarativeNetRequest.

Br Dev

unread,
Feb 3, 2022, 10:46:03 AM2/3/22
to Chromium Extensions, JC, salem...@gmail.com, Chromium Extensions, wOxxOm
I'm looking at adapting an enterprise Chrome extension for manifest v3 and have similar problems with  webRequest.onBeforeRequest requiring a synchronous response.

JC, you said "On subsequent requests a cached result can be used synchronously and locally to make the decision". How are you planning to do this with service workers?

As far as I can tell, the only way we can persist data in manifest v3 service workers is by using the chrome.storage API or IndexedDB, but they're both asynchronous.

Thanks
Reply all
Reply to author
Forward
0 new messages