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::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 ipc_channel::ipc::IpcSender;
18use rustc_hash::FxHashMap;
19use serde::{Deserialize, Serialize};
20use servo_geometry::DeviceIndependentIntRect;
21use servo_url::ServoUrl;
22use style_traits::CSSPixel;
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/// Messages to the constellation originating from the WebDriver server.
73#[derive(Debug)]
74pub enum WebDriverCommandMsg {
75    /// Get the window rectangle.
76    GetWindowRect(WebViewId, IpcSender<DeviceIndependentIntRect>),
77    /// Get the viewport size.
78    GetViewportSize(WebViewId, IpcSender<Size2D<u32, DevicePixel>>),
79    /// Load a URL in the top-level browsing context with the given ID.
80    LoadUrl(WebViewId, ServoUrl, GenericSender<WebDriverLoadStatus>),
81    /// Refresh the top-level browsing context with the given ID.
82    Refresh(WebViewId, GenericSender<WebDriverLoadStatus>),
83    /// Navigate the webview with the given ID to the previous page in the browsing context's history.
84    GoBack(WebViewId, GenericSender<WebDriverLoadStatus>),
85    /// Navigate the webview with the given ID to the next page in the browsing context's history.
86    GoForward(WebViewId, GenericSender<WebDriverLoadStatus>),
87    /// Pass a webdriver command to the script thread of the current pipeline
88    /// of a browsing context.
89    ScriptCommand(BrowsingContextId, WebDriverScriptCommand),
90    /// Dispatch an input event to the given [`WebView`]. Once the event has been handled in the
91    /// page DOM a single message should be sent through the [`Sender`], if provided, informing the
92    /// WebDriver server that the inpute event has been handled.
93    InputEvent(WebViewId, InputEvent, Option<Sender<()>>),
94    /// Set the outer window rectangle.
95    SetWindowRect(
96        WebViewId,
97        DeviceIndependentIntRect,
98        IpcSender<DeviceIndependentIntRect>,
99    ),
100    /// Maximize the window. Send back result window rectangle.
101    MaximizeWebView(WebViewId, IpcSender<DeviceIndependentIntRect>),
102    /// Take a screenshot of the viewport.
103    TakeScreenshot(
104        WebViewId,
105        Option<Rect<f32, CSSPixel>>,
106        Sender<Result<RgbaImage, ScreenshotCaptureError>>,
107    ),
108    /// Create a new webview that loads about:blank. The embedder will use
109    /// the provided channels to return the top level browsing context id
110    /// associated with the new webview, and sets a "load status sender" if provided.
111    NewWebView(
112        IpcSender<WebViewId>,
113        Option<GenericSender<WebDriverLoadStatus>>,
114    ),
115    /// Close the webview associated with the provided id.
116    CloseWebView(WebViewId, IpcSender<()>),
117    /// Focus the webview associated with the provided id.
118    FocusWebView(WebViewId),
119    /// Get focused webview. For now, this is only used when start new session.
120    GetFocusedWebView(IpcSender<Option<WebViewId>>),
121    /// Get webviews state
122    GetAllWebViews(IpcSender<Vec<WebViewId>>),
123    /// Check whether top-level browsing context is open.
124    IsWebViewOpen(WebViewId, IpcSender<bool>),
125    /// Check whether browsing context is open.
126    IsBrowsingContextOpen(BrowsingContextId, IpcSender<bool>),
127    CurrentUserPrompt(WebViewId, IpcSender<Option<WebDriverUserPrompt>>),
128    HandleUserPrompt(
129        WebViewId,
130        WebDriverUserPromptAction,
131        IpcSender<Result<Option<String>, ()>>,
132    ),
133    GetAlertText(WebViewId, IpcSender<Result<String, ()>>),
134    SendAlertText(WebViewId, String),
135    FocusBrowsingContext(BrowsingContextId),
136}
137
138#[derive(Debug, Deserialize, Serialize)]
139pub enum WebDriverScriptCommand {
140    AddCookie(
141        #[serde(
142            deserialize_with = "::hyper_serde::deserialize",
143            serialize_with = "::hyper_serde::serialize"
144        )]
145        Cookie<'static>,
146        IpcSender<Result<(), ErrorStatus>>,
147    ),
148    DeleteCookies(IpcSender<Result<(), ErrorStatus>>),
149    DeleteCookie(String, IpcSender<Result<(), ErrorStatus>>),
150    ElementClear(String, IpcSender<Result<(), ErrorStatus>>),
151    ExecuteScript(String, IpcSender<WebDriverJSResult>),
152    ExecuteAsyncScript(String, IpcSender<WebDriverJSResult>),
153    FindElementsCSSSelector(String, IpcSender<Result<Vec<String>, ErrorStatus>>),
154    FindElementsLinkText(String, bool, IpcSender<Result<Vec<String>, ErrorStatus>>),
155    FindElementsTagName(String, IpcSender<Result<Vec<String>, ErrorStatus>>),
156    FindElementsXpathSelector(String, IpcSender<Result<Vec<String>, ErrorStatus>>),
157    FindElementElementsCSSSelector(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
158    FindElementElementsLinkText(
159        String,
160        String,
161        bool,
162        IpcSender<Result<Vec<String>, ErrorStatus>>,
163    ),
164    FindElementElementsTagName(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
165    FindElementElementsXPathSelector(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
166    FindShadowElementsCSSSelector(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
167    FindShadowElementsLinkText(
168        String,
169        String,
170        bool,
171        IpcSender<Result<Vec<String>, ErrorStatus>>,
172    ),
173    FindShadowElementsTagName(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
174    FindShadowElementsXPathSelector(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
175    GetElementShadowRoot(String, IpcSender<Result<Option<String>, ErrorStatus>>),
176    ElementClick(String, IpcSender<Result<Option<String>, ErrorStatus>>),
177    GetKnownElement(String, IpcSender<Result<(), ErrorStatus>>),
178    GetKnownShadowRoot(String, IpcSender<Result<(), ErrorStatus>>),
179    GetActiveElement(IpcSender<Option<String>>),
180    GetComputedRole(String, IpcSender<Result<Option<String>, ErrorStatus>>),
181    GetCookie(
182        String,
183        IpcSender<Result<Vec<Serde<Cookie<'static>>>, ErrorStatus>>,
184    ),
185    GetCookies(IpcSender<Result<Vec<Serde<Cookie<'static>>>, ErrorStatus>>),
186    GetElementAttribute(
187        String,
188        String,
189        IpcSender<Result<Option<String>, ErrorStatus>>,
190    ),
191    GetElementProperty(String, String, IpcSender<Result<JSValue, ErrorStatus>>),
192    GetElementCSS(String, String, IpcSender<Result<String, ErrorStatus>>),
193    GetElementRect(String, IpcSender<Result<UntypedRect<f64>, ErrorStatus>>),
194    GetElementTagName(String, IpcSender<Result<String, ErrorStatus>>),
195    GetElementText(String, IpcSender<Result<String, ErrorStatus>>),
196    GetElementInViewCenterPoint(String, IpcSender<Result<Option<(i64, i64)>, ErrorStatus>>),
197    ScrollAndGetBoundingClientRect(String, IpcSender<Result<UntypedRect<f32>, ErrorStatus>>),
198    GetBrowsingContextId(
199        WebDriverFrameId,
200        IpcSender<Result<BrowsingContextId, ErrorStatus>>,
201    ),
202    GetParentFrameId(IpcSender<Result<BrowsingContextId, ErrorStatus>>),
203    GetUrl(IpcSender<ServoUrl>),
204    GetPageSource(IpcSender<Result<String, ErrorStatus>>),
205    IsEnabled(String, IpcSender<Result<bool, ErrorStatus>>),
206    IsSelected(String, IpcSender<Result<bool, ErrorStatus>>),
207    GetTitle(IpcSender<String>),
208    /// Deal with the case of input element for Element Send Keys, which does not send keys.
209    WillSendKeys(String, String, bool, IpcSender<Result<bool, ErrorStatus>>),
210    AddLoadStatusSender(WebViewId, GenericSender<WebDriverLoadStatus>),
211    RemoveLoadStatusSender(WebViewId),
212}
213
214pub type WebDriverJSResult = Result<JSValue, JavaScriptEvaluationError>;
215
216#[derive(Debug, Deserialize, Serialize)]
217pub enum WebDriverFrameId {
218    Short(u16),
219    Element(String),
220}
221
222#[derive(Debug, Deserialize, Serialize)]
223pub enum WebDriverLoadStatus {
224    NavigationStart,
225    // Navigation stops for any reason
226    NavigationStop,
227    // Document ready state is complete
228    Complete,
229    // Load timeout
230    Timeout,
231    // Navigation is blocked by a user prompt
232    Blocked,
233}
234
235/// A collection of [`IpcSender`]s that are used to asynchronously communicate
236/// to a WebDriver server with information about application state.
237#[derive(Clone, Default)]
238pub struct WebDriverSenders {
239    pub load_status_senders: FxHashMap<WebViewId, GenericSender<WebDriverLoadStatus>>,
240    pub script_evaluation_interrupt_sender: Option<IpcSender<WebDriverJSResult>>,
241    pub pending_traversals: HashMap<TraversalId, GenericSender<WebDriverLoadStatus>>,
242}