diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index b3dac565636..19a59d08726 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -373,6 +373,7 @@ set(SOURCES HTML/NavigationDestination.cpp HTML/NavigationCurrentEntryChangeEvent.cpp HTML/NavigationHistoryEntry.cpp + HTML/NavigationParams.cpp HTML/NavigationTransition.cpp HTML/Navigator.cpp HTML/NavigatorBeacon.cpp diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 94500538865..1fafa722a4f 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include diff --git a/Userland/Libraries/LibWeb/DOM/DocumentLoading.h b/Userland/Libraries/LibWeb/DOM/DocumentLoading.h index 1fa2db3661a..eccfbc19630 100644 --- a/Userland/Libraries/LibWeb/DOM/DocumentLoading.h +++ b/Userland/Libraries/LibWeb/DOM/DocumentLoading.h @@ -8,6 +8,7 @@ #pragma once #include +#include namespace Web { @@ -54,21 +55,20 @@ JS::NonnullGCPtr create_document_for_inline_content(JS::GCPtrurl_list().append(URL::URL("about:error")); // AD-HOC: https://github.com/whatwg/html/issues/9122 - HTML::NavigationParams navigation_params { - .id = navigation_id, - .navigable = navigable, - .request = {}, - .response = *response, - .fetch_controller = nullptr, - .commit_early_hints = nullptr, - .coop_enforcement_result = move(coop_enforcement_result), - .reserved_environment = {}, - .origin = move(origin), - .policy_container = HTML::PolicyContainer {}, - .final_sandboxing_flag_set = HTML::SandboxingFlagSet {}, - .cross_origin_opener_policy = move(coop), - .about_base_url = {}, - }; + auto navigation_params = vm.heap().allocate_without_realm(); + navigation_params->id = navigation_id; + navigation_params->navigable = navigable; + navigation_params->request = nullptr; + navigation_params->response = response; + navigation_params->fetch_controller = nullptr; + navigation_params->commit_early_hints = nullptr; + navigation_params->coop_enforcement_result = move(coop_enforcement_result); + navigation_params->reserved_environment = {}; + navigation_params->origin = move(origin); + navigation_params->policy_container = HTML::PolicyContainer {}; + navigation_params->final_sandboxing_flag_set = HTML::SandboxingFlagSet {}; + navigation_params->cross_origin_opener_policy = move(coop); + navigation_params->about_base_url = {}; // 5. Let document be the result of creating and initializing a Document object given "html", "text/html", and navigationParams. auto document = DOM::Document::create_and_initialize(DOM::Document::Type::HTML, "text/html"_string, navigation_params).release_value_but_fixme_should_propagate_errors(); diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.cpp b/Userland/Libraries/LibWeb/HTML/Navigable.cpp index 9981a9346f8..e9eb7a05ad1 100644 --- a/Userland/Libraries/LibWeb/HTML/Navigable.cpp +++ b/Userland/Libraries/LibWeb/HTML/Navigable.cpp @@ -586,7 +586,7 @@ static JS::GCPtr attempt_to_create_a_non_fetch_scheme_document(No } // https://html.spec.whatwg.org/multipage/browsing-the-web.html#create-navigation-params-from-a-srcdoc-resource -static WebIDL::ExceptionOr create_navigation_params_from_a_srcdoc_resource(JS::GCPtr entry, JS::GCPtr navigable, TargetSnapshotParams const& target_snapshot_params, Optional navigation_id) +static WebIDL::ExceptionOr> create_navigation_params_from_a_srcdoc_resource(JS::GCPtr entry, JS::GCPtr navigable, TargetSnapshotParams const& target_snapshot_params, Optional navigation_id) { auto& vm = navigable->vm(); auto& realm = navigable->active_window()->realm(); @@ -649,25 +649,22 @@ static WebIDL::ExceptionOr create_navigation_params_from_a_src // cross-origin opener policy: coop // FIXME: navigation timing type: navTimingType // about base URL: entry's document state's about base URL - return NavigationParams { - .id = move(navigation_id), - .navigable = navigable, - .request = nullptr, - .response = *response, - .fetch_controller = nullptr, - .commit_early_hints = nullptr, - .coop_enforcement_result = move(coop_enforcement_result), - .reserved_environment = {}, - .origin = move(response_origin), - .policy_container = policy_container, - .final_sandboxing_flag_set = target_snapshot_params.sandboxing_flags, - .cross_origin_opener_policy = move(coop), - .about_base_url = entry->document_state()->about_base_url(), - }; + auto navigation_params = vm.heap().allocate_without_realm(); + navigation_params->id = move(navigation_id); + navigation_params->navigable = navigable; + navigation_params->response = response; + navigation_params->coop_enforcement_result = move(coop_enforcement_result); + navigation_params->origin = move(response_origin); + navigation_params->policy_container = policy_container; + navigation_params->final_sandboxing_flag_set = target_snapshot_params.sandboxing_flags; + navigation_params->cross_origin_opener_policy = move(coop); + navigation_params->about_base_url = entry->document_state()->about_base_url(); + + return navigation_params; } // https://html.spec.whatwg.org/multipage/browsing-the-web.html#create-navigation-params-by-fetching -static WebIDL::ExceptionOr> create_navigation_params_by_fetching(JS::GCPtr entry, JS::GCPtr navigable, SourceSnapshotParams const& source_snapshot_params, TargetSnapshotParams const& target_snapshot_params, CSPNavigationType csp_navigation_type, Optional navigation_id) +static WebIDL::ExceptionOr, JS::NonnullGCPtr>> create_navigation_params_by_fetching(JS::GCPtr entry, JS::GCPtr navigable, SourceSnapshotParams const& source_snapshot_params, TargetSnapshotParams const& target_snapshot_params, CSPNavigationType csp_navigation_type, Optional navigation_id) { auto& vm = navigable->vm(); auto& realm = navigable->active_window()->realm(); @@ -953,14 +950,14 @@ static WebIDL::ExceptionOr(); + navigation_params->id = navigation_id; + navigation_params->navigable = navigable; + navigation_params->url = location_url.release_value().value(); + navigation_params->target_snapshot_sandboxing_flags = target_snapshot_params.sandboxing_flags; + navigation_params->source_snapshot_has_transient_activation = source_snapshot_params.has_transient_activation; + navigation_params->initiator_origin = move(*response_origin); + return navigation_params; } // 21. If any of the following are true: @@ -1002,22 +999,20 @@ static WebIDL::ExceptionOrresponse(), - .fetch_controller = fetch_controller, - .commit_early_hints = move(commit_early_hints), - .coop_enforcement_result = coop_enforcement_result, - .reserved_environment = request->reserved_client(), - .origin = *response_origin, - .policy_container = result_policy_container, - .final_sandboxing_flag_set = final_sandbox_flags, - .cross_origin_opener_policy = response_coop, - .about_base_url = entry->document_state()->about_base_url(), - }; - + auto navigation_params = vm.heap().allocate_without_realm(); + navigation_params->id = navigation_id; + navigation_params->navigable = navigable; + navigation_params->request = request; + navigation_params->response = *response_holder->response(); + navigation_params->fetch_controller = fetch_controller; + navigation_params->commit_early_hints = move(commit_early_hints); + navigation_params->coop_enforcement_result = coop_enforcement_result; + navigation_params->reserved_environment = request->reserved_client(); + navigation_params->origin = *response_origin; + navigation_params->policy_container = result_policy_container; + navigation_params->final_sandboxing_flag_set = final_sandbox_flags; + navigation_params->cross_origin_opener_policy = response_coop; + navigation_params->about_base_url = entry->document_state()->about_base_url(); return navigation_params; } @@ -1027,7 +1022,7 @@ WebIDL::ExceptionOr Navigable::populate_session_history_entry_document( SourceSnapshotParams const& source_snapshot_params, TargetSnapshotParams const& target_snapshot_params, Optional navigation_id, - Variant navigation_params, + Variant, JS::NonnullGCPtr> navigation_params, CSPNavigationType csp_navigation_type, bool allow_POST, Function completion_steps) @@ -1037,7 +1032,7 @@ WebIDL::ExceptionOr Navigable::populate_session_history_entry_document( // 2. Assert: if navigationParams is non-null, then navigationParams's response is non-null. // NavigationParams' response field is NonnullGCPtr if (!navigation_params.has()) - VERIFY(navigation_params.has()); + VERIFY(navigation_params.has>()); // 3. Let currentBrowsingContext be navigable's active browsing context. [[maybe_unused]] auto current_browsing_context = active_browsing_context(); @@ -1068,14 +1063,14 @@ WebIDL::ExceptionOr Navigable::populate_session_history_entry_document( // - source snapshot has transient activation: sourceSnapshotParams's has transient activation // - initiator origin: entry's document state's initiator origin // FIXME: - navigation timing type: navTimingType - navigation_params = NonFetchSchemeNavigationParams { - .id = navigation_id, - .navigable = this, - .url = entry->url(), - .target_snapshot_sandboxing_flags = target_snapshot_params.sandboxing_flags, - .source_snapshot_has_transient_activation = source_snapshot_params.has_transient_activation, - .initiator_origin = *entry->document_state()->initiator_origin(), - }; + auto non_fetching_scheme_navigation_params = vm().heap().allocate_without_realm(); + non_fetching_scheme_navigation_params->id = navigation_id; + non_fetching_scheme_navigation_params->navigable = this; + non_fetching_scheme_navigation_params->url = entry->url(); + non_fetching_scheme_navigation_params->target_snapshot_sandboxing_flags = target_snapshot_params.sandboxing_flags; + non_fetching_scheme_navigation_params->source_snapshot_has_transient_activation = source_snapshot_params.has_transient_activation; + non_fetching_scheme_navigation_params->initiator_origin = *entry->document_state()->initiator_origin(); + navigation_params = non_fetching_scheme_navigation_params; } } @@ -1100,10 +1095,10 @@ WebIDL::ExceptionOr Navigable::populate_session_history_entry_document( // 3. If navigationParams is a non-fetch scheme navigation params, then set entry's document state's document to the result of // running attempt to create a non-fetch scheme document navigationParams - if (navigation_params.has()) { + if (navigation_params.has>()) { // FIXME: https://github.com/whatwg/html/issues/9767 // We probably are expected to skip to steps 13 and 14 and return after doing this - entry->document_state()->set_document(attempt_to_create_a_non_fetch_scheme_document(navigation_params.get())); + entry->document_state()->set_document(attempt_to_create_a_non_fetch_scheme_document(navigation_params.get>())); if (entry->document()) { entry->document_state()->set_ever_populated(true); } @@ -1148,7 +1143,7 @@ WebIDL::ExceptionOr Navigable::populate_session_history_entry_document( } } // FIXME: 9. Otherwise, if navigationParams's response's status is 204 or 205, then: - else if (navigation_params.get().response->status() == 204 || navigation_params.get().response->status() == 205) { + else if (navigation_params.get>()->response->status() == 204 || navigation_params.get>()->response->status() == 205) { // 1. Run completionSteps. completion_steps(); @@ -1161,7 +1156,7 @@ WebIDL::ExceptionOr Navigable::populate_session_history_entry_document( else { // 1. Let document be the result of loading a document given navigationParams, sourceSnapshotParams, // and entry's document state's initiator origin. - auto document = load_document(navigation_params.get()); + auto document = load_document(navigation_params.get>()); // 2. If document is null, then run completionSteps and return. if (!document) { @@ -1415,7 +1410,7 @@ WebIDL::ExceptionOr Navigable::navigate(NavigateParams params) history_entry->set_document_state(document_state); // 7. Let navigationParams be null. - Variant navigation_params = Empty {}; + Variant, JS::NonnullGCPtr> navigation_params = Empty {}; // FIXME: 8. If response is non-null: if (response) { @@ -1425,7 +1420,7 @@ WebIDL::ExceptionOr Navigable::navigate(NavigateParams params) // for historyEntry, given navigable, "navigate", sourceSnapshotParams, // targetSnapshotParams, navigationId, navigationParams, cspNavigationType, with allowPOST // set to true and completionSteps set to the following step: - populate_session_history_entry_document(history_entry, source_snapshot_params, target_snapshot_params, navigation_id, move(navigation_params), csp_navigation_type, true, [this, history_entry, history_handling, navigation_id] { + populate_session_history_entry_document(history_entry, source_snapshot_params, target_snapshot_params, navigation_id, navigation_params, csp_navigation_type, true, [this, history_entry, history_handling, navigation_id] { // 1. Append session history traversal steps to navigable's traversable to finalize a cross-document navigation given navigable, historyHandling, and historyEntry. traversable_navigable()->append_session_history_traversal_steps([this, history_entry, history_handling, navigation_id] { if (this->has_been_destroyed()) { @@ -1615,21 +1610,20 @@ WebIDL::ExceptionOr> Navigable::evaluate_javascript_url // cross-origin opener policy: coop // FIXME: navigation timing type: "navigate" // about base URL: targetNavigable's active document's about base URL - NavigationParams navigation_params { - .id = navigation_id, - .navigable = this, - .request = {}, - .response = response, - .fetch_controller = nullptr, - .commit_early_hints = nullptr, - .coop_enforcement_result = move(coop_enforcement_result), - .reserved_environment = {}, - .origin = new_document_origin, - .policy_container = policy_container, - .final_sandboxing_flag_set = final_sandbox_flags, - .cross_origin_opener_policy = coop, - .about_base_url = active_document()->about_base_url(), - }; + auto navigation_params = vm.heap().allocate_without_realm(); + navigation_params->id = navigation_id; + navigation_params->navigable = this; + navigation_params->request = {}; + navigation_params->response = response; + navigation_params->fetch_controller = nullptr; + navigation_params->commit_early_hints = nullptr; + navigation_params->coop_enforcement_result = move(coop_enforcement_result); + navigation_params->reserved_environment = {}; + navigation_params->origin = new_document_origin; + navigation_params->policy_container = policy_container; + navigation_params->final_sandboxing_flag_set = final_sandbox_flags; + navigation_params->cross_origin_opener_policy = coop; + navigation_params->about_base_url = active_document()->about_base_url(); // 17. Return the result of loading an HTML document given navigationParams. return load_document(navigation_params); diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.h b/Userland/Libraries/LibWeb/HTML/Navigable.h index 6894eadded7..6ba2c7a5999 100644 --- a/Userland/Libraries/LibWeb/HTML/Navigable.h +++ b/Userland/Libraries/LibWeb/HTML/Navigable.h @@ -120,7 +120,7 @@ public: SourceSnapshotParams const& source_snapshot_params, TargetSnapshotParams const& target_snapshot_params, Optional navigation_id = {}, - Variant navigation_params = Empty {}, + Variant, JS::NonnullGCPtr> navigation_params = Empty {}, CSPNavigationType csp_navigation_type = CSPNavigationType::Other, bool allow_POST = false, Function completion_steps = [] {}); diff --git a/Userland/Libraries/LibWeb/HTML/NavigationParams.cpp b/Userland/Libraries/LibWeb/HTML/NavigationParams.cpp new file mode 100644 index 00000000000..e3ebbe260c8 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/NavigationParams.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024, Aliaksandr Kalenik + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +namespace Web::HTML { + +JS_DEFINE_ALLOCATOR(NavigationParams); +JS_DEFINE_ALLOCATOR(NonFetchSchemeNavigationParams); + +void NavigationParams::visit_edges(Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(navigable); + visitor.visit(request); + visitor.visit(response); + visitor.visit(fetch_controller); +} + +void NonFetchSchemeNavigationParams::visit_edges(Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(navigable); +} + +} diff --git a/Userland/Libraries/LibWeb/HTML/NavigationParams.h b/Userland/Libraries/LibWeb/HTML/NavigationParams.h index 0e27c9fc64e..ae624378c06 100644 --- a/Userland/Libraries/LibWeb/HTML/NavigationParams.h +++ b/Userland/Libraries/LibWeb/HTML/NavigationParams.h @@ -6,11 +6,14 @@ #pragma once +#include +#include +#include #include #include +#include #include #include -#include #include #include #include @@ -18,12 +21,15 @@ namespace Web::HTML { // https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigation-params -struct NavigationParams { +struct NavigationParams : JS::Cell { + JS_CELL(NavigationParams, JS::Cell); + JS_DECLARE_ALLOCATOR(NavigationParams); + // null or a navigation ID Optional id; // the navigable to be navigated - JS::Handle navigable; + JS::GCPtr navigable; // null or a request that started the navigation JS::GCPtr request; @@ -59,15 +65,20 @@ struct NavigationParams { // a URL or null used to populate the new Document's about base URL Optional about_base_url; + + void visit_edges(Visitor& visitor) override; }; // https://html.spec.whatwg.org/multipage/browsing-the-web.html#non-fetch-scheme-navigation-params -struct NonFetchSchemeNavigationParams { +struct NonFetchSchemeNavigationParams : JS::Cell { + JS_CELL(NonFetchSchemeNavigationParams, JS::Cell); + JS_DECLARE_ALLOCATOR(NonFetchSchemeNavigationParams); + // null or a navigation ID Optional id; // the navigable to be navigated - JS::Handle navigable; + JS::GCPtr navigable; // a URL URL::URL url; @@ -82,6 +93,8 @@ struct NonFetchSchemeNavigationParams { Origin initiator_origin; // FIXME: a NavigationTimingType used for creating the navigation timing entry for the new Document + + void visit_edges(Visitor& visitor) override; }; } diff --git a/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.cpp b/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.cpp index 8c84c4730c5..fdb1f28be89 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.cpp @@ -35,21 +35,14 @@ ErrorOr> SVGDecodedImageData::create(JS::R JS::NonnullGCPtr navigable = page->top_level_traversable(); auto response = Fetch::Infrastructure::Response::create(navigable->vm()); response->url_list().append(url); - HTML::NavigationParams navigation_params { - .id = {}, - .navigable = navigable, - .request = nullptr, - .response = response, - .fetch_controller = nullptr, - .commit_early_hints = nullptr, - .coop_enforcement_result = HTML::CrossOriginOpenerPolicyEnforcementResult {}, - .reserved_environment = {}, - .origin = HTML::Origin {}, - .policy_container = HTML::PolicyContainer {}, - .final_sandboxing_flag_set = HTML::SandboxingFlagSet {}, - .cross_origin_opener_policy = HTML::CrossOriginOpenerPolicy {}, - .about_base_url = {}, - }; + auto navigation_params = navigable->heap().allocate_without_realm(); + navigation_params->navigable = navigable; + navigation_params->response = response; + navigation_params->origin = HTML::Origin {}; + navigation_params->policy_container = HTML::PolicyContainer {}; + navigation_params->final_sandboxing_flag_set = HTML::SandboxingFlagSet {}; + navigation_params->cross_origin_opener_policy = HTML::CrossOriginOpenerPolicy {}; + // FIXME: Use Navigable::navigate() instead of manually replacing the navigable's document. auto document = DOM::Document::create_and_initialize(DOM::Document::Type::HTML, "text/html"_string, navigation_params).release_value_but_fixme_should_propagate_errors(); navigable->set_ongoing_navigation({});