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 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/// 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, Url, 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    Shutdown,
137}
138
139#[derive(Debug, Deserialize, Serialize)]
140pub enum WebDriverScriptCommand {
141    AddCookie(
142        #[serde(
143            deserialize_with = "::hyper_serde::deserialize",
144            serialize_with = "::hyper_serde::serialize"
145        )]
146        Cookie<'static>,
147        IpcSender<Result<(), ErrorStatus>>,
148    ),
149    DeleteCookies(IpcSender<Result<(), ErrorStatus>>),
150    DeleteCookie(String, IpcSender<Result<(), ErrorStatus>>),
151    ElementClear(String, IpcSender<Result<(), ErrorStatus>>),
152    ExecuteScript(String, IpcSender<WebDriverJSResult>),
153    ExecuteAsyncScript(String, IpcSender<WebDriverJSResult>),
154    FindElementsCSSSelector(String, IpcSender<Result<Vec<String>, ErrorStatus>>),
155    FindElementsLinkText(String, bool, IpcSender<Result<Vec<String>, ErrorStatus>>),
156    FindElementsTagName(String, IpcSender<Result<Vec<String>, ErrorStatus>>),
157    FindElementsXpathSelector(String, IpcSender<Result<Vec<String>, ErrorStatus>>),
158    FindElementElementsCSSSelector(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
159    FindElementElementsLinkText(
160        String,
161        String,
162        bool,
163        IpcSender<Result<Vec<String>, ErrorStatus>>,
164    ),
165    FindElementElementsTagName(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
166    FindElementElementsXPathSelector(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
167    FindShadowElementsCSSSelector(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
168    FindShadowElementsLinkText(
169        String,
170        String,
171        bool,
172        IpcSender<Result<Vec<String>, ErrorStatus>>,
173    ),
174    FindShadowElementsTagName(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
175    FindShadowElementsXPathSelector(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
176    GetElementShadowRoot(String, IpcSender<Result<Option<String>, ErrorStatus>>),
177    ElementClick(String, IpcSender<Result<Option<String>, ErrorStatus>>),
178    GetKnownElement(String, IpcSender<Result<(), ErrorStatus>>),
179    GetKnownShadowRoot(String, IpcSender<Result<(), ErrorStatus>>),
180    GetKnownWindow(String, IpcSender<Result<(), ErrorStatus>>),
181    GetActiveElement(IpcSender<Option<String>>),
182    GetComputedRole(String, IpcSender<Result<Option<String>, ErrorStatus>>),
183    GetCookie(
184        String,
185        IpcSender<Result<Vec<Serde<Cookie<'static>>>, ErrorStatus>>,
186    ),
187    GetCookies(IpcSender<Result<Vec<Serde<Cookie<'static>>>, ErrorStatus>>),
188    GetElementAttribute(
189        String,
190        String,
191        IpcSender<Result<Option<String>, ErrorStatus>>,
192    ),
193    GetElementProperty(String, String, IpcSender<Result<JSValue, ErrorStatus>>),
194    GetElementCSS(String, String, IpcSender<Result<String, ErrorStatus>>),
195    GetElementRect(String, IpcSender<Result<UntypedRect<f64>, ErrorStatus>>),
196    GetElementTagName(String, IpcSender<Result<String, ErrorStatus>>),
197    GetElementText(String, IpcSender<Result<String, ErrorStatus>>),
198    GetElementInViewCenterPoint(String, IpcSender<Result<Option<(i64, i64)>, ErrorStatus>>),
199    ScrollAndGetBoundingClientRect(String, IpcSender<Result<UntypedRect<f32>, ErrorStatus>>),
200    GetBrowsingContextId(
201        WebDriverFrameId,
202        IpcSender<Result<BrowsingContextId, ErrorStatus>>,
203    ),
204    GetParentFrameId(IpcSender<Result<BrowsingContextId, ErrorStatus>>),
205    GetUrl(IpcSender<String>),
206    GetPageSource(IpcSender<Result<String, ErrorStatus>>),
207    IsEnabled(String, IpcSender<Result<bool, ErrorStatus>>),
208    IsSelected(String, IpcSender<Result<bool, ErrorStatus>>),
209    GetTitle(IpcSender<String>),
210    /// Deal with the case of input element for Element Send Keys, which does not send keys.
211    WillSendKeys(String, String, bool, IpcSender<Result<bool, ErrorStatus>>),
212    AddLoadStatusSender(WebViewId, GenericSender<WebDriverLoadStatus>),
213    RemoveLoadStatusSender(WebViewId),
214}
215
216pub type WebDriverJSResult = Result<JSValue, JavaScriptEvaluationError>;
217
218#[derive(Debug, Deserialize, Serialize)]
219pub enum WebDriverFrameId {
220    Short(u16),
221    Element(String),
222}
223
224#[derive(Debug, Deserialize, Serialize)]
225pub enum WebDriverLoadStatus {
226    NavigationStart,
227    // Navigation stops for any reason
228    NavigationStop,
229    // Document ready state is complete
230    Complete,
231    // Load timeout
232    Timeout,
233    // Navigation is blocked by a user prompt
234    Blocked,
235}
236
237/// A collection of [`IpcSender`]s that are used to asynchronously communicate
238/// to a WebDriver server with information about application state.
239#[derive(Clone, Default)]
240pub struct WebDriverSenders {
241    pub load_status_senders: FxHashMap<WebViewId, GenericSender<WebDriverLoadStatus>>,
242    pub script_evaluation_interrupt_sender: Option<IpcSender<WebDriverJSResult>>,
243    pub pending_traversals: HashMap<TraversalId, GenericSender<WebDriverLoadStatus>>,
244}