From 2583996e183f6ce9d47769965b8ae2b25932b93e Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Wed, 5 Feb 2025 11:36:19 -0500 Subject: [PATCH] LibWeb+WebContent+WebDriver: Allow specifying multiple prompt handlers WebDriver script authors may now provide either: * A user prompt handler configuration to be used for all prompt types. * A set of per-prompt-type user prompt handlers. This also paves the way for interaction with the beforeunload prompt, though we do not yet support that feature in LibWeb. See: https://github.com/w3c/webdriver/commit/43903d0 --- Libraries/LibWeb/CMakeLists.txt | 1 + Libraries/LibWeb/WebDriver/Capabilities.cpp | 18 +- Libraries/LibWeb/WebDriver/Capabilities.h | 26 +-- Libraries/LibWeb/WebDriver/UserPrompt.cpp | 184 ++++++++++++++++++++ Libraries/LibWeb/WebDriver/UserPrompt.h | 67 +++++++ Services/WebContent/WebDriverClient.ipc | 3 +- Services/WebContent/WebDriverConnection.cpp | 119 +++++++++---- Services/WebContent/WebDriverConnection.h | 8 +- Services/WebDriver/Session.cpp | 12 +- Services/WebDriver/Session.h | 3 +- 10 files changed, 349 insertions(+), 92 deletions(-) create mode 100644 Libraries/LibWeb/WebDriver/UserPrompt.cpp create mode 100644 Libraries/LibWeb/WebDriver/UserPrompt.h diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index 01f413f573e..d3802d11ce5 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -828,6 +828,7 @@ set(SOURCES WebDriver/Response.cpp WebDriver/Screenshot.cpp WebDriver/TimeoutsConfiguration.cpp + WebDriver/UserPrompt.cpp WebGL/Extensions/ANGLEInstancedArrays.cpp WebGL/Extensions/OESVertexArrayObject.cpp WebGL/Extensions/WebGLDrawBuffers.cpp diff --git a/Libraries/LibWeb/WebDriver/Capabilities.cpp b/Libraries/LibWeb/WebDriver/Capabilities.cpp index a812cd51dcf..32af6757a30 100644 --- a/Libraries/LibWeb/WebDriver/Capabilities.cpp +++ b/Libraries/LibWeb/WebDriver/Capabilities.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Tim Flynn + * Copyright (c) 2022-2025, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -12,6 +12,7 @@ #include #include #include +#include namespace Web::WebDriver { @@ -30,21 +31,6 @@ static Response deserialize_as_a_page_load_strategy(JsonValue value) return value; } -// https://w3c.github.io/webdriver/#dfn-deserialize-as-an-unhandled-prompt-behavior -static Response deserialize_as_an_unhandled_prompt_behavior(JsonValue value) -{ - // 1. If value is not a string return an error with error code invalid argument. - if (!value.is_string()) - return Error::from_code(ErrorCode::InvalidArgument, "Capability unhandledPromptBehavior must be a string"sv); - - // 2. If value is not present as a keyword in the known prompt handling approaches table return an error with error code invalid argument. - if (!value.as_string().is_one_of("dismiss"sv, "accept"sv, "dismiss and notify"sv, "accept and notify"sv, "ignore"sv)) - return Error::from_code(ErrorCode::InvalidArgument, "Invalid pageLoadStrategy capability"sv); - - // 3. Return success with data value. - return value; -} - // https://w3c.github.io/webdriver/#dfn-deserialize-as-a-proxy static ErrorOr deserialize_as_a_proxy(JsonValue parameter) { diff --git a/Libraries/LibWeb/WebDriver/Capabilities.h b/Libraries/LibWeb/WebDriver/Capabilities.h index 27fb4a0a5e1..1939a39a652 100644 --- a/Libraries/LibWeb/WebDriver/Capabilities.h +++ b/Libraries/LibWeb/WebDriver/Capabilities.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Tim Flynn + * Copyright (c) 2022-2025, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -30,30 +30,6 @@ constexpr PageLoadStrategy page_load_strategy_from_string(StringView strategy) VERIFY_NOT_REACHED(); } -// https://w3c.github.io/webdriver/#dfn-unhandled-prompt-behavior -enum class UnhandledPromptBehavior { - Dismiss, - Accept, - DismissAndNotify, - AcceptAndNotify, - Ignore, -}; - -constexpr UnhandledPromptBehavior unhandled_prompt_behavior_from_string(StringView behavior) -{ - if (behavior == "dismiss"sv) - return UnhandledPromptBehavior::Dismiss; - if (behavior == "accept"sv) - return UnhandledPromptBehavior::Accept; - if (behavior == "dismiss and notify"sv) - return UnhandledPromptBehavior::DismissAndNotify; - if (behavior == "accept and notify"sv) - return UnhandledPromptBehavior::AcceptAndNotify; - if (behavior == "ignore"sv) - return UnhandledPromptBehavior::Ignore; - VERIFY_NOT_REACHED(); -} - enum class InterfaceMode { Graphical, Headless, diff --git a/Libraries/LibWeb/WebDriver/UserPrompt.cpp b/Libraries/LibWeb/WebDriver/UserPrompt.cpp new file mode 100644 index 00000000000..f97b9edac5e --- /dev/null +++ b/Libraries/LibWeb/WebDriver/UserPrompt.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2025, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include + +namespace Web::WebDriver { + +// https://w3c.github.io/webdriver/#dfn-user-prompt-handler +static UserPromptHandler s_user_prompt_handler; + +// https://w3c.github.io/webdriver/#dfn-known-prompt-handlers +static constexpr Array known_prompt_handlers { "dismiss"sv, "accept"sv, "dismiss and notify"sv, "accept and notify"sv, "ignore"sv }; + +// https://w3c.github.io/webdriver/#dfn-valid-prompt-types +static constexpr Array valid_prompt_types { "alert"sv, "beforeUnload"sv, "confirm"sv, "default"sv, "prompt"sv }; + +static constexpr PromptHandler prompt_handler_from_string(StringView prompt_handler) +{ + if (prompt_handler == "dismiss"sv) + return PromptHandler::Dismiss; + if (prompt_handler == "accept"sv) + return PromptHandler::Accept; + if (prompt_handler == "ignore"sv) + return PromptHandler::Ignore; + VERIFY_NOT_REACHED(); +} + +static constexpr PromptType prompt_type_from_string(StringView prompt_type) +{ + if (prompt_type == "alert"sv) + return PromptType::Alert; + if (prompt_type == "beforeUnload"sv) + return PromptType::BeforeUnload; + if (prompt_type == "confirm"sv) + return PromptType::Confirm; + if (prompt_type == "default"sv) + return PromptType::Default; + if (prompt_type == "prompt"sv) + return PromptType::Prompt; + if (prompt_type == "fallbackDefault"sv) + return PromptType::FallbackDefault; + VERIFY_NOT_REACHED(); +} + +PromptHandlerConfiguration PromptHandlerConfiguration::deserialize(JsonValue const& configuration) +{ + auto handler = prompt_handler_from_string(*configuration.as_object().get_byte_string("handler"sv)); + + auto notify = *configuration.as_object().get_bool("notify"sv) + ? PromptHandlerConfiguration::Notify::Yes + : PromptHandlerConfiguration::Notify::No; + + return { .handler = handler, .notify = notify }; +} + +UserPromptHandler const& user_prompt_handler() +{ + return s_user_prompt_handler; +} + +void set_user_prompt_handler(UserPromptHandler user_prompt_handler) +{ + s_user_prompt_handler = move(user_prompt_handler); +} + +// https://w3c.github.io/webdriver/#dfn-deserialize-as-an-unhandled-prompt-behavior +Response deserialize_as_an_unhandled_prompt_behavior(JsonValue value) +{ + // 1. Set value to the result of converting a JSON-derived JavaScript value to an Infra value with value. + // 2. If value is not a string, an implementation that does not also support [WebDriver-BiDi] may return error with + // error code invalid argument. + + // 3. Let is string value be false. + bool is_string_value = false; + + // 3. If value is a string set value to the map «["fallbackDefault" → value]» and set is string value to true. + if (value.is_string()) { + JsonObject map; + map.set("fallbackDefault"sv, move(value)); + + value = move(map); + is_string_value = true; + } + + // 4. If value is not a map return error with error code invalid argument. + if (!value.is_object()) + return WebDriver::Error::from_code(ErrorCode::InvalidArgument, "Capability unhandledPromptBehavior must be a string or object"sv); + + // 5. Let user prompt handler be an empty map. + JsonObject user_prompt_handler; + + // 6. For each prompt type → handler in value: + TRY(value.as_object().try_for_each_member([&](ByteString const& prompt_type, JsonValue const& handler_value) -> ErrorOr { + // 1. If is string value is false and valid prompt types does not contain prompt type return error with error code invalid argument. + if (!is_string_value && !valid_prompt_types.contains_slow(prompt_type)) + return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("'{}' is not a valid prompt type", prompt_type)); + + // 2. If known prompt handlers does not contain an entry with handler key handler return error with error code invalid argument. + if (!handler_value.is_string()) + return WebDriver::Error::from_code(ErrorCode::InvalidArgument, "Prompt handler must be a string"sv); + + StringView handler = handler_value.as_string(); + + if (!known_prompt_handlers.contains_slow(handler)) + return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("'{}' is not a known prompt handler", handler)); + + // 3. Let notify be false. + bool notify = false; + + // 4. If handler is "accept and notify", set handler to "accept" and notify to true. + if (handler == "accept and notify"sv) { + handler = "accept"sv; + notify = true; + } + + // 5. If handler is "dismiss and notify", set handler to "dismiss" and notify to true. + else if (handler == "dismiss and notify"sv) { + handler = "dismiss"sv; + notify = true; + } + + // 6. If handler is "ignore", set notify to true. + else if (handler == "ignore"sv) { + notify = true; + } + + // 7. Let configuration be a prompt handler configuration with handler handler and notify notify. + JsonObject configuration; + configuration.set("handler"sv, handler); + configuration.set("notify"sv, notify); + + // 8. Set user prompt handler[prompt type] to configuration. + user_prompt_handler.set(prompt_type, move(configuration)); + + return {}; + })); + + // Return success with data user prompt handler. + return JsonValue { move(user_prompt_handler) }; +} + +// https://w3c.github.io/webdriver/#dfn-update-the-user-prompt-handler +void update_the_user_prompt_handler(JsonObject const& requested_prompt_handler) +{ + // 1. If the user prompt handler is null, set the user prompt handler to an empty map. + if (!s_user_prompt_handler.has_value()) + s_user_prompt_handler = UserPromptHandler::ValueType {}; + + // 2. For each request prompt type → request handler in requested prompt handler: + requested_prompt_handler.for_each_member([&](ByteString const& request_prompt_type, JsonValue const& request_handler) { + // 1. Set user prompt handler[request prompt type] to request handler. + s_user_prompt_handler->set( + prompt_type_from_string(request_prompt_type), + PromptHandlerConfiguration::deserialize(request_handler)); + }); +} + +} + +template<> +ErrorOr IPC::encode(Encoder& encoder, Web::WebDriver::PromptHandlerConfiguration const& configuration) +{ + TRY(encoder.encode(configuration.handler)); + TRY(encoder.encode(configuration.notify)); + + return {}; +} + +template<> +ErrorOr IPC::decode(Decoder& decoder) +{ + auto handler = TRY(decoder.decode()); + auto notify = TRY(decoder.decode()); + + return Web::WebDriver::PromptHandlerConfiguration { .handler = handler, .notify = notify }; +} diff --git a/Libraries/LibWeb/WebDriver/UserPrompt.h b/Libraries/LibWeb/WebDriver/UserPrompt.h new file mode 100644 index 00000000000..a1e4e907328 --- /dev/null +++ b/Libraries/LibWeb/WebDriver/UserPrompt.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2025, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace Web::WebDriver { + +// https://w3c.github.io/webdriver/#dfn-known-prompt-handlers +enum class PromptHandler { + Accept, + Dismiss, + Ignore, +}; + +// https://w3c.github.io/webdriver/#dfn-valid-prompt-types +enum class PromptType { + Alert, + BeforeUnload, + Confirm, + Default, + Prompt, + FallbackDefault, +}; + +// https://w3c.github.io/webdriver/#dfn-prompt-handler-configuration +struct PromptHandlerConfiguration { + enum class Notify { + No, + Yes, + }; + + static PromptHandlerConfiguration deserialize(JsonValue const&); + + PromptHandler handler { PromptHandler::Dismiss }; + Notify notify { Notify::Yes }; +}; + +// https://w3c.github.io/webdriver/#dfn-user-prompt-handler +using UserPromptHandler = Optional>; + +UserPromptHandler const& user_prompt_handler(); +void set_user_prompt_handler(UserPromptHandler); + +Response deserialize_as_an_unhandled_prompt_behavior(JsonValue); +void update_the_user_prompt_handler(JsonObject const&); + +} + +namespace IPC { + +template<> +ErrorOr encode(Encoder&, Web::WebDriver::PromptHandlerConfiguration const&); + +template<> +ErrorOr decode(Decoder&); + +} diff --git a/Services/WebContent/WebDriverClient.ipc b/Services/WebContent/WebDriverClient.ipc index 5ef1de98318..2b6b070ecaf 100644 --- a/Services/WebContent/WebDriverClient.ipc +++ b/Services/WebContent/WebDriverClient.ipc @@ -1,10 +1,11 @@ #include #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_user_prompt_handler(Web::WebDriver::UserPromptHandler user_prompt_handler) =| set_strict_file_interactability(bool strict_file_interactability) =| set_is_webdriver_active(bool active) =| get_timeouts() => (Web::WebDriver::Response response) diff --git a/Services/WebContent/WebDriverConnection.cpp b/Services/WebContent/WebDriverConnection.cpp index 9df439f5b54..47374012de3 100644 --- a/Services/WebContent/WebDriverConnection.cpp +++ b/Services/WebContent/WebDriverConnection.cpp @@ -3,7 +3,7 @@ * Copyright (c) 2022-2023, Sam Atkins * Copyright (c) 2022, Tobias Christiansen * Copyright (c) 2022, Linus Groh - * Copyright (c) 2022-2024, Tim Flynn + * Copyright (c) 2022-2025, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -59,6 +59,7 @@ #include #include #include +#include #include namespace WebContent { @@ -232,9 +233,9 @@ void WebDriverConnection::set_page_load_strategy(Web::WebDriver::PageLoadStrateg m_page_load_strategy = page_load_strategy; } -void WebDriverConnection::set_unhandled_prompt_behavior(Web::WebDriver::UnhandledPromptBehavior const& unhandled_prompt_behavior) +void WebDriverConnection::set_user_prompt_handler(Web::WebDriver::UserPromptHandler const& user_prompt_handler) { - m_unhandled_prompt_behavior = unhandled_prompt_behavior; + Web::WebDriver::set_user_prompt_handler(move(const_cast(user_prompt_handler))); } void WebDriverConnection::set_strict_file_interactability(bool strict_file_interactability) @@ -2636,58 +2637,100 @@ ErrorOr WebDriverConnection::ensure_current_top_lev return Web::WebDriver::ensure_browsing_context_is_open(current_top_level_browsing_context()); } +// https://w3c.github.io/webdriver/#dfn-get-the-prompt-handler +Web::WebDriver::PromptHandlerConfiguration WebDriverConnection::get_the_prompt_handler(Web::WebDriver::PromptType type) const +{ + static Web::WebDriver::UserPromptHandler::ValueType empty_user_prompt_handler; + auto const& user_prompt_handler = Web::WebDriver::user_prompt_handler(); + + // 1. If the user prompt handler is null, let handlers be an empty map. Otherwise let handlers be user prompt handler. + auto const& handlers = user_prompt_handler.has_value() ? *user_prompt_handler : empty_user_prompt_handler; + + // 2. If handlers contains type return handlers[type]. + if (auto handler = handlers.get(type); handler.has_value()) + return *handler; + + // 3. If handlers contains "default" return handlers["default"]. + if (auto handler = handlers.get(Web::WebDriver::PromptType::Default); handler.has_value()) + return *handler; + + // 4. If type is "beforeUnload", return a prompt handler configuration with handler "accept" and notify false. + if (type == Web::WebDriver::PromptType::BeforeUnload) + return { .handler = Web::WebDriver::PromptHandler::Accept, .notify = Web::WebDriver::PromptHandlerConfiguration::Notify::No }; + + // 5. If handlers contains "fallbackDefault" return handlers["fallbackDefault"]. + if (auto handler = handlers.get(Web::WebDriver::PromptType::FallbackDefault); handler.has_value()) + return *handler; + + // 6. Return a prompt handler configuration with handler "dismiss" and notify true. + return { .handler = Web::WebDriver::PromptHandler::Dismiss, .notify = Web::WebDriver::PromptHandlerConfiguration::Notify::Yes }; +} + // https://w3c.github.io/webdriver/#dfn-handle-any-user-prompts void WebDriverConnection::handle_any_user_prompts(Function on_dialog_closed) { auto& page = current_browsing_context().page(); auto& heap = current_browsing_context().heap(); - // 1. If there is no current user prompt, abort these steps and return success. + // 1. If the current browsing context is not blocked by a dialog return success. if (!page.has_pending_dialog()) { on_dialog_closed(); return; } - // 2. Perform the following substeps based on the current session’s user prompt handler: - switch (m_unhandled_prompt_behavior) { - // -> dismiss state - case Web::WebDriver::UnhandledPromptBehavior::Dismiss: - // Dismiss the current user prompt. - page.dismiss_dialog(GC::create_function(heap, move(on_dialog_closed))); - break; + // 2. Let type be "default". + auto type = Web::WebDriver::PromptType::Default; - // -> accept state - case Web::WebDriver::UnhandledPromptBehavior::Accept: - // Accept the current user prompt. - page.accept_dialog(GC::create_function(heap, move(on_dialog_closed))); + // 3. If the current user prompt is an alert dialog, set type to "alert". Otherwise, if the current user prompt is a + // beforeunload dialog, set type to "beforeUnload". Otherwise, if the current user prompt is a confirm dialog, + // set type to "confirm". Otherwise, if the current user prompt is a prompt dialog, set type to "prompt". + // FIXME: Handle beforeunload dialogs when they are implemented. + switch (page.pending_dialog()) { + case Web::Page::PendingDialog::Alert: + type = Web::WebDriver::PromptType::Alert; break; - - // -> dismiss and notify state - case Web::WebDriver::UnhandledPromptBehavior::DismissAndNotify: - // Dismiss the current user prompt. - page.dismiss_dialog(GC::create_function(heap, [this]() { - // Return an annotated unexpected alert open error. - async_driver_execution_complete(Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::UnexpectedAlertOpen, "A user dialog is open"sv)); - })); + case Web::Page::PendingDialog::Confirm: + type = Web::WebDriver::PromptType::Confirm; break; - - // -> accept and notify state - case Web::WebDriver::UnhandledPromptBehavior::AcceptAndNotify: - // Accept the current user prompt. - page.accept_dialog(GC::create_function(heap, [this]() { - // Return an annotated unexpected alert open error. - async_driver_execution_complete(Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::UnexpectedAlertOpen, "A user dialog is open"sv)); - })); - break; - - // -> ignore state - case Web::WebDriver::UnhandledPromptBehavior::Ignore: - // Return an annotated unexpected alert open error. - async_driver_execution_complete(Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::UnexpectedAlertOpen, "A user dialog is open"sv)); + case Web::Page::PendingDialog::Prompt: + type = Web::WebDriver::PromptType::Prompt; break; + case Web::Page::PendingDialog::None: + VERIFY_NOT_REACHED(); } - // 3. Return success. + // 3. Let handler be get the prompt handler with type. + auto handler = get_the_prompt_handler(type); + + auto on_complete = GC::create_function(heap, [this, notify = handler.notify, on_dialog_closed = GC::create_function(heap, move(on_dialog_closed))]() { + // 5. If handler's notify is true, return annotated unexpected alert open error. + if (notify == Web::WebDriver::PromptHandlerConfiguration::Notify::Yes) { + async_driver_execution_complete(Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::UnexpectedAlertOpen, "A user prompt is open"sv)); + return; + } + + // 6. Return success. + on_dialog_closed->function()(); + }); + + // 4. Perform the following substeps based on handler's handler: + switch (handler.handler) { + // -> "accept" + case Web::WebDriver::PromptHandler::Accept: + // Accept the current user prompt. + page.accept_dialog(on_complete); + break; + // -> "dismiss" + case Web::WebDriver::PromptHandler::Dismiss: + // Dismiss the current user prompt. + page.dismiss_dialog(on_complete); + break; + // -> "ignore" + case Web::WebDriver::PromptHandler::Ignore: + // Do nothing. + on_complete->function()(); + break; + } } // https://w3c.github.io/webdriver/#dfn-wait-for-navigation-to-complete diff --git a/Services/WebContent/WebDriverConnection.h b/Services/WebContent/WebDriverConnection.h index e8177bc0119..44aba6d6cd4 100644 --- a/Services/WebContent/WebDriverConnection.h +++ b/Services/WebContent/WebDriverConnection.h @@ -1,7 +1,7 @@ /* * Copyright (c) 2022, Florent Castelli * Copyright (c) 2022, Linus Groh - * Copyright (c) 2022-2024, Tim Flynn + * Copyright (c) 2022-2025, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -48,7 +48,7 @@ private: 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_user_prompt_handler(Web::WebDriver::UserPromptHandler const& user_prompt_handler) 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; @@ -126,6 +126,7 @@ private: Web::WebDriver::Response element_send_keys_impl(String const& element_id, ByteString const& text); Web::WebDriver::Response add_cookie_impl(JsonObject const&); + Web::WebDriver::PromptHandlerConfiguration get_the_prompt_handler(Web::WebDriver::PromptType type) const; void handle_any_user_prompts(Function on_dialog_closed); void maximize_the_window(); @@ -155,9 +156,6 @@ private: // 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 }; diff --git a/Services/WebDriver/Session.cpp b/Services/WebDriver/Session.cpp index 0c340a8c932..df74e5cc7c6 100644 --- a/Services/WebDriver/Session.cpp +++ b/Services/WebDriver/Session.cpp @@ -3,7 +3,7 @@ * Copyright (c) 2022, Sam Atkins * Copyright (c) 2022, Tobias Christiansen * Copyright (c) 2022, Linus Groh - * Copyright (c) 2022-2024, Tim Flynn + * Copyright (c) 2022-2025, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -15,6 +15,7 @@ #include #include #include +#include #include namespace WebDriver { @@ -98,12 +99,13 @@ void Session::initialize_from_capabilities(JsonObject& capabilities) } // 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); + if (auto behavior = capabilities.get_object("unhandledPromptBehavior"sv); behavior.has_value()) { + Web::WebDriver::update_the_user_prompt_handler(*behavior); } else { capabilities.set("unhandledPromptBehavior"sv, "dismiss and notify"sv); } + + connection.async_set_user_prompt_handler(Web::WebDriver::user_prompt_handler()); } ErrorOr> Session::create_server(NonnullRefPtr promise) @@ -144,7 +146,7 @@ ErrorOr> Session::create_server(NonnullRefPtrasync_set_page_load_strategy(m_page_load_strategy); web_content_connection->async_set_strict_file_interactability(m_strict_file_interactiblity); - web_content_connection->async_set_unhandled_prompt_behavior(m_unhandled_prompt_behavior); + web_content_connection->async_set_user_prompt_handler(Web::WebDriver::user_prompt_handler()); if (m_timeouts_configuration.has_value()) web_content_connection->async_set_timeouts(*m_timeouts_configuration); diff --git a/Services/WebDriver/Session.h b/Services/WebDriver/Session.h index 32e27410368..f5eab93e73a 100644 --- a/Services/WebDriver/Session.h +++ b/Services/WebDriver/Session.h @@ -1,7 +1,7 @@ /* * Copyright (c) 2022, Florent Castelli * Copyright (c) 2022, Linus Groh - * Copyright (c) 2022-2024, Tim Flynn + * Copyright (c) 2022-2025, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -101,7 +101,6 @@ private: 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 }; };