Index: net/url_request/url_request_job_unittest.cc |
diff --git a/net/url_request/url_request_job_unittest.cc b/net/url_request/url_request_job_unittest.cc |
index 61d9188f540bf3290330aa8b54eafa3ec3b43eef..4583aa83d85b95355e8f9e42aeb894c18fc23f3e 100644 |
--- a/net/url_request/url_request_job_unittest.cc |
+++ b/net/url_request/url_request_job_unittest.cc |
@@ -9,6 +9,8 @@ |
#include "base/run_loop.h" |
#include "net/base/request_priority.h" |
#include "net/http/http_transaction_test_util.h" |
+#include "net/test/cert_test_util.h" |
+#include "net/test/test_data_directory.h" |
#include "net/url_request/url_request.h" |
#include "net/url_request/url_request_test_util.h" |
#include "testing/gtest/include/gtest/gtest.h" |
@@ -61,6 +63,32 @@ void BrotliHelloServer(const HttpRequestInfo* request, |
response_data->assign(kBrotliHelloData, sizeof(kBrotliHelloData) - 1); |
} |
+void MakeMockReferrerPolicyTransaction(const char* original_url, |
+ const char* referer_header, |
+ const char* response_headers, |
+ MockTransaction* transaction) { |
+ transaction->url = original_url; |
+ transaction->method = "GET"; |
+ transaction->request_time = base::Time(); |
+ transaction->request_headers = referer_header; |
+ transaction->load_flags = LOAD_NORMAL; |
+ transaction->status = "HTTP/1.1 302 Found"; |
+ transaction->response_headers = response_headers; |
+ transaction->response_time = base::Time(); |
+ transaction->data = "hello"; |
+ transaction->test_mode = TEST_MODE_NORMAL; |
+ transaction->handler = nullptr; |
+ if (GURL(original_url).SchemeIsCryptographic()) { |
+ transaction->cert = |
+ net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem"); |
+ } else { |
+ transaction->cert = nullptr; |
+ } |
+ transaction->cert_status = 0; |
+ transaction->ssl_connection_status = 0; |
+ transaction->return_code = OK; |
+} |
+ |
const MockTransaction kGZip_Transaction = { |
"http://www.google.com/gzyp", |
"GET", |
@@ -233,6 +261,199 @@ TEST(URLRequestJob, RedirectTransactionNotifiedWhenDone) { |
RemoveMockTransaction(&kRedirect_Transaction); |
} |
+TEST(URLRequestJob, RedirectTransactionWithReferrerPolicyHeader) { |
+ struct TestCase { |
+ const char* original_url; |
+ const char* original_referrer; |
+ const char* response_headers; |
+ URLRequest::ReferrerPolicy original_referrer_policy; |
+ URLRequest::ReferrerPolicy expected_final_referrer_policy; |
+ const char* expected_final_referrer; |
+ }; |
+ |
+ const TestCase kTests[] = { |
+ // If a redirect serves 'Referrer-Policy: no-referrer', then the referrer |
+ // should be cleared. |
+ {"http://foo.test/one" /* original url */, |
+ "http://foo.test/one" /* original referrer */, |
+ "Location: http://foo.test/test\n" |
+ "Referrer-Policy: no-referrer\n", |
+ // original policy |
+ URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, |
+ URLRequest::NO_REFERRER /* expected final policy */, |
+ "" /* expected final referrer */}, |
+ |
+ // Same as above but for the legacy keyword 'never'. |
+ {"http://foo.test/one" /* original url */, |
+ "http://foo.test/one" /* original referrer */, |
+ "Location: http://foo.test/test\nReferrer-Policy: never\n", |
+ // original policy |
+ URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, |
+ URLRequest::NO_REFERRER /* expected final policy */, |
+ "" /* expected final referrer */}, |
+ |
+ // If a redirect serves 'Referrer-Policy: |
+ // no-referrer-when-downgrade', then the referrer should be cleared |
+ // on downgrade, even if the original request's policy specified |
+ // that the referrer should never be cleared. |
+ {"https://foo.test/one" /* original url */, |
+ "https://foo.test/one" /* original referrer */, |
+ "Location: http://foo.test\n" |
+ "Referrer-Policy: no-referrer-when-downgrade\n", |
+ URLRequest::NEVER_CLEAR_REFERRER /* original policy */, |
+ // expected final policy |
+ URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, |
+ "" /* expected final referrer */}, |
+ |
+ // Same as above but for the legacy keyword 'default'. |
+ {"https://foo.test/one" /* original url */, |
+ "https://foo.test/one" /* original referrer */, |
+ "Location: http://foo.test\n" |
+ "Referrer-Policy: default\n", |
+ URLRequest::NEVER_CLEAR_REFERRER /* original policy */, |
+ // expected final policy |
+ URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, |
+ "" /* expected final referrer */}, |
+ |
+ // If a redirect serves 'Referrer-Policy: origin', then the referrer |
+ // should be stripped to its origin, even if the original request's |
+ // policy specified that the referrer should never be cleared. |
+ {"https://foo.test/one" /* original url */, |
+ "https://foo.test/one" /* original referrer */, |
+ "Location: https://foo.test/two\n" |
+ "Referrer-Policy: origin\n", |
+ URLRequest::NEVER_CLEAR_REFERRER /* original policy */, |
+ URLRequest::ORIGIN /* expected final policy */, |
+ "https://foo.test/" /* expected final referrer */}, |
+ |
+ // If a redirect serves 'Referrer-Policy: origin-when-cross-origin', |
+ // then the referrer should be untouched for a same-origin redirect... |
+ {"https://foo.test/one" /* original url */, |
+ "https://foo.test/referrer" /* original referrer */, |
+ "Location: https://foo.test/two\n" |
+ "Referrer-Policy: origin-when-cross-origin\n", |
+ URLRequest::NEVER_CLEAR_REFERRER /* original policy */, |
+ URLRequest:: |
+ ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* expected final policy */, |
+ "https://foo.test/referrer" /* expected final referrer */}, |
+ |
+ // ... but should be stripped to the origin for a cross-origin redirect. |
+ {"https://foo.test/one" /* original url */, |
+ "https://foo.test/one" /* original referrer */, |
+ "Location: https://bar.test/two\n" |
+ "Referrer-Policy: origin-when-cross-origin\n", |
+ URLRequest::NEVER_CLEAR_REFERRER /* original policy */, |
+ URLRequest:: |
+ ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* expected final policy */, |
+ "https://foo.test/" /* expected final referrer */}, |
+ |
+ // If a redirect serves 'Referrer-Policy: unsafe-url', then the |
+ // referrer should remain, even if originally set to clear on |
+ // downgrade. |
+ {"https://foo.test/one" /* original url */, |
+ "https://foo.test/one" /* original referrer */, |
+ "Location: https://bar.test/two\n" |
+ "Referrer-Policy: unsafe-url\n", |
+ URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */, |
+ URLRequest::NEVER_CLEAR_REFERRER /* expected final policy */, |
+ "https://foo.test/one" /* expected final referrer */}, |
+ |
+ // Same as above but for the legacy keyword 'always'. |
+ {"https://foo.test/one" /* original url */, |
+ "https://foo.test/one" /* original referrer */, |
+ "Location: https://bar.test/two\n" |
+ "Referrer-Policy: always\n", |
+ URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */, |
+ URLRequest::NEVER_CLEAR_REFERRER /* expected final policy */, |
+ "https://foo.test/one" /* expected final referrer */}, |
+ |
+ // An invalid keyword should leave the policy untouched. |
+ {"https://foo.test/one" /* original url */, |
+ "https://foo.test/one" /* original referrer */, |
+ "Location: https://bar.test/two\n" |
+ "Referrer-Policy: not-a-valid-policy\n", |
+ URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */, |
+ URLRequest:: |
+ ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* expected final policy */, |
+ "https://foo.test/" /* expected final referrer */}, |
+ |
+ {"https://foo.test/one" /* original url */, |
+ "https://foo.test/one" /* original referrer */, |
+ "Location: http://bar.test/two\n" |
+ "Referrer-Policy: not-a-valid-policy\n", |
+ // original policy |
+ URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, |
+ // expected final policy |
+ URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, |
+ "" /* expected final referrer */}, |
+ |
+ // The last valid keyword should take precedence. |
+ {"https://foo.test/one" /* original url */, |
+ "https://foo.test/one" /* original referrer */, |
+ "Location: https://bar.test/two\n" |
+ "Referrer-Policy: unsafe-url\n" |
+ "Referrer-Policy: not-a-valid-policy\n", |
+ URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */, |
+ URLRequest::NEVER_CLEAR_REFERRER /* expected final policy */, |
+ "https://foo.test/one" /* expected final referrer */}, |
+ |
+ {"https://foo.test/one" /* original url */, |
+ "https://foo.test/one" /* original referrer */, |
+ "Location: https://bar.test/two\n" |
+ "Referrer-Policy: unsafe-url\n" |
+ "Referrer-Policy: origin\n", |
+ URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */, |
+ URLRequest::ORIGIN /* expected final policy */, |
+ "https://foo.test/" /* expected final referrer */}, |
+ |
+ // An empty header should not affect the request. |
+ {"https://foo.test/one" /* original url */, |
+ "https://foo.test/one" /* original referrer */, |
+ "Location: https://bar.test/two\n" |
+ "Referrer-Policy: \n", |
+ URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* original policy */, |
+ URLRequest:: |
+ ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN /* expected final policy */, |
+ "https://foo.test/" /* expected final referrer */}, |
+ }; |
+ |
+ for (const auto& test : kTests) { |
+ MockTransaction transaction; |
+ std::string request_headers = |
+ "Referer: " + std::string(test.original_referrer) + "\n"; |
+ MakeMockReferrerPolicyTransaction(test.original_url, |
+ request_headers.c_str(), |
+ test.response_headers, &transaction); |
+ |
+ MockNetworkLayer network_layer; |
+ TestURLRequestContext context; |
+ context.set_enable_referrer_policy_header(true); |
+ context.set_http_transaction_factory(&network_layer); |
+ |
+ TestDelegate d; |
+ std::unique_ptr<URLRequest> req( |
+ context.CreateRequest(GURL(transaction.url), DEFAULT_PRIORITY, &d)); |
+ AddMockTransaction(&transaction); |
+ |
+ req->set_referrer_policy(test.original_referrer_policy); |
+ req->SetReferrer(test.original_referrer); |
+ |
+ req->set_method("GET"); |
+ req->Start(); |
+ |
+ base::RunLoop().Run(); |
+ |
+ EXPECT_TRUE(network_layer.done_reading_called()); |
+ |
+ RemoveMockTransaction(&transaction); |
+ |
+ // Test that the referrer policy and referrer were set correctly |
+ // according to the header received during the redirect. |
+ EXPECT_EQ(test.expected_final_referrer_policy, req->referrer_policy()); |
+ EXPECT_EQ(test.expected_final_referrer, req->referrer()); |
+ } |
+} |
+ |
TEST(URLRequestJob, TransactionNotCachedWhenNetworkDelegateRedirects) { |
MockNetworkLayer network_layer; |
TestNetworkDelegate network_delegate; |