From 70cafc558ec3a27114f11c45f817bdf94f296275 Mon Sep 17 00:00:00 2001 From: Kenneth Myhra Date: Thu, 7 Aug 2025 10:54:40 +0200 Subject: [PATCH] LibWeb: Replace request's "window" with "traversable for user prompts" User prompts are not tied to specific Windows or the client's Window. They are tied to a traversable navigable (browser tab). --- .../ContentSecurityPolicy/Violation.cpp | 6 ++-- Libraries/LibWeb/Fetch/Fetching/Fetching.cpp | 28 +++++++++---------- .../Fetch/Infrastructure/HTTP/Requests.cpp | 6 ++-- .../Fetch/Infrastructure/HTTP/Requests.h | 16 +++++------ Libraries/LibWeb/Fetch/Request.cpp | 23 +++++++-------- 5 files changed, 41 insertions(+), 38 deletions(-) diff --git a/Libraries/LibWeb/ContentSecurityPolicy/Violation.cpp b/Libraries/LibWeb/ContentSecurityPolicy/Violation.cpp index 5eb9b7d831d..577630fd785 100644 --- a/Libraries/LibWeb/ContentSecurityPolicy/Violation.cpp +++ b/Libraries/LibWeb/ContentSecurityPolicy/Violation.cpp @@ -421,9 +421,9 @@ void Violation::report_a_violation(JS::Realm& realm) auto& environment_settings_object = Bindings::principal_host_defined_environment_settings_object(HTML::principal_realm(realm)); request->set_origin(environment_settings_object.origin()); - // window - // "no-window" - request->set_window(Fetch::Infrastructure::Request::Window::NoWindow); + // traversable for user prompts + // "no-traversable" + request->set_traversable_for_user_prompts(Fetch::Infrastructure::Request::TraversableForUserPrompts::NoTraversable); // client // violation's global object's relevant settings object diff --git a/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp b/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp index 74017a87999..016ec0cb363 100644 --- a/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp +++ b/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp @@ -132,12 +132,12 @@ WebIDL::ExceptionOr> fetch(JS::Realm& r // 9. If request’s window is "client", then set request’s window to request’s client, if request’s client’s global // object is a Window object; otherwise "no-window". - auto const* window = request.window().get_pointer(); - if (window && *window == Infrastructure::Request::Window::Client) { + auto const* window = request.traversable_for_user_prompts().get_pointer(); + if (window && *window == Infrastructure::Request::TraversableForUserPrompts::Client) { if (is(request.client()->global_object())) { - request.set_window(request.client()); + request.set_traversable_for_user_prompts(request.client()); } else { - request.set_window(Infrastructure::Request::Window::NoWindow); + request.set_traversable_for_user_prompts(Infrastructure::Request::TraversableForUserPrompts::NoTraversable); } } @@ -153,7 +153,7 @@ WebIDL::ExceptionOr> fetch(JS::Realm& r // - request’s mode is "same-origin", "cors", or "no-cors" && (request.mode() == Infrastructure::Request::Mode::SameOrigin || request.mode() == Infrastructure::Request::Mode::CORS || request.mode() == Infrastructure::Request::Mode::NoCORS) // - request’s window is an environment settings object - && request.window().has>() + && request.traversable_for_user_prompts().has>() // - request’s method is `GET` && StringView { request.method() }.equals_ignoring_ascii_case("GET"sv) // - request’s unsafe-request flag is not set or request’s header list is empty @@ -1707,10 +1707,10 @@ WebIDL::ExceptionOr> http_network_or_cache_fetch(JS::Re aborted = true; }; - // 1. If request’s window is "no-window" and request’s redirect mode is "error", then set httpFetchParams to - // fetchParams and httpRequest to request. - if (request->window().has() - && request->window().get() == Infrastructure::Request::Window::NoWindow + // 1. If request’s traversable for user prompts is "no-traversable" and request’s redirect mode is "error", + // then set httpFetchParams to fetchParams and httpRequest to request. + if (request->traversable_for_user_prompts().has() + && request->traversable_for_user_prompts().get() == Infrastructure::Request::TraversableForUserPrompts::NoTraversable && request->redirect_mode() == Infrastructure::Request::RedirectMode::Error) { http_fetch_params = fetch_params; http_request = request; @@ -2123,11 +2123,11 @@ WebIDL::ExceptionOr> http_network_or_cache_fetch(JS::Re auto inner_pending_response = PendingResponse::create(vm, request, *response); // 14. If response’s status is 401, httpRequest’s response tainting is not "cors", includeCredentials is true, - // and request’s window is an environment settings object, then: + // and request’s traversable for user prompts is a traversable navigable: if (response->status() == 401 && http_request->response_tainting() != Infrastructure::Request::ResponseTainting::CORS && include_credentials == IncludeCredentials::Yes - && request->window().has>() + && request->traversable_for_user_prompts().has>() // AD-HOC: Require at least one WWW-Authenticate header to be set before automatically retrying an authenticated // request (see rule 1 below). See: https://github.com/whatwg/fetch/issues/1766 && request->header_list()->contains("WWW-Authenticate"sv.bytes())) { @@ -2181,9 +2181,9 @@ WebIDL::ExceptionOr> http_network_or_cache_fetch(JS::Re dbgln_if(WEB_FETCH_DEBUG, "Fetch: Running 'HTTP network-or-cache fetch' inner_pending_response load callback"); // 15. If response’s status is 407, then: if (response->status() == 407) { - // 1. If request’s window is "no-window", then return a network error. - if (request->window().has() - && request->window().get() == Infrastructure::Request::Window::NoWindow) { + // 1. If request’s traversable for user prompts is "no-traversable", then return a network error. + if (request->traversable_for_user_prompts().has() + && request->traversable_for_user_prompts().get() == Infrastructure::Request::TraversableForUserPrompts::NoTraversable) { returned_pending_response->resolve(Infrastructure::Response::network_error(vm, "Request requires proxy authentication but has 'no-window' set"_string)); return; } diff --git a/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Requests.cpp b/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Requests.cpp index 4febb443950..d4ba72541f5 100644 --- a/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Requests.cpp +++ b/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Requests.cpp @@ -13,6 +13,7 @@ #include #include #include +#include namespace Web::Fetch::Infrastructure { @@ -32,8 +33,9 @@ void Request::visit_edges(JS::Cell::Visitor& visitor) [&](GC::Ref& body) { visitor.visit(body); }, [](auto&) {}); visitor.visit(m_reserved_client); - m_window.visit( + m_traversable_for_user_prompts.visit( [&](GC::Ptr const& value) { visitor.visit(value); }, + [&](GC::Ptr const& value) { visitor.visit(value); }, [](auto const&) {}); visitor.visit(m_pending_responses); m_policy_container.visit( @@ -226,7 +228,7 @@ GC::Ref Request::clone(JS::Realm& realm) const new_request->set_client(m_client); new_request->set_reserved_client(m_reserved_client); new_request->set_replaces_client_id(m_replaces_client_id); - new_request->set_window(m_window); + new_request->set_traversable_for_user_prompts(m_traversable_for_user_prompts); new_request->set_keepalive(m_keepalive); new_request->set_initiator_type(m_initiator_type); new_request->set_service_workers_mode(m_service_workers_mode); diff --git a/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Requests.h b/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Requests.h index 3dda56d1068..c0261d685d4 100644 --- a/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Requests.h +++ b/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Requests.h @@ -147,8 +147,8 @@ public: None, }; - enum class Window { - NoWindow, + enum class TraversableForUserPrompts { + NoTraversable, Client, }; @@ -173,7 +173,7 @@ public: using PolicyContainerType = Variant>; using ReferrerType = Variant; using ReservedClientType = GC::Ptr; - using WindowType = Variant>; + using TraversableForUserPromptsType = Variant, GC::Ptr>; [[nodiscard]] static GC::Ref create(JS::VM&); @@ -204,8 +204,8 @@ public: [[nodiscard]] String const& replaces_client_id() const { return m_replaces_client_id; } void set_replaces_client_id(String replaces_client_id) { m_replaces_client_id = move(replaces_client_id); } - [[nodiscard]] WindowType const& window() const { return m_window; } - void set_window(WindowType window) { m_window = move(window); } + [[nodiscard]] TraversableForUserPromptsType const& traversable_for_user_prompts() const { return m_traversable_for_user_prompts; } + void set_traversable_for_user_prompts(TraversableForUserPromptsType traversable_for_user_prompts) { m_traversable_for_user_prompts = move(traversable_for_user_prompts); } [[nodiscard]] bool keepalive() const { return m_keepalive; } void set_keepalive(bool keepalive) { m_keepalive = keepalive; } @@ -373,9 +373,9 @@ private: String m_replaces_client_id; // https://fetch.spec.whatwg.org/#concept-request-window - // A request has an associated window ("no-window", "client", or an environment settings object whose global object - // is a Window object). Unless stated otherwise it is "client". - WindowType m_window { Window::Client }; + // A request has an associated traversable for user prompts, that is "no-traversable", "client", or a traversable + // navigable. Unless stated otherwise it is "client". + TraversableForUserPromptsType m_traversable_for_user_prompts { TraversableForUserPrompts::Client }; // https://fetch.spec.whatwg.org/#request-keepalive-flag // A request has an associated boolean keepalive. Unless stated otherwise it is false. diff --git a/Libraries/LibWeb/Fetch/Request.cpp b/Libraries/LibWeb/Fetch/Request.cpp index a3631311adf..422424f0aa4 100644 --- a/Libraries/LibWeb/Fetch/Request.cpp +++ b/Libraries/LibWeb/Fetch/Request.cpp @@ -153,23 +153,24 @@ WebIDL::ExceptionOr> Request::construct_impl(JS::Realm& realm, // 7. Let origin be this’s relevant settings object’s origin. auto const& origin = HTML::relevant_settings_object(*request_object).origin(); - // 8. Let window be "client". - auto window = Infrastructure::Request::WindowType { Infrastructure::Request::Window::Client }; + // 8. Let traversableForUserPrompts be "client". + auto traversable_for_user_prompts = Infrastructure::Request::TraversableForUserPromptsType { Infrastructure::Request::TraversableForUserPrompts::Client }; - // 9. If request’s window is an environment settings object and its origin is same origin with origin, then set window to request’s window. - if (input_request->window().has>()) { - auto eso = input_request->window().get>(); + // 9. If request’s traversable for user prompts is an environment settings object and its origin is same origin with + // origin, then set traversableForUserPrompts to request’s traversable for user prompts. + if (input_request->traversable_for_user_prompts().has>()) { + auto eso = input_request->traversable_for_user_prompts().get>(); if (eso->origin().is_same_origin(origin)) - window = input_request->window(); + traversable_for_user_prompts = input_request->traversable_for_user_prompts(); } // 10. If init["window"] exists and is non-null, then throw a TypeError. if (init.window.has_value() && !init.window->is_null()) return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "The 'window' property must be omitted or null"sv }; - // 11. If init["window"] exists, then set window to "no-window". + // 11. If init["window"] exists, then set traversableForUserPrompts to "no-traversable". if (init.window.has_value()) - window = Infrastructure::Request::Window::NoWindow; + traversable_for_user_prompts = Infrastructure::Request::TraversableForUserPrompts::NoTraversable; // 12. Set request to a new request with the following properties: // NOTE: This is done at the beginning as the 'this' value Request object @@ -199,9 +200,9 @@ WebIDL::ExceptionOr> Request::construct_impl(JS::Realm& realm, // This’s relevant settings object. request->set_client(&HTML::relevant_settings_object(*request_object)); - // window - // window. - request->set_window(window); + // traversable for user prompts + // traversableForUserPrompts. + request->set_traversable_for_user_prompts(traversable_for_user_prompts); // priority // request’s priority.