mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
Move webdriver actions commands to servoshell (#37669)
Move webdriver actions commands to servoshell. Testing: Test with webdriver enable in the CI [Test result 1](https://github.com/longvatrong111/servo/actions/runs/15875355256) [Test result 2](https://github.com/longvatrong111/servo/actions/runs/15875356595) [Test result 3](https://github.com/longvatrong111/servo/actions/runs/15875361886) Fixes: https://github.com/servo/servo/issues/37370 Signed-off-by: batu_hoang <longvatrong111@gmail.com>
This commit is contained in:
parent
9bd8d4f026
commit
940eff9497
12 changed files with 126 additions and 208 deletions
|
@ -27,10 +27,10 @@ use constellation_traits::{EmbedderToConstellationMessage, PaintMetricEvent};
|
||||||
use crossbeam_channel::{Receiver, Sender};
|
use crossbeam_channel::{Receiver, Sender};
|
||||||
use dpi::PhysicalSize;
|
use dpi::PhysicalSize;
|
||||||
use embedder_traits::{
|
use embedder_traits::{
|
||||||
CompositorHitTestResult, Cursor, InputEvent, MouseButtonEvent, MouseMoveEvent, ShutdownState,
|
CompositorHitTestResult, Cursor, InputEvent, ShutdownState, UntrustedNodeAddress,
|
||||||
UntrustedNodeAddress, ViewportDetails, WheelDelta, WheelEvent, WheelMode,
|
ViewportDetails,
|
||||||
};
|
};
|
||||||
use euclid::{Point2D, Rect, Scale, Size2D, Transform3D, Vector2D};
|
use euclid::{Point2D, Rect, Scale, Size2D, Transform3D};
|
||||||
use ipc_channel::ipc::{self, IpcSharedMemory};
|
use ipc_channel::ipc::{self, IpcSharedMemory};
|
||||||
use libc::c_void;
|
use libc::c_void;
|
||||||
use log::{debug, info, trace, warn};
|
use log::{debug, info, trace, warn};
|
||||||
|
@ -672,64 +672,6 @@ impl IOCompositor {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
CompositorMsg::WebDriverMouseButtonEvent(
|
|
||||||
webview_id,
|
|
||||||
action,
|
|
||||||
button,
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
message_id,
|
|
||||||
) => {
|
|
||||||
let Some(webview_renderer) = self.webview_renderers.get_mut(webview_id) else {
|
|
||||||
warn!("Handling input event for unknown webview: {webview_id}");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let dppx = webview_renderer.device_pixels_per_page_pixel();
|
|
||||||
let point = dppx.transform_point(Point2D::new(x, y));
|
|
||||||
webview_renderer.dispatch_point_input_event(
|
|
||||||
InputEvent::MouseButton(MouseButtonEvent::new(action, button, point))
|
|
||||||
.with_webdriver_message_id(message_id),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
CompositorMsg::WebDriverMouseMoveEvent(webview_id, x, y, message_id) => {
|
|
||||||
let Some(webview_renderer) = self.webview_renderers.get_mut(webview_id) else {
|
|
||||||
warn!("Handling input event for unknown webview: {webview_id}");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let dppx = webview_renderer.device_pixels_per_page_pixel();
|
|
||||||
let point = dppx.transform_point(Point2D::new(x, y));
|
|
||||||
webview_renderer.dispatch_point_input_event(
|
|
||||||
InputEvent::MouseMove(MouseMoveEvent::new(point))
|
|
||||||
.with_webdriver_message_id(message_id),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
CompositorMsg::WebDriverWheelScrollEvent(webview_id, x, y, dx, dy, message_id) => {
|
|
||||||
let Some(webview_renderer) = self.webview_renderers.get_mut(webview_id) else {
|
|
||||||
warn!("Handling input event for unknown webview: {webview_id}");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
// The sign of wheel delta value definition in uievent
|
|
||||||
// is inverted compared to `winit`s wheel delta. Hence,
|
|
||||||
// here we invert the sign to mimic wheel scroll
|
|
||||||
// implementation in `headed_window.rs`.
|
|
||||||
let delta = WheelDelta {
|
|
||||||
x: -dx,
|
|
||||||
y: -dy,
|
|
||||||
z: 0.0,
|
|
||||||
mode: WheelMode::DeltaPixel,
|
|
||||||
};
|
|
||||||
let dppx = webview_renderer.device_pixels_per_page_pixel();
|
|
||||||
let point = dppx.transform_point(Point2D::new(x, y));
|
|
||||||
let scroll_delta = dppx.transform_vector(Vector2D::new(dx as f32, dy as f32));
|
|
||||||
webview_renderer.dispatch_point_input_event(
|
|
||||||
InputEvent::Wheel(WheelEvent::new(delta, point))
|
|
||||||
.with_webdriver_message_id(message_id),
|
|
||||||
);
|
|
||||||
webview_renderer.on_webdriver_wheel_action(scroll_delta, point);
|
|
||||||
},
|
|
||||||
|
|
||||||
CompositorMsg::SendInitialTransaction(pipeline) => {
|
CompositorMsg::SendInitialTransaction(pipeline) => {
|
||||||
let mut txn = Transaction::new();
|
let mut txn = Transaction::new();
|
||||||
txn.set_display_list(WebRenderEpoch(0), (pipeline, Default::default()));
|
txn.set_display_list(WebRenderEpoch(0), (pipeline, Default::default()));
|
||||||
|
|
|
@ -40,9 +40,6 @@ mod from_constellation {
|
||||||
Self::NewWebRenderFrameReady(..) => target!("NewWebRenderFrameReady"),
|
Self::NewWebRenderFrameReady(..) => target!("NewWebRenderFrameReady"),
|
||||||
Self::PipelineExited(..) => target!("PipelineExited"),
|
Self::PipelineExited(..) => target!("PipelineExited"),
|
||||||
Self::LoadComplete(..) => target!("LoadComplete"),
|
Self::LoadComplete(..) => target!("LoadComplete"),
|
||||||
Self::WebDriverMouseButtonEvent(..) => target!("WebDriverMouseButtonEvent"),
|
|
||||||
Self::WebDriverMouseMoveEvent(..) => target!("WebDriverMouseMoveEvent"),
|
|
||||||
Self::WebDriverWheelScrollEvent(..) => target!("WebDriverWheelScrollEvent"),
|
|
||||||
Self::SendInitialTransaction(..) => target!("SendInitialTransaction"),
|
Self::SendInitialTransaction(..) => target!("SendInitialTransaction"),
|
||||||
Self::SendScrollNode(..) => target!("SendScrollNode"),
|
Self::SendScrollNode(..) => target!("SendScrollNode"),
|
||||||
Self::SendDisplayList { .. } => target!("SendDisplayList"),
|
Self::SendDisplayList { .. } => target!("SendDisplayList"),
|
||||||
|
|
|
@ -792,22 +792,6 @@ impl WebViewRenderer {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Push scroll pending event when receiving wheel action from webdriver
|
|
||||||
pub(crate) fn on_webdriver_wheel_action(
|
|
||||||
&mut self,
|
|
||||||
scroll_delta: Vector2D<f32, DevicePixel>,
|
|
||||||
point: Point2D<f32, DevicePixel>,
|
|
||||||
) {
|
|
||||||
if self.global.borrow().shutdown_state() != ShutdownState::NotShuttingDown {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let scroll_location =
|
|
||||||
ScrollLocation::Delta(LayoutVector2D::from_untyped(scroll_delta.to_untyped()));
|
|
||||||
let cursor = DeviceIntPoint::new(point.x as i32, point.y as i32);
|
|
||||||
self.on_scroll_window_event(scroll_location, cursor)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Process pending scroll events for this [`WebViewRenderer`]. Returns a tuple containing:
|
/// Process pending scroll events for this [`WebViewRenderer`]. Returns a tuple containing:
|
||||||
///
|
///
|
||||||
/// - A boolean that is true if a zoom occurred.
|
/// - A boolean that is true if a zoom occurred.
|
||||||
|
|
|
@ -1468,6 +1468,9 @@ where
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
EmbedderToConstellationMessage::SetWebDriverResponseSender(sender) => {
|
||||||
|
self.webdriver.input_command_response_sender = Some(sender);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1850,7 +1853,6 @@ where
|
||||||
.send(WebDriverCommandResponse { id: msg_id })
|
.send(WebDriverCommandResponse { id: msg_id })
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
warn!("Failed to send WebDriverInputComplete {:?}", msg_id);
|
warn!("Failed to send WebDriverInputComplete {:?}", msg_id);
|
||||||
self.webdriver.input_command_response_sender = None;
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
warn!("No WebDriver input_command_response_sender");
|
warn!("No WebDriver input_command_response_sender");
|
||||||
|
@ -4616,14 +4618,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
WebDriverCommandMsg::KeyboardAction(
|
WebDriverCommandMsg::KeyboardAction(browsing_context_id, key_event, msg_id) => {
|
||||||
browsing_context_id,
|
|
||||||
key_event,
|
|
||||||
msg_id,
|
|
||||||
response_sender,
|
|
||||||
) => {
|
|
||||||
self.webdriver.input_command_response_sender = Some(response_sender);
|
|
||||||
|
|
||||||
let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) {
|
let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) {
|
||||||
Some(browsing_context) => browsing_context.pipeline_id,
|
Some(browsing_context) => browsing_context.pipeline_id,
|
||||||
None => {
|
None => {
|
||||||
|
@ -4649,50 +4644,14 @@ where
|
||||||
self.handle_send_error(pipeline_id, e)
|
self.handle_send_error(pipeline_id, e)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
WebDriverCommandMsg::MouseButtonAction(
|
WebDriverCommandMsg::MouseButtonAction(..) => {
|
||||||
webview_id,
|
unreachable!("This command should be send directly to the embedder.");
|
||||||
mouse_event_type,
|
|
||||||
mouse_button,
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
msg_id,
|
|
||||||
response_sender,
|
|
||||||
) => {
|
|
||||||
self.webdriver.input_command_response_sender = Some(response_sender);
|
|
||||||
|
|
||||||
self.compositor_proxy
|
|
||||||
.send(CompositorMsg::WebDriverMouseButtonEvent(
|
|
||||||
webview_id,
|
|
||||||
mouse_event_type,
|
|
||||||
mouse_button,
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
msg_id,
|
|
||||||
));
|
|
||||||
},
|
},
|
||||||
WebDriverCommandMsg::MouseMoveAction(webview_id, x, y, msg_id, response_sender) => {
|
WebDriverCommandMsg::MouseMoveAction(..) => {
|
||||||
self.webdriver.input_command_response_sender = Some(response_sender);
|
unreachable!("This command should be send directly to the embedder.");
|
||||||
|
|
||||||
self.compositor_proxy
|
|
||||||
.send(CompositorMsg::WebDriverMouseMoveEvent(
|
|
||||||
webview_id, x, y, msg_id,
|
|
||||||
));
|
|
||||||
},
|
},
|
||||||
WebDriverCommandMsg::WheelScrollAction(
|
WebDriverCommandMsg::WheelScrollAction(..) => {
|
||||||
webview_id,
|
unreachable!("This command should be send directly to the embedder.");
|
||||||
x,
|
|
||||||
y,
|
|
||||||
delta_x,
|
|
||||||
delta_y,
|
|
||||||
msg_id,
|
|
||||||
response_sender,
|
|
||||||
) => {
|
|
||||||
self.webdriver.input_command_response_sender = Some(response_sender);
|
|
||||||
|
|
||||||
self.compositor_proxy
|
|
||||||
.send(CompositorMsg::WebDriverWheelScrollEvent(
|
|
||||||
webview_id, x, y, delta_x, delta_y, msg_id,
|
|
||||||
));
|
|
||||||
},
|
},
|
||||||
WebDriverCommandMsg::TakeScreenshot(webview_id, rect, response_sender) => {
|
WebDriverCommandMsg::TakeScreenshot(webview_id, rect, response_sender) => {
|
||||||
self.compositor_proxy.send(CompositorMsg::CreatePng(
|
self.compositor_proxy.send(CompositorMsg::CreatePng(
|
||||||
|
|
|
@ -77,6 +77,7 @@ mod from_compositor {
|
||||||
Self::EvaluateJavaScript(..) => target!("EvaluateJavaScript"),
|
Self::EvaluateJavaScript(..) => target!("EvaluateJavaScript"),
|
||||||
Self::CreateMemoryReport(..) => target!("CreateMemoryReport"),
|
Self::CreateMemoryReport(..) => target!("CreateMemoryReport"),
|
||||||
Self::SendImageKeysForPipeline(..) => target!("SendImageKeysForPipeline"),
|
Self::SendImageKeysForPipeline(..) => target!("SendImageKeysForPipeline"),
|
||||||
|
Self::SetWebDriverResponseSender(..) => target!("SetWebDriverResponseSender"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,7 @@ use std::fmt::{Debug, Error, Formatter};
|
||||||
|
|
||||||
use base::id::{PipelineId, WebViewId};
|
use base::id::{PipelineId, WebViewId};
|
||||||
use crossbeam_channel::Sender;
|
use crossbeam_channel::Sender;
|
||||||
use embedder_traits::{
|
use embedder_traits::{AnimationState, EventLoopWaker, TouchEventResult};
|
||||||
AnimationState, EventLoopWaker, MouseButton, MouseButtonAction, TouchEventResult,
|
|
||||||
WebDriverMessageId,
|
|
||||||
};
|
|
||||||
use euclid::Rect;
|
use euclid::Rect;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
|
@ -105,20 +102,6 @@ pub enum CompositorMsg {
|
||||||
PipelineExited(WebViewId, PipelineId, PipelineExitSource),
|
PipelineExited(WebViewId, PipelineId, PipelineExitSource),
|
||||||
/// The load of a page has completed
|
/// The load of a page has completed
|
||||||
LoadComplete(WebViewId),
|
LoadComplete(WebViewId),
|
||||||
/// WebDriver mouse button event
|
|
||||||
WebDriverMouseButtonEvent(
|
|
||||||
WebViewId,
|
|
||||||
MouseButtonAction,
|
|
||||||
MouseButton,
|
|
||||||
f32,
|
|
||||||
f32,
|
|
||||||
Option<WebDriverMessageId>,
|
|
||||||
),
|
|
||||||
/// WebDriver mouse move event
|
|
||||||
WebDriverMouseMoveEvent(WebViewId, f32, f32, Option<WebDriverMessageId>),
|
|
||||||
// Webdriver wheel scroll event
|
|
||||||
WebDriverWheelScrollEvent(WebViewId, f32, f32, f64, f64, Option<WebDriverMessageId>),
|
|
||||||
|
|
||||||
/// Inform WebRender of the existence of this pipeline.
|
/// Inform WebRender of the existence of this pipeline.
|
||||||
SendInitialTransaction(WebRenderPipelineId),
|
SendInitialTransaction(WebRenderPipelineId),
|
||||||
/// Perform a scroll operation.
|
/// Perform a scroll operation.
|
||||||
|
|
|
@ -20,7 +20,7 @@ use base::cross_process_instant::CrossProcessInstant;
|
||||||
use base::id::{MessagePortId, PipelineId, WebViewId};
|
use base::id::{MessagePortId, PipelineId, WebViewId};
|
||||||
use embedder_traits::{
|
use embedder_traits::{
|
||||||
CompositorHitTestResult, Cursor, InputEvent, JavaScriptEvaluationId, MediaSessionActionType,
|
CompositorHitTestResult, Cursor, InputEvent, JavaScriptEvaluationId, MediaSessionActionType,
|
||||||
Theme, ViewportDetails, WebDriverCommandMsg,
|
Theme, ViewportDetails, WebDriverCommandMsg, WebDriverCommandResponse,
|
||||||
};
|
};
|
||||||
pub use from_script_message::*;
|
pub use from_script_message::*;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
|
@ -96,6 +96,8 @@ pub enum EmbedderToConstellationMessage {
|
||||||
CreateMemoryReport(IpcSender<MemoryReportResult>),
|
CreateMemoryReport(IpcSender<MemoryReportResult>),
|
||||||
/// Sends the generated image key to the image cache associated with this pipeline.
|
/// Sends the generated image key to the image cache associated with this pipeline.
|
||||||
SendImageKeysForPipeline(PipelineId, Vec<ImageKey>),
|
SendImageKeysForPipeline(PipelineId, Vec<ImageKey>),
|
||||||
|
/// Set WebDriver input event handled sender.
|
||||||
|
SetWebDriverResponseSender(IpcSender<WebDriverCommandResponse>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A description of a paint metric that is sent from the Servo renderer to the
|
/// A description of a paint metric that is sent from the Servo renderer to the
|
||||||
|
|
|
@ -30,6 +30,9 @@ pub struct WebDriverMessageId(pub usize);
|
||||||
/// Messages to the constellation originating from the WebDriver server.
|
/// Messages to the constellation originating from the WebDriver server.
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub enum WebDriverCommandMsg {
|
pub enum WebDriverCommandMsg {
|
||||||
|
/// Used in the initialization of the WebDriver server to set the sender for sending responses
|
||||||
|
/// back to the WebDriver client. It is set to constellation for now
|
||||||
|
SetWebDriverResponseSender(IpcSender<WebDriverCommandResponse>),
|
||||||
/// Get the window size.
|
/// Get the window size.
|
||||||
GetWindowRect(WebViewId, IpcSender<DeviceIntRect>),
|
GetWindowRect(WebViewId, IpcSender<DeviceIntRect>),
|
||||||
/// Get the viewport size.
|
/// Get the viewport size.
|
||||||
|
@ -53,7 +56,6 @@ pub enum WebDriverCommandMsg {
|
||||||
KeyboardEvent,
|
KeyboardEvent,
|
||||||
// Should never be None.
|
// Should never be None.
|
||||||
Option<WebDriverMessageId>,
|
Option<WebDriverMessageId>,
|
||||||
IpcSender<WebDriverCommandResponse>,
|
|
||||||
),
|
),
|
||||||
/// Act as if the mouse was clicked in the browsing context with the given ID.
|
/// Act as if the mouse was clicked in the browsing context with the given ID.
|
||||||
MouseButtonAction(
|
MouseButtonAction(
|
||||||
|
@ -64,7 +66,6 @@ pub enum WebDriverCommandMsg {
|
||||||
f32,
|
f32,
|
||||||
// Should never be None.
|
// Should never be None.
|
||||||
Option<WebDriverMessageId>,
|
Option<WebDriverMessageId>,
|
||||||
IpcSender<WebDriverCommandResponse>,
|
|
||||||
),
|
),
|
||||||
/// Act as if the mouse was moved in the browsing context with the given ID.
|
/// Act as if the mouse was moved in the browsing context with the given ID.
|
||||||
MouseMoveAction(
|
MouseMoveAction(
|
||||||
|
@ -74,7 +75,6 @@ pub enum WebDriverCommandMsg {
|
||||||
// None if it's not the last `perform_pointer_move` since we only
|
// None if it's not the last `perform_pointer_move` since we only
|
||||||
// expect one response from constellation for each tick actions.
|
// expect one response from constellation for each tick actions.
|
||||||
Option<WebDriverMessageId>,
|
Option<WebDriverMessageId>,
|
||||||
IpcSender<WebDriverCommandResponse>,
|
|
||||||
),
|
),
|
||||||
/// Act as if the mouse wheel is scrolled in the browsing context given the given ID.
|
/// Act as if the mouse wheel is scrolled in the browsing context given the given ID.
|
||||||
WheelScrollAction(
|
WheelScrollAction(
|
||||||
|
@ -86,7 +86,6 @@ pub enum WebDriverCommandMsg {
|
||||||
// None if it's not the last `perform_wheel_scroll` since we only
|
// None if it's not the last `perform_wheel_scroll` since we only
|
||||||
// expect one response from constellation for each tick actions.
|
// expect one response from constellation for each tick actions.
|
||||||
Option<WebDriverMessageId>,
|
Option<WebDriverMessageId>,
|
||||||
IpcSender<WebDriverCommandResponse>,
|
|
||||||
),
|
),
|
||||||
/// Set the window size.
|
/// Set the window size.
|
||||||
SetWindowSize(
|
SetWindowSize(
|
||||||
|
|
|
@ -7,7 +7,6 @@ use std::thread;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use base::id::BrowsingContextId;
|
use base::id::BrowsingContextId;
|
||||||
use constellation_traits::EmbedderToConstellationMessage;
|
|
||||||
use embedder_traits::{MouseButtonAction, WebDriverCommandMsg, WebDriverScriptCommand};
|
use embedder_traits::{MouseButtonAction, WebDriverCommandMsg, WebDriverScriptCommand};
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
use keyboard_types::webdriver::KeyInputState;
|
use keyboard_types::webdriver::KeyInputState;
|
||||||
|
@ -178,7 +177,7 @@ impl Handler {
|
||||||
//
|
//
|
||||||
// Wait for num_pending_actions number of responses
|
// Wait for num_pending_actions number of responses
|
||||||
for _ in 0..self.num_pending_actions.get() {
|
for _ in 0..self.num_pending_actions.get() {
|
||||||
match self.constellation_receiver.recv() {
|
match self.webdriver_response_receiver.recv() {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
let current_waiting_id = self
|
let current_waiting_id = self
|
||||||
.current_action_id
|
.current_action_id
|
||||||
|
@ -316,11 +315,8 @@ impl Handler {
|
||||||
self.session().unwrap().browsing_context_id,
|
self.session().unwrap().browsing_context_id,
|
||||||
keyboard_event,
|
keyboard_event,
|
||||||
msg_id,
|
msg_id,
|
||||||
self.constellation_sender.clone(),
|
|
||||||
);
|
);
|
||||||
self.constellation_chan
|
let _ = self.send_message_to_embedder(cmd_msg);
|
||||||
.send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg))
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://w3c.github.io/webdriver/#dfn-dispatch-a-keyup-action>
|
/// <https://w3c.github.io/webdriver/#dfn-dispatch-a-keyup-action>
|
||||||
|
@ -358,11 +354,8 @@ impl Handler {
|
||||||
self.session().unwrap().browsing_context_id,
|
self.session().unwrap().browsing_context_id,
|
||||||
keyboard_event,
|
keyboard_event,
|
||||||
msg_id,
|
msg_id,
|
||||||
self.constellation_sender.clone(),
|
|
||||||
);
|
);
|
||||||
self.constellation_chan
|
let _ = self.send_message_to_embedder(cmd_msg);
|
||||||
.send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg))
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,11 +383,8 @@ impl Handler {
|
||||||
pointer_input_state.x as f32,
|
pointer_input_state.x as f32,
|
||||||
pointer_input_state.y as f32,
|
pointer_input_state.y as f32,
|
||||||
msg_id,
|
msg_id,
|
||||||
self.constellation_sender.clone(),
|
|
||||||
);
|
);
|
||||||
self.constellation_chan
|
let _ = self.send_message_to_embedder(cmd_msg);
|
||||||
.send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg))
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://w3c.github.io/webdriver/#dfn-dispatch-a-pointerup-action>
|
/// <https://w3c.github.io/webdriver/#dfn-dispatch-a-pointerup-action>
|
||||||
|
@ -439,11 +429,8 @@ impl Handler {
|
||||||
pointer_input_state.x as f32,
|
pointer_input_state.x as f32,
|
||||||
pointer_input_state.y as f32,
|
pointer_input_state.y as f32,
|
||||||
msg_id,
|
msg_id,
|
||||||
self.constellation_sender.clone(),
|
|
||||||
);
|
);
|
||||||
self.constellation_chan
|
let _ = self.send_message_to_embedder(cmd_msg);
|
||||||
.send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg))
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://w3c.github.io/webdriver/#dfn-dispatch-a-pointermove-action>
|
/// <https://w3c.github.io/webdriver/#dfn-dispatch-a-pointermove-action>
|
||||||
|
@ -567,11 +554,8 @@ impl Handler {
|
||||||
x as f32,
|
x as f32,
|
||||||
y as f32,
|
y as f32,
|
||||||
msg_id,
|
msg_id,
|
||||||
self.constellation_sender.clone(),
|
|
||||||
);
|
);
|
||||||
self.constellation_chan
|
let _ = self.send_message_to_embedder(cmd_msg);
|
||||||
.send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg))
|
|
||||||
.unwrap();
|
|
||||||
// Step 7.3
|
// Step 7.3
|
||||||
pointer_input_state.x = x;
|
pointer_input_state.x = x;
|
||||||
pointer_input_state.y = y;
|
pointer_input_state.y = y;
|
||||||
|
@ -707,11 +691,8 @@ impl Handler {
|
||||||
delta_x as f64,
|
delta_x as f64,
|
||||||
delta_y as f64,
|
delta_y as f64,
|
||||||
msg_id,
|
msg_id,
|
||||||
self.constellation_sender.clone(),
|
|
||||||
);
|
);
|
||||||
self.constellation_chan
|
let _ = self.send_message_to_embedder(cmd_msg);
|
||||||
.send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
curr_delta_x += delta_x;
|
curr_delta_x += delta_x;
|
||||||
curr_delta_y += delta_y;
|
curr_delta_y += delta_y;
|
||||||
|
|
|
@ -127,12 +127,15 @@ pub fn start_server(
|
||||||
constellation_chan_deprecated: Sender<EmbedderToConstellationMessage>,
|
constellation_chan_deprecated: Sender<EmbedderToConstellationMessage>,
|
||||||
embedder_sender: Sender<WebDriverCommandMsg>,
|
embedder_sender: Sender<WebDriverCommandMsg>,
|
||||||
event_loop_waker: Box<dyn EventLoopWaker>,
|
event_loop_waker: Box<dyn EventLoopWaker>,
|
||||||
|
webdriver_response_receiver: IpcReceiver<WebDriverCommandResponse>,
|
||||||
) {
|
) {
|
||||||
let handler = Handler::new(
|
let handler = Handler::new(
|
||||||
constellation_chan_deprecated,
|
constellation_chan_deprecated,
|
||||||
embedder_sender,
|
embedder_sender,
|
||||||
event_loop_waker,
|
event_loop_waker,
|
||||||
|
webdriver_response_receiver,
|
||||||
);
|
);
|
||||||
|
|
||||||
thread::Builder::new()
|
thread::Builder::new()
|
||||||
.name("WebDriverHttpServer".to_owned())
|
.name("WebDriverHttpServer".to_owned())
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
|
@ -242,12 +245,8 @@ struct Handler {
|
||||||
/// TODO: change name to constellation_sender
|
/// TODO: change name to constellation_sender
|
||||||
constellation_chan: Sender<EmbedderToConstellationMessage>,
|
constellation_chan: Sender<EmbedderToConstellationMessage>,
|
||||||
|
|
||||||
/// The IPC sender which we can clone and pass along to the constellation
|
|
||||||
/// TODO: change name to webdriver_response_sender
|
|
||||||
constellation_sender: IpcSender<WebDriverCommandResponse>,
|
|
||||||
|
|
||||||
/// Receiver notification from the constellation when a command is completed
|
/// Receiver notification from the constellation when a command is completed
|
||||||
constellation_receiver: IpcReceiver<WebDriverCommandResponse>,
|
webdriver_response_receiver: IpcReceiver<WebDriverCommandResponse>,
|
||||||
|
|
||||||
id_generator: WebDriverMessageIdGenerator,
|
id_generator: WebDriverMessageIdGenerator,
|
||||||
|
|
||||||
|
@ -474,6 +473,7 @@ impl Handler {
|
||||||
constellation_chan: Sender<EmbedderToConstellationMessage>,
|
constellation_chan: Sender<EmbedderToConstellationMessage>,
|
||||||
embedder_sender: Sender<WebDriverCommandMsg>,
|
embedder_sender: Sender<WebDriverCommandMsg>,
|
||||||
event_loop_waker: Box<dyn EventLoopWaker>,
|
event_loop_waker: Box<dyn EventLoopWaker>,
|
||||||
|
webdriver_response_receiver: IpcReceiver<WebDriverCommandResponse>,
|
||||||
) -> Handler {
|
) -> Handler {
|
||||||
// Create a pair of both an IPC and a threaded channel,
|
// Create a pair of both an IPC and a threaded channel,
|
||||||
// keep the IPC sender to clone and pass to the constellation for each load,
|
// keep the IPC sender to clone and pass to the constellation for each load,
|
||||||
|
@ -484,8 +484,6 @@ impl Handler {
|
||||||
let (sender, load_status_receiver) = unbounded();
|
let (sender, load_status_receiver) = unbounded();
|
||||||
ROUTER.route_ipc_receiver_to_crossbeam_sender(receiver, sender);
|
ROUTER.route_ipc_receiver_to_crossbeam_sender(receiver, sender);
|
||||||
|
|
||||||
let (constellation_sender, constellation_receiver) = ipc::channel().unwrap();
|
|
||||||
|
|
||||||
Handler {
|
Handler {
|
||||||
load_status_sender,
|
load_status_sender,
|
||||||
load_status_receiver,
|
load_status_receiver,
|
||||||
|
@ -493,8 +491,7 @@ impl Handler {
|
||||||
embedder_sender,
|
embedder_sender,
|
||||||
event_loop_waker,
|
event_loop_waker,
|
||||||
constellation_chan,
|
constellation_chan,
|
||||||
constellation_sender,
|
webdriver_response_receiver,
|
||||||
constellation_receiver,
|
|
||||||
id_generator: WebDriverMessageIdGenerator::new(),
|
id_generator: WebDriverMessageIdGenerator::new(),
|
||||||
current_action_id: Cell::new(None),
|
current_action_id: Cell::new(None),
|
||||||
num_pending_actions: Cell::new(0),
|
num_pending_actions: Cell::new(0),
|
||||||
|
@ -1836,9 +1833,7 @@ impl Handler {
|
||||||
sender,
|
sender,
|
||||||
);
|
);
|
||||||
let cmd_msg = WebDriverCommandMsg::ScriptCommand(browsing_context_id, cmd);
|
let cmd_msg = WebDriverCommandMsg::ScriptCommand(browsing_context_id, cmd);
|
||||||
self.constellation_chan
|
self.send_message_to_embedder(cmd_msg)?;
|
||||||
.send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// TODO: distinguish the not found and not focusable cases
|
// TODO: distinguish the not found and not focusable cases
|
||||||
// File input and non-typeable form control should have
|
// File input and non-typeable form control should have
|
||||||
|
@ -1853,9 +1848,7 @@ impl Handler {
|
||||||
// send keys command being two separate messages,
|
// send keys command being two separate messages,
|
||||||
// so the constellation may have changed state between them.
|
// so the constellation may have changed state between them.
|
||||||
let cmd_msg = WebDriverCommandMsg::SendKeys(browsing_context_id, input_events);
|
let cmd_msg = WebDriverCommandMsg::SendKeys(browsing_context_id, input_events);
|
||||||
self.constellation_chan
|
self.send_message_to_embedder(cmd_msg)?;
|
||||||
.send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
Ok(WebDriverResponse::Void)
|
Ok(WebDriverResponse::Void)
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@ euclid = { workspace = true }
|
||||||
getopts = { workspace = true }
|
getopts = { workspace = true }
|
||||||
hitrace = { workspace = true, optional = true }
|
hitrace = { workspace = true, optional = true }
|
||||||
image = { workspace = true }
|
image = { workspace = true }
|
||||||
|
ipc-channel = { workspace = true }
|
||||||
keyboard-types = { workspace = true }
|
keyboard-types = { workspace = true }
|
||||||
libc = { workspace = true }
|
libc = { workspace = true }
|
||||||
libservo = { path = "../../components/servo", features = ["background_hang_monitor", "bluetooth", "testbinding"] }
|
libservo = { path = "../../components/servo", features = ["background_hang_monitor", "bluetooth", "testbinding"] }
|
||||||
|
@ -78,7 +79,6 @@ webdriver_server = { path = "../../components/webdriver_server" }
|
||||||
|
|
||||||
[target.'cfg(target_os = "android")'.dependencies]
|
[target.'cfg(target_os = "android")'.dependencies]
|
||||||
android_logger = "0.15"
|
android_logger = "0.15"
|
||||||
ipc-channel = { workspace = true }
|
|
||||||
jni = "0.21.1"
|
jni = "0.21.1"
|
||||||
|
|
||||||
[target.'cfg(not(target_os = "android"))'.dependencies]
|
[target.'cfg(not(target_os = "android"))'.dependencies]
|
||||||
|
|
|
@ -12,14 +12,21 @@ use std::time::Instant;
|
||||||
use std::{env, fs};
|
use std::{env, fs};
|
||||||
|
|
||||||
use ::servo::ServoBuilder;
|
use ::servo::ServoBuilder;
|
||||||
|
use constellation_traits::EmbedderToConstellationMessage;
|
||||||
use crossbeam_channel::unbounded;
|
use crossbeam_channel::unbounded;
|
||||||
|
use euclid::{Point2D, Vector2D};
|
||||||
|
use ipc_channel::ipc;
|
||||||
use log::{info, trace, warn};
|
use log::{info, trace, warn};
|
||||||
use net::protocols::ProtocolRegistry;
|
use net::protocols::ProtocolRegistry;
|
||||||
use servo::config::opts::Opts;
|
use servo::config::opts::Opts;
|
||||||
use servo::config::prefs::Preferences;
|
use servo::config::prefs::Preferences;
|
||||||
use servo::servo_url::ServoUrl;
|
use servo::servo_url::ServoUrl;
|
||||||
use servo::user_content_manager::{UserContentManager, UserScript};
|
use servo::user_content_manager::{UserContentManager, UserScript};
|
||||||
use servo::{EventLoopWaker, WebDriverCommandMsg};
|
use servo::webrender_api::ScrollLocation;
|
||||||
|
use servo::{
|
||||||
|
EventLoopWaker, InputEvent, MouseButtonEvent, MouseMoveEvent, WebDriverCommandMsg, WheelDelta,
|
||||||
|
WheelEvent, WheelMode,
|
||||||
|
};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use winit::application::ApplicationHandler;
|
use winit::application::ApplicationHandler;
|
||||||
use winit::event::WindowEvent;
|
use winit::event::WindowEvent;
|
||||||
|
@ -162,15 +169,25 @@ impl App {
|
||||||
// Initialize WebDriver server here before `servo` is moved.
|
// Initialize WebDriver server here before `servo` is moved.
|
||||||
let webdriver_receiver = self.servoshell_preferences.webdriver_port.map(|port| {
|
let webdriver_receiver = self.servoshell_preferences.webdriver_port.map(|port| {
|
||||||
let (embedder_sender, embedder_receiver) = unbounded();
|
let (embedder_sender, embedder_receiver) = unbounded();
|
||||||
|
let (webdriver_response_sender, webdriver_response_receiver) = ipc::channel().unwrap();
|
||||||
|
|
||||||
|
// Set the WebDriver response sender to constellation.
|
||||||
|
// TODO: consider using Servo API to notify embedder about input events completions
|
||||||
|
servo
|
||||||
|
.constellation_sender()
|
||||||
|
.send(EmbedderToConstellationMessage::SetWebDriverResponseSender(
|
||||||
|
webdriver_response_sender,
|
||||||
|
))
|
||||||
|
.unwrap_or_else(|_| {
|
||||||
|
warn!("Failed to set WebDriver response sender in constellation");
|
||||||
|
});
|
||||||
|
|
||||||
// TODO: WebDriver will no longer need this channel once all WebDriver
|
|
||||||
// commands are executed via the Servo API.
|
|
||||||
let constellation_sender_deprecated = servo.constellation_sender();
|
|
||||||
webdriver_server::start_server(
|
webdriver_server::start_server(
|
||||||
port,
|
port,
|
||||||
constellation_sender_deprecated,
|
servo.constellation_sender(),
|
||||||
embedder_sender,
|
embedder_sender,
|
||||||
self.waker.clone(),
|
self.waker.clone(),
|
||||||
|
webdriver_response_receiver,
|
||||||
);
|
);
|
||||||
|
|
||||||
embedder_receiver
|
embedder_receiver
|
||||||
|
@ -331,6 +348,9 @@ impl App {
|
||||||
|
|
||||||
while let Ok(msg) = webdriver_receiver.try_recv() {
|
while let Ok(msg) = webdriver_receiver.try_recv() {
|
||||||
match msg {
|
match msg {
|
||||||
|
WebDriverCommandMsg::SetWebDriverResponseSender(..) => {
|
||||||
|
running_state.forward_webdriver_command(msg);
|
||||||
|
},
|
||||||
WebDriverCommandMsg::IsWebViewOpen(webview_id, sender) => {
|
WebDriverCommandMsg::IsWebViewOpen(webview_id, sender) => {
|
||||||
let context = running_state.webview_by_id(webview_id);
|
let context = running_state.webview_by_id(webview_id);
|
||||||
|
|
||||||
|
@ -338,8 +358,8 @@ impl App {
|
||||||
warn!("Failed to send response of IsWebViewOpein: {error}");
|
warn!("Failed to send response of IsWebViewOpein: {error}");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
webdriver_msg @ WebDriverCommandMsg::IsBrowsingContextOpen(..) => {
|
WebDriverCommandMsg::IsBrowsingContextOpen(..) => {
|
||||||
running_state.forward_webdriver_command(webdriver_msg);
|
running_state.forward_webdriver_command(msg);
|
||||||
},
|
},
|
||||||
WebDriverCommandMsg::NewWebView(response_sender, load_status_sender) => {
|
WebDriverCommandMsg::NewWebView(response_sender, load_status_sender) => {
|
||||||
let new_webview =
|
let new_webview =
|
||||||
|
@ -434,11 +454,68 @@ impl App {
|
||||||
webview.go_forward(1);
|
webview.go_forward(1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
WebDriverCommandMsg::SendKeys(..) |
|
// Key events don't need hit test so can be forwarded to constellation for now
|
||||||
WebDriverCommandMsg::KeyboardAction(..) |
|
WebDriverCommandMsg::SendKeys(..) => {
|
||||||
WebDriverCommandMsg::MouseButtonAction(..) |
|
running_state.forward_webdriver_command(msg);
|
||||||
WebDriverCommandMsg::MouseMoveAction(..) |
|
},
|
||||||
WebDriverCommandMsg::WheelScrollAction(..) |
|
WebDriverCommandMsg::KeyboardAction(..) => {
|
||||||
|
running_state.forward_webdriver_command(msg);
|
||||||
|
},
|
||||||
|
WebDriverCommandMsg::MouseButtonAction(
|
||||||
|
webview_id,
|
||||||
|
mouse_event_type,
|
||||||
|
mouse_button,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
webdriver_message_id,
|
||||||
|
) => {
|
||||||
|
if let Some(webview) = running_state.webview_by_id(webview_id) {
|
||||||
|
webview.notify_input_event(
|
||||||
|
InputEvent::MouseButton(MouseButtonEvent::new(
|
||||||
|
mouse_event_type,
|
||||||
|
mouse_button,
|
||||||
|
Point2D::new(x, y),
|
||||||
|
))
|
||||||
|
.with_webdriver_message_id(webdriver_message_id),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
WebDriverCommandMsg::MouseMoveAction(webview_id, x, y, webdriver_message_id) => {
|
||||||
|
if let Some(webview) = running_state.webview_by_id(webview_id) {
|
||||||
|
webview.notify_input_event(
|
||||||
|
InputEvent::MouseMove(MouseMoveEvent::new(Point2D::new(x, y)))
|
||||||
|
.with_webdriver_message_id(webdriver_message_id),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
WebDriverCommandMsg::WheelScrollAction(
|
||||||
|
webview_id,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
dx,
|
||||||
|
dy,
|
||||||
|
webdriver_message_id,
|
||||||
|
) => {
|
||||||
|
if let Some(webview) = running_state.webview_by_id(webview_id) {
|
||||||
|
let delta = WheelDelta {
|
||||||
|
x: -dx,
|
||||||
|
y: -dy,
|
||||||
|
z: 0.0,
|
||||||
|
mode: WheelMode::DeltaPixel,
|
||||||
|
};
|
||||||
|
|
||||||
|
let point = Point2D::new(x, y);
|
||||||
|
let scroll_location =
|
||||||
|
ScrollLocation::Delta(Vector2D::new(dx as f32, dy as f32));
|
||||||
|
|
||||||
|
webview.notify_input_event(
|
||||||
|
InputEvent::Wheel(WheelEvent::new(delta, point))
|
||||||
|
.with_webdriver_message_id(webdriver_message_id),
|
||||||
|
);
|
||||||
|
|
||||||
|
webview.notify_scroll_event(scroll_location, point.to_i32());
|
||||||
|
}
|
||||||
|
},
|
||||||
WebDriverCommandMsg::ScriptCommand(..) |
|
WebDriverCommandMsg::ScriptCommand(..) |
|
||||||
WebDriverCommandMsg::TakeScreenshot(..) => {
|
WebDriverCommandMsg::TakeScreenshot(..) => {
|
||||||
warn!(
|
warn!(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue