fix(focus): keys typed right after a reopen wait until the restored page has loaded, then reach it in order (dogfood port of #32633)
Summary
Dogfood port of #32633 (P0 reopen-browser-plain-keys, cycle B; journey kit cp/reopen-video-kit@4ff1d5e5ce6). After Cmd-Q (keep) and reopen, plain keys typed at once into a restored web page were lost. Lawrence's rule: a key typed before the restored content is ready is held and delivered in order, never dropped.
Cause (as on feat, REOPEN VIDEO 7493, 7660, 7710, 7801): the window key hold awaited a restored Chromium tab only until its pane showed the content. The tab shows before Chromium creates its browser, and its first loads are an empty document and documents that the same load replaces. Keys sent on at any of those points were lost.
Fix, same rule as #32633:
- A shown Chromium tab is awaited until its page is ready for keys (
AwaitedContent.Pane.shownPageReady,BrowserTab.pageReady). It is ready when Chromium created its browser and stopped loading (.loadingState(loading: false)) with a real (not blank) document loaded, or with an error page. An aborted load is no page, and a new commit forgets the document loaded before it (Chrome'sDidStopLoading). CEFTab.onReadyForKeysreports it once per browser and writesready-for-keysto the lifecycle trace.TabContentCacheforwards it toonBrowserReady. On this lineonBrowserReadydid not end a page hold (only a focus settle did), so it now calls the newCreationInputCoordinator.pageArrived, which flushes the holds that await that tab, each key once, in order.- Bound and end for a page that never gets ready: the hold ends at
holdLimit(2 s) and its keys go on in order. This line lacked feat'sCreationHoldLog.pageExpired(#32030), so with the new readiness rule the next key would open a new 2 s hold for the same page. This PR ports it: a page whose hold ended at its bound is not held again until it is ready. - Paid back the 5 app lines (arch ratchet) by folding two one-line
ifblocks inTabContentCacheand theonBrowserReadyline.
Cost: none per key. One flag check when a hold decides what it awaits; one callback per browser.
Testing
Fleet, 5 runs each, proof-step.py (step ids follow in a comment when done):
- Red 0ec5dee1a9f (the same tests, behavior stubbed):
AwaitedContentTests(aShownBrowserTabIsAwaitedUntilItsPageIsReady,aTabExcludedAfterItsBoundIsHeldAgainOnceItsPageArrived),CEFTabHostFocusTests.aTabIsReadyForKeysOnlyOnceLoadingStoppedOnARealDocument. - Green b8acefff35d (this head): those suites 5x, plus
CreationInputHoldTests(withtwoReadySignalsWithKeysHeldBetweenThemDeliverEachKeyOnceInOrder, a guard that is green before and after),ColdBrowserFocusKeysTests,PageFirstKeysTests. - Journeys (REOPEN VIDEO, real keys on a mini, kit 4ff1d5e5ce6):
reopen-browser-plain-keys(both cycles) andbrowser-click-then-type, 3 rounds each on a dogfood proof build of this PR + #32579 (link hints) + #32654 (ChildPageFocus grant guard: the dogfood cycle A miss in STATUS 7801).
Observed / Not run
- Observed on feat: #32633 on proof build 3d14c646 passed both journeys 3/3 (STATUS 7828); held keys went on 3-11 ms after
ready-for-keysin every cycle B round. - Not run yet on this line: the 5x runs and the journeys; results follow in a comment.
Changelog
Fixed: Keys you type at once into a web page that a reopen restores reach the page, in order
Proof
No capture: key routing; the proof is the tests and the journeys.
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Fixes lost keystrokes after a reopen: keys typed right after Cmd-Q (keep) and reopen now wait until the restored Chromium page has actually loaded, then reach it in order.
After a reopen, a restored Chromium tab showed in its pane before Chromium created its browser, and its first loads were an empty document or documents the same load replaced, so keys sent immediately never reached the page.
- A shown Chromium tab is awaited until its page is ready for keys: Chromium created its browser and stopped loading with a real document or an error page loaded; an aborted load is no page, and a new commit forgets the previously loaded document.
- A page asked to show something waits for that document, so a reopen by address no longer sends keys to the empty document before its navigation; a page with nothing to load takes keys once Chromium creates it, and a blank target counts its blank document.
- Cmd-L passes an empty page hold once the page exists, so the address bar does not wait for the restored document.
CEFTab.onReadyForKeysreports once per browser, and the hold's keys are flushed once each, in order, when the page arrives.- A page that never gets ready ends the hold at its 2 s bound, and is not held again until its page arrives (ports
pageExpiredfrom #32030). - Tests cover the readiness rule, the bound, the blank-tab and fresh-page cases, and that no held key is delivered twice or out of order.