-
Notifications
You must be signed in to change notification settings - Fork 7
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
readonly attribute Promise<AutoplayPolicy> autoplayPolicy; #6
Comments
The ServiceWorkerContainer.ready is different in that it resolves to a ServiceWorkerRegistration object, and there is only one instance of this object per ServiceWorkerContainer. The fields of the ServiceWorkerRegistration instance can change, but the instance of that object associated with the ServiceWorkerContainer doesn't change. Whereas the values returned by Document.autoplayPolicy can change over time. So once the promise has settled on a particular allowed/not-allowed result, what happens when that changes and the document becomes allowed to play? Clear Document.autoplayPolicy and assign to it a new promise resolved to the new value? That might have surprising results, for example if the only reference to some other object was held by closures in that promise chain, that thing would be GC'd. If this must be async, it makes more sense for this to be:
Then it's more obvious that the calling script is the only thing keeping the promise/chain alive. |
The next obvious question is why does this need to be async? :) The description in issue 1 is:
The fact this says "returns" to me implies it was intended to be synchronous. Being synchronous makes sense, as this is basically just looking up a bit set on the relevant document object. |
From a browser perspective there may be a lot of state across many different components that goes into determining whether a page can play or not. It would be nice to not have to keep all this state in sync in the renderer when we do not necessarily need to. i.e. when a user calls If we are using a promise we probably should forward any user gesture state so things like this would work:
|
Sure, but that argument can be made for almost any API, especially all those on HTMLMediaElement. I don't think it's unreasonable that a browser engine should be able to answer "what's the current time" synchronously, though that could require cross-component calls to answer accurately. Same for "buffered", "seekable", etc. So what is it that makes "autoplayPolicy" different? Promises make features that are inherently asynchronous nicer; IMHO, I don't think they should be used to make inherently synchronous features "future proof" for browser implementers. |
Making the feature synchronous requires a lot of added complexity that we have to deal with because of some ways people currently detect autoplay ( Worth nothing that
And whether this should be an attribute or a function, it doesn't really matter much to me. |
It's the UA's job to manage complexity. "It's complex" is not a good enough reason to require web developers to absorb that complexity. |
I agree with this when it's just "hard to do" but here the complexity is architectural and I guess it's more of a cost/limitations. Synchronous APIs should be easily available synchronously. This is definitely not the case for autoplay and there are a lot of cases where answering this question should take more than a quick query. I'm actually very surprised Mozilla would support the API being synchronous as they are considering backing this with some permissions and the Permissions API is fully designed asynchronously. I would expect the permissions to be accessed at the browser process level which means that the renderer process would either need to be aware of the permission at its creation and for each navigation or the API would do a synchronous call to the browser process. |
So, it's inherently synchronous because it's known before the page is ever loaded. Promises should be used for inherently /asynchronous/ APIs, and not merely where they're convenient for a specific UAs process model. |
The TAG recommendations seem to be aligned with my approach here: https://w3ctag.github.io/design-principles/#promises In particular, I think the points around disk access and different process apply here. Today, we have to load everything from disk on startup and we would rather have this done lazily which we can only do with an async API. Same for the process: we have to pass the information to the child process at creation because the API is synchronous and could be avoided with an async API. |
No, there's nothing about this API that's inherently asynchronous. Your implementation may be designed in such a way that makes the implementation asynchronous, but that is not inherent to the API. That exact same argument could be made about any API. Making this API a Promise pushes your own internal design decisions upon your clients, and that's bad API design. |
My understanding from the TAG's recommendations are exactly that API should be asynchronous unless we are fairly certain that:
My understanding is that today Safari, Chrome and Firefox are doing cross process operations with disk access to answer the question the API is asking. Our design allows us to resolve this synchronously but I don't think we should put this constraints to every browser that will have to implement this API. |
Your understanding is incorrect w.r.t. Safari. The TAG recommendations should apply if the API requires disk access, not if there is any possible implementation which may want to lazily read from disk. And that's ignoring the weirdness of having a Promise backed property change state dynamically after it has resolved. |
Additionally, the "implementations may need to consider information that might be stored on disk in order to compute the result" recommendation doesn't apply here. There is no input to this API which a browser would need to read data from disk to compute. All the inputs to this property are known before the page is even loaded. |
Checking the document's URL against a list of allowed website (MEI for Chrome, permission for Firefox) is a disk access even if there is no input, right? |
Sure, everything is on disk at some point. And if you take this argument to it's maximal conclusions, there is no API that should not be made a Promise because there exists some potential UA that may want to lazily load things from disk. |
The TAG recommendations also cover cross thread and cross process implementations which would also be the case here since checking the list will likely require a process hop. |
Again, that is an implementation choice, and not intrinsic to the API. The Promise requirements should be reserved for things that require a process hop, like communication between Workers, and not for implementation optimization decisions. |
Yes, although the recommendations specify that if an implementation may want to go down that route then the API should be async. The section in particular is talking about implementations, rather than whether a cross-thread/process hop is part of the spec. |
And as I said earlier, the logical conclusion of that argument is that every new API has to be a Promise. Therefore, that interpretation must be wrong, as it would make the recommendation meaningless. If instead of looking at the Promise guidelines, you look at the actual Writing Promise-Using Specifications document, you see this recommendation under "3. When Not To Use Promises":
Because the value of this property will logically change over time, a Promise is the wrong thing to use. |
I am not sure that the "recurring events" section would apply here because we are exposing state rather than an event. Maybe if it was something like an It's also not a series of events, it is a single async operation and also the recommendation here is to use EventTarget which we are not using. |
Yes, that's another problem with the proposal: there is no way to know when the property changed, as there is no event defined that fires when the value resolved by the Promise is no longer valid. |
To expand on this last point: the only reason for the property to be a Promise is due to a browser-specific optimization, and not because it is inherently asynchronous, and because the property will change over time, it should have an associated event to notify clients that the property changed, but because it is a recurring event and not a one-shot, that would require the property to not be a Promise in the first place. |
I believe the "2.3. More General State Transitions" applies here and this goes back to the original suggestion of having an attribute that returns a Promise:
This is already used in other places like the "Font Face" interface which uses a From an autoplay perspective here we could check the state asynchronously when the getter is called on the attribute and then resolve the promise. |
That would require a new Promise to be returned from the object for every time the property is accessed, breaking the EDIT: I misread the source document, you absolutely can move to the unloaded state. Mea culpa. |
Updated my previous comment. I still don't believe this is an appropriate example, because in the case of Image unloading, that property change is due to an explicit action on the image element by the client, and this property could happen at any time (so the client has no option other than to poll to detect a state transition.) |
Also, note the caveat in that section:
Neither of those applies here. |
Hi, I'm a software architect working at an online video player company. We've been dealing with autoplay policies in our web player, so I've been following these discussions a bit on the sidelines. 🙂 I also believe a promise property isn't the right approach here. For example, I don't see how this could handle changes in the autoplay policy. The page could start out with an
let currentPolicy;
function updatePolicy(policy) {
// Do something with the new autoplay policy...
currentPolicy = policy;
// Attach a handler to the new promise, in case the policy changes later
document.autoplayPolicy.then(updatePolicy);
}
// Wait for the first change
// But what if it never changes, or it already changed but we "missed" it?
document.autoplayPolicy.then(updatePolicy); I agree with @jernoble that a string property let currentPolicy = document.autoplayPolicy;
document.addEventListener('autoplaypolicychange', () => {
currentPolicy = document.autoplayPolicy;
// Do something with the new autoplay policy...
}); If the user agent does not yet know the correct autoplay policy on document load, it could initialize the property to some sane default (e.g. |
@MattiasBuelens - Setting to I'm not sure we should be taking away autoplay from a document once it has been granted e.g. disabling autoplay on a site won't have an effect if the site is already autoplaying. In which case we would always be progressing towards an allowed state. |
Based on experimental results, Mozilla has decided to not prompt the user for permission to allow autoplay. So we don't need to worry about this here, and elsewhere, on Firefox's behalf. We will still have per-origin permissions, but they'll be managed via some other UX mechanism.
Firefox does not do synchronous disk access, or have to call across processes, in order to lookup a permission for an origin. Permissions are cached in memory. When a content process loads or navigates a document, or when permissions change, that process is sent the permissions relevant to it.
I'd assume you'd cache the MEI whitelist in memory in your main process for speed purposes, and based on what you said above it sounds like whether a document has passed the MEI threshold is already passed onto the content process when a load starts. So you should be able to implement this API synchronously. |
I don't think we want an autoplaypolicychange event. For UAs that are blocking autoplay, this would just encourage sites to start autoplaying once the user has interacted with the site, even if they're not interacting with a video. For example, assuming Firefox/Chrome's document activation model, user opens site, UA blocks autoplay video, user clicks an "I accept your cookie policy" button, and then the site starts to autoplay. Also, sites can assume in most UAs that once the user has clicked or pressed a key (and played something in said event handler in the case of Safari) that they're probably allowed to play, so adding this also seems mostly redundant. Granted, it's not entirely redundant due to differences in UA blocking policies, but it does seem like something that's user hostile. |
At the moment the MEI preseed and an individual users scores are in memory and we send this to all the renderer processes on navigation. However, the MEI data is growing quite a bit and we would like to potentially move this out of memory and only do the check when we actually need to.
I agree that we should avoid having an event. It would just encourage sites to autoplay when they can rather than when they should. |
This is an old issue, which was already solved by the TAG resolution (the conclusion is to make API sync). So close this issue. |
@mounirlamouri said #1 (comment)
@jernoble said #1 (comment)
@mounirlamouri said
The text was updated successfully, but these errors were encountered: