LibWeb: Connect iframe referrerpolicy to ancestorOrigins

Corresponds to:
e161310ae7

This unfortunately isn't testable as we don't implement enough of
ancestorOrigins to be able to observe it.
This commit is contained in:
Sam Atkins 2026-06-11 12:18:41 +01:00
parent 935b9e8e41
commit e7aad5a9d3
9 changed files with 90 additions and 23 deletions

View file

@ -472,10 +472,18 @@ WebIDL::ExceptionOr<GC::Ref<Document>> Document::create_and_initialize(Type type
// 10. Set window's associated Document to document.
window->set_associated_document(*document);
// 11. Run CSP initialization for a Document given document.
// 11. Set document's internal ancestor origin objects list to the result of running the internal ancestor origin
// objects list creation steps given document and navigationParams's iframe element referrer policy.
document->set_internal_ancestor_origin_objects_list(document->internal_ancestor_origin_objects_list_creation_steps(navigation_params.iframe_element_referrer_policy));
// 12. Set document's ancestor origins list to the result of running the ancestor origins list creation steps given
// document.
document->set_ancestor_origins_list(document->ancestor_origins_list_creation_steps());
// 13. Run CSP initialization for a Document given document.
document->run_csp_initialization();
// 12. If navigationParams's request is non-null, then:
// 14. If navigationParams's request is non-null, then:
if (navigation_params.request) {
// 1. Set document's referrer to the empty string.
document->m_referrer = String {};
@ -489,12 +497,13 @@ WebIDL::ExceptionOr<GC::Ref<Document>> Document::create_and_initialize(Type type
}
}
// FIXME: 13: If navigationParams's fetch controller is not null, then:
// FIXME: 15: If navigationParams's fetch controller is not null, then:
// FIXME: 14. Create the navigation timing entry for document, with navigationParams's response's timing info, redirectCount, navigationParams's navigation timing type, and
// navigationParams's response's service worker timing info.
// FIXME: 16. Create the navigation timing entry for document, with navigationParams's response's timing info,
// redirectCount, navigationParams's navigation timing type, and navigationParams's response's service
// worker timing info.
// 15. If navigationParams's response has a `Refresh` header, then:
// 17. If navigationParams's response has a `Refresh` header, then:
if (auto maybe_refresh = navigation_params.response->header_list()->get("Refresh"sv); maybe_refresh.has_value()) {
// 1. Let value be the isomorphic decoding of the value of the header.
auto value = TextCodec::isomorphic_decode(maybe_refresh.value());
@ -503,13 +512,17 @@ WebIDL::ExceptionOr<GC::Ref<Document>> Document::create_and_initialize(Type type
document->shared_declarative_refresh_steps(value, nullptr);
}
// FIXME: 16. If navigationParams's commit early hints is not null, then call navigationParams's commit early hints with document.
// FIXME: 18. If navigationParams's commit early hints is not null, then call navigationParams's commit early hints
// with document.
// FIXME: 17. Process link headers given document, navigationParams's response, and "pre-media".
// FIXME: 19. Process link headers given document, navigationParams's response, and "pre-media".
// FIXME: 18. Potentially free deferred fetch quota for document.
// FIXME: 20. If navigationParams's navigable is a top-level traversable, then process the `Speculation-Rules`
// header given document and navigationParams's response .
// 19. Return document.
// FIXME: 21. Potentially free deferred fetch quota for document.
// 22. Return document.
return document;
}

View file

@ -52,6 +52,7 @@ GC::Ref<DOM::Document> create_document_for_inline_content(GC::Ptr<HTML::Navigabl
// reserved environment: null
// policy container: a new policy container
// final sandboxing flag set: an empty set
// iframe element referrer policy: the empty string
// opener policy: coop
// FIXME: navigation timing type: navTimingType
// about base URL: null
@ -70,6 +71,7 @@ GC::Ref<DOM::Document> create_document_for_inline_content(GC::Ptr<HTML::Navigabl
move(origin),
vm.heap().allocate<HTML::PolicyContainer>(vm.heap()),
HTML::SandboxingFlagSet {},
ReferrerPolicy::ReferrerPolicy::EmptyString,
move(coop),
OptionalNone {},
user_involvement);

View file

@ -252,7 +252,17 @@ BrowsingContext::BrowsingContextAndDocument BrowsingContext::create_a_new_browsi
// custom element registry: A new CustomElementRegistry object.
document->set_custom_element_registry(realm.create<CustomElementRegistry>(realm));
// 16. If creator is non-null, then:
// 16. Let iframeReferrerPolicy be the result of determining the iframe element referrer policy given embedder.
auto iframe_referrer_policy = determine_iframe_element_referrer_policy(embedder);
// 17. Set document's internal ancestor origin objects list to the result of running the internal ancestor origin
// objects list creation steps given document and iframeReferrerPolicy.
document->set_internal_ancestor_origin_objects_list(document->internal_ancestor_origin_objects_list_creation_steps(iframe_referrer_policy));
// 18. Set document's ancestor origins list to the result of running the ancestor origins list creation steps given document.
document->set_ancestor_origins_list(document->ancestor_origins_list_creation_steps());
// 19. If creator is non-null:
if (creator) {
// 1. Set document's referrer to the serialization of creator's URL.
document->set_referrer(creator->url().serialize());
@ -269,25 +279,25 @@ BrowsingContext::BrowsingContextAndDocument BrowsingContext::create_a_new_browsi
}
}
// 17. Assert: document's URL and document's relevant settings object's creation URL are about:blank.
// 20. Assert: document's URL and document's relevant settings object's creation URL are about:blank.
VERIFY(document->url() == URL::about_blank());
VERIFY(document->relevant_settings_object().creation_url == URL::about_blank());
// 18. Mark document as ready for post-load tasks.
// 21. Mark document as ready for post-load tasks.
document->set_ready_for_post_load_tasks(true);
// 19. Populate with html/head/body given document.
// 22. Populate with html/head/body given document.
populate_with_html_head_body(*document);
if (!embedder)
document->set_supported_color_schemes({ "light"_string, "dark"_string });
// 20. Make active document.
// 23. Make active document.
document->make_active();
// 21. Completely finish loading document.
// 24. Completely finish loading document.
document->completely_finish_loading();
// 22. Return browsingContext and document.
// 25. Return browsingContext and document.
return BrowsingContext::BrowsingContextAndDocument { browsing_context, document };
}

