Skip to content

Track nested browsing-context focus ownership for webviews #413

Description

@wieslawsoltes

Parent: #268. Release trackers: #264 and #227.

Proven gap

At unchanged Code OSS revision 645f29cc3176500b4b5762ba887cf2a7f0ffdf2c, the webview prelude handles the host focus command with activeFrame.contentWindow.focus() and repeats that handoff when replacing the visible Markdown frame. It polls document.hasFocus() to publish did-focus/did-blur.

Chrome 153 makes the iframe the outer document's activeElement, reports the child document focused, keeps that ownership when an inner control focuses, then restores the child activeElement to BODY and reports the child unfocused when an outer control focuses. Current WebScene returns from child Window.focus() without changing focus ownership and derives every document's hasFocus() from one top-level boolean.

Scope

  • Track the focused browsing-context/document owner for same-origin nested documents.
  • Make child Window.focus() enter that browsing context without requesting operating-system activation.
  • Keep outer/inner activeElement and per-document hasFocus() consistent across inner/outer element focus, replacement, navigation, detach, and host focus loss/return.
  • Preserve browser-ordered focus/blur/focusin/focusout transitions and clear stale owners during teardown.
  • Add a Chrome/native contract plus the unchanged Markdown focus handoff, bounded latency/memory, and 100-cycle replacement/detach evidence.

Security and collision boundary

Opaque and cross-origin frame access remains unavailable and must not gain a focus side channel. Top-level Window.focus() retains its typed host request and admission behavior. This issue does not change keyboard routing, CSS, File APIs, accessibility publication, packaging, navigation/origin/CSP semantics owned by #267 and its active work, or AppScene host focus implementation.

Activity

  1. wieslawsoltes commented on Sep 18, 2026

    @wieslawsoltes
    CollaboratorAuthor

    Exact implementation base: d355d3fd021d792f97f5010aad5951ff7776b772.

    The Chrome 153 oracle establishes the next product-visible invariant: frame.contentWindow.focus() sets the outer activeElement to the iframe, the child document becomes focused with BODY active, inner focus keeps iframe ownership, and outer focus exits the child and resets its active element. The unchanged Code OSS prelude uses exactly this call for host focus and visible-frame replacement.

    Owned paths will be the generic V8 focus/window bindings and state, focused native browser-DOM/input tests, and one dedicated browser/native contract/profile. The implementation will not touch CSS, File APIs, packaging, AppScene, keyboard routing, accessibility publication, or #267 navigation/origin/CSP behavior. Opaque/cross-origin access remains fail-closed, and top-level Window.focus() keeps its typed host request.

  2. wieslawsoltes commented on Sep 18, 2026

    @wieslawsoltes
    CollaboratorAuthor

    Completed by #416, merged as dd39f118b8eba301f1884740e8b25573f49d687e.

    Evidence:

    • Chrome 153 oracle: 6/6 focus ownership assertions passed.
    • Native WebPlatformSubset: 1/1 document, 6/6 subtests passed.
    • Exact navigated Code-shaped Markdown fake.html plus document.open/write/close focus handoff passed.
    • Same-origin child focus emits no host activation request; top-level focus emits exactly one typed request; opaque/cross-origin access remains fail-closed.
    • Post-rebase native lifecycle gate: 100 create/focus/inner-focus/remove cycles, p95 0.476 ms (10 ms limit), V8 heap 1,417,252 -> 1,417,252 bytes, native nodes 7 -> 7, RSS 44.9 -> 46.2 MiB (64 MiB limit).
    • Hosted macOS ARM64 and portable V8 passed at exact PR head 8f2732033761d86a936ab3ae7f308a160f8f1529; remaining broad tails were canceled under the fast-merge policy.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    vscode-oss/plannedPlanned for the AppScene/WebScene VS Code OSS integration

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions