-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Automation section and WebDriver support #265
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies for taking so long to review this pull request. Supporting workers (shared workers in particular) presents additional challenges. I was also trying to take the DevTools use case into consideration; even though it's orthogonal to the spec, having the WebDriver and DevTools models be similar helps us enormously.
What we've done in Generic Sensors, Device Orientation and Device Posture is plug any overridden data into a top-level navigable, so that essentially all frames in a tab use the same override, which also persists across navigations (since it's basically tied to the tab, not the main frame). This works great for features exposed to Window, and possibly for dedicated workers too, but shared workers are tied to an origin, not a tab, and can even outlive it.
Option 1: tracking origins
One approach would be tying the pressure override information to an origin rather than a top-level navigable like the Permissions API does. Since we need more endpoints than the Permissions API, perhaps we could draw some inspiration from WebAuthn and keep a mapping of source type to a list of domains that could be referred to by an id. The pseudocode would look like this in JS:
const id = await add_override("cpu", ["kde.org", "www.foo.bar:8443"]);
await set_pressure(id, { state: "critical" });
await remove_override(id);
This works great for WebDriver and web tests but not so much for DevTools, where the effects are only supposed to last while the UI is open and only affect the current tab. We'd probably need separate CDP commands for this use case and error out when both modes are being used at the same time, and optionally just not support shared workers in this case at all.
Option 2: storing the data in the top-level traversable
The usual approach. Works great with DevTools and WebDriver, except in the shared workers case: what should happen when the top-level traversable is destroyed but the shared worker's owner set remains non-empty?
This is the easiest approach to spec and implement though.
General comments
Before reviewing this PR line by line and regardless of the issue above, some bigger picture points need to be settled:
- It is generally a good idea to use WebDriver to provide fake/virtual/mock versions of the lowest level of your stack so that more of the real one is exercised.
- Specifically, I am not convinced you need a "mock platform collector" on top of a virtual pressure source; instead, the spec needs to make a regular platform collector connect to a virtual pressure source when desired.
- Related to the above, there needs to be a closer integration into the existing algorithms. For example:
- What does "using a virtual source type" mean exactly?
- Which parts of https://w3c.github.io/compute-pressure/#processing-model and https://w3c.github.io/compute-pressure/#the-pressureobserver-object (and others) need to be aware of the automation concepts and use them?
- What happens when a virtual source type is removed while one or more observers are active? Should they just stop receiving callbacks?
- The data delivery model: should an update immediately notify the platform collector, or should it be stored and picked up by the platform collector at its sampling rate? This is normally an implementation detail, but with this API we have the problem of a potentially too slow sampling rate in production that the former option could help with.
- there is one platform collector per global object (GO) - a platform collector will use virtual sources for non-worker GOs - virtual sources update data at a given sample rate set when created - pressure observers collect data at their own given sample rate
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In addition to the inline comments and discussions, let's summarize some pending items so we don't forget about them:
- @JuhaVainio's point that it should be possible for a virtual pressure source to report itself as non-existent, so that
observe()
rejecting with NotSupportedError can be tested. - When an update's timestamp should be set when a virtual pressure source is being used.
- What to do when "update virtual pressure source" is called before any observers are observing. The simplest option is to just ignore these updates; another option is to save either all or the latest and report it once the first observer starts observing.
This ended up being fixed a while ago.
Getters are tricky because the information they return might be outdated by the time it reaches users. Unless really needed, I don't think we need to provide ways to access this information (which should be available to users anyway given that they made the WebDriver calls).
If we take the "let users handle the sampling rate" approach I mentioned in one of the inline comments, this might end up becoming a non-issue as a side-effect. |
It was not being used anywhere; the source type is always when manipulating the virtual pressure source mapping, which uses source types as keys.
This makes it more clear when writing the spec that this is a concept related to a virtual pressure source rather than a general one.
…te algorithm This makes it possible to invoke it from multiple locations in preparation for supporting adding a virtual pressure source that reports itself as non-existent. While here: add `class="algorithm"` to the "data collection" algorithm.
This flag can be set in the "create virtual pressure source" endpoint, where it is set to true by default. When false, it causes calls to PressureObserver.observe() to reject with NotSupportedError when attempting to use the given virtual pressure source.
This was copied from the Generic Sensor spec and not done in other places, so drop the tag for uniformity.
… types" This ensures that the types accepted in automation are the same which are returned by `PressureObserver.knownSources`. Whether this is really desired can be worked out later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If pressure source sample is now describing also "virtual pressure source" samples.
Would the definition of data require change?
The telemetry information provided by a pressure source is represented in this specification as a pressure source sample, a struct consisting of the following items:
data: contributing factors obtained from the underlying hardware or operating system.
or is test data being included in "operating system"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If pressure source sample is now describing also "virtual pressure source" samples.
Would the definition of data require change?
The telemetry information provided by a pressure source is represented in this specification as a pressure source sample, a struct consisting of the following items:
data: contributing factors obtained from the underlying hardware or operating system.
or is test data being included in "operating system"
Good point, I think allowing a PressureState there was too much of a stretch. I've made the definition clearer in commit d11d169 by saying data is a PressureState when the pressure source is a virtual one. |
Alright, everything's been taken care of! The last bigger change is 93beaa0, which aligns the pressure type checks in the WebDriver endpoints with the same list of types used by It does mean that one cannot add a virtual pressure source for a type that is not in |
There are a lot of changes in this PR as everyone can see. A lot of them are not in the newly-added Automation section, but in the rest where we had to provide less vague definitions for some concepts and make some of the algorithms less abstract. I will file a tracking bug for the WebDriver work and split this PR into multiple ones to make the changes easier to understand in the future. |
…pping Avoid adding a platform collector with an empty associated pressure source to the platform collector mapping. Having observe() attempt to find a suitable platform collector every time in this case is not that expensive, and _not_ doing it leads to a situation where inactive observers still need to call unobserve() or disconnect() to remove an entry from the platform collector mapping (to get observe() to try to connect to a platform collector again, for example).
One major change we forgot in this PR: |
Indeed, I wanted to mention that in the meeting yesterday and totally forgot! |
Related to #282: we need these algorithms to be properly defined in order to be able to support WebDriver and fake pressure states. This somewhat big change intends to clarify what "activate" and "deactivate" data delivery actually mean, as there used to be just a "data delivery" algorithm and no accompanying definitions for those two verbs. Furthermore, the data delivery algorithm itself was confusing: - It referenced a `data` variable in its declaration that was never passed by any callers. - `data` was of an implementation-defined type and format, but the steps assumed it had some associated information like source type that was not set anywhere. Fixing the above has required changes in different layers: - The "platform collector" concept, which used to be an abstract entity with which all globals interacted to retrieve telemetry data for all source types, is now a per-global and per-source type concept. The lower-level concept that represents a cross-global interface for the hardware or OS is now a "pressure source", which contains a snapshot of the latest reading it has retrieved along with a timestamp. - "Data delivery" is now called "data collection". It uses a platform collector and its associated pressure source to retrieve a telemetry sample that is transformed into a pressure state. - There are algorithms for activating and deactivating data collection. Both ensure they data collection cannot be started/stopped if they have already been. - `PressureObserver.observe()`'s had a "is not a valid source type" check that was too vague, as this step determined whether a given source type is supported by the platform or not, but the definition of "valid source type" was something else entirely. This step has been replaced by a sequence of steps that attempts to retrieve an existing platform collector for a source type and, if one does not exist, tries to connect to a corresponding pressure source. This change makes the same platform collector be used for all observers of a given source type and lays out in more detail what it means to check whether a source type is valid or not in this context. Co-authored with @kenchris in #265. It was split off as a separate pull request to make it easier to review and understand.
Usage so far had been inconsistent, with some places using the `!` syntax for normative references and others not doing so.
#283) Related to #282: we need these algorithms to be properly defined in order to be able to support WebDriver and fake pressure states. This somewhat big change intends to clarify what "activate" and "deactivate" data delivery actually mean, as there used to be just a "data delivery" algorithm and no accompanying definitions for those two verbs. Furthermore, the data delivery algorithm itself was confusing: - It referenced a `data` variable in its declaration that was never passed by any callers. - `data` was of an implementation-defined type and format, but the steps assumed it had some associated information like source type that was not set anywhere. Fixing the above has required changes in different layers: - The "platform collector" concept, which used to be an abstract entity with which all globals interacted to retrieve telemetry data for all source types, is now a per-global and per-source type concept. The lower-level concept that represents a cross-global interface for the hardware or OS is now a "pressure source", which contains a snapshot of the latest reading it has retrieved along with a timestamp. - "Data delivery" is now called "data collection". It uses a platform collector and its associated pressure source to retrieve a telemetry sample that is transformed into a pressure state. - There are algorithms for activating and deactivating data collection. Both ensure they data collection cannot be started/stopped if they have already been. - `PressureObserver.observe()`'s had a "is not a valid source type" check that was too vague, as this step determined whether a given source type is supported by the platform or not, but the definition of "valid source type" was something else entirely. This step has been replaced by a sequence of steps that attempts to retrieve an existing platform collector for a source type and, if one does not exist, tries to connect to a corresponding pressure source. This change makes the same platform collector be used for all observers of a given source type and lays out in more detail what it means to check whether a source type is valid or not in this context. Co-authored with @kenchris in #265. It was split off as a separate pull request to make it easier to review and understand.
Add WebDriver endpoints which allow manipulating virtual pressure sources, which are pressure sources whose behavior and samples are entirelly user-controlled. Also contrary to regular pressure sources, the provided samples (or, in spec parlance, a virtual pressure source's latest sample's data) are already PressureState instances rather than raw telemetry data that will be transformed into an adjusted pressure state. Caveats: - Shared workers are unsupported at the moment (i.e. the WebDriver endpoints only have an effect on Window and DedicaredWorkerGlobalScope globals). Storing virtual pressure source information in a top-level traversable does not play well with shared workers, for which the concept is somewhat irrelevant. We need to think of a different solution in the future if support for shared workers is important. - Once `PressureObserver.observe()` resolves, the same platform collector will be used until `disconnect()` or `unobserve()` are called. In other words, if a PressureObserver instance is active and using a real pressure source, adding a virtual pressure source of the same type will only have an effect on it and other instances in the same global once they all disconnect from the existing pressure source first. In terms of changes to the existing algorithms and concepts: - A top-level traversable has a mapping of source types to virtual pressure sources that is manipulated by the WebDriver endpoints. - When creating a new platform collector, `PressureObserver.observe()` first attempts to use a virtual pressure source when one exists and can be used. - The data collection algorithm distinguishes between the data format used by a virtual pressure source (which already is a PressureState) and by a real pressure source (which needs to be transformed into a PressureState). Co-authored with @kenchris in #265. It was split off as a separate pull request to make it easier to review and understand. Fixes #282.
Add WebDriver endpoints which allow manipulating virtual pressure sources, which are pressure sources whose behavior and samples are entirelly user-controlled. Also contrary to regular pressure sources, the provided samples (or, in spec parlance, a virtual pressure source's latest sample's data) are already PressureState instances rather than raw telemetry data that will be transformed into an adjusted pressure state. Caveats: - Shared workers are unsupported at the moment (i.e. the WebDriver endpoints only have an effect on Window and DedicaredWorkerGlobalScope globals). Storing virtual pressure source information in a top-level traversable does not play well with shared workers, for which the concept is somewhat irrelevant. We need to think of a different solution in the future if support for shared workers is important. - Once `PressureObserver.observe()` resolves, the same platform collector will be used until `disconnect()` or `unobserve()` are called. In other words, if a PressureObserver instance is active and using a real pressure source, adding a virtual pressure source of the same type will only have an effect on it and other instances in the same global once they all disconnect from the existing pressure source first. In terms of changes to the existing algorithms and concepts: - A top-level traversable has a mapping of source types to virtual pressure sources that is manipulated by the WebDriver endpoints. - When creating a new platform collector, `PressureObserver.observe()` first attempts to use a virtual pressure source when one exists and can be used. - The data collection algorithm distinguishes between the data format used by a virtual pressure source (which already is a PressureState) and by a real pressure source (which needs to be transformed into a PressureState). Co-authored with @kenchris in #265. It was split off as a separate pull request to make it easier to review and understand. Fixes #282.
Preview | Diff