Skip to content

Cross-origin context swap should be synchronous with navigation policy #310

Description

@davertay-j

Context

Raised in review of #298 (comment). Pre-existing behavior, not introduced by that PR, but retained background sessions widen the exposure.

Problem

WebPageSessionController.didInitiateNavigation schedules the cross-origin context swap asynchronously:

case .crossOrigin:
    // TODO: move this to be synchronous work on decidePolicyFor:navigationAction instead
    pendingContextSwap = Task { @MainActor [weak self] in
        _ = await previousSwap?.value
        await self.detachOldHandlerAndWait(from: webView)
        self.contextId = newContextId
        self.attachNewHandler(to: webView)
    }

The destination page can begin executing JS while the previous origin's ScriptHandler and its BLE message processors are still attached, so a new (potentially untrusted) origin can interact with BLE state belonging to the origin it replaced. The window is bounded by detachOldHandlerAndWait, but nothing prevents the new origin's script from running inside it.

With multi-tab support, live sessions now persist in the background and cross-origin navigations happen on tabs the user is not watching, so the window is both more frequent and less observable.

What to build

Swap the context synchronously with the navigation decision rather than racing it:

  • Perform the detach/attach in decidePolicyFor:navigationAction, or
  • Withhold the navigation decision until the detach has completed

Either way, the old origin's handlers must never be attached while the new origin's JS is executing. Remove the TODO at the call site once done.

Acceptance criteria

  • A cross-origin navigation cannot execute page JS against the prior origin's script handler or BLE processors
  • Rapid successive cross-origin navigations still end with exactly one attached context (no interleaved detach/attach pairs)
  • Same-origin navigations still carry their context over, keeping BLE connections alive
  • Unit tests cover the ordering; CI green

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions