Skip to content

Cherry pick PR #10416: feat(lifecycle): implement race-free and spec-compliant application lifecycle transitions#10788

Open
jellefoks wants to merge 1 commit into
youtube:26.eapfrom
jellefoks:cherry-pick-10416
Open

Cherry pick PR #10416: feat(lifecycle): implement race-free and spec-compliant application lifecycle transitions#10788
jellefoks wants to merge 1 commit into
youtube:26.eapfrom
jellefoks:cherry-pick-10416

Conversation

@jellefoks
Copy link
Copy Markdown
Member

@jellefoks jellefoks commented Jun 5, 2026

Refer to the original PR: #10416

This also brings in cobalt/common/cobalt_thread_checker.h from #8905 but not the other changes from that PR.

This PR implements a natively resilient and completely race-free application lifecycle transition framework for Cobalt (specifically targeting Evergreen RDK and Starboard systems). By strictly serializing transitions between visible, hidden, focused, blurred, frozen, and resumed states, this framework guarantees deterministic synchronization between native OS events, browser-side window widget mapping, and Blink Renderer Mojo updates—completely eliminating all high-speed race conditions, compositor DCHECK aborts, and focus de-synchronizations.

This CL introduces the following key behavioral guarantees and functional correctness enhancements:

  1. Deterministic Visibility and Focus Ordering: On resume (reveal), the system guarantees that the native window widget is fully mapped and active before notifying the page's document visibility state. Consequently, the W3C visibility state is guaranteed to update to visible before the page gains active focus, eliminating any visibility-focus restore races.
  2. Spec-Compliant Lifecycle Resource Reclaim: On deactivation (conceal), the browser window widget is fully minimized and hidden, triggering native EGL/graphics surface release to reclaim 100% GPU memory. On activation (reveal), the window widget is restored and shown, synchronously re-negotiating EGL surface bounds and allowing the platform window to fully map prior to layout rendering.
  3. Synchronous Transition Serialization (Focus-Loss Wait Gate): During application deactivation (blur), the main browser thread blocks synchronously until the renderer process has fully dispatched the Javascript blur event loop and Mojo ACKed it back. This guarantees that focus-loss completes atomically before the page document visibility state is concealed, enforcing absolute transition linearity.
  4. Dormant Focus Deferral Coordination: Any physical OS focus events arriving concurrently while the browser is waiting for Blink's layout Reveal ACK are safely deferred browser-side. Once layout is complete and Mojo ACKed, the deferred focus is automatically restored, ensuring focus never races layout visibility.
  5. Clean Browser Teardown: During process teardown, the UI thread synchronously pumps the message loop to drain and delete all remaining frame nodes. This guarantees that the context graph is completely empty prior to Performance Manager shutdown, preventing context reset crashes.

Verification Results

  • Compiled cleanly across all 5 configurations (unittests, Modular devel/qa, and RDK TV devel/qa).
  • Passed 100% of C++ Lifecycle unittests (147/147 passed flakelessly).
  • Passed 100% of local Modular sequential sweeps (25/25 devel loops).
  • Passed RDK TV HDMI CEC disconnect test flakelessly purely over remote keypresses.

Bug: 477170017
Bug: 498107481
Bug: 505584259
Bug: 489821073
Bug: 491962441
Bug: 475990372
Bug: 494002968

This fixes missing visibilityChange events on resume caused by early
focus signaling.

How it works:
The fix blocks focus at the narrowest point in the browser process, in
`WebContentsImpl::Focus()`, while waiting for the reveal acknowledgment
from the web application. It also ignores OS-initiated focus events in
`PlatformWindowStarboard::ProcessFocusEvent` and defers all
focus-triggering actions until `OnPageVisibilityVisible`.

This commit fixes the missing `visibilitychange` event in the YTS test
by deferring the focus event until AFTER the web application has
acknowledged that it received the visibility change signal. Previously,
the focus event was delivered too early, causing race conditions. By
ignoring early focus events and only triggering focus after the web app
calls `PageVisibilityVisible` via Mojo, we ensure the strict sequence:
[Unfreeze -> Reveal -> Focus], which satisfies the YTS test
requirements.

Detailed changes:

1. Blink Side (Detecting Visibility and Sending Signal)
-
third_party/blink/renderer/modules/cobalt/h5vcc_runtime/h_5_vcc_runtime.h
& .cc: Inherits from PageVisibilityObserver to listen for visibility
changes in Blink. Implements PageVisibilityChanged() to send a Mojo
message (PageVisibilityVisible) to the browser process when the page
becomes visible on resume.

2. Mojo Interface
- cobalt/browser/h5vcc_runtime/public/mojom/h5vcc_runtime.mojom: Adds
the PageVisibilityVisible() method to the H5vccRuntime interface to
bridge the signal from Blink to the browser.

3. Browser Side (Receiving Signal and State Management)
- cobalt/browser/h5vcc_runtime/h5vcc_runtime_impl.h & .cc: Receives the
PageVisibilityVisible Mojo call from Blink. Calls
OnPageVisibilityVisible on ShellPlatformDelegate.
- cobalt/shell/browser/shell_platform_delegate.h & .cc: Maintains the
waiting_for_reveal_ack_ state. In OnReveal(), sets this flag to true and
informs Starboard. In OnPageVisibilityVisible(), clears the flag and
triggers all the deferred actions (showing windows and applying focus).

4. Browser Side (Deferring Actions and Ignoring Early Focus)
- cobalt/shell/browser/shell_platform_data_aura.cc: Constructor defers
calling host_->window()->Show() if waiting_for_reveal_ack() is true.
- cobalt/shell/browser/shell_platform_delegate_aura.cc: SetContents()
defers showing the content window if waiting for reveal ACK.
RevealShell() calls Show with kInactive to prevent automatic focus
stealing on resume.
- content/browser/web_contents/web_contents_impl.cc: Ignores calls to
Focus() if waiting_for_reveal_ack() is true, preventing early
programmatic focus.
- ui/ozone/platform/starboard/platform_window_starboard.h & .cc:
Maintains a static waiting_for_reveal_ack_ flag accessible by both
Cobalt and Ozone. ProcessFocusEvent() and Activate() return early if
this flag is true, ignoring OS-level focus events during resume.
- cobalt/shell/browser/shell.h & .cc: Modifies Focus() and
ActivateContents() to respect waiting_for_reveal_ack(). Adds
ShouldFocusPageAfterCrash to also respect this flag.

Bug: 477170017
@jellefoks
Copy link
Copy Markdown
Member Author

The lifecycle PR (#10416) merged, and the cherry-pick to 26.eap is ready, and CI is running on it.

#10788 and manually verified working and the same as main, except for:

@jellefoks jellefoks marked this pull request as ready for review June 5, 2026 22:49
@jellefoks jellefoks requested review from a team as code owners June 5, 2026 22:49
@jellefoks jellefoks requested a review from andrewsavage1 June 5, 2026 22:49
gemini-code-assist[bot]

This comment was marked as off-topic.

@jellefoks jellefoks enabled auto-merge (squash) June 8, 2026 04:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant