From 7e1caf30a77940e92e83cfc23fcddce22260cc48 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Sun, 3 Nov 2024 07:22:54 -0500 Subject: [PATCH] LibWeb: Implement some window/frame reference WebDriver AOs We must also be careful in how we decide if a window's active browsing context is top-level. --- .../Libraries/LibWeb/WebDriver/Contexts.cpp | 95 ++++++++++++++++++- .../Libraries/LibWeb/WebDriver/Contexts.h | 14 +-- 2 files changed, 100 insertions(+), 9 deletions(-) diff --git a/Userland/Libraries/LibWeb/WebDriver/Contexts.cpp b/Userland/Libraries/LibWeb/WebDriver/Contexts.cpp index 1d4a37399d2..c0d6dcc34e2 100644 --- a/Userland/Libraries/LibWeb/WebDriver/Contexts.cpp +++ b/Userland/Libraries/LibWeb/WebDriver/Contexts.cpp @@ -13,6 +13,12 @@ namespace Web::WebDriver { +// https://w3c.github.io/webdriver/#dfn-web-window-identifier +static ByteString const WEB_WINDOW_IDENTIFIER = "window-fcc6-11e5-b4f8-330a88ab9d7f"sv; + +// https://w3c.github.io/webdriver/#dfn-web-frame-identifier +static ByteString const WEB_FRAME_IDENTIFIER = "frame-075b-4da1-b6ba-e579c2d3230a"sv; + // https://w3c.github.io/webdriver/#dfn-windowproxy-reference-object JsonObject window_proxy_reference_object(HTML::WindowProxy const& window) { @@ -22,9 +28,9 @@ JsonObject window_proxy_reference_object(HTML::WindowProxy const& window) // NOTE: We look at the active browsing context's active document's node navigable instead. // Because a Browsing context's top-level traversable is this navigable's top level traversable. // Ref: https://html.spec.whatwg.org/multipage/document-sequences.html#bc-traversable - auto traversable_navigable = window.associated_browsing_context()->active_document()->navigable()->traversable_navigable(); + auto navigable = window.associated_browsing_context()->active_document()->navigable(); - auto identifier = traversable_navigable->is_top_level_traversable() + auto identifier = navigable->is_top_level_traversable() ? WEB_WINDOW_IDENTIFIER : WEB_FRAME_IDENTIFIER; @@ -33,9 +39,92 @@ JsonObject window_proxy_reference_object(HTML::WindowProxy const& window) // identifier // Associated window handle of the window’s browsing context. - object.set(identifier, traversable_navigable->window_handle().to_byte_string()); + object.set(identifier, navigable->traversable_navigable()->window_handle().to_byte_string()); return object; } +static JS::GCPtr find_navigable_with_handle(StringView handle, bool should_be_top_level) +{ + for (auto* navigable : Web::HTML::all_navigables()) { + if (navigable->is_top_level_traversable() != should_be_top_level) + continue; + + if (navigable->traversable_navigable()->window_handle() == handle) + return navigable; + } + + return {}; +} + +// https://w3c.github.io/webdriver/#dfn-represents-a-web-frame +bool represents_a_web_frame(JS::Value value) +{ + // An ECMAScript Object represents a web frame if it has a web frame identifier own property. + if (!value.is_object()) + return false; + + auto result = value.as_object().has_own_property(WEB_FRAME_IDENTIFIER); + return !result.is_error() && result.value(); +} + +// https://w3c.github.io/webdriver/#dfn-deserialize-a-web-frame +ErrorOr, WebDriver::Error> deserialize_web_frame(JS::Object const& object) +{ + // 1. If object has no own property web frame identifier, return error with error code invalid argument. + auto property = object.get(WEB_FRAME_IDENTIFIER); + if (property.is_error() || !property.value().is_string()) + return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a web frame"sv); + + // 2. Let reference be the result of getting the web frame identifier property from object. + auto reference = property.value().as_string().utf8_string(); + + // 3. Let browsing context be the browsing context whose window handle is reference, or null if no such browsing + // context exists. + auto navigable = find_navigable_with_handle(reference, false); + + // 4. If browsing context is null or a top-level browsing context, return error with error code no such frame. + // NOTE: We filtered on the top-level browsing context condition in the previous step. + if (!navigable) + return WebDriver::Error::from_code(WebDriver::ErrorCode::NoSuchFrame, "Could not locate frame"sv); + + // 5. Return success with data browsing context's associated window. + return *navigable->active_window_proxy(); +} + +// https://w3c.github.io/webdriver/#dfn-represents-a-web-frame +bool represents_a_web_window(JS::Value value) +{ + // An ECMAScript Object represents a web window if it has a web window identifier own property. + if (!value.is_object()) + return false; + + auto result = value.as_object().has_own_property(WEB_WINDOW_IDENTIFIER); + return !result.is_error() && result.value(); +} + +// https://w3c.github.io/webdriver/#dfn-deserialize-a-web-frame +ErrorOr, WebDriver::Error> deserialize_web_window(JS::Object const& object) +{ + // 1. If object has no own property web window identifier, return error with error code invalid argument. + auto property = object.get(WEB_WINDOW_IDENTIFIER); + if (property.is_error() || !property.value().is_string()) + return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a web window"sv); + + // 2. Let reference be the result of getting the web window identifier property from object. + auto reference = property.value().as_string().utf8_string(); + + // 3. Let browsing context be the browsing context whose window handle is reference, or null if no such browsing + // context exists. + auto navigable = find_navigable_with_handle(reference, true); + + // 4. If browsing context is null or not a top-level browsing context, return error with error code no such window. + // NOTE: We filtered on the top-level browsing context condition in the previous step. + if (!navigable) + return WebDriver::Error::from_code(WebDriver::ErrorCode::NoSuchWindow, "Could not locate window"sv); + + // 5. Return success with data browsing context's associated window. + return *navigable->active_window_proxy(); +} + } diff --git a/Userland/Libraries/LibWeb/WebDriver/Contexts.h b/Userland/Libraries/LibWeb/WebDriver/Contexts.h index 11fa2c82f78..ab47caff8d3 100644 --- a/Userland/Libraries/LibWeb/WebDriver/Contexts.h +++ b/Userland/Libraries/LibWeb/WebDriver/Contexts.h @@ -8,16 +8,18 @@ #include #include +#include #include +#include namespace Web::WebDriver { -// https://w3c.github.io/webdriver/#dfn-web-window-identifier -static constexpr auto WEB_WINDOW_IDENTIFIER = "window-fcc6-11e5-b4f8-330a88ab9d7f"sv; - -// https://w3c.github.io/webdriver/#dfn-web-frame-identifier -static constexpr auto WEB_FRAME_IDENTIFIER = "frame-075b-4da1-b6ba-e579c2d3230a"sv; - JsonObject window_proxy_reference_object(HTML::WindowProxy const&); +bool represents_a_web_frame(JS::Value); +ErrorOr, WebDriver::Error> deserialize_web_frame(JS::Object const&); + +bool represents_a_web_window(JS::Value); +ErrorOr, WebDriver::Error> deserialize_web_window(JS::Object const&); + }