diff options
author | Linus Groh <mail@linusgroh.de> | 2022-11-02 18:12:28 +0000 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-11-02 23:46:30 +0000 |
commit | 629fbc2cfc1c7a88f51476908eebda80d99db2bf (patch) | |
tree | 4883181903f122162e2e383129d0cb818445b128 | |
parent | f88a0c51a329435f6a706c65a25c9cd959e26168 (diff) | |
download | serenity-629fbc2cfc1c7a88f51476908eebda80d99db2bf.zip |
WebDriver: Implement `POST /session/{session id}/execute/async` endpoint
-rw-r--r-- | Userland/Services/WebDriver/Client.cpp | 11 | ||||
-rw-r--r-- | Userland/Services/WebDriver/Client.h | 1 | ||||
-rw-r--r-- | Userland/Services/WebDriver/Session.cpp | 40 | ||||
-rw-r--r-- | Userland/Services/WebDriver/Session.h | 1 |
4 files changed, 53 insertions, 0 deletions
diff --git a/Userland/Services/WebDriver/Client.cpp b/Userland/Services/WebDriver/Client.cpp index ea20088864..0e1a4e81d6 100644 --- a/Userland/Services/WebDriver/Client.cpp +++ b/Userland/Services/WebDriver/Client.cpp @@ -50,6 +50,7 @@ Vector<Client::Route> Client::s_routes = { { HTTP::HttpRequest::Method::GET, { "session", ":session_id", "element", ":element_id", "text" }, &Client::handle_get_element_text }, { HTTP::HttpRequest::Method::GET, { "session", ":session_id", "element", ":element_id", "name" }, &Client::handle_get_element_tag_name }, { HTTP::HttpRequest::Method::POST, { "session", ":session_id", "execute", "sync" }, &Client::handle_execute_script }, + { HTTP::HttpRequest::Method::POST, { "session", ":session_id", "execute", "async" }, &Client::handle_execute_async_script }, { HTTP::HttpRequest::Method::GET, { "session", ":session_id", "cookie" }, &Client::handle_get_all_cookies }, { HTTP::HttpRequest::Method::GET, { "session", ":session_id", "cookie", ":name" }, &Client::handle_get_named_cookie }, { HTTP::HttpRequest::Method::POST, { "session", ":session_id", "cookie" }, &Client::handle_add_cookie }, @@ -696,6 +697,16 @@ ErrorOr<JsonValue, WebDriverError> Client::handle_execute_script(Vector<StringVi return make_json_value(result); } +// 13.2.2 Execute Async Script, https://w3c.github.io/webdriver/#dfn-execute-async-script +// POST /session/{session id}/execute/async +ErrorOr<JsonValue, WebDriverError> Client::handle_execute_async_script(Vector<StringView> const& parameters, JsonValue const& payload) +{ + dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/execute/async"); + auto* session = TRY(find_session_with_id(parameters[0])); + auto result = TRY(session->execute_async_script(payload)); + return make_json_value(result); +} + // 14.1 Get All Cookies, https://w3c.github.io/webdriver/#dfn-get-all-cookies // GET /session/{session id}/cookie ErrorOr<JsonValue, WebDriverError> Client::handle_get_all_cookies(Vector<StringView> const& parameters, JsonValue const&) diff --git a/Userland/Services/WebDriver/Client.h b/Userland/Services/WebDriver/Client.h index 33239087e1..1550b2dfdd 100644 --- a/Userland/Services/WebDriver/Client.h +++ b/Userland/Services/WebDriver/Client.h @@ -75,6 +75,7 @@ private: ErrorOr<JsonValue, WebDriverError> handle_get_element_text(Vector<StringView> const&, JsonValue const& payload); ErrorOr<JsonValue, WebDriverError> handle_get_element_tag_name(Vector<StringView> const&, JsonValue const& payload); ErrorOr<JsonValue, WebDriverError> handle_execute_script(Vector<StringView> const&, JsonValue const& payload); + ErrorOr<JsonValue, WebDriverError> handle_execute_async_script(Vector<StringView> const&, JsonValue const& payload); ErrorOr<JsonValue, WebDriverError> handle_get_all_cookies(Vector<StringView> const&, JsonValue const& payload); ErrorOr<JsonValue, WebDriverError> handle_get_named_cookie(Vector<StringView> const&, JsonValue const& payload); ErrorOr<JsonValue, WebDriverError> handle_add_cookie(Vector<StringView> const&, JsonValue const& payload); diff --git a/Userland/Services/WebDriver/Session.cpp b/Userland/Services/WebDriver/Session.cpp index 53ab8bdbd2..ba31b82b70 100644 --- a/Userland/Services/WebDriver/Session.cpp +++ b/Userland/Services/WebDriver/Session.cpp @@ -973,6 +973,46 @@ ErrorOr<JsonValue, WebDriverError> Session::execute_script(JsonValue const& payl } } +// 13.2.2 Execute Async Script, https://w3c.github.io/webdriver/#dfn-execute-async-script +ErrorOr<JsonValue, WebDriverError> Session::execute_async_script(JsonValue const& parameters) +{ + // 1. Let body and arguments by the result of trying to extract the script arguments from a request with argument parameters. + auto [body, arguments] = TRY(extract_the_script_arguments_from_a_request(parameters)); + + // 2. If the current browsing context is no longer open, return error with error code no such window. + TRY(check_for_open_top_level_browsing_context_or_return_error()); + + // FIXME: 3. Handle any user prompts, and return its value if it is an error. + + // 4., 5.1-5.11. + Vector<String> json_arguments; + arguments.for_each([&](JsonValue const& json_value) { + // NOTE: serialized() instead of to_string() ensures proper quoting. + json_arguments.append(json_value.serialized<StringBuilder>()); + }); + + dbgln("Executing async script with 'args': [{}] / 'body':\n{}", String::join(", "sv, json_arguments), body); + auto execute_script_response = m_browser_connection->execute_script(body, json_arguments, m_timeouts_configuration.script_timeout, true); + dbgln("Executing async script returned: {}", execute_script_response.json_result()); + + // NOTE: This is assumed to be a valid JSON value. + auto result = MUST(JsonValue::from_string(execute_script_response.json_result())); + + switch (execute_script_response.result_type()) { + // 6. If promise is still pending and the session script timeout is reached, return error with error code script timeout. + case Web::WebDriver::ExecuteScriptResultType::Timeout: + return WebDriverError::from_code(ErrorCode::ScriptTimeoutError, "Script timed out"); + // 7. Upon fulfillment of promise with value v, let result be a JSON clone of v, and return success with data result. + case Web::WebDriver::ExecuteScriptResultType::PromiseResolved: + return result; + // 8. Upon rejection of promise with reason r, let result be a JSON clone of r, and return error with error code javascript error and data result. + case Web::WebDriver::ExecuteScriptResultType::PromiseRejected: + return WebDriverError::from_code(ErrorCode::JavascriptError, "Script returned an error", move(result)); + default: + VERIFY_NOT_REACHED(); + } +} + // https://w3c.github.io/webdriver/#dfn-serialized-cookie static JsonObject serialize_cookie(Web::Cookie::Cookie const& cookie) { diff --git a/Userland/Services/WebDriver/Session.h b/Userland/Services/WebDriver/Session.h index 9dc8943d59..fad69e44ba 100644 --- a/Userland/Services/WebDriver/Session.h +++ b/Userland/Services/WebDriver/Session.h @@ -64,6 +64,7 @@ public: ErrorOr<JsonValue, WebDriverError> get_element_text(JsonValue const& payload, StringView element_id); ErrorOr<JsonValue, WebDriverError> get_element_tag_name(JsonValue const& payload, StringView element_id); ErrorOr<JsonValue, WebDriverError> execute_script(JsonValue const& payload); + ErrorOr<JsonValue, WebDriverError> execute_async_script(JsonValue const& payload); ErrorOr<JsonValue, WebDriverError> get_all_cookies(); ErrorOr<JsonValue, WebDriverError> get_named_cookie(String const& name); ErrorOr<JsonValue, WebDriverError> add_cookie(JsonValue const& payload); |