mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-20 03:25:13 +00:00
LibWeb: Make PolicyContainer GC allocated
This is required to store Content Security Policies, as their Directives are implemented as subclasses with overridden virtual functions. Thus, they cannot be stored as generic Directive classes, as it'll lose the ability to call overridden functions when they are copied.
This commit is contained in:
parent
2e27ffab6c
commit
cae0ab2139
Notes:
github-actions[bot]
2025-02-21 12:55:13 +00:00
Author: https://github.com/Lubrsi Commit: https://github.com/LadybirdBrowser/ladybird/commit/cae0ab2139a Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3627 Reviewed-by: https://github.com/AtkinsSJ ✅
43 changed files with 381 additions and 130 deletions
|
@ -485,11 +485,13 @@ set(SOURCES
|
|||
HTML/Scripting/SerializedEnvironmentSettingsObject.cpp
|
||||
HTML/SelectedFile.cpp
|
||||
HTML/SelectItem.cpp
|
||||
HTML/SerializedPolicyContainer.cpp
|
||||
HTML/SessionHistoryEntry.cpp
|
||||
HTML/SessionHistoryTraversalQueue.cpp
|
||||
HTML/ShadowRealmGlobalScope.cpp
|
||||
HTML/SharedResourceRequest.cpp
|
||||
HTML/SourceSet.cpp
|
||||
HTML/SourceSnapshotParams.cpp
|
||||
HTML/Storage.cpp
|
||||
HTML/StorageEvent.cpp
|
||||
HTML/StructuredSerialize.cpp
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2024, Andreas Kling <andreas@ladybird.org>
|
||||
* Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2021-2023, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2021-2025, Luke Wilde <luke@ladybird.org>
|
||||
* Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org>
|
||||
* Copyright (c) 2024, Matthew Olsson <mattco@serenityos.org>
|
||||
* Copyright (c) 2025, Jelle Raaijmakers <jelle@ladybird.org>
|
||||
|
@ -118,6 +118,7 @@
|
|||
#include <LibWeb/HTML/NavigationParams.h>
|
||||
#include <LibWeb/HTML/Numbers.h>
|
||||
#include <LibWeb/HTML/Parser/HTMLParser.h>
|
||||
#include <LibWeb/HTML/PolicyContainers.h>
|
||||
#include <LibWeb/HTML/PopStateEvent.h>
|
||||
#include <LibWeb/HTML/Scripting/Agent.h>
|
||||
#include <LibWeb/HTML/Scripting/ClassicScript.h>
|
||||
|
@ -586,6 +587,7 @@ void Document::visit_edges(Cell::Visitor& visitor)
|
|||
visitor.visit(m_local_storage_holder);
|
||||
visitor.visit(m_session_storage_holder);
|
||||
visitor.visit(m_render_blocking_elements);
|
||||
visitor.visit(m_policy_container);
|
||||
}
|
||||
|
||||
// https://w3c.github.io/selection-api/#dom-document-getselection
|
||||
|
@ -3705,39 +3707,46 @@ void Document::set_active_sandboxing_flag_set(HTML::SandboxingFlagSet sandboxing
|
|||
m_active_sandboxing_flag_set = sandboxing_flag_set;
|
||||
}
|
||||
|
||||
HTML::PolicyContainer Document::policy_container() const
|
||||
GC::Ref<HTML::PolicyContainer> Document::policy_container() const
|
||||
{
|
||||
return m_policy_container;
|
||||
auto& realm = this->realm();
|
||||
if (!m_policy_container) {
|
||||
m_policy_container = realm.create<HTML::PolicyContainer>(realm);
|
||||
}
|
||||
return *m_policy_container;
|
||||
}
|
||||
|
||||
void Document::set_policy_container(HTML::PolicyContainer policy_container)
|
||||
void Document::set_policy_container(GC::Ref<HTML::PolicyContainer> policy_container)
|
||||
{
|
||||
m_policy_container = move(policy_container);
|
||||
m_policy_container = policy_container;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#snapshotting-source-snapshot-params
|
||||
HTML::SourceSnapshotParams Document::snapshot_source_snapshot_params() const
|
||||
GC::Ref<HTML::SourceSnapshotParams> Document::snapshot_source_snapshot_params() const
|
||||
{
|
||||
auto& realm = this->realm();
|
||||
|
||||
// To snapshot source snapshot params given a Document sourceDocument, return a new source snapshot params with
|
||||
return realm.create<HTML::SourceSnapshotParams>(
|
||||
// has transient activation
|
||||
// true if sourceDocument's relevant global object has transient activation; otherwise false
|
||||
as<HTML::Window>(HTML::relevant_global_object(*this)).has_transient_activation(),
|
||||
|
||||
// has transient activation
|
||||
// true if sourceDocument's relevant global object has transient activation; otherwise false
|
||||
// sandboxing flags
|
||||
// sourceDocument's active sandboxing flag set
|
||||
// allows downloading
|
||||
// false if sourceDocument's active sandboxing flag set has the sandboxed downloads browsing context flag set; otherwise true
|
||||
// fetch client
|
||||
// sourceDocument's relevant settings object
|
||||
// source policy container
|
||||
// a clone of sourceDocument's policy container
|
||||
// sandboxing flags
|
||||
// sourceDocument's active sandboxing flag set
|
||||
m_active_sandboxing_flag_set,
|
||||
|
||||
return HTML::SourceSnapshotParams {
|
||||
.has_transient_activation = as<HTML::Window>(HTML::relevant_global_object(*this)).has_transient_activation(),
|
||||
.sandboxing_flags = m_active_sandboxing_flag_set,
|
||||
.allows_downloading = !has_flag(m_active_sandboxing_flag_set, HTML::SandboxingFlagSet::SandboxedDownloads),
|
||||
.fetch_client = relevant_settings_object(),
|
||||
.source_policy_container = m_policy_container
|
||||
};
|
||||
// allows downloading
|
||||
// false if sourceDocument's active sandboxing flag set has the sandboxed downloads browsing context flag set; otherwise true
|
||||
!has_flag(m_active_sandboxing_flag_set, HTML::SandboxingFlagSet::SandboxedDownloads),
|
||||
|
||||
// fetch client
|
||||
// sourceDocument's relevant settings object
|
||||
relevant_settings_object(),
|
||||
|
||||
// source policy container
|
||||
// a clone of sourceDocument's policy container
|
||||
policy_container()->clone(realm));
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/document-sequences.html#descendant-navigables
|
||||
|
|
|
@ -548,8 +548,8 @@ public:
|
|||
void set_active_sandboxing_flag_set(HTML::SandboxingFlagSet);
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/dom.html#concept-document-policy-container
|
||||
HTML::PolicyContainer policy_container() const;
|
||||
void set_policy_container(HTML::PolicyContainer);
|
||||
GC::Ref<HTML::PolicyContainer> policy_container() const;
|
||||
void set_policy_container(GC::Ref<HTML::PolicyContainer>);
|
||||
|
||||
Vector<GC::Root<HTML::Navigable>> descendant_navigables();
|
||||
Vector<GC::Root<HTML::Navigable>> const descendant_navigables() const;
|
||||
|
@ -635,7 +635,7 @@ public:
|
|||
|
||||
u32 unload_counter() const { return m_unload_counter; }
|
||||
|
||||
HTML::SourceSnapshotParams snapshot_source_snapshot_params() const;
|
||||
GC::Ref<HTML::SourceSnapshotParams> snapshot_source_snapshot_params() const;
|
||||
|
||||
void update_for_history_step_application(GC::Ref<HTML::SessionHistoryEntry>, bool do_not_reactivate, size_t script_history_length, size_t script_history_index, Optional<Bindings::NavigationType> navigation_type, Optional<Vector<GC::Ref<HTML::SessionHistoryEntry>>> entries_for_navigation_api = {}, GC::Ptr<HTML::SessionHistoryEntry> previous_entry_for_activation = {}, bool update_navigation_api = true);
|
||||
|
||||
|
@ -1018,7 +1018,7 @@ private:
|
|||
HTML::SandboxingFlagSet m_active_sandboxing_flag_set;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/dom.html#concept-document-policy-container
|
||||
HTML::PolicyContainer m_policy_container;
|
||||
mutable GC::Ptr<HTML::PolicyContainer> m_policy_container;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/interaction.html#visibility-state
|
||||
HTML::VisibilityState m_visibility_state { HTML::VisibilityState::Hidden };
|
||||
|
|
|
@ -21,6 +21,8 @@ template<typename MutateDocument>
|
|||
GC::Ref<DOM::Document> create_document_for_inline_content(GC::Ptr<HTML::Navigable> navigable, Optional<String> navigation_id, HTML::UserNavigationInvolvement user_involvement, MutateDocument mutate_document)
|
||||
{
|
||||
auto& vm = navigable->vm();
|
||||
VERIFY(navigable->active_document());
|
||||
auto& realm = navigable->active_document()->realm();
|
||||
|
||||
// 1. Let origin be a new opaque origin.
|
||||
URL::Origin origin {};
|
||||
|
@ -66,7 +68,7 @@ GC::Ref<DOM::Document> create_document_for_inline_content(GC::Ptr<HTML::Navigabl
|
|||
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->policy_container = vm.heap().allocate<HTML::PolicyContainer>(realm);
|
||||
navigation_params->final_sandboxing_flag_set = HTML::SandboxingFlagSet {};
|
||||
navigation_params->opener_policy = move(coop);
|
||||
navigation_params->about_base_url = {};
|
||||
|
|
|
@ -181,10 +181,10 @@ WebIDL::ExceptionOr<GC::Ref<Infrastructure::FetchController>> fetch(JS::Realm& r
|
|||
// 1. If request’s client is non-null, then set request’s policy container to a clone of request’s client’s
|
||||
// policy container.
|
||||
if (request.client() != nullptr)
|
||||
request.set_policy_container(request.client()->policy_container());
|
||||
request.set_policy_container(request.client()->policy_container()->clone(realm));
|
||||
// 2. Otherwise, set request’s policy container to a new policy container.
|
||||
else
|
||||
request.set_policy_container(HTML::PolicyContainer {});
|
||||
request.set_policy_container(realm.create<HTML::PolicyContainer>(realm));
|
||||
}
|
||||
|
||||
// 13. If request’s header list does not contain `Accept`, then:
|
||||
|
@ -301,8 +301,8 @@ WebIDL::ExceptionOr<GC::Ptr<PendingResponse>> main_fetch(JS::Realm& realm, Infra
|
|||
// 8. If request’s referrer policy is the empty string, then set request’s referrer policy to request’s policy
|
||||
// container’s referrer policy.
|
||||
if (request->referrer_policy() == ReferrerPolicy::ReferrerPolicy::EmptyString) {
|
||||
VERIFY(request->policy_container().has<HTML::PolicyContainer>());
|
||||
request->set_referrer_policy(request->policy_container().get<HTML::PolicyContainer>().referrer_policy);
|
||||
VERIFY(request->policy_container().has<GC::Ref<HTML::PolicyContainer>>());
|
||||
request->set_referrer_policy(request->policy_container().get<GC::Ref<HTML::PolicyContainer>>()->referrer_policy);
|
||||
}
|
||||
|
||||
// 9. If request’s referrer is not "no-referrer", then set request’s referrer to the result of invoking determine
|
||||
|
|
|
@ -33,6 +33,9 @@ void Request::visit_edges(JS::Cell::Visitor& visitor)
|
|||
[&](GC::Ptr<HTML::EnvironmentSettingsObject> const& value) { visitor.visit(value); },
|
||||
[](auto const&) {});
|
||||
visitor.visit(m_pending_responses);
|
||||
m_policy_container.visit(
|
||||
[&](GC::Ref<HTML::PolicyContainer> const& policy_container) { visitor.visit(policy_container); },
|
||||
[](auto const&) {});
|
||||
}
|
||||
|
||||
GC::Ref<Request> Request::create(JS::VM& vm)
|
||||
|
@ -359,7 +362,7 @@ bool Request::cross_origin_embedder_policy_allows_credentials() const
|
|||
return true;
|
||||
|
||||
// 3. If request’s client’s policy container’s embedder policy’s value is not "credentialless", then return true.
|
||||
if (m_policy_container.has<HTML::PolicyContainer>() && m_policy_container.get<HTML::PolicyContainer>().embedder_policy.value != HTML::EmbedderPolicyValue::Credentialless)
|
||||
if (m_policy_container.has<GC::Ref<HTML::PolicyContainer>>() && m_policy_container.get<GC::Ref<HTML::PolicyContainer>>()->embedder_policy.value != HTML::EmbedderPolicyValue::Credentialless)
|
||||
return true;
|
||||
|
||||
// 4. If request’s origin is same origin with request’s current URL’s origin and request does not have a redirect-tainted origin, then return true.
|
||||
|
|
|
@ -171,7 +171,7 @@ public:
|
|||
|
||||
using BodyType = Variant<Empty, ByteBuffer, GC::Ref<Body>>;
|
||||
using OriginType = Variant<Origin, URL::Origin>;
|
||||
using PolicyContainerType = Variant<PolicyContainer, HTML::PolicyContainer>;
|
||||
using PolicyContainerType = Variant<PolicyContainer, GC::Ref<HTML::PolicyContainer>>;
|
||||
using ReferrerType = Variant<Referrer, URL::URL>;
|
||||
using ReservedClientType = GC::Ptr<HTML::Environment>;
|
||||
using WindowType = Variant<Window, GC::Ptr<HTML::EnvironmentSettingsObject>>;
|
||||
|
|
|
@ -583,6 +583,7 @@ struct POSTResource;
|
|||
struct ScrollOptions;
|
||||
struct ScrollToOptions;
|
||||
struct SerializedFormData;
|
||||
struct SerializedPolicyContainer;
|
||||
struct StructuredSerializeOptions;
|
||||
struct SyntheticRealmSettings;
|
||||
struct ToggleTaskTracker;
|
||||
|
|
|
@ -251,7 +251,7 @@ WebIDL::ExceptionOr<BrowsingContext::BrowsingContextAndDocument> BrowsingContext
|
|||
document->set_referrer(creator->url().serialize());
|
||||
|
||||
// 2. Set document's policy container to a clone of creator's policy container.
|
||||
document->set_policy_container(creator->policy_container());
|
||||
document->set_policy_container(creator->policy_container()->clone(document->realm()));
|
||||
|
||||
// 3. If creator's origin is same origin with creator's relevant settings object's top-level origin,
|
||||
if (creator->origin().is_same_origin(creator->relevant_settings_object().top_level_origin)) {
|
||||
|
|
|
@ -38,6 +38,9 @@ void DocumentState::visit_edges(Cell::Visitor& visitor)
|
|||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_document);
|
||||
m_history_policy_container.visit(
|
||||
[&](GC::Ref<PolicyContainer> const& policy_container) { visitor.visit(policy_container); },
|
||||
[](auto const&) {});
|
||||
for (auto& nested_history : m_nested_histories) {
|
||||
visitor.visit(nested_history.entries);
|
||||
}
|
||||
|
|
|
@ -40,8 +40,8 @@ public:
|
|||
[[nodiscard]] GC::Ptr<DOM::Document> document() const { return m_document; }
|
||||
void set_document(GC::Ptr<DOM::Document> document) { m_document = document; }
|
||||
|
||||
[[nodiscard]] Variant<PolicyContainer, Client> history_policy_container() const { return m_history_policy_container; }
|
||||
void set_history_policy_container(Variant<PolicyContainer, Client> history_policy_container) { m_history_policy_container = move(history_policy_container); }
|
||||
[[nodiscard]] Variant<GC::Ref<PolicyContainer>, Client> history_policy_container() const { return m_history_policy_container; }
|
||||
void set_history_policy_container(Variant<GC::Ref<PolicyContainer>, Client> history_policy_container) { m_history_policy_container = move(history_policy_container); }
|
||||
|
||||
[[nodiscard]] Fetch::Infrastructure::Request::ReferrerType request_referrer() const { return m_request_referrer; }
|
||||
void set_request_referrer(Fetch::Infrastructure::Request::ReferrerType request_referrer) { m_request_referrer = move(request_referrer); }
|
||||
|
@ -82,7 +82,7 @@ private:
|
|||
GC::Ptr<DOM::Document> m_document;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#document-state-history-policy-container
|
||||
Variant<PolicyContainer, Client> m_history_policy_container { Client::Tag };
|
||||
Variant<GC::Ref<PolicyContainer>, Client> m_history_policy_container { Client::Tag };
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#document-state-request-referrer
|
||||
Fetch::Infrastructure::Request::ReferrerType m_request_referrer { Fetch::Infrastructure::Request::Referrer::Client };
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
* Copyright (c) 2025, Luke Wilde <luke@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibIPC/Decoder.h>
|
||||
#include <LibIPC/Encoder.h>
|
||||
#include <LibWeb/HTML/EmbedderPolicy.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
@ -33,3 +36,31 @@ Optional<EmbedderPolicyValue> embedder_policy_value_from_string(StringView strin
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template<>
|
||||
ErrorOr<void> encode(Encoder& encoder, Web::HTML::EmbedderPolicy const& embedder_policy)
|
||||
{
|
||||
TRY(encoder.encode(embedder_policy.value));
|
||||
TRY(encoder.encode(embedder_policy.reporting_endpoint));
|
||||
TRY(encoder.encode(embedder_policy.report_only_value));
|
||||
TRY(encoder.encode(embedder_policy.report_only_reporting_endpoint));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
template<>
|
||||
ErrorOr<Web::HTML::EmbedderPolicy> decode(Decoder& decoder)
|
||||
{
|
||||
Web::HTML::EmbedderPolicy embedder_policy {};
|
||||
|
||||
embedder_policy.value = TRY(decoder.decode<Web::HTML::EmbedderPolicyValue>());
|
||||
embedder_policy.reporting_endpoint = TRY(decoder.decode<String>());
|
||||
embedder_policy.report_only_value = TRY(decoder.decode<Web::HTML::EmbedderPolicyValue>());
|
||||
embedder_policy.report_only_reporting_endpoint = TRY(decoder.decode<String>());
|
||||
|
||||
return embedder_policy;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
* Copyright (c) 2025, Luke Wilde <luke@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -9,6 +10,7 @@
|
|||
#include <AK/Optional.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/StringView.h>
|
||||
#include <LibIPC/Forward.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
|
@ -42,3 +44,13 @@ struct EmbedderPolicy {
|
|||
};
|
||||
|
||||
}
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template<>
|
||||
ErrorOr<void> encode(Encoder&, Web::HTML::EmbedderPolicy const&);
|
||||
|
||||
template<>
|
||||
ErrorOr<Web::HTML::EmbedderPolicy> decode(Decoder&);
|
||||
|
||||
}
|
||||
|
|
|
@ -286,7 +286,7 @@ GC::Ptr<Fetch::Infrastructure::Request> HTMLLinkElement::create_link_request(HTM
|
|||
auto request = create_potential_CORS_request(vm(), *url, options.destination, options.crossorigin);
|
||||
|
||||
// 6. Set request's policy container to options's policy container.
|
||||
request->set_policy_container(options.policy_container);
|
||||
request->set_policy_container(GC::Ref { *options.policy_container });
|
||||
|
||||
// 7. Set request's integrity metadata to options's integrity.
|
||||
request->set_integrity_metadata(options.integrity);
|
||||
|
|
|
@ -92,7 +92,7 @@ private:
|
|||
GC::Ptr<HTML::EnvironmentSettingsObject> environment;
|
||||
// policy container
|
||||
// A policy container
|
||||
HTML::PolicyContainer policy_container;
|
||||
GC::Ptr<HTML::PolicyContainer> policy_container;
|
||||
// document (default null)
|
||||
// Null or a Document
|
||||
GC::Ptr<Web::DOM::Document> document;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2024, Andreas Kling <andreas@ladybird.org>
|
||||
* Copyright (c) 2023, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
* Copyright (c) 2025, Luke Wilde <luke@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -608,42 +609,41 @@ Vector<GC::Ref<SessionHistoryEntry>>& Navigable::get_session_history_entries() c
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/browsers.html#determining-navigation-params-policy-container
|
||||
static PolicyContainer determine_navigation_params_policy_container(URL::URL const& response_url,
|
||||
Optional<PolicyContainer> history_policy_container,
|
||||
Optional<PolicyContainer> initiator_policy_container,
|
||||
Optional<PolicyContainer> parent_policy_container,
|
||||
Optional<PolicyContainer> response_policy_container)
|
||||
static GC::Ref<PolicyContainer> determine_navigation_params_policy_container(URL::URL const& response_url,
|
||||
JS::Realm& realm,
|
||||
GC::Ptr<PolicyContainer> history_policy_container,
|
||||
GC::Ptr<PolicyContainer> initiator_policy_container,
|
||||
GC::Ptr<PolicyContainer> parent_policy_container,
|
||||
GC::Ptr<PolicyContainer> response_policy_container)
|
||||
{
|
||||
// NOTE: The clone a policy container AO is just a C++ copy
|
||||
|
||||
// 1. If historyPolicyContainer is not null, then:
|
||||
if (history_policy_container.has_value()) {
|
||||
if (history_policy_container) {
|
||||
// FIXME: 1. Assert: responseURL requires storing the policy container in history.
|
||||
|
||||
// 2. Return a clone of historyPolicyContainer.
|
||||
return *history_policy_container;
|
||||
return history_policy_container->clone(realm);
|
||||
}
|
||||
|
||||
// 2. If responseURL is about:srcdoc, then:
|
||||
if (response_url == URL::about_srcdoc()) {
|
||||
// 1. Assert: parentPolicyContainer is not null.
|
||||
VERIFY(parent_policy_container.has_value());
|
||||
VERIFY(parent_policy_container);
|
||||
|
||||
// 2. Return a clone of parentPolicyContainer.
|
||||
return *parent_policy_container;
|
||||
return parent_policy_container->clone(realm);
|
||||
}
|
||||
|
||||
// 3. If responseURL is local and initiatorPolicyContainer is not null, then return a clone of initiatorPolicyContainer.
|
||||
if (Fetch::Infrastructure::is_local_url(response_url) && initiator_policy_container.has_value())
|
||||
return *initiator_policy_container;
|
||||
if (Fetch::Infrastructure::is_local_url(response_url) && initiator_policy_container)
|
||||
return initiator_policy_container->clone(realm);
|
||||
|
||||
// 4. If responsePolicyContainer is not null, then return responsePolicyContainer.
|
||||
// FIXME: File a spec issue to say "a clone of" here for consistency
|
||||
if (response_policy_container.has_value())
|
||||
return *response_policy_container;
|
||||
if (response_policy_container)
|
||||
return response_policy_container->clone(realm);
|
||||
|
||||
// 5. Return a new policy container.
|
||||
return {};
|
||||
return realm.create<PolicyContainer>(realm);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/browsers.html#obtain-coop
|
||||
|
@ -724,15 +724,17 @@ static GC::Ref<NavigationParams> create_navigation_params_from_a_srcdoc_resource
|
|||
|
||||
// 6. Let policyContainer be the result of determining navigation params policy container given response's URL,
|
||||
// entry's document state's history policy container, null, navigable's container document's policy container, and null.
|
||||
Optional<PolicyContainer> history_policy_container = entry->document_state()->history_policy_container().visit(
|
||||
[](PolicyContainer const& c) -> Optional<PolicyContainer> { return c; },
|
||||
[](DocumentState::Client) -> Optional<PolicyContainer> { return {}; });
|
||||
PolicyContainer policy_container;
|
||||
GC::Ptr<PolicyContainer> history_policy_container = entry->document_state()->history_policy_container().visit(
|
||||
[](GC::Ref<PolicyContainer> const& c) -> GC::Ptr<PolicyContainer> { return c; },
|
||||
[](DocumentState::Client) -> GC::Ptr<PolicyContainer> { return {}; });
|
||||
GC::Ptr<PolicyContainer> policy_container;
|
||||
if (navigable->container()) {
|
||||
// NOTE: Specification assumes that only navigables corresponding to iframes can be navigated to about:srcdoc.
|
||||
// We also use srcdoc to implement load_html() for top level navigables so we need to null check container
|
||||
// because it might be null.
|
||||
policy_container = determine_navigation_params_policy_container(*response->url(), history_policy_container, {}, navigable->container_document()->policy_container(), {});
|
||||
policy_container = determine_navigation_params_policy_container(*response->url(), realm, history_policy_container, {}, navigable->container_document()->policy_container(), {});
|
||||
} else {
|
||||
policy_container = realm.create<PolicyContainer>(realm);
|
||||
}
|
||||
|
||||
// 7. Return a new navigation params, with
|
||||
|
@ -757,7 +759,7 @@ static GC::Ref<NavigationParams> create_navigation_params_from_a_srcdoc_resource
|
|||
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->policy_container = *policy_container;
|
||||
navigation_params->final_sandboxing_flag_set = target_snapshot_params.sandboxing_flags;
|
||||
navigation_params->opener_policy = move(coop);
|
||||
navigation_params->about_base_url = entry->document_state()->about_base_url();
|
||||
|
@ -904,7 +906,7 @@ static WebIDL::ExceptionOr<Navigable::NavigationParamsVariant> create_navigation
|
|||
SandboxingFlagSet final_sandbox_flags = {};
|
||||
|
||||
// 14. Let responsePolicyContainer be null.
|
||||
Optional<PolicyContainer> response_policy_container = {};
|
||||
GC::Ptr<PolicyContainer> response_policy_container = {};
|
||||
|
||||
// 15. Let responseCOOP be a new opener policy.
|
||||
OpenerPolicy response_coop = {};
|
||||
|
@ -1096,10 +1098,10 @@ static WebIDL::ExceptionOr<Navigable::NavigationParamsVariant> create_navigation
|
|||
|
||||
// 23. Let resultPolicyContainer be the result of determining navigation params policy container given response's URL,
|
||||
// entry's document state's history policy container, sourceSnapshotParams's source policy container, null, and responsePolicyContainer.
|
||||
Optional<PolicyContainer> history_policy_container = entry->document_state()->history_policy_container().visit(
|
||||
[](PolicyContainer const& c) -> Optional<PolicyContainer> { return c; },
|
||||
[](DocumentState::Client) -> Optional<PolicyContainer> { return {}; });
|
||||
auto result_policy_container = determine_navigation_params_policy_container(*response_holder->response()->url(), history_policy_container, source_snapshot_params.source_policy_container, {}, response_policy_container);
|
||||
GC::Ptr<PolicyContainer> history_policy_container = entry->document_state()->history_policy_container().visit(
|
||||
[](GC::Ref<PolicyContainer> const& c) -> GC::Ptr<PolicyContainer> { return c; },
|
||||
[](DocumentState::Client) -> GC::Ptr<PolicyContainer> { return {}; });
|
||||
auto result_policy_container = determine_navigation_params_policy_container(*response_holder->response()->url(), realm, history_policy_container, source_snapshot_params.source_policy_container, {}, response_policy_container);
|
||||
|
||||
// 24. If navigable's container is an iframe, and response's timing allow passed flag is set, then set container's pending resource-timing start time to null.
|
||||
if (navigable->container() && is<HTML::HTMLIFrameElement>(*navigable->container()) && response_holder->response()->timing_allow_passed())
|
||||
|
@ -1298,7 +1300,14 @@ WebIDL::ExceptionOr<void> Navigable::populate_session_history_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. If document's URL requires storing the policy container in history, then:
|
||||
if (url_requires_storing_the_policy_container_in_history(document->url())) {
|
||||
// 1. Assert: navigationParams is a navigation params (i.e., neither null nor a non-fetch scheme navigation params).
|
||||
VERIFY(navigation_params.has<GC::Ref<NavigationParams>>());
|
||||
|
||||
// 2. Set entry's document state's history policy container to navigationParams's policy container.
|
||||
entry->document_state()->set_history_policy_container(GC::Ref { *navigation_params.get<GC::Ref<NavigationParams>>()->policy_container });
|
||||
}
|
||||
}
|
||||
|
||||
// 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:
|
||||
|
@ -1810,7 +1819,7 @@ GC::Ptr<DOM::Document> Navigable::evaluate_javascript_url(URL::URL const& url, U
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigate-to-a-javascript:-url
|
||||
void Navigable::navigate_to_a_javascript_url(URL::URL const& url, HistoryHandlingBehavior history_handling, SourceSnapshotParams, URL::Origin const& initiator_origin, UserNavigationInvolvement user_involvement, CSPNavigationType csp_navigation_type, String navigation_id)
|
||||
void Navigable::navigate_to_a_javascript_url(URL::URL const& url, HistoryHandlingBehavior history_handling, GC::Ref<SourceSnapshotParams>, URL::Origin const& initiator_origin, UserNavigationInvolvement user_involvement, CSPNavigationType csp_navigation_type, String navigation_id)
|
||||
{
|
||||
// 1. Assert: historyHandling is "replace".
|
||||
VERIFY(history_handling == HistoryHandlingBehavior::Replace);
|
||||
|
|
|
@ -154,7 +154,7 @@ public:
|
|||
WebIDL::ExceptionOr<void> navigate_to_a_fragment(URL::URL const&, HistoryHandlingBehavior, UserNavigationInvolvement, GC::Ptr<DOM::Element> source_element, Optional<SerializationRecord> navigation_api_state, String navigation_id);
|
||||
|
||||
GC::Ptr<DOM::Document> evaluate_javascript_url(URL::URL const&, URL::Origin const& new_document_origin, UserNavigationInvolvement, String navigation_id);
|
||||
void navigate_to_a_javascript_url(URL::URL const&, HistoryHandlingBehavior, SourceSnapshotParams, URL::Origin const& initiator_origin, UserNavigationInvolvement, CSPNavigationType csp_navigation_type, String navigation_id);
|
||||
void navigate_to_a_javascript_url(URL::URL const&, HistoryHandlingBehavior, GC::Ref<SourceSnapshotParams>, URL::Origin const& initiator_origin, UserNavigationInvolvement, CSPNavigationType csp_navigation_type, String navigation_id);
|
||||
|
||||
bool allowed_by_sandboxing_to_navigate(Navigable const& target, SourceSnapshotParams const&);
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ void NavigationParams::visit_edges(Visitor& visitor)
|
|||
visitor.visit(response);
|
||||
visitor.visit(fetch_controller);
|
||||
visitor.visit(reserved_environment);
|
||||
visitor.visit(policy_container);
|
||||
}
|
||||
|
||||
void NonFetchSchemeNavigationParams::visit_edges(Visitor& visitor)
|
||||
|
|
|
@ -60,7 +60,7 @@ struct NavigationParams : JS::Cell {
|
|||
URL::Origin origin;
|
||||
|
||||
// a policy container to use for the new Document
|
||||
PolicyContainer policy_container;
|
||||
GC::Ptr<PolicyContainer> policy_container;
|
||||
|
||||
// a sandboxing flag set to impose on the new Document
|
||||
SandboxingFlagSet final_sandboxing_flag_set = {};
|
||||
|
|
|
@ -1,29 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Andrew Kaster <akaster@serenityos.org>
|
||||
* Copyright (c) 2025, Luke Wilde <luke@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibIPC/Decoder.h>
|
||||
#include <LibIPC/Encoder.h>
|
||||
#include <LibJS/Runtime/Realm.h>
|
||||
#include <LibURL/URL.h>
|
||||
#include <LibWeb/Fetch/Infrastructure/URL.h>
|
||||
#include <LibWeb/HTML/PolicyContainers.h>
|
||||
#include <LibWeb/HTML/SerializedPolicyContainer.h>
|
||||
|
||||
namespace IPC {
|
||||
namespace Web::HTML {
|
||||
|
||||
template<>
|
||||
ErrorOr<void> encode(IPC::Encoder& encoder, Web::HTML::PolicyContainer const& policy_container)
|
||||
GC_DEFINE_ALLOCATOR(PolicyContainer);
|
||||
|
||||
PolicyContainer::PolicyContainer(JS::Realm&)
|
||||
{
|
||||
TRY(encode(encoder, policy_container.referrer_policy));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
template<>
|
||||
ErrorOr<Web::HTML::PolicyContainer> decode(IPC::Decoder& decoder)
|
||||
// https://html.spec.whatwg.org/multipage/browsers.html#requires-storing-the-policy-container-in-history
|
||||
bool url_requires_storing_the_policy_container_in_history(URL::URL const& url)
|
||||
{
|
||||
auto referrer_policy = TRY(decoder.decode<Web::ReferrerPolicy::ReferrerPolicy>());
|
||||
// 1. If url's scheme is "blob", then return false.
|
||||
if (url.scheme() == "blob"sv)
|
||||
return false;
|
||||
|
||||
return Web::HTML::PolicyContainer { .referrer_policy = referrer_policy };
|
||||
// 2. If url is local, then return true.
|
||||
// 3. Return false.
|
||||
return Fetch::Infrastructure::is_local_url(url);
|
||||
}
|
||||
|
||||
GC::Ref<PolicyContainer> create_a_policy_container_from_serialized_policy_container(JS::Realm& realm, SerializedPolicyContainer const& serialized_policy_container)
|
||||
{
|
||||
GC::Ref<PolicyContainer> result = realm.create<PolicyContainer>(realm);
|
||||
result->embedder_policy = serialized_policy_container.embedder_policy;
|
||||
result->referrer_policy = serialized_policy_container.referrer_policy;
|
||||
return result;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/browsers.html#clone-a-policy-container
|
||||
GC::Ref<PolicyContainer> PolicyContainer::clone(JS::Realm& realm) const
|
||||
{
|
||||
// 1. Let clone be a new policy container.
|
||||
auto clone = realm.create<PolicyContainer>(realm);
|
||||
|
||||
// FIXME: 2. For each policy in policyContainer's CSP list, append a copy of policy into clone's CSP list.
|
||||
|
||||
// 3. Set clone's embedder policy to a copy of policyContainer's embedder policy.
|
||||
// NOTE: This is a C++ copy.
|
||||
clone->embedder_policy = embedder_policy;
|
||||
|
||||
// 4. Set clone's referrer policy to policyContainer's referrer policy.
|
||||
clone->referrer_policy = referrer_policy;
|
||||
|
||||
// 5. Return clone.
|
||||
return clone;
|
||||
}
|
||||
|
||||
SerializedPolicyContainer PolicyContainer::serialize() const
|
||||
{
|
||||
return SerializedPolicyContainer {
|
||||
.embedder_policy = embedder_policy,
|
||||
.referrer_policy = referrer_policy,
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2025, Luke Wilde <luke@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibIPC/Forward.h>
|
||||
#include <LibGC/CellAllocator.h>
|
||||
#include <LibJS/Heap/Cell.h>
|
||||
#include <LibURL/Forward.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
#include <LibWeb/HTML/EmbedderPolicy.h>
|
||||
#include <LibWeb/ReferrerPolicy/ReferrerPolicy.h>
|
||||
|
||||
|
@ -14,7 +18,13 @@ namespace Web::HTML {
|
|||
|
||||
// https://html.spec.whatwg.org/multipage/origin.html#policy-container
|
||||
// A policy container is a struct containing policies that apply to a Document, a WorkerGlobalScope, or a WorkletGlobalScope. It has the following items:
|
||||
struct PolicyContainer {
|
||||
struct PolicyContainer : public JS::Cell {
|
||||
GC_CELL(PolicyContainer, JS::Cell)
|
||||
GC_DECLARE_ALLOCATOR(PolicyContainer);
|
||||
|
||||
public:
|
||||
virtual ~PolicyContainer() = default;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/origin.html#policy-container-csp-list
|
||||
// FIXME: A CSP list, which is a CSP list. It is initially empty.
|
||||
|
||||
|
@ -25,14 +35,17 @@ struct PolicyContainer {
|
|||
// https://html.spec.whatwg.org/multipage/origin.html#policy-container-referrer-policy
|
||||
// A referrer policy, which is a referrer policy. It is initially the default referrer policy.
|
||||
ReferrerPolicy::ReferrerPolicy referrer_policy { ReferrerPolicy::DEFAULT_REFERRER_POLICY };
|
||||
|
||||
[[nodiscard]] GC::Ref<PolicyContainer> clone(JS::Realm&) const;
|
||||
[[nodiscard]] SerializedPolicyContainer serialize() const;
|
||||
|
||||
private:
|
||||
PolicyContainer(JS::Realm&);
|
||||
};
|
||||
|
||||
}
|
||||
// https://html.spec.whatwg.org/multipage/browsers.html#requires-storing-the-policy-container-in-history
|
||||
[[nodiscard]] bool url_requires_storing_the_policy_container_in_history(URL::URL const& url);
|
||||
|
||||
namespace IPC {
|
||||
template<>
|
||||
ErrorOr<void> encode(IPC::Encoder&, Web::HTML::PolicyContainer const&);
|
||||
[[nodiscard]] GC::Ref<PolicyContainer> create_a_policy_container_from_serialized_policy_container(JS::Realm&, SerializedPolicyContainer const&);
|
||||
|
||||
template<>
|
||||
ErrorOr<Web::HTML::PolicyContainer> decode(IPC::Decoder&);
|
||||
}
|
||||
|
|
|
@ -10,12 +10,12 @@ namespace Web::HTML {
|
|||
|
||||
GC_DEFINE_ALLOCATOR(EnvironmentSettingsSnapshot);
|
||||
|
||||
EnvironmentSettingsSnapshot::EnvironmentSettingsSnapshot(NonnullOwnPtr<JS::ExecutionContext> execution_context, SerializedEnvironmentSettingsObject const& serialized_settings)
|
||||
EnvironmentSettingsSnapshot::EnvironmentSettingsSnapshot(JS::Realm& realm, NonnullOwnPtr<JS::ExecutionContext> 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)
|
||||
, m_policy_container(create_a_policy_container_from_serialized_policy_container(realm, serialized_settings.policy_container))
|
||||
, m_time_origin(serialized_settings.time_origin)
|
||||
{
|
||||
// Why can't we put these in the init list? grandparent class members are strange it seems
|
||||
|
@ -27,4 +27,10 @@ EnvironmentSettingsSnapshot::EnvironmentSettingsSnapshot(NonnullOwnPtr<JS::Execu
|
|||
// Out of line to ensure this class has a key function
|
||||
EnvironmentSettingsSnapshot::~EnvironmentSettingsSnapshot() = default;
|
||||
|
||||
void EnvironmentSettingsSnapshot::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_policy_container);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ class EnvironmentSettingsSnapshot final
|
|||
GC_DECLARE_ALLOCATOR(EnvironmentSettingsSnapshot);
|
||||
|
||||
public:
|
||||
EnvironmentSettingsSnapshot(NonnullOwnPtr<JS::ExecutionContext>, SerializedEnvironmentSettingsObject const&);
|
||||
EnvironmentSettingsSnapshot(JS::Realm&, NonnullOwnPtr<JS::ExecutionContext>, SerializedEnvironmentSettingsObject const&);
|
||||
|
||||
virtual ~EnvironmentSettingsSnapshot() override;
|
||||
|
||||
|
@ -26,15 +26,18 @@ public:
|
|||
String api_url_character_encoding() const override { return m_api_url_character_encoding; }
|
||||
URL::URL api_base_url() const override { return m_url; }
|
||||
URL::Origin origin() const override { return m_origin; }
|
||||
PolicyContainer policy_container() const override { return m_policy_container; }
|
||||
GC::Ref<PolicyContainer> policy_container() const override { return m_policy_container; }
|
||||
CanUseCrossOriginIsolatedAPIs cross_origin_isolated_capability() const override { return CanUseCrossOriginIsolatedAPIs::No; }
|
||||
double time_origin() const override { return m_time_origin; }
|
||||
|
||||
protected:
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
private:
|
||||
String m_api_url_character_encoding;
|
||||
URL::URL m_url;
|
||||
URL::Origin m_origin;
|
||||
HTML::PolicyContainer m_policy_container;
|
||||
GC::Ref<PolicyContainer> m_policy_container;
|
||||
double m_time_origin { 0 };
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2021-2025, Luke Wilde <luke@ladybird.org>
|
||||
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2022, networkException <networkexception@serenityos.org>
|
||||
* Copyright (c) 2024, Shannon Booth <shannon@serenityos.org>
|
||||
|
@ -565,7 +565,7 @@ SerializedEnvironmentSettingsObject EnvironmentSettingsObject::serialize()
|
|||
object.api_url_character_encoding = api_url_character_encoding();
|
||||
object.api_base_url = api_base_url();
|
||||
object.origin = origin();
|
||||
object.policy_container = policy_container();
|
||||
object.policy_container = policy_container()->serialize();
|
||||
object.cross_origin_isolated_capability = cross_origin_isolated_capability();
|
||||
|
||||
return object;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2021-2025, Luke Wilde <luke@ladybird.org>
|
||||
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2024, Shannon Booth <shannon@serenityos.org>
|
||||
*
|
||||
|
@ -83,7 +83,7 @@ public:
|
|||
virtual URL::Origin origin() const = 0;
|
||||
|
||||
// A policy container https://html.spec.whatwg.org/multipage/webappapis.html#concept-settings-object-policy-container
|
||||
virtual PolicyContainer policy_container() const = 0;
|
||||
virtual GC::Ref<PolicyContainer> policy_container() const = 0;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/webappapis.html#concept-settings-object-cross-origin-isolated-capability
|
||||
virtual CanUseCrossOriginIsolatedAPIs cross_origin_isolated_capability() const = 0;
|
||||
|
|
|
@ -39,7 +39,7 @@ ErrorOr<Web::HTML::SerializedEnvironmentSettingsObject> decode(Decoder& decoder)
|
|||
object.api_url_character_encoding = TRY(decoder.decode<String>());
|
||||
object.api_base_url = TRY(decoder.decode<URL::URL>());
|
||||
object.origin = TRY(decoder.decode<URL::Origin>());
|
||||
object.policy_container = TRY(decoder.decode<Web::HTML::PolicyContainer>());
|
||||
object.policy_container = TRY(decoder.decode<Web::HTML::SerializedPolicyContainer>());
|
||||
object.cross_origin_isolated_capability = TRY(decoder.decode<Web::HTML::CanUseCrossOriginIsolatedAPIs>());
|
||||
object.time_origin = TRY(decoder.decode<double>());
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include <LibIPC/Forward.h>
|
||||
#include <LibURL/Origin.h>
|
||||
#include <LibURL/URL.h>
|
||||
#include <LibWeb/HTML/PolicyContainers.h>
|
||||
#include <LibWeb/HTML/SerializedPolicyContainer.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
|
@ -28,7 +28,7 @@ struct SerializedEnvironmentSettingsObject {
|
|||
String api_url_character_encoding;
|
||||
URL::URL api_base_url;
|
||||
URL::Origin origin;
|
||||
PolicyContainer policy_container;
|
||||
SerializedPolicyContainer policy_container;
|
||||
CanUseCrossOriginIsolatedAPIs cross_origin_isolated_capability;
|
||||
double time_origin;
|
||||
};
|
||||
|
|
|
@ -111,7 +111,7 @@ URL::Origin WindowEnvironmentSettingsObject::origin() const
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/window-object.html#script-settings-for-window-objects:concept-settings-object-policy-container
|
||||
PolicyContainer WindowEnvironmentSettingsObject::policy_container() const
|
||||
GC::Ref<PolicyContainer> WindowEnvironmentSettingsObject::policy_container() const
|
||||
{
|
||||
// Return the policy container of window's associated Document.
|
||||
return m_window->associated_document().policy_container();
|
||||
|
|
|
@ -24,7 +24,7 @@ public:
|
|||
virtual String api_url_character_encoding() const override;
|
||||
virtual URL::URL api_base_url() const override;
|
||||
virtual URL::Origin origin() const override;
|
||||
virtual PolicyContainer policy_container() const override;
|
||||
virtual GC::Ref<PolicyContainer> policy_container() const override;
|
||||
virtual CanUseCrossOriginIsolatedAPIs cross_origin_isolated_capability() const override;
|
||||
virtual double time_origin() const override;
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ URL::Origin WorkerEnvironmentSettingsObject::origin() const
|
|||
return m_origin;
|
||||
}
|
||||
|
||||
PolicyContainer WorkerEnvironmentSettingsObject::policy_container() const
|
||||
GC::Ref<PolicyContainer> WorkerEnvironmentSettingsObject::policy_container() const
|
||||
{
|
||||
// Return worker global scope's policy container.
|
||||
return m_global_scope->policy_container();
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
String api_url_character_encoding() const override { return m_api_url_character_encoding; }
|
||||
URL::URL api_base_url() const override;
|
||||
URL::Origin origin() const override;
|
||||
PolicyContainer policy_container() const override;
|
||||
GC::Ref<PolicyContainer> policy_container() const override;
|
||||
CanUseCrossOriginIsolatedAPIs cross_origin_isolated_capability() const override;
|
||||
double time_origin() const override;
|
||||
|
||||
|
|
33
Libraries/LibWeb/HTML/SerializedPolicyContainer.cpp
Normal file
33
Libraries/LibWeb/HTML/SerializedPolicyContainer.cpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Luke Wilde <luke@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibIPC/Decoder.h>
|
||||
#include <LibIPC/Encoder.h>
|
||||
#include <LibWeb/HTML/SerializedPolicyContainer.h>
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template<>
|
||||
ErrorOr<void> encode(Encoder& encoder, Web::HTML::SerializedPolicyContainer const& serialized_policy_container)
|
||||
{
|
||||
TRY(encoder.encode(serialized_policy_container.embedder_policy));
|
||||
TRY(encoder.encode(serialized_policy_container.referrer_policy));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
template<>
|
||||
ErrorOr<Web::HTML::SerializedPolicyContainer> decode(Decoder& decoder)
|
||||
{
|
||||
Web::HTML::SerializedPolicyContainer serialized_policy_container {};
|
||||
|
||||
serialized_policy_container.embedder_policy = TRY(decoder.decode<Web::HTML::EmbedderPolicy>());
|
||||
serialized_policy_container.referrer_policy = TRY(decoder.decode<Web::ReferrerPolicy::ReferrerPolicy>());
|
||||
|
||||
return serialized_policy_container;
|
||||
}
|
||||
|
||||
}
|
29
Libraries/LibWeb/HTML/SerializedPolicyContainer.h
Normal file
29
Libraries/LibWeb/HTML/SerializedPolicyContainer.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Luke Wilde <luke@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/HTML/EmbedderPolicy.h>
|
||||
#include <LibWeb/ReferrerPolicy/ReferrerPolicy.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
struct SerializedPolicyContainer {
|
||||
EmbedderPolicy embedder_policy;
|
||||
ReferrerPolicy::ReferrerPolicy referrer_policy;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template<>
|
||||
ErrorOr<void> encode(Encoder&, Web::HTML::SerializedPolicyContainer const&);
|
||||
|
||||
template<>
|
||||
ErrorOr<Web::HTML::SerializedPolicyContainer> decode(Decoder&);
|
||||
|
||||
}
|
|
@ -18,6 +18,7 @@ void SessionHistoryEntry::visit_edges(Cell::Visitor& visitor)
|
|||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_document_state);
|
||||
visitor.visit(m_original_source_browsing_context);
|
||||
visitor.visit(m_policy_container);
|
||||
}
|
||||
|
||||
SessionHistoryEntry::SessionHistoryEntry()
|
||||
|
|
|
@ -69,8 +69,8 @@ public:
|
|||
[[nodiscard]] ScrollRestorationMode scroll_restoration_mode() const { return m_scroll_restoration_mode; }
|
||||
void set_scroll_restoration_mode(ScrollRestorationMode scroll_restoration_mode) { m_scroll_restoration_mode = scroll_restoration_mode; }
|
||||
|
||||
[[nodiscard]] Optional<PolicyContainer> const& policy_container() const { return m_policy_container; }
|
||||
void set_policy_container(Optional<PolicyContainer> policy_container) { m_policy_container = move(policy_container); }
|
||||
[[nodiscard]] GC::Ptr<PolicyContainer> policy_container() const { return m_policy_container; }
|
||||
void set_policy_container(GC::Ptr<PolicyContainer> policy_container) { m_policy_container = policy_container; }
|
||||
|
||||
[[nodiscard]] Optional<ByteString> const& browsing_context_name() const { return m_browsing_context_name; }
|
||||
void set_browsing_context_name(Optional<ByteString> browsing_context_name) { m_browsing_context_name = move(browsing_context_name); }
|
||||
|
@ -111,7 +111,7 @@ private:
|
|||
ScrollRestorationMode m_scroll_restoration_mode { ScrollRestorationMode::Auto };
|
||||
|
||||
// policy container, a policy container or null
|
||||
Optional<PolicyContainer> m_policy_container;
|
||||
GC::Ptr<PolicyContainer> m_policy_container;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#she-scroll-position
|
||||
// FIXME: scroll position data, which is scroll position data for the document's restorable scrollable regions
|
||||
|
|
22
Libraries/LibWeb/HTML/SourceSnapshotParams.cpp
Normal file
22
Libraries/LibWeb/HTML/SourceSnapshotParams.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Luke Wilde <luke@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/HTML/PolicyContainers.h>
|
||||
#include <LibWeb/HTML/Scripting/Environments.h>
|
||||
#include <LibWeb/HTML/SourceSnapshotParams.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
GC_DEFINE_ALLOCATOR(SourceSnapshotParams);
|
||||
|
||||
void SourceSnapshotParams::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(fetch_client);
|
||||
visitor.visit(source_policy_container);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
* Copyright (c) 2025, Luke Wilde <luke@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -12,7 +13,22 @@
|
|||
namespace Web::HTML {
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#source-snapshot-params
|
||||
struct SourceSnapshotParams {
|
||||
struct SourceSnapshotParams : public JS::Cell {
|
||||
GC_CELL(SourceSnapshotParams, JS::Cell)
|
||||
GC_DECLARE_ALLOCATOR(SourceSnapshotParams);
|
||||
|
||||
public:
|
||||
SourceSnapshotParams(bool has_transient_activation, SandboxingFlagSet sandboxing_flags, bool allows_downloading, GC::Ref<EnvironmentSettingsObject> fetch_client, GC::Ref<PolicyContainer> source_policy_container)
|
||||
: has_transient_activation(has_transient_activation)
|
||||
, sandboxing_flags(sandboxing_flags)
|
||||
, allows_downloading(allows_downloading)
|
||||
, fetch_client(fetch_client)
|
||||
, source_policy_container(source_policy_container)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~SourceSnapshotParams() = default;
|
||||
|
||||
// a boolean
|
||||
bool has_transient_activation;
|
||||
|
||||
|
@ -23,10 +39,13 @@ struct SourceSnapshotParams {
|
|||
bool allows_downloading;
|
||||
|
||||
// an environment settings object, only to be used as a request client
|
||||
GC::Ptr<EnvironmentSettingsObject> fetch_client;
|
||||
GC::Ref<EnvironmentSettingsObject> fetch_client;
|
||||
|
||||
// a policy container
|
||||
PolicyContainer source_policy_container;
|
||||
GC::Ref<PolicyContainer> source_policy_container;
|
||||
|
||||
protected:
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -438,7 +438,7 @@ GC_DEFINE_ALLOCATOR(ChangingNavigableContinuationState);
|
|||
TraversableNavigable::HistoryStepResult TraversableNavigable::apply_the_history_step(
|
||||
int step,
|
||||
bool check_for_cancelation,
|
||||
IGNORE_USE_IN_ESCAPING_LAMBDA Optional<SourceSnapshotParams> source_snapshot_params,
|
||||
GC::Ptr<SourceSnapshotParams> source_snapshot_params,
|
||||
GC::Ptr<Navigable> initiator_to_check,
|
||||
IGNORE_USE_IN_ESCAPING_LAMBDA UserNavigationInvolvement user_involvement,
|
||||
IGNORE_USE_IN_ESCAPING_LAMBDA Optional<Bindings::NavigationType> navigation_type,
|
||||
|
@ -456,7 +456,7 @@ TraversableNavigable::HistoryStepResult TraversableNavigable::apply_the_history_
|
|||
// 3. If initiatorToCheck is not null, then:
|
||||
if (initiator_to_check != nullptr) {
|
||||
// 1. Assert: sourceSnapshotParams is not null.
|
||||
VERIFY(source_snapshot_params.has_value());
|
||||
VERIFY(source_snapshot_params);
|
||||
|
||||
// 2. For each navigable of get all navigables whose current session history entry will change or reload:
|
||||
// if initiatorToCheck is not allowed by sandboxing to navigate navigable given sourceSnapshotParams, then return "initiator-disallowed".
|
||||
|
@ -628,10 +628,10 @@ TraversableNavigable::HistoryStepResult TraversableNavigable::apply_the_history_
|
|||
auto target_snapshot_params = navigable->snapshot_target_snapshot_params();
|
||||
|
||||
// 3. Let potentiallyTargetSpecificSourceSnapshotParams be sourceSnapshotParams.
|
||||
Optional<SourceSnapshotParams> potentially_target_specific_source_snapshot_params = source_snapshot_params;
|
||||
GC::Ptr<SourceSnapshotParams> potentially_target_specific_source_snapshot_params = source_snapshot_params;
|
||||
|
||||
// 4. If potentiallyTargetSpecificSourceSnapshotParams is null, then set it to the result of snapshotting source snapshot params given navigable's active document.
|
||||
if (!potentially_target_specific_source_snapshot_params.has_value()) {
|
||||
if (!potentially_target_specific_source_snapshot_params) {
|
||||
potentially_target_specific_source_snapshot_params = navigable->active_document()->snapshot_source_snapshot_params();
|
||||
}
|
||||
|
||||
|
@ -1134,17 +1134,17 @@ bool TraversableNavigable::can_go_forward() const
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#traverse-the-history-by-a-delta
|
||||
void TraversableNavigable::traverse_the_history_by_delta(int delta, Optional<DOM::Document&> source_document)
|
||||
void TraversableNavigable::traverse_the_history_by_delta(int delta, GC::Ptr<DOM::Document> source_document)
|
||||
{
|
||||
// 1. Let sourceSnapshotParams and initiatorToCheck be null.
|
||||
Optional<SourceSnapshotParams> source_snapshot_params = {};
|
||||
GC::Ptr<SourceSnapshotParams> source_snapshot_params = nullptr;
|
||||
GC::Ptr<Navigable> initiator_to_check = nullptr;
|
||||
|
||||
// 2. Let userInvolvement be "browser UI".
|
||||
UserNavigationInvolvement user_involvement = UserNavigationInvolvement::BrowserUI;
|
||||
|
||||
// 1. If sourceDocument is given, then:
|
||||
if (source_document.has_value()) {
|
||||
if (source_document) {
|
||||
// 1. Set sourceSnapshotParams to the result of snapshotting source snapshot params given sourceDocument.
|
||||
source_snapshot_params = source_document->snapshot_source_snapshot_params();
|
||||
|
||||
|
@ -1156,7 +1156,7 @@ void TraversableNavigable::traverse_the_history_by_delta(int delta, Optional<DOM
|
|||
}
|
||||
|
||||
// 4. Append the following session history traversal steps to traversable:
|
||||
append_session_history_traversal_steps(GC::create_function(heap(), [this, delta, source_snapshot_params = move(source_snapshot_params), initiator_to_check, user_involvement] {
|
||||
append_session_history_traversal_steps(GC::create_function(heap(), [this, delta, source_snapshot_params, initiator_to_check, user_involvement] {
|
||||
// 1. Let allSteps be the result of getting all used history steps for traversable.
|
||||
auto all_steps = get_all_used_history_steps();
|
||||
|
||||
|
@ -1205,10 +1205,10 @@ TraversableNavigable::HistoryStepResult TraversableNavigable::apply_the_push_or_
|
|||
return apply_the_history_step(step, false, {}, {}, user_involvement, navigation_type, synchronous_navigation);
|
||||
}
|
||||
|
||||
TraversableNavigable::HistoryStepResult TraversableNavigable::apply_the_traverse_history_step(int step, Optional<SourceSnapshotParams> source_snapshot_params, GC::Ptr<Navigable> initiator_to_check, UserNavigationInvolvement user_involvement)
|
||||
TraversableNavigable::HistoryStepResult TraversableNavigable::apply_the_traverse_history_step(int step, GC::Ptr<SourceSnapshotParams> source_snapshot_params, GC::Ptr<Navigable> initiator_to_check, UserNavigationInvolvement user_involvement)
|
||||
{
|
||||
// 1. Return the result of applying the history step step to traversable given true, sourceSnapshotParams, initiatorToCheck, userInvolvement, and "traverse".
|
||||
return apply_the_history_step(step, true, move(source_snapshot_params), initiator_to_check, user_involvement, Bindings::NavigationType::Traverse, SynchronousNavigation::No);
|
||||
return apply_the_history_step(step, true, source_snapshot_params, initiator_to_check, user_involvement, Bindings::NavigationType::Traverse, SynchronousNavigation::No);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/document-sequences.html#close-a-top-level-traversable
|
||||
|
|
|
@ -60,7 +60,7 @@ public:
|
|||
Applied,
|
||||
};
|
||||
|
||||
HistoryStepResult apply_the_traverse_history_step(int, Optional<SourceSnapshotParams>, GC::Ptr<Navigable>, UserNavigationInvolvement);
|
||||
HistoryStepResult apply_the_traverse_history_step(int, GC::Ptr<SourceSnapshotParams>, GC::Ptr<Navigable>, UserNavigationInvolvement);
|
||||
HistoryStepResult apply_the_reload_history_step(UserNavigationInvolvement);
|
||||
enum class SynchronousNavigation : bool {
|
||||
Yes,
|
||||
|
@ -76,7 +76,7 @@ public:
|
|||
|
||||
Vector<int> get_all_used_history_steps() const;
|
||||
void clear_the_forward_session_history();
|
||||
void traverse_the_history_by_delta(int delta, Optional<DOM::Document&> source_document = {});
|
||||
void traverse_the_history_by_delta(int delta, GC::Ptr<DOM::Document> source_document = {});
|
||||
|
||||
void close_top_level_traversable();
|
||||
void definitely_close_top_level_traversable();
|
||||
|
@ -125,7 +125,7 @@ private:
|
|||
HistoryStepResult apply_the_history_step(
|
||||
int step,
|
||||
bool check_for_cancelation,
|
||||
Optional<SourceSnapshotParams>,
|
||||
GC::Ptr<SourceSnapshotParams>,
|
||||
GC::Ptr<Navigable> initiator_to_check,
|
||||
UserNavigationInvolvement user_involvement,
|
||||
Optional<Bindings::NavigationType> navigation_type,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
|
||||
* Copyright (c) 2025, Luke Wilde <luke@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -52,6 +53,7 @@ void WorkerGlobalScope::visit_edges(Cell::Visitor& visitor)
|
|||
visitor.visit(m_internal_port);
|
||||
visitor.visit(m_page);
|
||||
visitor.visit(m_fonts);
|
||||
visitor.visit(m_policy_container);
|
||||
}
|
||||
|
||||
void WorkerGlobalScope::finalize()
|
||||
|
@ -165,4 +167,13 @@ GC::Ref<CSS::FontFaceSet> WorkerGlobalScope::fonts()
|
|||
return *m_fonts;
|
||||
}
|
||||
|
||||
GC::Ref<PolicyContainer> WorkerGlobalScope::policy_container() const
|
||||
{
|
||||
auto& realm = this->realm();
|
||||
if (!m_policy_container) {
|
||||
m_policy_container = realm.create<PolicyContainer>(realm);
|
||||
}
|
||||
return *m_policy_container;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
|
||||
* Copyright (c) 2025, Luke Wilde <luke@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -92,7 +93,7 @@ public:
|
|||
|
||||
Web::Page* page() { return m_page.ptr(); }
|
||||
|
||||
PolicyContainer policy_container() const { return m_policy_container; }
|
||||
GC::Ref<PolicyContainer> policy_container() const;
|
||||
|
||||
bool is_closing() const { return m_closing; }
|
||||
|
||||
|
@ -137,7 +138,7 @@ private:
|
|||
|
||||
// https://html.spec.whatwg.org/multipage/workers.html#concept-workerglobalscope-policy-container
|
||||
// A WorkerGlobalScope object has an associated policy container (a policy container). It is initially a new policy container.
|
||||
PolicyContainer m_policy_container;
|
||||
mutable GC::Ptr<PolicyContainer> m_policy_container;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/workers.html#concept-workerglobalscope-embedder-policy
|
||||
// A WorkerGlobalScope object has an associated embedder policy (an embedder policy).
|
||||
|
|
|
@ -40,7 +40,7 @@ ErrorOr<GC::Ref<SVGDecodedImageData>> SVGDecodedImageData::create(JS::Realm& rea
|
|||
navigation_params->navigable = navigable;
|
||||
navigation_params->response = response;
|
||||
navigation_params->origin = URL::Origin {};
|
||||
navigation_params->policy_container = HTML::PolicyContainer {};
|
||||
navigation_params->policy_container = navigable->heap().allocate<HTML::PolicyContainer>(navigable->active_document()->realm());
|
||||
navigation_params->final_sandboxing_flag_set = HTML::SandboxingFlagSet {};
|
||||
navigation_params->opener_policy = HTML::OpenerPolicy {};
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ void DedicatedWorkerHost::run(GC::Ref<Web::Page> page, Web::HTML::TransferDataHo
|
|||
// 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->realm().create<Web::HTML::EnvironmentSettingsSnapshot>(inner_settings->realm_execution_context().copy(), outside_settings_snapshot);
|
||||
auto outside_settings = inner_settings->realm().create<Web::HTML::EnvironmentSettingsSnapshot>(inner_settings->realm(), inner_settings->realm_execution_context().copy(), outside_settings_snapshot);
|
||||
|
||||
// 12. If is shared is true, then:
|
||||
if (is_shared) {
|
||||
|
|
Loading…
Add table
Reference in a new issue