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 euclid::default::Rect as UntypedRect;
13use euclid::{Rect, Size2D};
14use hyper_serde::Serde;
15use ipc_channel::ipc::IpcSender;
16use keyboard_types::{CompositionEvent, KeyboardEvent};
17use pixels::RasterImage;
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::{JSValue, MouseButton, MouseButtonAction, TraversalId};
27
28#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
29pub struct WebDriverMessageId(pub usize);
30
31#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
32pub enum WebDriverUserPrompt {
33    Alert,
34    BeforeUnload,
35    Confirm,
36    Default,
37    File,
38    Prompt,
39    FallbackDefault,
40}
41
42impl WebDriverUserPrompt {
43    pub fn new_from_str(s: &str) -> Option<Self> {
44        match s {
45            "alert" => Some(WebDriverUserPrompt::Alert),
46            "beforeUnload" => Some(WebDriverUserPrompt::BeforeUnload),
47            "confirm" => Some(WebDriverUserPrompt::Confirm),
48            "default" => Some(WebDriverUserPrompt::Default),
49            "file" => Some(WebDriverUserPrompt::File),
50            "prompt" => Some(WebDriverUserPrompt::Prompt),
51            "fallbackDefault" => Some(WebDriverUserPrompt::FallbackDefault),
52            _ => None,
53        }
54    }
55}
56
57#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
58pub enum WebDriverUserPromptAction {
59    Accept,
60    Dismiss,
61    Ignore,
62}
63
64impl WebDriverUserPromptAction {
65    pub fn new_from_str(s: &str) -> Option<Self> {
66        match s {
67            "accept" => Some(WebDriverUserPromptAction::Accept),
68            "dismiss" => Some(WebDriverUserPromptAction::Dismiss),
69            "ignore" => Some(WebDriverUserPromptAction::Ignore),
70            _ => None,
71        }
72    }
73}
74
75/// Messages to the constellation originating from the WebDriver server.
76#[derive(Debug, Deserialize, Serialize)]
77pub enum WebDriverCommandMsg {
78    /// Used in the initialization of the WebDriver server to set the sender for sending responses
79    /// back to the WebDriver client. It is set to constellation for now
80    SetWebDriverResponseSender(IpcSender<WebDriverCommandResponse>),
81    /// Get the window rectangle.
82    GetWindowRect(WebViewId, IpcSender<DeviceIndependentIntRect>),
83    /// Get the viewport size.
84    GetViewportSize(WebViewId, IpcSender<Size2D<u32, DevicePixel>>),
85    /// Load a URL in the top-level browsing context with the given ID.
86    LoadUrl(WebViewId, ServoUrl, GenericSender<WebDriverLoadStatus>),
87    /// Refresh the top-level browsing context with the given ID.
88    Refresh(WebViewId, GenericSender<WebDriverLoadStatus>),
89    /// Navigate the webview with the given ID to the previous page in the browsing context's history.
90    GoBack(WebViewId, GenericSender<WebDriverLoadStatus>),
91    /// Navigate the webview with the given ID to the next page in the browsing context's history.
92    GoForward(WebViewId, GenericSender<WebDriverLoadStatus>),
93    /// Pass a webdriver command to the script thread of the current pipeline
94    /// of a browsing context.
95    ScriptCommand(BrowsingContextId, WebDriverScriptCommand),
96    /// Dispatch composition event from element send keys command.
97    DispatchComposition(WebViewId, CompositionEvent),
98    /// Act as if keys were pressed or release in the browsing context with the given ID.
99    KeyboardAction(
100        WebViewId,
101        KeyboardEvent,
102        // Should never be None.
103        Option<WebDriverMessageId>,
104    ),
105    /// Act as if the mouse was clicked in the browsing context with the given ID.
106    MouseButtonAction(
107        WebViewId,
108        MouseButtonAction,
109        MouseButton,
110        f32,
111        f32,
112        // Should never be None.
113        Option<WebDriverMessageId>,
114    ),
115    /// Act as if the mouse was moved in the browsing context with the given ID.
116    MouseMoveAction(
117        WebViewId,
118        f32,
119        f32,
120        // None if it's not the last `perform_pointer_move` since we only
121        // expect one response from constellation for each tick actions.
122        Option<WebDriverMessageId>,
123    ),
124    /// Act as if the mouse wheel is scrolled in the browsing context given the given ID.
125    WheelScrollAction(
126        WebViewId,
127        f64,
128        f64,
129        f64,
130        f64,
131        // None if it's not the last `perform_wheel_scroll` since we only
132        // expect one response from constellation for each tick actions.
133        Option<WebDriverMessageId>,
134    ),
135    /// Set the outer window rectangle.
136    SetWindowRect(
137        WebViewId,
138        DeviceIndependentIntRect,
139        IpcSender<DeviceIndependentIntRect>,
140    ),
141    /// Maximize the window. Send back result window rectangle.
142    MaximizeWebView(WebViewId, IpcSender<DeviceIndependentIntRect>),
143    /// Take a screenshot of the viewport.
144    TakeScreenshot(
145        WebViewId,
146        Option<Rect<f32, CSSPixel>>,
147        IpcSender<Option<RasterImage>>,
148    ),
149    /// Create a new webview that loads about:blank. The embedder will use
150    /// the provided channels to return the top level browsing context id
151    /// associated with the new webview, and sets a "load status sender" if provided.
152    NewWebView(
153        IpcSender<WebViewId>,
154        Option<GenericSender<WebDriverLoadStatus>>,
155    ),
156    /// Close the webview associated with the provided id.
157    CloseWebView(WebViewId, IpcSender<()>),
158    /// Focus the webview associated with the provided id.
159    FocusWebView(WebViewId),
160    /// Get focused webview. For now, this is only used when start new session.
161    GetFocusedWebView(IpcSender<Option<WebViewId>>),
162    /// Get webviews state
163    GetAllWebViews(IpcSender<Vec<WebViewId>>),
164    /// Check whether top-level browsing context is open.
165    IsWebViewOpen(WebViewId, IpcSender<bool>),
166    /// Check whether browsing context is open.
167    IsBrowsingContextOpen(BrowsingContextId, IpcSender<bool>),
168    CurrentUserPrompt(WebViewId, IpcSender<Option<WebDriverUserPrompt>>),
169    HandleUserPrompt(
170        WebViewId,
171        WebDriverUserPromptAction,
172        IpcSender<Result<Option<String>, ()>>,
173    ),
174    GetAlertText(WebViewId, IpcSender<Result<String, ()>>),
175    SendAlertText(WebViewId, String),
176    FocusBrowsingContext(BrowsingContextId),
177}
178
179#[derive(Debug, Deserialize, Serialize)]
180pub enum WebDriverScriptCommand {
181    AddCookie(
182        #[serde(
183            deserialize_with = "::hyper_serde::deserialize",
184            serialize_with = "::hyper_serde::serialize"
185        )]
186        Cookie<'static>,
187        IpcSender<Result<(), ErrorStatus>>,
188    ),
189    DeleteCookies(IpcSender<Result<(), ErrorStatus>>),
190    DeleteCookie(String, IpcSender<Result<(), ErrorStatus>>),
191    ElementClear(String, IpcSender<Result<(), ErrorStatus>>),
192    ExecuteScript(String, IpcSender<WebDriverJSResult>),
193    ExecuteAsyncScript(String, IpcSender<WebDriverJSResult>),
194    FindElementsCSSSelector(String, IpcSender<Result<Vec<String>, ErrorStatus>>),
195    FindElementsLinkText(String, bool, IpcSender<Result<Vec<String>, ErrorStatus>>),
196    FindElementsTagName(String, IpcSender<Result<Vec<String>, ErrorStatus>>),
197    FindElementsXpathSelector(String, IpcSender<Result<Vec<String>, ErrorStatus>>),
198    FindElementElementsCSSSelector(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
199    FindElementElementsLinkText(
200        String,
201        String,
202        bool,
203        IpcSender<Result<Vec<String>, ErrorStatus>>,
204    ),
205    FindElementElementsTagName(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
206    FindElementElementsXPathSelector(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
207    FindShadowElementsCSSSelector(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
208    FindShadowElementsLinkText(
209        String,
210        String,
211        bool,
212        IpcSender<Result<Vec<String>, ErrorStatus>>,
213    ),
214    FindShadowElementsTagName(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
215    FindShadowElementsXPathSelector(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
216    GetElementShadowRoot(String, IpcSender<Result<Option<String>, ErrorStatus>>),
217    ElementClick(String, IpcSender<Result<Option<String>, ErrorStatus>>),
218    GetKnownElement(String, IpcSender<Result<(), ErrorStatus>>),
219    GetKnownShadowRoot(String, IpcSender<Result<(), ErrorStatus>>),
220    GetActiveElement(IpcSender<Option<String>>),
221    GetComputedRole(String, IpcSender<Result<Option<String>, ErrorStatus>>),
222    GetCookie(
223        String,
224        IpcSender<Result<Vec<Serde<Cookie<'static>>>, ErrorStatus>>,
225    ),
226    GetCookies(IpcSender<Result<Vec<Serde<Cookie<'static>>>, ErrorStatus>>),
227    GetElementAttribute(
228        String,
229        String,
230        IpcSender<Result<Option<String>, ErrorStatus>>,
231    ),
232    GetElementProperty(String, String, IpcSender<Result<JSValue, ErrorStatus>>),
233    GetElementCSS(String, String, IpcSender<Result<String, ErrorStatus>>),
234    GetElementRect(String, IpcSender<Result<UntypedRect<f64>, ErrorStatus>>),
235    GetElementTagName(String, IpcSender<Result<String, ErrorStatus>>),
236    GetElementText(String, IpcSender<Result<String, ErrorStatus>>),
237    GetElementInViewCenterPoint(String, IpcSender<Result<Option<(i64, i64)>, ErrorStatus>>),
238    ScrollAndGetBoundingClientRect(String, IpcSender<Result<UntypedRect<f32>, ErrorStatus>>),
239    GetBrowsingContextId(
240        WebDriverFrameId,
241        IpcSender<Result<BrowsingContextId, ErrorStatus>>,
242    ),
243    GetParentFrameId(IpcSender<Result<BrowsingContextId, ErrorStatus>>),
244    GetUrl(IpcSender<ServoUrl>),
245    GetPageSource(IpcSender<Result<String, ErrorStatus>>),
246    IsEnabled(String, IpcSender<Result<bool, ErrorStatus>>),
247    IsSelected(String, IpcSender<Result<bool, ErrorStatus>>),
248    GetTitle(IpcSender<String>),
249    /// Deal with the case of input element for Element Send Keys, which does not send keys.
250    WillSendKeys(String, String, bool, IpcSender<Result<bool, ErrorStatus>>),
251    AddLoadStatusSender(WebViewId, GenericSender<WebDriverLoadStatus>),
252    RemoveLoadStatusSender(WebViewId),
253}
254
255#[derive(Debug, Deserialize, Serialize)]
256pub enum WebDriverJSError {
257    /// Occurs when handler received an event message for a layout channel that is not
258    /// associated with the current script thread
259    BrowsingContextNotFound,
260    DetachedShadowRoot,
261    JSException(JSValue),
262    JSError,
263    StaleElementReference,
264    Timeout,
265    UnknownType,
266}
267
268pub type WebDriverJSResult = Result<JSValue, WebDriverJSError>;
269
270#[derive(Debug, Deserialize, Serialize)]
271pub enum WebDriverFrameId {
272    Short(u16),
273    Element(String),
274}
275
276#[derive(Debug, Deserialize, Serialize)]
277pub struct WebDriverCommandResponse {
278    pub id: WebDriverMessageId,
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 [`IpcSender`]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<IpcSender<WebDriverJSResult>>,
300    pub pending_traversals: HashMap<TraversalId, GenericSender<WebDriverLoadStatus>>,
301}