View file

@ -322,4 +322,17 @@ WebIDL::ExceptionOr<void> HTMLIFrameElement::set_srcdoc(TrustedTypes::TrustedHTM
return {};
}
// https://html.spec.whatwg.org/multipage/browsers.html#determining-the-iframe-element-referrer-policy
ReferrerPolicy::ReferrerPolicy determine_iframe_element_referrer_policy(GC::Ptr<DOM::Element> embedder)
{
// 1. If embedder is an iframe element, then return embedder's referrerpolicy attribute's state's corresponding
// keyword.
if (auto* iframe = as_if<HTMLIFrameElement>(embedder.ptr())) {
return ReferrerPolicy::from_string(iframe->get_attribute_value(HTML::AttributeNames::referrerpolicy)).value_or(ReferrerPolicy::ReferrerPolicy::EmptyString);
}
// 2. Return the empty string.
return ReferrerPolicy::ReferrerPolicy::EmptyString;
}
}

View file

@ -88,6 +88,8 @@ private:
void run_iframe_load_event_steps(HTML::HTMLIFrameElement&);
ReferrerPolicy::ReferrerPolicy determine_iframe_element_referrer_policy(GC::Ptr<DOM::Element> embedder);
}
namespace Web::DOM {

View file

@ -1081,6 +1081,7 @@ static GC::Ref<NavigationParams> create_navigation_params_from_a_srcdoc_resource
// origin: responseOrigin
// policy container: policyContainer
// final sandboxing flag set: targetSnapshotParams's sandboxing flags
// iframe element referrer policy: targetSnapshotParams's iframe element referrer policy
// opener policy: coop
// FIXME: navigation timing type: navTimingType
// about base URL: entry's document state's about base URL
@ -1097,6 +1098,7 @@ static GC::Ref<NavigationParams> create_navigation_params_from_a_srcdoc_resource
move(response_origin),
*policy_container,
target_snapshot_params.sandboxing_flags,
target_snapshot_params.iframe_element_referrer_policy,
move(coop),
about_base_url,
user_involvement);
@ -1572,6 +1574,8 @@ static void create_navigation_params_by_fetching(
// FIXME: navigation timing type: navTimingType
// about base URL: entry's document state's about base URL
// user involvement: userInvolvement
// FIXME: Value for iframe element referrer policy is missing in the spec. https://github.com/whatwg/html/issues/12567
// So, we default to the empty string.
result->navigation_params = realm.heap().allocate<NavigationParams>(
state_holder->navigation_id,
state_holder->navigable,
@ -1584,6 +1588,7 @@ static void create_navigation_params_by_fetching(
*state_holder->response_origin,
result_policy_container,
state_holder->final_sandbox_flags,
ReferrerPolicy::ReferrerPolicy::EmptyString,
state_holder->response_coop,
state_holder->about_base_url,
user_involvement);
@ -2029,7 +2034,7 @@ void Navigable::begin_navigation(NavigateParams params)
set_delaying_load_events(true);
// 16. Let targetSnapshotParams be the result of snapshotting target snapshot params given navigable.
[[maybe_unused]] auto target_snapshot_params = snapshot_target_snapshot_params();
auto target_snapshot_params = snapshot_target_snapshot_params();
// FIXME: 17. Invoke WebDriver BiDi navigation started with navigable and a new WebDriver BiDi navigation status whose id
// is navigationId, status is "pending", and url is url.
@ -2236,6 +2241,7 @@ void Navigable::begin_navigation(NavigateParams params)
// origin: responseOrigin
// policy container: policyContainer
// final sandboxing flag set: finalSandboxFlags
// iframe element referrer policy: targetSnapshotParams's iframe element referrer policy
// opener policy: coop
// FIXME: navigation timing type: "navigate"
// about base URL: documentState's about base URL
@ -2252,6 +2258,7 @@ void Navigable::begin_navigation(NavigateParams params)
move(response_origin),
policy_container,
final_sandbox_flags,
target_snapshot_params.iframe_element_referrer_policy,
response_coop,
document_state->about_base_url(),
user_involvement);
@ -2454,6 +2461,9 @@ GC::Ptr<DOM::Document> Navigable::evaluate_javascript_url(URL::URL const& url, U
.opener_policy = coop,
};
// AD-HOC: Get the target snapshot params. This is missing from the spec, see https://github.com/whatwg/html/issues/12563
auto target_snapshot_params = snapshot_target_snapshot_params();
// 16. Let navigationParams be a new navigation params, with
// id: navigationId
// navigable: targetNavigable
@ -2466,6 +2476,7 @@ GC::Ptr<DOM::Document> Navigable::evaluate_javascript_url(URL::URL const& url, U
// origin: newDocumentOrigin
// policy container: policyContainer
// final sandboxing flag set: finalSandboxFlags
// iframe element referrer policy: targetSnapshotParams's iframe element referrer policy
// opener policy: coop
// FIXME: navigation timing type: "navigate"
// about base URL: targetNavigable's active document's about base URL
@ -2482,6 +2493,7 @@ GC::Ptr<DOM::Document> Navigable::evaluate_javascript_url(URL::URL const& url, U
new_document_origin,
policy_container,
final_sandbox_flags,
target_snapshot_params.iframe_element_referrer_policy,
coop,
active_document()->about_base_url(),
user_involvement);
@ -2709,11 +2721,15 @@ bool Navigable::allowed_by_sandboxing_to_navigate(Navigable const& target, Sourc
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#snapshotting-target-snapshot-params
TargetSnapshotParams Navigable::snapshot_target_snapshot_params()
{
// To snapshot target snapshot params given a navigable targetNavigable, return a new target snapshot params
// with sandboxing flags set to the result of determining the creation sandboxing flags given targetNavigable's
// active browsing context and targetNavigable's container.
return { determine_the_creation_sandboxing_flags(*active_browsing_context(), container()) };
// To snapshot target snapshot params given a navigable targetNavigable, return a new target snapshot params with:
// - sandboxing flags: the result of determining the creation sandboxing flags given targetNavigable's active
// browsing context and targetNavigable's container
// - iframe element referrer policy: the result of determining the iframe element referrer policy given
// targetNavigable's container
return {
.sandboxing_flags = determine_the_creation_sandboxing_flags(*active_browsing_context(), container()),
.iframe_element_referrer_policy = determine_iframe_element_referrer_policy(container()),
};
}
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#finalize-a-cross-document-navigation

View file

@ -52,7 +52,11 @@ using OnApplyHistoryStepComplete = GC::Function<void(HistoryStepResult)>;
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#target-snapshot-params
struct TargetSnapshotParams {
// sandboxing flags: a sandboxing flag set
SandboxingFlagSet sandboxing_flags {};
// iframe element referrer policy: a referrer policy
ReferrerPolicy::ReferrerPolicy iframe_element_referrer_policy { ReferrerPolicy::ReferrerPolicy::EmptyString };
};
// https://html.spec.whatwg.org/multipage/document-sequences.html#navigable

View file

@ -18,6 +18,7 @@
#include <LibWeb/HTML/PolicyContainers.h>
#include <LibWeb/HTML/SandboxingFlagSet.h>
#include <LibWeb/HTML/UserNavigationInvolvement.h>
#include <LibWeb/ReferrerPolicy/ReferrerPolicy.h>
namespace Web::HTML {
@ -59,6 +60,9 @@ struct NavigationParams : GC::Cell {
// a sandboxing flag set to impose on the new Document
SandboxingFlagSet final_sandboxing_flag_set = {};
// a referrer policy, used in the internal ancestor origin objects list creation steps
ReferrerPolicy::ReferrerPolicy iframe_element_referrer_policy { ReferrerPolicy::ReferrerPolicy::EmptyString };
// an opener policy to use for the new Document
OpenerPolicy opener_policy;
@ -85,6 +89,7 @@ protected:
URL::Origin origin,
GC::Ptr<PolicyContainer> policy_container,
SandboxingFlagSet final_sandboxing_flag_set,
ReferrerPolicy::ReferrerPolicy iframe_element_referrer_policy,
OpenerPolicy opener_policy,
Optional<URL::URL> about_base_url,
UserNavigationInvolvement user_involvement)
@ -99,6 +104,7 @@ protected:
, origin(move(origin))
, policy_container(policy_container)
, final_sandboxing_flag_set(final_sandboxing_flag_set)
, iframe_element_referrer_policy(iframe_element_referrer_policy)
, opener_policy(opener_policy)
, about_base_url(move(about_base_url))
, user_involvement(user_involvement)

View file

@ -59,6 +59,7 @@ ErrorOr<GC::Ref<SVGDecodedImageData>> SVGDecodedImageData::create(JS::Realm& rea
origin,
navigable->heap().allocate<HTML::PolicyContainer>(realm.heap()),
HTML::SandboxingFlagSet {},
ReferrerPolicy::ReferrerPolicy::EmptyString,
HTML::OpenerPolicy {},
OptionalNone {},
HTML::UserNavigationInvolvement::None);