Serenity Operating System
1/*
2 * Copyright (c) 2022, Florent Castelli <florent.castelli@gmail.com>
3 * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
4 * Copyright (c) 2022, Tobias Christiansen <tobyase@serenityos.org>
5 * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
6 * Copyright (c) 2022-2023, Tim Flynn <trflynn89@serenityos.org>
7 *
8 * SPDX-License-Identifier: BSD-2-Clause
9 */
10
11#include <AK/Debug.h>
12#include <AK/JsonObject.h>
13#include <AK/JsonValue.h>
14#include <LibWeb/WebDriver/Capabilities.h>
15#include <LibWeb/WebDriver/TimeoutsConfiguration.h>
16#include <WebDriver/Client.h>
17
18namespace WebDriver {
19
20Atomic<unsigned> Client::s_next_session_id;
21HashMap<unsigned, NonnullRefPtr<Session>> Client::s_sessions;
22
23ErrorOr<NonnullRefPtr<Client>> Client::try_create(NonnullOwnPtr<Core::BufferedTCPSocket> socket, LaunchBrowserCallbacks callbacks, Core::Object* parent)
24{
25 if (!callbacks.launch_browser || !callbacks.launch_headless_browser)
26 return Error::from_string_view("All callbacks to launch a browser must be provided"sv);
27
28 TRY(socket->set_blocking(true));
29 return adopt_nonnull_ref_or_enomem(new (nothrow) Client(move(socket), move(callbacks), parent));
30}
31
32Client::Client(NonnullOwnPtr<Core::BufferedTCPSocket> socket, LaunchBrowserCallbacks callbacks, Core::Object* parent)
33 : Web::WebDriver::Client(move(socket), parent)
34 , m_callbacks(move(callbacks))
35{
36}
37
38Client::~Client() = default;
39
40ErrorOr<NonnullRefPtr<Session>, Web::WebDriver::Error> Client::find_session_with_id(StringView session_id)
41{
42 auto session_id_or_error = session_id.to_uint<>();
43 if (!session_id_or_error.has_value())
44 return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidSessionId, "Invalid session id");
45
46 if (auto session = s_sessions.get(*session_id_or_error); session.has_value())
47 return *session.release_value();
48
49 return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidSessionId, "Invalid session id");
50}
51
52void Client::close_session(unsigned session_id)
53{
54 if (s_sessions.remove(session_id))
55 dbgln_if(WEBDRIVER_DEBUG, "Shut down session {}", session_id);
56 else
57 dbgln_if(WEBDRIVER_DEBUG, "Unable to shut down session {}: Not found", session_id);
58}
59
60// Step 12 of https://w3c.github.io/webdriver/#dfn-new-sessions
61static void initialize_session_from_capabilities(WebContentConnection& web_content_connection, JsonObject& capabilities)
62{
63 // 1. Let strategy be the result of getting property "pageLoadStrategy" from capabilities.
64 auto strategy = capabilities.get_deprecated_string("pageLoadStrategy"sv);
65
66 // 2. If strategy is a string, set the current session’s page loading strategy to strategy. Otherwise, set the page loading strategy to normal and set a property of capabilities with name "pageLoadStrategy" and value "normal".
67 if (strategy.has_value())
68 web_content_connection.async_set_page_load_strategy(Web::WebDriver::page_load_strategy_from_string(*strategy));
69 else
70 capabilities.set("pageLoadStrategy"sv, "normal"sv);
71
72 // 3. Let strictFileInteractability be the result of getting property "strictFileInteractability" from capabilities.
73 auto strict_file_interactiblity = capabilities.get_bool("strictFileInteractability"sv);
74
75 // 4. If strictFileInteractability is a boolean, set the current session’s strict file interactability to strictFileInteractability. Otherwise set the current session’s strict file interactability to false.
76 if (strict_file_interactiblity.has_value())
77 web_content_connection.async_set_strict_file_interactability(*strict_file_interactiblity);
78 else
79 capabilities.set("strictFileInteractability"sv, false);
80
81 // FIXME: 5. Let proxy be the result of getting property "proxy" from capabilities and run the substeps of the first matching statement:
82 // FIXME: proxy is a proxy configuration object
83 // FIXME: Take implementation-defined steps to set the user agent proxy using the extracted proxy configuration. If the defined proxy cannot be configured return error with error code session not created.
84 // FIXME: Otherwise
85 // FIXME: Set a property of capabilities with name "proxy" and a value that is a new JSON Object.
86
87 // 6. If capabilities has a property with the key "timeouts":
88 if (auto timeouts = capabilities.get_object("timeouts"sv); timeouts.has_value()) {
89 // a. Let timeouts be the result of trying to JSON deserialize as a timeouts configuration the value of the "timeouts" property.
90 // NOTE: This happens on the remote end.
91
92 // b. Make the session timeouts the new timeouts.
93 MUST(web_content_connection.set_timeouts(*timeouts));
94 } else {
95 // 7. Set a property on capabilities with name "timeouts" and value that of the JSON deserialization of the session timeouts.
96 capabilities.set("timeouts"sv, Web::WebDriver::timeouts_object({}));
97 }
98
99 // 8. Apply changes to the user agent for any implementation-defined capabilities selected during the capabilities processing step.
100 auto behavior = capabilities.get_deprecated_string("unhandledPromptBehavior"sv);
101 if (behavior.has_value())
102 web_content_connection.async_set_unhandled_prompt_behavior(Web::WebDriver::unhandled_prompt_behavior_from_string(*behavior));
103 else
104 capabilities.set("unhandledPromptBehavior"sv, "dismiss and notify"sv);
105}
106
107// 8.1 New Session, https://w3c.github.io/webdriver/#dfn-new-sessions
108// POST /session
109Web::WebDriver::Response Client::new_session(Web::WebDriver::Parameters, JsonValue payload)
110{
111 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session");
112
113 // FIXME: 1. If the maximum active sessions is equal to the length of the list of active sessions,
114 // return error with error code session not created.
115
116 // FIXME: 2. If the remote end is an intermediary node, take implementation-defined steps that either
117 // result in returning an error with error code session not created, or in returning a
118 // success with data that is isomorphic to that returned by remote ends according to the
119 // rest of this algorithm. If an error is not returned, the intermediary node must retain a
120 // reference to the session created on the upstream node as the associated session such
121 // that commands may be forwarded to this associated session on subsequent commands.
122
123 // FIXME: 3. If the maximum active sessions is equal to the length of the list of active sessions,
124 // return error with error code session not created.
125
126 // 4. Let capabilities be the result of trying to process capabilities with parameters as an argument.
127 auto capabilities = TRY(Web::WebDriver::process_capabilities(payload));
128
129 // 5. If capabilities’s is null, return error with error code session not created.
130 if (capabilities.is_null())
131 return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::SessionNotCreated, "Could not match capabilities"sv);
132
133 // 6. Let session id be the result of generating a UUID.
134 // FIXME: Actually create a UUID.
135 auto session_id = Client::s_next_session_id++;
136
137 // 7. Let session be a new session with the session ID of session id.
138 Web::WebDriver::LadybirdOptions options { capabilities.as_object() };
139 auto session = make_ref_counted<Session>(session_id, *this, move(options));
140
141 if (auto start_result = session->start(m_callbacks); start_result.is_error())
142 return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::SessionNotCreated, DeprecatedString::formatted("Failed to start session: {}", start_result.error().string_literal()));
143
144 auto& web_content_connection = session->web_content_connection();
145
146 // FIXME: 8. Set the current session to session.
147
148 // FIXME: 9. Run any WebDriver new session algorithm defined in external specifications,
149 // with arguments session and capabilities.
150
151 // 10. Append session to active sessions.
152 s_sessions.set(session_id, move(session));
153
154 // NOTE: We do step 12 before 11 because step 12 mutates the capabilities we set in step 11.
155
156 // 12. Initialize the following from capabilities:
157 initialize_session_from_capabilities(web_content_connection, capabilities.as_object());
158
159 // 11. Let body be a JSON Object initialized with:
160 JsonObject body;
161 // "sessionId"
162 // session id
163 body.set("sessionId", DeprecatedString::number(session_id));
164 // "capabilities"
165 // capabilities
166 body.set("capabilities", move(capabilities));
167
168 // 13. Set the webdriver-active flag to true.
169 web_content_connection.async_set_is_webdriver_active(true);
170
171 // FIXME: 14. Set the current top-level browsing context for session with the top-level browsing context
172 // of the UA’s current browsing context.
173
174 // FIXME: 15. Set the request queue to a new queue.
175
176 // 16. Return success with data body.
177 return JsonValue { move(body) };
178}
179
180// 8.2 Delete Session, https://w3c.github.io/webdriver/#dfn-delete-session
181// DELETE /session/{session id}
182Web::WebDriver::Response Client::delete_session(Web::WebDriver::Parameters parameters, JsonValue)
183{
184 dbgln_if(WEBDRIVER_DEBUG, "Handling DELETE /session/<session_id>");
185
186 // 1. If the current session is an active session, try to close the session.
187 if (auto session = find_session_with_id(parameters[0]); !session.is_error())
188 TRY(session.value()->stop());
189
190 // 2. Return success with data null.
191 return JsonValue {};
192}
193
194// 8.3 Status, https://w3c.github.io/webdriver/#dfn-status
195// GET /status
196Web::WebDriver::Response Client::get_status(Web::WebDriver::Parameters, JsonValue)
197{
198 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /status");
199
200 // 1. Let body be a new JSON Object with the following properties:
201 // "ready"
202 // The remote end’s readiness state.
203 // "message"
204 // An implementation-defined string explaining the remote end’s readiness state.
205 // FIXME: Report if we are somehow not ready.
206 JsonObject body;
207 body.set("ready", true);
208 body.set("message", "Ready to start some sessions!");
209
210 // 2. Return success with data body.
211 return JsonValue { body };
212}
213
214// 9.1 Get Timeouts, https://w3c.github.io/webdriver/#dfn-get-timeouts
215// GET /session/{session id}/timeouts
216Web::WebDriver::Response Client::get_timeouts(Web::WebDriver::Parameters parameters, JsonValue)
217{
218 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session id>/timeouts");
219 auto session = TRY(find_session_with_id(parameters[0]));
220 return session->web_content_connection().get_timeouts();
221}
222
223// 9.2 Set Timeouts, https://w3c.github.io/webdriver/#dfn-set-timeouts
224// POST /session/{session id}/timeouts
225Web::WebDriver::Response Client::set_timeouts(Web::WebDriver::Parameters parameters, JsonValue payload)
226{
227 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session id>/timeouts");
228 auto session = TRY(find_session_with_id(parameters[0]));
229 return session->web_content_connection().set_timeouts(payload);
230}
231
232// 10.1 Navigate To, https://w3c.github.io/webdriver/#dfn-navigate-to
233// POST /session/{session id}/url
234Web::WebDriver::Response Client::navigate_to(Web::WebDriver::Parameters parameters, JsonValue payload)
235{
236 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/url");
237 auto session = TRY(find_session_with_id(parameters[0]));
238 return session->web_content_connection().navigate_to(payload);
239}
240
241// 10.2 Get Current URL, https://w3c.github.io/webdriver/#dfn-get-current-url
242// GET /session/{session id}/url
243Web::WebDriver::Response Client::get_current_url(Web::WebDriver::Parameters parameters, JsonValue)
244{
245 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/url");
246 auto session = TRY(find_session_with_id(parameters[0]));
247 return session->web_content_connection().get_current_url();
248}
249
250// 10.3 Back, https://w3c.github.io/webdriver/#dfn-back
251// POST /session/{session id}/back
252Web::WebDriver::Response Client::back(Web::WebDriver::Parameters parameters, JsonValue)
253{
254 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/back");
255 auto session = TRY(find_session_with_id(parameters[0]));
256 return session->web_content_connection().back();
257}
258
259// 10.4 Forward, https://w3c.github.io/webdriver/#dfn-forward
260// POST /session/{session id}/forward
261Web::WebDriver::Response Client::forward(Web::WebDriver::Parameters parameters, JsonValue)
262{
263 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/forward");
264 auto session = TRY(find_session_with_id(parameters[0]));
265 return session->web_content_connection().forward();
266}
267
268// 10.5 Refresh, https://w3c.github.io/webdriver/#dfn-refresh
269// POST /session/{session id}/refresh
270Web::WebDriver::Response Client::refresh(Web::WebDriver::Parameters parameters, JsonValue)
271{
272 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/refresh");
273 auto session = TRY(find_session_with_id(parameters[0]));
274 return session->web_content_connection().refresh();
275}
276
277// 10.6 Get Title, https://w3c.github.io/webdriver/#dfn-get-title
278// GET /session/{session id}/title
279Web::WebDriver::Response Client::get_title(Web::WebDriver::Parameters parameters, JsonValue)
280{
281 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/title");
282 auto session = TRY(find_session_with_id(parameters[0]));
283 return session->web_content_connection().get_title();
284}
285
286// 11.1 Get Window Handle, https://w3c.github.io/webdriver/#get-window-handle
287// GET /session/{session id}/window
288Web::WebDriver::Response Client::get_window_handle(Web::WebDriver::Parameters parameters, JsonValue)
289{
290 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/window");
291 auto session = TRY(find_session_with_id(parameters[0]));
292
293 // 1. If the current top-level browsing context is no longer open, return error with error code no such window.
294 TRY(session->web_content_connection().ensure_top_level_browsing_context_is_open());
295
296 // 2. Return success with data being the window handle associated with the current top-level browsing context.
297 return JsonValue { session->current_window_handle() };
298}
299
300// 11.2 Close Window, https://w3c.github.io/webdriver/#dfn-close-window
301// DELETE /session/{session id}/window
302Web::WebDriver::Response Client::close_window(Web::WebDriver::Parameters parameters, JsonValue)
303{
304 dbgln_if(WEBDRIVER_DEBUG, "Handling DELETE /session/<session_id>/window");
305 auto session = TRY(find_session_with_id(parameters[0]));
306 return session->close_window();
307}
308
309// 11.3 Switch to Window, https://w3c.github.io/webdriver/#dfn-switch-to-window
310// POST /session/{session id}/window
311Web::WebDriver::Response Client::switch_to_window(Web::WebDriver::Parameters parameters, AK::JsonValue payload)
312{
313 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/window");
314 auto session = TRY(find_session_with_id(parameters[0]));
315
316 if (!payload.is_object())
317 return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "Payload is not a JSON object");
318
319 // 1. Let handle be the result of getting the property "handle" from the parameters argument.
320 auto handle = payload.as_object().get("handle"sv);
321
322 // 2. If handle is undefined, return error with error code invalid argument.
323 if (!handle.has_value())
324 return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "No property called 'handle' present");
325
326 return session->switch_to_window(handle->as_string());
327}
328
329// 11.4 Get Window Handles, https://w3c.github.io/webdriver/#dfn-get-window-handles
330// GET /session/{session id}/window/handles
331Web::WebDriver::Response Client::get_window_handles(Web::WebDriver::Parameters parameters, JsonValue)
332{
333 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/window/handles");
334 auto session = TRY(find_session_with_id(parameters[0]));
335 return session->get_window_handles();
336}
337
338// 11.8.1 Get Window Rect, https://w3c.github.io/webdriver/#dfn-get-window-rect
339// GET /session/{session id}/window/rect
340Web::WebDriver::Response Client::get_window_rect(Web::WebDriver::Parameters parameters, JsonValue)
341{
342 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/window/rect");
343 auto session = TRY(find_session_with_id(parameters[0]));
344 return session->web_content_connection().get_window_rect();
345}
346
347// 11.8.2 Set Window Rect, https://w3c.github.io/webdriver/#dfn-set-window-rect
348// POST /session/{session id}/window/rect
349Web::WebDriver::Response Client::set_window_rect(Web::WebDriver::Parameters parameters, JsonValue payload)
350{
351 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/window/rect");
352 auto session = TRY(find_session_with_id(parameters[0]));
353 return session->web_content_connection().set_window_rect(payload);
354}
355
356// 11.8.3 Maximize Window, https://w3c.github.io/webdriver/#dfn-maximize-window
357// POST /session/{session id}/window/maximize
358Web::WebDriver::Response Client::maximize_window(Web::WebDriver::Parameters parameters, JsonValue)
359{
360 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/window/maximize");
361 auto session = TRY(find_session_with_id(parameters[0]));
362 return session->web_content_connection().maximize_window();
363}
364
365// 11.8.4 Minimize Window, https://w3c.github.io/webdriver/#minimize-window
366// POST /session/{session id}/window/minimize
367Web::WebDriver::Response Client::minimize_window(Web::WebDriver::Parameters parameters, JsonValue)
368{
369 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/window/minimize");
370 auto session = TRY(find_session_with_id(parameters[0]));
371 return session->web_content_connection().minimize_window();
372}
373
374// 11.8.5 Fullscreen Window, https://w3c.github.io/webdriver/#dfn-fullscreen-window
375// POST /session/{session id}/window/fullscreen
376Web::WebDriver::Response Client::fullscreen_window(Web::WebDriver::Parameters parameters, JsonValue)
377{
378 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/window/fullscreen");
379 auto session = TRY(find_session_with_id(parameters[0]));
380 return session->web_content_connection().fullscreen_window();
381}
382
383// 12.3.2 Find Element, https://w3c.github.io/webdriver/#dfn-find-element
384// POST /session/{session id}/element
385Web::WebDriver::Response Client::find_element(Web::WebDriver::Parameters parameters, JsonValue payload)
386{
387 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/element");
388 auto session = TRY(find_session_with_id(parameters[0]));
389 return session->web_content_connection().find_element(payload);
390}
391
392// 12.3.3 Find Elements, https://w3c.github.io/webdriver/#dfn-find-elements
393// POST /session/{session id}/elements
394Web::WebDriver::Response Client::find_elements(Web::WebDriver::Parameters parameters, JsonValue payload)
395{
396 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/elements");
397 auto session = TRY(find_session_with_id(parameters[0]));
398 return session->web_content_connection().find_elements(payload);
399}
400
401// 12.3.4 Find Element From Element, https://w3c.github.io/webdriver/#dfn-find-element-from-element
402// POST /session/{session id}/element/{element id}/element
403Web::WebDriver::Response Client::find_element_from_element(Web::WebDriver::Parameters parameters, JsonValue payload)
404{
405 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/element/<element_id>/element");
406 auto session = TRY(find_session_with_id(parameters[0]));
407 return session->web_content_connection().find_element_from_element(payload, move(parameters[1]));
408}
409
410// 12.3.5 Find Elements From Element, https://w3c.github.io/webdriver/#dfn-find-elements-from-element
411// POST /session/{session id}/element/{element id}/elements
412Web::WebDriver::Response Client::find_elements_from_element(Web::WebDriver::Parameters parameters, JsonValue payload)
413{
414 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/element/<element_id>/elements");
415 auto session = TRY(find_session_with_id(parameters[0]));
416 return session->web_content_connection().find_elements_from_element(payload, move(parameters[1]));
417}
418
419// 12.3.6 Find Element From Shadow Root, https://w3c.github.io/webdriver/#find-element-from-shadow-root
420// POST /session/{session id}/shadow/{shadow id}/element
421Web::WebDriver::Response Client::find_element_from_shadow_root(Web::WebDriver::Parameters parameters, JsonValue payload)
422{
423 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/shadow/<shadow_id>/element");
424 auto session = TRY(find_session_with_id(parameters[0]));
425 return session->web_content_connection().find_element_from_shadow_root(payload, move(parameters[1]));
426}
427
428// 12.3.7 Find Elements From Shadow Root, https://w3c.github.io/webdriver/#find-elements-from-shadow-root
429// POST /session/{session id}/shadow/{shadow id}/elements
430Web::WebDriver::Response Client::find_elements_from_shadow_root(Web::WebDriver::Parameters parameters, JsonValue payload)
431{
432 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/shadow/<shadow_id>/elements");
433 auto session = TRY(find_session_with_id(parameters[0]));
434 return session->web_content_connection().find_elements_from_shadow_root(payload, move(parameters[1]));
435}
436
437// 12.3.8 Get Active Element, https://w3c.github.io/webdriver/#get-active-element
438// GET /session/{session id}/element/active
439Web::WebDriver::Response Client::get_active_element(Web::WebDriver::Parameters parameters, JsonValue)
440{
441 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/active");
442 auto session = TRY(find_session_with_id(parameters[0]));
443 return session->web_content_connection().get_active_element();
444}
445
446// 12.3.9 Get Element Shadow Root, https://w3c.github.io/webdriver/#get-element-shadow-root
447// GET /session/{session id}/element/{element id}/shadow
448Web::WebDriver::Response Client::get_element_shadow_root(Web::WebDriver::Parameters parameters, JsonValue)
449{
450 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/shadow");
451 auto session = TRY(find_session_with_id(parameters[0]));
452 return session->web_content_connection().get_element_shadow_root(move(parameters[1]));
453}
454
455// 12.4.1 Is Element Selected, https://w3c.github.io/webdriver/#dfn-is-element-selected
456// GET /session/{session id}/element/{element id}/selected
457Web::WebDriver::Response Client::is_element_selected(Web::WebDriver::Parameters parameters, JsonValue)
458{
459 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/selected");
460 auto session = TRY(find_session_with_id(parameters[0]));
461 return session->web_content_connection().is_element_selected(move(parameters[1]));
462}
463
464// 12.4.2 Get Element Attribute, https://w3c.github.io/webdriver/#dfn-get-element-attribute
465// GET /session/{session id}/element/{element id}/attribute/{name}
466Web::WebDriver::Response Client::get_element_attribute(Web::WebDriver::Parameters parameters, JsonValue)
467{
468 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/attribute/<name>");
469 auto session = TRY(find_session_with_id(parameters[0]));
470 return session->web_content_connection().get_element_attribute(move(parameters[1]), move(parameters[2]));
471}
472
473// 12.4.3 Get Element Property, https://w3c.github.io/webdriver/#dfn-get-element-property
474// GET /session/{session id}/element/{element id}/property/{name}
475Web::WebDriver::Response Client::get_element_property(Web::WebDriver::Parameters parameters, JsonValue)
476{
477 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/property/<name>");
478 auto session = TRY(find_session_with_id(parameters[0]));
479 return session->web_content_connection().get_element_property(move(parameters[1]), move(parameters[2]));
480}
481
482// 12.4.4 Get Element CSS Value, https://w3c.github.io/webdriver/#dfn-get-element-css-value
483// GET /session/{session id}/element/{element id}/css/{property name}
484Web::WebDriver::Response Client::get_element_css_value(Web::WebDriver::Parameters parameters, JsonValue)
485{
486 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/css/<property_name>");
487 auto session = TRY(find_session_with_id(parameters[0]));
488 return session->web_content_connection().get_element_css_value(move(parameters[1]), move(parameters[2]));
489}
490
491// 12.4.5 Get Element Text, https://w3c.github.io/webdriver/#dfn-get-element-text
492// GET /session/{session id}/element/{element id}/text
493Web::WebDriver::Response Client::get_element_text(Web::WebDriver::Parameters parameters, JsonValue)
494{
495 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/text");
496 auto session = TRY(find_session_with_id(parameters[0]));
497 return session->web_content_connection().get_element_text(move(parameters[1]));
498}
499
500// 12.4.6 Get Element Tag Name, https://w3c.github.io/webdriver/#dfn-get-element-tag-name
501// GET /session/{session id}/element/{element id}/name
502Web::WebDriver::Response Client::get_element_tag_name(Web::WebDriver::Parameters parameters, JsonValue)
503{
504 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/name");
505 auto session = TRY(find_session_with_id(parameters[0]));
506 return session->web_content_connection().get_element_tag_name(move(parameters[1]));
507}
508
509// 12.4.7 Get Element Rect, https://w3c.github.io/webdriver/#dfn-get-element-rect
510// GET /session/{session id}/element/{element id}/rect
511Web::WebDriver::Response Client::get_element_rect(Web::WebDriver::Parameters parameters, JsonValue)
512{
513 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/rect");
514 auto session = TRY(find_session_with_id(parameters[0]));
515 return session->web_content_connection().get_element_rect(move(parameters[1]));
516}
517
518// 12.4.8 Is Element Enabled, https://w3c.github.io/webdriver/#dfn-is-element-enabled
519// GET /session/{session id}/element/{element id}/enabled
520Web::WebDriver::Response Client::is_element_enabled(Web::WebDriver::Parameters parameters, JsonValue)
521{
522 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/enabled");
523 auto session = TRY(find_session_with_id(parameters[0]));
524 return session->web_content_connection().is_element_enabled(move(parameters[1]));
525}
526
527// 12.4.9 https://w3c.github.io/webdriver/#dfn-get-computed-role
528// GET /session/{session id}/element/{element id}/computedrole
529Web::WebDriver::Response Client::get_computed_role(Web::WebDriver::Parameters parameters, AK::JsonValue)
530{
531 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session id>/element/<element id>/computedrole");
532 auto session = TRY(find_session_with_id(parameters[0]));
533 return session->web_content_connection().get_computed_role(move(parameters[1]));
534}
535
536// 12.4.10 Get Computed Label, https://w3c.github.io/webdriver/#get-computed-label
537// GET /session/{session id}/element/{element id}/computedlabel
538Web::WebDriver::Response Client::get_computed_label(Web::WebDriver::Parameters parameters, JsonValue)
539{
540 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session id>/element/<element id>/computedlabel");
541 auto session = TRY(find_session_with_id(parameters[0]));
542 return session->web_content_connection().get_computed_label(move(parameters[1]));
543}
544
545// 12.5.1 Element Click, https://w3c.github.io/webdriver/#element-click
546// POST /session/{session id}/element/{element id}/click
547Web::WebDriver::Response Client::element_click(Web::WebDriver::Parameters parameters, JsonValue)
548{
549 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/element/<element_id>/click");
550 auto session = TRY(find_session_with_id(parameters[0]));
551 return session->web_content_connection().element_click(move(parameters[1]));
552}
553
554// 13.1 Get Page Source, https://w3c.github.io/webdriver/#dfn-get-page-source
555// GET /session/{session id}/source
556Web::WebDriver::Response Client::get_source(Web::WebDriver::Parameters parameters, JsonValue)
557{
558 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/source");
559 auto session = TRY(find_session_with_id(parameters[0]));
560 return session->web_content_connection().get_source();
561}
562
563// 13.2.1 Execute Script, https://w3c.github.io/webdriver/#dfn-execute-script
564// POST /session/{session id}/execute/sync
565Web::WebDriver::Response Client::execute_script(Web::WebDriver::Parameters parameters, JsonValue payload)
566{
567 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/execute/sync");
568 auto session = TRY(find_session_with_id(parameters[0]));
569 return session->web_content_connection().execute_script(payload);
570}
571
572// 13.2.2 Execute Async Script, https://w3c.github.io/webdriver/#dfn-execute-async-script
573// POST /session/{session id}/execute/async
574Web::WebDriver::Response Client::execute_async_script(Web::WebDriver::Parameters parameters, JsonValue payload)
575{
576 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/execute/async");
577 auto session = TRY(find_session_with_id(parameters[0]));
578 return session->web_content_connection().execute_async_script(payload);
579}
580
581// 14.1 Get All Cookies, https://w3c.github.io/webdriver/#dfn-get-all-cookies
582// GET /session/{session id}/cookie
583Web::WebDriver::Response Client::get_all_cookies(Web::WebDriver::Parameters parameters, JsonValue)
584{
585 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/cookie");
586 auto session = TRY(find_session_with_id(parameters[0]));
587 return session->web_content_connection().get_all_cookies();
588}
589
590// 14.2 Get Named Cookie, https://w3c.github.io/webdriver/#dfn-get-named-cookie
591// GET /session/{session id}/cookie/{name}
592Web::WebDriver::Response Client::get_named_cookie(Web::WebDriver::Parameters parameters, JsonValue)
593{
594 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/cookie/<name>");
595 auto session = TRY(find_session_with_id(parameters[0]));
596 return session->web_content_connection().get_named_cookie(move(parameters[1]));
597}
598
599// 14.3 Add Cookie, https://w3c.github.io/webdriver/#dfn-adding-a-cookie
600// POST /session/{session id}/cookie
601Web::WebDriver::Response Client::add_cookie(Web::WebDriver::Parameters parameters, JsonValue payload)
602{
603 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/cookie");
604 auto session = TRY(find_session_with_id(parameters[0]));
605 return session->web_content_connection().add_cookie(payload);
606}
607
608// 14.4 Delete Cookie, https://w3c.github.io/webdriver/#dfn-delete-cookie
609// DELETE /session/{session id}/cookie/{name}
610Web::WebDriver::Response Client::delete_cookie(Web::WebDriver::Parameters parameters, JsonValue)
611{
612 dbgln_if(WEBDRIVER_DEBUG, "Handling DELETE /session/<session_id>/cookie/<name>");
613 auto session = TRY(find_session_with_id(parameters[0]));
614 return session->web_content_connection().delete_cookie(move(parameters[1]));
615}
616
617// 14.5 Delete All Cookies, https://w3c.github.io/webdriver/#dfn-delete-all-cookies
618// DELETE /session/{session id}/cookie
619Web::WebDriver::Response Client::delete_all_cookies(Web::WebDriver::Parameters parameters, JsonValue)
620{
621 dbgln_if(WEBDRIVER_DEBUG, "Handling DELETE /session/<session_id>/cookie");
622 auto session = TRY(find_session_with_id(parameters[0]));
623 return session->web_content_connection().delete_all_cookies();
624}
625
626// 16.1 Dismiss Alert, https://w3c.github.io/webdriver/#dismiss-alert
627// POST /session/{session id}/alert/dismiss
628Web::WebDriver::Response Client::dismiss_alert(Web::WebDriver::Parameters parameters, JsonValue)
629{
630 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/alert/dismiss");
631 auto session = TRY(find_session_with_id(parameters[0]));
632 return session->web_content_connection().dismiss_alert();
633}
634
635// 16.2 Accept Alert, https://w3c.github.io/webdriver/#accept-alert
636// POST /session/{session id}/alert/accept
637Web::WebDriver::Response Client::accept_alert(Web::WebDriver::Parameters parameters, JsonValue)
638{
639 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/alert/accept");
640 auto session = TRY(find_session_with_id(parameters[0]));
641 return session->web_content_connection().accept_alert();
642}
643
644// 16.3 Get Alert Text, https://w3c.github.io/webdriver/#get-alert-text
645// GET /session/{session id}/alert/text
646Web::WebDriver::Response Client::get_alert_text(Web::WebDriver::Parameters parameters, JsonValue)
647{
648 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/alert/text");
649 auto session = TRY(find_session_with_id(parameters[0]));
650 return session->web_content_connection().get_alert_text();
651}
652
653// 16.4 Send Alert Text, https://w3c.github.io/webdriver/#send-alert-text
654// POST /session/{session id}/alert/text
655Web::WebDriver::Response Client::send_alert_text(Web::WebDriver::Parameters parameters, JsonValue payload)
656{
657 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/alert/text");
658 auto session = TRY(find_session_with_id(parameters[0]));
659 return session->web_content_connection().send_alert_text(payload);
660}
661
662// 17.1 Take Screenshot, https://w3c.github.io/webdriver/#take-screenshot
663// GET /session/{session id}/screenshot
664Web::WebDriver::Response Client::take_screenshot(Web::WebDriver::Parameters parameters, JsonValue)
665{
666 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/screenshot");
667 auto session = TRY(find_session_with_id(parameters[0]));
668 return session->web_content_connection().take_screenshot();
669}
670
671// 17.2 Take Element Screenshot, https://w3c.github.io/webdriver/#dfn-take-element-screenshot
672// GET /session/{session id}/element/{element id}/screenshot
673Web::WebDriver::Response Client::take_element_screenshot(Web::WebDriver::Parameters parameters, JsonValue)
674{
675 dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/screenshot");
676 auto session = TRY(find_session_with_id(parameters[0]));
677 return session->web_content_connection().take_element_screenshot(move(parameters[1]));
678}
679
680// 18.1 Print Page, https://w3c.github.io/webdriver/#dfn-print-page
681// POST /session/{session id}/print
682Web::WebDriver::Response Client::print_page(Web::WebDriver::Parameters parameters, JsonValue)
683{
684 dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session id>/print");
685 auto session = TRY(find_session_with_id(parameters[0]));
686 return session->web_content_connection().print_page();
687}
688
689}