mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-10-03 14:50:02 +00:00
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).
This commit is contained in:
parent
681e4e5d01
commit
70cafc558e
Notes:
github-actions[bot]
2025-08-08 10:14:14 +00:00
Author: https://github.com/kennethmyhra
Commit: 70cafc558e
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5771
Reviewed-by: https://github.com/AtkinsSJ ✅
5 changed files with 41 additions and 38 deletions
|
@ -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
|
||||
|
|
|
@ -132,12 +132,12 @@ WebIDL::ExceptionOr<GC::Ref<Infrastructure::FetchController>> 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<Infrastructure::Request::Window>();
|
||||
if (window && *window == Infrastructure::Request::Window::Client) {
|
||||
auto const* window = request.traversable_for_user_prompts().get_pointer<Infrastructure::Request::TraversableForUserPrompts>();
|
||||
if (window && *window == Infrastructure::Request::TraversableForUserPrompts::Client) {
|
||||
if (is<HTML::Window>(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<GC::Ref<Infrastructure::FetchController>> 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<GC::Ptr<HTML::EnvironmentSettingsObject>>()
|
||||
&& request.traversable_for_user_prompts().has<GC::Ptr<HTML::EnvironmentSettingsObject>>()
|
||||
// - 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<GC::Ref<PendingResponse>> 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<Infrastructure::Request::Window>()
|
||||
&& request->window().get<Infrastructure::Request::Window>() == 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<Infrastructure::Request::TraversableForUserPrompts>()
|
||||
&& request->traversable_for_user_prompts().get<Infrastructure::Request::TraversableForUserPrompts>() == 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<GC::Ref<PendingResponse>> 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<GC::Ptr<HTML::EnvironmentSettingsObject>>()
|
||||
&& request->traversable_for_user_prompts().has<GC::Ptr<HTML::TraversableNavigable>>()
|
||||
// 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<GC::Ref<PendingResponse>> 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<Infrastructure::Request::Window>()
|
||||
&& request->window().get<Infrastructure::Request::Window>() == 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<Infrastructure::Request::TraversableForUserPrompts>()
|
||||
&& request->traversable_for_user_prompts().get<Infrastructure::Request::TraversableForUserPrompts>() == Infrastructure::Request::TraversableForUserPrompts::NoTraversable) {
|
||||
returned_pending_response->resolve(Infrastructure::Response::network_error(vm, "Request requires proxy authentication but has 'no-window' set"_string));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <LibWeb/DOMURL/DOMURL.h>
|
||||
#include <LibWeb/Fetch/Fetching/PendingResponse.h>
|
||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
||||
#include <LibWeb/HTML/TraversableNavigable.h>
|
||||
|
||||
namespace Web::Fetch::Infrastructure {
|
||||
|
||||
|
@ -32,8 +33,9 @@ void Request::visit_edges(JS::Cell::Visitor& visitor)
|
|||
[&](GC::Ref<Body>& body) { visitor.visit(body); },
|
||||
[](auto&) {});
|
||||
visitor.visit(m_reserved_client);
|
||||
m_window.visit(
|
||||
m_traversable_for_user_prompts.visit(
|
||||
[&](GC::Ptr<HTML::EnvironmentSettingsObject> const& value) { visitor.visit(value); },
|
||||
[&](GC::Ptr<HTML::TraversableNavigable> const& value) { visitor.visit(value); },
|
||||
[](auto const&) {});
|
||||
visitor.visit(m_pending_responses);
|
||||
m_policy_container.visit(
|
||||
|
@ -226,7 +228,7 @@ GC::Ref<Request> 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);
|
||||
|
|
|
@ -147,8 +147,8 @@ public:
|
|||
None,
|
||||
};
|
||||
|
||||
enum class Window {
|
||||
NoWindow,
|
||||
enum class TraversableForUserPrompts {
|
||||
NoTraversable,
|
||||
Client,
|
||||
};
|
||||
|
||||
|
@ -173,7 +173,7 @@ public:
|
|||
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>>;
|
||||
using TraversableForUserPromptsType = Variant<TraversableForUserPrompts, GC::Ptr<HTML::EnvironmentSettingsObject>, GC::Ptr<HTML::TraversableNavigable>>;
|
||||
|
||||
[[nodiscard]] static GC::Ref<Request> 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.
|
||||
|
|
|
@ -153,23 +153,24 @@ WebIDL::ExceptionOr<GC::Ref<Request>> 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<GC::Ptr<HTML::EnvironmentSettingsObject>>()) {
|
||||
auto eso = input_request->window().get<GC::Ptr<HTML::EnvironmentSettingsObject>>();
|
||||
// 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<GC::Ptr<HTML::EnvironmentSettingsObject>>()) {
|
||||
auto eso = input_request->traversable_for_user_prompts().get<GC::Ptr<HTML::EnvironmentSettingsObject>>();
|
||||
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<GC::Ref<Request>> 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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue