From 1950048138ced5ad4313e98b88e098ebd4222b09 Mon Sep 17 00:00:00 2001 From: SGavrl <277843151+SGavrl@users.noreply.github.com> Date: Mon, 18 May 2026 10:11:54 +0000 Subject: [PATCH] fix(browser,cdp,js): about:blank navigation, real getBoxModel/getContentQuads, expose _wrap and self - about: URL scheme now handled in navigate_single instead of hitting validate_url and failing with "Forbidden URL scheme" - DOM.getBoxModel calls getBoundingClientRect via JS instead of returning hardcoded pixel coords - DOM.getContentQuads added (was missing, needed by Playwright click) - globalThis._wrap exposed so CDP eval code can look up nodes by id - globalThis.self = globalThis for webpack/bundler worker detection --- crates/obscura-browser/src/page.rs | 6 +++ crates/obscura-cdp/src/domains/dom.rs | 60 ++++++++++++++++++++++++--- crates/obscura-js/js/bootstrap.js | 3 ++ 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/crates/obscura-browser/src/page.rs b/crates/obscura-browser/src/page.rs index 0b7d8c3..0a8067a 100644 --- a/crates/obscura-browser/src/page.rs +++ b/crates/obscura-browser/src/page.rs @@ -611,6 +611,12 @@ impl Page { } } + if url.scheme() == "about" { + self.navigate_blank(); + self.init_js(); + return Ok(()); + } + let response = if url.scheme() == "data" { let content_type = url_str.strip_prefix("data:") .and_then(|s| s.split(',').next()) diff --git a/crates/obscura-cdp/src/domains/dom.rs b/crates/obscura-cdp/src/domains/dom.rs index 18e08dc..ed9e1b4 100644 --- a/crates/obscura-cdp/src/domains/dom.rs +++ b/crates/obscura-cdp/src/domains/dom.rs @@ -138,16 +138,66 @@ pub async fn handle( "setAttributeValue" => Ok(json!({})), "removeNode" => Ok(json!({})), "getBoxModel" => { + let node_id = params.get("nodeId").and_then(|v| v.as_u64()) + .or_else(|| params.get("backendNodeId").and_then(|v| v.as_u64())) + .unwrap_or(0); + let page = ctx.get_session_page_mut(session_id).ok_or("No page")?; + let code = format!( + "(function() {{\ + var el = globalThis._wrap && globalThis._wrap({0});\ + if (!el || typeof el.getBoundingClientRect !== 'function') return null;\ + var r = el.getBoundingClientRect();\ + return [r.left, r.top, r.right, r.top, r.right, r.bottom, r.left, r.bottom,\ + r.width, r.height];\ + }})()", + node_id + ); + let val = page.evaluate(&code); + let (quad, w, h) = if let Some(arr) = val.as_array() { + let nums: Vec = arr.iter().filter_map(|v| v.as_f64()).collect(); + if nums.len() >= 10 { + let q: Vec = nums[..8].iter().map(|n| json!(n)).collect(); + (q, nums[8], nums[9]) + } else { + (vec![json!(8),json!(8),json!(108),json!(8),json!(108),json!(28),json!(8),json!(28)], 100.0, 20.0) + } + } else { + (vec![json!(8),json!(8),json!(108),json!(8),json!(108),json!(28),json!(8),json!(28)], 100.0, 20.0) + }; Ok(json!({ "model": { - "content": [8,8, 108,8, 108,28, 8,28], - "padding": [8,8, 108,8, 108,28, 8,28], - "border": [8,8, 108,8, 108,28, 8,28], - "margin": [0,0, 116,0, 116,36, 0,36], - "width": 100, "height": 20, + "content": quad.clone(), + "padding": quad.clone(), + "border": quad.clone(), + "margin": quad, + "width": w, "height": h, } })) } + "getContentQuads" => { + let node_id = params.get("nodeId").and_then(|v| v.as_u64()) + .or_else(|| params.get("backendNodeId").and_then(|v| v.as_u64())) + .unwrap_or(0); + let page = ctx.get_session_page_mut(session_id).ok_or("No page")?; + let code = format!( + "(function() {{\ + var el = globalThis._wrap && globalThis._wrap({0});\ + if (!el || typeof el.getBoundingClientRect !== 'function') return null;\ + var r = el.getBoundingClientRect();\ + return [r.left, r.top, r.right, r.top, r.right, r.bottom, r.left, r.bottom];\ + }})()", + node_id + ); + let val = page.evaluate(&code); + let quad = if let Some(arr) = val.as_array() { + let nums: Vec = arr.iter().filter_map(|v| v.as_f64()).collect(); + if nums.len() == 8 { nums.iter().map(|n| json!(n)).collect::>() } + else { vec![json!(8),json!(8),json!(108),json!(8),json!(108),json!(28),json!(8),json!(28)] } + } else { + vec![json!(8),json!(8),json!(108),json!(8),json!(108),json!(28),json!(8),json!(28)] + }; + Ok(json!({ "quads": [quad] })) + } _ => Err(format!("Unknown DOM method: {}", method)), } } diff --git a/crates/obscura-js/js/bootstrap.js b/crates/obscura-js/js/bootstrap.js index 2aa1016..0b19fcb 100644 --- a/crates/obscura-js/js/bootstrap.js +++ b/crates/obscura-js/js/bootstrap.js @@ -1076,6 +1076,9 @@ function _wrapEl(nid) { return n; } +globalThis._wrap = _wrap; +globalThis.self = globalThis; + globalThis.document = null; function _resolveUrl(url) { if (!url) return url;