LibWeb+WebContent+WebDriver: Port WebDriver to String

This commit is contained in:
Timothy Flynn 2025-02-17 13:58:21 -05:00 committed by Tim Flynn
parent bc54c0cdfb
commit 9879ac0893
Notes: github-actions[bot] 2025-02-21 00:29:12 +00:00
21 changed files with 194 additions and 190 deletions

View file

@ -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);

View file

@ -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"

View file

@ -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);

View file

@ -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 windows 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();
}

View file

@ -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);

View file

@ -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);

View file

@ -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_))

View file

@ -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)));
}
};

View file

@ -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 contexts 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();

View file

@ -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);
}

View file

@ -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.

View file

@ -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

View file

@ -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;
}

View file

@ -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) };

View file

@ -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) };
}
}

View file

@ -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);
}

View file

@ -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;

View file

@ -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 documents 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 contexts active documents 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 prompts 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();

View file

@ -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);

View file

@ -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;
}

View file

@ -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.