diff --git a/Userland/Services/WebContent/WebDriverClient.ipc b/Userland/Services/WebContent/WebDriverClient.ipc index 91cc04ba15..41cf2401e8 100644 --- a/Userland/Services/WebContent/WebDriverClient.ipc +++ b/Userland/Services/WebContent/WebDriverClient.ipc @@ -1,7 +1,11 @@ +#include #include endpoint WebDriverClient { close_session() => () + set_page_load_strategy(Web::WebDriver::PageLoadStrategy page_load_strategy) =| + set_unhandled_prompt_behavior(Web::WebDriver::UnhandledPromptBehavior unhandled_prompt_behavior) =| + set_strict_file_interactability(bool strict_file_interactability) =| set_is_webdriver_active(bool active) =| get_timeouts() => (Web::WebDriver::Response response) set_timeouts(JsonValue payload) => (Web::WebDriver::Response response) diff --git a/Userland/Services/WebContent/WebDriverConnection.cpp b/Userland/Services/WebContent/WebDriverConnection.cpp index 015b9dd0d1..8540ad8133 100644 --- a/Userland/Services/WebContent/WebDriverConnection.cpp +++ b/Userland/Services/WebContent/WebDriverConnection.cpp @@ -280,6 +280,21 @@ void WebDriverConnection::close_session() m_page_host.page().top_level_browsing_context().close(); } +void WebDriverConnection::set_page_load_strategy(Web::WebDriver::PageLoadStrategy const& page_load_strategy) +{ + m_page_load_strategy = page_load_strategy; +} + +void WebDriverConnection::set_unhandled_prompt_behavior(Web::WebDriver::UnhandledPromptBehavior const& unhandled_prompt_behavior) +{ + m_unhandled_prompt_behavior = unhandled_prompt_behavior; +} + +void WebDriverConnection::set_strict_file_interactability(bool strict_file_interactability) +{ + m_strict_file_interactability = strict_file_interactability; +} + void WebDriverConnection::set_is_webdriver_active(bool is_webdriver_active) { m_page_host.set_is_webdriver_active(is_webdriver_active); diff --git a/Userland/Services/WebContent/WebDriverConnection.h b/Userland/Services/WebContent/WebDriverConnection.h index 4d00ca8853..134a3a3292 100644 --- a/Userland/Services/WebContent/WebDriverConnection.h +++ b/Userland/Services/WebContent/WebDriverConnection.h @@ -37,6 +37,9 @@ private: virtual void die() override { } virtual void close_session() override; + virtual void set_page_load_strategy(Web::WebDriver::PageLoadStrategy const& page_load_strategy) override; + virtual void set_unhandled_prompt_behavior(Web::WebDriver::UnhandledPromptBehavior const& unhandled_prompt_behavior) override; + virtual void set_strict_file_interactability(bool strict_file_interactability) override; virtual void set_is_webdriver_active(bool) override; virtual Messages::WebDriverClient::GetTimeoutsResponse get_timeouts() override; virtual Messages::WebDriverClient::SetTimeoutsResponse set_timeouts(JsonValue const& payload) override; @@ -102,6 +105,15 @@ private: ConnectionFromClient& m_web_content_client; PageHost& m_page_host; + // https://w3c.github.io/webdriver/#dfn-page-load-strategy + Web::WebDriver::PageLoadStrategy m_page_load_strategy { Web::WebDriver::PageLoadStrategy::Normal }; + + // https://w3c.github.io/webdriver/#dfn-unhandled-prompt-behavior + Web::WebDriver::UnhandledPromptBehavior m_unhandled_prompt_behavior { Web::WebDriver::UnhandledPromptBehavior::DismissAndNotify }; + + // https://w3c.github.io/webdriver/#dfn-strict-file-interactability + bool m_strict_file_interactability { false }; + // https://w3c.github.io/webdriver/#dfn-session-script-timeout Web::WebDriver::TimeoutsConfiguration m_timeouts_configuration; diff --git a/Userland/Services/WebDriver/Client.cpp b/Userland/Services/WebDriver/Client.cpp index 24a777e3fb..6ee64e8073 100644 --- a/Userland/Services/WebDriver/Client.cpp +++ b/Userland/Services/WebDriver/Client.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include namespace WebDriver { @@ -72,6 +73,53 @@ 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 const* strategy = capabilities.get_ptr("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 && strategy->is_string()) + web_content_connection.async_set_page_load_strategy(Web::WebDriver::page_load_strategy_from_string(strategy->as_string())); + else + capabilities.set("pageLoadStrategy"sv, "normal"sv); + + // 3. Let strictFileInteractability be the result of getting property "strictFileInteractability" from capabilities. + auto const* strict_file_interactiblity = capabilities.get_ptr("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 && strict_file_interactiblity->is_bool()) + web_content_connection.async_set_strict_file_interactability(strict_file_interactiblity->as_bool()); + 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 const* timeouts = capabilities.get_ptr("timeouts"sv); timeouts && timeouts->is_object()) { + // 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 const* behavior = capabilities.get_ptr("unhandledPromptBehavior"sv); + if (behavior && behavior->is_string()) + web_content_connection.async_set_unhandled_prompt_behavior(Web::WebDriver::unhandled_prompt_behavior_from_string(behavior->as_string())); + 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) @@ -119,6 +167,11 @@ Web::WebDriver::Response Client::new_session(Web::WebDriver::Parameters, JsonVal // 10. Append session to active sessions. Client::s_sessions.append(move(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()); + // 11. Let body be a JSON Object initialized with: JsonObject body; // "sessionId" @@ -128,9 +181,6 @@ Web::WebDriver::Response Client::new_session(Web::WebDriver::Parameters, JsonVal // capabilities body.set("capabilities", move(capabilities)); - // FIXME: 12. Initialize the following from capabilities: - // NOTE: See spec for steps - // 13. Set the webdriver-active flag to true. web_content_connection.async_set_is_webdriver_active(true);