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