Skip to content

Commit

Permalink
LibWeb+WebContent: Partially implement the switch-to-frame endpoint
Browse files Browse the repository at this point in the history
This is needed by the cookie tests for WPT.

(cherry picked from commit 60fa3752ee8c6eecc1e338c8ebebba2e288eea35)
  • Loading branch information
trflynn89 authored and nico committed Nov 24, 2024
1 parent f2b55d1 commit 440c2fa
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 25 deletions.
14 changes: 14 additions & 0 deletions Userland/Libraries/LibWeb/WebDriver/ElementReference.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@ JsonObject web_element_reference_object(Web::DOM::Node const& element)
return object;
}

// https://w3c.github.io/webdriver/#dfn-represents-a-web-element
bool represents_a_web_element(JsonValue const& value)
{
// An ECMAScript Object represents a web element if it has a web element identifier own property.
if (!value.is_object())
return false;

auto const& object = value.as_object();
if (!object.has_string("name"sv) || !object.has_string("value"sv))
return false;

return object.get_byte_string("name"sv) == web_element_identifier;
}

// https://w3c.github.io/webdriver/#dfn-get-a-known-connected-element
ErrorOr<Web::DOM::Element*, Web::WebDriver::Error> get_known_connected_element(StringView element_id)
{
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibWeb/WebDriver/ElementReference.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace Web::WebDriver {

ByteString get_or_create_a_web_element_reference(Web::DOM::Node const& element);
JsonObject web_element_reference_object(Web::DOM::Node const& element);
bool represents_a_web_element(JsonValue const& value);
ErrorOr<Web::DOM::Element*, Web::WebDriver::Error> get_known_connected_element(StringView element_id);
bool is_element_stale(Web::DOM::Node const& element);

Expand Down
63 changes: 38 additions & 25 deletions Userland/Services/WebContent/WebDriverConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include <LibWeb/HTML/Focus.h>
#include <LibWeb/HTML/FormAssociatedElement.h>
#include <LibWeb/HTML/HTMLDataListElement.h>
#include <LibWeb/HTML/HTMLFrameElement.h>
#include <LibWeb/HTML/HTMLIFrameElement.h>
#include <LibWeb/HTML/HTMLInputElement.h>
#include <LibWeb/HTML/HTMLOptGroupElement.h>
#include <LibWeb/HTML/HTMLOptionElement.h>
Expand Down Expand Up @@ -504,62 +506,73 @@ Messages::WebDriverClient::NewWindowResponse WebDriverConnection::new_window(Jso
}

// 11.6 Switch To Frame, https://w3c.github.io/webdriver/#dfn-switch-to-frame
Messages::WebDriverClient::SwitchToFrameResponse WebDriverConnection::switch_to_frame(JsonValue const&)
Messages::WebDriverClient::SwitchToFrameResponse WebDriverConnection::switch_to_frame(JsonValue const& payload)
{
dbgln("FIXME: WebDriverConnection::switch_to_frame()");
// 1. Let id be the result of getting the property "id" from parameters.
if (!payload.is_object() || !payload.as_object().has("id"sv))
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "Payload doesn't have property `id`"sv);

// FIXME: 1. Let id be the result of getting the property "id" from parameters.
auto id = payload.as_object().get("id"sv).release_value();

// FIXME: 2. If id is not null, a Number object, or an Object that represents a web element, return error with error code invalid argument.
// 2. If id is not null, a Number object, or an Object that represents a web element, return error with error code invalid argument.
if (!id.is_null() && !id.is_number() && !Web::WebDriver::represents_a_web_element(id))
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "Payload property `id` is not null, a number, or a web element"sv);

// FIXME: 3. Run the substeps of the first matching condition:
// 3. Run the substeps of the first matching condition:

// -> id is null

{
if (id.is_null()) {
// FIXME: 1. If session's current top-level browsing context is no longer open, return error with error code no such window.

// FIXME: 2. Try to handle any user prompts with session.

// FIXME: 3. Set the current browsing context with session and session's current top-level browsing context.
dbgln("FIXME: WebDriverConnection::switch_to_frame(id=null)");
}

// -> id is a Number object

{
else if (id.is_number()) {
// FIXME: 1. If id is less than 0 or greater than 216 – 1, return error with error code invalid argument.

// FIXME: 2. If session's current browsing context is no longer open, return error with error code no such window.

// FIXME: 3. Try to handle any user prompts with session.

// FIXME: 4. Let window be the associated window of session's current browsing context's active document.

// FIXME: 5. If id is not a supported property index of window, return error with error code no such frame.

// FIXME: 6. Let child window be the WindowProxy object obtained by calling window.[[GetOwnProperty]] (id).

// FIXME: 7. Set the current browsing context with session and child window's browsing context.
dbgln("FIXME: WebDriverConnection::switch_to_frame(id={})", id);
}

// -> id represents a web element
else if (id.is_object()) {
auto element_id = id.as_object().get_byte_string("value"sv).release_value();

{
// FIXME: 1. If session's current browsing context is no longer open, return error with error code no such window.
// 1. If session's current browsing context is no longer open, return error with error code no such window.
TRY(ensure_current_browsing_context_is_open());

// FIXME: 2. Try to handle any user prompts with session.
// 2. Try to handle any user prompts with session.
TRY(handle_any_user_prompts());

// 3. Let element be the result of trying to get a known element with session and id.
auto* element = TRY(Web::WebDriver::get_known_connected_element(element_id));

// FIXME: 3. Let element be the result of trying to get a known element with session and id.
// 4. If element is not a frame or iframe element, return error with error code no such frame.
bool is_frame = is<Web::HTML::HTMLFrameElement>(element);
bool is_iframe = is<Web::HTML::HTMLIFrameElement>(element);

// FIXME: 4. If element is not a frame or iframe element, return error with error code no such frame.
if (!is_frame && !is_iframe)
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchFrame, "element is not a frame"sv);

// FIXME: 5. Set the current browsing context with session and element's content navigable's active browsing context.
// 5. Set the current browsing context with session and element's content navigable's active browsing context.
if (is_frame) {
// FIXME: Should HTMLFrameElement also be a NavigableContainer?
m_current_browsing_context = *element->navigable()->active_browsing_context();
} else {
auto& navigable_container = static_cast<Web::HTML::NavigableContainer&>(*element);
m_current_browsing_context = navigable_container.content_navigable()->active_browsing_context();
}
}

// FIXME: 4. Update any implementation-specific state that would result from the user selecting session's current browsing context for interaction, without altering OS-level focus.

// FIXME: 5. Return success with data null

// 5. Return success with data null
return JsonValue {};
}

Expand Down

0 comments on commit 440c2fa

Please sign in to comment.