Skip to content

feat: add session-aware cross-origin iframe support - #331

Open
xjasonli wants to merge 1 commit into
mattsse:mainfrom
xjasonli:feat/oopif-support
Open

feat: add session-aware cross-origin iframe support#331
xjasonli wants to merge 1 commit into
mattsse:mainfrom
xjasonli:feat/oopif-support

Conversation

@xjasonli

Copy link
Copy Markdown

Issue

Closes #280.

Related to #296:
this adds frame-scoped element lookup, but not a public Element constructor
for arbitrary CDP identifiers.

Description of changes

This adds first-class support for cross-origin, out-of-process iframes
(OOPIFs).

Previously, chromiumoxide could discover iframe targets, but their child CDP
sessions were not connected to the higher-level Page, Frame, Element,
navigation, execution-context, and interception APIs. Callers therefore had to
work with raw SessionId values and CDP commands.

The frame model follows the same core idea as Puppeteer's Frame abstraction:
a frame keeps a stable identity while its effective CDP session may change as
site isolation moves it between processes.

The attach sequence differs deliberately from Puppeteer's unpause-early
approach. Chromiumoxide registers the child session's initialization work while
the iframe target is still paused, then resumes it after that initialization
chain is in place.

Frames and sessions

  • Add Page::main_frame, Page::all_frames, and Page::frame_by_id.
  • Add session-pinned Frame::execute, Frame::eval,
    Frame::query_selector, Frame::goto, and
    Frame::wait_for_navigation.
  • Recursively attach and initialize child iframe sessions.
  • Route Runtime, DOM, Network, lifecycle, and navigation work through the
    session that currently owns the frame.
  • Keep frame identity stable across site-isolation-induced process swaps,
    including swaps back to the main process.
  • Scope execution contexts by session as well as execution-context identity.

Elements, interception, and lifecycle

  • Make Element operations session-aware, including geometry accumulation
    across frame boundaries.
  • Add explicit remote-object cleanup through Element::dispose.
  • Capture the session that produced Fetch.requestPaused, so interception
    responses are sent through the same session.
  • Replay preload scripts and relevant Network/Emulation state when child iframe
    sessions attach.
  • Complete pending commands, navigation requests, and page-creation requests
    when a child session detaches, a target is destroyed, or the connection
    closes.

Fetch interception in this PR is session-local: a paused request is handled on
the session that produced it. Adopting an entire request lifecycle across
sessions remains follow-up work.

Breaking changes

  • Element::node_id changes from NodeId to Option<NodeId>. Runtime-based
    frame queries can return valid elements without a frontend node id.
    Downstream code that reads this field directly will need to handle None.
  • CdpError becomes #[non_exhaustive] and gains frame- and
    interception-specific variants. Downstream exhaustive matches will need a
    wildcard arm.

Page.navigate sent through Frame::execute is rejected immediately with
CdpError::NotAllowed. A raw navigation command would bypass the frame-aware
navigation watcher and routing checks. Use Frame::goto, which keeps the frame
and session binding intact.

Validation

  • Library tests: 128 passed
  • Compatibility tests: 2 passed
  • Local OOPIF integration tests: 7 passed, run twice to exercise attach/detach
    stability
  • cargo check --workspace --all-targets
  • Examples compile
  • Clippy with -D warnings
  • Formatting and diff checks

The integration tests use local cross-site fixtures (localhost and
127.0.0.1) with site isolation enabled. They cover nested OOPIFs, process
swaps, JavaScript evaluation, elements, navigation, request interception,
authentication, preload replay, stale handles, detach, and teardown.

Follow-up work

This PR covers the core OOPIF interaction path. Broader state-management work
is intentionally kept separate:

  • Reconciliation and fan-out for dynamically changed Network settings.
  • Cross-frame expose_function and User-Agent replay.
  • Preload removal, stealth-script replay, and isolated-world recovery.
  • Explicit operation gating during the short frameAttached to
    attachedToTarget handoff.
  • Full request-lifecycle adoption across sessions.

Checklist

  • Added change to the changelog
  • Created unit tests for my feature (if needed)
  • Created a least one integration test

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.

Interact with cross-origin iframe

1 participant