Fixes #51. `Runtime.evaluate` and `Runtime.callFunctionOn` previously ignored the `contextId` / `executionContextId` parameter entirely, so clients targeting an isolated world (e.g. Playwright's locator path, which calls `Page.createIsolatedWorld` → contextId 100 → evaluates the UtilityScript against that id) silently fell through to the default context, breaking the contract advertised via Runtime.executionContextCreated. Track the set of advertised execution context ids on CdpContext (pre-seeded with 1 and 2 — the default-frame contexts emitted by Runtime.enable and post-navigation) and extend it from Page.createIsolatedWorld. Both handlers now reject unknown ids with `Cannot find context with specified id: <id>` — matching the wording real Chrome returns — and log accepted ids at debug for observability. Obscura still routes every JS call against the page's single V8 isolate, so this PR is spec-compliance scaffolding rather than full multi-world execution. Follow-up work to physically isolate worlds can build on the same valid_context_ids registry.
This commit is contained in:
1 parent
f3c783f6f5
commit
2ff0f8fe1d
3 files changed
+173
-2
No files matched your search
@@ -1,4 +1,4 @@
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
|
||||
use obscura_browser::{BrowserContext, Page};
|
||||
@@ -25,6 +25,16 @@ pub struct CdpContext {
|
||||
// back. Stored as plain Strings (not by-page) — for now we only model
|
||||
// a single page in CdpContext anyway.
|
||||
pub isolated_worlds: Vec<String>,
|
||||
// Set of executionContextIds Obscura has emitted via
|
||||
// Runtime.executionContextCreated. Pre-populated with the default-frame
|
||||
// contexts (`1`, `2`) that Runtime.enable / Page.navigate emit, then
|
||||
// extended each time Page.createIsolatedWorld assigns a fresh id.
|
||||
//
|
||||
// Runtime.evaluate / Runtime.callFunctionOn consult this set to reject
|
||||
// requests targeting an unknown context — matching real Chrome's
|
||||
// "Cannot find context with specified id" CDP error and unblocking the
|
||||
// Playwright locator path described in issue #51.
|
||||
pub valid_context_ids: HashSet<i64>,
|
||||
pub fetch_intercept: FetchInterceptState,
|
||||
pub intercept_tx: Option<tokio::sync::mpsc::UnboundedSender<InterceptedRequest>>,
|
||||
}
|
||||
@@ -53,6 +63,15 @@ impl CdpContext {
|
||||
stealth,
|
||||
user_agent,
|
||||
));
|
||||
// Pre-seed with the default-frame execution context ids that
|
||||
// `Runtime.enable` (1) and post-navigation re-emission (2) advertise
|
||||
// via Runtime.executionContextCreated. Anything else has to be
|
||||
// registered explicitly (Page.createIsolatedWorld), otherwise
|
||||
// Runtime.{evaluate,callFunctionOn} should reject it per CDP spec.
|
||||
let mut valid_context_ids = HashSet::new();
|
||||
valid_context_ids.insert(1);
|
||||
valid_context_ids.insert(2);
|
||||
|
||||
CdpContext {
|
||||
pages: Vec::new(),
|
||||
sessions: HashMap::new(),
|
||||
@@ -64,6 +83,7 @@ impl CdpContext {
|
||||
fetch_intercept: FetchInterceptState::new(),
|
||||
intercept_tx: None,
|
||||
isolated_worlds: Vec::new(),
|
||||
valid_context_ids,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user