Serenity Operating System
at master 689 lines 34 kB view raw
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}