Closed Bug 1826645 Opened 1 year ago Closed 1 year ago

Tests of DOM fullscreen are vulnerable to timeouts

Categories

(Core :: DOM: Core & HTML, defect, P2)

defect

Tracking

()

RESOLVED FIXED
Tracking Status
firefox114 --- fixed

People

(Reporter: bradwerth, Assigned: bradwerth)

References

(Blocks 3 open bugs)

Details

Attachments

(3 files, 1 obsolete file)

The DOM fullscreen code is not adequate to handle the rapid requests of enter -> exit -> enter fullscreen done by our testing harness. For platforms with asynchronous fullscreen transitions, our fullscreen tests will intermittently timeout. These tests serve the important purpose of ensuring that users experience correct fullscreen behavior, so we want to keep them enabled. Unfortunately, the code is fundamentally unable to do this, as demonstrated by a test that will be added in this Bug.

The root of the problem is that a fullscreen transition has several points of notification, but all the content-visible ones are fired before an asynchronous transition is complete. Our non-Chrome tests typically use these notifications unchecked to proceed to the next part ot the test, which might trigger another fullscreen transition. Events occur in this order (as an implementation detail, not by spec):

  1. Resolve or reject the Promise and update internal state (immediately on the content process, possibly one event loop later on the parent process).
  2. Trigger the transition in a platform-specific fashion.
  3. Schedule the fullscreenchange or fullscreenerror event on the next event loop.
    -- transition completes --
  4. (Chrome only) send the sizemodechange event.
  5. Update window occlusion state.

On platforms with synchronous fullscreen transitions, these 5 things all happen in the same event loop, which allows our tests to rapid cycle requests and be successful. However on platforms with async fullscreen transitions, the following unexpected outcomes can occur with the pattern of enter -> exit -> enter:

  • Upon exit, the content process may send the fullscreenchange event before the parent has processed the exit, then the content process requests a new enter which the parent processes immediately. It determines in FullscreenElementReadyCheck that the requesting element is already in fullscreen and resolves the Promise without ever sending the fullscreenchange event. Tests listening for the event will timeout. This type of failure may be possible even with a sync transition, since the content and the parent processes get out of agreement while the content process has already scheduled its fullscreenchange event.
  • Before the window occlusion state is updated, a new fullscreen request will have its Promise rejected because the browsing context is not active. Tests awaiting enterFullscreen and not checking for rejects will be in an unexpected state and probably fail.
  • When the asynchronous exit transition completes, it will again update internal state which could arrive during the processing of the next fullscreen request (which is also async). This introduces complicated overwriting of the internal state that is hard to diagnose and appears to either squash events or reject the Promise.

Even though these problems are probably never encountered by users, they impact the tests that check user-facing behavior. Possible fixes:

  • Work through all these complicated timings and make the Document and AppWindow logic handle them. This is very hard.
  • Add a new event fired at end of transition (similar to sizemodechange) that is checked by our tests, update all the tests. This has the disadvantage that it would be nice if the tests would "just work" and continue to use web-exposed APIs only.
  • Make our test harness spoof the methods used to enter and exit fullscreen and add a delay representing user reaction time. Many entry points, possibly tricky, not guaranteed to work but more representative of user experience.
  • Change the timing of the notifications. For example, Promises could be made to resolve at the end of fullscreen transitions. This doesn't appear to violate the spec and would allow any tests that wait on Promises to be left unchanged. Tests that wait for events would still be vulnerable.

None of these options seem great, and I welcome other approaches. I'll leave the Bug open while landing a test which demonstrates some of these points of failure.

This test is marked expected fail on platforms with asynchronous
fullscreen transitions.

Keywords: leave-open
See Also: → 1776738

The unlanded patch in Bug 1603334 is very useful for debugging Promise rejections.

See Also: → 1603334
Assignee: nobody → bwerth
Status: NEW → ASSIGNED

Removing this check from content processes helps alleviate a race
condition on fullscreen exit followed by enter. This gives time for the
content process to process the exit without silently resolving the enter
without firing the event.

This change relaxes the check slightly. Spec requires that the tab is
focused. Our existing check for "active" is additionally requiring the tab
to be non-occluded. Since occlusion updates are asynchronous when the
transition itself is asynchronous, this change allows rapid requests to be
permitted as long as the underlying window and tab state is as expected.

Depends on D174982

Attachment #9327210 - Attachment description: Bug 1826645: Add a test of fullscreen rapid-cycle enters and exits. → Bug 1826645 Part 3: Add a test of fullscreen rapid-cycle enters and exits.

