From 0064d2e8c8ff9aa6279d07ca04b68650169ff7be Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Wed, 19 Oct 2022 18:07:30 +0200 Subject: [PATCH] WebDriver: Implement `POST /session/{session id}/timeouts` endpoint --- Userland/Services/WebDriver/Client.cpp | 13 +++++ Userland/Services/WebDriver/Client.h | 1 + Userland/Services/WebDriver/Session.cpp | 13 +++++ Userland/Services/WebDriver/Session.h | 1 + .../WebDriver/TimeoutsConfiguration.cpp | 56 +++++++++++++++++++ .../WebDriver/TimeoutsConfiguration.h | 1 + 6 files changed, 85 insertions(+) diff --git a/Userland/Services/WebDriver/Client.cpp b/Userland/Services/WebDriver/Client.cpp index 2151465a43..fe3844b102 100644 --- a/Userland/Services/WebDriver/Client.cpp +++ b/Userland/Services/WebDriver/Client.cpp @@ -26,6 +26,7 @@ Vector Client::s_routes = { { HTTP::HttpRequest::Method::DELETE, { "session", ":session_id" }, &Client::handle_delete_session }, { HTTP::HttpRequest::Method::GET, { "status" }, &Client::handle_get_status }, { HTTP::HttpRequest::Method::GET, { "session", ":session_id", "timeouts" }, &Client::handle_get_timeouts }, + { HTTP::HttpRequest::Method::POST, { "session", ":session_id", "timeouts" }, &Client::handle_set_timeouts }, { HTTP::HttpRequest::Method::POST, { "session", ":session_id", "url" }, &Client::handle_navigate_to }, { HTTP::HttpRequest::Method::GET, { "session", ":session_id", "url" }, &Client::handle_get_current_url }, { HTTP::HttpRequest::Method::POST, { "session", ":session_id", "back" }, &Client::handle_back }, @@ -440,6 +441,18 @@ ErrorOr Client::handle_get_timeouts(Vector return make_json_value(result); } +// 9.2 Set Timeouts, https://w3c.github.io/webdriver/#dfn-set-timeouts +// POST /session/{session id}/timeouts +ErrorOr Client::handle_set_timeouts(Vector const& parameters, AK::JsonValue const& payload) +{ + dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session//timeouts"); + auto* session = TRY(find_session_with_id(parameters[0])); + + // NOTE: Spec steps handled in Session::set_timeouts(). + auto result = TRY(session->set_timeouts(payload)); + return make_json_value(result); +} + // 10.1 Navigate To, https://w3c.github.io/webdriver/#dfn-navigate-to // POST /session/{session id}/url ErrorOr Client::handle_navigate_to(Vector const& parameters, JsonValue const& payload) diff --git a/Userland/Services/WebDriver/Client.h b/Userland/Services/WebDriver/Client.h index c08223d015..16c65f0dd1 100644 --- a/Userland/Services/WebDriver/Client.h +++ b/Userland/Services/WebDriver/Client.h @@ -51,6 +51,7 @@ private: ErrorOr handle_delete_session(Vector const&, JsonValue const& payload); ErrorOr handle_get_status(Vector const&, JsonValue const& payload); ErrorOr handle_get_timeouts(Vector const&, JsonValue const& payload); + ErrorOr handle_set_timeouts(Vector const&, JsonValue const& payload); ErrorOr handle_navigate_to(Vector const&, JsonValue const& payload); ErrorOr handle_get_current_url(Vector const&, JsonValue const& payload); ErrorOr handle_back(Vector const&, JsonValue const& payload); diff --git a/Userland/Services/WebDriver/Session.cpp b/Userland/Services/WebDriver/Session.cpp index 964c3b31b2..52265574d5 100644 --- a/Userland/Services/WebDriver/Session.cpp +++ b/Userland/Services/WebDriver/Session.cpp @@ -83,6 +83,19 @@ JsonObject Session::get_timeouts() return timeouts; } +// 9.2 Set Timeouts, https://w3c.github.io/webdriver/#dfn-set-timeouts +ErrorOr Session::set_timeouts(JsonValue const& payload) +{ + // 1. Let timeouts be the result of trying to JSON deserialize as a timeouts configuration the request’s parameters. + auto timeouts = TRY(json_deserialize_as_a_timeouts_configuration(payload)); + + // 2. Make the session timeouts the new timeouts. + m_timeouts_configuration = move(timeouts); + + // 3. Return success with data null. + return JsonValue {}; +} + // 10.1 Navigate To, https://w3c.github.io/webdriver/#dfn-navigate-to ErrorOr Session::navigate_to(JsonValue const& payload) { diff --git a/Userland/Services/WebDriver/Session.h b/Userland/Services/WebDriver/Session.h index bbf3ba073a..3cf85cee47 100644 --- a/Userland/Services/WebDriver/Session.h +++ b/Userland/Services/WebDriver/Session.h @@ -40,6 +40,7 @@ public: ErrorOr start(); ErrorOr stop(); JsonObject get_timeouts(); + ErrorOr set_timeouts(JsonValue const& payload); ErrorOr navigate_to(JsonValue const& url); ErrorOr get_current_url(); ErrorOr back(); diff --git a/Userland/Services/WebDriver/TimeoutsConfiguration.cpp b/Userland/Services/WebDriver/TimeoutsConfiguration.cpp index a127ca1795..93c2d315f8 100644 --- a/Userland/Services/WebDriver/TimeoutsConfiguration.cpp +++ b/Userland/Services/WebDriver/TimeoutsConfiguration.cpp @@ -5,6 +5,7 @@ */ #include +#include #include namespace WebDriver { @@ -33,4 +34,59 @@ JsonObject timeouts_object(TimeoutsConfiguration const& timeouts) return timeouts_object; } +// https://w3c.github.io/webdriver/#ref-for-dfn-json-deserialize-3 +ErrorOr json_deserialize_as_a_timeouts_configuration(JsonValue const& value) +{ + constexpr i64 max_safe_integer = 9007199254740991; + + // 1. Let timeouts be a new timeouts configuration. + auto timeouts = TimeoutsConfiguration {}; + + // 2. If value is not a JSON Object, return error with error code invalid argument. + if (!value.is_object()) + return HttpError { 400, "invalid argument", "Payload is not a JSON object" }; + + // 3. If value has a property with the key "script": + if (value.as_object().has("script"sv)) { + // 1. Let script duration be the value of property "script". + auto const& script_duration = value.as_object().get("script"sv); + + // 2. If script duration is a number and less than 0 or greater than maximum safe integer, or it is not null, return error with error code invalid argument. + if ((script_duration.is_number() && (script_duration.to_i64() < 0 || script_duration.to_i64() > max_safe_integer)) || !script_duration.is_null()) + return HttpError { 400, "invalid argument", "Invalid script duration" }; + + // 3. Set timeouts’s script timeout to script duration. + timeouts.script_timeout = script_duration.is_null() ? Optional {} : script_duration.to_u64(); + } + + // 4. If value has a property with the key "pageLoad": + if (value.as_object().has("pageLoad"sv)) { + // 1. Let page load duration be the value of property "pageLoad". + auto const& page_load_duration = value.as_object().get("pageLoad"sv); + + // 2. If page load duration is less than 0 or greater than maximum safe integer, return error with error code invalid argument. + if (!page_load_duration.is_number() || page_load_duration.to_i64() < 0 || page_load_duration.to_i64() > max_safe_integer) + return HttpError { 400, "invalid argument", "Invalid page load duration" }; + + // 3. Set timeouts’s page load timeout to page load duration. + timeouts.page_load_timeout = page_load_duration.to_u64(); + } + + // 5. If value has a property with the key "implicit": + if (value.as_object().has("implicit"sv)) { + // 1. Let implicit duration be the value of property "implicit". + auto const& implicit_duration = value.as_object().get("implicit"sv); + + // 2. If implicit duration is less than 0 or greater than maximum safe integer, return error with error code invalid argument. + if (!implicit_duration.is_number() || implicit_duration.to_i64() < 0 || implicit_duration.to_i64() > max_safe_integer) + return HttpError { 400, "invalid argument", "Invalid implicit duration" }; + + // 3. Set timeouts’s implicit wait timeout to implicit duration. + timeouts.implicit_wait_timeout = implicit_duration.to_u64(); + } + + // 6. Return success with data timeouts. + return timeouts; +} + } diff --git a/Userland/Services/WebDriver/TimeoutsConfiguration.h b/Userland/Services/WebDriver/TimeoutsConfiguration.h index f9048cd49d..8b7e52a43f 100644 --- a/Userland/Services/WebDriver/TimeoutsConfiguration.h +++ b/Userland/Services/WebDriver/TimeoutsConfiguration.h @@ -19,5 +19,6 @@ struct TimeoutsConfiguration { }; JsonObject timeouts_object(TimeoutsConfiguration const&); +ErrorOr json_deserialize_as_a_timeouts_configuration(JsonValue const&); }