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 base::generic_channel::{GenericOneshotSender, GenericSender};
10use base::id::{BrowsingContextId, WebViewId};
11use cookie::Cookie;
12use crossbeam_channel::Sender;
13use euclid::default::Rect as UntypedRect;
14use euclid::{Rect, Size2D};
15use hyper_serde::Serde;
16use image::RgbaImage;
17use malloc_size_of_derive::MallocSizeOf;
18use rustc_hash::FxHashMap;
19use serde::{Deserialize, Serialize};
20use servo_geometry::DeviceIndependentIntRect;
21use style_traits::CSSPixel;
22use url::Url;
23use webdriver::error::ErrorStatus;
24use webrender_api::units::DevicePixel;
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(WebViewId, GenericOneshotSender<Size2D<u32, DevicePixel>>),
96    /// Load a URL in the top-level browsing context with the given ID.
97    LoadUrl(WebViewId, Url, GenericSender<WebDriverLoadStatus>),
98    /// Refresh the top-level browsing context with the given ID.
99    Refresh(WebViewId, GenericSender<WebDriverLoadStatus>),
100    /// Navigate the webview with the given ID to the previous page in the browsing context's history.
101    GoBack(WebViewId, GenericSender<WebDriverLoadStatus>),
102    /// Navigate the webview with the given ID to the next page in the browsing context's history.
103    GoForward(WebViewId, GenericSender<WebDriverLoadStatus>),
104    /// Pass a webdriver command to the script thread of the current pipeline
105    /// of a browsing context.
106    ScriptCommand(BrowsingContextId, WebDriverScriptCommand),
107    /// Dispatch an input event to the given [`WebView`]. Once the event has been handled in the
108    /// page DOM a single message should be sent through the [`Sender`], if provided, informing the
109    /// WebDriver server that the inpute event has been handled.
110    InputEvent(WebViewId, InputEvent, Option<Sender<()>>),
111    /// Set the outer window rectangle.
112    SetWindowRect(
113        WebViewId,
114        DeviceIndependentIntRect,
115        GenericOneshotSender<DeviceIndependentIntRect>,
116    ),
117    /// Maximize the window. Send back result window rectangle.
118    MaximizeWebView(WebViewId, GenericOneshotSender<DeviceIndependentIntRect>),
119    /// Take a screenshot of the viewport.
120    TakeScreenshot(
121        WebViewId,
122        Option<Rect<f32, CSSPixel>>,
123        Sender<Result<RgbaImage, ScreenshotCaptureError>>,
124    ),
125    /// Create a new webview that loads about:blank. The embedder will use
126    /// the provided channels to return the top level browsing context id
127    /// associated with the new webview, and sets a "load status sender" if provided.
128    NewWindow(
129        NewWindowTypeHint,
130        GenericOneshotSender<WebViewId>,
131        Option<GenericSender<WebDriverLoadStatus>>,
132    ),
133    /// Close the webview associated with the provided id.
134    CloseWebView(WebViewId, GenericOneshotSender<()>),
135    /// Focus the webview associated with the provided id.
136    FocusWebView(WebViewId),
137    /// Get focused webview. For now, this is only used when start new session.
138    GetFocusedWebView(GenericOneshotSender<Option<WebViewId>>),
139    /// Get webviews state
140    GetAllWebViews(GenericOneshotSender<Vec<WebViewId>>),
141    /// Check whether top-level browsing context is open.
142    IsWebViewOpen(WebViewId, GenericOneshotSender<bool>),
143    /// Check whether browsing context is open.
144    IsBrowsingContextOpen(BrowsingContextId, GenericOneshotSender<bool>),
145    CurrentUserPrompt(WebViewId, GenericOneshotSender<Option<WebDriverUserPrompt>>),
146    HandleUserPrompt(
147        WebViewId,
148        WebDriverUserPromptAction,
149        GenericOneshotSender<Result<String, ()>>,
150    ),
151    GetAlertText(WebViewId, GenericOneshotSender<Result<String, ()>>),
152    SendAlertText(WebViewId, String),
153    FocusBrowsingContext(BrowsingContextId),
154    Shutdown,
155    ResetAllCookies(Sender<()>),
156}
157
158#[derive(Debug, Deserialize, Serialize)]
159pub enum WebDriverScriptCommand {
160    AddCookie(
161        #[serde(
162            deserialize_with = "::hyper_serde::deserialize",
163            serialize_with = "::hyper_serde::serialize"
164        )]
165        Cookie<'static>,
166        GenericSender<Result<(), ErrorStatus>>,
167    ),
168    DeleteCookies(GenericSender<Result<(), ErrorStatus>>),
169    DeleteCookie(String, GenericSender<Result<(), ErrorStatus>>),
170    ElementClear(String, GenericSender<Result<(), ErrorStatus>>),
171    ExecuteScriptWithCallback(String, GenericSender<WebDriverJSResult>),
172    FindElementsCSSSelector(String, GenericSender<Result<Vec<String>, ErrorStatus>>),
173    FindElementsLinkText(
174        String,
175        bool,
176        GenericSender<Result<Vec<String>, ErrorStatus>>,
177    ),
178    FindElementsTagName(String, GenericSender<Result<Vec<String>, ErrorStatus>>),
179    FindElementsXpathSelector(String, GenericSender<Result<Vec<String>, ErrorStatus>>),
180    FindElementElementsCSSSelector(
181        String,
182        String,
183        GenericSender<Result<Vec<String>, ErrorStatus>>,
184    ),
185    FindElementElementsLinkText(
186        String,
187        String,
188        bool,
189        GenericSender<Result<Vec<String>, ErrorStatus>>,
190    ),
191    FindElementElementsTagName(
192        String,
193        String,
194        GenericSender<Result<Vec<String>, ErrorStatus>>,
195    ),
196    FindElementElementsXPathSelector(
197        String,
198        String,
199        GenericSender<Result<Vec<String>, ErrorStatus>>,
200    ),
201    FindShadowElementsCSSSelector(
202        String,
203        String,
204        GenericSender<Result<Vec<String>, ErrorStatus>>,
205    ),
206    FindShadowElementsLinkText(
207        String,
208        String,
209        bool,
210        GenericSender<Result<Vec<String>, ErrorStatus>>,
211    ),
212    FindShadowElementsTagName(
213        String,
214        String,
215        GenericSender<Result<Vec<String>, ErrorStatus>>,
216    ),
217    FindShadowElementsXPathSelector(
218        String,
219        String,
220        GenericSender<Result<Vec<String>, ErrorStatus>>,
221    ),
222    GetElementShadowRoot(String, GenericSender<Result<Option<String>, ErrorStatus>>),
223    ElementClick(String, GenericSender<Result<Option<String>, ErrorStatus>>),
224    GetKnownElement(String, GenericSender<Result<(), ErrorStatus>>),
225    GetKnownShadowRoot(String, GenericSender<Result<(), ErrorStatus>>),
226    GetKnownWindow(String, GenericSender<Result<(), ErrorStatus>>),
227    GetActiveElement(GenericSender<Option<String>>),
228    GetComputedRole(String, GenericSender<Result<Option<String>, ErrorStatus>>),
229    GetCookie(
230        String,
231        GenericSender<Result<Vec<Serde<Cookie<'static>>>, ErrorStatus>>,
232    ),
233    GetCookies(GenericSender<Result<Vec<Serde<Cookie<'static>>>, ErrorStatus>>),
234    GetElementAttribute(
235        String,
236        String,
237        GenericSender<Result<Option<String>, ErrorStatus>>,
238    ),
239    GetElementProperty(String, String, GenericSender<Result<JSValue, ErrorStatus>>),
240    GetElementCSS(String, String, GenericSender<Result<String, ErrorStatus>>),
241    GetElementRect(String, GenericSender<Result<UntypedRect<f64>, ErrorStatus>>),
242    GetElementTagName(String, GenericSender<Result<String, ErrorStatus>>),
243    GetElementText(String, GenericSender<Result<String, ErrorStatus>>),
244    GetElementInViewCenterPoint(
245        String,
246        GenericOneshotSender<Result<Option<(i64, i64)>, ErrorStatus>>,
247    ),
248    ScrollAndGetBoundingClientRect(String, GenericSender<Result<UntypedRect<f32>, ErrorStatus>>),
249    GetBrowsingContextId(
250        WebDriverFrameId,
251        GenericSender<Result<BrowsingContextId, ErrorStatus>>,
252    ),
253    GetParentFrameId(GenericSender<Result<BrowsingContextId, ErrorStatus>>),
254    GetUrl(GenericSender<String>),
255    GetPageSource(GenericSender<Result<String, ErrorStatus>>),
256    IsEnabled(String, GenericSender<Result<bool, ErrorStatus>>),
257    IsSelected(String, GenericSender<Result<bool, ErrorStatus>>),
258    GetTitle(GenericSender<String>),
259    /// Deal with the case of input element for Element Send Keys, which does not send keys.
260    WillSendKeys(
261        String,
262        String,
263        bool,
264        GenericSender<Result<bool, ErrorStatus>>,
265    ),
266    AddLoadStatusSender(WebViewId, GenericSender<WebDriverLoadStatus>),
267    RemoveLoadStatusSender(WebViewId),
268    SetProtocolHandlerAutomationMode(CustomHandlersAutomationMode),
269}
270
271pub type WebDriverJSResult = Result<JSValue, JavaScriptEvaluationError>;
272
273#[derive(Debug, Deserialize, Serialize)]
274pub enum WebDriverFrameId {
275    Short(u16),
276    Element(String),
277}
278
279#[derive(Debug, Deserialize, Serialize)]
280pub enum WebDriverLoadStatus {
281    NavigationStart,
282    // Navigation stops for any reason
283    NavigationStop,
284    // Document ready state is complete
285    Complete,
286    // Load timeout
287    Timeout,
288    // Navigation is blocked by a user prompt
289    Blocked,
290}
291
292/// A collection of [`GenericSender`]s that are used to asynchronously communicate
293/// to a WebDriver server with information about application state.
294#[derive(Clone, Default)]
295pub struct WebDriverSenders {
296    pub load_status_senders: FxHashMap<WebViewId, GenericSender<WebDriverLoadStatus>>,
297    pub script_evaluation_interrupt_sender: Option<GenericSender<WebDriverJSResult>>,
298    pub pending_traversals: HashMap<TraversalId, GenericSender<WebDriverLoadStatus>>,
299}