1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/url_request/url_request_job.h"
6
7 #include <memory>
8 #include <optional>
9
10 #include "base/functional/bind.h"
11 #include "base/run_loop.h"
12 #include "base/test/bind.h"
13 #include "base/test/scoped_feature_list.h"
14 #include "net/base/features.h"
15 #include "net/base/request_priority.h"
16 #include "net/http/http_transaction_test_util.h"
17 #include "net/test/cert_test_util.h"
18 #include "net/test/gtest_util.h"
19 #include "net/test/test_data_directory.h"
20 #include "net/test/test_with_task_environment.h"
21 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
22 #include "net/url_request/referrer_policy.h"
23 #include "net/url_request/url_request.h"
24 #include "net/url_request/url_request_context.h"
25 #include "net/url_request/url_request_context_builder.h"
26 #include "net/url_request/url_request_test_util.h"
27 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "url/url_util.h"
30
31 using net::test::IsError;
32 using net::test::IsOk;
33
34 namespace net {
35
36 namespace {
37
38 // Data encoded in kBrotliHelloData.
39 const char kHelloData[] = "hello, world!\n";
40 // kHelloData encoded with brotli.
41 const char kBrotliHelloData[] =
42 "\033\015\0\0\244\024\102\152\020\111\152\072\235\126\034";
43
44 // This is a header that signals the end of the data.
45 const char kGzipData[] = "\x1f\x08b\x08\0\0\0\0\0\0\3\3\0\0\0\0\0\0\0\0";
46 const char kGzipDataWithName[] =
47 "\x1f\x08b\x08\x08\0\0\0\0\0\0name\0\3\0\0\0\0\0\0\0\0";
48 // kHelloData encoded with gzip.
49 const char kGzipHelloData[] =
50 "\x1f\x8b\x08\x08\x46\x7d\x4e\x56\x00\x03\x67\x7a\x69\x70\x2e\x74\x78\x74"
51 "\x00\xcb\x48\xcd\xc9\xc9\xe7\x02\x00\x20\x30\x3a\x36\x06\x00\x00\x00";
52
GZipServer(const HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)53 void GZipServer(const HttpRequestInfo* request,
54 std::string* response_status,
55 std::string* response_headers,
56 std::string* response_data) {
57 response_data->assign(kGzipData, sizeof(kGzipData));
58 }
59
GZipHelloServer(const HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)60 void GZipHelloServer(const HttpRequestInfo* request,
61 std::string* response_status,
62 std::string* response_headers,
63 std::string* response_data) {
64 response_data->assign(kGzipHelloData, sizeof(kGzipHelloData) - 1);
65 }
66
BigGZipServer(const HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)67 void BigGZipServer(const HttpRequestInfo* request,
68 std::string* response_status,
69 std::string* response_headers,
70 std::string* response_data) {
71 response_data->assign(kGzipDataWithName, sizeof(kGzipDataWithName));
72 response_data->insert(10, 64 * 1024, 'a');
73 }
74
BrotliHelloServer(const HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)75 void BrotliHelloServer(const HttpRequestInfo* request,
76 std::string* response_status,
77 std::string* response_headers,
78 std::string* response_data) {
79 response_data->assign(kBrotliHelloData, sizeof(kBrotliHelloData) - 1);
80 }
81
MakeMockReferrerPolicyTransaction(const char * referer_header,const char * response_headers,MockTransaction * transaction)82 void MakeMockReferrerPolicyTransaction(const char* referer_header,
83 const char* response_headers,
84 MockTransaction* transaction) {
85 transaction->method = "GET";
86 transaction->request_time = base::Time();
87 transaction->request_headers = referer_header;
88 transaction->load_flags = LOAD_NORMAL;
89 transaction->status = "HTTP/1.1 302 Found";
90 transaction->response_headers = response_headers;
91 transaction->response_time = base::Time();
92 transaction->data = "hello";
93 transaction->dns_aliases = {};
94 transaction->test_mode = TEST_MODE_NORMAL;
95 transaction->handler = MockTransactionHandler();
96 transaction->read_handler = MockTransactionReadHandler();
97 if (GURL(transaction->url).SchemeIsCryptographic()) {
98 transaction->cert =
99 net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
100 } else {
101 transaction->cert = nullptr;
102 }
103 transaction->cert_status = 0;
104 transaction->ssl_connection_status = 0;
105 transaction->start_return_code = OK;
106 }
107
108 const MockTransaction kNoFilterTransaction = {
109 "http://www.google.com/gzyp",
110 "GET",
111 base::Time(),
112 "",
113 LOAD_NORMAL,
114 DefaultTransportInfo(),
115 "HTTP/1.1 200 OK",
116 "Cache-Control: max-age=10000\n"
117 "Content-Length: 30\n", // Intentionally wrong.
118 base::Time(),
119 "hello",
120 {},
121 std::nullopt,
122 std::nullopt,
123 TEST_MODE_NORMAL,
124 MockTransactionHandler(),
125 MockTransactionReadHandler(),
126 nullptr,
127 0,
128 OK,
129 OK,
130 };
131
132 const MockTransaction kNoFilterTransactionWithInvalidLength = {
133 "http://www.google.com/gzyp",
134 "GET",
135 base::Time(),
136 "",
137 LOAD_NORMAL,
138 DefaultTransportInfo(),
139 "HTTP/1.1 200 OK",
140 "Cache-Control: max-age=10000\n"
141 "Content-Length: +30\n", // Invalid
142 base::Time(),
143 "hello",
144 {},
145 std::nullopt,
146 std::nullopt,
147 TEST_MODE_NORMAL,
148 MockTransactionHandler(),
149 MockTransactionReadHandler(),
150 nullptr,
151 0,
152 OK,
153 OK,
154 };
155
156 const MockTransaction kGZipTransaction = {
157 "http://www.google.com/gzyp",
158 "GET",
159 base::Time(),
160 "",
161 LOAD_NORMAL,
162 DefaultTransportInfo(),
163 "HTTP/1.1 200 OK",
164 "Cache-Control: max-age=10000\n"
165 "Content-Encoding: gzip\n"
166 "Content-Length: 30\n", // Intentionally wrong.
167 base::Time(),
168 "",
169 {},
170 std::nullopt,
171 std::nullopt,
172 TEST_MODE_NORMAL,
173 base::BindRepeating(&GZipServer),
174 MockTransactionReadHandler(),
175 nullptr,
176 0,
177 0,
178 OK,
179 OK,
180 };
181
182 const MockTransaction kGzipSlowTransaction = {
183 "http://www.google.com/gzyp",
184 "GET",
185 base::Time(),
186 "",
187 LOAD_NORMAL,
188 DefaultTransportInfo(),
189 "HTTP/1.1 200 OK",
190 "Cache-Control: max-age=10000\n"
191 "Content-Encoding: gzip\n",
192 base::Time(),
193 "",
194 {},
195 std::nullopt,
196 std::nullopt,
197 TEST_MODE_SLOW_READ,
198 base::BindRepeating(&GZipHelloServer),
199 MockTransactionReadHandler(),
200 nullptr,
201 0,
202 0,
203 OK,
204 OK,
205 };
206
207 const MockTransaction kRedirectTransaction = {
208 "http://www.google.com/redirect",
209 "GET",
210 base::Time(),
211 "",
212 LOAD_NORMAL,
213 DefaultTransportInfo(),
214 "HTTP/1.1 302 Found",
215 "Cache-Control: max-age=10000\n"
216 "Location: http://www.google.com/destination\n"
217 "Content-Length: 5\n",
218 base::Time(),
219 "hello",
220 {},
221 std::nullopt,
222 std::nullopt,
223 TEST_MODE_NORMAL,
224 MockTransactionHandler(),
225 MockTransactionReadHandler(),
226 nullptr,
227 0,
228 0,
229 OK,
230 OK,
231 };
232
233 const MockTransaction kEmptyBodyGzipTransaction = {
234 "http://www.google.com/empty_body",
235 "GET",
236 base::Time(),
237 "",
238 LOAD_NORMAL,
239 DefaultTransportInfo(),
240 "HTTP/1.1 200 OK",
241 "Content-Encoding: gzip\n",
242 base::Time(),
243 "",
244 {},
245 std::nullopt,
246 std::nullopt,
247 TEST_MODE_NORMAL,
248 MockTransactionHandler(),
249 MockTransactionReadHandler(),
250 nullptr,
251 0,
252 0,
253 OK,
254 OK,
255 };
256
257 const MockTransaction kInvalidContentGZipTransaction = {
258 "http://www.google.com/gzyp",
259 "GET",
260 base::Time(),
261 "",
262 LOAD_NORMAL,
263 DefaultTransportInfo(),
264 "HTTP/1.1 200 OK",
265 "Content-Encoding: gzip\n"
266 "Content-Length: 21\n",
267 base::Time(),
268 "not a valid gzip body",
269 {},
270 std::nullopt,
271 std::nullopt,
272 TEST_MODE_NORMAL,
273 MockTransactionHandler(),
274 MockTransactionReadHandler(),
275 nullptr,
276 0,
277 0,
278 OK,
279 OK,
280 };
281
282 const MockTransaction kBrotliSlowTransaction = {
283 "http://www.google.com/brotli",
284 "GET",
285 base::Time(),
286 "",
287 LOAD_NORMAL,
288 DefaultTransportInfo(),
289 "HTTP/1.1 200 OK",
290 "Cache-Control: max-age=10000\n"
291 "Content-Encoding: br\n"
292 "Content-Length: 230\n", // Intentionally wrong.
293 base::Time(),
294 "",
295 {},
296 std::nullopt,
297 std::nullopt,
298 TEST_MODE_SLOW_READ,
299 base::BindRepeating(&BrotliHelloServer),
300 MockTransactionReadHandler(),
301 nullptr,
302 0,
303 0,
304 OK,
305 OK,
306 };
307
308 } // namespace
309
310 using URLRequestJobTest = TestWithTaskEnvironment;
311
TEST_F(URLRequestJobTest,TransactionNoFilter)312 TEST_F(URLRequestJobTest, TransactionNoFilter) {
313 auto context_builder = CreateTestURLRequestContextBuilder();
314 auto* network_layer = context_builder->SetHttpTransactionFactoryForTesting(
315 std::make_unique<MockNetworkLayer>());
316 context_builder->DisableHttpCache();
317 auto context = context_builder->Build();
318
319 ScopedMockTransaction transaction(kNoFilterTransaction);
320 TestDelegate d;
321 std::unique_ptr<URLRequest> req(
322 context->CreateRequest(GURL(transaction.url), DEFAULT_PRIORITY, &d,
323 TRAFFIC_ANNOTATION_FOR_TESTS));
324
325 req->set_method("GET");
326 req->Start();
327
328 d.RunUntilComplete();
329
330 EXPECT_FALSE(d.request_failed());
331 EXPECT_EQ(200, req->GetResponseCode());
332 EXPECT_EQ("hello", d.data_received());
333 EXPECT_TRUE(network_layer->done_reading_called());
334 // When there's no filter and a Content-Length, expected content size should
335 // be available.
336 EXPECT_EQ(30, req->GetExpectedContentSize());
337 }
338
TEST_F(URLRequestJobTest,TransactionNoFilterWithInvalidLength)339 TEST_F(URLRequestJobTest, TransactionNoFilterWithInvalidLength) {
340 auto context_builder = CreateTestURLRequestContextBuilder();
341 auto* network_layer = context_builder->SetHttpTransactionFactoryForTesting(
342 std::make_unique<MockNetworkLayer>());
343 context_builder->DisableHttpCache();
344 auto context = context_builder->Build();
345
346 ScopedMockTransaction transaction(kNoFilterTransactionWithInvalidLength);
347 TestDelegate d;
348 std::unique_ptr<URLRequest> req(
349 context->CreateRequest(GURL(transaction.url), DEFAULT_PRIORITY, &d,
350 TRAFFIC_ANNOTATION_FOR_TESTS));
351
352 req->set_method("GET");
353 req->Start();
354
355 d.RunUntilComplete();
356
357 EXPECT_FALSE(d.request_failed());
358 EXPECT_EQ(200, req->GetResponseCode());
359 EXPECT_EQ("hello", d.data_received());
360 EXPECT_TRUE(network_layer->done_reading_called());
361 // Invalid Content-Lengths that start with a + should not be reported.
362 EXPECT_EQ(-1, req->GetExpectedContentSize());
363 }
364
TEST_F(URLRequestJobTest,TransactionNotifiedWhenDone)365 TEST_F(URLRequestJobTest, TransactionNotifiedWhenDone) {
366 auto context_builder = CreateTestURLRequestContextBuilder();
367 auto* network_layer = context_builder->SetHttpTransactionFactoryForTesting(
368 std::make_unique<MockNetworkLayer>());
369 context_builder->DisableHttpCache();
370 auto context = context_builder->Build();
371
372 ScopedMockTransaction transaction(kGZipTransaction);
373 TestDelegate d;
374 std::unique_ptr<URLRequest> req(
375 context->CreateRequest(GURL(transaction.url), DEFAULT_PRIORITY, &d,
376 TRAFFIC_ANNOTATION_FOR_TESTS));
377
378 req->set_method("GET");
379 req->Start();
380
381 d.RunUntilComplete();
382
383 EXPECT_TRUE(d.response_completed());
384 EXPECT_EQ(OK, d.request_status());
385 EXPECT_EQ(200, req->GetResponseCode());
386 EXPECT_EQ("", d.data_received());
387 EXPECT_TRUE(network_layer->done_reading_called());
388 // When there's a filter and a Content-Length, expected content size should
389 // not be available.
390 EXPECT_EQ(-1, req->GetExpectedContentSize());
391 }
392
TEST_F(URLRequestJobTest,SyncTransactionNotifiedWhenDone)393 TEST_F(URLRequestJobTest, SyncTransactionNotifiedWhenDone) {
394 auto context_builder = CreateTestURLRequestContextBuilder();
395 auto* network_layer = context_builder->SetHttpTransactionFactoryForTesting(
396 std::make_unique<MockNetworkLayer>());
397 context_builder->DisableHttpCache();
398 auto context = context_builder->Build();
399
400 ScopedMockTransaction transaction(kGZipTransaction);
401 TestDelegate d;
402 std::unique_ptr<URLRequest> req(
403 context->CreateRequest(GURL(kGZipTransaction.url), DEFAULT_PRIORITY, &d,
404 TRAFFIC_ANNOTATION_FOR_TESTS));
405 transaction.test_mode = TEST_MODE_SYNC_ALL;
406
407 req->set_method("GET");
408 req->Start();
409
410 d.RunUntilComplete();
411
412 EXPECT_TRUE(d.response_completed());
413 EXPECT_EQ(OK, d.request_status());
414 EXPECT_EQ(200, req->GetResponseCode());
415 EXPECT_EQ("", d.data_received());
416 EXPECT_TRUE(network_layer->done_reading_called());
417 // When there's a filter and a Content-Length, expected content size should
418 // not be available.
419 EXPECT_EQ(-1, req->GetExpectedContentSize());
420 }
421
422 // Tests processing a large gzip header one byte at a time.
TEST_F(URLRequestJobTest,SyncSlowTransaction)423 TEST_F(URLRequestJobTest, SyncSlowTransaction) {
424 auto context_builder = CreateTestURLRequestContextBuilder();
425 auto* network_layer = context_builder->SetHttpTransactionFactoryForTesting(
426 std::make_unique<MockNetworkLayer>());
427 context_builder->DisableHttpCache();
428 auto context = context_builder->Build();
429
430 ScopedMockTransaction transaction(kGZipTransaction);
431 TestDelegate d;
432 std::unique_ptr<URLRequest> req(
433 context->CreateRequest(GURL(transaction.url), DEFAULT_PRIORITY, &d,
434 TRAFFIC_ANNOTATION_FOR_TESTS));
435 transaction.test_mode = TEST_MODE_SYNC_ALL | TEST_MODE_SLOW_READ;
436 transaction.handler = base::BindRepeating(&BigGZipServer);
437
438 req->set_method("GET");
439 req->Start();
440
441 d.RunUntilComplete();
442
443 EXPECT_TRUE(d.response_completed());
444 EXPECT_EQ(OK, d.request_status());
445 EXPECT_EQ(200, req->GetResponseCode());
446 EXPECT_EQ("", d.data_received());
447 EXPECT_TRUE(network_layer->done_reading_called());
448 EXPECT_EQ(-1, req->GetExpectedContentSize());
449 }
450
TEST_F(URLRequestJobTest,RedirectTransactionNotifiedWhenDone)451 TEST_F(URLRequestJobTest, RedirectTransactionNotifiedWhenDone) {
452 auto context_builder = CreateTestURLRequestContextBuilder();
453 auto* network_layer = context_builder->SetHttpTransactionFactoryForTesting(
454 std::make_unique<MockNetworkLayer>());
455 context_builder->DisableHttpCache();
456 auto context = context_builder->Build();
457
458 ScopedMockTransaction transaction(kRedirectTransaction);
459 TestDelegate d;
460 std::unique_ptr<URLRequest> req(
461 context->CreateRequest(GURL(transaction.url), DEFAULT_PRIORITY, &d,
462 TRAFFIC_ANNOTATION_FOR_TESTS));
463
464 req->set_method("GET");
465 req->Start();
466
467 d.RunUntilComplete();
468
469 EXPECT_TRUE(network_layer->done_reading_called());
470 }
471
TEST_F(URLRequestJobTest,RedirectTransactionWithReferrerPolicyHeader)472 TEST_F(URLRequestJobTest, RedirectTransactionWithReferrerPolicyHeader) {
473 struct TestCase {
474 const char* original_url;
475 const char* original_referrer;
476 const char* response_headers;
477 ReferrerPolicy original_referrer_policy;
478 ReferrerPolicy expected_final_referrer_policy;
479 const char* expected_final_referrer;
480 };
481
482 // Note: There are more thorough test cases in RedirectInfoTest.
483 const TestCase kTests[] = {
484 // If a redirect serves 'Referrer-Policy: no-referrer', then the referrer
485 // should be cleared.
486 {"http://foo.test/one" /* original url */,
487 "http://foo.test/one" /* original referrer */,
488 "Location: http://foo.test/test\n"
489 "Referrer-Policy: no-referrer\n",
490 // original policy
491 ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
492 ReferrerPolicy::NO_REFERRER /* expected final policy */,
493 "" /* expected final referrer */},
494
495 // A redirect response without Referrer-Policy header should not affect
496 // the policy and the referrer.
497 {"http://foo.test/one" /* original url */,
498 "http://foo.test/one" /* original referrer */,
499 "Location: http://foo.test/test\n",
500 // original policy
501 ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
502 // expected final policy
503 ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
504 "http://foo.test/one" /* expected final referrer */},
505 };
506
507 for (const auto& test : kTests) {
508 ScopedMockTransaction transaction(test.original_url);
509 std::string request_headers =
510 "Referer: " + std::string(test.original_referrer) + "\n";
511 MakeMockReferrerPolicyTransaction(request_headers.c_str(),
512 test.response_headers, &transaction);
513
514 auto context_builder = CreateTestURLRequestContextBuilder();
515 auto* network_layer = context_builder->SetHttpTransactionFactoryForTesting(
516 std::make_unique<MockNetworkLayer>());
517 context_builder->DisableHttpCache();
518 auto context = context_builder->Build();
519
520 TestDelegate d;
521 std::unique_ptr<URLRequest> req(
522 context->CreateRequest(GURL(transaction.url), DEFAULT_PRIORITY, &d,
523 TRAFFIC_ANNOTATION_FOR_TESTS));
524
525 req->set_referrer_policy(test.original_referrer_policy);
526 req->SetReferrer(test.original_referrer);
527
528 req->set_method("GET");
529 req->Start();
530
531 d.RunUntilComplete();
532
533 EXPECT_TRUE(network_layer->done_reading_called());
534
535 // Test that the referrer policy and referrer were set correctly
536 // according to the header received during the redirect.
537 EXPECT_EQ(test.expected_final_referrer_policy, req->referrer_policy());
538 EXPECT_EQ(test.expected_final_referrer, req->referrer());
539 }
540 }
541
TEST_F(URLRequestJobTest,TransactionNotCachedWhenNetworkDelegateRedirects)542 TEST_F(URLRequestJobTest, TransactionNotCachedWhenNetworkDelegateRedirects) {
543 auto context_builder = CreateTestURLRequestContextBuilder();
544 auto* network_layer = context_builder->SetHttpTransactionFactoryForTesting(
545 std::make_unique<MockNetworkLayer>());
546 auto network_delegate = std::make_unique<TestNetworkDelegate>();
547 network_delegate->set_redirect_on_headers_received_url(GURL("http://foo"));
548 context_builder->DisableHttpCache();
549 context_builder->set_network_delegate(std::move(network_delegate));
550 auto context = context_builder->Build();
551
552 ScopedMockTransaction transaction(kGZipTransaction);
553 TestDelegate d;
554 std::unique_ptr<URLRequest> req(
555 context->CreateRequest(GURL(transaction.url), DEFAULT_PRIORITY, &d,
556 TRAFFIC_ANNOTATION_FOR_TESTS));
557
558 req->set_method("GET");
559 req->Start();
560
561 d.RunUntilComplete();
562
563 EXPECT_TRUE(network_layer->stop_caching_called());
564 }
565
566 // Makes sure that ReadRawDataComplete correctly updates request status before
567 // calling ReadFilteredData.
568 // Regression test for crbug.com/553300.
TEST_F(URLRequestJobTest,EmptyBodySkipFilter)569 TEST_F(URLRequestJobTest, EmptyBodySkipFilter) {
570 auto context_builder = CreateTestURLRequestContextBuilder();
571 auto* network_layer = context_builder->SetHttpTransactionFactoryForTesting(
572 std::make_unique<MockNetworkLayer>());
573 context_builder->DisableHttpCache();
574 auto context = context_builder->Build();
575
576 ScopedMockTransaction transaction(kEmptyBodyGzipTransaction);
577 TestDelegate d;
578 std::unique_ptr<URLRequest> req(
579 context->CreateRequest(GURL(transaction.url), DEFAULT_PRIORITY, &d,
580 TRAFFIC_ANNOTATION_FOR_TESTS));
581
582 req->set_method("GET");
583 req->Start();
584
585 d.RunUntilComplete();
586
587 EXPECT_FALSE(d.request_failed());
588 EXPECT_EQ(200, req->GetResponseCode());
589 EXPECT_TRUE(d.data_received().empty());
590 EXPECT_TRUE(network_layer->done_reading_called());
591 }
592
593 // Regression test for crbug.com/575213.
TEST_F(URLRequestJobTest,InvalidContentGZipTransaction)594 TEST_F(URLRequestJobTest, InvalidContentGZipTransaction) {
595 auto context_builder = CreateTestURLRequestContextBuilder();
596 auto* network_layer = context_builder->SetHttpTransactionFactoryForTesting(
597 std::make_unique<MockNetworkLayer>());
598 context_builder->DisableHttpCache();
599 auto context = context_builder->Build();
600
601 ScopedMockTransaction transaction(kInvalidContentGZipTransaction);
602 TestDelegate d;
603 std::unique_ptr<URLRequest> req(
604 context->CreateRequest(GURL(transaction.url), DEFAULT_PRIORITY, &d,
605 TRAFFIC_ANNOTATION_FOR_TESTS));
606
607 req->set_method("GET");
608 req->Start();
609
610 d.RunUntilComplete();
611
612 // Request failed indicates the request failed before headers were received,
613 // so should be false.
614 EXPECT_FALSE(d.request_failed());
615 EXPECT_EQ(200, req->GetResponseCode());
616 EXPECT_EQ(ERR_CONTENT_DECODING_FAILED, d.request_status());
617 EXPECT_TRUE(d.data_received().empty());
618 EXPECT_FALSE(network_layer->done_reading_called());
619 }
620
621 // Regression test for crbug.com/553300.
TEST_F(URLRequestJobTest,SlowFilterRead)622 TEST_F(URLRequestJobTest, SlowFilterRead) {
623 auto context_builder = CreateTestURLRequestContextBuilder();
624 auto* network_layer = context_builder->SetHttpTransactionFactoryForTesting(
625 std::make_unique<MockNetworkLayer>());
626 context_builder->DisableHttpCache();
627 auto context = context_builder->Build();
628
629 ScopedMockTransaction transaction(kGzipSlowTransaction);
630 TestDelegate d;
631 std::unique_ptr<URLRequest> req(
632 context->CreateRequest(GURL(transaction.url), DEFAULT_PRIORITY, &d,
633 TRAFFIC_ANNOTATION_FOR_TESTS));
634
635 req->set_method("GET");
636 req->Start();
637
638 d.RunUntilComplete();
639
640 EXPECT_FALSE(d.request_failed());
641 EXPECT_EQ(200, req->GetResponseCode());
642 EXPECT_EQ("hello\n", d.data_received());
643 EXPECT_TRUE(network_layer->done_reading_called());
644 }
645
TEST_F(URLRequestJobTest,SlowBrotliRead)646 TEST_F(URLRequestJobTest, SlowBrotliRead) {
647 auto context_builder = CreateTestURLRequestContextBuilder();
648 auto* network_layer = context_builder->SetHttpTransactionFactoryForTesting(
649 std::make_unique<MockNetworkLayer>());
650 context_builder->DisableHttpCache();
651 auto context = context_builder->Build();
652
653 ScopedMockTransaction transaction(kBrotliSlowTransaction);
654 TestDelegate d;
655 std::unique_ptr<URLRequest> req(
656 context->CreateRequest(GURL(transaction.url), DEFAULT_PRIORITY, &d,
657 TRAFFIC_ANNOTATION_FOR_TESTS));
658
659 req->set_method("GET");
660 req->Start();
661
662 d.RunUntilComplete();
663
664 EXPECT_FALSE(d.request_failed());
665 EXPECT_EQ(200, req->GetResponseCode());
666 EXPECT_EQ(kHelloData, d.data_received());
667 EXPECT_TRUE(network_layer->done_reading_called());
668 // When there's a filter and a Content-Length, expected content size should
669 // not be available.
670 EXPECT_EQ(-1, req->GetExpectedContentSize());
671 }
672
TEST(URLRequestJobComputeReferrer,SetsSameOriginForMetricsOnSameOrigin)673 TEST(URLRequestJobComputeReferrer, SetsSameOriginForMetricsOnSameOrigin) {
674 bool same_origin = false;
675 URLRequestJob::ComputeReferrerForPolicy(
676 ReferrerPolicy(),
677 /*original_referrer=*/GURL("http://google.com"),
678 /*destination=*/GURL("http://google.com"), &same_origin);
679 EXPECT_TRUE(same_origin);
680 }
681
TEST(URLRequestJobComputeReferrer,SetsSameOriginForMetricsOnCrossOrigin)682 TEST(URLRequestJobComputeReferrer, SetsSameOriginForMetricsOnCrossOrigin) {
683 bool same_origin = true;
684 URLRequestJob::ComputeReferrerForPolicy(
685 ReferrerPolicy(),
686 /*original_referrer=*/GURL("http://google.com"),
687 /*destination=*/GURL("http://boggle.com"), &same_origin);
688 EXPECT_FALSE(same_origin);
689 }
690
TEST(URLRequestJobComputeReferrer,AcceptsNullptrInput)691 TEST(URLRequestJobComputeReferrer, AcceptsNullptrInput) {
692 // Shouldn't segfault.
693 URLRequestJob::ComputeReferrerForPolicy(ReferrerPolicy(), GURL(), GURL(),
694 nullptr);
695 }
696
TEST(URLRequestJobComputeReferrer,FilesystemDestination)697 TEST(URLRequestJobComputeReferrer, FilesystemDestination) {
698 EXPECT_EQ(URLRequestJob::ComputeReferrerForPolicy(
699 ReferrerPolicy::NEVER_CLEAR, GURL("https://referrer.example"),
700 GURL("filesystem:https://destination.example"), nullptr),
701 GURL("https://referrer.example"));
702 }
703
TEST(URLRequestJobComputeReferrer,TruncatesLongReferrer)704 TEST(URLRequestJobComputeReferrer, TruncatesLongReferrer) {
705 std::string original_spec = "https://referrer.example/";
706 original_spec.resize(4097, 'a');
707 const GURL kOriginalReferrer(original_spec);
708
709 EXPECT_EQ(URLRequestJob::ComputeReferrerForPolicy(ReferrerPolicy::NEVER_CLEAR,
710 kOriginalReferrer,
711 GURL("https://google.com")),
712 GURL("https://referrer.example/"));
713 }
714
TEST(URLRequestJobComputeReferrer,DoesntTruncateShortReferrer)715 TEST(URLRequestJobComputeReferrer, DoesntTruncateShortReferrer) {
716 std::string original_spec = "https://referrer.example/";
717 original_spec.resize(4096, 'a');
718 const GURL kOriginalReferrer(original_spec);
719
720 EXPECT_EQ(URLRequestJob::ComputeReferrerForPolicy(ReferrerPolicy::NEVER_CLEAR,
721 kOriginalReferrer,
722 GURL("https://google.com")),
723 kOriginalReferrer);
724 }
725
TEST(URLRequestJobComputeReferrer,DoesntTruncateEvenShorterReferrer)726 TEST(URLRequestJobComputeReferrer, DoesntTruncateEvenShorterReferrer) {
727 std::string original_spec = "https://referrer.example/";
728 original_spec.resize(4095, 'a');
729 const GURL kOriginalReferrer(original_spec);
730
731 EXPECT_EQ(URLRequestJob::ComputeReferrerForPolicy(ReferrerPolicy::NEVER_CLEAR,
732 kOriginalReferrer,
733 GURL("https://google.com")),
734 kOriginalReferrer);
735 }
736
TEST(URLRequestJobComputeReferrer,DoesntTruncateReferrerWithLongRef)737 TEST(URLRequestJobComputeReferrer, DoesntTruncateReferrerWithLongRef) {
738 // Because the "is the length greater than 4096?" check comes *after*
739 // stripping the ref in the Referrer Policy spec, a URL that is short except
740 // for having a very long ref should not be stripped to an origin by the "if
741 // the length is too long, strip to the origin" check.
742 EXPECT_EQ(URLRequestJob::ComputeReferrerForPolicy(
743 ReferrerPolicy::NEVER_CLEAR,
744 GURL(std::string("https://referrer.example/path#") +
745 std::string(5000, 'a')),
746 GURL("https://google.com")),
747 GURL("https://referrer.example/path"));
748 }
749
TEST(URLRequestJobComputeReferrer,InvalidSchemeReferrer)750 TEST(URLRequestJobComputeReferrer, InvalidSchemeReferrer) {
751 const GURL kOriginalReferrer("about:blank");
752 ASSERT_FALSE(url::IsReferrerScheme(
753 kOriginalReferrer.spec().data(),
754 kOriginalReferrer.parsed_for_possibly_invalid_spec().scheme));
755
756 EXPECT_EQ(URLRequestJob::ComputeReferrerForPolicy(ReferrerPolicy::NEVER_CLEAR,
757 kOriginalReferrer,
758 GURL("https://google.com")),
759 GURL());
760
761 EXPECT_EQ(URLRequestJob::ComputeReferrerForPolicy(ReferrerPolicy::ORIGIN,
762 kOriginalReferrer,
763 GURL("https://google.com")),
764 GURL());
765 }
766
TEST(URLRequestJobComputeReferrer,CapReferrerOnCrossOrigin)767 TEST(URLRequestJobComputeReferrer, CapReferrerOnCrossOrigin) {
768 base::test::ScopedFeatureList feature_list;
769 feature_list.InitAndEnableFeature(
770 features::kCapReferrerToOriginOnCrossOrigin);
771
772 const GURL kOriginalReferrer("https://boggle.com/path");
773
774 EXPECT_EQ(URLRequestJob::ComputeReferrerForPolicy(ReferrerPolicy::NEVER_CLEAR,
775 kOriginalReferrer,
776 GURL("https://google.com")),
777 GURL("https://boggle.com/"));
778 }
779
TEST(URLRequestJobComputeReferrer,CapReferrerOnCrossOriginRespectsStricterPolicy)780 TEST(URLRequestJobComputeReferrer,
781 CapReferrerOnCrossOriginRespectsStricterPolicy) {
782 base::test::ScopedFeatureList feature_list;
783 feature_list.InitAndEnableFeature(
784 features::kCapReferrerToOriginOnCrossOrigin);
785
786 const GURL kOriginalReferrer("https://boggle.com/path");
787
788 EXPECT_EQ(URLRequestJob::ComputeReferrerForPolicy(ReferrerPolicy::NO_REFERRER,
789 kOriginalReferrer,
790 GURL("https://google.com")),
791 GURL());
792 }
793
TEST(URLRequestJobComputeReferrer,CapReferrerOnCrossOriginDoesntCapOnSameOrigin)794 TEST(URLRequestJobComputeReferrer,
795 CapReferrerOnCrossOriginDoesntCapOnSameOrigin) {
796 base::test::ScopedFeatureList feature_list;
797 feature_list.InitAndEnableFeature(
798 features::kCapReferrerToOriginOnCrossOrigin);
799
800 const GURL kOriginalReferrer("https://boggle.com/path");
801
802 EXPECT_EQ(URLRequestJob::ComputeReferrerForPolicy(ReferrerPolicy::NEVER_CLEAR,
803 kOriginalReferrer,
804 GURL("https://boggle.com")),
805 kOriginalReferrer);
806 }
807
808 } // namespace net
809