From b5acc5f2df52e5092da00dfd48cc63e4763b81b9 Mon Sep 17 00:00:00 2001 From: Andrew Kaster Date: Tue, 5 Mar 2024 09:42:10 -0700 Subject: [PATCH] LibWeb: Serialize and pass to the WebWorker the current ESO This allows the initial fetch() in the run a worker AO to use the proper values from the outside settings. --- .../Libraries/LibWeb/HTML/Scripting/BUILD.gn | 1 + Userland/Libraries/LibWeb/CMakeLists.txt | 1 + .../Scripting/EnvironmentSettingsSnapshot.cpp | 30 ++++++++++++++ .../Scripting/EnvironmentSettingsSnapshot.h | 39 +++++++++++++++++++ Userland/Libraries/LibWeb/HTML/Worker.cpp | 4 +- .../Libraries/LibWeb/HTML/WorkerAgent.cpp | 6 ++- Userland/Libraries/LibWeb/HTML/WorkerAgent.h | 3 +- .../LibWeb/Worker/WebWorkerServer.ipc | 3 +- .../WebWorker/ConnectionFromClient.cpp | 4 +- .../Services/WebWorker/ConnectionFromClient.h | 2 +- .../WebWorker/DedicatedWorkerHost.cpp | 9 +++-- .../Services/WebWorker/DedicatedWorkerHost.h | 3 +- 12 files changed, 92 insertions(+), 13 deletions(-) create mode 100644 Userland/Libraries/LibWeb/HTML/Scripting/EnvironmentSettingsSnapshot.cpp create mode 100644 Userland/Libraries/LibWeb/HTML/Scripting/EnvironmentSettingsSnapshot.h diff --git a/Meta/gn/secondary/Userland/Libraries/LibWeb/HTML/Scripting/BUILD.gn b/Meta/gn/secondary/Userland/Libraries/LibWeb/HTML/Scripting/BUILD.gn index 88331a8b68..ddedee6bbc 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibWeb/HTML/Scripting/BUILD.gn +++ b/Meta/gn/secondary/Userland/Libraries/LibWeb/HTML/Scripting/BUILD.gn @@ -3,6 +3,7 @@ source_set("Scripting") { deps = [ "//Userland/Libraries/LibWeb:all_generated" ] sources = [ "ClassicScript.cpp", + "EnvironmentSettingsSnapshot.cpp", "Environments.cpp", "ExceptionReporter.cpp", "Fetching.cpp", diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 8f88920c0a..727827ea2d 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -383,6 +383,7 @@ set(SOURCES HTML/PromiseRejectionEvent.cpp HTML/Scripting/ClassicScript.cpp HTML/Scripting/Environments.cpp + HTML/Scripting/EnvironmentSettingsSnapshot.cpp HTML/Scripting/ExceptionReporter.cpp HTML/Scripting/Fetching.cpp HTML/Scripting/ModuleMap.cpp diff --git a/Userland/Libraries/LibWeb/HTML/Scripting/EnvironmentSettingsSnapshot.cpp b/Userland/Libraries/LibWeb/HTML/Scripting/EnvironmentSettingsSnapshot.cpp new file mode 100644 index 0000000000..9f6661014c --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/Scripting/EnvironmentSettingsSnapshot.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +namespace Web::HTML { + +JS_DEFINE_ALLOCATOR(EnvironmentSettingsSnapshot); + +EnvironmentSettingsSnapshot::EnvironmentSettingsSnapshot(NonnullOwnPtr execution_context, SerializedEnvironmentSettingsObject const& serialized_settings) + : EnvironmentSettingsObject(move(execution_context)) + , m_api_url_character_encoding(serialized_settings.api_url_character_encoding) + , m_url(serialized_settings.api_base_url) + , m_origin(serialized_settings.origin) + , m_policy_container(serialized_settings.policy_container) +{ + // Why can't we put these in the init list? grandparent class members are strange it seems + this->id = serialized_settings.id; + this->creation_url = serialized_settings.creation_url; + this->top_level_creation_url = serialized_settings.top_level_creation_url; + this->top_level_creation_url = serialized_settings.top_level_creation_url; +} + +// Out of line to ensure this class has a key function +EnvironmentSettingsSnapshot::~EnvironmentSettingsSnapshot() = default; + +} diff --git a/Userland/Libraries/LibWeb/HTML/Scripting/EnvironmentSettingsSnapshot.h b/Userland/Libraries/LibWeb/HTML/Scripting/EnvironmentSettingsSnapshot.h new file mode 100644 index 0000000000..10a13d15dc --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/Scripting/EnvironmentSettingsSnapshot.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace Web::HTML { + +class EnvironmentSettingsSnapshot final + : public EnvironmentSettingsObject { + JS_CELL(EnvironmentSettingsSnapshot, EnvironmentSettingsObject); + JS_DECLARE_ALLOCATOR(EnvironmentSettingsSnapshot); + +public: + EnvironmentSettingsSnapshot(NonnullOwnPtr, SerializedEnvironmentSettingsObject const&); + + virtual ~EnvironmentSettingsSnapshot() override; + + JS::GCPtr responsible_document() override { return nullptr; } + String api_url_character_encoding() override { return m_api_url_character_encoding; } + URL api_base_url() override { return m_url; } + Origin origin() override { return m_origin; } + PolicyContainer policy_container() override { return m_policy_container; } + CanUseCrossOriginIsolatedAPIs cross_origin_isolated_capability() override { return CanUseCrossOriginIsolatedAPIs::No; } + +private: + String m_api_url_character_encoding; + URL m_url; + HTML::Origin m_origin; + HTML::PolicyContainer m_policy_container; +}; + +} diff --git a/Userland/Libraries/LibWeb/HTML/Worker.cpp b/Userland/Libraries/LibWeb/HTML/Worker.cpp index d963d49a47..bdda083d55 100644 --- a/Userland/Libraries/LibWeb/HTML/Worker.cpp +++ b/Userland/Libraries/LibWeb/HTML/Worker.cpp @@ -57,7 +57,7 @@ WebIDL::ExceptionOr> Worker::create(String const& scrip // Technically not a fixme if our policy is not to throw errors :^) // 2. Let outside settings be the current settings object. - auto& outside_settings = document.relevant_settings_object(); + auto& outside_settings = current_settings_object(); // 3. Parse the scriptURL argument relative to outside settings. auto url = document.parse_url(script_url.to_byte_string()); @@ -110,7 +110,7 @@ void Worker::run_a_worker(URL& url, EnvironmentSettingsObject& outside_settings, // and is shared. Run the rest of these steps in that agent. // Note: This spawns a new process to act as the 'agent' for the worker. - m_agent = heap().allocate(outside_settings.realm(), url, options, port); + m_agent = heap().allocate(outside_settings.realm(), url, options, port, outside_settings); } // https://html.spec.whatwg.org/multipage/workers.html#dom-worker-terminate diff --git a/Userland/Libraries/LibWeb/HTML/WorkerAgent.cpp b/Userland/Libraries/LibWeb/HTML/WorkerAgent.cpp index 4a46d50f64..835d020d92 100644 --- a/Userland/Libraries/LibWeb/HTML/WorkerAgent.cpp +++ b/Userland/Libraries/LibWeb/HTML/WorkerAgent.cpp @@ -13,10 +13,11 @@ namespace Web::HTML { JS_DEFINE_ALLOCATOR(WorkerAgent); -WorkerAgent::WorkerAgent(URL url, WorkerOptions const& options, JS::GCPtr outside_port) +WorkerAgent::WorkerAgent(URL url, WorkerOptions const& options, JS::GCPtr outside_port, JS::NonnullGCPtr outside_settings) : m_worker_options(options) , m_url(move(url)) , m_outside_port(outside_port) + , m_outside_settings(outside_settings) { } @@ -41,7 +42,7 @@ void WorkerAgent::initialize(JS::Realm& realm) m_worker_ipc = make_ref_counted(move(worker_socket)); m_worker_ipc->set_fd_passing_socket(move(fd_passing_socket)); - m_worker_ipc->async_start_dedicated_worker(m_url, m_worker_options.type, m_worker_options.credentials, m_worker_options.name, move(data_holder)); + m_worker_ipc->async_start_dedicated_worker(m_url, m_worker_options.type, m_worker_options.credentials, m_worker_options.name, move(data_holder), m_outside_settings->serialize()); } void WorkerAgent::visit_edges(Cell::Visitor& visitor) @@ -49,6 +50,7 @@ void WorkerAgent::visit_edges(Cell::Visitor& visitor) Base::visit_edges(visitor); visitor.visit(m_message_port); visitor.visit(m_outside_port); + visitor.visit(m_outside_settings); } } diff --git a/Userland/Libraries/LibWeb/HTML/WorkerAgent.h b/Userland/Libraries/LibWeb/HTML/WorkerAgent.h index d82edc36fc..65b93242dc 100644 --- a/Userland/Libraries/LibWeb/HTML/WorkerAgent.h +++ b/Userland/Libraries/LibWeb/HTML/WorkerAgent.h @@ -22,7 +22,7 @@ class WorkerAgent : public JS::Cell { JS_CELL(Agent, JS::Cell); JS_DECLARE_ALLOCATOR(WorkerAgent); - WorkerAgent(URL url, WorkerOptions const& options, JS::GCPtr outside_port); + WorkerAgent(URL url, WorkerOptions const& options, JS::GCPtr outside_port, JS::NonnullGCPtr outside_settings); private: virtual void initialize(JS::Realm&) override; @@ -33,6 +33,7 @@ private: JS::GCPtr m_message_port; JS::GCPtr m_outside_port; + JS::NonnullGCPtr m_outside_settings; RefPtr m_worker_ipc; }; diff --git a/Userland/Libraries/LibWeb/Worker/WebWorkerServer.ipc b/Userland/Libraries/LibWeb/Worker/WebWorkerServer.ipc index 42610e2ea8..eefcd92d09 100644 --- a/Userland/Libraries/LibWeb/Worker/WebWorkerServer.ipc +++ b/Userland/Libraries/LibWeb/Worker/WebWorkerServer.ipc @@ -1,10 +1,11 @@ #include #include #include +#include endpoint WebWorkerServer { - start_dedicated_worker(URL url, String type, String credentials, String name, Web::HTML::TransferDataHolder message_port) =| + start_dedicated_worker(URL url, String type, String credentials, String name, Web::HTML::TransferDataHolder message_port, Web::HTML::SerializedEnvironmentSettingsObject outside_settings) =| handle_file_return(i32 error, Optional file, i32 request_id) =| } diff --git a/Userland/Services/WebWorker/ConnectionFromClient.cpp b/Userland/Services/WebWorker/ConnectionFromClient.cpp index 7820ae4e48..df923a8100 100644 --- a/Userland/Services/WebWorker/ConnectionFromClient.cpp +++ b/Userland/Services/WebWorker/ConnectionFromClient.cpp @@ -52,12 +52,12 @@ Web::Page const& ConnectionFromClient::page() const return m_page_host->page(); } -void ConnectionFromClient::start_dedicated_worker(URL const& url, String const& type, String const&, String const&, Web::HTML::TransferDataHolder const& implicit_port) +void ConnectionFromClient::start_dedicated_worker(URL const& url, String const& type, String const&, String const&, Web::HTML::TransferDataHolder const& implicit_port, Web::HTML::SerializedEnvironmentSettingsObject const& outside_settings) { m_worker_host = make_ref_counted(url, type); // FIXME: Yikes, const_cast to move? Feels like a LibIPC bug. // We should be able to move non-copyable types from a Message type. - m_worker_host->run(page(), move(const_cast(implicit_port))); + m_worker_host->run(page(), move(const_cast(implicit_port)), outside_settings); } void ConnectionFromClient::handle_file_return(i32 error, Optional const& file, i32 request_id) diff --git a/Userland/Services/WebWorker/ConnectionFromClient.h b/Userland/Services/WebWorker/ConnectionFromClient.h index b253855fed..cf240a2d24 100644 --- a/Userland/Services/WebWorker/ConnectionFromClient.h +++ b/Userland/Services/WebWorker/ConnectionFromClient.h @@ -39,7 +39,7 @@ private: Web::Page& page(); Web::Page const& page() const; - virtual void start_dedicated_worker(URL const& url, String const&, String const&, String const&, Web::HTML::TransferDataHolder const&) override; + virtual void start_dedicated_worker(URL const& url, String const&, String const&, String const&, Web::HTML::TransferDataHolder const&, Web::HTML::SerializedEnvironmentSettingsObject const&) override; virtual void handle_file_return(i32 error, Optional const& file, i32 request_id) override; JS::Handle m_page_host; diff --git a/Userland/Services/WebWorker/DedicatedWorkerHost.cpp b/Userland/Services/WebWorker/DedicatedWorkerHost.cpp index 7778ba507b..8fb28d133b 100644 --- a/Userland/Services/WebWorker/DedicatedWorkerHost.cpp +++ b/Userland/Services/WebWorker/DedicatedWorkerHost.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -28,7 +29,7 @@ DedicatedWorkerHost::~DedicatedWorkerHost() = default; // https://html.spec.whatwg.org/multipage/workers.html#run-a-worker // FIXME: Extract out into a helper for both shared and dedicated workers -void DedicatedWorkerHost::run(JS::NonnullGCPtr page, Web::HTML::TransferDataHolder message_port_data) +void DedicatedWorkerHost::run(JS::NonnullGCPtr page, Web::HTML::TransferDataHolder message_port_data, Web::HTML::SerializedEnvironmentSettingsObject const& outside_settings_snapshot) { bool const is_shared = false; @@ -64,6 +65,9 @@ void DedicatedWorkerHost::run(JS::NonnullGCPtr page, Web::HTML::Trans // 11. Append owner to worker global scope's owner set. // FIXME: support for 'owner' set on WorkerGlobalScope + // IMPLEMENTATION DEFINED: We need an object to represent the fetch response's client + auto outside_settings = inner_settings->heap().allocate(inner_settings->realm(), inner_settings->realm_execution_context().copy(), outside_settings_snapshot); + // 12. If is shared is true, then: if (is_shared) { // FIXME: Shared worker support @@ -210,8 +214,7 @@ void DedicatedWorkerHost::run(JS::NonnullGCPtr page, Web::HTML::Trans dbgln("Unsupported script type {} for LibWeb/Worker", m_type); TODO(); } - // FIXME: We don't have outside settings anymore, they live in the owner. https://github.com/whatwg/html/issues/9920 - if (auto err = Web::HTML::fetch_classic_worker_script(m_url, inner_settings, destination, inner_settings, perform_fetch, on_complete); err.is_error()) { + if (auto err = Web::HTML::fetch_classic_worker_script(m_url, outside_settings, destination, inner_settings, perform_fetch, on_complete); err.is_error()) { dbgln("Failed to run worker script"); // FIXME: Abort the worker properly TODO(); diff --git a/Userland/Services/WebWorker/DedicatedWorkerHost.h b/Userland/Services/WebWorker/DedicatedWorkerHost.h index 4c2c566ff5..706d80a8a8 100644 --- a/Userland/Services/WebWorker/DedicatedWorkerHost.h +++ b/Userland/Services/WebWorker/DedicatedWorkerHost.h @@ -10,6 +10,7 @@ #include #include #include +#include #include namespace WebWorker { @@ -19,7 +20,7 @@ public: explicit DedicatedWorkerHost(URL url, String type); ~DedicatedWorkerHost(); - void run(JS::NonnullGCPtr, Web::HTML::TransferDataHolder message_port_data); + void run(JS::NonnullGCPtr, Web::HTML::TransferDataHolder message_port_data, Web::HTML::SerializedEnvironmentSettingsObject const&); private: RefPtr m_console;