The complete automated matrix ran end-to-end on a Pixel 6a, including the new landscape viewport-fit transition cases (cover → auto → contain → cover → auto) and the on-device keyboard accessory instrumentation test. Both artifacts found during this work are now root-caused and fixed: the cold-launch toolbar hairline remnant and the system bar icons staying white over a white page. All fixes are uploaded under Gerrit topic hja-pwa-fixups.
| Case | Patched | Stock control |
|---|---|---|
| Fullscreen PWA cold launch | PASS 832/832, safe top 29 | 803/832, safe top 0 |
| Standalone PWA cold launch | PASS top edge-to-edge, opaque 48px nav fallback | 755/832, safe top 0 |
| Pull-to-refresh | PASS metrics stable | control remains fitted |
| Off-origin CCT toolbar | PASS toolbar begins below status bar | same |
| Standalone parent recovery | PASS 784/832 remains stable | 755/832 remains fitted |
| Fullscreen parent recovery | PASS remains 832/832, safe top 29 | 803 before and after |
| Fullscreen backswipe | PASS viewport remains 832 | starts fitted at 803 |
| requestFullscreen baseline | PASS 832/832 | 832/832 |
| Three-button navigation rendering | PASS page content renders behind the buttons | content renders behind buttons |
| Dynamic status icon contrast | FIXED status icons and navigation buttons follow the page theme | stock 141 toggles |
| Landscape viewport-fit transitions | PASS cover/auto/contain geometry and repeat-cycle equality | n/a (feature off) |
| Cold-launch toolbar hairline remnant | FIXED capture parked fully offscreen | hidden by fitted status bar |
| IME CSS safe-area transition | PASS 15px closed, 0px open | not edge-to-edge, 0px throughout |
| Keyboard accessory integration | PASS physical IME geometry + injected Chrome accessory | production accessory captured |
All patched-side screenshots below are from the latest all-fixes Pixel 6a run. Metric numbers quoted in the case texts (832/832, safe top 29) are from the original SM-A546B run and correspond to that device's dimensions; the Pixel 6a equivalents are 914/915 with safe top 51. Stock-control screenshots remain from the Samsung control run. The only intentionally old capture is the fullscreen-recovery "before" failure evidence.
Patched Chromium occupies the complete 832 CSS px screen and exposes the 29px top safe area. Stock Chrome reproduces the original fitted top and reports no safe area.


The patched page draws behind the status bar and receives a 29px safe area. Its 48px height difference is solely the opaque three-button navigation fallback. Stock excludes both status and navigation bars.


The sampler initially called the patched result a failure because its heuristic assumed a navigation bar no taller than the status safe area. The live sampler now allows a 64 CSS px opaque three-button navigation fallback while still requiring a non-zero top safe area.
Gesture navigation was enabled temporarily and restored afterward. Patched Chromium retained innerHeight=832, visualViewport=832, and safe-area-inset-top=29px. No resize event was added by the swipe.


The regular document API remains unchanged and fills the complete screen in both builds.


The failure came from mutating the window's copied layout attributes without applying them. The child transition reset the registered cutout mode to default. Calling Window.setAttributes() makes shortEdges reach WindowManager again when immersive mode returns.


The toolbar starts at physical y=80, below the status bar, and closing it returns to the same 784/832 standalone viewport with top safe area 29px.


The Fit Switch PWA cycles cover → auto → contain → cover → auto under a landscape rotation lock. cover must span the full landscape width with a non-zero CSS side safe-area inset; auto and contain must use a narrower fitted viewport with zero CSS side inset. The second cover and auto captures must exactly match the first, which catches stale padding or inset ownership after dynamic transitions. Every state also records JSON metrics and the WindowManager state.


Every cold launch of an edge-to-edge web app showed a 1 dp strip of the dynamic theme surface color at the very top of the screen. Root cause: the toolbar capture is toolbar + hairline tall (150 px here), but fully hidden browser controls rest exactly at the zero min-height boundary with browser-applied offsets, so the scroll-time boundary guard from the earlier hairline series skipped the adjustment and parked the layer at -147 px instead of -150 px, leaving the capture's hairline row visible. The fix also applies the adjustment when the controls are entirely off screen. Verified red/green in TopToolbarCoordinatorUnitTest (wanted setYOffset(-150), previously -147) and on hardware; 106 related stacker/control-container tests pass unchanged.




Commit: Hide toolbar hairline capture for fully hidden browser controls (Bug: 512898018). The artifact reproduced with the WebAppShortEdgesCutoutMode feature disabled, on a clean origin/main build, and persisted across scrolling; one off-origin CCT round-trip cleared it, which is why it needed a cold launch to reproduce.
Two stacked causes. First, homescreen webapp shortcuts run as ActivityType.WEBAPP and were excluded from bright and night-mode page theming, so a page switching theme-color to white never reached the status bar computation and APPEARANCE_LIGHT_STATUS_BARS never toggled. Second, edge-to-edge navigation buttons render over page content with a transparent bar but ignored the page theme entirely, leaving white Back/Home/Recents buttons invisible over a white page. The fix allows webapp theming like WebAPKs and derives the navigation button appearance from the theme color, updating on theme and edge-to-edge changes. Verified red/green in BaseCustomTabRootUiCoordinatorUnitTest and CustomTabNavigationBarControllerTest; on hardware the white page now reports LIGHT_STATUS_BARS LIGHT_NAVIGATION_BARS and the black page clears both. Uploaded as CL 8227486.




Under temporary gesture navigation, the standalone page reports bottom safe area 15px with the keyboard closed and 0px after the IME opens. The visual viewport changes from 832px to 488.5px while innerHeight remains 832px on this Samsung keyboard implementation.


Public Chromium cannot create a production saved-password entry on this device. The complete automated check combines the physical fullscreen PWA run, which verifies resizing-IME geometry and no empty gap, with AutofillKeyboardAccessoryIntegrationTest#testTapInputFieldShowsKeyboardAccessory, which injects a suggestion and exercises the real Chrome accessory UI. Both parts passed on the same device.
The installed WebKit Repro PWA exposes the stale safe-area-inset-bottom bug directly. With the all-fixes APK plus CL 8207801, focusing its bottom input resizes innerHeight from 914px to 572px and updates bottom padding from 56px to 8px; the input ends at 563.8px inside the 571.8px visual viewport, so there is no stale 56px gap above the IME. Raw metrics: before / after.

The complete hardware workflow is published with direct links so another Chromium checkout and Android device can reproduce the run.
The bundle also contains the separately scoped sampler pages needed to install independent stock Chrome WebAPKs.
d8fede429bccc5328f7f760492bc1c27d9a22a7db8b059f7c75a7658c139db9b.e46439920ab79b515b41ca5065180254b7c3b139388cda4254bd1d06d02e1683._ --enable-features=WebAppShortEdgesCutoutMode.PASS, 9 passed, 0 failed, 0 skipped, no known issues.