diff options
author | Martin Robinson <mrobinson@igalia.com> | 2025-02-24 14:57:28 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-02-24 13:57:28 +0000 |
commit | 606299563668b44f0a0b4593790324d776ffb2a5 (patch) | |
tree | 6eaaa9f112b3a7f758f79d48fd816bb3451d174d /components/shared/embedder/webdriver.rs | |
parent | 41c2422a662926ea4b4ccc3ba6c3fd7e071586f5 (diff) | |
download | servo-606299563668b44f0a0b4593790324d776ffb2a5.tar.gz servo-606299563668b44f0a0b4593790324d776ffb2a5.zip |
libservo: Move WebDriver messages to the `embedder` crate (#35602)
This is the first step toward moving the WebDriver implementation to
servoshell. This move will make it possible to start testing the
embedding API with WebDriver. See [this zulip thread][a] for more details.
While WebDriver will be able to use a lot of API commands to do what it
is doing now, there will still need to be some "cheat codes" for more
gnarly access to `ScriptThread` details. That's why we likely won't be
able to remove all WebDriver-specific messages from the API -- but maybe
they will be useful for embedders somehow.
A couple messages have to change as they depended on `script_traits`
types, particularly those that used `WindowSizeData` and `LoadData`. I
think this helps to encapsulate the WebDriver commands a bit more
though.
[a]: https://servo.zulipchat.com/#narrow/channel/437943-embedding/topic/webdriver.20as.20embedding.20api.20playgound
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Diffstat (limited to 'components/shared/embedder/webdriver.rs')
-rw-r--r-- | components/shared/embedder/webdriver.rs | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/components/shared/embedder/webdriver.rs b/components/shared/embedder/webdriver.rs new file mode 100644 index 00000000000..b312339c08a --- /dev/null +++ b/components/shared/embedder/webdriver.rs @@ -0,0 +1,191 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#![allow(missing_docs)] + +use std::collections::HashMap; + +use base::id::{BrowsingContextId, WebViewId}; +use cookie::Cookie; +use euclid::default::Rect as UntypedRect; +use euclid::{Rect, Size2D}; +use hyper_serde::Serde; +use ipc_channel::ipc::IpcSender; +use keyboard_types::webdriver::Event as WebDriverInputEvent; +use keyboard_types::KeyboardEvent; +use pixels::Image; +use serde::{Deserialize, Serialize}; +use servo_url::ServoUrl; +use style_traits::CSSPixel; +use webdriver::common::{WebElement, WebFrame, WebWindow}; +use webdriver::error::ErrorStatus; +use webrender_api::units::DeviceIntSize; + +use crate::{MouseButton, MouseButtonAction}; + +/// Messages to the constellation originating from the WebDriver server. +#[derive(Debug, Deserialize, Serialize)] +pub enum WebDriverCommandMsg { + /// Get the window size. + GetWindowSize(WebViewId, IpcSender<Size2D<f32, CSSPixel>>), + /// Load a URL in the top-level browsing context with the given ID. + LoadUrl(WebViewId, ServoUrl, IpcSender<WebDriverLoadStatus>), + /// Refresh the top-level browsing context with the given ID. + Refresh(WebViewId, IpcSender<WebDriverLoadStatus>), + /// Pass a webdriver command to the script thread of the current pipeline + /// of a browsing context. + ScriptCommand(BrowsingContextId, WebDriverScriptCommand), + /// Act as if keys were pressed in the browsing context with the given ID. + SendKeys(BrowsingContextId, Vec<WebDriverInputEvent>), + /// Act as if keys were pressed or release in the browsing context with the given ID. + KeyboardAction(BrowsingContextId, KeyboardEvent), + /// Act as if the mouse was clicked in the browsing context with the given ID. + MouseButtonAction(MouseButtonAction, MouseButton, f32, f32), + /// Act as if the mouse was moved in the browsing context with the given ID. + MouseMoveAction(f32, f32), + /// Set the window size. + SetWindowSize(WebViewId, DeviceIntSize, IpcSender<Size2D<f32, CSSPixel>>), + /// Take a screenshot of the window. + TakeScreenshot( + WebViewId, + Option<Rect<f32, CSSPixel>>, + IpcSender<Option<Image>>, + ), + /// Create a new webview that loads about:blank. The constellation will use + /// the provided channels to return the top level browsing context id + /// associated with the new webview, and a notification when the initial + /// load is complete. + NewWebView( + WebViewId, + IpcSender<WebViewId>, + IpcSender<WebDriverLoadStatus>, + ), + /// Close the webview associated with the provided id. + CloseWebView(WebViewId), + /// Focus the webview associated with the provided id. + FocusWebView(WebViewId), +} + +#[derive(Debug, Deserialize, Serialize)] +pub enum WebDriverScriptCommand { + AddCookie( + #[serde( + deserialize_with = "::hyper_serde::deserialize", + serialize_with = "::hyper_serde::serialize" + )] + Cookie<'static>, + IpcSender<Result<(), WebDriverCookieError>>, + ), + DeleteCookies(IpcSender<Result<(), ErrorStatus>>), + ExecuteScript(String, IpcSender<WebDriverJSResult>), + ExecuteAsyncScript(String, IpcSender<WebDriverJSResult>), + FindElementCSS(String, IpcSender<Result<Option<String>, ErrorStatus>>), + FindElementLinkText(String, bool, IpcSender<Result<Option<String>, ErrorStatus>>), + FindElementTagName(String, IpcSender<Result<Option<String>, ErrorStatus>>), + FindElementsCSS(String, IpcSender<Result<Vec<String>, ErrorStatus>>), + FindElementsLinkText(String, bool, IpcSender<Result<Vec<String>, ErrorStatus>>), + FindElementsTagName(String, IpcSender<Result<Vec<String>, ErrorStatus>>), + FindElementElementCSS( + String, + String, + IpcSender<Result<Option<String>, ErrorStatus>>, + ), + FindElementElementLinkText( + String, + String, + bool, + IpcSender<Result<Option<String>, ErrorStatus>>, + ), + FindElementElementTagName( + String, + String, + IpcSender<Result<Option<String>, ErrorStatus>>, + ), + FindElementElementsCSS(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>), + FindElementElementsLinkText( + String, + String, + bool, + IpcSender<Result<Vec<String>, ErrorStatus>>, + ), + FindElementElementsTagName(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>), + FocusElement(String, IpcSender<Result<(), ErrorStatus>>), + ElementClick(String, IpcSender<Result<Option<String>, ErrorStatus>>), + GetActiveElement(IpcSender<Option<String>>), + GetCookie(String, IpcSender<Vec<Serde<Cookie<'static>>>>), + GetCookies(IpcSender<Vec<Serde<Cookie<'static>>>>), + GetElementAttribute( + String, + String, + IpcSender<Result<Option<String>, ErrorStatus>>, + ), + GetElementProperty( + String, + String, + IpcSender<Result<WebDriverJSValue, ErrorStatus>>, + ), + GetElementCSS(String, String, IpcSender<Result<String, ErrorStatus>>), + GetElementRect(String, IpcSender<Result<UntypedRect<f64>, ErrorStatus>>), + GetElementTagName(String, IpcSender<Result<String, ErrorStatus>>), + GetElementText(String, IpcSender<Result<String, ErrorStatus>>), + GetElementInViewCenterPoint(String, IpcSender<Result<Option<(i64, i64)>, ErrorStatus>>), + GetBoundingClientRect(String, IpcSender<Result<UntypedRect<f32>, ErrorStatus>>), + GetBrowsingContextId( + WebDriverFrameId, + IpcSender<Result<BrowsingContextId, ErrorStatus>>, + ), + GetUrl(IpcSender<ServoUrl>), + GetPageSource(IpcSender<Result<String, ErrorStatus>>), + IsEnabled(String, IpcSender<Result<bool, ErrorStatus>>), + IsSelected(String, IpcSender<Result<bool, ErrorStatus>>), + GetTitle(IpcSender<String>), +} + +#[derive(Debug, Deserialize, Serialize)] +pub enum WebDriverCookieError { + InvalidDomain, + UnableToSetCookie, +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub enum WebDriverJSValue { + Undefined, + Null, + Boolean(bool), + Int(i32), + Number(f64), + String(String), + Element(WebElement), + Frame(WebFrame), + Window(WebWindow), + ArrayLike(Vec<WebDriverJSValue>), + Object(HashMap<String, WebDriverJSValue>), +} + +#[derive(Debug, Deserialize, Serialize)] +pub enum WebDriverJSError { + /// Occurs when handler received an event message for a layout channel that is not + /// associated with the current script thread + BrowsingContextNotFound, + JSError, + StaleElementReference, + Timeout, + UnknownType, +} + +pub type WebDriverJSResult = Result<WebDriverJSValue, WebDriverJSError>; + +#[derive(Debug, Deserialize, Serialize)] +pub enum WebDriverFrameId { + Short(u16), + Element(String), + Parent, +} + +#[derive(Debug, Deserialize, Serialize)] +pub enum WebDriverLoadStatus { + Complete, + Timeout, + Canceled, +} |