mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 20:15:17 +00:00
LibWeb+WebContent: Move WebDriver property extraction to a helper file
This will be needed outside of WebContent.
This commit is contained in:
parent
5e99715377
commit
8944c6db3f
Notes:
github-actions[bot]
2024-10-01 09:04:02 +00:00
Author: https://github.com/trflynn89 Commit: https://github.com/LadybirdBrowser/ladybird/commit/8944c6db3f8 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1566
2 changed files with 80 additions and 62 deletions
54
Userland/Libraries/LibWeb/WebDriver/Properties.h
Normal file
54
Userland/Libraries/LibWeb/WebDriver/Properties.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Tim Flynn <trflynn89@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/ByteString.h>
|
||||
#include <AK/JsonArray.h>
|
||||
#include <AK/JsonObject.h>
|
||||
#include <AK/JsonValue.h>
|
||||
#include <LibWeb/WebDriver/Error.h>
|
||||
|
||||
namespace Web::WebDriver {
|
||||
|
||||
template<typename PropertyType = ByteString>
|
||||
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");
|
||||
|
||||
auto property = payload.as_object().get(key);
|
||||
|
||||
if (!property.has_value())
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::formatted("No property called '{}' present", key));
|
||||
|
||||
if constexpr (IsSame<PropertyType, ByteString>) {
|
||||
if (!property->is_string())
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::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 property->as_bool();
|
||||
} else if constexpr (IsSame<PropertyType, u32>) {
|
||||
if (auto maybe_u32 = property->get_u32(); maybe_u32.has_value())
|
||||
return *maybe_u32;
|
||||
return WebDriver::Error::from_code(ErrorCode::InvalidArgument, ByteString::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 &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 &property->as_object();
|
||||
} else {
|
||||
static_assert(DependentFalse<PropertyType>, "get_property invoked with unknown property type");
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (c) 2022-2023, Sam Atkins <atkinssj@serenityos.org>
|
||||
* Copyright (c) 2022, Tobias Christiansen <tobyase@serenityos.org>
|
||||
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2022-2024, Tim Flynn <trflynn89@serenityos.org>
|
||||
* Copyright (c) 2022-2024, Tim Flynn <trflynn89@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -46,6 +46,7 @@
|
|||
#include <LibWeb/UIEvents/MouseEvent.h>
|
||||
#include <LibWeb/WebDriver/ElementReference.h>
|
||||
#include <LibWeb/WebDriver/ExecuteScript.h>
|
||||
#include <LibWeb/WebDriver/Properties.h>
|
||||
#include <LibWeb/WebDriver/Screenshot.h>
|
||||
#include <WebContent/WebDriverConnection.h>
|
||||
|
||||
|
@ -115,43 +116,6 @@ static ErrorOr<void> scroll_element_into_view(Web::DOM::Element& element)
|
|||
return {};
|
||||
}
|
||||
|
||||
template<typename PropertyType = ByteString>
|
||||
static ErrorOr<PropertyType, Web::WebDriver::Error> get_property(JsonValue const& payload, StringView key)
|
||||
{
|
||||
if (!payload.is_object())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "Payload is not a JSON object");
|
||||
|
||||
auto property = payload.as_object().get(key);
|
||||
|
||||
if (!property.has_value())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("No property called '{}' present", key));
|
||||
|
||||
if constexpr (IsSame<PropertyType, ByteString>) {
|
||||
if (!property->is_string())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not a String", key));
|
||||
return property->as_string();
|
||||
} else if constexpr (IsSame<PropertyType, bool>) {
|
||||
if (!property->is_bool())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not a Boolean", key));
|
||||
return property->as_bool();
|
||||
} else if constexpr (IsSame<PropertyType, u32>) {
|
||||
if (auto maybe_u32 = property->get_u32(); maybe_u32.has_value())
|
||||
return *maybe_u32;
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not a Number", key));
|
||||
} else if constexpr (IsSame<PropertyType, JsonArray const*>) {
|
||||
if (!property->is_array())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not an Array", key));
|
||||
return &property->as_array();
|
||||
} else if constexpr (IsSame<PropertyType, JsonObject const*>) {
|
||||
if (!property->is_object())
|
||||
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not an Object", key));
|
||||
return &property->as_object();
|
||||
} else {
|
||||
static_assert(DependentFalse<PropertyType>, "get_property invoked with unknown property type");
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-container
|
||||
static Optional<Web::DOM::Element&> container_for_element(Web::DOM::Element& element)
|
||||
{
|
||||
|
@ -800,7 +764,7 @@ Messages::WebDriverClient::ConsumeUserActivationResponse WebDriverConnection::co
|
|||
Messages::WebDriverClient::FindElementResponse WebDriverConnection::find_element(JsonValue const& payload)
|
||||
{
|
||||
// 1. Let location strategy be the result of getting a property called "using".
|
||||
auto location_strategy_string = TRY(get_property(payload, "using"sv));
|
||||
auto location_strategy_string = TRY(Web::WebDriver::get_property(payload, "using"sv));
|
||||
auto location_strategy = Web::WebDriver::location_strategy_from_string(location_strategy_string);
|
||||
|
||||
// 2. If location strategy is not present as a keyword in the table of location strategies, return error with error code invalid argument.
|
||||
|
@ -809,7 +773,7 @@ Messages::WebDriverClient::FindElementResponse WebDriverConnection::find_element
|
|||
|
||||
// 3. Let selector be the result of getting a property called "value".
|
||||
// 4. If selector is undefined, return error with error code invalid argument.
|
||||
auto selector = TRY(get_property(payload, "value"sv));
|
||||
auto selector = TRY(Web::WebDriver::get_property(payload, "value"sv));
|
||||
|
||||
// 5. If the current browsing context is no longer open, return error with error code no such window.
|
||||
TRY(ensure_current_browsing_context_is_open());
|
||||
|
@ -842,7 +806,7 @@ Messages::WebDriverClient::FindElementResponse WebDriverConnection::find_element
|
|||
Messages::WebDriverClient::FindElementsResponse WebDriverConnection::find_elements(JsonValue const& payload)
|
||||
{
|
||||
// 1. Let location strategy be the result of getting a property called "using".
|
||||
auto location_strategy_string = TRY(get_property(payload, "using"sv));
|
||||
auto location_strategy_string = TRY(Web::WebDriver::get_property(payload, "using"sv));
|
||||
auto location_strategy = Web::WebDriver::location_strategy_from_string(location_strategy_string);
|
||||
|
||||
// 2. If location strategy is not present as a keyword in the table of location strategies, return error with error code invalid argument.
|
||||
|
@ -851,7 +815,7 @@ Messages::WebDriverClient::FindElementsResponse WebDriverConnection::find_elemen
|
|||
|
||||
// 3. Let selector be the result of getting a property called "value".
|
||||
// 4. If selector is undefined, return error with error code invalid argument.
|
||||
auto selector = TRY(get_property(payload, "value"sv));
|
||||
auto selector = TRY(Web::WebDriver::get_property(payload, "value"sv));
|
||||
|
||||
// 5. If the current browsing context is no longer open, return error with error code no such window.
|
||||
TRY(ensure_current_browsing_context_is_open());
|
||||
|
@ -878,7 +842,7 @@ Messages::WebDriverClient::FindElementsResponse WebDriverConnection::find_elemen
|
|||
Messages::WebDriverClient::FindElementFromElementResponse WebDriverConnection::find_element_from_element(JsonValue const& payload, String const& element_id)
|
||||
{
|
||||
// 1. Let location strategy be the result of getting a property called "using".
|
||||
auto location_strategy_string = TRY(get_property(payload, "using"sv));
|
||||
auto location_strategy_string = TRY(Web::WebDriver::get_property(payload, "using"sv));
|
||||
auto location_strategy = Web::WebDriver::location_strategy_from_string(location_strategy_string);
|
||||
|
||||
// 2. If location strategy is not present as a keyword in the table of location strategies, return error with error code invalid argument.
|
||||
|
@ -887,7 +851,7 @@ Messages::WebDriverClient::FindElementFromElementResponse WebDriverConnection::f
|
|||
|
||||
// 3. Let selector be the result of getting a property called "value".
|
||||
// 4. If selector is undefined, return error with error code invalid argument.
|
||||
auto selector = TRY(get_property(payload, "value"sv));
|
||||
auto selector = TRY(Web::WebDriver::get_property(payload, "value"sv));
|
||||
|
||||
// 5. If the current browsing context is no longer open, return error with error code no such window.
|
||||
TRY(ensure_current_browsing_context_is_open());
|
||||
|
@ -914,7 +878,7 @@ Messages::WebDriverClient::FindElementFromElementResponse WebDriverConnection::f
|
|||
Messages::WebDriverClient::FindElementsFromElementResponse WebDriverConnection::find_elements_from_element(JsonValue const& payload, String const& element_id)
|
||||
{
|
||||
// 1. Let location strategy be the result of getting a property called "using".
|
||||
auto location_strategy_string = TRY(get_property(payload, "using"sv));
|
||||
auto location_strategy_string = TRY(Web::WebDriver::get_property(payload, "using"sv));
|
||||
auto location_strategy = Web::WebDriver::location_strategy_from_string(location_strategy_string);
|
||||
|
||||
// 2. If location strategy is not present as a keyword in the table of location strategies, return error with error code invalid argument.
|
||||
|
@ -923,7 +887,7 @@ Messages::WebDriverClient::FindElementsFromElementResponse WebDriverConnection::
|
|||
|
||||
// 3. Let selector be the result of getting a property called "value".
|
||||
// 4. If selector is undefined, return error with error code invalid argument.
|
||||
auto selector = TRY(get_property(payload, "value"sv));
|
||||
auto selector = TRY(Web::WebDriver::get_property(payload, "value"sv));
|
||||
|
||||
// 5. If the current browsing context is no longer open, return error with error code no such window.
|
||||
TRY(ensure_current_browsing_context_is_open());
|
||||
|
@ -944,7 +908,7 @@ Messages::WebDriverClient::FindElementsFromElementResponse WebDriverConnection::
|
|||
Messages::WebDriverClient::FindElementFromShadowRootResponse WebDriverConnection::find_element_from_shadow_root(JsonValue const& payload, String const& shadow_id)
|
||||
{
|
||||
// 1. Let location strategy be the result of getting a property called "using".
|
||||
auto location_strategy_string = TRY(get_property(payload, "using"sv));
|
||||
auto location_strategy_string = TRY(Web::WebDriver::get_property(payload, "using"sv));
|
||||
auto location_strategy = Web::WebDriver::location_strategy_from_string(location_strategy_string);
|
||||
|
||||
// 2. If location strategy is not present as a keyword in the table of location strategies, return error with error code invalid argument.
|
||||
|
@ -953,7 +917,7 @@ Messages::WebDriverClient::FindElementFromShadowRootResponse WebDriverConnection
|
|||
|
||||
// 3. Let selector be the result of getting a property called "value".
|
||||
// 4. If selector is undefined, return error with error code invalid argument.
|
||||
auto selector = TRY(get_property(payload, "value"sv));
|
||||
auto selector = TRY(Web::WebDriver::get_property(payload, "value"sv));
|
||||
|
||||
// 5. If the current browsing context is no longer open, return error with error code no such window.
|
||||
TRY(ensure_current_browsing_context_is_open());
|
||||
|
@ -980,7 +944,7 @@ Messages::WebDriverClient::FindElementFromShadowRootResponse WebDriverConnection
|
|||
Messages::WebDriverClient::FindElementsFromShadowRootResponse WebDriverConnection::find_elements_from_shadow_root(JsonValue const& payload, String const& shadow_id)
|
||||
{
|
||||
// 1. Let location strategy be the result of getting a property called "using".
|
||||
auto location_strategy_string = TRY(get_property(payload, "using"sv));
|
||||
auto location_strategy_string = TRY(Web::WebDriver::get_property(payload, "using"sv));
|
||||
auto location_strategy = Web::WebDriver::location_strategy_from_string(location_strategy_string);
|
||||
|
||||
// 2. If location strategy is not present as a keyword in the table of location strategies, return error with error code invalid argument.
|
||||
|
@ -989,7 +953,7 @@ Messages::WebDriverClient::FindElementsFromShadowRootResponse WebDriverConnectio
|
|||
|
||||
// 3. Let selector be the result of getting a property called "value".
|
||||
// 4. If selector is undefined, return error with error code invalid argument.
|
||||
auto selector = TRY(get_property(payload, "value"sv));
|
||||
auto selector = TRY(Web::WebDriver::get_property(payload, "value"sv));
|
||||
|
||||
// 5. If the current browsing context is no longer open, return error with error code no such window.
|
||||
TRY(ensure_current_browsing_context_is_open());
|
||||
|
@ -1819,7 +1783,7 @@ Messages::WebDriverClient::GetNamedCookieResponse WebDriverConnection::get_named
|
|||
Messages::WebDriverClient::AddCookieResponse WebDriverConnection::add_cookie(JsonValue const& payload)
|
||||
{
|
||||
// 1. Let data be the result of getting a property named cookie from the parameters argument.
|
||||
auto const& data = *TRY(get_property<JsonObject const*>(payload, "cookie"sv));
|
||||
auto const& data = *TRY(Web::WebDriver::get_property<JsonObject const*>(payload, "cookie"sv));
|
||||
|
||||
// 2. If data is not a JSON Object with all the required (non-optional) JSON keys listed in the table for cookie conversion, return error with error code invalid argument.
|
||||
// NOTE: This validation is performed in subsequent steps.
|
||||
|
@ -1837,13 +1801,13 @@ Messages::WebDriverClient::AddCookieResponse WebDriverConnection::add_cookie(Jso
|
|||
|
||||
// 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(get_property(data, "name"sv))));
|
||||
cookie.value = MUST(String::from_byte_string(TRY(get_property(data, "value"sv))));
|
||||
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 path
|
||||
// The value if the entry exists, otherwise "/".
|
||||
if (data.has("path"sv))
|
||||
cookie.path = MUST(String::from_byte_string(TRY(get_property(data, "path"sv))));
|
||||
cookie.path = MUST(String::from_byte_string(TRY(Web::WebDriver::get_property(data, "path"sv))));
|
||||
else
|
||||
cookie.path = "/"_string;
|
||||
|
||||
|
@ -1851,30 +1815,30 @@ Messages::WebDriverClient::AddCookieResponse WebDriverConnection::add_cookie(Jso
|
|||
// 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(get_property(data, "domain"sv))));
|
||||
cookie.domain = MUST(String::from_byte_string(TRY(Web::WebDriver::get_property(data, "domain"sv))));
|
||||
|
||||
// Cookie secure only
|
||||
// The value if the entry exists, otherwise false.
|
||||
if (data.has("secure"sv))
|
||||
cookie.secure_attribute_present = TRY(get_property<bool>(data, "secure"sv));
|
||||
cookie.secure_attribute_present = TRY(Web::WebDriver::get_property<bool>(data, "secure"sv));
|
||||
|
||||
// Cookie HTTP only
|
||||
// The value if the entry exists, otherwise false.
|
||||
if (data.has("httpOnly"sv))
|
||||
cookie.http_only_attribute_present = TRY(get_property<bool>(data, "httpOnly"sv));
|
||||
cookie.http_only_attribute_present = TRY(Web::WebDriver::get_property<bool>(data, "httpOnly"sv));
|
||||
|
||||
// Cookie expiry time
|
||||
// The value if the entry exists, otherwise leave unset to indicate that this is a session cookie.
|
||||
if (data.has("expiry"sv)) {
|
||||
// NOTE: less than 0 or greater than safe integer are handled by the JSON parser
|
||||
auto expiry = TRY(get_property<u32>(data, "expiry"sv));
|
||||
auto expiry = TRY(Web::WebDriver::get_property<u32>(data, "expiry"sv));
|
||||
cookie.expiry_time_from_expires_attribute = UnixDateTime::from_seconds_since_epoch(expiry);
|
||||
}
|
||||
|
||||
// Cookie same site
|
||||
// The value if the entry exists, otherwise leave unset to indicate that no same site policy is defined.
|
||||
if (data.has("sameSite"sv)) {
|
||||
auto same_site = TRY(get_property(data, "sameSite"sv));
|
||||
auto same_site = TRY(Web::WebDriver::get_property(data, "sameSite"sv));
|
||||
cookie.same_site_attribute = Web::Cookie::same_site_from_string(same_site);
|
||||
}
|
||||
|
||||
|
@ -2012,7 +1976,7 @@ Messages::WebDriverClient::SendAlertTextResponse WebDriverConnection::send_alert
|
|||
{
|
||||
// 1. Let text be the result of getting the property "text" from parameters.
|
||||
// 2. If text is not a String, return error with error code invalid argument.
|
||||
auto text = TRY(get_property(payload, "text"sv));
|
||||
auto text = TRY(Web::WebDriver::get_property(payload, "text"sv));
|
||||
|
||||
// 3. 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());
|
||||
|
@ -2356,11 +2320,11 @@ ErrorOr<WebDriverConnection::ScriptArguments, Web::WebDriver::Error> WebDriverCo
|
|||
|
||||
// 1. Let script be the result of getting a property named script from the parameters.
|
||||
// 2. If script is not a String, return error with error code invalid argument.
|
||||
auto script = TRY(get_property(payload, "script"sv));
|
||||
auto script = TRY(Web::WebDriver::get_property(payload, "script"sv));
|
||||
|
||||
// 3. Let args be the result of getting a property named args from the parameters.
|
||||
// 4. If args is not an Array return error with error code invalid argument.
|
||||
auto const& args = *TRY(get_property<JsonArray const*>(payload, "args"sv));
|
||||
auto const& args = *TRY(Web::WebDriver::get_property<JsonArray const*>(payload, "args"sv));
|
||||
|
||||
// 5. Let arguments be the result of calling the JSON deserialize algorithm with arguments args.
|
||||
auto arguments = JS::MarkedVector<JS::Value> { vm.heap() };
|
||||
|
|
Loading…
Add table
Reference in a new issue