render: unify responsive geometry and inline gradients
This commit is contained in:
1 parent
29d0bce3f5
commit
3618549842
16 files changed
+587
-102
No files matched your search
@@ -387,13 +387,14 @@ pub async fn dispatch(req: &CdpRequest, ctx: &mut CdpContext) -> CdpResponse {
|
||||
"Fetch" => domains::fetch::handle(method, &req.params, ctx, &req.session_id).await,
|
||||
"IO" => domains::io::handle(method, &req.params, ctx).await,
|
||||
"Input" => domains::input::handle(method, &req.params, ctx, &req.session_id).await,
|
||||
"Emulation" => domains::emulation::handle(method, &req.params, ctx, &req.session_id).await,
|
||||
"Storage" => domains::storage::handle(method, &req.params, ctx, &req.session_id).await,
|
||||
"LP" => domains::lp::handle(method, &req.params, ctx, &req.session_id).await,
|
||||
"Accessibility" => domains::accessibility::handle(method, &req.params, ctx, &req.session_id).await,
|
||||
// Accepted but no-op. Puppeteer's FrameManager.initialize calls
|
||||
// Audits.enable on connect — refusing it breaks puppeteer.connect()
|
||||
// before any user code runs.
|
||||
"Emulation" | "Log" | "Performance" | "Security" | "CSS"
|
||||
"Log" | "Performance" | "Security" | "CSS"
|
||||
| "ServiceWorker" | "Inspector"
|
||||
| "Debugger" | "Profiler" | "HeapProfiler" | "Overlay"
|
||||
| "Audits" => {
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
use serde_json::{json, Value};
|
||||
|
||||
use crate::dispatch::CdpContext;
|
||||
|
||||
pub async fn handle(
|
||||
method: &str,
|
||||
params: &Value,
|
||||
ctx: &mut CdpContext,
|
||||
session_id: &Option<String>,
|
||||
) -> Result<Value, String> {
|
||||
match method {
|
||||
"setDeviceMetricsOverride" => {
|
||||
let width = params
|
||||
.get("width")
|
||||
.and_then(Value::as_f64)
|
||||
.ok_or("Emulation.setDeviceMetricsOverride requires width")?;
|
||||
let height = params
|
||||
.get("height")
|
||||
.and_then(Value::as_f64)
|
||||
.ok_or("Emulation.setDeviceMetricsOverride requires height")?;
|
||||
if !width.is_finite() || !height.is_finite() || width <= 0.0 || height <= 0.0 {
|
||||
return Err(
|
||||
"Emulation.setDeviceMetricsOverride requires positive finite dimensions"
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
let page = ctx
|
||||
.get_session_page_mut(session_id)
|
||||
.ok_or("No page for session")?;
|
||||
page.set_viewport((width as f32, height as f32));
|
||||
Ok(json!({}))
|
||||
}
|
||||
"clearDeviceMetricsOverride" => {
|
||||
let page = ctx
|
||||
.get_session_page_mut(session_id)
|
||||
.ok_or("No page for session")?;
|
||||
page.set_viewport((1280.0, 720.0));
|
||||
Ok(json!({}))
|
||||
}
|
||||
// Touch emulation does not affect layout yet, but acknowledging it is
|
||||
// compatible with clients that pair it with a metrics override.
|
||||
"setTouchEmulationEnabled" => Ok(json!({})),
|
||||
_ => Ok(json!({})),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn device_metrics_override_updates_page_and_window_viewport() {
|
||||
let mut ctx = CdpContext::new();
|
||||
let page_id = ctx.create_page();
|
||||
let session_id = Some("viewport-session".to_string());
|
||||
ctx.sessions
|
||||
.insert(session_id.clone().unwrap(), page_id);
|
||||
|
||||
handle(
|
||||
"setDeviceMetricsOverride",
|
||||
&json!({"width": 1024, "height": 768, "deviceScaleFactor": 1}),
|
||||
&mut ctx,
|
||||
&session_id,
|
||||
)
|
||||
.await
|
||||
.expect("metrics override");
|
||||
|
||||
let page = ctx
|
||||
.get_session_page_mut(&session_id)
|
||||
.expect("page for session");
|
||||
assert_eq!(page.viewport, (1024.0, 768.0));
|
||||
assert_eq!(
|
||||
page.evaluate(
|
||||
"return [innerWidth, innerHeight, visualViewport.width,\
|
||||
visualViewport.height];"
|
||||
),
|
||||
json!([1024, 768, 1024, 768])
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn device_metrics_override_rejects_zero_dimensions() {
|
||||
let mut ctx = CdpContext::new();
|
||||
let page_id = ctx.create_page();
|
||||
let session_id = Some("viewport-session".to_string());
|
||||
ctx.sessions
|
||||
.insert(session_id.clone().unwrap(), page_id);
|
||||
let error = handle(
|
||||
"setDeviceMetricsOverride",
|
||||
&json!({"width": 0, "height": 768}),
|
||||
&mut ctx,
|
||||
&session_id,
|
||||
)
|
||||
.await
|
||||
.expect_err("zero width must fail");
|
||||
assert!(error.contains("positive finite dimensions"));
|
||||
}
|
||||
}
|
||||
@@ -11,3 +11,4 @@ pub mod input;
|
||||
pub mod storage;
|
||||
pub mod accessibility;
|
||||
pub mod lp;
|
||||
pub mod emulation;
|
||||
@@ -400,13 +400,12 @@ pub async fn handle(
|
||||
// configure; ack it so clients that set it do not warn (issue #340).
|
||||
"setDownloadBehavior" => Ok(json!({})),
|
||||
"getLayoutMetrics" => {
|
||||
// Obscura has no visual layout engine, so we return a fixed
|
||||
// 1280x720 viewport (Chrome's default) and try to derive the
|
||||
// content height from document.documentElement.scrollHeight.
|
||||
// Playwright calls this before every page.screenshot() and
|
||||
// would otherwise fail with "Unknown Page method".
|
||||
let width = 1280.0_f64;
|
||||
let height = 720.0_f64;
|
||||
// Playwright calls this before every page.screenshot(). Report the
|
||||
// same live CSS viewport that responsive page code and paint use.
|
||||
let (width, height) = ctx
|
||||
.get_session_page(session_id)
|
||||
.map(|page| (page.viewport.0 as f64, page.viewport.1 as f64))
|
||||
.unwrap_or((1280.0, 720.0));
|
||||
let content_height = ctx
|
||||
.get_session_page_mut(session_id)
|
||||
.map(|p| p.evaluate("document.documentElement && document.documentElement.scrollHeight"))
|
||||
@@ -528,7 +527,7 @@ pub async fn handle(
|
||||
#[cfg(feature = "render")]
|
||||
{
|
||||
let page = ctx.get_session_page(session_id).ok_or("No page for session")?;
|
||||
match page.screenshot((1280.0, 720.0)) {
|
||||
match page.screenshot(page.viewport) {
|
||||
Some(png) => {
|
||||
use base64::Engine as _;
|
||||
let data = base64::engine::general_purpose::STANDARD.encode(&png);
|
||||
|
||||
@@ -1227,7 +1227,7 @@ fn fast_path_response(text: &str) -> Option<String> {
|
||||
"Page.enable" | "Page.setLifecycleEventsEnabled" | "Page.setInterceptFileChooserDialog" |
|
||||
"Runtime.runIfWaitingForDebugger" | "Runtime.discardConsoleEntries" |
|
||||
"Performance.enable" | "Log.enable" | "Security.enable" |
|
||||
"Emulation.setDeviceMetricsOverride" | "Emulation.setTouchEmulationEnabled" |
|
||||
"Emulation.setTouchEmulationEnabled" |
|
||||
"CSS.enable" | "Accessibility.enable" | "ServiceWorker.enable" |
|
||||
"Inspector.enable" | "Debugger.enable" | "Profiler.enable" |
|
||||
"HeapProfiler.enable" | "Overlay.enable" | "Storage.enable" |
|
||||
|
||||
Reference in new issue
Block a user