Skip to main content

embedder_traits/
webdriver.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5#![allow(missing_docs)]
6
7use std::collections::HashMap;
8
9use cookie::Cookie;
10use crossbeam_channel::Sender;
11use euclid::default::Rect as UntypedRect;
12use euclid::{Rect, Size2D};
13use hyper_serde::Serde;
14use image::RgbaImage;
15use malloc_size_of_derive::MallocSizeOf;
16use rustc_hash::FxHashMap;
17use serde::{Deserialize, Serialize};
18use servo_base::generic_channel::{GenericOneshotSender, GenericSender};
19use servo_base::id::{BrowsingContextId, WebViewId};
20use servo_geometry::{DeviceIndependentIntRect, DeviceIndependentPixel};
21use style_traits::CSSPixel;
22use url::Url;
23use webdriver::command::SetPermissionState;
24use webdriver::error::ErrorStatus;
25
26use crate::{InputEvent, JSValue, JavaScriptEvaluationError, ScreenshotCaptureError, TraversalId};
27
28#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
29pub enum WebDriverUserPrompt {
30    Alert,
31    BeforeUnload,
32    Confirm,
33    Default,
34    File,
35    Prompt,
36    FallbackDefault,
37}
38
39impl WebDriverUserPrompt {
40    pub fn new_from_str(s: &str) -> Option<Self> {
41        match s {
42            "alert" => Some(WebDriverUserPrompt::Alert),
43            "beforeUnload" => Some(WebDriverUserPrompt::BeforeUnload),
44            "confirm" => Some(WebDriverUserPrompt::Confirm),
45            "default" => Some(WebDriverUserPrompt::Default),
46            "file" => Some(WebDriverUserPrompt::File),
47            "prompt" => Some(WebDriverUserPrompt::Prompt),
48            "fallbackDefault" => Some(WebDriverUserPrompt::FallbackDefault),
49            _ => None,
50        }
51    }
52}
53
54#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
55pub enum WebDriverUserPromptAction {
56    Accept,
57    Dismiss,
58    Ignore,
59}
60
61impl WebDriverUserPromptAction {
62    pub fn new_from_str(s: &str) -> Option<Self> {
63        match s {
64            "accept" => Some(WebDriverUserPromptAction::Accept),
65            "dismiss" => Some(WebDriverUserPromptAction::Dismiss),
66            "ignore" => Some(WebDriverUserPromptAction::Ignore),
67            _ => None,
68        }
69    }
70}
71
72/// <https://html.spec.whatwg.org/multipage/#registerprotocolhandler()-automation-mode>
73#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)]
74pub enum CustomHandlersAutomationMode {
75    AutoAccept,
76    AutoReject,
77    #[default]
78    None,
79}
80
81/// <https://w3c.github.io/webdriver/#new-window>
82#[derive(Clone, Copy, Debug, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)]
83pub enum NewWindowTypeHint {
84    Auto,
85    Tab,
86    Window,
87}
88
89/// Messages to the constellation originating from the WebDriver server.
90#[derive(Debug)]
91pub enum WebDriverCommandMsg {
92    /// Get the window rectangle.
93    GetWindowRect(WebViewId, GenericOneshotSender<DeviceIndependentIntRect>),
94    /// Get the viewport size.
95    GetViewportSize(
96        WebViewId,
97        GenericOneshotSender<Size2D<f32, DeviceIndependentPixel>>,
98    ),
99    /// Load a URL in the top-level browsing context with the given ID.
100    LoadUrl(WebViewId, Url, GenericSender<WebDriverLoadStatus>),
101    /// Refresh the top-level browsing context with the given ID.
102    Refresh(WebViewId, GenericSender<WebDriverLoadStatus>),
103    /// Navigate the webview with the given ID to the previous page in the browsing context's history.
104    GoBack(WebViewId, GenericSender<WebDriverLoadStatus>),
105    /// Navigate the webview with the given ID to the next page in the browsing context's history.
106    GoForward(WebViewId, GenericSender<WebDriverLoadStatus>),
107    /// Pass a webdriver command to the script thread of the current pipeline
108    /// of a browsing context.
109    ScriptCommand(BrowsingContextId, WebDriverScriptCommand),
110    /// Dispatch an input event to the given [`WebView`]. Once the event has been handled in the
111    /// page DOM a single message should be sent through the [`Sender`], if provided, informing the
112    /// WebDriver server that the inpute event has been handled.
113    InputEvent(WebViewId, InputEvent, Option<Sender<()>>),
114    /// Set the outer window rectangle.
115    SetWindowRect(
116        WebViewId,
117        DeviceIndependentIntRect,
118        GenericOneshotSender<DeviceIndependentIntRect>,
119    ),
120    /// Maximize the window. Send back result window rectangle.
121    MaximizeWebView(WebViewId, GenericOneshotSender<DeviceIndependentIntRect>),
122    /// Take a screenshot of the viewport.
123    TakeScreenshot(
124        WebViewId,
125        Option<Rect<f32, CSSPixel>>,
126        Sender<Result<RgbaImage, ScreenshotCaptureError>>,
127    ),
128    /// Create a new webview that loads about:blank. The embedder will use
129    /// the provided channels to return the top level browsing context id
130    /// associated with the new webview, and sets a "load status sender" if provided.
131    NewWindow(
132        NewWindowTypeHint,
133        GenericOneshotSender<WebViewId>,
134        Option<GenericSender<WebDriverLoadStatus>>,
135    ),
136    /// Close the webview associated with the provided id.
137    CloseWebView(WebViewId, GenericOneshotSender<()>),
138    /// Focus the webview associated with the provided id.
139    FocusWebView(WebViewId),
140    /// Get focused webview. For now, this is only used when start new session.
141    GetFocusedWebView(GenericOneshotSender<Option<WebViewId>>),
142    /// Get webviews state
143    GetAllWebViews(GenericOneshotSender<Vec<WebViewId>>),
144    /// Check whether top-level browsing context is open.
145    IsWebViewOpen(WebViewId, GenericOneshotSender<bool>),
146    /// Check whether browsing context is open.
147    IsBrowsingContextOpen(BrowsingContextId, GenericOneshotSender<bool>),
148    CurrentUserPrompt(WebViewId, GenericOneshotSender<Option<WebDriverUserPrompt>>),
149    HandleUserPrompt(
150        WebViewId,
151        WebDriverUserPromptAction,
152        GenericOneshotSender<Result<String, ()>>,
153    ),
154    GetAlertText(WebViewId, GenericOneshotSender<Result<String, ()>>),
155    SendAlertText(WebViewId, String),
156    FocusBrowsingContext(BrowsingContextId),
157    Shutdown,
158    ResetAllCookies(Sender<()>),
159}
160
161#[derive(Debug, Deserialize, Serialize)]
162pub enum WebDriverScriptCommand {
163    AddCookie(
164        #[serde(
165            deserialize_with = "::hyper_serde::deserialize",
166            serialize_with = "::hyper_serde::serialize"
167        )]
168        Cookie<'static>,
169        GenericSender<Result<(), ErrorStatus>>,
170    ),
171    DeleteCookies(GenericSender<Result<(), ErrorStatus>>),
172    DeleteCookie(String, GenericSender<Result<(), ErrorStatus>>),
173    ElementClear(String, GenericSender<Result<(), ErrorStatus>>),
174    ExecuteScriptWithCallback(String, GenericSender<WebDriverJSResult>),
175    FindElementsCSSSelector(String, GenericSender<Result<Vec<String>, ErrorStatus>>),
176    FindElementsLinkText(
177        String,
178        bool,
179        GenericSender<Result<Vec<String>, ErrorStatus>>,
180    ),
181    FindElementsTagName(String, GenericSender<Result<Vec<String>, ErrorStatus>>),
182    FindElementsXpathSelector(String, GenericSender<Result<Vec<String>, ErrorStatus>>),
183    FindElementElementsCSSSelector(
184        String,
185        String,
186        GenericSender<Result<Vec<String>, ErrorStatus>>,
187    ),
188    FindElementElementsLinkText(
189        String,
190        String,
191        bool,
192        GenericSender<Result<Vec<String>, ErrorStatus>>,
193    ),
194    FindElementElementsTagName(
195        String,
196        String,
197        GenericSender<Result<Vec<String>, ErrorStatus>>,
198    ),
199    FindElementElementsXPathSelector(
200        String,
201        String,
202        GenericSender<Result<Vec<String>, ErrorStatus>>,
203    ),
204    FindShadowElementsCSSSelector(
205        String,
206        String,
207        GenericSender<Result<Vec<String>, ErrorStatus>>,
208    ),
209    FindShadowElementsLinkText(
210        String,
211        String,
212        bool,
213        GenericSender<Result<Vec<String>, ErrorStatus>>,
214    ),
215    FindShadowElementsTagName(
216        String,
217        String,
218        GenericSender<Result<Vec<String>, ErrorStatus>>,
219    ),
220    FindShadowElementsXPathSelector(
221        String,
222        String,
223        GenericSender<Result<Vec<String>, ErrorStatus>>,
224    ),
225    GetElementShadowRoot(String, GenericSender<Result<Option<String>, ErrorStatus>>),
226    ElementClick(String, GenericSender<Result<Option<String>, ErrorStatus>>),
227    GetKnownElement(String, GenericSender<Result<(), ErrorStatus>>),
228    GetKnownShadowRoot(String, GenericSender<Result<(), ErrorStatus>>),
229    GetKnownWindow(String, GenericSender<Result<(), ErrorStatus>>),
230    GetActiveElement(GenericSender<Option<String>>),
231    GetComputedRole(String, GenericSender<Result<Option<String>, ErrorStatus>>),
232    GetCookie(
233        String,
234        GenericSender<Result<Vec<Serde<Cookie<'static>>>, ErrorStatus>>,
235    ),
236    GetCookies(GenericSender<Result<Vec<Serde<Cookie<'static>>>, ErrorStatus>>),
237    GetElementAttribute(
238        String,
239        String,
240        GenericSender<Result<Option<String>, ErrorStatus>>,
241    ),
242    GetElementProperty(String, String, GenericSender<Result<JSValue, ErrorStatus>>),
243    GetElementCSS(String, String, GenericSender<Result<String, ErrorStatus>>),
244    GetElementRect(String, GenericSender<Result<UntypedRect<f64>, ErrorStatus>>),
245    GetElementTagName(String, GenericSender<Result<String, ErrorStatus>>),
246    GetElementText(String, GenericSender<Result<String, ErrorStatus>>),
247    GetElementInViewCenterPoint(
248        String,
249        GenericOneshotSender<Result<Option<(i64, i64)>, ErrorStatus>>,
250    ),
251    ScrollAndGetBoundingClientRect(String, GenericSender<Result<UntypedRect<f32>, ErrorStatus>>),
252    GetBrowsingContextId(
253        WebDriverFrameId,
254        GenericSender<Result<BrowsingContextId, ErrorStatus>>,
255    ),
256    GetParentFrameId(GenericSender<Result<BrowsingContextId, ErrorStatus>>),
257    GetUrl(GenericSender<String>),
258    GetPageSource(GenericSender<Result<String, ErrorStatus>>),
259    IsEnabled(String, GenericSender<Result<bool, ErrorStatus>>),
260    IsSelected(String, GenericSender<Result<bool, ErrorStatus>>),
261    GetTitle(GenericSender<String>),
262    /// Deal with the case of input element for Element Send Keys, which does not send keys.
263    WillSendKeys(
264        String,
265        String,
266        bool,
267        GenericSender<Result<bool, ErrorStatus>>,
268    ),
269    AddLoadStatusSender(WebViewId, GenericSender<WebDriverLoadStatus>),
270    RemoveLoadStatusSender(WebViewId),
271    SetProtocolHandlerAutomationMode(CustomHandlersAutomationMode),
272    SetPermission(
273        String,
274        SetPermissionState,
275        GenericOneshotSender<Result<(), ErrorStatus>>,
276    ),
277}
278
279pub type WebDriverJSResult = Result<JSValue, JavaScriptEvaluationError>;
280
281#[derive(Debug, Deserialize, Serialize)]
282pub enum WebDriverFrameId {
283    Short(u16),
284    Element(String),
285}
286
287#[derive(Debug, Deserialize, Serialize)]
288pub enum WebDriverLoadStatus {
289    NavigationStart,
290    // Navigation stops for any reason
291    NavigationStop,
292    // Document ready state is complete
293    Complete,
294    // Load timeout
295    Timeout,
296    // Navigation is blocked by a user prompt
297    Blocked,
298}
299
300/// A collection of [`GenericSender`]s that are used to asynchronously communicate
301/// to a WebDriver server with information about application state.
302#[derive(Clone, Default)]
303pub struct WebDriverSenders {
304    pub load_status_senders: FxHashMap<WebViewId, GenericSender<WebDriverLoadStatus>>,
305    pub script_evaluation_interrupt_sender: Option<GenericSender<WebDriverJSResult>>,
306    pub pending_traversals: HashMap<TraversalId, GenericSender<WebDriverLoadStatus>>,
307}