Skip to main content

Module frame_graph

Module frame_graph 

Source
Expand description

Frame + shadow-root graph for the current page.

Every captcha-solving operation that has to walk frames today does this:

for fid in page.frames().await? {
    if let Some(ctx) = page.frame_execution_context(fid).await? {
        page.evaluate_expression(...with ctx...).await?;
    }
}

Three problems with the bare-loop pattern:

  1. No structure. page.frames() returns a flat list, you can’t ask “which frame is this iframe’s parent?”, “which frames live inside the captcha container?”, “which frame is nested deepest?” without re-running an extraction pass each time. Solvers re-derive the topology over and over.
  2. Shadow roots are invisible. page.frames() only sees cross-document boundaries; same-document shadow roots are missed. The existing in-DOM walkAllRoots JS pass handles them but lives in every solver as a copy-paste blob.
  3. No reasoning. With a graph you can BFS from “the deepest frame containing a captcha widget” outward to find the nearest token field, or topo-sort frames so the deepest challenge runs first. With a flat list you can’t.

FrameGraph is the substrate: snapshot once, query many times. FrameNode is the per-node shape (frame_id + parent + URL + title + presence of captcha markers).

Pure data type, no IO ourselves; FrameGraph::snapshot recovers the real topology with one WebDriver BiDi browsingContext.getTree call (via crate::browser::Page::frame_tree) plus a per-frame eval for title/marker, then returns a built graph. Tests can construct synthetic graphs without a browser.

Structs§

FrameGraph
The full graph for a page snapshot.
FrameNode
One node in the frame graph.