From ed04124cbffbfe8b850e8e3a1bc0788513ce6a4d Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Sun, 8 Sep 2024 00:28:22 -0400 Subject: [PATCH] LibWeb: Fix "attempt to update a history entry's document" This updates our implementation of [attempt-to-populate-the-history-entry's-document](https://html.spec.whatwg.org/multipage/browsing-the-web.html#attempt-to-populate-the-history-entry's-document) after fixes were made to the logic inside the queued task in https://github.com/whatwg/html/commit/cdd014ae84faf3165f8ce8441d132bb0e76513fb#diff-41cf6794ba4200b839c53531555f0f3998df4cbb01a4d5cb0b94e3ca5e23947dL99534. --- Userland/Libraries/LibWeb/HTML/Navigable.cpp | 122 ++++++++----------- 1 file changed, 53 insertions(+), 69 deletions(-) diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.cpp b/Userland/Libraries/LibWeb/HTML/Navigable.cpp index c6b09fa6a9f..656f62785fe 100644 --- a/Userland/Libraries/LibWeb/HTML/Navigable.cpp +++ b/Userland/Libraries/LibWeb/HTML/Navigable.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -1065,9 +1066,10 @@ WebIDL::ExceptionOr Navigable::populate_session_history_entry_document( if (document_resource.has()) { navigation_params = TRY(create_navigation_params_from_a_srcdoc_resource(entry, this, target_snapshot_params, navigation_id)); } - // 2. Otherwise, if both of the following are true: + // 2. Otherwise, if all of the following are true: // - entry's URL's scheme is a fetch scheme; and // - documentResource is null, or allowPOST is true and documentResource's request body is not failure (FIXME: check if request body is not failure) + // then set navigationParams to the result of creating navigation params by fetching given entry, navigable, sourceSnapshotParams, targetSnapshotParams, cspNavigationType, navigationId, and navTimingType. else if (Fetch::Infrastructure::is_fetch_scheme(entry->url().scheme()) && (document_resource.has() || allow_POST)) { navigation_params = TRY(create_navigation_params_by_fetching(entry, this, source_snapshot_params, target_snapshot_params, csp_navigation_type, navigation_id)); } @@ -1101,48 +1103,35 @@ WebIDL::ExceptionOr Navigable::populate_session_history_entry_document( if (has_been_destroyed()) return; - // 1. If navigable's ongoing navigation no longer equals navigationId, then run completionSteps and return. + // 1. If navigable's ongoing navigation no longer equals navigationId, then run completionSteps and abort these steps. if (navigation_id.has_value() && (!ongoing_navigation().has() || ongoing_navigation().get() != *navigation_id)) { if (completion_steps) completion_steps->function()(); return; } - // 2. Let failure be false. - auto failure = false; + // 2. Let saveExtraDocumentState be true. + auto saveExtraDocumentState = true; - // 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 + // 3. If navigationParams is a non-fetch scheme navigation params, then: 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 + // 1. Set entry's document state's document to the result of running attempt to create a non-fetch scheme document given navigationParams. 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); } - if (completion_steps) - completion_steps->function()(); - return; + + // 2. Set saveExtraDocumentState to false. + saveExtraDocumentState = false; } - // 4. Otherwise, if navigationParams is null, then set failure to true. + // 4. Otherwise, if any of the following are true: + // - navigationParams is null; + // - FIXME: the result of should navigation response to navigation request of type in target be blocked by Content Security Policy? given navigationParams's request, navigationParams's response, navigationParams's policy container's CSP list, cspNavigationType, and navigable is "Blocked"; + // - FIXME: navigationParams's reserved environment is non-null and the result of checking a navigation response's adherence to its embedder policy given navigationParams's response, navigable, and navigationParams's policy container's embedder policy is false; or + // - FIXME: the result of checking a navigation response's adherence to `X-Frame-Options` given navigationParams's response, navigable, navigationParams's policy container's CSP list, and navigationParams's origin is false, if (navigation_params.has() || navigation_params.has()) { - failure = true; - } - - // FIXME: 5. Otherwise, if the result of should navigation response to navigation request of type in target be blocked by Content Security Policy? given navigationParams's request, - // navigationParams's response, navigationParams's policy container's CSP list, cspNavigationType, and navigable is "Blocked", then set failure to true. - - // FIXME: 6. Otherwise, if navigationParams's reserved environment is non-null and the result of checking a navigation response's adherence to its embedder policy given - // navigationParams's response, navigable, and navigationParams's policy container's embedder policy is false, then set failure to true. - - // FIXME: 7. Otherwise, if the result of checking a navigation response's adherence to `X-Frame-Options` given navigationParams's response, navigable, - // navigationParams's policy container's CSP list, and navigationParams's origin is false, then set failure to true. - - // 8. If failure is true, then: - if (failure) { - // 1. Set entry's document state's document to the result of creating a document for inline content that doesn't have a DOM, given navigable, null, and navTimingType. - // The inline content should indicate to the user the sort of error that occurred. + // 1. Set entry's document state's document to the result of creating a document for inline content that doesn't have a DOM, given navigable, null, and navTimingType. The inline content should indicate to the user the sort of error that occurred. auto error_message = navigation_params.has() ? navigation_params.get() : "Unknown error"sv; auto error_html = load_error_page(entry->url(), error_message).release_value_but_fixme_should_propagate_errors(); @@ -1152,57 +1141,52 @@ WebIDL::ExceptionOr Navigable::populate_session_history_entry_document( parser->run(); })); - // 2. Set entry's document state's document's salvageable to false. - entry->document()->set_salvageable(false); + // 2. Make document unsalvageable given entry's document state's document and "navigation-failure". + entry->document()->make_unsalvageable("navigation-failure"_string); - // FIXME: 3. If navigationParams is not null, then: - if (!navigation_params.has()) { - // 1. FIXME: Run the environment discarding steps for navigationParams's reserved environment. - // 2. Invoke WebDriver BiDi navigation failed with currentBrowsingContext and a new WebDriver BiDi navigation status - // whose id is navigationId, status is "canceled", and url is navigationParams's response's URL. + // 3. Set saveExtraDocumentState to false. + saveExtraDocumentState = false; + + // 4. If navigationParams is not null, then: + if (navigation_params.has()) { + // FIXME: 1. Run the environment discarding steps for navigationParams's reserved environment. + // FIXME: 2. Invoke WebDriver BiDi navigation failed with currentBrowsingContext and a new WebDriver BiDi navigation status whose id is navigationId, status is "canceled", and url is navigationParams's response's URL. } } - // 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) { - // 1. Run completionSteps. - if (completion_steps) - completion_steps->function()(); - - // 2. Return. - return; - } - // FIXME: 10. Otherwise, if navigationParams's response has a `Content-Disposition` + // FIXME: 5. Otherwise, if navigationParams's response has a `Content-Disposition` // header specifying the attachment disposition type, then: - // 11. Otherwise: - else { - // 1. Let document be the result of loading a document given navigationParams, sourceSnapshotParams, - // and entry's document state's initiator origin. + // 6. Otherwise, if navigationParams's response's status is not 204 and is not 205, then set entry's document state's document to the result of + // loading a document given navigationParams, sourceSnapshotParams, and entry's document state's initiator origin. + else if (navigation_params.get>()->response->status() != 204 && navigation_params.get>()->response->status() != 205) { auto document = load_document(navigation_params.get>()); + entry->document_state()->set_document(document); + } - // 2. If document is null, then run completionSteps and return. - if (!document) { - if (completion_steps) - completion_steps->function()(); - return; + // 7. If entry's document state's document is not null, then: + if (entry->document()) { + // 1. Set entry's document state's ever populated to true. + entry->document_state()->set_ever_populated(true); + + // 2. If saveExtraDocumentState is true: + if (saveExtraDocumentState) { + // 1. Let document be entry's document state's document. + auto document = entry->document(); + + // 2. Set entry's document state's origin to document's origin. + entry->document_state()->set_origin(document->origin()); + + // FIXME: 3. If document's URL requires storing the policy container in history, then: } - // 3. Set entry's document state's document to document. - entry->document_state()->set_document(document.ptr()); - - // 4. Set entry's document state's origin to document's origin. - entry->document_state()->set_origin(document->origin()); + // 3. If entry's document state's request referrer is "client", and navigationParams is a navigation params (i.e., neither null nor a non-fetch scheme navigation params), then: + if (entry->document_state()->request_referrer() == Fetch::Infrastructure::Request::Referrer::Client + && (!navigation_params.has() && Fetch::Infrastructure::is_fetch_scheme(entry->url().scheme()))) { + // FIXME: 1. Assert: navigationParams's request is not null. + // FIXME: 2. Set entry's document state's request referrer to navigationParams's request's referrer. + } } - // FIXME: 12. If entry's document state's request referrer is "client", then set it to request's referrer. - // https://github.com/whatwg/html/issues/9767 - // What is "request" here? - - // 13. If entry's document state's document is not null, then set entry's document state's ever populated to true. - if (entry->document()) { - entry->document_state()->set_ever_populated(true); - } - - // 14. Run completionSteps. + // 8. Run completionSteps. if (completion_steps) completion_steps->function()(); }));