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    /// Make the given WebView the WebView to use for input event interaction.
139    SelectWebViewForInteraction(WebViewId),
140    /// Get the WebView selected for user interaction. For now, this is only used when
141    /// starting new sessions.
142    GetWebViewSelectedForInteraction(GenericOneshotSender<Option<WebViewId>>),
143    /// Get webviews state
144    GetAllWebViews(GenericOneshotSender<Vec<WebViewId>>),
145    /// Check whether top-level browsing context is open.
146    IsWebViewOpen(WebViewId, GenericOneshotSender<bool>),
147    /// Check whether browsing context is open.
148    IsBrowsingContextOpen(BrowsingContextId, GenericOneshotSender<bool>),
149    CurrentUserPrompt(WebViewId, GenericOneshotSender<Option<WebDriverUserPrompt>>),
150    HandleUserPrompt(
151        WebViewId,
152        WebDriverUserPromptAction,
153        GenericOneshotSender<Result<String, ()>>,
154    ),
155    GetAlertText(WebViewId, GenericOneshotSender<Result<String, ()>>),
156    SendAlertText(WebViewId, String),
157    FocusBrowsingContext(BrowsingContextId),
158    Shutdown,
159    ResetAllCookies(Sender<()>),
160}
161
162#[derive(Debug, Deserialize, Serialize)]
163pub enum WebDriverScriptCommand {
164    AddCookie(
165        #[serde(
166            deserialize_with = "::hyper_serde::deserialize",
167            serialize_with = "::hyper_serde::serialize"
168        )]
169        Cookie<'static>,
170        GenericSender<Result<(), ErrorStatus>>,
171    ),
172    DeleteCookies(GenericSender<Result<(), ErrorStatus>>),
173    DeleteCookie(String, GenericSender<Result<(), ErrorStatus>>),
174    ElementClear(String, GenericSender<Result<(), ErrorStatus>>),
175    ExecuteScriptWithCallback(String, GenericSender<WebDriverJSResult>),
176    FindElementsCSSSelector(String, GenericSender<Result<Vec<String>, ErrorStatus>>),
177    FindElementsLinkText(
178        String,
179        bool,
180        GenericSender<Result<Vec<String>, ErrorStatus>>,
181    ),
182    FindElementsTagName(String, GenericSender<Result<Vec<String>, ErrorStatus>>),
183    FindElementsXpathSelector(String, GenericSender<Result<Vec<String>, ErrorStatus>>),
184    FindElementElementsCSSSelector(
185        String,
186        String,
187        GenericSender<Result<Vec<String>, ErrorStatus>>,
188    ),
189    FindElementElementsLinkText(
190        String,
191        String,
192        bool,
193        GenericSender<Result<Vec<String>, ErrorStatus>>,
194    ),
195    FindElementElementsTagName(
196        String,
197        String,
198        GenericSender<Result<Vec<String>, ErrorStatus>>,
199    ),
200    FindElementElementsXPathSelector(
201        String,
202        String,
203        GenericSender<Result<Vec<String>, ErrorStatus>>,
204    ),
205    FindShadowElementsCSSSelector(
206        String,
207        String,
208        GenericSender<Result<Vec<String>, ErrorStatus>>,
209    ),
210    FindShadowElementsLinkText(
211        String,
212        String,
213        bool,
214        GenericSender<Result<Vec<String>, ErrorStatus>>,
215    ),
216    FindShadowElementsTagName(
217        String,
218        String,
219        GenericSender<Result<Vec<String>, ErrorStatus>>,
220    ),
221    FindShadowElementsXPathSelector(
222        String,
223        String,
224        GenericSender<Result<Vec<String>, ErrorStatus>>,
225    ),
226    GetElementShadowRoot(String, GenericSender<Result<Option<String>, ErrorStatus>>),
227    ElementClick(String, GenericSender<Result<Option<String>, ErrorStatus>>),
228    GetKnownElement(String, GenericSender<Result<(), ErrorStatus>>),
229    GetKnownShadowRoot(String, GenericSender<Result<(), ErrorStatus>>),
230    GetKnownWindow(String, GenericSender<Result<(), ErrorStatus>>),
231    GetActiveElement(GenericSender<Option<String>>),
232    GetComputedRole(String, GenericSender<Result<Option<String>, ErrorStatus>>),
233    GetCookie(
234        String,
235        GenericSender<Result<Vec<Serde<Cookie<'static>>>, ErrorStatus>>,
236    ),
237    GetCookies(GenericSender<Result<Vec<Serde<Cookie<'static>>>, ErrorStatus>>),
238    GetElementAttribute(
239        String,
240        String,
241        GenericSender<Result<Option<String>, ErrorStatus>>,
242    ),
243    GetElementProperty(String, String, GenericSender<Result<JSValue, ErrorStatus>>),
244    GetElementCSS(String, String, GenericSender<Result<String, ErrorStatus>>),
245    GetElementRect(String, GenericSender<Result<UntypedRect<f64>, ErrorStatus>>),
246    GetElementTagName(String, GenericSender<Result<String, ErrorStatus>>),
247    GetElementText(String, GenericSender<Result<String, ErrorStatus>>),
248    GetElementInViewCenterPoint(
249        String,
250        GenericOneshotSender<Result<Option<(i64, i64)>, ErrorStatus>>,
251    ),
252    ScrollAndGetBoundingClientRect(String, GenericSender<Result<UntypedRect<f32>, ErrorStatus>>),
253    GetBrowsingContextId(
254        WebDriverFrameId,
255        GenericSender<Result<BrowsingContextId, ErrorStatus>>,
256    ),
257    GetParentFrameId(GenericSender<Result<BrowsingContextId, ErrorStatus>>),
258    GetUrl(GenericSender<String>),
259    GetPageSource(GenericSender<Result<String, ErrorStatus>>),
260    IsEnabled(String, GenericSender<Result<bool, ErrorStatus>>),
261    IsSelected(String, GenericSender<Result<bool, ErrorStatus>>),
262    GetTitle(GenericSender<String>),
263    /// Deal with the case of input element for Element Send Keys, which does not send keys.
264    WillSendKeys(
265        String,
266        String,
267        bool,
268        GenericSender<Result<bool, ErrorStatus>>,
269    ),
270    AddLoadStatusSender(WebViewId, GenericSender<WebDriverLoadStatus>),
271    RemoveLoadStatusSender(WebViewId),
272    SetProtocolHandlerAutomationMode(CustomHandlersAutomationMode),
273    SetPermission(
274        String,
275        SetPermissionState,
276        GenericOneshotSender<Result<(), ErrorStatus>>,
277    ),
278}
279
280pub type WebDriverJSResult = Result<JSValue, JavaScriptEvaluationError>;
281
282#[derive(Debug, Deserialize, Serialize)]
283pub enum WebDriverFrameId {
284    Short(u16),
285    Element(String),
286}
287
288#[derive(Debug, Deserialize, Serialize)]
289pub enum WebDriverLoadStatus {
290    NavigationStart,
291    // Navigation stops for any reason
292    NavigationStop,
293    // Document ready state is complete
294    Complete,
295    // Load timeout
296    Timeout,
297    // Navigation is blocked by a user prompt
298    Blocked,
299}
300
301/// A collection of [`GenericSender`]s that are used to asynchronously communicate
302/// to a WebDriver server with information about application state.
303#[derive(Clone, Default)]
304pub struct WebDriverSenders {
305    pub load_status_senders: FxHashMap<WebViewId, GenericSender<WebDriverLoadStatus>>,
306    pub script_evaluation_interrupt_sender: Option<GenericSender<WebDriverJSResult>>,
307    pub pending_traversals: HashMap<TraversalId, GenericSender<WebDriverLoadStatus>>,
308}