diff --git a/Userland/Services/WebContent/WebDriverConnection.cpp b/Userland/Services/WebContent/WebDriverConnection.cpp index 43c23592c94..6f1672e10c7 100644 --- a/Userland/Services/WebContent/WebDriverConnection.cpp +++ b/Userland/Services/WebContent/WebDriverConnection.cpp @@ -279,7 +279,8 @@ Messages::WebDriverClient::SetTimeoutsResponse WebDriverConnection::set_timeouts // 2. Make the session timeouts the new timeouts. // 3. Return success with data null. - return JsonValue {}; + // NOTE: We return the current timeouts configuration so the client may store them for new sessions. + return Web::WebDriver::timeouts_object(m_timeouts_configuration); } // 10.1 Navigate To, https://w3c.github.io/webdriver/#navigate-to diff --git a/Userland/Services/WebDriver/Client.cpp b/Userland/Services/WebDriver/Client.cpp index 37752b77262..5db5bc0f32f 100644 --- a/Userland/Services/WebDriver/Client.cpp +++ b/Userland/Services/WebDriver/Client.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include namespace WebDriver { @@ -63,53 +62,6 @@ void Client::close_session(unsigned session_id) dbgln_if(WEBDRIVER_DEBUG, "Unable to shut down session {}: Not found", session_id); } -// Step 12 of https://w3c.github.io/webdriver/#dfn-new-sessions -static void initialize_session_from_capabilities(WebContentConnection& web_content_connection, JsonObject& capabilities) -{ - // 1. Let strategy be the result of getting property "pageLoadStrategy" from capabilities. - auto strategy = capabilities.get_byte_string("pageLoadStrategy"sv); - - // 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". - if (strategy.has_value()) - web_content_connection.async_set_page_load_strategy(Web::WebDriver::page_load_strategy_from_string(*strategy)); - else - capabilities.set("pageLoadStrategy"sv, "normal"sv); - - // 3. Let strictFileInteractability be the result of getting property "strictFileInteractability" from capabilities. - auto strict_file_interactiblity = capabilities.get_bool("strictFileInteractability"sv); - - // 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. - if (strict_file_interactiblity.has_value()) - web_content_connection.async_set_strict_file_interactability(*strict_file_interactiblity); - else - capabilities.set("strictFileInteractability"sv, false); - - // FIXME: 5. Let proxy be the result of getting property "proxy" from capabilities and run the substeps of the first matching statement: - // FIXME: proxy is a proxy configuration object - // 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. - // FIXME: Otherwise - // FIXME: Set a property of capabilities with name "proxy" and a value that is a new JSON Object. - - // 6. If capabilities has a property with the key "timeouts": - if (auto timeouts = capabilities.get_object("timeouts"sv); timeouts.has_value()) { - // a. Let timeouts be the result of trying to JSON deserialize as a timeouts configuration the value of the "timeouts" property. - // NOTE: This happens on the remote end. - - // b. Make the session timeouts the new timeouts. - MUST(web_content_connection.set_timeouts(*timeouts)); - } else { - // 7. Set a property on capabilities with name "timeouts" and value that of the JSON deserialization of the session timeouts. - capabilities.set("timeouts"sv, Web::WebDriver::timeouts_object({})); - } - - // 8. Apply changes to the user agent for any implementation-defined capabilities selected during the capabilities processing step. - auto behavior = capabilities.get_byte_string("unhandledPromptBehavior"sv); - if (behavior.has_value()) - web_content_connection.async_set_unhandled_prompt_behavior(Web::WebDriver::unhandled_prompt_behavior_from_string(*behavior)); - else - capabilities.set("unhandledPromptBehavior"sv, "dismiss and notify"sv); -} - // 8.1 New Session, https://w3c.github.io/webdriver/#dfn-new-sessions // POST /session Web::WebDriver::Response Client::new_session(Web::WebDriver::Parameters, JsonValue payload) @@ -155,12 +107,12 @@ Web::WebDriver::Response Client::new_session(Web::WebDriver::Parameters, JsonVal // with arguments session and capabilities. // 10. Append session to active sessions. - s_sessions.set(session_id, move(session)); + s_sessions.set(session_id, session); // NOTE: We do step 12 before 11 because step 12 mutates the capabilities we set in step 11. // 12. Initialize the following from capabilities: - initialize_session_from_capabilities(web_content_connection, capabilities.as_object()); + session->initialize_from_capabilities(capabilities.as_object()); // 11. Let body be a JSON Object initialized with: JsonObject body; @@ -232,7 +184,7 @@ Web::WebDriver::Response Client::set_timeouts(Web::WebDriver::Parameters paramet { dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session//timeouts"); auto session = TRY(find_session_with_id(parameters[0])); - return session->web_content_connection().set_timeouts(payload); + return session->set_timeouts(move(payload)); } // 10.1 Navigate To, https://w3c.github.io/webdriver/#dfn-navigate-to diff --git a/Userland/Services/WebDriver/Session.cpp b/Userland/Services/WebDriver/Session.cpp index 615472bc24a..5fb77e41dca 100644 --- a/Userland/Services/WebDriver/Session.cpp +++ b/Userland/Services/WebDriver/Session.cpp @@ -11,10 +11,10 @@ #include "Session.h" #include "Client.h" #include -#include #include #include #include +#include #include namespace WebDriver { @@ -53,6 +53,60 @@ Session::~Session() } } +// Step 12 of https://w3c.github.io/webdriver/#dfn-new-sessions +void Session::initialize_from_capabilities(JsonObject& capabilities) +{ + auto& connection = web_content_connection(); + + // 1. Let strategy be the result of getting property "pageLoadStrategy" from capabilities. + auto strategy = capabilities.get_byte_string("pageLoadStrategy"sv); + + // 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". + if (strategy.has_value()) { + m_page_load_strategy = Web::WebDriver::page_load_strategy_from_string(*strategy); + connection.async_set_page_load_strategy(m_page_load_strategy); + } else { + capabilities.set("pageLoadStrategy"sv, "normal"sv); + } + + // 3. Let strictFileInteractability be the result of getting property "strictFileInteractability" from capabilities. + auto strict_file_interactiblity = capabilities.get_bool("strictFileInteractability"sv); + + // 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. + if (strict_file_interactiblity.has_value()) { + m_strict_file_interactiblity = *strict_file_interactiblity; + connection.async_set_strict_file_interactability(m_strict_file_interactiblity); + } else { + capabilities.set("strictFileInteractability"sv, false); + } + + // FIXME: 5. Let proxy be the result of getting property "proxy" from capabilities and run the substeps of the first matching statement: + // FIXME: proxy is a proxy configuration object + // 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. + // FIXME: Otherwise + // FIXME: Set a property of capabilities with name "proxy" and a value that is a new JSON Object. + + // 6. If capabilities has a property with the key "timeouts": + if (auto timeouts = capabilities.get_object("timeouts"sv); timeouts.has_value()) { + // a. Let timeouts be the result of trying to JSON deserialize as a timeouts configuration the value of the "timeouts" property. + // NOTE: This happens on the remote end. + + // b. Make the session timeouts the new timeouts. + MUST(set_timeouts(*timeouts)); + } else { + // 7. Set a property on capabilities with name "timeouts" and value that of the JSON deserialization of the session timeouts. + capabilities.set("timeouts"sv, Web::WebDriver::timeouts_object({})); + } + + // 8. Apply changes to the user agent for any implementation-defined capabilities selected during the capabilities processing step. + if (auto behavior = capabilities.get_byte_string("unhandledPromptBehavior"sv); behavior.has_value()) { + m_unhandled_prompt_behavior = Web::WebDriver::unhandled_prompt_behavior_from_string(*behavior); + connection.async_set_unhandled_prompt_behavior(m_unhandled_prompt_behavior); + } else { + capabilities.set("unhandledPromptBehavior"sv, "dismiss and notify"sv); + } +} + ErrorOr> Session::create_server(NonnullRefPtr promise) { static_assert(IsSame, "Need to handle other IPC transports here"); @@ -123,6 +177,12 @@ ErrorOr Session::start(LaunchBrowserCallbacks const& callbacks) return {}; } +Web::WebDriver::Response Session::set_timeouts(JsonValue payload) +{ + m_timeouts_configuration = TRY(web_content_connection().set_timeouts(move(payload))); + return JsonValue {}; +} + // 11.2 Close Window, https://w3c.github.io/webdriver/#dfn-close-window Web::WebDriver::Response Session::close_window() { diff --git a/Userland/Services/WebDriver/Session.h b/Userland/Services/WebDriver/Session.h index c0b00d80f64..6c8bd05e212 100644 --- a/Userland/Services/WebDriver/Session.h +++ b/Userland/Services/WebDriver/Session.h @@ -9,12 +9,14 @@ #pragma once #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -29,6 +31,8 @@ public: Session(unsigned session_id, NonnullRefPtr client, Web::WebDriver::LadybirdOptions options); ~Session(); + void initialize_from_capabilities(JsonObject&); + unsigned session_id() const { return m_id; } struct Window { @@ -52,6 +56,8 @@ public: bool has_window_handle(StringView handle) const { return m_windows.contains(handle); } ErrorOr start(LaunchBrowserCallbacks const&); + + Web::WebDriver::Response set_timeouts(JsonValue); Web::WebDriver::Response close_window(); Web::WebDriver::Response switch_to_window(StringView); Web::WebDriver::Response get_window_handles() const; @@ -92,6 +98,11 @@ private: Optional m_browser_pid; RefPtr m_web_content_server; + + Web::WebDriver::PageLoadStrategy m_page_load_strategy { Web::WebDriver::PageLoadStrategy::Normal }; + Web::WebDriver::UnhandledPromptBehavior m_unhandled_prompt_behavior { Web::WebDriver::UnhandledPromptBehavior::DismissAndNotify }; + Optional m_timeouts_configuration; + bool m_strict_file_interactiblity { false }; }; }