| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "services/network/prefetch_matches.h" |
| |
| #include "base/memory/scoped_refptr.h" |
| #include "base/unguessable_token.h" |
| #include "services/network/public/cpp/resource_request.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/blink/public/common/navigation/preloading_headers.h" |
| |
| namespace network { |
| |
| namespace { |
| |
| TEST(PrefetchMatchesTest, EmptyMatchesEmpty) { |
| EXPECT_TRUE(PrefetchMatches(ResourceRequest(), ResourceRequest())); |
| } |
| |
| // We do not test every field, as we assume if the generic logic works for one |
| // field it will work for another. |
| |
| TEST(PrefetchMatchesTest, Method) { |
| ResourceRequest prefetch; |
| ResourceRequest real; |
| prefetch.method = "GET"; |
| real.method = "POST"; |
| EXPECT_FALSE(PrefetchMatches(prefetch, real)); |
| } |
| |
| TEST(PrefetchMatchesTest, URL) { |
| ResourceRequest prefetch; |
| ResourceRequest real; |
| prefetch.url = GURL("https://example.com/a"); |
| real.url = GURL("https://example.com/a"); |
| EXPECT_TRUE(PrefetchMatches(prefetch, real)); |
| real.url = GURL("https://example.com/b"); |
| EXPECT_FALSE(PrefetchMatches(prefetch, real)); |
| } |
| |
| TEST(PrefetchMatchesTest, SiteForCookies) { |
| ResourceRequest prefetch; |
| ResourceRequest real; |
| prefetch.site_for_cookies = |
| net::SiteForCookies::FromUrl(GURL("https://example.com/")); |
| real.site_for_cookies = net::SiteForCookies(); |
| EXPECT_FALSE(PrefetchMatches(prefetch, real)); |
| } |
| |
| TEST(PrefetchMatchesTest, RequestInitiator) { |
| ResourceRequest prefetch; |
| ResourceRequest real; |
| prefetch.request_initiator = |
| url::Origin::Create(GURL("https://example.com/")); |
| real.request_initiator = url::Origin::Create(GURL("http://example.com/")); |
| EXPECT_FALSE(PrefetchMatches(prefetch, real)); |
| } |
| |
| TEST(PrefetchMatchesTest, ReferrerPolicy) { |
| ResourceRequest prefetch; |
| ResourceRequest real; |
| real.referrer_policy = net::ReferrerPolicy::ORIGIN; |
| EXPECT_FALSE(PrefetchMatches(prefetch, real)); |
| } |
| |
| TEST(PrefetchMatchesTest, HeadersPurposeDiffers) { |
| ResourceRequest prefetch; |
| ResourceRequest real; |
| prefetch.headers.SetHeader(net::HttpRequestHeaders::kUserAgent, |
| "Mozilla/1.0"); |
| prefetch.headers.SetHeader(net::HttpRequestHeaders::kReferer, |
| "https://www.example.com/"); |
| prefetch.headers.SetHeader(blink::kPurposeHeaderName, |
| blink::kSecPurposePrefetchHeaderValue); |
| real.headers.SetHeader(net::HttpRequestHeaders::kUserAgent, "Mozilla/1.0"); |
| real.headers.SetHeader(net::HttpRequestHeaders::kReferer, |
| "https://www.example.com/"); |
| EXPECT_TRUE(PrefetchMatches(prefetch, real)); |
| } |
| |
| TEST(PrefetchMatchesTest, HeadersOrderDoesntMatter) { |
| ResourceRequest prefetch; |
| ResourceRequest real; |
| prefetch.headers.SetHeader(net::HttpRequestHeaders::kUserAgent, |
| "Mozilla/1.0"); |
| prefetch.headers.SetHeader(net::HttpRequestHeaders::kReferer, |
| "https://www.example.com/"); |
| prefetch.headers.SetHeader(blink::kPurposeHeaderName, |
| blink::kSecPurposePrefetchHeaderValue); |
| real.headers.SetHeader(net::HttpRequestHeaders::kReferer, |
| "https://www.example.com/"); |
| real.headers.SetHeader(net::HttpRequestHeaders::kUserAgent, "Mozilla/1.0"); |
| EXPECT_TRUE(PrefetchMatches(prefetch, real)); |
| } |
| |
| TEST(PrefetchMatchesTest, HeadersOriginDiffers) { |
| ResourceRequest prefetch; |
| ResourceRequest real; |
| prefetch.headers.SetHeader(net::HttpRequestHeaders::kUserAgent, |
| "Mozilla/1.0"); |
| prefetch.headers.SetHeader(net::HttpRequestHeaders::kOrigin, |
| "https://www.example.com/"); |
| prefetch.headers.SetHeader(blink::kPurposeHeaderName, |
| blink::kSecPurposePrefetchHeaderValue); |
| real.headers.SetHeader(net::HttpRequestHeaders::kUserAgent, "Mozilla/1.0"); |
| real.headers.SetHeader(net::HttpRequestHeaders::kReferer, |
| "https://www.example.com/"); |
| real.headers.SetHeader(net::HttpRequestHeaders::kOrigin, |
| "https://www2.example/"); |
| EXPECT_FALSE(PrefetchMatches(prefetch, real)); |
| } |
| |
| TEST(PrefetchMatchesTest, CorsExemptHeadersPurposeDiffers) { |
| ResourceRequest prefetch; |
| ResourceRequest real; |
| // The "Purpose" header is not ignored when it is a field other than |
| // "headers". |
| prefetch.cors_exempt_headers.SetHeader(net::HttpRequestHeaders::kUserAgent, |
| "Mozilla/1.0"); |
| prefetch.cors_exempt_headers.SetHeader(net::HttpRequestHeaders::kReferer, |
| "https://www.example.com/"); |
| prefetch.cors_exempt_headers.SetHeader(blink::kPurposeHeaderName, |
| blink::kSecPurposePrefetchHeaderValue); |
| real.cors_exempt_headers.SetHeader(net::HttpRequestHeaders::kUserAgent, |
| "Mozilla/1.0"); |
| real.cors_exempt_headers.SetHeader(net::HttpRequestHeaders::kReferer, |
| "https://www.example.com/"); |
| EXPECT_FALSE(PrefetchMatches(prefetch, real)); |
| } |
| |
| TEST(PrefetchMatchesTest, RequestBodySameBytes) { |
| constexpr char kBytes[] = "Some bytes"; |
| ResourceRequest prefetch; |
| ResourceRequest real; |
| // Set the bodies to different objects with the same contents. |
| prefetch.request_body = ResourceRequestBody::CreateFromCopyOfBytes( |
| base::byte_span_from_cstring(kBytes)); |
| real.request_body = ResourceRequestBody::CreateFromCopyOfBytes( |
| base::byte_span_from_cstring(kBytes)); |
| EXPECT_TRUE(PrefetchMatches(prefetch, real)); |
| } |
| |
| TEST(PrefetchMatchesTest, RequestBodyDifferentBytes) { |
| constexpr char kPrefetchBytes[] = "Some bytes"; |
| constexpr char kRealBytes[] = "Some different bytes"; |
| ResourceRequest prefetch; |
| ResourceRequest real; |
| // Set the bodies to different objects. |
| prefetch.request_body = ResourceRequestBody::CreateFromCopyOfBytes( |
| base::byte_span_from_cstring(kPrefetchBytes)); |
| real.request_body = ResourceRequestBody::CreateFromCopyOfBytes( |
| base::byte_span_from_cstring(kRealBytes)); |
| EXPECT_FALSE(PrefetchMatches(prefetch, real)); |
| } |
| |
| TEST(PrefetchMatchesTest, RequestBodyDifferentType) { |
| constexpr char kBytes[] = "Some bytes"; |
| ResourceRequest prefetch; |
| ResourceRequest real; |
| // Set the bodies to different objects with the same contents. |
| prefetch.request_body = ResourceRequestBody::CreateFromCopyOfBytes( |
| base::byte_span_from_cstring(kBytes)); |
| real.request_body = base::MakeRefCounted<ResourceRequestBody>(); |
| real.request_body->AppendFileRange(base::FilePath::FromASCII("path"), 0, 7, |
| base::Time::Now()); |
| EXPECT_FALSE(PrefetchMatches(prefetch, real)); |
| } |
| |
| // A ResourceRequestBody consists of zero or more DataElements. If the number is |
| // different, they should not compare equal. |
| TEST(PrefetchMatchesTest, RequestBodyDifferentLength) { |
| constexpr std::string_view kBytes = "Some bytes"; |
| constexpr std::string_view kSplit1 = kBytes.substr(0, 5); |
| constexpr std::string_view kSplit2 = kBytes.substr(5); |
| ResourceRequest prefetch; |
| ResourceRequest real; |
| // Set the bodies to different objects with the same contents. |
| prefetch.request_body = |
| ResourceRequestBody::CreateFromCopyOfBytes(base::as_byte_span(kBytes)); |
| real.request_body = |
| ResourceRequestBody::CreateFromCopyOfBytes(base::as_byte_span(kSplit1)); |
| real.request_body->AppendCopyOfBytes(base::as_byte_span(kSplit2)); |
| EXPECT_FALSE(PrefetchMatches(prefetch, real)); |
| } |
| |
| TEST(PrefetchMatchesTest, FetchWindowIdIgnored) { |
| ResourceRequest prefetch; |
| ResourceRequest real; |
| real.fetch_window_id = base::UnguessableToken::Create(); |
| EXPECT_TRUE(PrefetchMatches(prefetch, real)); |
| } |
| |
| TEST(PrefetchMatchesTest, WebBundleTokenParamsMatch) { |
| ResourceRequest prefetch; |
| ResourceRequest real; |
| const GURL bundle_url("https://example.com/bundle"); |
| const auto token = base::UnguessableToken::Create(); |
| constexpr int kProcessId1 = 1; |
| constexpr int kProcessId2 = 2; |
| prefetch.web_bundle_token_params = |
| ResourceRequest::WebBundleTokenParams(bundle_url, token, kProcessId1); |
| real.web_bundle_token_params = |
| ResourceRequest::WebBundleTokenParams(bundle_url, token, kProcessId2); |
| EXPECT_TRUE(PrefetchMatches(prefetch, real)); |
| } |
| |
| TEST(PrefetchMatchesTest, WebBundleTokenParamsMismatch) { |
| ResourceRequest prefetch; |
| ResourceRequest real; |
| const GURL bundle_url("https://example.com/bundle"); |
| const auto token1 = base::UnguessableToken::Create(); |
| const auto token2 = base::UnguessableToken::Create(); |
| constexpr int kProcessId1 = 1; |
| constexpr int kProcessId2 = 2; |
| prefetch.web_bundle_token_params = |
| ResourceRequest::WebBundleTokenParams(bundle_url, token1, kProcessId1); |
| real.web_bundle_token_params = |
| ResourceRequest::WebBundleTokenParams(bundle_url, token2, kProcessId2); |
| EXPECT_FALSE(PrefetchMatches(prefetch, real)); |
| } |
| |
| } // namespace |
| |
| } // namespace network |