diff --git a/blink/public/mojom/fetch/fetch_api_request.mojom b/blink/public/mojom/fetch/fetch_api_request.mojom index 8e30381eef67..e952c541d5b1 100644 --- a/blink/public/mojom/fetch/fetch_api_request.mojom +++ b/blink/public/mojom/fetch/fetch_api_request.mojom @@ -14,6 +14,7 @@ import "services/network/public/mojom/url_request.mojom"; import "third_party/blink/public/mojom/blob/serialized_blob.mojom"; import "third_party/blink/public/mojom/loader/request_context_frame_type.mojom"; import "third_party/blink/public/mojom/loader/referrer.mojom"; +import "url/mojom/origin.mojom"; import "url/mojom/url.mojom"; @@ -162,6 +163,14 @@ struct FetchAPIRequest { SerializedBlob? blob; FetchAPIRequestBody? body; + // `request_initiator` indicates the origin that initiated the request. See + // also `network::ResourceRequest::request_initiator`, and the doc comment + // for `request_initiator` in services/network/public/mojom/url_request.mojom. + // + // Note that the origin may be missing for browser-initiated navigations + // (e.g. ones initiated from the Omnibox). + url.mojom.Origin? request_initiator; + Referrer? referrer; network.mojom.CredentialsMode credentials_mode = network.mojom.CredentialsMode.kOmit; diff --git a/blink/renderer/core/fetch/fetch_manager.cc b/blink/renderer/core/fetch/fetch_manager.cc index 325d96a1453d..e9e099c26167 100644 --- a/blink/renderer/core/fetch/fetch_manager.cc +++ b/blink/renderer/core/fetch/fetch_manager.cc @@ -762,22 +762,7 @@ void FetchManager::Loader::PerformHTTPFetch() { request.SetHttpMethod(fetch_request_data_->Method()); request.SetFetchWindowId(fetch_request_data_->WindowId()); request.SetTrustTokenParams(fetch_request_data_->TrustTokenParams()); - - switch (fetch_request_data_->Mode()) { - case RequestMode::kSameOrigin: - case RequestMode::kNoCors: - case RequestMode::kCors: - case RequestMode::kCorsWithForcedPreflight: - request.SetMode(fetch_request_data_->Mode()); - break; - case RequestMode::kNavigate: - // NetworkService (i.e. CorsURLLoaderFactory::IsSane) rejects kNavigate - // requests coming from renderers, so using kSameOrigin here. - // TODO(lukasza): Tweak CorsURLLoaderFactory::IsSane to accept kNavigate - // if request_initiator and the target are same-origin. - request.SetMode(RequestMode::kSameOrigin); - break; - } + request.SetMode(fetch_request_data_->Mode()); request.SetCredentialsMode(fetch_request_data_->Credentials()); for (const auto& header : fetch_request_data_->HeaderList()->List()) { @@ -825,6 +810,8 @@ void FetchManager::Loader::PerformHTTPFetch() { UseCounter::Count(execution_context_, mojom::WebFeature::kFetchKeepalive); } + request.SetOriginalDestination(fetch_request_data_->OriginalDestination()); + // "3. Append `Host`, ..." // FIXME: Implement this when the spec is fixed. diff --git a/blink/renderer/core/fetch/fetch_request_data.cc b/blink/renderer/core/fetch/fetch_request_data.cc index 7e569ba2100a..314d379cee83 100644 --- a/blink/renderer/core/fetch/fetch_request_data.cc +++ b/blink/renderer/core/fetch/fetch_request_data.cc @@ -164,6 +164,8 @@ FetchRequestData* FetchRequestData::Create( // we deprecate SetContext. request->SetDestination(fetch_api_request->destination); + if (fetch_api_request->request_initiator) + request->SetOrigin(fetch_api_request->request_initiator); request->SetReferrerString(AtomicString(Referrer::NoReferrer())); if (fetch_api_request->referrer) { if (!fetch_api_request->referrer->url.IsEmpty()) { @@ -184,6 +186,7 @@ FetchRequestData* FetchRequestData::Create( fetch_api_request->priority)); if (fetch_api_request->fetch_window_id) request->SetWindowId(fetch_api_request->fetch_window_id.value()); + return request; } @@ -205,6 +208,7 @@ FetchRequestData* FetchRequestData::CloneExceptBody() { request->integrity_ = integrity_; request->priority_ = priority_; request->importance_ = importance_; + request->original_destination_ = original_destination_; request->keepalive_ = keepalive_; request->is_history_navigation_ = is_history_navigation_; request->window_id_ = window_id_; diff --git a/blink/renderer/core/fetch/fetch_request_data.h b/blink/renderer/core/fetch/fetch_request_data.h index 02b690998d3a..3465196f0856 100644 --- a/blink/renderer/core/fetch/fetch_request_data.h +++ b/blink/renderer/core/fetch/fetch_request_data.h @@ -108,6 +108,15 @@ class CORE_EXPORT FetchRequestData final void SetIntegrity(const String& integrity) { integrity_ = integrity; } ResourceLoadPriority Priority() const { return priority_; } void SetPriority(ResourceLoadPriority priority) { priority_ = priority; } + + // The original destination of a request passed through by a service worker. + void SetOriginalDestination(network::mojom::RequestDestination value) { + original_destination_ = value; + } + network::mojom::RequestDestination OriginalDestination() const { + return original_destination_; + } + bool Keepalive() const { return keepalive_; } void SetKeepalive(bool b) { keepalive_ = b; } bool IsHistoryNavigation() const { return is_history_navigation_; } @@ -174,6 +183,8 @@ class CORE_EXPORT FetchRequestData final String mime_type_; String integrity_; ResourceLoadPriority priority_; + network::mojom::RequestDestination original_destination_ = + network::mojom::RequestDestination::kEmpty; bool keepalive_; bool is_history_navigation_ = false; // A specific factory that should be used for this request instead of whatever diff --git a/blink/renderer/core/fetch/request.cc b/blink/renderer/core/fetch/request.cc index 9cf7fe8c1159..8421ed69d094 100644 --- a/blink/renderer/core/fetch/request.cc +++ b/blink/renderer/core/fetch/request.cc @@ -70,7 +70,8 @@ FetchRequestData* CreateCopyOfFetchRequestDataForFetch( request->SetURL(original->Url()); request->SetMethod(original->Method()); request->SetHeaderList(original->HeaderList()->Clone()); - request->SetOrigin(context->GetSecurityOrigin()); + request->SetOrigin(original->Origin() ? original->Origin() + : context->GetSecurityOrigin()); // FIXME: Set client. DOMWrapperWorld& world = script_state->World(); if (world.IsIsolatedWorld()) { @@ -97,6 +98,18 @@ FetchRequestData* CreateCopyOfFetchRequestDataForFetch( } request->SetWindowId(original->WindowId()); request->SetTrustTokenParams(original->TrustTokenParams()); + + // When a new request is created from another the destination is always reset + // to be `kEmpty`. In order to facilitate some later checks when a service + // worker forwards a navigation request we want to keep track of the + // destination of the original request. Therefore record the original + // request's destination if its non-empty, otherwise just carry forward + // whatever "original destination" value was already set. + if (original->Destination() != network::mojom::RequestDestination::kEmpty) + request->SetOriginalDestination(original->Destination()); + else + request->SetOriginalDestination(original->OriginalDestination()); + return request; } @@ -319,6 +332,9 @@ Request* Request::CreateRequestWithRequestOrString( // "If any of |init|'s members are present, then:" if (AreAnyMembersPresent(init)) { + request->SetOrigin(execution_context->GetSecurityOrigin()); + request->SetOriginalDestination(network::mojom::RequestDestination::kEmpty); + // "If |request|'s |mode| is "navigate", then set it to "same-origin". if (request->Mode() == network::mojom::RequestMode::kNavigate) request->SetMode(network::mojom::RequestMode::kSameOrigin); @@ -982,6 +998,7 @@ mojom::blink::FetchAPIRequestPtr Request::CreateFetchAPIRequest() const { fetch_api_request->integrity = request_->Integrity(); fetch_api_request->is_history_navigation = request_->IsHistoryNavigation(); fetch_api_request->destination = request_->Destination(); + fetch_api_request->request_initiator = request_->Origin(); // Strip off the fragment part of URL. So far, all callers expect the fragment // to be excluded. diff --git a/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc b/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc index 3ae614067408..cad84d21d03e 100644 --- a/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc +++ b/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc @@ -268,11 +268,12 @@ class ResponsesAccumulator : public RefCounted { auto request_clone_without_body = mojom::blink::FetchAPIRequest::New( request->mode, request->is_main_resource_load, request->destination, request->frame_type, request->url, request->method, request->headers, - nullptr /* blob */, ResourceRequestBody(), request->referrer.Clone(), - request->credentials_mode, request->cache_mode, - request->redirect_mode, request->integrity, request->priority, - request->fetch_window_id, request->keepalive, request->is_reload, - request->is_history_navigation, request->devtools_stack_id); + nullptr /* blob */, ResourceRequestBody(), request->request_initiator, + request->referrer.Clone(), request->credentials_mode, + request->cache_mode, request->redirect_mode, request->integrity, + request->priority, request->fetch_window_id, request->keepalive, + request->is_reload, request->is_history_navigation, + request->devtools_stack_id); cache_remote_->Match( std::move(request), mojom::blink::CacheQueryOptions::New(), /*in_related_fetch_event=*/false, /*in_range_fetch_event=*/false, diff --git a/blink/renderer/platform/loader/fetch/resource_request.h b/blink/renderer/platform/loader/fetch/resource_request.h index 172797442ce1..fbc30546d6ce 100644 --- a/blink/renderer/platform/loader/fetch/resource_request.h +++ b/blink/renderer/platform/loader/fetch/resource_request.h @@ -513,6 +513,14 @@ class PLATFORM_EXPORT ResourceRequestHead { return allowHTTP1ForStreamingUpload_; } + // The original destination of a request passed through by a service worker. + network::mojom::RequestDestination GetOriginalDestination() const { + return original_destination_; + } + void SetOriginalDestination(network::mojom::RequestDestination value) { + original_destination_ = value; + } + const absl::optional& GetWebBundleTokenParams() const { return web_bundle_token_params_; @@ -603,6 +611,9 @@ class PLATFORM_EXPORT ResourceRequestHead { base::UnguessableToken fetch_window_id_; + network::mojom::RequestDestination original_destination_ = + network::mojom::RequestDestination::kEmpty; + uint64_t inspector_id_ = 0; bool is_from_origin_dirty_style_sheet_ = false; diff --git a/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc b/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc index f42275b433d4..be6ac858aa6b 100644 --- a/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc +++ b/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc @@ -421,6 +421,8 @@ void PopulateResourceRequest(const ResourceRequestHead& src, dest->headers.SetHeaderIfMissing(net::HttpRequestHeaders::kAccept, network::kDefaultAcceptHeaderValue); } + + dest->original_destination = src.GetOriginalDestination(); } } // namespace blink diff --git a/blink/web_tests/external/wpt/service-workers/service-worker/navigation-headers.https.html b/blink/web_tests/external/wpt/service-workers/service-worker/navigation-headers.https.html new file mode 100644 index 000000000000..b2c6b7ac3796 --- /dev/null +++ b/blink/web_tests/external/wpt/service-workers/service-worker/navigation-headers.https.html @@ -0,0 +1,559 @@ + + + +Service Worker: Navigation Post Request Origin Header + + + + + + + diff --git a/blink/web_tests/external/wpt/service-workers/service-worker/resources/fetch-rewrite-worker.js b/blink/web_tests/external/wpt/service-workers/service-worker/resources/fetch-rewrite-worker.js index 4631e83e0cea..20a80665270d 100644 --- a/blink/web_tests/external/wpt/service-workers/service-worker/resources/fetch-rewrite-worker.js +++ b/blink/web_tests/external/wpt/service-workers/service-worker/resources/fetch-rewrite-worker.js @@ -90,8 +90,12 @@ self.addEventListener('fetch', function(event) { var request = event.request; if (url) { request = new Request(url, init); + } else if (params['change-request']) { + request = new Request(request, init); } - fetch(request).then(function(response) { + const response_promise = params['navpreload'] ? event.preloadResponse + : fetch(request); + response_promise.then(function(response) { var expectedType = params['expected_type']; if (expectedType && response.type !== expectedType) { // Resolve a JSON object with a failure instead of rejecting diff --git a/blink/web_tests/external/wpt/service-workers/service-worker/resources/fetch-rewrite-worker.js.headers b/blink/web_tests/external/wpt/service-workers/service-worker/resources/fetch-rewrite-worker.js.headers new file mode 100644 index 000000000000..123053b38c66 --- /dev/null +++ b/blink/web_tests/external/wpt/service-workers/service-worker/resources/fetch-rewrite-worker.js.headers @@ -0,0 +1,2 @@ +Content-Type: text/javascript +Service-Worker-Allowed: / diff --git a/blink/web_tests/external/wpt/service-workers/service-worker/resources/form-poster.html b/blink/web_tests/external/wpt/service-workers/service-worker/resources/form-poster.html new file mode 100644 index 000000000000..5d56fde19a8e --- /dev/null +++ b/blink/web_tests/external/wpt/service-workers/service-worker/resources/form-poster.html @@ -0,0 +1,12 @@ + + +
+ diff --git a/blink/web_tests/external/wpt/service-workers/service-worker/resources/location-setter.html b/blink/web_tests/external/wpt/service-workers/service-worker/resources/location-setter.html new file mode 100644 index 000000000000..fae18e806655 --- /dev/null +++ b/blink/web_tests/external/wpt/service-workers/service-worker/resources/location-setter.html @@ -0,0 +1,10 @@ + + + diff --git a/blink/web_tests/external/wpt/service-workers/service-worker/resources/navigation-headers-server.py b/blink/web_tests/external/wpt/service-workers/service-worker/resources/navigation-headers-server.py new file mode 100644 index 000000000000..5b2e044f8b52 --- /dev/null +++ b/blink/web_tests/external/wpt/service-workers/service-worker/resources/navigation-headers-server.py @@ -0,0 +1,19 @@ +def main(request, response): + response.status = (200, b"OK") + response.headers.set(b"Content-Type", b"text/html") + return b""" + """ % (request.headers.get( + b"origin", b"not set"), request.headers.get(b"referer", b"not set"), + request.headers.get(b"sec-fetch-site", b"not set"), + request.headers.get(b"sec-fetch-mode", b"not set"), + request.headers.get(b"sec-fetch-dest", b"not set")) diff --git a/blink/web_tests/external/wpt/service-workers/service-worker/resources/same-site-cookies-register.html b/blink/web_tests/external/wpt/service-workers/service-worker/resources/same-site-cookies-register.html new file mode 100644 index 000000000000..084f0a08a8e6 --- /dev/null +++ b/blink/web_tests/external/wpt/service-workers/service-worker/resources/same-site-cookies-register.html @@ -0,0 +1,22 @@ + + + diff --git a/blink/web_tests/external/wpt/service-workers/service-worker/resources/same-site-cookies-unregister.html b/blink/web_tests/external/wpt/service-workers/service-worker/resources/same-site-cookies-unregister.html new file mode 100644 index 000000000000..cca3620b61e7 --- /dev/null +++ b/blink/web_tests/external/wpt/service-workers/service-worker/resources/same-site-cookies-unregister.html @@ -0,0 +1,11 @@ + + + diff --git a/blink/web_tests/external/wpt/service-workers/service-worker/same-site-cookies.https-expected.txt b/blink/web_tests/external/wpt/service-workers/service-worker/same-site-cookies.https-expected.txt new file mode 100644 index 000000000000..96ebf3b64938 --- /dev/null +++ b/blink/web_tests/external/wpt/service-workers/service-worker/same-site-cookies.https-expected.txt @@ -0,0 +1,32 @@ +This is a testharness.js-based test. +PASS Setup service workers +PASS same-origin, window.open with no service worker +PASS same-origin, window.open with fallback +PASS same-origin, window.open with passthrough +PASS same-origin, window.open with change-request +PASS same-origin, window.open with navpreload +PASS same-site, window.open with no service worker +PASS same-site, window.open with fallback +PASS same-site, window.open with passthrough +PASS same-site, window.open with change-request +PASS same-site, window.open with navpreload +PASS cross-site, window.open with no service worker +PASS cross-site, window.open with fallback +PASS cross-site, window.open with passthrough +PASS cross-site, window.open with change-request +PASS cross-site, window.open with navpreload +PASS same-origin, form post with no service worker +PASS same-origin, form post with fallback +PASS same-origin, form post with passthrough +PASS same-origin, form post with change-request +PASS same-site, form post with no service worker +PASS same-site, form post with fallback +PASS same-site, form post with passthrough +PASS same-site, form post with change-request +FAIL cross-site, form post with no service worker assert_not_equals: Unspecified-SameSite cookies are not sent with cross-site requests. got disallowed value "COOKIE_VALUE" +FAIL cross-site, form post with fallback assert_not_equals: Unspecified-SameSite cookies are not sent with cross-site requests. got disallowed value "COOKIE_VALUE" +FAIL cross-site, form post with passthrough assert_not_equals: Unspecified-SameSite cookies are not sent with cross-site requests. got disallowed value "COOKIE_VALUE" +PASS cross-site, form post with change-request +PASS Cleanup service workers +Harness: the test ran to completion. + diff --git a/blink/web_tests/external/wpt/service-workers/service-worker/same-site-cookies.https.html b/blink/web_tests/external/wpt/service-workers/service-worker/same-site-cookies.https.html new file mode 100644 index 000000000000..7003903408f8 --- /dev/null +++ b/blink/web_tests/external/wpt/service-workers/service-worker/same-site-cookies.https.html @@ -0,0 +1,216 @@ + + + +Service Worker: Same-site cookie behavior + + + + + + + +