webdriver_server/
session.rs1use std::collections::HashMap;
6
7use base::id::{BrowsingContextId, WebViewId};
8use rustc_hash::FxHashSet;
9use serde_json::{Map, Value, json};
10use uuid::Uuid;
11use webdriver::error::WebDriverResult;
12
13use crate::Handler;
14use crate::actions::{ActionItem, InputSourceState};
15use crate::capabilities::ServoCapabilities;
16use crate::timeout::{
17 TimeoutsConfiguration, deserialize_as_timeouts_configuration, serialize_timeouts_configuration,
18};
19use crate::user_prompt::{
20 UserPromptHandler, default_unhandled_prompt_behavior, deserialize_unhandled_prompt_behaviour,
21};
22
23#[derive(Debug, Clone, PartialEq, serde::Serialize)]
24pub(crate) enum PageLoadStrategy {
25 None,
26 Eager,
27 Normal,
28}
29
30#[allow(clippy::to_string_trait_impl)]
32impl ToString for PageLoadStrategy {
33 fn to_string(&self) -> String {
34 match self {
35 PageLoadStrategy::None => String::from("none"),
36 PageLoadStrategy::Eager => String::from("eager"),
37 PageLoadStrategy::Normal => String::from("normal"),
38 }
39 }
40}
41
42pub(crate) struct WebDriverSession {
46 id: Uuid,
48
49 webview_id: Option<WebViewId>,
52
53 browsing_context_id: Option<BrowsingContextId>,
56
57 timeouts: TimeoutsConfiguration,
58
59 page_loading_strategy: PageLoadStrategy,
60
61 strict_file_interactability: bool,
62
63 user_prompt_handler: UserPromptHandler,
65
66 pub(crate) input_state_table: HashMap<String, InputSourceState>,
68
69 pub(crate) input_cancel_list: Vec<(String, ActionItem)>,
71}
72
73impl WebDriverSession {
74 pub(crate) fn new() -> WebDriverSession {
75 WebDriverSession {
76 id: Uuid::new_v4(),
77 webview_id: None,
78 browsing_context_id: None,
79 timeouts: TimeoutsConfiguration::default(),
80 page_loading_strategy: PageLoadStrategy::Normal,
81 strict_file_interactability: false,
82 user_prompt_handler: UserPromptHandler::new(),
83 input_state_table: Default::default(),
84 input_cancel_list: Default::default(),
85 }
86 }
87
88 pub(crate) fn set_webview_id(&mut self, webview_id: WebViewId) {
89 self.webview_id = Some(webview_id);
90 }
91
92 pub(crate) fn set_browsing_context_id(&mut self, browsing_context_id: BrowsingContextId) {
93 self.browsing_context_id = Some(browsing_context_id);
94 }
95
96 pub(crate) fn current_webview_id(&self) -> Option<WebViewId> {
97 self.webview_id
98 }
99
100 pub(crate) fn current_browsing_context_id(&self) -> Option<BrowsingContextId> {
101 self.browsing_context_id
102 }
103
104 pub(crate) fn session_timeouts(&self) -> &TimeoutsConfiguration {
105 &self.timeouts
106 }
107
108 pub(crate) fn session_timeouts_mut(&mut self) -> &mut TimeoutsConfiguration {
109 &mut self.timeouts
110 }
111
112 pub(crate) fn page_loading_strategy(&self) -> PageLoadStrategy {
113 self.page_loading_strategy.clone()
114 }
115
116 pub(crate) fn strict_file_interactability(&self) -> bool {
117 self.strict_file_interactability
118 }
119
120 pub(crate) fn user_prompt_handler(&self) -> &UserPromptHandler {
121 &self.user_prompt_handler
122 }
123
124 pub(crate) fn pointer_ids(&self) -> FxHashSet<u32> {
125 self.input_state_table
126 .values()
127 .filter_map(|source| match source {
128 InputSourceState::Pointer(pointer_state) => Some(pointer_state.pointer_id),
129 _ => None,
130 })
131 .collect()
132 }
133}
134
135impl Handler {
136 pub(crate) fn create_session(
138 &mut self,
139 capabilities: &mut Map<String, Value>,
140 servo_capabilities: &ServoCapabilities,
141 ) -> WebDriverResult<Uuid> {
142 let mut session = WebDriverSession::new();
144
145 match capabilities.get("proxy") {
147 Some(_) => {
149 },
155 None => {
158 capabilities.insert(String::from("proxy"), json!({}));
159 },
160 }
161
162 match capabilities.get("acceptInsecureCerts") {
164 Some(_accept_insecure_certs) => {
165 },
167 None => {
168 capabilities.insert(String::from("acceptInsecureCerts"), json!(false));
169 },
170 }
171
172 match capabilities.get("unhandledPromptBehavior") {
175 Some(unhandled_prompt_behavior) => {
177 session.user_prompt_handler =
178 deserialize_unhandled_prompt_behaviour(unhandled_prompt_behavior.clone())?;
179 },
180 None => {
185 capabilities.insert(
186 String::from("unhandledPromptBehavior"),
187 json!(default_unhandled_prompt_behavior()),
188 );
189 },
190 }
191
192 match capabilities.get("pageLoadStrategy") {
196 Some(strategy) => match strategy.to_string().as_str() {
198 "none" => session.page_loading_strategy = PageLoadStrategy::None,
199 "eager" => session.page_loading_strategy = PageLoadStrategy::Eager,
200 _ => session.page_loading_strategy = PageLoadStrategy::Normal,
201 },
202 None => {
205 capabilities.insert(
206 String::from("pageLoadStrategy"),
207 json!(session.page_loading_strategy.to_string()),
208 );
209 session.page_loading_strategy = PageLoadStrategy::Normal;
210 },
211 }
212
213 if let Some(Value::Bool(strict_file_interactability)) =
216 capabilities.get("strictFileInteractability")
217 {
218 session.strict_file_interactability = *strict_file_interactability;
219 } else {
220 capabilities.insert(String::from("strictFileInteractability"), json!(false));
221 }
222
223 if let Some(timeouts) = capabilities.get("timeouts") {
226 session.timeouts = deserialize_as_timeouts_configuration(timeouts)?;
227 }
228
229 capabilities.insert(
232 "timeouts".to_string(),
233 json!(serialize_timeouts_configuration(&session.timeouts)),
234 );
235
236 capabilities.insert(
241 "browserName".to_string(),
242 json!(servo_capabilities.browser_name),
243 );
244 capabilities.insert(
245 "browserVersion".to_string(),
246 json!(servo_capabilities.browser_version),
247 );
248 capabilities.insert(
249 "platformName".to_string(),
250 json!(
251 servo_capabilities
252 .platform_name
253 .clone()
254 .unwrap_or("unknown".to_string())
255 ),
256 );
257 capabilities.insert(
258 "setWindowRect".to_string(),
259 json!(servo_capabilities.set_window_rect),
260 );
261 capabilities.insert(
262 "userAgent".to_string(),
263 servo_config::pref!(user_agent).into(),
264 );
265
266 let id = session.id;
268 self.session = Some(session);
269
270 Ok(id)
271 }
272}