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