mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-19 15:32:31 +00:00
LibWeb+WebDriver: Validate WebDriver proxy capabilities
We don't yet support a proxy configuration, but we can still validate the capability received from the WebDriver client. We should also fail to create a WebDriver session if a proxy configuration is present.
This commit is contained in:
parent
88eda159af
commit
d873dc0744
Notes:
github-actions[bot]
2025-02-10 16:34:53 +00:00
Author: https://github.com/trflynn89
Commit: d873dc0744
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3497
5 changed files with 178 additions and 34 deletions
135
Libraries/LibWeb/WebDriver/Proxy.cpp
Normal file
135
Libraries/LibWeb/WebDriver/Proxy.cpp
Normal file
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Tim Flynn <trflynn89@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/JsonValue.h>
|
||||
#include <LibURL/URL.h>
|
||||
#include <LibWeb/WebDriver/Proxy.h>
|
||||
|
||||
namespace Web::WebDriver {
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-has-proxy-configuration
|
||||
// An endpoint node has an associated has proxy configuration flag that indicates whether the proxy is already configured.
|
||||
// The default value of the flag is true if the endpoint doesn't support proxy configuration, or false otherwise.
|
||||
static constexpr bool s_default_has_proxy_configuration = true;
|
||||
static bool s_has_proxy_configuration = s_default_has_proxy_configuration;
|
||||
|
||||
bool has_proxy_configuration()
|
||||
{
|
||||
return s_has_proxy_configuration;
|
||||
}
|
||||
|
||||
void set_has_proxy_configuration(bool has_proxy_configuration)
|
||||
{
|
||||
s_has_proxy_configuration = has_proxy_configuration;
|
||||
}
|
||||
|
||||
void reset_has_proxy_configuration()
|
||||
{
|
||||
s_has_proxy_configuration = s_default_has_proxy_configuration;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-proxy-configuration
|
||||
static ErrorOr<void, Error> validate_proxy_item(StringView key, JsonValue const& value)
|
||||
{
|
||||
if (key == "proxyType"sv) {
|
||||
if (!value.is_string())
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Proxy configuration item 'proxyType' must be a string"sv);
|
||||
if (!value.as_string().is_one_of("pac"sv, "direct"sv, "autodetect"sv, "system"sv, "manual"sv))
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Invalid 'proxyType' value"sv);
|
||||
return {};
|
||||
}
|
||||
|
||||
if (key == "proxyAutoconfigUrl"sv) {
|
||||
if (!value.is_string())
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Proxy configuration item 'proxyAutoconfigUrl' must be a string"sv);
|
||||
if (URL::URL url { value.as_string() }; !url.is_valid())
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Proxy configuration item 'proxyAutoconfigUrl' must be a valid URL"sv);
|
||||
return {};
|
||||
}
|
||||
|
||||
if (key == "ftpProxy"sv) {
|
||||
if (!value.is_string())
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Proxy configuration item 'ftpProxy' must be a string"sv);
|
||||
if (URL::URL url { value.as_string() }; !url.is_valid() || url.scheme() != "ftp"sv)
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Proxy configuration item 'ftpProxy' must be a valid FTP URL"sv);
|
||||
return {};
|
||||
}
|
||||
|
||||
if (key == "httpProxy"sv) {
|
||||
if (!value.is_string())
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Proxy configuration item 'httpProxy' must be a string"sv);
|
||||
if (URL::URL url { value.as_string() }; !url.is_valid() || url.scheme() != "http"sv)
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Proxy configuration item 'httpProxy' must be a valid HTTP URL"sv);
|
||||
return {};
|
||||
}
|
||||
|
||||
if (key == "noProxy"sv) {
|
||||
if (!value.is_array())
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Proxy configuration item 'noProxy' must be a list"sv);
|
||||
|
||||
TRY(value.as_array().try_for_each([&](JsonValue const& item) -> ErrorOr<void, Error> {
|
||||
if (!item.is_string())
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Proxy configuration item 'noProxy' must be a list of strings"sv);
|
||||
return {};
|
||||
}));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (key == "sslProxy"sv) {
|
||||
if (!value.is_string())
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Proxy configuration item 'sslProxy' must be a string"sv);
|
||||
if (URL::URL url { value.as_string() }; !url.is_valid() || url.scheme() != "https"sv)
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Proxy configuration item 'sslProxy' must be a valid HTTPS URL"sv);
|
||||
return {};
|
||||
}
|
||||
|
||||
if (key == "socksProxy"sv) {
|
||||
if (!value.is_string())
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Proxy configuration item 'proxyAutoconfigUrl' must be a string"sv);
|
||||
if (URL::URL url { value.as_string() }; !url.is_valid())
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Proxy configuration item 'proxyAutoconfigUrl' must be a valid URL"sv);
|
||||
return {};
|
||||
}
|
||||
|
||||
if (key == "socksVersion"sv) {
|
||||
if (!value.is_integer<u8>())
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Proxy configuration item 'socksVersion' must be an integer in the range [0, 255]"sv);
|
||||
return {};
|
||||
}
|
||||
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Invalid proxy configuration item"sv);
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-deserialize-as-a-proxy
|
||||
ErrorOr<JsonObject, Error> deserialize_as_a_proxy(JsonValue const& parameter)
|
||||
{
|
||||
// 1. If parameter is not a JSON Object return an error with error code invalid argument.
|
||||
if (!parameter.is_object())
|
||||
return Error::from_code(ErrorCode::InvalidArgument, "Capability proxy must be an object"sv);
|
||||
|
||||
// 2. Let proxy be a new, empty proxy configuration object.
|
||||
JsonObject proxy;
|
||||
|
||||
// 3. For each enumerable own property in parameter run the following substeps:
|
||||
TRY(parameter.as_object().try_for_each_member([&](ByteString const& key, JsonValue const& value) -> ErrorOr<void, Error> {
|
||||
// 1. Let key be the name of the property.
|
||||
// 2. Let value be the result of getting a property named name from capability.
|
||||
|
||||
// 3. If there is no matching key for key in the proxy configuration table return an error with error code invalid argument.
|
||||
// 4. If value is not one of the valid values for that key, return an error with error code invalid argument.
|
||||
TRY(validate_proxy_item(key, value));
|
||||
|
||||
// 5. Set a property key to value on proxy.
|
||||
proxy.set(key, value);
|
||||
|
||||
return {};
|
||||
}));
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue