mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
WebContent+WebDriver: Transfer WebDriver capability init to Session
Capabilities are configured on a per-session basis, but we were only applying these options to the first WebContent process created. We will need to pass these options to new windows created from that process. This patch re-organizes capability processing so that our session can remember them for new windows.
This commit is contained in:
parent
f5d67cefc1
commit
d66b54fec5
Notes:
github-actions[bot]
2024-11-05 19:07:17 +00:00
Author: https://github.com/trflynn89 Commit: https://github.com/LadybirdBrowser/ladybird/commit/d66b54fec5e Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2176 Reviewed-by: https://github.com/ADKaster ✅
4 changed files with 77 additions and 53 deletions
|
@ -279,7 +279,8 @@ Messages::WebDriverClient::SetTimeoutsResponse WebDriverConnection::set_timeouts
|
||||||
// 2. Make the session timeouts the new timeouts.
|
// 2. Make the session timeouts the new timeouts.
|
||||||
|
|
||||||
// 3. Return success with data null.
|
// 3. Return success with data null.
|
||||||
return JsonValue {};
|
// NOTE: We return the current timeouts configuration so the client may store them for new sessions.
|
||||||
|
return Web::WebDriver::timeouts_object(m_timeouts_configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 10.1 Navigate To, https://w3c.github.io/webdriver/#navigate-to
|
// 10.1 Navigate To, https://w3c.github.io/webdriver/#navigate-to
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include <LibCore/EventLoop.h>
|
#include <LibCore/EventLoop.h>
|
||||||
#include <LibCore/Timer.h>
|
#include <LibCore/Timer.h>
|
||||||
#include <LibWeb/WebDriver/Capabilities.h>
|
#include <LibWeb/WebDriver/Capabilities.h>
|
||||||
#include <LibWeb/WebDriver/TimeoutsConfiguration.h>
|
|
||||||
#include <WebDriver/Client.h>
|
#include <WebDriver/Client.h>
|
||||||
|
|
||||||
namespace WebDriver {
|
namespace WebDriver {
|
||||||
|
@ -63,53 +62,6 @@ void Client::close_session(unsigned session_id)
|
||||||
dbgln_if(WEBDRIVER_DEBUG, "Unable to shut down session {}: Not found", session_id);
|
dbgln_if(WEBDRIVER_DEBUG, "Unable to shut down session {}: Not found", session_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 12 of https://w3c.github.io/webdriver/#dfn-new-sessions
|
|
||||||
static void initialize_session_from_capabilities(WebContentConnection& web_content_connection, JsonObject& capabilities)
|
|
||||||
{
|
|
||||||
// 1. Let strategy be the result of getting property "pageLoadStrategy" from capabilities.
|
|
||||||
auto strategy = capabilities.get_byte_string("pageLoadStrategy"sv);
|
|
||||||
|
|
||||||
// 2. If strategy is a string, set the current 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 (strategy.has_value())
|
|
||||||
web_content_connection.async_set_page_load_strategy(Web::WebDriver::page_load_strategy_from_string(*strategy));
|
|
||||||
else
|
|
||||||
capabilities.set("pageLoadStrategy"sv, "normal"sv);
|
|
||||||
|
|
||||||
// 3. Let strictFileInteractability be the result of getting property "strictFileInteractability" from capabilities.
|
|
||||||
auto strict_file_interactiblity = capabilities.get_bool("strictFileInteractability"sv);
|
|
||||||
|
|
||||||
// 4. If strictFileInteractability is a boolean, set the current session’s strict file interactability to strictFileInteractability. Otherwise set the current session’s strict file interactability to false.
|
|
||||||
if (strict_file_interactiblity.has_value())
|
|
||||||
web_content_connection.async_set_strict_file_interactability(*strict_file_interactiblity);
|
|
||||||
else
|
|
||||||
capabilities.set("strictFileInteractability"sv, false);
|
|
||||||
|
|
||||||
// FIXME: 5. Let proxy be the result of getting property "proxy" from capabilities and run the substeps of the first matching statement:
|
|
||||||
// FIXME: proxy is a proxy configuration object
|
|
||||||
// FIXME: Take implementation-defined steps to set the user agent proxy using the extracted proxy configuration. If the defined proxy cannot be configured return error with error code session not created.
|
|
||||||
// FIXME: Otherwise
|
|
||||||
// FIXME: Set a property of capabilities with name "proxy" and a value that is a new JSON Object.
|
|
||||||
|
|
||||||
// 6. If capabilities has a property with the key "timeouts":
|
|
||||||
if (auto timeouts = capabilities.get_object("timeouts"sv); timeouts.has_value()) {
|
|
||||||
// a. Let timeouts be the result of trying to JSON deserialize as a timeouts configuration the value of the "timeouts" property.
|
|
||||||
// NOTE: This happens on the remote end.
|
|
||||||
|
|
||||||
// b. Make the session timeouts the new timeouts.
|
|
||||||
MUST(web_content_connection.set_timeouts(*timeouts));
|
|
||||||
} else {
|
|
||||||
// 7. Set a property on capabilities with name "timeouts" and value that of the JSON deserialization of the session timeouts.
|
|
||||||
capabilities.set("timeouts"sv, Web::WebDriver::timeouts_object({}));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 8. Apply changes to the user agent for any implementation-defined capabilities selected during the capabilities processing step.
|
|
||||||
auto behavior = capabilities.get_byte_string("unhandledPromptBehavior"sv);
|
|
||||||
if (behavior.has_value())
|
|
||||||
web_content_connection.async_set_unhandled_prompt_behavior(Web::WebDriver::unhandled_prompt_behavior_from_string(*behavior));
|
|
||||||
else
|
|
||||||
capabilities.set("unhandledPromptBehavior"sv, "dismiss and notify"sv);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 8.1 New Session, https://w3c.github.io/webdriver/#dfn-new-sessions
|
// 8.1 New Session, https://w3c.github.io/webdriver/#dfn-new-sessions
|
||||||
// POST /session
|
// POST /session
|
||||||
Web::WebDriver::Response Client::new_session(Web::WebDriver::Parameters, JsonValue payload)
|
Web::WebDriver::Response Client::new_session(Web::WebDriver::Parameters, JsonValue payload)
|
||||||
|
@ -155,12 +107,12 @@ Web::WebDriver::Response Client::new_session(Web::WebDriver::Parameters, JsonVal
|
||||||
// with arguments session and capabilities.
|
// with arguments session and capabilities.
|
||||||
|
|
||||||
// 10. Append session to active sessions.
|
// 10. Append session to active sessions.
|
||||||
s_sessions.set(session_id, move(session));
|
s_sessions.set(session_id, session);
|
||||||
|
|
||||||
// NOTE: We do step 12 before 11 because step 12 mutates the capabilities we set in step 11.
|
// NOTE: We do step 12 before 11 because step 12 mutates the capabilities we set in step 11.
|
||||||
|
|
||||||
// 12. Initialize the following from capabilities:
|
// 12. Initialize the following from capabilities:
|
||||||
initialize_session_from_capabilities(web_content_connection, capabilities.as_object());
|
session->initialize_from_capabilities(capabilities.as_object());
|
||||||
|
|
||||||
// 11. Let body be a JSON Object initialized with:
|
// 11. Let body be a JSON Object initialized with:
|
||||||
JsonObject body;
|
JsonObject body;
|
||||||
|
@ -232,7 +184,7 @@ Web::WebDriver::Response Client::set_timeouts(Web::WebDriver::Parameters paramet
|
||||||
{
|
{
|
||||||
dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session id>/timeouts");
|
dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session id>/timeouts");
|
||||||
auto session = TRY(find_session_with_id(parameters[0]));
|
auto session = TRY(find_session_with_id(parameters[0]));
|
||||||
return session->web_content_connection().set_timeouts(payload);
|
return session->set_timeouts(move(payload));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 10.1 Navigate To, https://w3c.github.io/webdriver/#dfn-navigate-to
|
// 10.1 Navigate To, https://w3c.github.io/webdriver/#dfn-navigate-to
|
||||||
|
|
|
@ -11,10 +11,10 @@
|
||||||
#include "Session.h"
|
#include "Session.h"
|
||||||
#include "Client.h"
|
#include "Client.h"
|
||||||
#include <AK/JsonObject.h>
|
#include <AK/JsonObject.h>
|
||||||
#include <AK/JsonValue.h>
|
|
||||||
#include <LibCore/LocalServer.h>
|
#include <LibCore/LocalServer.h>
|
||||||
#include <LibCore/StandardPaths.h>
|
#include <LibCore/StandardPaths.h>
|
||||||
#include <LibCore/System.h>
|
#include <LibCore/System.h>
|
||||||
|
#include <LibWeb/WebDriver/TimeoutsConfiguration.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
namespace WebDriver {
|
namespace WebDriver {
|
||||||
|
@ -53,6 +53,60 @@ Session::~Session()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Step 12 of https://w3c.github.io/webdriver/#dfn-new-sessions
|
||||||
|
void Session::initialize_from_capabilities(JsonObject& capabilities)
|
||||||
|
{
|
||||||
|
auto& connection = web_content_connection();
|
||||||
|
|
||||||
|
// 1. Let strategy be the result of getting property "pageLoadStrategy" from capabilities.
|
||||||
|
auto strategy = capabilities.get_byte_string("pageLoadStrategy"sv);
|
||||||
|
|
||||||
|
// 2. If strategy is a string, set the current 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 (strategy.has_value()) {
|
||||||
|
m_page_load_strategy = Web::WebDriver::page_load_strategy_from_string(*strategy);
|
||||||
|
connection.async_set_page_load_strategy(m_page_load_strategy);
|
||||||
|
} else {
|
||||||
|
capabilities.set("pageLoadStrategy"sv, "normal"sv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Let strictFileInteractability be the result of getting property "strictFileInteractability" from capabilities.
|
||||||
|
auto strict_file_interactiblity = capabilities.get_bool("strictFileInteractability"sv);
|
||||||
|
|
||||||
|
// 4. If strictFileInteractability is a boolean, set the current session’s strict file interactability to strictFileInteractability. Otherwise set the current session’s strict file interactability to false.
|
||||||
|
if (strict_file_interactiblity.has_value()) {
|
||||||
|
m_strict_file_interactiblity = *strict_file_interactiblity;
|
||||||
|
connection.async_set_strict_file_interactability(m_strict_file_interactiblity);
|
||||||
|
} else {
|
||||||
|
capabilities.set("strictFileInteractability"sv, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: 5. Let proxy be the result of getting property "proxy" from capabilities and run the substeps of the first matching statement:
|
||||||
|
// FIXME: proxy is a proxy configuration object
|
||||||
|
// FIXME: Take implementation-defined steps to set the user agent proxy using the extracted proxy configuration. If the defined proxy cannot be configured return error with error code session not created.
|
||||||
|
// FIXME: Otherwise
|
||||||
|
// FIXME: Set a property of capabilities with name "proxy" and a value that is a new JSON Object.
|
||||||
|
|
||||||
|
// 6. If capabilities has a property with the key "timeouts":
|
||||||
|
if (auto timeouts = capabilities.get_object("timeouts"sv); timeouts.has_value()) {
|
||||||
|
// a. Let timeouts be the result of trying to JSON deserialize as a timeouts configuration the value of the "timeouts" property.
|
||||||
|
// NOTE: This happens on the remote end.
|
||||||
|
|
||||||
|
// b. Make the session timeouts the new timeouts.
|
||||||
|
MUST(set_timeouts(*timeouts));
|
||||||
|
} else {
|
||||||
|
// 7. Set a property on capabilities with name "timeouts" and value that of the JSON deserialization of the session timeouts.
|
||||||
|
capabilities.set("timeouts"sv, Web::WebDriver::timeouts_object({}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8. Apply changes to the user agent for any implementation-defined capabilities selected during the capabilities processing step.
|
||||||
|
if (auto behavior = capabilities.get_byte_string("unhandledPromptBehavior"sv); behavior.has_value()) {
|
||||||
|
m_unhandled_prompt_behavior = Web::WebDriver::unhandled_prompt_behavior_from_string(*behavior);
|
||||||
|
connection.async_set_unhandled_prompt_behavior(m_unhandled_prompt_behavior);
|
||||||
|
} else {
|
||||||
|
capabilities.set("unhandledPromptBehavior"sv, "dismiss and notify"sv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ErrorOr<NonnullRefPtr<Core::LocalServer>> Session::create_server(NonnullRefPtr<ServerPromise> promise)
|
ErrorOr<NonnullRefPtr<Core::LocalServer>> Session::create_server(NonnullRefPtr<ServerPromise> promise)
|
||||||
{
|
{
|
||||||
static_assert(IsSame<IPC::Transport, IPC::TransportSocket>, "Need to handle other IPC transports here");
|
static_assert(IsSame<IPC::Transport, IPC::TransportSocket>, "Need to handle other IPC transports here");
|
||||||
|
@ -123,6 +177,12 @@ ErrorOr<void> Session::start(LaunchBrowserCallbacks const& callbacks)
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Web::WebDriver::Response Session::set_timeouts(JsonValue payload)
|
||||||
|
{
|
||||||
|
m_timeouts_configuration = TRY(web_content_connection().set_timeouts(move(payload)));
|
||||||
|
return JsonValue {};
|
||||||
|
}
|
||||||
|
|
||||||
// 11.2 Close Window, https://w3c.github.io/webdriver/#dfn-close-window
|
// 11.2 Close Window, https://w3c.github.io/webdriver/#dfn-close-window
|
||||||
Web::WebDriver::Response Session::close_window()
|
Web::WebDriver::Response Session::close_window()
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,12 +9,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/Error.h>
|
#include <AK/Error.h>
|
||||||
|
#include <AK/JsonValue.h>
|
||||||
#include <AK/RefCounted.h>
|
#include <AK/RefCounted.h>
|
||||||
#include <AK/RefPtr.h>
|
#include <AK/RefPtr.h>
|
||||||
#include <AK/ScopeGuard.h>
|
#include <AK/ScopeGuard.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <LibCore/EventLoop.h>
|
#include <LibCore/EventLoop.h>
|
||||||
#include <LibCore/Promise.h>
|
#include <LibCore/Promise.h>
|
||||||
|
#include <LibWeb/WebDriver/Capabilities.h>
|
||||||
#include <LibWeb/WebDriver/Error.h>
|
#include <LibWeb/WebDriver/Error.h>
|
||||||
#include <LibWeb/WebDriver/Response.h>
|
#include <LibWeb/WebDriver/Response.h>
|
||||||
#include <WebDriver/WebContentConnection.h>
|
#include <WebDriver/WebContentConnection.h>
|
||||||
|
@ -29,6 +31,8 @@ public:
|
||||||
Session(unsigned session_id, NonnullRefPtr<Client> client, Web::WebDriver::LadybirdOptions options);
|
Session(unsigned session_id, NonnullRefPtr<Client> client, Web::WebDriver::LadybirdOptions options);
|
||||||
~Session();
|
~Session();
|
||||||
|
|
||||||
|
void initialize_from_capabilities(JsonObject&);
|
||||||
|
|
||||||
unsigned session_id() const { return m_id; }
|
unsigned session_id() const { return m_id; }
|
||||||
|
|
||||||
struct Window {
|
struct Window {
|
||||||
|
@ -52,6 +56,8 @@ public:
|
||||||
bool has_window_handle(StringView handle) const { return m_windows.contains(handle); }
|
bool has_window_handle(StringView handle) const { return m_windows.contains(handle); }
|
||||||
|
|
||||||
ErrorOr<void> start(LaunchBrowserCallbacks const&);
|
ErrorOr<void> start(LaunchBrowserCallbacks const&);
|
||||||
|
|
||||||
|
Web::WebDriver::Response set_timeouts(JsonValue);
|
||||||
Web::WebDriver::Response close_window();
|
Web::WebDriver::Response close_window();
|
||||||
Web::WebDriver::Response switch_to_window(StringView);
|
Web::WebDriver::Response switch_to_window(StringView);
|
||||||
Web::WebDriver::Response get_window_handles() const;
|
Web::WebDriver::Response get_window_handles() const;
|
||||||
|
@ -92,6 +98,11 @@ private:
|
||||||
Optional<pid_t> m_browser_pid;
|
Optional<pid_t> m_browser_pid;
|
||||||
|
|
||||||
RefPtr<Core::LocalServer> m_web_content_server;
|
RefPtr<Core::LocalServer> m_web_content_server;
|
||||||
|
|
||||||
|
Web::WebDriver::PageLoadStrategy m_page_load_strategy { Web::WebDriver::PageLoadStrategy::Normal };
|
||||||
|
Web::WebDriver::UnhandledPromptBehavior m_unhandled_prompt_behavior { Web::WebDriver::UnhandledPromptBehavior::DismissAndNotify };
|
||||||
|
Optional<JsonValue> m_timeouts_configuration;
|
||||||
|
bool m_strict_file_interactiblity { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue