feat: add session-aware cross-origin iframe support - #331
Open
xjasonli wants to merge 1 commit into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue
Closes #280.
Related to #296:
this adds frame-scoped element lookup, but not a public
Elementconstructorfor 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
SessionIdvalues and CDP commands.The frame model follows the same core idea as Puppeteer's
Frameabstraction: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
Page::main_frame,Page::all_frames, andPage::frame_by_id.Frame::execute,Frame::eval,Frame::query_selector,Frame::goto, andFrame::wait_for_navigation.session that currently owns the frame.
including swaps back to the main process.
Elements, interception, and lifecycle
Elementoperations session-aware, including geometry accumulationacross frame boundaries.
Element::dispose.Fetch.requestPaused, so interceptionresponses are sent through the same session.
sessions attach.
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_idchanges fromNodeIdtoOption<NodeId>. Runtime-basedframe queries can return valid elements without a frontend node id.
Downstream code that reads this field directly will need to handle
None.CdpErrorbecomes#[non_exhaustive]and gains frame- andinterception-specific variants. Downstream exhaustive matches will need a
wildcard arm.
Page.navigatesent throughFrame::executeis rejected immediately withCdpError::NotAllowed. A raw navigation command would bypass the frame-awarenavigation watcher and routing checks. Use
Frame::goto, which keeps the frameand session binding intact.
Validation
stability
cargo check --workspace --all-targets-D warningsThe integration tests use local cross-site fixtures (
localhostand127.0.0.1) with site isolation enabled. They cover nested OOPIFs, processswaps, 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:
expose_functionand User-Agent replay.frameAttachedtoattachedToTargethandoff.Checklist