1 // Copyright 2014 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/http/http_transaction_test_util.h"
6
7 #include <algorithm>
8 #include <unordered_map>
9 #include <utility>
10
11 #include "base/functional/bind.h"
12 #include "base/functional/callback_helpers.h"
13 #include "base/location.h"
14 #include "base/run_loop.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/task/single_thread_task_runner.h"
17 #include "base/time/clock.h"
18 #include "base/time/time.h"
19 #include "net/base/ip_address.h"
20 #include "net/base/ip_endpoint.h"
21 #include "net/base/load_flags.h"
22 #include "net/base/load_timing_info.h"
23 #include "net/base/net_errors.h"
24 #include "net/base/network_isolation_key.h"
25 #include "net/base/schemeful_site.h"
26 #include "net/cert/x509_certificate.h"
27 #include "net/disk_cache/disk_cache.h"
28 #include "net/http/http_cache.h"
29 #include "net/http/http_request_info.h"
30 #include "net/http/http_response_info.h"
31 #include "net/http/http_transaction.h"
32 #include "net/log/net_log.h"
33 #include "net/log/net_log_source.h"
34 #include "net/ssl/ssl_private_key.h"
35 #include "testing/gtest/include/gtest/gtest.h"
36 #include "url/gurl.h"
37
38 namespace net {
39
40 namespace {
41 using MockTransactionMap =
42 std::unordered_map<std::string, const MockTransaction*>;
43 static MockTransactionMap mock_transactions;
44
AddMockTransaction(const MockTransaction * trans)45 void AddMockTransaction(const MockTransaction* trans) {
46 auto result =
47 mock_transactions.insert(std::make_pair(GURL(trans->url).spec(), trans));
48 CHECK(result.second) << "Transaction already exists: " << trans->url;
49 }
50
RemoveMockTransaction(const MockTransaction * trans)51 void RemoveMockTransaction(const MockTransaction* trans) {
52 mock_transactions.erase(GURL(trans->url).spec());
53 }
54
55 } // namespace
56
DefaultTransportInfo()57 TransportInfo DefaultTransportInfo() {
58 return TransportInfo(TransportType::kDirect,
59 IPEndPoint(IPAddress::IPv4Localhost(), 80),
60 /*accept_ch_frame_arg=*/"",
61 /*cert_is_issued_by_known_root=*/false, kProtoUnknown);
62 }
63
64 //-----------------------------------------------------------------------------
65 // mock transaction data
66
67 const MockTransaction kSimpleGET_Transaction = {
68 "http://www.google.com/",
69 "GET",
70 base::Time(),
71 "",
72 LOAD_NORMAL,
73 DefaultTransportInfo(),
74 "HTTP/1.1 200 OK",
75 "Cache-Control: max-age=10000\n",
76 base::Time(),
77 "<html><body>Google Blah Blah</body></html>",
78 {},
79 std::nullopt,
80 std::nullopt,
81 TEST_MODE_NORMAL,
82 MockTransactionHandler(),
83 MockTransactionReadHandler(),
84 nullptr,
85 0,
86 0,
87 OK,
88 OK,
89 };
90
91 const MockTransaction kSimplePOST_Transaction = {
92 "http://bugdatabase.com/edit",
93 "POST",
94 base::Time(),
95 "",
96 LOAD_NORMAL,
97 DefaultTransportInfo(),
98 "HTTP/1.1 200 OK",
99 "",
100 base::Time(),
101 "<html><body>Google Blah Blah</body></html>",
102 {},
103 std::nullopt,
104 std::nullopt,
105 TEST_MODE_NORMAL,
106 MockTransactionHandler(),
107 MockTransactionReadHandler(),
108 nullptr,
109 0,
110 0,
111 OK,
112 OK,
113 };
114
115 const MockTransaction kTypicalGET_Transaction = {
116 "http://www.example.com/~foo/bar.html",
117 "GET",
118 base::Time(),
119 "",
120 LOAD_NORMAL,
121 DefaultTransportInfo(),
122 "HTTP/1.1 200 OK",
123 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
124 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n",
125 base::Time(),
126 "<html><body>Google Blah Blah</body></html>",
127 {},
128 std::nullopt,
129 std::nullopt,
130 TEST_MODE_NORMAL,
131 MockTransactionHandler(),
132 MockTransactionReadHandler(),
133 nullptr,
134 0,
135 0,
136 OK,
137 OK,
138 };
139
140 const MockTransaction kETagGET_Transaction = {
141 "http://www.google.com/foopy",
142 "GET",
143 base::Time(),
144 "",
145 LOAD_NORMAL,
146 DefaultTransportInfo(),
147 "HTTP/1.1 200 OK",
148 "Cache-Control: max-age=10000\n"
149 "Etag: \"foopy\"\n",
150 base::Time(),
151 "<html><body>Google Blah Blah</body></html>",
152 {},
153 std::nullopt,
154 std::nullopt,
155 TEST_MODE_NORMAL,
156 MockTransactionHandler(),
157 MockTransactionReadHandler(),
158 nullptr,
159 0,
160 0,
161 OK,
162 OK,
163 };
164
165 const MockTransaction kRangeGET_Transaction = {
166 "http://www.google.com/",
167 "GET",
168 base::Time(),
169 "Range: 0-100\r\n",
170 LOAD_NORMAL,
171 DefaultTransportInfo(),
172 "HTTP/1.1 200 OK",
173 "Cache-Control: max-age=10000\n",
174 base::Time(),
175 "<html><body>Google Blah Blah</body></html>",
176 {},
177 std::nullopt,
178 std::nullopt,
179 TEST_MODE_NORMAL,
180 MockTransactionHandler(),
181 MockTransactionReadHandler(),
182 nullptr,
183 0,
184 0,
185 OK,
186 OK,
187 };
188
189 static const MockTransaction* const kBuiltinMockTransactions[] = {
190 &kSimpleGET_Transaction,
191 &kSimplePOST_Transaction,
192 &kTypicalGET_Transaction,
193 &kETagGET_Transaction,
194 &kRangeGET_Transaction
195 };
196
FindMockTransaction(const GURL & url)197 const MockTransaction* FindMockTransaction(const GURL& url) {
198 // look for overrides:
199 MockTransactionMap::const_iterator it = mock_transactions.find(url.spec());
200 if (it != mock_transactions.end())
201 return it->second;
202
203 // look for builtins:
204 for (const auto* transaction : kBuiltinMockTransactions) {
205 if (url == GURL(transaction->url))
206 return transaction;
207 }
208 return nullptr;
209 }
210
ScopedMockTransaction(const char * url)211 ScopedMockTransaction::ScopedMockTransaction(const char* url)
212 : MockTransaction({nullptr}) {
213 CHECK(url);
214 this->url = url;
215 AddMockTransaction(this);
216 }
217
ScopedMockTransaction(const MockTransaction & t,const char * url)218 ScopedMockTransaction::ScopedMockTransaction(const MockTransaction& t,
219 const char* url)
220 : MockTransaction(t) {
221 if (url) {
222 this->url = url;
223 }
224 AddMockTransaction(this);
225 }
226
~ScopedMockTransaction()227 ScopedMockTransaction::~ScopedMockTransaction() {
228 RemoveMockTransaction(this);
229 }
230
MockHttpRequest(const MockTransaction & t)231 MockHttpRequest::MockHttpRequest(const MockTransaction& t) {
232 url = GURL(t.url);
233 method = t.method;
234 extra_headers.AddHeadersFromString(t.request_headers);
235 load_flags = t.load_flags;
236 SchemefulSite site(url);
237 network_isolation_key = NetworkIsolationKey(site, site);
238 network_anonymization_key = NetworkAnonymizationKey::CreateSameSite(site);
239 frame_origin = url::Origin::Create(url);
240 fps_cache_filter = t.fps_cache_filter;
241 browser_run_id = t.browser_run_id;
242 }
243
CacheKey()244 std::string MockHttpRequest::CacheKey() {
245 return *HttpCache::GenerateCacheKeyForRequest(this);
246 }
247
248 //-----------------------------------------------------------------------------
249
TestTransactionConsumer(RequestPriority priority,HttpTransactionFactory * factory)250 TestTransactionConsumer::TestTransactionConsumer(
251 RequestPriority priority,
252 HttpTransactionFactory* factory) {
253 // Disregard the error code.
254 factory->CreateTransaction(priority, &trans_);
255 }
256
257 TestTransactionConsumer::~TestTransactionConsumer() = default;
258
Start(const HttpRequestInfo * request,const NetLogWithSource & net_log)259 void TestTransactionConsumer::Start(const HttpRequestInfo* request,
260 const NetLogWithSource& net_log) {
261 state_ = State::kStarting;
262 int result =
263 trans_->Start(request,
264 base::BindOnce(&TestTransactionConsumer::OnIOComplete,
265 base::Unretained(this)),
266 net_log);
267 if (result != ERR_IO_PENDING)
268 DidStart(result);
269
270 base::RunLoop loop;
271 quit_closure_ = loop.QuitClosure();
272 loop.Run();
273 }
274
DidStart(int result)275 void TestTransactionConsumer::DidStart(int result) {
276 if (result != OK) {
277 DidFinish(result);
278 } else {
279 Read();
280 }
281 }
282
DidRead(int result)283 void TestTransactionConsumer::DidRead(int result) {
284 if (result <= 0) {
285 DidFinish(result);
286 } else {
287 content_.append(read_buf_->data(), result);
288 Read();
289 }
290 }
291
DidFinish(int result)292 void TestTransactionConsumer::DidFinish(int result) {
293 state_ = State::kDone;
294 error_ = result;
295 if (!quit_closure_.is_null()) {
296 std::move(quit_closure_).Run();
297 }
298 }
299
Read()300 void TestTransactionConsumer::Read() {
301 state_ = State::kReading;
302 read_buf_ = base::MakeRefCounted<IOBufferWithSize>(1024);
303 int result =
304 trans_->Read(read_buf_.get(), 1024,
305 base::BindOnce(&TestTransactionConsumer::OnIOComplete,
306 base::Unretained(this)));
307 if (result != ERR_IO_PENDING)
308 DidRead(result);
309 }
310
OnIOComplete(int result)311 void TestTransactionConsumer::OnIOComplete(int result) {
312 switch (state_) {
313 case State::kStarting:
314 DidStart(result);
315 break;
316 case State::kReading:
317 DidRead(result);
318 break;
319 default:
320 NOTREACHED();
321 }
322 }
323
MockNetworkTransaction(RequestPriority priority,MockNetworkLayer * factory)324 MockNetworkTransaction::MockNetworkTransaction(RequestPriority priority,
325 MockNetworkLayer* factory)
326 : priority_(priority), transaction_factory_(factory->AsWeakPtr()) {}
327
~MockNetworkTransaction()328 MockNetworkTransaction::~MockNetworkTransaction() {
329 // Use `original_request_ptr_` as in ~HttpNetworkTransaction to make sure its
330 // valid and not already freed by the consumer. Only check till Read is
331 // invoked since HttpNetworkTransaction sets request_ to nullptr when Read is
332 // invoked. See crbug.com/734037.
333 if (original_request_ptr_ && !reading_) {
334 DCHECK(original_request_ptr_->load_flags >= 0);
335 }
336 }
337
Start(const HttpRequestInfo * request,CompletionOnceCallback callback,const NetLogWithSource & net_log)338 int MockNetworkTransaction::Start(const HttpRequestInfo* request,
339 CompletionOnceCallback callback,
340 const NetLogWithSource& net_log) {
341 net_log_ = net_log;
342 CHECK(!original_request_ptr_);
343 original_request_ptr_ = request;
344 return StartInternal(*request, std::move(callback));
345 }
346
RestartIgnoringLastError(CompletionOnceCallback callback)347 int MockNetworkTransaction::RestartIgnoringLastError(
348 CompletionOnceCallback callback) {
349 return ERR_FAILED;
350 }
351
RestartWithCertificate(scoped_refptr<X509Certificate> client_cert,scoped_refptr<SSLPrivateKey> client_private_key,CompletionOnceCallback callback)352 int MockNetworkTransaction::RestartWithCertificate(
353 scoped_refptr<X509Certificate> client_cert,
354 scoped_refptr<SSLPrivateKey> client_private_key,
355 CompletionOnceCallback callback) {
356 return ERR_FAILED;
357 }
358
RestartWithAuth(const AuthCredentials & credentials,CompletionOnceCallback callback)359 int MockNetworkTransaction::RestartWithAuth(const AuthCredentials& credentials,
360 CompletionOnceCallback callback) {
361 if (!IsReadyToRestartForAuth())
362 return ERR_FAILED;
363
364 HttpRequestInfo auth_request_info = *original_request_ptr_;
365 auth_request_info.extra_headers.SetHeader("Authorization", "Bar");
366
367 // Let the MockTransactionHandler worry about this: the only way for this
368 // test to succeed is by using an explicit handler for the transaction so
369 // that server behavior can be simulated.
370 return StartInternal(std::move(auth_request_info), std::move(callback));
371 }
372
PopulateNetErrorDetails(NetErrorDetails *) const373 void MockNetworkTransaction::PopulateNetErrorDetails(
374 NetErrorDetails* /*details*/) const {
375 NOTIMPLEMENTED();
376 }
377
IsReadyToRestartForAuth()378 bool MockNetworkTransaction::IsReadyToRestartForAuth() {
379 CHECK(original_request_ptr_);
380 if (!original_request_ptr_->extra_headers.HasHeader("X-Require-Mock-Auth")) {
381 return false;
382 }
383
384 // Allow the mock server to decide whether authentication is required or not.
385 std::string status_line = response_.headers->GetStatusLine();
386 return status_line.find(" 401 ") != std::string::npos ||
387 status_line.find(" 407 ") != std::string::npos;
388 }
389
Read(net::IOBuffer * buf,int buf_len,CompletionOnceCallback callback)390 int MockNetworkTransaction::Read(net::IOBuffer* buf,
391 int buf_len,
392 CompletionOnceCallback callback) {
393 const MockTransaction* t = FindMockTransaction(current_request_.url);
394 DCHECK(t);
395
396 CHECK(!done_reading_called_);
397 reading_ = true;
398
399 int num = t->read_return_code;
400
401 if (OK == num) {
402 if (t->read_handler) {
403 num = t->read_handler.Run(content_length_, data_cursor_, buf, buf_len);
404 data_cursor_ += num;
405 } else {
406 int data_len = static_cast<int>(data_.size());
407 num = std::min(static_cast<int64_t>(buf_len), data_len - data_cursor_);
408 if (test_mode_ & TEST_MODE_SLOW_READ)
409 num = std::min(num, 1);
410 if (num) {
411 memcpy(buf->data(), data_.data() + data_cursor_, num);
412 data_cursor_ += num;
413 }
414 }
415 }
416
417 if (test_mode_ & TEST_MODE_SYNC_NET_READ)
418 return num;
419
420 CallbackLater(std::move(callback), num);
421 return ERR_IO_PENDING;
422 }
423
StopCaching()424 void MockNetworkTransaction::StopCaching() {
425 if (transaction_factory_.get())
426 transaction_factory_->TransactionStopCaching();
427 }
428
GetTotalReceivedBytes() const429 int64_t MockNetworkTransaction::GetTotalReceivedBytes() const {
430 return received_bytes_;
431 }
432
GetTotalSentBytes() const433 int64_t MockNetworkTransaction::GetTotalSentBytes() const {
434 return sent_bytes_;
435 }
436
DoneReading()437 void MockNetworkTransaction::DoneReading() {
438 CHECK(!done_reading_called_);
439 done_reading_called_ = true;
440 if (transaction_factory_.get())
441 transaction_factory_->TransactionDoneReading();
442 }
443
GetResponseInfo() const444 const HttpResponseInfo* MockNetworkTransaction::GetResponseInfo() const {
445 return &response_;
446 }
447
GetLoadState() const448 LoadState MockNetworkTransaction::GetLoadState() const {
449 if (data_cursor_)
450 return LOAD_STATE_READING_RESPONSE;
451 return LOAD_STATE_IDLE;
452 }
453
SetQuicServerInfo(QuicServerInfo * quic_server_info)454 void MockNetworkTransaction::SetQuicServerInfo(
455 QuicServerInfo* quic_server_info) {
456 }
457
GetLoadTimingInfo(LoadTimingInfo * load_timing_info) const458 bool MockNetworkTransaction::GetLoadTimingInfo(
459 LoadTimingInfo* load_timing_info) const {
460 if (socket_log_id_ != NetLogSource::kInvalidId) {
461 // The minimal set of times for a request that gets a response, assuming it
462 // gets a new socket.
463 load_timing_info->socket_reused = false;
464 load_timing_info->socket_log_id = socket_log_id_;
465 load_timing_info->connect_timing.connect_start = base::TimeTicks::Now();
466 load_timing_info->connect_timing.connect_end = base::TimeTicks::Now();
467 load_timing_info->send_start = base::TimeTicks::Now();
468 load_timing_info->send_end = base::TimeTicks::Now();
469 } else {
470 // If there's no valid socket ID, just use the generic socket reused values.
471 // No tests currently depend on this, just should not match the values set
472 // by a cache hit.
473 load_timing_info->socket_reused = true;
474 load_timing_info->send_start = base::TimeTicks::Now();
475 load_timing_info->send_end = base::TimeTicks::Now();
476 }
477 return true;
478 }
479
GetRemoteEndpoint(IPEndPoint * endpoint) const480 bool MockNetworkTransaction::GetRemoteEndpoint(IPEndPoint* endpoint) const {
481 *endpoint = IPEndPoint(IPAddress(127, 0, 0, 1), 80);
482 return true;
483 }
484
SetPriority(RequestPriority priority)485 void MockNetworkTransaction::SetPriority(RequestPriority priority) {
486 priority_ = priority;
487 }
488
SetWebSocketHandshakeStreamCreateHelper(WebSocketHandshakeStreamBase::CreateHelper * create_helper)489 void MockNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
490 WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
491 websocket_handshake_stream_create_helper_ = create_helper;
492 }
493
494 // static
495 const int64_t MockNetworkTransaction::kTotalReceivedBytes = 1000;
496
497 // static
498 const int64_t MockNetworkTransaction::kTotalSentBytes = 100;
499
StartInternal(HttpRequestInfo request,CompletionOnceCallback callback)500 int MockNetworkTransaction::StartInternal(HttpRequestInfo request,
501 CompletionOnceCallback callback) {
502 current_request_ = std::move(request);
503 const MockTransaction* t = FindMockTransaction(current_request_.url);
504 if (!t) {
505 return ERR_FAILED;
506 }
507 test_mode_ = t->test_mode;
508
509 // Return immediately if we're returning an error.
510 if (OK != t->start_return_code) {
511 if (test_mode_ & TEST_MODE_SYNC_NET_START) {
512 return t->start_return_code;
513 }
514 CallbackLater(std::move(callback), t->start_return_code);
515 return ERR_IO_PENDING;
516 }
517
518 next_state_ = State::NOTIFY_BEFORE_CREATE_STREAM;
519 int rv = DoLoop(OK);
520 if (rv == ERR_IO_PENDING) {
521 callback_ = std::move(callback);
522 }
523 return rv;
524 }
525
DoNotifyBeforeCreateStream()526 int MockNetworkTransaction::DoNotifyBeforeCreateStream() {
527 next_state_ = State::CREATE_STREAM;
528 bool defer = false;
529 if (!before_network_start_callback_.is_null()) {
530 std::move(before_network_start_callback_).Run(&defer);
531 }
532 if (!defer) {
533 return OK;
534 }
535 return ERR_IO_PENDING;
536 }
537
DoCreateStream()538 int MockNetworkTransaction::DoCreateStream() {
539 next_state_ = State::CREATE_STREAM_COMPLETE;
540 if (test_mode_ & TEST_MODE_SYNC_NET_START) {
541 return OK;
542 }
543 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
544 FROM_HERE, base::BindOnce(&MockNetworkTransaction::OnIOComplete,
545 weak_factory_.GetWeakPtr(), OK));
546 return ERR_IO_PENDING;
547 }
548
DoCreateStreamComplete(int result)549 int MockNetworkTransaction::DoCreateStreamComplete(int result) {
550 // We don't have a logic which simulate stream creation
551 CHECK_EQ(OK, result);
552 next_state_ = State::CONNECTED_CALLBACK;
553 return OK;
554 }
555
DoConnectedCallback()556 int MockNetworkTransaction::DoConnectedCallback() {
557 next_state_ = State::CONNECTED_CALLBACK_COMPLETE;
558 if (connected_callback_.is_null()) {
559 return OK;
560 }
561
562 const MockTransaction* t = FindMockTransaction(current_request_.url);
563 CHECK(t);
564 return connected_callback_.Run(
565 t->transport_info, base::BindOnce(&MockNetworkTransaction::OnIOComplete,
566 weak_factory_.GetWeakPtr()));
567 }
568
DoConnectedCallbackComplete(int result)569 int MockNetworkTransaction::DoConnectedCallbackComplete(int result) {
570 if (result != OK) {
571 return result;
572 }
573 next_state_ = State::BUILD_REQUEST;
574 return OK;
575 }
576
DoBuildRequest()577 int MockNetworkTransaction::DoBuildRequest() {
578 next_state_ = State::BUILD_REQUEST_COMPLETE;
579 if (modify_request_headers_callback_) {
580 modify_request_headers_callback_.Run(¤t_request_.extra_headers);
581 }
582 return OK;
583 }
584
DoBuildRequestComplete(int result)585 int MockNetworkTransaction::DoBuildRequestComplete(int result) {
586 CHECK_EQ(OK, result);
587 next_state_ = State::SEND_REQUEST;
588 return OK;
589 }
590
DoSendRequest()591 int MockNetworkTransaction::DoSendRequest() {
592 next_state_ = State::SEND_REQUEST_COMPLETE;
593
594 sent_bytes_ = kTotalSentBytes;
595 received_bytes_ = kTotalReceivedBytes;
596
597 const MockTransaction* t = FindMockTransaction(current_request_.url);
598 CHECK(t);
599
600 std::string resp_status = t->status;
601 std::string resp_headers = t->response_headers;
602 std::string resp_data = t->data;
603
604 if (t->handler) {
605 t->handler.Run(¤t_request_, &resp_status, &resp_headers, &resp_data);
606 }
607 std::string header_data =
608 base::StringPrintf("%s\n%s\n", resp_status.c_str(), resp_headers.c_str());
609 std::replace(header_data.begin(), header_data.end(), '\n', '\0');
610
611 response_.request_time = transaction_factory_->Now();
612 if (!t->request_time.is_null())
613 response_.request_time = t->request_time;
614
615 response_.was_cached = false;
616 response_.network_accessed = true;
617 response_.remote_endpoint = t->transport_info.endpoint;
618 response_.was_fetched_via_proxy =
619 t->transport_info.type == TransportType::kProxied;
620
621 response_.response_time = transaction_factory_->Now();
622 if (!t->response_time.is_null())
623 response_.response_time = t->response_time;
624
625 response_.headers = base::MakeRefCounted<HttpResponseHeaders>(header_data);
626 response_.ssl_info.cert = t->cert;
627 response_.ssl_info.cert_status = t->cert_status;
628 response_.ssl_info.connection_status = t->ssl_connection_status;
629 response_.dns_aliases = t->dns_aliases;
630 data_ = resp_data;
631 content_length_ = response_.headers->GetContentLength();
632
633 if (net_log_.net_log()) {
634 socket_log_id_ = net_log_.net_log()->NextID();
635 }
636
637 if (current_request_.load_flags & LOAD_PREFETCH) {
638 response_.unused_since_prefetch = true;
639 }
640
641 if (current_request_.load_flags & LOAD_RESTRICTED_PREFETCH) {
642 DCHECK(response_.unused_since_prefetch);
643 response_.restricted_prefetch = true;
644 }
645 return OK;
646 }
647
DoSendRequestComplete(int result)648 int MockNetworkTransaction::DoSendRequestComplete(int result) {
649 CHECK_EQ(OK, result);
650 next_state_ = State::READ_HEADERS;
651 return OK;
652 }
653
DoReadHeaders()654 int MockNetworkTransaction::DoReadHeaders() {
655 next_state_ = State::READ_HEADERS_COMPLETE;
656 return OK;
657 }
658
DoReadHeadersComplete(int result)659 int MockNetworkTransaction::DoReadHeadersComplete(int result) {
660 CHECK_EQ(OK, result);
661 return OK;
662 }
663
DoLoop(int result)664 int MockNetworkTransaction::DoLoop(int result) {
665 CHECK(next_state_ != State::NONE);
666
667 int rv = result;
668 do {
669 State state = next_state_;
670 next_state_ = State::NONE;
671 switch (state) {
672 case State::NOTIFY_BEFORE_CREATE_STREAM:
673 CHECK_EQ(OK, rv);
674 rv = DoNotifyBeforeCreateStream();
675 break;
676 case State::CREATE_STREAM:
677 CHECK_EQ(OK, rv);
678 rv = DoCreateStream();
679 break;
680 case State::CREATE_STREAM_COMPLETE:
681 rv = DoCreateStreamComplete(rv);
682 break;
683 case State::CONNECTED_CALLBACK:
684 rv = DoConnectedCallback();
685 break;
686 case State::CONNECTED_CALLBACK_COMPLETE:
687 rv = DoConnectedCallbackComplete(rv);
688 break;
689 case State::BUILD_REQUEST:
690 CHECK_EQ(OK, rv);
691 rv = DoBuildRequest();
692 break;
693 case State::BUILD_REQUEST_COMPLETE:
694 rv = DoBuildRequestComplete(rv);
695 break;
696 case State::SEND_REQUEST:
697 CHECK_EQ(OK, rv);
698 rv = DoSendRequest();
699 break;
700 case State::SEND_REQUEST_COMPLETE:
701 rv = DoSendRequestComplete(rv);
702 break;
703 case State::READ_HEADERS:
704 CHECK_EQ(OK, rv);
705 rv = DoReadHeaders();
706 break;
707 case State::READ_HEADERS_COMPLETE:
708 rv = DoReadHeadersComplete(rv);
709 break;
710 default:
711 NOTREACHED() << "bad state";
712 rv = ERR_FAILED;
713 break;
714 }
715 } while (rv != ERR_IO_PENDING && next_state_ != State::NONE);
716
717 return rv;
718 }
719
OnIOComplete(int result)720 void MockNetworkTransaction::OnIOComplete(int result) {
721 int rv = DoLoop(result);
722 if (rv != ERR_IO_PENDING) {
723 CHECK(callback_);
724 std::move(callback_).Run(rv);
725 }
726 }
727
SetBeforeNetworkStartCallback(BeforeNetworkStartCallback callback)728 void MockNetworkTransaction::SetBeforeNetworkStartCallback(
729 BeforeNetworkStartCallback callback) {
730 before_network_start_callback_ = std::move(callback);
731 }
732
SetModifyRequestHeadersCallback(base::RepeatingCallback<void (net::HttpRequestHeaders *)> callback)733 void MockNetworkTransaction::SetModifyRequestHeadersCallback(
734 base::RepeatingCallback<void(net::HttpRequestHeaders*)> callback) {
735 modify_request_headers_callback_ = std::move(callback);
736 }
737
SetConnectedCallback(const ConnectedCallback & callback)738 void MockNetworkTransaction::SetConnectedCallback(
739 const ConnectedCallback& callback) {
740 connected_callback_ = callback;
741 }
742
ResumeNetworkStart()743 int MockNetworkTransaction::ResumeNetworkStart() {
744 CHECK_EQ(next_state_, State::CREATE_STREAM);
745 return DoLoop(OK);
746 }
747
GetConnectionAttempts() const748 ConnectionAttempts MockNetworkTransaction::GetConnectionAttempts() const {
749 // TODO(ricea): Replace this with a proper implementation if needed.
750 return {};
751 }
752
CloseConnectionOnDestruction()753 void MockNetworkTransaction::CloseConnectionOnDestruction() {
754 NOTIMPLEMENTED();
755 }
756
IsMdlMatchForMetrics() const757 bool MockNetworkTransaction::IsMdlMatchForMetrics() const {
758 return false;
759 }
760
CallbackLater(CompletionOnceCallback callback,int result)761 void MockNetworkTransaction::CallbackLater(CompletionOnceCallback callback,
762 int result) {
763 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
764 FROM_HERE,
765 base::BindOnce(&MockNetworkTransaction::RunCallback,
766 weak_factory_.GetWeakPtr(), std::move(callback), result));
767 }
768
RunCallback(CompletionOnceCallback callback,int result)769 void MockNetworkTransaction::RunCallback(CompletionOnceCallback callback,
770 int result) {
771 std::move(callback).Run(result);
772 }
773
774 MockNetworkLayer::MockNetworkLayer() = default;
775
776 MockNetworkLayer::~MockNetworkLayer() = default;
777
TransactionDoneReading()778 void MockNetworkLayer::TransactionDoneReading() {
779 CHECK(!done_reading_called_);
780 done_reading_called_ = true;
781 }
782
TransactionStopCaching()783 void MockNetworkLayer::TransactionStopCaching() {
784 stop_caching_called_ = true;
785 }
786
ResetTransactionCount()787 void MockNetworkLayer::ResetTransactionCount() {
788 transaction_count_ = 0;
789 }
790
CreateTransaction(RequestPriority priority,std::unique_ptr<HttpTransaction> * trans)791 int MockNetworkLayer::CreateTransaction(
792 RequestPriority priority,
793 std::unique_ptr<HttpTransaction>* trans) {
794 transaction_count_++;
795 last_create_transaction_priority_ = priority;
796 auto mock_transaction =
797 std::make_unique<MockNetworkTransaction>(priority, this);
798 last_transaction_ = mock_transaction->AsWeakPtr();
799 *trans = std::move(mock_transaction);
800 return OK;
801 }
802
GetCache()803 HttpCache* MockNetworkLayer::GetCache() {
804 return nullptr;
805 }
806
GetSession()807 HttpNetworkSession* MockNetworkLayer::GetSession() {
808 return nullptr;
809 }
810
SetClock(base::Clock * clock)811 void MockNetworkLayer::SetClock(base::Clock* clock) {
812 DCHECK(!clock_);
813 clock_ = clock;
814 }
815
Now()816 base::Time MockNetworkLayer::Now() {
817 if (clock_)
818 return clock_->Now();
819 return base::Time::Now();
820 }
821
822 //-----------------------------------------------------------------------------
823 // helpers
824
ReadTransaction(HttpTransaction * trans,std::string * result)825 int ReadTransaction(HttpTransaction* trans, std::string* result) {
826 int rv;
827
828 std::string content;
829 do {
830 TestCompletionCallback callback;
831 auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
832 rv = trans->Read(buf.get(), 256, callback.callback());
833 if (rv == ERR_IO_PENDING) {
834 rv = callback.WaitForResult();
835 base::RunLoop().RunUntilIdle();
836 }
837
838 if (rv > 0)
839 content.append(buf->data(), rv);
840 else if (rv < 0)
841 return rv;
842 } while (rv > 0);
843
844 result->swap(content);
845 return OK;
846 }
847
848 //-----------------------------------------------------------------------------
849 // connected callback handler
850
851 ConnectedHandler::ConnectedHandler() = default;
852 ConnectedHandler::~ConnectedHandler() = default;
853
854 ConnectedHandler::ConnectedHandler(const ConnectedHandler&) = default;
855 ConnectedHandler& ConnectedHandler::operator=(const ConnectedHandler&) =
856 default;
857 ConnectedHandler::ConnectedHandler(ConnectedHandler&&) = default;
858 ConnectedHandler& ConnectedHandler::operator=(ConnectedHandler&&) = default;
859
OnConnected(const TransportInfo & info,CompletionOnceCallback callback)860 int ConnectedHandler::OnConnected(const TransportInfo& info,
861 CompletionOnceCallback callback) {
862 transports_.push_back(info);
863 if (run_callback_) {
864 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
865 FROM_HERE, base::BindOnce(std::move(callback), result_));
866 return net::ERR_IO_PENDING;
867 }
868 return result_;
869 }
870
871 } // namespace net
872