Decide whether to resize synchronously in requestFullscreen()#64
Decide whether to resize synchronously in requestFullscreen()#64foolip wants to merge 2 commits into
Conversation
|
|
||
| <li><p>If <var>error</var> is true, <a>fire an event</a> named <code>fullscreenerror</code> on | ||
| <var>pending</var>'s <a>node document</a>, reject <var>promise</var> with a | ||
| <code>TypeError</code> exception, and terminate these steps. |
There was a problem hiding this comment.
This actually reminds me another issue with the old spec text: if the fullscreen request triggers resizing, but fails here, the viewport would keep fullscreen, while the content would not be in fullscreen state, which seems to be unfortunate.
Rather than simply "terminate these steps", it should probably also say "If resize is true, resize topLevelDoc’s viewport to its 'normal' dimensions" before.
(This actually caused a vulnerability in Gecko which was fixed recently. And I didn't realize this is a spec issue.)
That would still be tricky, though. If one triggers two fullscreen requests continuously, and the latter one fails the check here, then boom. But I guess it is better than leaving window in fullscreen while content is not.
There was a problem hiding this comment.
Yes, both in the case where the element was removed after the request and if it was moved to another window as in #33, we might have gone fullscreen but there's nothing to make the fullscreen element. Calling "fully exit fullscreen" would do nothing, so I think your suggestion is the best here. I'll try an edit.
| <var>pending</var> returns false, <a>fire an event</a> named <code>fullscreenerror</code> on | ||
|
|
||
| <li> | ||
| <p>If any of the following conditions are false, then set <var>error</var> to true: |
There was a problem hiding this comment.
I might be wrong, but I think "any" should use "is" rather than "are" here?
There was a problem hiding this comment.
I don't think so, because conditions is plural. "If any following condition is false" would be grammatically correct, but less clear.
|
@annevk, could you also review? |
|
|
||
| <li><p>Reject <var>promise</var> with a <code>TypeError</code> exception. | ||
|
|
||
| <li><p>Terminate these steps and run the remaining subsubsteps <a>in parallel</a>. |
There was a problem hiding this comment.
Maybe just "If resize is true, in parallel, resize ..."?
There was a problem hiding this comment.
Oh, the parallel step is not quite right...
There was a problem hiding this comment.
The trick is how to both stop the steps in the animation frame task and to capture the fact that the resize doesn't happen synchronously within the animation frame task. But let's figure out the right behavior first.
|
|
||
| <li><p>Terminate these steps and run the remaining subsubsteps <a>in parallel</a>. | ||
|
|
||
| <li><p>If <var>resize</var> is true, resize <var>topLevelDoc</var>'s viewport to its "normal" |
There was a problem hiding this comment.
This is still not quite right. There could be a fullscreen element, in which case one would also have to fiddle with the top layer. Ideas on the minimal amount of fiddling required to end up in a good state appreciated.
There was a problem hiding this comment.
Can there still be a fullscreen element because this happens in parallel? I'm not quite sure I still follow.
There was a problem hiding this comment.
It would be a case like this:
button.addEventListener('click', () => {
a.requestFullscreen();
b.requestFullscreen()
b.remove();
});Both requests will try to resize, and per spec it's a racy situation, but let's assume that after the resize the animation frame task for a runs first and a becomes the fullscreen element. Then b will end up in this situation, exiting fullscreen, but a will still be the fullscreen element.
| <li><p>Let <var>topLevelDoc</var> be <var>pendingDoc</var>'s <a>top-level browsing context</a>'s | ||
| <a>active document</a>. <!-- cross-process --> | ||
|
|
||
| <li><p>Let <var>resize</var> be true if <var>error</var> is false and <var>topLevelDoc</var>'s |
| <a>top-level browsing context</a>'s <a>active document</a>'s viewport's dimensions to match the | ||
| dimensions of the screen of the output device. Optionally display a message how the end user can | ||
| revert this. | ||
| <li><p>If <var>resize</var> is true, resize <var>topLevelDoc</var>'s viewport to match the |
| <li><p>Let <var>pendingDoc</var> be <var>pending</var>'s <a>node document</a>. | ||
|
|
||
| <li><p>Let <var>topLevelDoc</var> be <var>pendingDoc</var>'s <a>top-level browsing context</a>'s | ||
| <a>active document</a>. <!-- cross-process --> |
|
Given #64 (comment) and that In order to make it well defined what happens with racing resizes and which order all the promises are resolved, I think we'll need to have some state on the top-level browsing context, or some kind of queue of requests. For at least exits, I think that all requests will also have be handled in a single animation frame task following the resize, otherwise some promises can't be resolved in the same tasks where the corresponding events are fired. What do you think, can it be simpler and still completely well defined? |
|
Gecko has a global queue for pending fullscreen requests when the fullscreen state cannot be applied immediately. (It is especially important for us because we have a transition animation.) And our algorithm is roughly:
Having written this down, I wonder whether this is the only reason we reject when element is moved to a different document. If so, I guess we probably don't really need that restriction. We should probably be recording the top level document instead, otherwise it would still be an issue that the requesting document can be moved to a different top level document. |
|
Thanks, @upsuper, that's very helpful. Is this queue in the same process/thread as the rendering engine, i.e. can you inspect its state synchronously in Are you currently synchronizing "apply the fullscreen request" with animation frames, or does it happen whenever the resize is reported to be done?
Yes, keeping track only of topLevelDoc would for for #33. Using pendingDoc amounts to a pretty harmless restriction though, so I wouldn't mind aligning with that if it'd be simpler for you.
I don't think it's possible to move documents, here's a test that shows that moving an iframe causes its document to change: https://software.hixie.ch/utilities/js/live-dom-viewer/saved/4693 In addition to all of the above, can you elaborate on how exiting works? Do exits also end up in the same queue, and how are competing requests and exists handled? I would like the spec to match Gecko in #63, so if you have a good model we can just copy it exactly :) |
Yes, yes.
Not really. In Gecko, in case I think the difference between this behavior and doing everything in the next animation frame is probably observable, but should be hard to detect in practice, so it may not worth fixing in either spec side or Gecko's impl. FWIW, I guess we would fix this gap in Gecko when we implement
Given these, I would be happy that the spec just uses the pending document :)
No, exits just go immediately, and they are even synchronous if Oh, and in I don't think we have any explicit handling of competing requests and exits. I think the two phases resize ("set |
7111f92 to
4a14d1f
Compare
4a14d1f to
7ab6a5d
Compare
|
I've rebased this now as it came up in #88, and split it into two commits. This is taking the third option from #63 (comment) but I haven't fully convinced myself this is the best path, since it makes the cross-process considerations harder. I'm still working on #86 and there are tricky things about "exit fullscreen" to sort out there, so I'm going to finish that before coming back to this. |
|
Closing this. #63 still needs fixing, but probably not like this. Not allowing competing requests would be a simpler model. |
Fixes #63. It does not fix #33, although to fix it would now involve
saying "If both error and resize are true, then ..." in the animation
frame task.
Preview | Diff