mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-22 04:25:13 +00:00
LibWeb+WebContent+WebDriver: Port WebDriver to String
This commit is contained in:
parent
bc54c0cdfb
commit
9879ac0893
Notes:
github-actions[bot]
2025-02-21 00:29:12 +00:00
Author: https://github.com/trflynn89 Commit: https://github.com/LadybirdBrowser/ladybird/commit/9879ac0893d Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3631 Reviewed-by: https://github.com/awesomekling ✅
21 changed files with 194 additions and 190 deletions
|
@ -106,7 +106,7 @@ static Optional<ActionObject::Origin> determine_origin(ActionsOptions const& act
|
|||
|
||||
if (origin->is_object()) {
|
||||
if (actions_options.is_element_origin(origin->as_object()))
|
||||
return MUST(String::from_byte_string(extract_web_element_reference(origin->as_object())));
|
||||
return extract_web_element_reference(origin->as_object());
|
||||
}
|
||||
|
||||
return {};
|
||||
|
@ -229,7 +229,7 @@ static ErrorOr<PointerParameters, WebDriver::Error> process_pointer_parameters(O
|
|||
|
||||
// 3. If parameters data is not an Object, return error with error code invalid argument.
|
||||
if (!parameters_data->is_object())
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'parameters' is not an Object");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'parameters' is not an Object"sv);
|
||||
|
||||
// 4. Let pointer type be the result of getting a property named "pointerType" from parameters data.
|
||||
auto pointer_type = TRY(get_optional_property(parameters_data->as_object(), "pointerType"sv));
|
||||
|
@ -241,7 +241,7 @@ static ErrorOr<PointerParameters, WebDriver::Error> process_pointer_parameters(O
|
|||
auto parsed_pointer_type = pointer_input_source_subtype_from_string(*pointer_type);
|
||||
|
||||
if (!parsed_pointer_type.has_value())
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'pointerType' must be one of 'mouse', 'pen', or 'touch'");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'pointerType' must be one of 'mouse', 'pen', or 'touch'"sv);
|
||||
|
||||
// 2. Set the pointerType property of parameters to pointer type.
|
||||
parameters.pointer_type = *parsed_pointer_type;
|
||||
|
@ -272,7 +272,7 @@ static ErrorOr<ActionObject, WebDriver::Error> process_null_action(String id, Js
|
|||
|
||||
// 2. If subtype is not "pause", return error with error code invalid argument.
|
||||
if (subtype != ActionObject::Subtype::Pause)
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be 'pause'");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be 'pause'"sv);
|
||||
|
||||
// 3. Let action be an action object constructed with arguments id, "none", and subtype.
|
||||
ActionObject action { move(id), InputSourceType::None, *subtype };
|
||||
|
@ -294,7 +294,7 @@ static ErrorOr<ActionObject, WebDriver::Error> process_key_action(String id, Jso
|
|||
|
||||
// 2. If subtype is not one of the values "keyUp", "keyDown", or "pause", return an error with error code invalid argument.
|
||||
if (!first_is_one_of(subtype, KeyUp, KeyDown, Pause))
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be one of 'keyUp', 'keyDown', or 'pause'");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be one of 'keyUp', 'keyDown', or 'pause'"sv);
|
||||
|
||||
// 3. Let action be an action object constructed with arguments id, "key", and subtype.
|
||||
ActionObject action { move(id), InputSourceType::Key, *subtype };
|
||||
|
@ -317,7 +317,7 @@ static ErrorOr<ActionObject, WebDriver::Error> process_key_action(String id, Jso
|
|||
// FIXME: The spec seems undecided on whether grapheme clusters should be supported. Update this step to check
|
||||
// for graphemes if we end up needing to support them. We would also need to update Page's key event
|
||||
// handlers to support multi-code point events.
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'value' must be a single code point");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'value' must be a single code point"sv);
|
||||
}
|
||||
|
||||
// 7. Set the value property on action to key.
|
||||
|
@ -412,7 +412,7 @@ static ErrorOr<void, WebDriver::Error> process_pointer_move_action(JsonObject co
|
|||
// 6. If origin is not equal to "viewport" or "pointer", and actions options is element origin steps given origin
|
||||
// return false, return error with error code invalid argument.
|
||||
if (!origin.has_value())
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'origin' must be 'viewport', 'pointer', or an element origin");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'origin' must be 'viewport', 'pointer', or an element origin"sv);
|
||||
|
||||
// 7. Set the origin property of action to origin.
|
||||
fields.origin = origin.release_value();
|
||||
|
@ -440,7 +440,7 @@ static ErrorOr<ActionObject, WebDriver::Error> process_pointer_action(String id,
|
|||
|
||||
// 2. If subtype is not one of the values "pause", "pointerUp", "pointerDown", "pointerMove", or "pointerCancel", return an error with error code invalid argument.
|
||||
if (!first_is_one_of(subtype, Pause, PointerUp, PointerDown, PointerMove, PointerCancel))
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be one of 'pause', 'pointerUp', 'pointerDown', 'pointerMove', or 'pointerCancel'");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be one of 'pause', 'pointerUp', 'pointerDown', 'pointerMove', or 'pointerCancel'"sv);
|
||||
|
||||
// 3. Let action be an action object constructed with arguments id, "pointer", and subtype.
|
||||
ActionObject action { move(id), InputSourceType::Pointer, *subtype };
|
||||
|
@ -487,7 +487,7 @@ static ErrorOr<ActionObject, WebDriver::Error> process_wheel_action(String id, J
|
|||
|
||||
// 2. If subtype is not the value "pause", or "scroll", return an error with error code invalid argument.
|
||||
if (!first_is_one_of(subtype, Pause, Scroll))
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be one of 'pause' or 'scroll'");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be one of 'pause' or 'scroll'"sv);
|
||||
|
||||
// 3. Let action be an action object constructed with arguments id, "wheel", and subtype.
|
||||
ActionObject action { move(id), InputSourceType::Wheel, *subtype };
|
||||
|
@ -514,7 +514,7 @@ static ErrorOr<ActionObject, WebDriver::Error> process_wheel_action(String id, J
|
|||
// 10. If origin is not equal to "viewport", or actions options' is element origin steps given origin return false,
|
||||
// return error with error code invalid argument.
|
||||
if (!origin.has_value() || origin == ActionObject::OriginType::Pointer)
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'origin' must be 'viewport' or an element origin");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'origin' must be 'viewport' or an element origin"sv);
|
||||
|
||||
// 11. Set the origin property of action to origin.
|
||||
fields.origin = origin.release_value();
|
||||
|
@ -551,11 +551,11 @@ static ErrorOr<Vector<ActionObject>, WebDriver::Error> process_input_source_acti
|
|||
|
||||
// 2. If type is not "key", "pointer", "wheel", or "none", return an error with error code invalid argument.
|
||||
if (!type.has_value())
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be one of 'key', 'pointer', 'wheel', or 'none'");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' must be one of 'key', 'pointer', 'wheel', or 'none'"sv);
|
||||
|
||||
// 3. Let id be the result of getting the property "id" from action sequence.
|
||||
// 4. If id is undefined or is not a String, return error with error code invalid argument.
|
||||
auto const id = MUST(String::from_byte_string(TRY(get_property(action_sequence, "id"sv))));
|
||||
auto const id = TRY(get_property(action_sequence, "id"sv));
|
||||
|
||||
// 5. If type is equal to "pointer", let parameters data be the result of getting the property "parameters" from
|
||||
// action sequence. Then let parameters be the result of trying to process pointer parameters with argument
|
||||
|
@ -575,7 +575,7 @@ static ErrorOr<Vector<ActionObject>, WebDriver::Error> process_input_source_acti
|
|||
// return an error with error code invalid argument.
|
||||
if (auto const* pointer_input_source = source.get_pointer<PointerInputSource>(); pointer_input_source && parameters.has_value()) {
|
||||
if (parameters->pointer_type != pointer_input_source->subtype)
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Invalid 'pointerType' property");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Invalid 'pointerType' property"sv);
|
||||
}
|
||||
|
||||
// 8. Let action items be the result of getting a property named "actions" from action sequence.
|
||||
|
@ -589,7 +589,7 @@ static ErrorOr<Vector<ActionObject>, WebDriver::Error> process_input_source_acti
|
|||
TRY(action_items.try_for_each([&](auto const& action_item) -> ErrorOr<void, WebDriver::Error> {
|
||||
// 1. If action item is not an Object return error with error code invalid argument.
|
||||
if (!action_item.is_object())
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'actions' item is not an Object");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'actions' item is not an Object"sv);
|
||||
|
||||
auto action = TRY([&]() {
|
||||
switch (*type) {
|
||||
|
@ -1240,11 +1240,11 @@ static ErrorOr<void, WebDriver::Error> dispatch_pointer_move_action(ActionObject
|
|||
|
||||
// 5. If x is less than 0 or greater than the width of the viewport in CSS pixels, then return error with error code move target out of bounds.
|
||||
if (coordinates.x() < 0 || coordinates.x() > viewport.width())
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::MoveTargetOutOfBounds, ByteString::formatted("Coordinates {} are out of bounds", coordinates));
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::MoveTargetOutOfBounds, MUST(String::formatted("Coordinates {} are out of bounds", coordinates)));
|
||||
|
||||
// 6. If y is less than 0 or greater than the height of the viewport in CSS pixels, then return error with error code move target out of bounds.
|
||||
if (coordinates.y() < 0 || coordinates.y() > viewport.height())
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::MoveTargetOutOfBounds, ByteString::formatted("Coordinates {} are out of bounds", coordinates));
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::MoveTargetOutOfBounds, MUST(String::formatted("Coordinates {} are out of bounds", coordinates)));
|
||||
|
||||
// 7. Let duration be equal to action object's duration property if it is not undefined, or tick duration otherwise.
|
||||
[[maybe_unused]] auto duration = action_object.duration.value_or(tick_duration);
|
||||
|
|
|
@ -91,7 +91,7 @@ static ErrorOr<JsonObject, Error> validate_capabilities(JsonValue const& capabil
|
|||
else if (name.is_one_of("browserName"sv, "browserVersion"sv, "platformName"sv)) {
|
||||
// If value is not a string return an error with error code invalid argument. Otherwise, let deserialized be set to value.
|
||||
if (!value.is_string())
|
||||
return Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Capability {} must be a string", name));
|
||||
return Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("Capability {} must be a string", name)));
|
||||
deserialized = value;
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,7 @@ static ErrorOr<JsonObject, Error> validate_capabilities(JsonValue const& capabil
|
|||
// -> The remote end is an endpoint node
|
||||
else {
|
||||
// Return an error with error code invalid argument.
|
||||
return Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Unrecognized capability: {}", name));
|
||||
return Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("Unrecognized capability: {}", name)));
|
||||
}
|
||||
|
||||
// d. If deserialized is not null, set a property on result with name name and value deserialized.
|
||||
|
@ -195,7 +195,7 @@ static ErrorOr<JsonObject, Error> merge_capabilities(JsonObject const& primary,
|
|||
|
||||
// d. If primary value is not undefined, return an error with error code invalid argument.
|
||||
if (primary_value.has_value())
|
||||
return Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Unable to merge capability {}", name));
|
||||
return Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("Unable to merge capability {}", name)));
|
||||
|
||||
// e. Set a property on result with name name and value value.
|
||||
result.set(name, value);
|
||||
|
@ -290,13 +290,13 @@ static JsonValue match_capabilities(JsonObject const& capabilities, SessionFlags
|
|||
else if (name == "browserVersion"sv) {
|
||||
// Compare value to the "browserVersion" entry in matched capabilities using an implementation-defined comparison algorithm. The comparison is to accept a value that places constraints on the version using the "<", "<=", ">", and ">=" operators.
|
||||
// If the two values do not match, return success with data null.
|
||||
if (!matches_browser_version(value.as_string(), matched_capabilities.get_byte_string(name).value()))
|
||||
if (!matches_browser_version(value.as_string(), matched_capabilities.get_string(name).value()))
|
||||
return AK::Error::from_string_literal("browserVersion");
|
||||
}
|
||||
// -> "platformName"
|
||||
else if (name == "platformName"sv) {
|
||||
// If value is not a string equal to the "platformName" entry in matched capabilities, return success with data null.
|
||||
if (!matches_platform_name(value.as_string(), matched_capabilities.get_byte_string(name).value()))
|
||||
if (!matches_platform_name(value.as_string(), matched_capabilities.get_string(name).value()))
|
||||
return AK::Error::from_string_literal("platformName");
|
||||
}
|
||||
// -> "acceptInsecureCerts"
|
||||
|
|
|
@ -167,7 +167,7 @@ static ErrorOr<MatchedRoute, Error> match_route(HTTP::HttpRequest const& request
|
|||
}
|
||||
}
|
||||
|
||||
return Error::from_code(ErrorCode::UnknownCommand, "The command was not recognized.");
|
||||
return Error::from_code(ErrorCode::UnknownCommand, "The command was not recognized."sv);
|
||||
}
|
||||
|
||||
static JsonValue make_success_response(JsonValue value)
|
||||
|
@ -329,8 +329,8 @@ ErrorOr<void, Client::WrappedError> Client::send_error_response(HTTP::HttpReques
|
|||
auto reason = HTTP::HttpResponse::reason_phrase_for_code(error.http_status);
|
||||
|
||||
JsonObject error_response;
|
||||
error_response.set("error"sv, MUST(String::from_byte_string(error.error)));
|
||||
error_response.set("message"sv, MUST(String::from_byte_string(error.message)));
|
||||
error_response.set("error"sv, error.error);
|
||||
error_response.set("message"sv, error.message);
|
||||
error_response.set("stacktrace"sv, ""sv);
|
||||
if (error.data.has_value())
|
||||
error_response.set("data"sv, *error.data);
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
namespace Web::WebDriver {
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-web-window-identifier
|
||||
static ByteString const WEB_WINDOW_IDENTIFIER = "window-fcc6-11e5-b4f8-330a88ab9d7f"sv;
|
||||
static JS::PropertyKey const WEB_WINDOW_IDENTIFIER { "window-fcc6-11e5-b4f8-330a88ab9d7f" };
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-web-frame-identifier
|
||||
static ByteString const WEB_FRAME_IDENTIFIER = "frame-075b-4da1-b6ba-e579c2d3230a"sv;
|
||||
static JS::PropertyKey const WEB_FRAME_IDENTIFIER { "frame-075b-4da1-b6ba-e579c2d3230a" };
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-windowproxy-reference-object
|
||||
JsonObject window_proxy_reference_object(HTML::WindowProxy const& window)
|
||||
|
@ -30,7 +30,7 @@ JsonObject window_proxy_reference_object(HTML::WindowProxy const& window)
|
|||
// Ref: https://html.spec.whatwg.org/multipage/document-sequences.html#bc-traversable
|
||||
auto navigable = window.associated_browsing_context()->active_document()->navigable();
|
||||
|
||||
auto identifier = navigable->is_top_level_traversable()
|
||||
auto const& identifier = navigable->is_top_level_traversable()
|
||||
? WEB_WINDOW_IDENTIFIER
|
||||
: WEB_FRAME_IDENTIFIER;
|
||||
|
||||
|
@ -39,7 +39,7 @@ JsonObject window_proxy_reference_object(HTML::WindowProxy const& window)
|
|||
|
||||
// identifier
|
||||
// Associated window handle of the window’s browsing context.
|
||||
object.set(identifier, navigable->traversable_navigable()->window_handle());
|
||||
object.set(identifier.as_string(), navigable->traversable_navigable()->window_handle());
|
||||
|
||||
return object;
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ bool represents_a_web_frame(JS::Value value)
|
|||
if (!value.is_object())
|
||||
return false;
|
||||
|
||||
auto result = value.as_object().has_own_property(WEB_FRAME_IDENTIFIER);
|
||||
auto result = value.as_object().has_own_property(WEB_WINDOW_IDENTIFIER);
|
||||
return !result.is_error() && result.value();
|
||||
}
|
||||
|
||||
|
|
|
@ -25,16 +25,18 @@
|
|||
namespace Web::WebDriver {
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-web-element-identifier
|
||||
static ByteString const web_element_identifier = "element-6066-11e4-a52e-4f735466cecf"sv;
|
||||
static String const web_element_identifier = "element-6066-11e4-a52e-4f735466cecf"_string;
|
||||
static JS::PropertyKey web_element_identifier_key { web_element_identifier.to_byte_string() };
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-shadow-root-identifier
|
||||
static ByteString const shadow_root_identifier = "shadow-6066-11e4-a52e-4f735466cecf"sv;
|
||||
static String const shadow_root_identifier = "shadow-6066-11e4-a52e-4f735466cecf"_string;
|
||||
static JS::PropertyKey shadow_root_identifier_key { shadow_root_identifier.to_byte_string() };
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-browsing-context-group-node-map
|
||||
static HashMap<GC::RawPtr<HTML::BrowsingContextGroup const>, HashTable<ByteString>> browsing_context_group_node_map;
|
||||
static HashMap<GC::RawPtr<HTML::BrowsingContextGroup const>, HashTable<String>> browsing_context_group_node_map;
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-navigable-seen-nodes-map
|
||||
static HashMap<GC::RawPtr<HTML::Navigable>, HashTable<ByteString>> navigable_seen_nodes_map;
|
||||
static HashMap<GC::RawPtr<HTML::Navigable>, HashTable<String>> navigable_seen_nodes_map;
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-get-a-node
|
||||
GC::Ptr<Web::DOM::Node> get_node(HTML::BrowsingContext const& browsing_context, StringView reference)
|
||||
|
@ -62,7 +64,7 @@ GC::Ptr<Web::DOM::Node> get_node(HTML::BrowsingContext const& browsing_context,
|
|||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-get-or-create-a-node-reference
|
||||
ByteString get_or_create_a_node_reference(HTML::BrowsingContext const& browsing_context, Web::DOM::Node const& node)
|
||||
String get_or_create_a_node_reference(HTML::BrowsingContext const& browsing_context, Web::DOM::Node const& node)
|
||||
{
|
||||
// 1. Let browsing context group node map be session's browsing context group node map.
|
||||
// 2. Let browsing context group be browsing context's browsing context group.
|
||||
|
@ -73,7 +75,7 @@ ByteString get_or_create_a_node_reference(HTML::BrowsingContext const& browsing_
|
|||
// 4. Let node id map be browsing context group node map[browsing context group].
|
||||
auto& node_id_map = browsing_context_group_node_map.ensure(browsing_context_group);
|
||||
|
||||
auto node_id = ByteString::number(node.unique_id().value());
|
||||
auto node_id = String::number(node.unique_id().value());
|
||||
|
||||
// 5. If node id map does not contain node:
|
||||
if (!node_id_map.contains(node_id)) {
|
||||
|
@ -111,7 +113,7 @@ bool node_reference_is_known(HTML::BrowsingContext const& browsing_context, Stri
|
|||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-get-or-create-a-web-element-reference
|
||||
ByteString get_or_create_a_web_element_reference(HTML::BrowsingContext const& browsing_context, Web::DOM::Node const& element)
|
||||
String get_or_create_a_web_element_reference(HTML::BrowsingContext const& browsing_context, Web::DOM::Node const& element)
|
||||
{
|
||||
// 1. Assert: element implements Element.
|
||||
VERIFY(element.is_element());
|
||||
|
@ -132,7 +134,7 @@ JsonObject web_element_reference_object(HTML::BrowsingContext const& browsing_co
|
|||
|
||||
// 3. Return a JSON Object initialized with a property with name identifier and value reference.
|
||||
JsonObject object;
|
||||
object.set(identifier, MUST(String::from_byte_string(reference)));
|
||||
object.set(identifier, move(reference));
|
||||
return object;
|
||||
}
|
||||
|
||||
|
@ -153,7 +155,7 @@ bool represents_a_web_element(JS::Value value)
|
|||
if (!value.is_object())
|
||||
return false;
|
||||
|
||||
auto result = value.as_object().has_own_property(web_element_identifier);
|
||||
auto result = value.as_object().has_own_property(web_element_identifier_key);
|
||||
return !result.is_error() && result.value();
|
||||
}
|
||||
|
||||
|
@ -162,7 +164,7 @@ ErrorOr<GC::Ref<Web::DOM::Element>, WebDriver::Error> deserialize_web_element(We
|
|||
{
|
||||
// 1. If object has no own property web element identifier, return error with error code invalid argument.
|
||||
if (!object.has_string(web_element_identifier))
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a web element");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a web element"sv);
|
||||
|
||||
// 2. Let reference be the result of getting the web element identifier property from object.
|
||||
auto reference = extract_web_element_reference(object);
|
||||
|
@ -178,9 +180,9 @@ ErrorOr<GC::Ref<Web::DOM::Element>, WebDriver::Error> deserialize_web_element(We
|
|||
ErrorOr<GC::Ref<Web::DOM::Element>, WebDriver::Error> deserialize_web_element(Web::HTML::BrowsingContext const& browsing_context, JS::Object const& object)
|
||||
{
|
||||
// 1. If object has no own property web element identifier, return error with error code invalid argument.
|
||||
auto property = object.get(web_element_identifier);
|
||||
auto property = object.get(web_element_identifier_key);
|
||||
if (property.is_error() || !property.value().is_string())
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a web element");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a web element"sv);
|
||||
|
||||
// 2. Let reference be the result of getting the web element identifier property from object.
|
||||
auto reference = property.value().as_string().utf8_string();
|
||||
|
@ -192,9 +194,9 @@ ErrorOr<GC::Ref<Web::DOM::Element>, WebDriver::Error> deserialize_web_element(We
|
|||
return element;
|
||||
}
|
||||
|
||||
ByteString extract_web_element_reference(JsonObject const& object)
|
||||
String extract_web_element_reference(JsonObject const& object)
|
||||
{
|
||||
return object.get_byte_string(web_element_identifier).release_value();
|
||||
return object.get_string(web_element_identifier).release_value();
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-get-a-webelement-origin
|
||||
|
@ -215,18 +217,18 @@ ErrorOr<GC::Ref<Web::DOM::Element>, Web::WebDriver::Error> get_known_element(Web
|
|||
// 1. If not node reference is known with session, session's current browsing context, and reference return error
|
||||
// with error code no such element.
|
||||
if (!node_reference_is_known(browsing_context, reference))
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchElement, ByteString::formatted("Element reference '{}' is not known", reference));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchElement, MUST(String::formatted("Element reference '{}' is not known", reference)));
|
||||
|
||||
// 2. Let node be the result of get a node with session, session's current browsing context, and reference.
|
||||
auto node = get_node(browsing_context, reference);
|
||||
|
||||
// 3. If node is not null and node does not implement Element return error with error code no such element.
|
||||
if (node && !node->is_element())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchElement, ByteString::formatted("Could not find element with reference '{}'", reference));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchElement, MUST(String::formatted("Could not find element with reference '{}'", reference)));
|
||||
|
||||
// 4. If node is null or node is stale return error with error code stale element reference.
|
||||
if (!node || is_element_stale(*node))
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::StaleElementReference, ByteString::formatted("Element reference '{}' is stale", reference));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::StaleElementReference, MUST(String::formatted("Element reference '{}' is stale", reference)));
|
||||
|
||||
// 5. Return success with data node.
|
||||
return static_cast<Web::DOM::Element&>(*node);
|
||||
|
@ -403,7 +405,7 @@ GC::RootVector<GC::Ref<Web::DOM::Element>> pointer_interactable_tree(Web::HTML::
|
|||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-get-or-create-a-shadow-root-reference
|
||||
ByteString get_or_create_a_shadow_root_reference(HTML::BrowsingContext const& browsing_context, Web::DOM::ShadowRoot const& shadow_root)
|
||||
String get_or_create_a_shadow_root_reference(HTML::BrowsingContext const& browsing_context, Web::DOM::ShadowRoot const& shadow_root)
|
||||
{
|
||||
// 1. Assert: element implements ShadowRoot.
|
||||
// 2. Return the result of trying to get or create a node reference with session, session's current browsing context,
|
||||
|
@ -422,7 +424,7 @@ JsonObject shadow_root_reference_object(HTML::BrowsingContext const& browsing_co
|
|||
|
||||
// 3. Return a JSON Object initialized with a property with name identifier and value reference.
|
||||
JsonObject object;
|
||||
object.set(identifier, MUST(String::from_byte_string(reference)));
|
||||
object.set(identifier, move(reference));
|
||||
return object;
|
||||
}
|
||||
|
||||
|
@ -443,7 +445,7 @@ bool represents_a_shadow_root(JS::Value value)
|
|||
if (!value.is_object())
|
||||
return false;
|
||||
|
||||
auto result = value.as_object().has_own_property(shadow_root_identifier);
|
||||
auto result = value.as_object().has_own_property(shadow_root_identifier_key);
|
||||
return !result.is_error() && result.value();
|
||||
}
|
||||
|
||||
|
@ -452,10 +454,10 @@ ErrorOr<GC::Ref<Web::DOM::ShadowRoot>, WebDriver::Error> deserialize_shadow_root
|
|||
{
|
||||
// 1. If object has no own property shadow root identifier, return error with error code invalid argument.
|
||||
if (!object.has_string(shadow_root_identifier))
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a Shadow Root");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a Shadow Root"sv);
|
||||
|
||||
// 2. Let reference be the result of getting the shadow root identifier property from object.
|
||||
auto reference = object.get_byte_string(shadow_root_identifier).release_value();
|
||||
auto const& reference = object.get_string(shadow_root_identifier).release_value();
|
||||
|
||||
// 3. Let shadow be the result of trying to get a known shadow root with session and reference.
|
||||
auto shadow = TRY(get_known_shadow_root(browsing_context, reference));
|
||||
|
@ -468,9 +470,9 @@ ErrorOr<GC::Ref<Web::DOM::ShadowRoot>, WebDriver::Error> deserialize_shadow_root
|
|||
ErrorOr<GC::Ref<Web::DOM::ShadowRoot>, WebDriver::Error> deserialize_shadow_root(Web::HTML::BrowsingContext const& browsing_context, JS::Object const& object)
|
||||
{
|
||||
// 1. If object has no own property shadow root identifier, return error with error code invalid argument.
|
||||
auto property = object.get(shadow_root_identifier);
|
||||
auto property = object.get(shadow_root_identifier_key);
|
||||
if (property.is_error() || !property.value().is_string())
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a Shadow Root");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Object is not a Shadow Root"sv);
|
||||
|
||||
// 2. Let reference be the result of getting the shadow root identifier property from object.
|
||||
auto reference = property.value().as_string().utf8_string();
|
||||
|
@ -487,18 +489,18 @@ ErrorOr<GC::Ref<Web::DOM::ShadowRoot>, Web::WebDriver::Error> get_known_shadow_r
|
|||
{
|
||||
// 1. If not node reference is known with session, session's current browsing context, and reference return error with error code no such shadow root.
|
||||
if (!node_reference_is_known(browsing_context, reference))
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchShadowRoot, ByteString::formatted("Shadow root reference '{}' is not known", reference));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchShadowRoot, MUST(String::formatted("Shadow root reference '{}' is not known", reference)));
|
||||
|
||||
// 2. Let node be the result of get a node with session, session's current browsing context, and reference.
|
||||
auto node = get_node(browsing_context, reference);
|
||||
|
||||
// 3. If node is not null and node does not implement ShadowRoot return error with error code no such shadow root.
|
||||
if (node && !node->is_shadow_root())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchShadowRoot, ByteString::formatted("Could not find shadow root with reference '{}'", reference));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchShadowRoot, MUST(String::formatted("Could not find shadow root with reference '{}'", reference)));
|
||||
|
||||
// 4. If node is null or node is detached return error with error code detached shadow root.
|
||||
if (!node || is_shadow_root_detached(static_cast<Web::DOM::ShadowRoot&>(*node)))
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::DetachedShadowRoot, ByteString::formatted("Element reference '{}' is stale", reference));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::DetachedShadowRoot, MUST(String::formatted("Element reference '{}' is stale", reference)));
|
||||
|
||||
// 5. Return success with data node.
|
||||
return static_cast<Web::DOM::ShadowRoot&>(*node);
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <AK/ByteString.h>
|
||||
#include <AK/Error.h>
|
||||
#include <AK/JsonObject.h>
|
||||
#include <AK/String.h>
|
||||
#include <LibGC/Ptr.h>
|
||||
#include <LibJS/Forward.h>
|
||||
#include <LibJS/Runtime/Value.h>
|
||||
|
@ -19,16 +19,16 @@
|
|||
namespace Web::WebDriver {
|
||||
|
||||
GC::Ptr<Web::DOM::Node> get_node(HTML::BrowsingContext const&, StringView reference);
|
||||
ByteString get_or_create_a_node_reference(HTML::BrowsingContext const&, Web::DOM::Node const&);
|
||||
String get_or_create_a_node_reference(HTML::BrowsingContext const&, Web::DOM::Node const&);
|
||||
bool node_reference_is_known(HTML::BrowsingContext const&, StringView reference);
|
||||
|
||||
ByteString get_or_create_a_web_element_reference(HTML::BrowsingContext const&, Web::DOM::Node const& element);
|
||||
String get_or_create_a_web_element_reference(HTML::BrowsingContext const&, Web::DOM::Node const& element);
|
||||
JsonObject web_element_reference_object(HTML::BrowsingContext const&, Web::DOM::Node const& element);
|
||||
bool represents_a_web_element(JsonValue const&);
|
||||
bool represents_a_web_element(JS::Value);
|
||||
ErrorOr<GC::Ref<Web::DOM::Element>, WebDriver::Error> deserialize_web_element(Web::HTML::BrowsingContext const&, JsonObject const&);
|
||||
ErrorOr<GC::Ref<Web::DOM::Element>, WebDriver::Error> deserialize_web_element(Web::HTML::BrowsingContext const&, JS::Object const&);
|
||||
ByteString extract_web_element_reference(JsonObject const&);
|
||||
String extract_web_element_reference(JsonObject const&);
|
||||
ErrorOr<GC::Ref<Web::DOM::Element>, Web::WebDriver::Error> get_web_element_origin(Web::HTML::BrowsingContext const&, StringView origin);
|
||||
ErrorOr<GC::Ref<Web::DOM::Element>, Web::WebDriver::Error> get_known_element(Web::HTML::BrowsingContext const&, StringView reference);
|
||||
|
||||
|
@ -46,7 +46,7 @@ bool is_element_in_view(ReadonlySpan<GC::Ref<Web::DOM::Element>> paint_tree, Web
|
|||
bool is_element_obscured(ReadonlySpan<GC::Ref<Web::DOM::Element>> paint_tree, Web::DOM::Element&);
|
||||
GC::RootVector<GC::Ref<Web::DOM::Element>> pointer_interactable_tree(Web::HTML::BrowsingContext&, Web::DOM::Element&);
|
||||
|
||||
ByteString get_or_create_a_shadow_root_reference(HTML::BrowsingContext const&, Web::DOM::ShadowRoot const&);
|
||||
String get_or_create_a_shadow_root_reference(HTML::BrowsingContext const&, Web::DOM::ShadowRoot const&);
|
||||
JsonObject shadow_root_reference_object(HTML::BrowsingContext const&, Web::DOM::ShadowRoot const&);
|
||||
bool represents_a_shadow_root(JsonValue const&);
|
||||
bool represents_a_shadow_root(JS::Value);
|
||||
|
|
|
@ -13,43 +13,43 @@ namespace Web::WebDriver {
|
|||
struct ErrorCodeData {
|
||||
ErrorCode error_code;
|
||||
unsigned http_status;
|
||||
ByteString json_error_code;
|
||||
String json_error_code;
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-error-code
|
||||
static Vector<ErrorCodeData> const s_error_code_data = {
|
||||
{ ErrorCode::ElementClickIntercepted, 400, "element click intercepted" },
|
||||
{ ErrorCode::ElementNotInteractable, 400, "element not interactable" },
|
||||
{ ErrorCode::InsecureCertificate, 400, "insecure certificate" },
|
||||
{ ErrorCode::InvalidArgument, 400, "invalid argument" },
|
||||
{ ErrorCode::InvalidCookieDomain, 400, "invalid cookie domain" },
|
||||
{ ErrorCode::InvalidElementState, 400, "invalid element state" },
|
||||
{ ErrorCode::InvalidSelector, 400, "invalid selector" },
|
||||
{ ErrorCode::InvalidSessionId, 404, "invalid session id" },
|
||||
{ ErrorCode::JavascriptError, 500, "javascript error" },
|
||||
{ ErrorCode::MoveTargetOutOfBounds, 500, "move target out of bounds" },
|
||||
{ ErrorCode::NoSuchAlert, 404, "no such alert" },
|
||||
{ ErrorCode::NoSuchCookie, 404, "no such cookie" },
|
||||
{ ErrorCode::NoSuchElement, 404, "no such element" },
|
||||
{ ErrorCode::NoSuchFrame, 404, "no such frame" },
|
||||
{ ErrorCode::NoSuchWindow, 404, "no such window" },
|
||||
{ ErrorCode::NoSuchShadowRoot, 404, "no such shadow root" },
|
||||
{ ErrorCode::ScriptTimeoutError, 500, "script timeout" },
|
||||
{ ErrorCode::SessionNotCreated, 500, "session not created" },
|
||||
{ ErrorCode::StaleElementReference, 404, "stale element reference" },
|
||||
{ ErrorCode::DetachedShadowRoot, 404, "detached shadow root" },
|
||||
{ ErrorCode::Timeout, 500, "timeout" },
|
||||
{ ErrorCode::UnableToSetCookie, 500, "unable to set cookie" },
|
||||
{ ErrorCode::UnableToCaptureScreen, 500, "unable to capture screen" },
|
||||
{ ErrorCode::UnexpectedAlertOpen, 500, "unexpected alert open" },
|
||||
{ ErrorCode::UnknownCommand, 404, "unknown command" },
|
||||
{ ErrorCode::UnknownError, 500, "unknown error" },
|
||||
{ ErrorCode::UnknownMethod, 405, "unknown method" },
|
||||
{ ErrorCode::UnsupportedOperation, 500, "unsupported operation" },
|
||||
{ ErrorCode::OutOfMemory, 500, "out of memory" },
|
||||
{ ErrorCode::ElementClickIntercepted, 400, "element click intercepted"_string },
|
||||
{ ErrorCode::ElementNotInteractable, 400, "element not interactable"_string },
|
||||
{ ErrorCode::InsecureCertificate, 400, "insecure certificate"_string },
|
||||
{ ErrorCode::InvalidArgument, 400, "invalid argument"_string },
|
||||
{ ErrorCode::InvalidCookieDomain, 400, "invalid cookie domain"_string },
|
||||
{ ErrorCode::InvalidElementState, 400, "invalid element state"_string },
|
||||
{ ErrorCode::InvalidSelector, 400, "invalid selector"_string },
|
||||
{ ErrorCode::InvalidSessionId, 404, "invalid session id"_string },
|
||||
{ ErrorCode::JavascriptError, 500, "javascript error"_string },
|
||||
{ ErrorCode::MoveTargetOutOfBounds, 500, "move target out of bounds"_string },
|
||||
{ ErrorCode::NoSuchAlert, 404, "no such alert"_string },
|
||||
{ ErrorCode::NoSuchCookie, 404, "no such cookie"_string },
|
||||
{ ErrorCode::NoSuchElement, 404, "no such element"_string },
|
||||
{ ErrorCode::NoSuchFrame, 404, "no such frame"_string },
|
||||
{ ErrorCode::NoSuchWindow, 404, "no such window"_string },
|
||||
{ ErrorCode::NoSuchShadowRoot, 404, "no such shadow root"_string },
|
||||
{ ErrorCode::ScriptTimeoutError, 500, "script timeout"_string },
|
||||
{ ErrorCode::SessionNotCreated, 500, "session not created"_string },
|
||||
{ ErrorCode::StaleElementReference, 404, "stale element reference"_string },
|
||||
{ ErrorCode::DetachedShadowRoot, 404, "detached shadow root"_string },
|
||||
{ ErrorCode::Timeout, 500, "timeout"_string },
|
||||
{ ErrorCode::UnableToSetCookie, 500, "unable to set cookie"_string },
|
||||
{ ErrorCode::UnableToCaptureScreen, 500, "unable to capture screen"_string },
|
||||
{ ErrorCode::UnexpectedAlertOpen, 500, "unexpected alert open"_string },
|
||||
{ ErrorCode::UnknownCommand, 404, "unknown command"_string },
|
||||
{ ErrorCode::UnknownError, 500, "unknown error"_string },
|
||||
{ ErrorCode::UnknownMethod, 405, "unknown method"_string },
|
||||
{ ErrorCode::UnsupportedOperation, 500, "unsupported operation"_string },
|
||||
{ ErrorCode::OutOfMemory, 500, "out of memory"_string },
|
||||
};
|
||||
|
||||
Error Error::from_code(ErrorCode code, ByteString message, Optional<JsonValue> data)
|
||||
Error Error::from_code(ErrorCode code, String message, Optional<JsonValue> data)
|
||||
{
|
||||
auto const& error_code_data = s_error_code_data[to_underlying(code)];
|
||||
|
||||
|
@ -61,13 +61,18 @@ Error Error::from_code(ErrorCode code, ByteString message, Optional<JsonValue> d
|
|||
};
|
||||
}
|
||||
|
||||
Error Error::from_code(ErrorCode code, StringView message, Optional<JsonValue> data)
|
||||
{
|
||||
return from_code(code, String::from_utf8_without_validation(message.bytes()), move(data));
|
||||
}
|
||||
|
||||
Error::Error(AK::Error const& error)
|
||||
{
|
||||
VERIFY(error.code() == ENOMEM);
|
||||
*this = from_code(ErrorCode::OutOfMemory, {}, {});
|
||||
*this = from_code(ErrorCode::OutOfMemory, String {}, {});
|
||||
}
|
||||
|
||||
Error::Error(unsigned http_status_, ByteString error_, ByteString message_, Optional<JsonValue> data_)
|
||||
Error::Error(unsigned http_status_, String error_, String message_, Optional<JsonValue> data_)
|
||||
: http_status(http_status_)
|
||||
, error(move(error_))
|
||||
, message(move(message_))
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <AK/ByteString.h>
|
||||
#include <AK/JsonValue.h>
|
||||
#include <AK/String.h>
|
||||
|
||||
namespace Web::WebDriver {
|
||||
|
||||
|
@ -50,13 +50,14 @@ enum class ErrorCode {
|
|||
// https://w3c.github.io/webdriver/#errors
|
||||
struct Error {
|
||||
unsigned http_status;
|
||||
ByteString error;
|
||||
ByteString message;
|
||||
String error;
|
||||
String message;
|
||||
Optional<JsonValue> data;
|
||||
|
||||
static Error from_code(ErrorCode, ByteString message, Optional<JsonValue> data = {});
|
||||
static Error from_code(ErrorCode, String message, Optional<JsonValue> data = {});
|
||||
static Error from_code(ErrorCode, StringView message, Optional<JsonValue> data = {});
|
||||
|
||||
Error(unsigned http_status, ByteString error, ByteString message, Optional<JsonValue> data);
|
||||
Error(unsigned http_status, String error, String message, Optional<JsonValue> data);
|
||||
Error(AK::Error const&);
|
||||
};
|
||||
|
||||
|
@ -66,6 +67,6 @@ template<>
|
|||
struct AK::Formatter<Web::WebDriver::Error> : Formatter<StringView> {
|
||||
ErrorOr<void> format(FormatBuilder& builder, Web::WebDriver::Error const& error)
|
||||
{
|
||||
return Formatter<StringView>::format(builder, ByteString::formatted("Error {}, {}: {}", error.http_status, error.error, error.message));
|
||||
return Formatter<StringView>::format(builder, MUST(String::formatted("Error {}, {}: {}", error.http_status, error.error, error.message)));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
namespace Web::WebDriver {
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-execute-a-function-body
|
||||
static JS::ThrowCompletionOr<JS::Value> execute_a_function_body(HTML::BrowsingContext const& browsing_context, ByteString const& body, ReadonlySpan<JS::Value> parameters)
|
||||
static JS::ThrowCompletionOr<JS::Value> execute_a_function_body(HTML::BrowsingContext const& browsing_context, StringView body, ReadonlySpan<JS::Value> parameters)
|
||||
{
|
||||
// 1. Let window be the associated window of the current browsing context’s active document.
|
||||
auto window = browsing_context.active_document()->window();
|
||||
|
@ -84,7 +84,7 @@ static JS::ThrowCompletionOr<JS::Value> execute_a_function_body(HTML::BrowsingCo
|
|||
return completion;
|
||||
}
|
||||
|
||||
void execute_script(HTML::BrowsingContext const& browsing_context, ByteString body, GC::RootVector<JS::Value> arguments, Optional<u64> const& timeout_ms, GC::Ref<OnScriptComplete> on_complete)
|
||||
void execute_script(HTML::BrowsingContext const& browsing_context, String body, GC::RootVector<JS::Value> arguments, Optional<u64> const& timeout_ms, GC::Ref<OnScriptComplete> on_complete)
|
||||
{
|
||||
auto const* document = browsing_context.active_document();
|
||||
auto& realm = document->realm();
|
||||
|
@ -142,7 +142,7 @@ void execute_script(HTML::BrowsingContext const& browsing_context, ByteString bo
|
|||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#execute-async-script
|
||||
void execute_async_script(HTML::BrowsingContext const& browsing_context, ByteString body, GC::RootVector<JS::Value> arguments, Optional<u64> const& timeout_ms, GC::Ref<OnScriptComplete> on_complete)
|
||||
void execute_async_script(HTML::BrowsingContext const& browsing_context, String body, GC::RootVector<JS::Value> arguments, Optional<u64> const& timeout_ms, GC::Ref<OnScriptComplete> on_complete)
|
||||
{
|
||||
auto const* document = browsing_context.active_document();
|
||||
auto& realm = document->realm();
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Forward.h>
|
||||
#include <AK/String.h>
|
||||
#include <LibGC/Function.h>
|
||||
#include <LibJS/Forward.h>
|
||||
#include <LibJS/Runtime/Promise.h>
|
||||
|
@ -23,7 +24,7 @@ struct ExecutionResult {
|
|||
|
||||
using OnScriptComplete = GC::Function<void(ExecutionResult)>;
|
||||
|
||||
void execute_script(HTML::BrowsingContext const&, ByteString body, GC::RootVector<JS::Value> arguments, Optional<u64> const& timeout_ms, GC::Ref<OnScriptComplete> on_complete);
|
||||
void execute_async_script(HTML::BrowsingContext const&, ByteString body, GC::RootVector<JS::Value> arguments, Optional<u64> const& timeout_ms, GC::Ref<OnScriptComplete> on_complete);
|
||||
void execute_script(HTML::BrowsingContext const&, String body, GC::RootVector<JS::Value> arguments, Optional<u64> const& timeout_ms, GC::Ref<OnScriptComplete> on_complete);
|
||||
void execute_async_script(HTML::BrowsingContext const&, String body, GC::RootVector<JS::Value> arguments, Optional<u64> const& timeout_ms, GC::Ref<OnScriptComplete> on_complete);
|
||||
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ ErrorOr<InputSource*, WebDriver::Error> get_or_create_input_source(InputState& i
|
|||
// FIXME: Spec issue: It does not make sense to check if "source is a pointer input source". This would errantly
|
||||
// prevent the ability to perform two pointer actions in a row.
|
||||
// https://github.com/w3c/webdriver/issues/1810
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' does not match existing input source type");
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, "Property 'type' does not match existing input source type"sv);
|
||||
}
|
||||
|
||||
// 3. If source is undefined, set source to the result of trying to create an input source with input state and type.
|
||||
|
|
|
@ -30,14 +30,14 @@
|
|||
|
||||
namespace Web::WebDriver {
|
||||
|
||||
#define TRY_OR_JS_ERROR(expression) \
|
||||
({ \
|
||||
auto&& _temporary_result = (expression); \
|
||||
if (_temporary_result.is_error()) [[unlikely]] \
|
||||
return WebDriver::Error::from_code(ErrorCode::JavascriptError, "Script returned an error"); \
|
||||
static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_result.release_value())>, \
|
||||
"Do not return a reference from a fallible expression"); \
|
||||
_temporary_result.release_value(); \
|
||||
#define TRY_OR_JS_ERROR(expression) \
|
||||
({ \
|
||||
auto&& _temporary_result = (expression); \
|
||||
if (_temporary_result.is_error()) [[unlikely]] \
|
||||
return WebDriver::Error::from_code(ErrorCode::JavascriptError, "Script returned an error"sv); \
|
||||
static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_result.release_value())>, \
|
||||
"Do not return a reference from a fallible expression"); \
|
||||
_temporary_result.release_value(); \
|
||||
})
|
||||
|
||||
using SeenMap = HashTable<GC::RawPtr<JS::Object const>>;
|
||||
|
@ -120,7 +120,7 @@ static ErrorOr<ResultType, WebDriver::Error> clone_an_object(HTML::BrowsingConte
|
|||
// script to be run and that script throws an error, return error with error code javascript error.
|
||||
auto source_property_value = value.get(name);
|
||||
if (source_property_value.is_error()) {
|
||||
error = WebDriver::Error::from_code(ErrorCode::JavascriptError, "Script returned an error");
|
||||
error = WebDriver::Error::from_code(ErrorCode::JavascriptError, "Script returned an error"sv);
|
||||
return JS::normal_completion({});
|
||||
}
|
||||
|
||||
|
@ -183,7 +183,7 @@ static Response internal_json_clone(HTML::BrowsingContext const& browsing_contex
|
|||
if (value.is_number())
|
||||
return JsonValue { value.as_double() };
|
||||
if (value.is_string())
|
||||
return JsonValue { value.as_string().byte_string() };
|
||||
return JsonValue { value.as_string().utf8_string() };
|
||||
|
||||
// AD-HOC: BigInt and Symbol not mentioned anywhere in the WebDriver spec, as it references ES5.
|
||||
// It assumes that all primitives are handled above, and the value is an object for the remaining steps.
|
||||
|
@ -257,7 +257,7 @@ static Response internal_json_clone(HTML::BrowsingContext const& browsing_contex
|
|||
if (!to_json_result.is_string())
|
||||
return WebDriver::Error::from_code(ErrorCode::JavascriptError, "toJSON did not return a String"sv);
|
||||
|
||||
return JsonValue { to_json_result.as_string().byte_string() };
|
||||
return JsonValue { to_json_result.as_string().utf8_string() };
|
||||
}
|
||||
|
||||
// -> Otherwise
|
||||
|
|
|
@ -6,22 +6,22 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <AK/ByteString.h>
|
||||
#include <AK/JsonArray.h>
|
||||
#include <AK/JsonObject.h>
|
||||
#include <AK/JsonValue.h>
|
||||
#include <AK/String.h>
|
||||
#include <LibJS/Runtime/Value.h>
|
||||
#include <LibWeb/WebDriver/Error.h>
|
||||
|
||||
namespace Web::WebDriver {
|
||||
|
||||
template<typename PropertyType = ByteString>
|
||||
template<typename PropertyType = String>
|
||||
static ErrorOr<PropertyType, WebDriver::Error> get_property(JsonObject const& payload, StringView key)
|
||||
{
|
||||
auto property = payload.get(key);
|
||||
|
||||
if (!property.has_value())
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("No property called '{}' present", key));
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("No property called '{}' present", key)));
|
||||
|
||||
auto is_safe_number = []<typename T>(T value) {
|
||||
if constexpr (sizeof(T) >= 8) {
|
||||
|
@ -37,29 +37,29 @@ static ErrorOr<PropertyType, WebDriver::Error> get_property(JsonObject const& pa
|
|||
return true;
|
||||
};
|
||||
|
||||
if constexpr (IsSame<PropertyType, ByteString>) {
|
||||
if constexpr (IsSame<PropertyType, String>) {
|
||||
if (!property->is_string())
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not a String", key));
|
||||
return property->as_string().to_byte_string();
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("Property '{}' is not a String", key)));
|
||||
return property->as_string();
|
||||
} else if constexpr (IsSame<PropertyType, bool>) {
|
||||
if (!property->is_bool())
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not a Boolean", key));
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("Property '{}' is not a Boolean", key)));
|
||||
return property->as_bool();
|
||||
} else if constexpr (IsIntegral<PropertyType>) {
|
||||
if (auto maybe_number = property->get_integer<PropertyType>(); maybe_number.has_value() && is_safe_number(*maybe_number))
|
||||
return *maybe_number;
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not an Integer", key));
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("Property '{}' is not an Integer", key)));
|
||||
} else if constexpr (IsSame<PropertyType, double>) {
|
||||
if (auto maybe_number = property->get_double_with_precision_loss(); maybe_number.has_value() && is_safe_number(*maybe_number))
|
||||
return *maybe_number;
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not a Number", key));
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("Property '{}' is not a Number", key)));
|
||||
} else if constexpr (IsSame<PropertyType, JsonArray const*>) {
|
||||
if (!property->is_array())
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not an Array", key));
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("Property '{}' is not an Array", key)));
|
||||
return &property->as_array();
|
||||
} else if constexpr (IsSame<PropertyType, JsonObject const*>) {
|
||||
if (!property->is_object())
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not an Object", key));
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("Property '{}' is not an Object", key)));
|
||||
return &property->as_object();
|
||||
} else {
|
||||
static_assert(DependentFalse<PropertyType>, "get_property invoked with unknown property type");
|
||||
|
@ -67,15 +67,15 @@ static ErrorOr<PropertyType, WebDriver::Error> get_property(JsonObject const& pa
|
|||
}
|
||||
}
|
||||
|
||||
template<typename PropertyType = ByteString>
|
||||
template<typename PropertyType = String>
|
||||
static ErrorOr<PropertyType, WebDriver::Error> get_property(JsonValue const& payload, StringView key)
|
||||
{
|
||||
if (!payload.is_object())
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, "Payload is not a JSON object");
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, "Payload is not a JSON object"sv);
|
||||
return get_property<PropertyType>(payload.as_object(), key);
|
||||
}
|
||||
|
||||
template<typename PropertyType = ByteString>
|
||||
template<typename PropertyType = String>
|
||||
static ErrorOr<Optional<PropertyType>, WebDriver::Error> get_optional_property(JsonObject const& object, StringView key)
|
||||
{
|
||||
if (!object.has(key))
|
||||
|
@ -89,9 +89,9 @@ static ErrorOr<PropertyType, WebDriver::Error> get_property_with_limits(JsonObje
|
|||
auto value = TRY(get_property<PropertyType>(object, key));
|
||||
|
||||
if (min.has_value() && value < *min)
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' must not be less than {}", key, *min));
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, MUST(String::formatted("Property '{}' must not be less than {}", key, *min)));
|
||||
if (max.has_value() && value > *max)
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' must not be greater than {}", key, *max));
|
||||
return WebDriver::Error::from_code(WebDriver::ErrorCode::InvalidArgument, MUST(String::formatted("Property '{}' must not be greater than {}", key, *max)));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -58,8 +58,8 @@ ErrorOr<Web::WebDriver::Response> IPC::decode(Decoder& decoder)
|
|||
|
||||
case ResponseType::Error: {
|
||||
auto http_status = TRY(decoder.decode<unsigned>());
|
||||
auto error = TRY(decoder.decode<ByteString>());
|
||||
auto message = TRY(decoder.decode<ByteString>());
|
||||
auto error = TRY(decoder.decode<String>());
|
||||
auto message = TRY(decoder.decode<String>());
|
||||
auto data = TRY(decoder.decode<Optional<JsonValue>>());
|
||||
|
||||
return Web::WebDriver::Error { http_status, move(error), move(message), move(data) };
|
||||
|
|
|
@ -85,7 +85,7 @@ Response encode_canvas_element(HTML::HTMLCanvasElement& canvas)
|
|||
auto encoded_string = MUST(data_url.substring_from_byte_offset(*index + 1));
|
||||
|
||||
// 7. Return success with data encoded string.
|
||||
return JsonValue { encoded_string.to_byte_string() };
|
||||
return JsonValue { move(encoded_string) };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ ErrorOr<void, Error> json_deserialize_as_a_timeouts_configuration_into(JsonValue
|
|||
{
|
||||
// 1. Set timeouts to the result of converting a JSON-derived JavaScript value to an Infra value with timeouts.
|
||||
if (!timeouts.is_object())
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Payload is not a JSON object");
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Payload is not a JSON object"sv);
|
||||
|
||||
// 3. For each key → value in timeouts:
|
||||
TRY(timeouts.as_object().try_for_each_member([&](auto const& key, JsonValue const& value) -> ErrorOr<void, Error> {
|
||||
|
@ -62,7 +62,7 @@ ErrorOr<void, Error> json_deserialize_as_a_timeouts_configuration_into(JsonValue
|
|||
auto duration = value.get_integer<u64>();
|
||||
|
||||
if (!duration.has_value() || *duration > JS::MAX_ARRAY_LIKE_INDEX)
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Invalid timeout value");
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Invalid timeout value"sv);
|
||||
|
||||
parsed_value = static_cast<u64>(*duration);
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ static constexpr PromptType prompt_type_from_string(StringView prompt_type)
|
|||
|
||||
PromptHandlerConfiguration PromptHandlerConfiguration::deserialize(JsonValue const& configuration)
|
||||
{
|
||||
auto handler = prompt_handler_from_string(*configuration.as_object().get_byte_string("handler"sv));
|
||||
auto handler = prompt_handler_from_string(*configuration.as_object().get_string("handler"sv));
|
||||
|
||||
auto notify = *configuration.as_object().get_bool("notify"sv)
|
||||
? PromptHandlerConfiguration::Notify::Yes
|
||||
|
@ -138,7 +138,7 @@ Response deserialize_as_an_unhandled_prompt_behavior(JsonValue value)
|
|||
TRY(value.as_object().try_for_each_member([&](String const& prompt_type, JsonValue const& handler_value) -> ErrorOr<void, WebDriver::Error> {
|
||||
// 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));
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, MUST(String::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())
|
||||
|
@ -147,7 +147,7 @@ Response deserialize_as_an_unhandled_prompt_behavior(JsonValue value)
|
|||
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));
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, MUST(String::formatted("'{}' is not a known prompt handler", handler)));
|
||||
|
||||
// 3. Let notify be false.
|
||||
bool notify = false;
|
||||
|
|
|
@ -282,15 +282,13 @@ Messages::WebDriverClient::SetTimeoutsResponse WebDriverConnection::set_timeouts
|
|||
// 10.1 Navigate To, https://w3c.github.io/webdriver/#navigate-to
|
||||
Messages::WebDriverClient::NavigateToResponse WebDriverConnection::navigate_to(JsonValue const& payload)
|
||||
{
|
||||
dbgln_if(WEBDRIVER_DEBUG, "WebDriverConnection::navigate_to {}", payload);
|
||||
|
||||
// 1. If the current top-level browsing context is no longer open, return error with error code no such window.
|
||||
TRY(ensure_current_top_level_browsing_context_is_open());
|
||||
|
||||
// 2. Let url be the result of getting the property url from the parameters argument.
|
||||
if (!payload.is_object() || !payload.as_object().has_string("url"sv))
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "Payload doesn't have a string `url`"sv);
|
||||
auto url = URL::Parser::basic_parse(payload.as_object().get_byte_string("url"sv).value());
|
||||
auto url = URL::Parser::basic_parse(payload.as_object().get_string("url"sv).value());
|
||||
|
||||
// FIXME: 3. If url is not an absolute URL or is not an absolute URL with fragment or not a local scheme, return error with error code invalid argument.
|
||||
|
||||
|
@ -335,8 +333,6 @@ Messages::WebDriverClient::NavigateToResponse WebDriverConnection::navigate_to(J
|
|||
// 10.2 Get Current URL, https://w3c.github.io/webdriver/#get-current-url
|
||||
Messages::WebDriverClient::GetCurrentUrlResponse WebDriverConnection::get_current_url()
|
||||
{
|
||||
dbgln_if(WEBDRIVER_DEBUG, "WebDriverConnection::get_current_url");
|
||||
|
||||
// 1. If the current top-level browsing context is no longer open, return error with error code no such window.
|
||||
TRY(ensure_current_top_level_browsing_context_is_open());
|
||||
|
||||
|
@ -589,7 +585,7 @@ Messages::WebDriverClient::SwitchToWindowResponse WebDriverConnection::switch_to
|
|||
}
|
||||
|
||||
if (!found_matching_context)
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchWindow, "Window not found");
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchWindow, "Window not found"sv);
|
||||
|
||||
// 5. Update any implementation-specific state that would result from the user selecting the current
|
||||
// browsing context for interaction, without altering OS-level focus.
|
||||
|
@ -610,7 +606,7 @@ Messages::WebDriverClient::NewWindowResponse WebDriverConnection::new_window(Jso
|
|||
handle_any_user_prompts([this, payload = move(const_cast<JsonValue&>(payload))]() {
|
||||
// 4. Let type hint be the result of getting the property "type" from the parameters argument.
|
||||
if (!payload.is_object()) {
|
||||
async_driver_execution_complete(Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "Payload is not a JSON object"));
|
||||
async_driver_execution_complete(Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "Payload is not a JSON object"sv));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -688,7 +684,7 @@ Messages::WebDriverClient::SwitchToFrameResponse WebDriverConnection::switch_to_
|
|||
auto id_value = id.get_integer<u16>();
|
||||
|
||||
if (!id_value.has_value())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Frame ID {} is invalid", id));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, MUST(String::formatted("Frame ID {} is invalid", id)));
|
||||
|
||||
// 2. 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());
|
||||
|
@ -704,7 +700,7 @@ Messages::WebDriverClient::SwitchToFrameResponse WebDriverConnection::switch_to_
|
|||
auto property = window->get(id);
|
||||
|
||||
if (property.is_error() || !property.value().is_object() || !is<Web::HTML::WindowProxy>(property.value().as_object())) {
|
||||
async_driver_execution_complete(Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchFrame, ByteString::formatted("Frame ID {} not found", id)));
|
||||
async_driver_execution_complete(Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchFrame, MUST(String::formatted("Frame ID {} not found", id))));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -802,7 +798,7 @@ Messages::WebDriverClient::GetWindowRectResponse WebDriverConnection::get_window
|
|||
Messages::WebDriverClient::SetWindowRectResponse WebDriverConnection::set_window_rect(JsonValue const& payload)
|
||||
{
|
||||
if (!payload.is_object())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "Payload is not a JSON object");
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "Payload is not a JSON object"sv);
|
||||
|
||||
auto const& properties = payload.as_object();
|
||||
|
||||
|
@ -812,11 +808,11 @@ Messages::WebDriverClient::SetWindowRectResponse WebDriverConnection::set_window
|
|||
|
||||
auto value = property.get_double_with_precision_loss();
|
||||
if (!value.has_value())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not a Number", name));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, MUST(String::formatted("Property '{}' is not a Number", name)));
|
||||
if (*value < min)
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' value {} exceeds the minimum allowed value {}", name, *value, min));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, MUST(String::formatted("Property '{}' value {} exceeds the minimum allowed value {}", name, *value, min)));
|
||||
if (*value > max)
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' value {} exceeds the maximum allowed value {}", name, *value, max));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, MUST(String::formatted("Property '{}' value {} exceeds the maximum allowed value {}", name, *value, max)));
|
||||
|
||||
return value;
|
||||
};
|
||||
|
@ -990,7 +986,7 @@ Messages::WebDriverClient::FindElementResponse WebDriverConnection::find_element
|
|||
// 2. If location strategy is not present as a keyword in the table of location strategies, return error with error
|
||||
// code invalid argument.
|
||||
if (!location_strategy.has_value())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Location strategy '{}' is invalid", location_strategy_string));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, MUST(String::formatted("Location strategy '{}' is invalid", location_strategy_string)));
|
||||
|
||||
// 3. Let selector be the result of getting a property named "value" from parameters.
|
||||
// 4. If selector is undefined, return error with error code invalid argument.
|
||||
|
@ -1032,7 +1028,7 @@ Messages::WebDriverClient::FindElementsResponse WebDriverConnection::find_elemen
|
|||
// 2. If location strategy is not present as a keyword in the table of location strategies, return error with error
|
||||
// code invalid argument.
|
||||
if (!location_strategy.has_value())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Location strategy '{}' is invalid", location_strategy_string));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, MUST(String::formatted("Location strategy '{}' is invalid", location_strategy_string)));
|
||||
|
||||
// 3. Let selector be the result of getting a property named "value" from parameters.
|
||||
// 4. If selector is undefined, return error with error code invalid argument.
|
||||
|
@ -1072,7 +1068,7 @@ Messages::WebDriverClient::FindElementFromElementResponse WebDriverConnection::f
|
|||
|
||||
// 2. If location strategy is not present as a keyword in the table of location strategies, return error with error code invalid argument.
|
||||
if (!location_strategy.has_value())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Location strategy '{}' is invalid", location_strategy_string));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, MUST(String::formatted("Location strategy '{}' is invalid", location_strategy_string)));
|
||||
|
||||
// 3. Let selector be the result of getting a property named "value" from parameters.
|
||||
// 4. If selector is undefined, return error with error code invalid argument.
|
||||
|
@ -1107,7 +1103,7 @@ Messages::WebDriverClient::FindElementsFromElementResponse WebDriverConnection::
|
|||
|
||||
// 2. If location strategy is not present as a keyword in the table of location strategies, return error with error code invalid argument.
|
||||
if (!location_strategy.has_value())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Location strategy '{}' is invalid", location_strategy_string));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, MUST(String::formatted("Location strategy '{}' is invalid", location_strategy_string)));
|
||||
|
||||
// 3. Let selector be the result of getting a property named "value" from parameters.
|
||||
// 4. If selector is undefined, return error with error code invalid argument.
|
||||
|
@ -1141,7 +1137,7 @@ Messages::WebDriverClient::FindElementFromShadowRootResponse WebDriverConnection
|
|||
|
||||
// 2. If location strategy is not present as a keyword in the table of location strategies, return error with error code invalid argument.
|
||||
if (!location_strategy.has_value())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Location strategy '{}' is invalid", location_strategy_string));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, MUST(String::formatted("Location strategy '{}' is invalid", location_strategy_string)));
|
||||
|
||||
// 3. Let selector be the result of getting a property called "value".
|
||||
// 4. If selector is undefined, return error with error code invalid argument.
|
||||
|
@ -1176,7 +1172,7 @@ Messages::WebDriverClient::FindElementsFromShadowRootResponse WebDriverConnectio
|
|||
|
||||
// 2. If location strategy is not present as a keyword in the table of location strategies, return error with error code invalid argument.
|
||||
if (!location_strategy.has_value())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Location strategy '{}' is invalid", location_strategy_string));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, MUST(String::formatted("Location strategy '{}' is invalid", location_strategy_string)));
|
||||
|
||||
// 3. Let selector be the result of getting a property called "value".
|
||||
// 4. If selector is undefined, return error with error code invalid argument.
|
||||
|
@ -1242,7 +1238,7 @@ Messages::WebDriverClient::GetElementShadowRootResponse WebDriverConnection::get
|
|||
|
||||
// 5. If shadow root is null, return error with error code no such shadow root.
|
||||
if (!shadow_root) {
|
||||
async_driver_execution_complete(Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchShadowRoot, ByteString::formatted("Element with ID '{}' does not have a shadow root", element_id)));
|
||||
async_driver_execution_complete(Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchShadowRoot, MUST(String::formatted("Element with ID '{}' does not have a shadow root", element_id))));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1697,8 +1693,7 @@ Web::WebDriver::Response WebDriverConnection::element_click_impl(String const& e
|
|||
pointer_move_action.pointer_move_fields().position = { 0, 0 };
|
||||
|
||||
// 10. Set a property origin to element on pointer move action.
|
||||
auto origin = Web::WebDriver::get_or_create_a_web_element_reference(current_browsing_context(), *element);
|
||||
pointer_move_action.pointer_move_fields().origin = MUST(String::from_byte_string(origin));
|
||||
pointer_move_action.pointer_move_fields().origin = Web::WebDriver::get_or_create_a_web_element_reference(current_browsing_context(), *element);
|
||||
|
||||
// 11. Let pointer down action be an action object constructed with arguments input id, "pointer", and "pointerDown".
|
||||
Web::WebDriver::ActionObject pointer_down_action { input_id, Web::WebDriver::InputSourceType::Pointer, Web::WebDriver::ActionObject::Subtype::PointerDown };
|
||||
|
@ -1858,7 +1853,7 @@ Messages::WebDriverClient::ElementSendKeysResponse WebDriverConnection::element_
|
|||
return JsonValue {};
|
||||
}
|
||||
|
||||
Web::WebDriver::Response WebDriverConnection::element_send_keys_impl(String const& element_id, ByteString const& text)
|
||||
Web::WebDriver::Response WebDriverConnection::element_send_keys_impl(String const& element_id, String const& text)
|
||||
{
|
||||
// 5. Let element be the result of trying to get a known element with session and URL variables[element id].
|
||||
auto element = TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id));
|
||||
|
@ -1895,7 +1890,7 @@ Web::WebDriver::Response WebDriverConnection::element_send_keys_impl(String cons
|
|||
auto& input_element = static_cast<Web::HTML::HTMLInputElement&>(*element);
|
||||
|
||||
// 1. Let files be the result of splitting text on the newline (\n) character.
|
||||
auto files = text.split('\n');
|
||||
auto files = MUST(text.split('\n'));
|
||||
|
||||
// 2. If files is of 0 length, return an error with error code invalid argument.
|
||||
if (files.is_empty())
|
||||
|
@ -1922,9 +1917,9 @@ Web::WebDriver::Response WebDriverConnection::element_send_keys_impl(String cons
|
|||
selected_files.ensure_capacity(files.size());
|
||||
|
||||
for (auto const& path : files) {
|
||||
auto selected_file = create_selected_file(path);
|
||||
auto selected_file = create_selected_file(path.bytes_as_string_view());
|
||||
if (selected_file.is_error())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("'{}' does not exist", path));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, MUST(String::formatted("'{}' does not exist", path)));
|
||||
|
||||
selected_files.unchecked_append(selected_file.release_value());
|
||||
}
|
||||
|
@ -1956,7 +1951,7 @@ Web::WebDriver::Response WebDriverConnection::element_send_keys_impl(String cons
|
|||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::ElementNotInteractable, "Element is immutable"sv);
|
||||
|
||||
// 3. Set a property value to text on element.
|
||||
MUST(input_element.set_value(MUST(String::from_byte_string(text))));
|
||||
MUST(input_element.set_value(text));
|
||||
|
||||
// FIXME: 4. If element is suffering from bad input return an error with error code invalid argument.
|
||||
|
||||
|
@ -2124,7 +2119,7 @@ void WebDriverConnection::handle_script_response(Web::WebDriver::ExecutionResult
|
|||
// 10. If promise is still pending and timer's timeout fired flag is set, return error with error code script
|
||||
// timeout.
|
||||
case JS::Promise::State::Pending:
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::ScriptTimeoutError, "Script timed out");
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::ScriptTimeoutError, "Script timed out"sv);
|
||||
|
||||
// 11. If promise is fulfilled with value v, let result be JSON clone with session and v, and return success
|
||||
// with data result.
|
||||
|
@ -2135,7 +2130,7 @@ void WebDriverConnection::handle_script_response(Web::WebDriver::ExecutionResult
|
|||
// with error code javascript error and data result.
|
||||
case JS::Promise::State::Rejected: {
|
||||
auto reason = TRY(Web::WebDriver::json_clone(current_browsing_context(), result.value));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::JavascriptError, "Script returned an error", move(reason));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::JavascriptError, "Script returned an error"sv, move(reason));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2192,7 +2187,7 @@ Messages::WebDriverClient::GetNamedCookieResponse WebDriverConnection::get_named
|
|||
}
|
||||
|
||||
// 4. Otherwise, return error with error code no such cookie.
|
||||
async_driver_execution_complete(Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchCookie, ByteString::formatted("Cookie '{}' not found", name)));
|
||||
async_driver_execution_complete(Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchCookie, MUST(String::formatted("Cookie '{}' not found", name))));
|
||||
});
|
||||
|
||||
return JsonValue {};
|
||||
|
@ -2235,13 +2230,13 @@ Web::WebDriver::Response WebDriverConnection::add_cookie_impl(JsonObject const&
|
|||
|
||||
// 7. Create a cookie in the cookie store associated with the active document’s address using cookie name name, cookie value value, and an attribute-value list of the following cookie concepts listed in the table for cookie conversion from data:
|
||||
Web::Cookie::ParsedCookie cookie {};
|
||||
cookie.name = MUST(String::from_byte_string(TRY(Web::WebDriver::get_property(data, "name"sv))));
|
||||
cookie.value = MUST(String::from_byte_string(TRY(Web::WebDriver::get_property(data, "value"sv))));
|
||||
cookie.name = TRY(Web::WebDriver::get_property(data, "name"sv));
|
||||
cookie.value = TRY(Web::WebDriver::get_property(data, "value"sv));
|
||||
|
||||
// Cookie path
|
||||
// The value if the entry exists, otherwise "/".
|
||||
if (data.has("path"sv))
|
||||
cookie.path = MUST(String::from_byte_string(TRY(Web::WebDriver::get_property(data, "path"sv))));
|
||||
cookie.path = TRY(Web::WebDriver::get_property(data, "path"sv));
|
||||
else
|
||||
cookie.path = "/"_string;
|
||||
|
||||
|
@ -2249,7 +2244,7 @@ Web::WebDriver::Response WebDriverConnection::add_cookie_impl(JsonObject const&
|
|||
// The value if the entry exists, otherwise the current browsing context’s active document’s URL domain.
|
||||
// NOTE: The otherwise case is handled by the CookieJar
|
||||
if (data.has("domain"sv)) {
|
||||
cookie.domain = MUST(String::from_byte_string(TRY(Web::WebDriver::get_property(data, "domain"sv))));
|
||||
cookie.domain = TRY(Web::WebDriver::get_property(data, "domain"sv));
|
||||
|
||||
// FIXME: Spec issue: We must return InvalidCookieDomain for invalid domains, rather than InvalidArgument.
|
||||
// https://github.com/w3c/webdriver/issues/1570
|
||||
|
@ -2504,7 +2499,7 @@ Messages::WebDriverClient::SendAlertTextResponse WebDriverConnection::send_alert
|
|||
}
|
||||
|
||||
// 6. Perform user agent dependent steps to set the value of current user prompt’s text field to text.
|
||||
current_browsing_context().page().client().page_did_request_set_prompt_text(TRY(String::from_byte_string(text)));
|
||||
current_browsing_context().page().client().page_did_request_set_prompt_text(text);
|
||||
|
||||
// 7. Return success with data null.
|
||||
return JsonValue {};
|
||||
|
@ -2932,7 +2927,7 @@ public:
|
|||
ElementLocator(
|
||||
Web::HTML::BrowsingContext const& browsing_context,
|
||||
Web::WebDriver::LocationStrategy location_strategy,
|
||||
ByteString selector,
|
||||
String selector,
|
||||
WebDriverConnection::GetStartNode get_start_node,
|
||||
WebDriverConnection::OnFindComplete on_complete,
|
||||
GC::Ref<Web::WebDriver::HeapTimer> timer)
|
||||
|
@ -2970,7 +2965,7 @@ private:
|
|||
// 2. If a DOMException, SyntaxError, XPathException, or other error occurs during the execution of the element
|
||||
// location strategy, return error invalid selector.
|
||||
if (maybe_elements.is_error())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidSelector, ByteString::formatted("The location strategy could not finish: {}", maybe_elements.error().message));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidSelector, MUST(String::formatted("The location strategy could not finish: {}", maybe_elements.error().message)));
|
||||
|
||||
if (auto elements = maybe_elements.release_value(); elements->length() > 0) {
|
||||
// 8. Let result be an empty List.
|
||||
|
@ -3001,7 +2996,7 @@ private:
|
|||
GC::Ref<Web::HTML::BrowsingContext const> m_browsing_context;
|
||||
|
||||
Web::WebDriver::LocationStrategy m_location_strategy;
|
||||
ByteString m_selector;
|
||||
String m_selector;
|
||||
|
||||
WebDriverConnection::GetStartNode m_get_start_node;
|
||||
WebDriverConnection::OnFindComplete m_on_complete;
|
||||
|
@ -3012,7 +3007,7 @@ private:
|
|||
GC_DEFINE_ALLOCATOR(ElementLocator);
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-find
|
||||
void WebDriverConnection::find(Web::WebDriver::LocationStrategy location_strategy, ByteString selector, GetStartNode get_start_node, OnFindComplete on_complete)
|
||||
void WebDriverConnection::find(Web::WebDriver::LocationStrategy location_strategy, String selector, GetStartNode get_start_node, OnFindComplete on_complete)
|
||||
{
|
||||
auto& realm = current_browsing_context().active_document()->realm();
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ private:
|
|||
|
||||
Web::WebDriver::Response element_click_impl(String const& element_id);
|
||||
Web::WebDriver::Response element_clear_impl(String const& element_id);
|
||||
Web::WebDriver::Response element_send_keys_impl(String const& element_id, ByteString const& text);
|
||||
Web::WebDriver::Response element_send_keys_impl(String const& element_id, String const& text);
|
||||
Web::WebDriver::Response add_cookie_impl(JsonObject const&);
|
||||
|
||||
Web::WebDriver::PromptHandlerConfiguration get_the_prompt_handler(Web::WebDriver::PromptType type) const;
|
||||
|
@ -142,10 +142,10 @@ private:
|
|||
|
||||
using GetStartNode = GC::Ref<GC::Function<ErrorOr<GC::Ref<Web::DOM::ParentNode>, Web::WebDriver::Error>()>>;
|
||||
using OnFindComplete = GC::Ref<GC::Function<void(Web::WebDriver::Response)>>;
|
||||
void find(Web::WebDriver::LocationStrategy, ByteString, GetStartNode, OnFindComplete);
|
||||
void find(Web::WebDriver::LocationStrategy, String, GetStartNode, OnFindComplete);
|
||||
|
||||
struct ScriptArguments {
|
||||
ByteString script;
|
||||
String script;
|
||||
GC::RootVector<JS::Value> arguments;
|
||||
};
|
||||
ErrorOr<ScriptArguments, Web::WebDriver::Error> extract_the_script_arguments_from_a_request(JS::VM&, JsonValue const& payload);
|
||||
|
|
|
@ -68,7 +68,7 @@ Web::WebDriver::Response Client::new_session(Web::WebDriver::Parameters, JsonVal
|
|||
// 6. Let session be the result of create a session, with capabilities, and flags.
|
||||
auto maybe_session = Session::create(*this, capabilities.as_object(), flags);
|
||||
if (maybe_session.is_error())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::SessionNotCreated, ByteString::formatted("Failed to start session: {}", maybe_session.error()));
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::SessionNotCreated, MUST(String::formatted("Failed to start session: {}", maybe_session.error())));
|
||||
|
||||
auto session = maybe_session.release_value();
|
||||
|
||||
|
@ -258,14 +258,14 @@ Web::WebDriver::Response Client::switch_to_window(Web::WebDriver::Parameters par
|
|||
auto session = TRY(Session::find_session(parameters[0], Web::WebDriver::SessionFlags::Default, Session::AllowInvalidWindowHandle::Yes));
|
||||
|
||||
if (!payload.is_object())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "Payload is not a JSON object");
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "Payload is not a JSON object"sv);
|
||||
|
||||
// 1. Let handle be the result of getting the property "handle" from the parameters argument.
|
||||
auto handle = payload.as_object().get("handle"sv);
|
||||
|
||||
// 2. If handle is undefined, return error with error code invalid argument.
|
||||
if (!handle.has_value())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "No property called 'handle' present");
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "No property called 'handle' present"sv);
|
||||
|
||||
return session->switch_to_window(handle->as_string());
|
||||
}
|
||||
|
@ -300,7 +300,7 @@ Web::WebDriver::Response Client::new_window(Web::WebDriver::Parameters parameter
|
|||
});
|
||||
|
||||
if (timeout_fired)
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::Timeout, "Timed out waiting for window handle");
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::Timeout, "Timed out waiting for window handle"sv);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ ErrorOr<NonnullRefPtr<Session>> Session::create(NonnullRefPtr<Client> client, Js
|
|||
// 1. Let strategy be the result of getting property "pageLoadStrategy" from capabilities. If strategy is a
|
||||
// string, set the 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 (auto strategy = capabilities.get_byte_string("pageLoadStrategy"sv); strategy.has_value()) {
|
||||
if (auto strategy = capabilities.get_string("pageLoadStrategy"sv); strategy.has_value()) {
|
||||
session->m_page_load_strategy = Web::WebDriver::page_load_strategy_from_string(*strategy);
|
||||
session->web_content_connection().async_set_page_load_strategy(session->m_page_load_strategy);
|
||||
} else {
|
||||
|
@ -139,7 +139,7 @@ ErrorOr<NonnullRefPtr<Session>, Web::WebDriver::Error> Session::find_session(Str
|
|||
return *session.release_value();
|
||||
}
|
||||
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidSessionId, "Invalid session id");
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidSessionId, "Invalid session id"sv);
|
||||
}
|
||||
|
||||
size_t Session::session_count(Web::WebDriver::SessionFlags session_flags)
|
||||
|
@ -306,7 +306,7 @@ Web::WebDriver::Response Session::switch_to_window(StringView handle)
|
|||
if (auto it = m_windows.find(handle); it != m_windows.end())
|
||||
m_current_window_handle = it->key;
|
||||
else
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchWindow, "Window not found");
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchWindow, "Window not found"sv);
|
||||
|
||||
// 5. Update any implementation-specific state that would result from the user selecting the current
|
||||
// browsing context for interaction, without altering OS-level focus.
|
||||
|
|
Loading…
Add table
Reference in a new issue