LibWeb: Fix "attempt to update a history entry's document"
Some checks are pending
CI / Lagom (false, FUZZ, ubuntu-22.04, Linux, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, macos-14, macOS, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, ubuntu-22.04, Linux, GNU) (push) Waiting to run
CI / Lagom (true, NO_FUZZ, ubuntu-22.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (macos-14, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (ubuntu-22.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Push notes / build (push) Waiting to run

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
cdd014ae84 (diff-41cf6794ba4200b839c53531555f0f3998df4cbb01a4d5cb0b94e3ca5e23947dL99534).
This commit is contained in:
Daniel La Rocque 2024-09-08 00:28:22 -04:00 committed by Andrew Kaster
parent 8b4dde0b09
commit ed04124cbf
Notes: github-actions[bot] 2024-09-23 22:50:48 +00:00

View file

@ -14,6 +14,7 @@
#include <LibWeb/Fetch/Fetching/Fetching.h> #include <LibWeb/Fetch/Fetching/Fetching.h>
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h> #include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
#include <LibWeb/Fetch/Infrastructure/FetchController.h> #include <LibWeb/Fetch/Infrastructure/FetchController.h>
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
#include <LibWeb/Fetch/Infrastructure/URL.h> #include <LibWeb/Fetch/Infrastructure/URL.h>
#include <LibWeb/HTML/BrowsingContext.h> #include <LibWeb/HTML/BrowsingContext.h>
#include <LibWeb/HTML/DocumentState.h> #include <LibWeb/HTML/DocumentState.h>
@ -1065,9 +1066,10 @@ WebIDL::ExceptionOr<void> Navigable::populate_session_history_entry_document(
if (document_resource.has<String>()) { if (document_resource.has<String>()) {
navigation_params = TRY(create_navigation_params_from_a_srcdoc_resource(entry, this, target_snapshot_params, navigation_id)); 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 // - 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) // - 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<Empty>() || allow_POST)) { else if (Fetch::Infrastructure::is_fetch_scheme(entry->url().scheme()) && (document_resource.has<Empty>() || allow_POST)) {
navigation_params = TRY(create_navigation_params_by_fetching(entry, this, source_snapshot_params, target_snapshot_params, csp_navigation_type, navigation_id)); 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<void> Navigable::populate_session_history_entry_document(
if (has_been_destroyed()) if (has_been_destroyed())
return; 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<String>() || ongoing_navigation().get<String>() != *navigation_id)) { if (navigation_id.has_value() && (!ongoing_navigation().has<String>() || ongoing_navigation().get<String>() != *navigation_id)) {
if (completion_steps) if (completion_steps)
completion_steps->function()(); completion_steps->function()();
return; return;
} }
// 2. Let failure be false. // 2. Let saveExtraDocumentState be true.
auto failure = false; 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 // 3. If navigationParams is a non-fetch scheme navigation params, then:
// running attempt to create a non-fetch scheme document navigationParams
if (navigation_params.has<JS::NonnullGCPtr<NonFetchSchemeNavigationParams>>()) { if (navigation_params.has<JS::NonnullGCPtr<NonFetchSchemeNavigationParams>>()) {
// FIXME: https://github.com/whatwg/html/issues/9767 // 1. Set entry's document state's document to the result of running attempt to create a non-fetch scheme document given navigationParams.
// 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<JS::NonnullGCPtr<NonFetchSchemeNavigationParams>>())); entry->document_state()->set_document(attempt_to_create_a_non_fetch_scheme_document(navigation_params.get<JS::NonnullGCPtr<NonFetchSchemeNavigationParams>>()));
if (entry->document()) { if (entry->document()) {
entry->document_state()->set_ever_populated(true); entry->document_state()->set_ever_populated(true);
} }
if (completion_steps)
completion_steps->function()(); // 2. Set saveExtraDocumentState to false.
return; 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<Empty>() || navigation_params.has<NullWithError>()) { if (navigation_params.has<Empty>() || navigation_params.has<NullWithError>()) {
failure = true; // 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.
}
// 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.
auto error_message = navigation_params.has<NullWithError>() ? navigation_params.get<NullWithError>() : "Unknown error"sv; auto error_message = navigation_params.has<NullWithError>() ? navigation_params.get<NullWithError>() : "Unknown error"sv;
auto error_html = load_error_page(entry->url(), error_message).release_value_but_fixme_should_propagate_errors(); auto error_html = load_error_page(entry->url(), error_message).release_value_but_fixme_should_propagate_errors();
@ -1152,57 +1141,52 @@ WebIDL::ExceptionOr<void> Navigable::populate_session_history_entry_document(
parser->run(); parser->run();
})); }));
// 2. Set entry's document state's document's salvageable to false. // 2. Make document unsalvageable given entry's document state's document and "navigation-failure".
entry->document()->set_salvageable(false); entry->document()->make_unsalvageable("navigation-failure"_string);
// FIXME: 3. If navigationParams is not null, then: // 3. Set saveExtraDocumentState to false.
if (!navigation_params.has<Empty>()) { saveExtraDocumentState = false;
// 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.
}
}
// FIXME: 9. Otherwise, if navigationParams's response's status is 204 or 205, then:
else if (navigation_params.get<JS::NonnullGCPtr<NavigationParams>>()->response->status() == 204 || navigation_params.get<JS::NonnullGCPtr<NavigationParams>>()->response->status() == 205) {
// 1. Run completionSteps.
if (completion_steps)
completion_steps->function()();
// 2. Return. // 4. If navigationParams is not null, then:
return; if (navigation_params.has<Empty>()) {
// 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: 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: // header specifying the attachment disposition type, then:
// 11. Otherwise: // 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
else { // loading a document given navigationParams, sourceSnapshotParams, and entry's document state's initiator origin.
// 1. Let document be the result of loading a document given navigationParams, sourceSnapshotParams, else if (navigation_params.get<JS::NonnullGCPtr<NavigationParams>>()->response->status() != 204 && navigation_params.get<JS::NonnullGCPtr<NavigationParams>>()->response->status() != 205) {
// and entry's document state's initiator origin.
auto document = load_document(navigation_params.get<JS::NonnullGCPtr<NavigationParams>>()); auto document = load_document(navigation_params.get<JS::NonnullGCPtr<NavigationParams>>());
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;
} }
// 3. Set entry's document state's document to document. // 7. If entry's document state's document is not null, then:
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());
}
// 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()) { if (entry->document()) {
// 1. Set entry's document state's ever populated to true.
entry->document_state()->set_ever_populated(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:
} }
// 14. Run completionSteps. // 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<Empty>() && 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.
}
}
// 8. Run completionSteps.
if (completion_steps) if (completion_steps)
completion_steps->function()(); completion_steps->function()();
})); }));