This change makes the parent process delay a fullscreen request if there
is a pending fullscreen exit. It also changes the DOMFullscreenParent
actor listener lifecycle. Once it has started handling a fullscreen
request, it will remain a listener to the Document until it has received
an enter event and an exit event in either order.

Attachment #9327210 - Attachment description: Bug 1826645 Part 3: Add a test of fullscreen rapid-cycle enters and exits. → Bug 1826645 Part 4: Add a test of fullscreen rapid-cycle enters and exits.

(In reply to Brad Werth [:bradwerth] from comment #0)

I am not too worried about this, as the promise is eventually rejected. Fullscreen requests can fail for multiple reasons, so the test should check the result of the promise as well. Can the test wait for the docshell to be active first, something like https://searchfox.org/mozilla-central/rev/ad732108b073742d7324f998c085f459674a6846/browser/components/customizableui/test/browser_panelUINotifications_fullscreen_noAutoHideToolbar.js#19-26 instead?

  • When the asynchronous exit transition completes, it will again update internal state which could arrive during the processing of the next fullscreen request (which is also async). This introduces complicated overwriting of the internal state that is hard to diagnose and appears to either squash events or reject the Promise.

I think we could try to remove this, as nsGlobalWindowOuter::FinishFullscreenChange also ensures that the fullscreen state is synchronized, but only when there is no ongoing request.

  • Work through all these complicated timings and make the Document and AppWindow logic handle them. This is very hard.

One of the major challenges is that there is no good way to track individual fullscreen IPC requests and handle multiple IPC requests arriving in a row. Document has a mechanism to handle multiple requests. While AppWindow doesn't do that directly, nsGlobalWindowOuter does.

(In reply to Edgar Chen [:edgar] from comment #7)

I am not too worried about this, as the promise is eventually rejected. Fullscreen requests can fail for multiple reasons, so the test should check the result of the promise as well.

But many tests don't check the promises, and only check for the fullscreenchange events. Some of these tests are WPT tests which we couldn't justify changing just to make them work in Firefox.

Blocks: 1776738
Blocks: 1802193
Severity: -- → S3
Type: enhancement → defect
Priority: -- → P2
Attachment #9327603 - Attachment is obsolete: true
Attachment #9327604 - Attachment description: Bug 1826645 Part 2: Make FullscreenElementReadyCheck check for focused tabs, not active tabs. → Bug 1826645 Part 1: Make FullscreenElementReadyCheck check for focused tabs, not active tabs.
Attachment #9328049 - Attachment description: Bug 1826645 Part 3: Make Document hold fullscreen requests while an exit is being processed. → Bug 1826645 Part 2: Make Document hold fullscreen requests while an exit is being processed.
Attachment #9327210 - Attachment description: Bug 1826645 Part 4: Add a test of fullscreen rapid-cycle enters and exits. → Bug 1826645 Part 3: Add a test of fullscreen rapid-cycle enters and exits.
Pushed by bwerth@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/eb4ea58aaa6d
Part 1: Make FullscreenElementReadyCheck check for focused tabs, not active tabs. r=edgar
https://hg.mozilla.org/integration/autoland/rev/8f8c8f79661a
Part 2: Make Document hold fullscreen requests while an exit is being processed. r=edgar
https://hg.mozilla.org/integration/autoland/rev/aadec7cf67f8
Part 3: Add a test of fullscreen rapid-cycle enters and exits. r=edgar
Regressions: 1828910

Looks like the patches make this test_fullscreen-api.html permafail in the Linux 18.04 x64 WebRender debug-mochitest-plain-headless-spi-nw test configuration. Those are Tier 2 but there's no reason for us to fail there. I'll do some try runs and figure out what that configuration needs changed.

(In reply to Brad Werth [:bradwerth] from comment #11)

Looks like the patches make this test_fullscreen-api.html permafail in the Linux 18.04 x64 WebRender debug-mochitest-plain-headless-spi-nw test configuration. Those are Tier 2 but there's no reason for us to fail there. I'll do some try runs and figure out what that configuration needs changed.

Probably these patches will stay landed and I'll do the fix in Bug 1828910.

Blocks: 1563947

Bug 1828910 was fixed, this can be resolved.

Status: ASSIGNED → RESOLVED
Closed: 1 year ago
Keywords: leave-open
Resolution: --- → FIXED
Blocks: 1776996
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: