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..9a6d23286bcdc73c7e5791f708daa6ac2a9c2a74 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_location, |
+ const char* referer_header, |
+ const char* response_headers, |
+ MockTransaction* transaction) { |
+ transaction->url = original_location; |
+ 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_location).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,156 @@ TEST(URLRequestJob, RedirectTransactionNotifiedWhenDone) { |
RemoveMockTransaction(&kRedirect_Transaction); |
} |
+TEST(URLRequestJob, RedirectTransactionWithReferrerPolicyHeader) { |
+ struct TestCase { |
+ const char* original_location; |
+ const char* original_referrer; |
mmenke
2016/06/27 18:38:05
These two are always the same in this test, so I t
estark
2016/06/27 22:18:34
Done. (Changed a test so they're different.)
|
+ 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", "http://foo.test/one", |
mmenke
2016/06/27 18:38:05
A bit of a pain, but I suggest comments labelling
estark
2016/06/27 22:18:34
Done. Though the formatting's a little weird :(
|
+ "Location: http://foo.test/test\n" |
+ "Referrer-Policy: no-referrer\n", |
+ URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, |
+ URLRequest::NEVER_CLEAR_REFERRER, ""}, |
+ |
+ // Same as above but for the legacy keyword 'never'. |
+ {"http://foo.test/one", "http://foo.test/one", |
+ "Location: http://foo.test/test\nReferrer-Policy: never\n", |
+ URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, |
+ URLRequest::NEVER_CLEAR_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", "https://foo.test/one", |
+ "Location: http://foo.test\n" |
+ "Referrer-Policy: no-referrer-when-downgrade\n", |
+ URLRequest::NEVER_CLEAR_REFERRER, |
+ URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, ""}, |
+ |
+ // Same as above but for the legacy keyword 'default'. |
+ {"https://foo.test/one", "https://foo.test/one", |
+ "Location: http://foo.test\n" |
+ "Referrer-Policy: default\n", |
+ URLRequest::NEVER_CLEAR_REFERRER, |
+ URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, ""}, |
+ |
+ // 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", "https://foo.test/one", |
+ "Location: https://foo.test/two\n" |
+ "Referrer-Policy: origin\n", |
+ URLRequest::NEVER_CLEAR_REFERRER, URLRequest::NEVER_CLEAR_REFERRER, |
+ "https://foo.test/"}, |
+ |
+ // 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", "https://foo.test/one", |
+ "Location: https://foo.test/two\n" |
+ "Referrer-Policy: origin-when-cross-origin\n", |
+ URLRequest::NEVER_CLEAR_REFERRER, |
+ URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, |
+ "https://foo.test/one"}, |
+ |
+ // ... but should be stripped to the origin for a cross-origin redirect. |
+ {"https://foo.test/one", "https://foo.test/one", |
+ "Location: https://bar.test/two\n" |
+ "Referrer-Policy: origin-when-cross-origin\n", |
+ URLRequest::NEVER_CLEAR_REFERRER, |
+ URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, "https://foo.test/"}, |
+ |
+ // 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", "https://foo.test/one", |
+ "Location: https://bar.test/two\n" |
+ "Referrer-Policy: unsafe-url\n", |
+ URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, |
+ URLRequest::NEVER_CLEAR_REFERRER, "https://foo.test/one"}, |
+ |
+ // Same as above but for the legacy keyword 'always'. |
+ {"https://foo.test/one", "https://foo.test/one", |
+ "Location: https://bar.test/two\n" |
+ "Referrer-Policy: always\n", |
+ URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, |
+ URLRequest::NEVER_CLEAR_REFERRER, "https://foo.test/one"}, |
+ |
+ // An invalid keyword should leave the policy untouched. |
+ {"https://foo.test/one", "https://foo.test/one", |
+ "Location: https://bar.test/two\n" |
+ "Referrer-Policy: not-a-valid-policy\n", |
+ URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, |
+ URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, "https://foo.test/"}, |
+ |
+ // The last valid keyword should take precedence. |
+ {"https://foo.test/one", "https://foo.test/one", |
+ "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, |
+ URLRequest::NEVER_CLEAR_REFERRER, "https://foo.test/one"}, |
+ |
+ {"https://foo.test/one", "https://foo.test/one", |
+ "Location: https://bar.test/two\n" |
+ "Referrer-Policy: unsafe-url\n" |
+ "Referrer-Policy: origin\n", |
+ URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, |
+ URLRequest::NEVER_CLEAR_REFERRER, "https://foo.test/"}, |
+ |
+ // An empty header should not affect the request. |
+ {"https://foo.test/one", "https://foo.test/one", |
+ "Location: https://bar.test/two\n" |
+ "Referrer-Policy: \n", |
+ URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, |
+ URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN, "https://foo.test/"}, |
+ }; |
+ |
+ for (const auto& test : kTests) { |
+ MockTransaction transaction; |
+ std::string request_headers = |
+ "Referer: " + std::string(test.original_referrer) + "\n"; |
+ MakeMockReferrerPolicyTransaction(test.original_location, |
+ 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; |