On 28/06/2023 22:22, 'Oliver Dunk' via Chromium Extensions wrote:
>
> There are some specific ways of
> doing this in certain APIs - for example, chrome.desktopCapture has a
> cancelChooseDesktopMedia
> <
https://developer.chrome.com/docs/extensions/reference/desktopCapture/#method-cancelChooseDesktopMedia>
> function.
Thank you, Oliver for this example. I have never used the desktopCapture
API. At first glance, with help of AbortSignal, the
cancelChooseDesktopMedia method and desktopMediaRequestId can be made
unnecessary. A method that should be introduced in addition to
chooseDesktopMedia may return a Promise for a {streamId, options}
object. Method's last argument may be either a callback or a {callback,
signal} object with optional fields. Another variant is an additional
"parameters" ({signal}} argument before callback.
An example of current API that does not require any change is messaging
using connections. Ports can be closed when necessary. Unfortunately
such technique would be inconvenient for functions returning single value.
> If you can't find a bug, please do open one!
Do you mean a Chromium bug or
https://github.com/w3c/webextensions/ ? My
impression is that the latter one is better for discussion.
> One of the tricky things here would be that it's unclear where it would
> go in different APIs. An extra parameter you can pass? A property you
> set somewhere? Definitely solvable, but would require some thinking.
Polymorphic functions increase complexity of implementation code, but
{callback, signal} may be a viable alternative to just callback function
as the last argument.
> I usually use Promise.race with two promises, the one I actually care
> about and then one that will just reject after a set period of time.
> That usually seems like a fairly nice solution.
To deal with current API, Promise.race or callback wrappers are
unavoidable. Besides timeout, another reason to not wait results is a
new action initiated by the user, so processing of the previous action
should be abandoned. A kind of execution context object is necessary
anyway to observe cancellation. Approximately the same amount of code is
required to implement such context purely with promises or to use
AbortController and AbortSignal pair and convert the signal into a
promise when necessary. A minor advantage of second approach is that the
signal may be reused for fetch() directly without an adapter converting
promise to a signal instance.
A bit more tricky task is to pass deadline to a content script to not
run it at all if delay between calling scripting.executeScript and
actual execution is too large. I have even tried killing content script
by another call of executeScript, but I consider it fragile. Native
support of scripts aborting may keep developers aside from such complexity.