• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }  // namespace
45 
DefaultTransportInfo()46 TransportInfo DefaultTransportInfo() {
47   return TransportInfo(TransportType::kDirect,
48                        IPEndPoint(IPAddress::IPv4Localhost(), 80), "");
49 }
50 
51 //-----------------------------------------------------------------------------
52 // mock transaction data
53 
54 const MockTransaction kSimpleGET_Transaction = {
55     "http://www.google.com/",
56     "GET",
57     base::Time(),
58     "",
59     LOAD_NORMAL,
60     DefaultTransportInfo(),
61     "HTTP/1.1 200 OK",
62     "Cache-Control: max-age=10000\n",
63     base::Time(),
64     "<html><body>Google Blah Blah</body></html>",
65     {},
66     absl::nullopt,
67     absl::nullopt,
68     TEST_MODE_NORMAL,
69     nullptr,
70     nullptr,
71     nullptr,
72     0,
73     0,
74     OK,
75     OK,
76 };
77 
78 const MockTransaction kSimplePOST_Transaction = {
79     "http://bugdatabase.com/edit",
80     "POST",
81     base::Time(),
82     "",
83     LOAD_NORMAL,
84     DefaultTransportInfo(),
85     "HTTP/1.1 200 OK",
86     "",
87     base::Time(),
88     "<html><body>Google Blah Blah</body></html>",
89     {},
90     absl::nullopt,
91     absl::nullopt,
92     TEST_MODE_NORMAL,
93     nullptr,
94     nullptr,
95     nullptr,
96     0,
97     0,
98     OK,
99     OK,
100 };
101 
102 const MockTransaction kTypicalGET_Transaction = {
103     "http://www.example.com/~foo/bar.html",
104     "GET",
105     base::Time(),
106     "",
107     LOAD_NORMAL,
108     DefaultTransportInfo(),
109     "HTTP/1.1 200 OK",
110     "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
111     "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n",
112     base::Time(),
113     "<html><body>Google Blah Blah</body></html>",
114     {},
115     absl::nullopt,
116     absl::nullopt,
117     TEST_MODE_NORMAL,
118     nullptr,
119     nullptr,
120     nullptr,
121     0,
122     0,
123     OK,
124     OK,
125 };
126 
127 const MockTransaction kETagGET_Transaction = {
128     "http://www.google.com/foopy",
129     "GET",
130     base::Time(),
131     "",
132     LOAD_NORMAL,
133     DefaultTransportInfo(),
134     "HTTP/1.1 200 OK",
135     "Cache-Control: max-age=10000\n"
136     "Etag: \"foopy\"\n",
137     base::Time(),
138     "<html><body>Google Blah Blah</body></html>",
139     {},
140     absl::nullopt,
141     absl::nullopt,
142     TEST_MODE_NORMAL,
143     nullptr,
144     nullptr,
145     nullptr,
146     0,
147     0,
148     OK,
149     OK,
150 };
151 
152 const MockTransaction kRangeGET_Transaction = {
153     "http://www.google.com/",
154     "GET",
155     base::Time(),
156     "Range: 0-100\r\n",
157     LOAD_NORMAL,
158     DefaultTransportInfo(),
159     "HTTP/1.1 200 OK",
160     "Cache-Control: max-age=10000\n",
161     base::Time(),
162     "<html><body>Google Blah Blah</body></html>",
163     {},
164     absl::nullopt,
165     absl::nullopt,
166     TEST_MODE_NORMAL,
167     nullptr,
168     nullptr,
169     nullptr,
170     0,
171     0,
172     OK,
173     OK,
174 };
175 
176 static const MockTransaction* const kBuiltinMockTransactions[] = {
177   &kSimpleGET_Transaction,
178   &kSimplePOST_Transaction,
179   &kTypicalGET_Transaction,
180   &kETagGET_Transaction,
181   &kRangeGET_Transaction
182 };
183 
FindMockTransaction(const GURL & url)184 const MockTransaction* FindMockTransaction(const GURL& url) {
185   // look for overrides:
186   MockTransactionMap::const_iterator it = mock_transactions.find(url.spec());
187   if (it != mock_transactions.end())
188     return it->second;
189 
190   // look for builtins:
191   for (const auto* transaction : kBuiltinMockTransactions) {
192     if (url == GURL(transaction->url))
193       return transaction;
194   }
195   return nullptr;
196 }
197 
AddMockTransaction(const MockTransaction * trans)198 void AddMockTransaction(const MockTransaction* trans) {
199   mock_transactions[GURL(trans->url).spec()] = trans;
200 }
201 
RemoveMockTransaction(const MockTransaction * trans)202 void RemoveMockTransaction(const MockTransaction* trans) {
203   mock_transactions.erase(GURL(trans->url).spec());
204 }
205 
MockHttpRequest(const MockTransaction & t)206 MockHttpRequest::MockHttpRequest(const MockTransaction& t) {
207   url = GURL(t.url);
208   method = t.method;
209   extra_headers.AddHeadersFromString(t.request_headers);
210   load_flags = t.load_flags;
211   SchemefulSite site(url);
212   network_isolation_key = NetworkIsolationKey(site, site);
213   network_anonymization_key = NetworkAnonymizationKey::CreateSameSite(site);
214   fps_cache_filter = t.fps_cache_filter;
215   browser_run_id = t.browser_run_id;
216 }
217 
CacheKey()218 std::string MockHttpRequest::CacheKey() {
219   return *HttpCache::GenerateCacheKeyForRequest(this);
220 }
221 
222 //-----------------------------------------------------------------------------
223 
224 // static
225 int TestTransactionConsumer::quit_counter_ = 0;
226 
TestTransactionConsumer(RequestPriority priority,HttpTransactionFactory * factory)227 TestTransactionConsumer::TestTransactionConsumer(
228     RequestPriority priority,
229     HttpTransactionFactory* factory) {
230   // Disregard the error code.
231   factory->CreateTransaction(priority, &trans_);
232   ++quit_counter_;
233 }
234 
235 TestTransactionConsumer::~TestTransactionConsumer() = default;
236 
Start(const HttpRequestInfo * request,const NetLogWithSource & net_log)237 void TestTransactionConsumer::Start(const HttpRequestInfo* request,
238                                     const NetLogWithSource& net_log) {
239   state_ = State::kStarting;
240   int result =
241       trans_->Start(request,
242                     base::BindOnce(&TestTransactionConsumer::OnIOComplete,
243                                    base::Unretained(this)),
244                     net_log);
245   if (result != ERR_IO_PENDING)
246     DidStart(result);
247 }
248 
DidStart(int result)249 void TestTransactionConsumer::DidStart(int result) {
250   if (result != OK) {
251     DidFinish(result);
252   } else {
253     Read();
254   }
255 }
256 
DidRead(int result)257 void TestTransactionConsumer::DidRead(int result) {
258   if (result <= 0) {
259     DidFinish(result);
260   } else {
261     content_.append(read_buf_->data(), result);
262     Read();
263   }
264 }
265 
DidFinish(int result)266 void TestTransactionConsumer::DidFinish(int result) {
267   state_ = State::kDone;
268   error_ = result;
269   if (--quit_counter_ == 0)
270     base::RunLoop::QuitCurrentWhenIdleDeprecated();
271 }
272 
Read()273 void TestTransactionConsumer::Read() {
274   state_ = State::kReading;
275   read_buf_ = base::MakeRefCounted<IOBuffer>(1024);
276   int result =
277       trans_->Read(read_buf_.get(), 1024,
278                    base::BindOnce(&TestTransactionConsumer::OnIOComplete,
279                                   base::Unretained(this)));
280   if (result != ERR_IO_PENDING)
281     DidRead(result);
282 }
283 
OnIOComplete(int result)284 void TestTransactionConsumer::OnIOComplete(int result) {
285   switch (state_) {
286     case State::kStarting:
287       DidStart(result);
288       break;
289     case State::kReading:
290       DidRead(result);
291       break;
292     default:
293       NOTREACHED();
294   }
295 }
296 
MockNetworkTransaction(RequestPriority priority,MockNetworkLayer * factory)297 MockNetworkTransaction::MockNetworkTransaction(RequestPriority priority,
298                                                MockNetworkLayer* factory)
299     : priority_(priority), transaction_factory_(factory->AsWeakPtr()) {}
300 
~MockNetworkTransaction()301 MockNetworkTransaction::~MockNetworkTransaction() {
302   // Use request_ as in ~HttpNetworkTransaction to make sure its valid and not
303   // already freed by the consumer. Only check till Read is invoked since
304   // HttpNetworkTransaction sets request_ to nullptr when Read is invoked.
305   // See crbug.com/734037.
306   if (request_ && !reading_)
307     DCHECK(request_->load_flags >= 0);
308 }
309 
Start(const HttpRequestInfo * request,CompletionOnceCallback callback,const NetLogWithSource & net_log)310 int MockNetworkTransaction::Start(const HttpRequestInfo* request,
311                                   CompletionOnceCallback callback,
312                                   const NetLogWithSource& net_log) {
313   if (request_)
314     return ERR_FAILED;
315 
316   request_ = request;
317   return StartInternal(request, std::move(callback), net_log);
318 }
319 
RestartIgnoringLastError(CompletionOnceCallback callback)320 int MockNetworkTransaction::RestartIgnoringLastError(
321     CompletionOnceCallback callback) {
322   return ERR_FAILED;
323 }
324 
RestartWithCertificate(scoped_refptr<X509Certificate> client_cert,scoped_refptr<SSLPrivateKey> client_private_key,CompletionOnceCallback callback)325 int MockNetworkTransaction::RestartWithCertificate(
326     scoped_refptr<X509Certificate> client_cert,
327     scoped_refptr<SSLPrivateKey> client_private_key,
328     CompletionOnceCallback callback) {
329   return ERR_FAILED;
330 }
331 
RestartWithAuth(const AuthCredentials & credentials,CompletionOnceCallback callback)332 int MockNetworkTransaction::RestartWithAuth(const AuthCredentials& credentials,
333                                             CompletionOnceCallback callback) {
334   if (!IsReadyToRestartForAuth())
335     return ERR_FAILED;
336 
337   HttpRequestInfo auth_request_info = *request_;
338   auth_request_info.extra_headers.SetHeader("Authorization", "Bar");
339 
340   // Let the MockTransactionHandler worry about this: the only way for this
341   // test to succeed is by using an explicit handler for the transaction so
342   // that server behavior can be simulated.
343   return StartInternal(&auth_request_info, std::move(callback),
344                        NetLogWithSource());
345 }
346 
PopulateNetErrorDetails(NetErrorDetails *) const347 void MockNetworkTransaction::PopulateNetErrorDetails(
348     NetErrorDetails* /*details*/) const {
349   NOTIMPLEMENTED();
350 }
351 
IsReadyToRestartForAuth()352 bool MockNetworkTransaction::IsReadyToRestartForAuth() {
353   if (!request_)
354     return false;
355 
356   if (!request_->extra_headers.HasHeader("X-Require-Mock-Auth"))
357     return false;
358 
359   // Allow the mock server to decide whether authentication is required or not.
360   std::string status_line = response_.headers->GetStatusLine();
361   return status_line.find(" 401 ") != std::string::npos ||
362       status_line.find(" 407 ") != std::string::npos;
363 }
364 
Read(net::IOBuffer * buf,int buf_len,CompletionOnceCallback callback)365 int MockNetworkTransaction::Read(net::IOBuffer* buf,
366                                  int buf_len,
367                                  CompletionOnceCallback callback) {
368   const MockTransaction* t = FindMockTransaction(request_->url);
369   DCHECK(t);
370 
371   CHECK(!done_reading_called_);
372   reading_ = true;
373 
374   int num = t->read_return_code;
375 
376   if (OK == num) {
377     if (read_handler_) {
378       num = (*read_handler_)(content_length_, data_cursor_, buf, buf_len);
379       data_cursor_ += num;
380     } else {
381       int data_len = static_cast<int>(data_.size());
382       num = std::min(static_cast<int64_t>(buf_len), data_len - data_cursor_);
383       if (test_mode_ & TEST_MODE_SLOW_READ)
384         num = std::min(num, 1);
385       if (num) {
386         memcpy(buf->data(), data_.data() + data_cursor_, num);
387         data_cursor_ += num;
388       }
389     }
390   }
391 
392   if (test_mode_ & TEST_MODE_SYNC_NET_READ)
393     return num;
394 
395   CallbackLater(std::move(callback), num);
396   return ERR_IO_PENDING;
397 }
398 
StopCaching()399 void MockNetworkTransaction::StopCaching() {
400   if (transaction_factory_.get())
401     transaction_factory_->TransactionStopCaching();
402 }
403 
GetTotalReceivedBytes() const404 int64_t MockNetworkTransaction::GetTotalReceivedBytes() const {
405   return received_bytes_;
406 }
407 
GetTotalSentBytes() const408 int64_t MockNetworkTransaction::GetTotalSentBytes() const {
409   return sent_bytes_;
410 }
411 
DoneReading()412 void MockNetworkTransaction::DoneReading() {
413   CHECK(!done_reading_called_);
414   done_reading_called_ = true;
415   if (transaction_factory_.get())
416     transaction_factory_->TransactionDoneReading();
417 }
418 
GetResponseInfo() const419 const HttpResponseInfo* MockNetworkTransaction::GetResponseInfo() const {
420   return &response_;
421 }
422 
GetLoadState() const423 LoadState MockNetworkTransaction::GetLoadState() const {
424   if (data_cursor_)
425     return LOAD_STATE_READING_RESPONSE;
426   return LOAD_STATE_IDLE;
427 }
428 
SetQuicServerInfo(QuicServerInfo * quic_server_info)429 void MockNetworkTransaction::SetQuicServerInfo(
430     QuicServerInfo* quic_server_info) {
431 }
432 
GetLoadTimingInfo(LoadTimingInfo * load_timing_info) const433 bool MockNetworkTransaction::GetLoadTimingInfo(
434     LoadTimingInfo* load_timing_info) const {
435   if (socket_log_id_ != NetLogSource::kInvalidId) {
436     // The minimal set of times for a request that gets a response, assuming it
437     // gets a new socket.
438     load_timing_info->socket_reused = false;
439     load_timing_info->socket_log_id = socket_log_id_;
440     load_timing_info->connect_timing.connect_start = base::TimeTicks::Now();
441     load_timing_info->connect_timing.connect_end = base::TimeTicks::Now();
442     load_timing_info->send_start = base::TimeTicks::Now();
443     load_timing_info->send_end = base::TimeTicks::Now();
444   } else {
445     // If there's no valid socket ID, just use the generic socket reused values.
446     // No tests currently depend on this, just should not match the values set
447     // by a cache hit.
448     load_timing_info->socket_reused = true;
449     load_timing_info->send_start = base::TimeTicks::Now();
450     load_timing_info->send_end = base::TimeTicks::Now();
451   }
452   return true;
453 }
454 
GetRemoteEndpoint(IPEndPoint * endpoint) const455 bool MockNetworkTransaction::GetRemoteEndpoint(IPEndPoint* endpoint) const {
456   *endpoint = IPEndPoint(IPAddress(127, 0, 0, 1), 80);
457   return true;
458 }
459 
SetPriority(RequestPriority priority)460 void MockNetworkTransaction::SetPriority(RequestPriority priority) {
461   priority_ = priority;
462 }
463 
SetWebSocketHandshakeStreamCreateHelper(WebSocketHandshakeStreamBase::CreateHelper * create_helper)464 void MockNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
465     WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
466   websocket_handshake_stream_create_helper_ = create_helper;
467 }
468 
469 // static
470 const int64_t MockNetworkTransaction::kTotalReceivedBytes = 1000;
471 
472 // static
473 const int64_t MockNetworkTransaction::kTotalSentBytes = 100;
474 
StartInternal(const HttpRequestInfo * request,CompletionOnceCallback callback,const NetLogWithSource & net_log)475 int MockNetworkTransaction::StartInternal(const HttpRequestInfo* request,
476                                           CompletionOnceCallback callback,
477                                           const NetLogWithSource& net_log) {
478   const MockTransaction* t = FindMockTransaction(request->url);
479   if (!t)
480     return ERR_FAILED;
481 
482   test_mode_ = t->test_mode;
483 
484   // Return immediately if we're returning an error.
485   if (OK != t->start_return_code) {
486     if (test_mode_ & TEST_MODE_SYNC_NET_START)
487       return t->start_return_code;
488     CallbackLater(std::move(callback), t->start_return_code);
489     return ERR_IO_PENDING;
490   }
491 
492   sent_bytes_ = kTotalSentBytes;
493   received_bytes_ = kTotalReceivedBytes;
494 
495   std::string resp_status = t->status;
496   std::string resp_headers = t->response_headers;
497   std::string resp_data = t->data;
498   if (t->handler)
499     (t->handler)(request, &resp_status, &resp_headers, &resp_data);
500   if (t->read_handler)
501     read_handler_ = t->read_handler;
502 
503   std::string header_data = base::StringPrintf(
504       "%s\n%s\n", resp_status.c_str(), resp_headers.c_str());
505   std::replace(header_data.begin(), header_data.end(), '\n', '\0');
506 
507   response_.request_time = transaction_factory_->Now();
508   if (!t->request_time.is_null())
509     response_.request_time = t->request_time;
510 
511   response_.was_cached = false;
512   response_.network_accessed = true;
513   response_.remote_endpoint = t->transport_info.endpoint;
514   response_.was_fetched_via_proxy =
515       t->transport_info.type == TransportType::kProxied;
516 
517   response_.response_time = transaction_factory_->Now();
518   if (!t->response_time.is_null())
519     response_.response_time = t->response_time;
520 
521   response_.headers = base::MakeRefCounted<HttpResponseHeaders>(header_data);
522   response_.ssl_info.cert = t->cert;
523   response_.ssl_info.cert_status = t->cert_status;
524   response_.ssl_info.connection_status = t->ssl_connection_status;
525   response_.dns_aliases = t->dns_aliases;
526   data_ = resp_data;
527   content_length_ = response_.headers->GetContentLength();
528 
529   if (net_log.net_log())
530     socket_log_id_ = net_log.net_log()->NextID();
531 
532   if (request_->load_flags & LOAD_PREFETCH)
533     response_.unused_since_prefetch = true;
534 
535   if (request_->load_flags & LOAD_RESTRICTED_PREFETCH) {
536     DCHECK(response_.unused_since_prefetch);
537     response_.restricted_prefetch = true;
538   }
539 
540   // Pause and resume.
541   if (!before_network_start_callback_.is_null()) {
542     bool defer = false;
543     std::move(before_network_start_callback_).Run(&defer);
544     if (defer) {
545       resume_start_callback_ = std::move(callback);
546       return net::ERR_IO_PENDING;
547     }
548   }
549 
550   if (test_mode_ & TEST_MODE_SYNC_NET_START)
551     return OK;
552 
553   int result = OK;
554   if (!connected_callback_.is_null()) {
555     result = connected_callback_.Run(t->transport_info, base::DoNothing());
556   }
557 
558   CallbackLater(std::move(callback), result);
559   return ERR_IO_PENDING;
560 }
561 
SetBeforeNetworkStartCallback(BeforeNetworkStartCallback callback)562 void MockNetworkTransaction::SetBeforeNetworkStartCallback(
563     BeforeNetworkStartCallback callback) {
564   before_network_start_callback_ = std::move(callback);
565 }
566 
SetConnectedCallback(const ConnectedCallback & callback)567 void MockNetworkTransaction::SetConnectedCallback(
568     const ConnectedCallback& callback) {
569   connected_callback_ = callback;
570 }
571 
ResumeNetworkStart()572 int MockNetworkTransaction::ResumeNetworkStart() {
573   DCHECK(!resume_start_callback_.is_null());
574   CallbackLater(std::move(resume_start_callback_), OK);
575   return ERR_IO_PENDING;
576 }
577 
GetConnectionAttempts() const578 ConnectionAttempts MockNetworkTransaction::GetConnectionAttempts() const {
579   // TODO(ricea): Replace this with a proper implementation if needed.
580   return {};
581 }
582 
CloseConnectionOnDestruction()583 void MockNetworkTransaction::CloseConnectionOnDestruction() {
584   NOTIMPLEMENTED();
585 }
586 
CallbackLater(CompletionOnceCallback callback,int result)587 void MockNetworkTransaction::CallbackLater(CompletionOnceCallback callback,
588                                            int result) {
589   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
590       FROM_HERE,
591       base::BindOnce(&MockNetworkTransaction::RunCallback,
592                      weak_factory_.GetWeakPtr(), std::move(callback), result));
593 }
594 
RunCallback(CompletionOnceCallback callback,int result)595 void MockNetworkTransaction::RunCallback(CompletionOnceCallback callback,
596                                          int result) {
597   std::move(callback).Run(result);
598 }
599 
600 MockNetworkLayer::MockNetworkLayer() = default;
601 
602 MockNetworkLayer::~MockNetworkLayer() = default;
603 
TransactionDoneReading()604 void MockNetworkLayer::TransactionDoneReading() {
605   CHECK(!done_reading_called_);
606   done_reading_called_ = true;
607 }
608 
TransactionStopCaching()609 void MockNetworkLayer::TransactionStopCaching() {
610   stop_caching_called_ = true;
611 }
612 
ResetTransactionCount()613 void MockNetworkLayer::ResetTransactionCount() {
614   transaction_count_ = 0;
615 }
616 
CreateTransaction(RequestPriority priority,std::unique_ptr<HttpTransaction> * trans)617 int MockNetworkLayer::CreateTransaction(
618     RequestPriority priority,
619     std::unique_ptr<HttpTransaction>* trans) {
620   transaction_count_++;
621   last_create_transaction_priority_ = priority;
622   auto mock_transaction =
623       std::make_unique<MockNetworkTransaction>(priority, this);
624   last_transaction_ = mock_transaction->AsWeakPtr();
625   *trans = std::move(mock_transaction);
626   return OK;
627 }
628 
GetCache()629 HttpCache* MockNetworkLayer::GetCache() {
630   return nullptr;
631 }
632 
GetSession()633 HttpNetworkSession* MockNetworkLayer::GetSession() {
634   return nullptr;
635 }
636 
SetClock(base::Clock * clock)637 void MockNetworkLayer::SetClock(base::Clock* clock) {
638   DCHECK(!clock_);
639   clock_ = clock;
640 }
641 
Now()642 base::Time MockNetworkLayer::Now() {
643   if (clock_)
644     return clock_->Now();
645   return base::Time::Now();
646 }
647 
648 //-----------------------------------------------------------------------------
649 // helpers
650 
ReadTransaction(HttpTransaction * trans,std::string * result)651 int ReadTransaction(HttpTransaction* trans, std::string* result) {
652   int rv;
653 
654   std::string content;
655   do {
656     TestCompletionCallback callback;
657     scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
658     rv = trans->Read(buf.get(), 256, callback.callback());
659     if (rv == ERR_IO_PENDING) {
660       rv = callback.WaitForResult();
661       base::RunLoop().RunUntilIdle();
662     }
663 
664     if (rv > 0)
665       content.append(buf->data(), rv);
666     else if (rv < 0)
667       return rv;
668   } while (rv > 0);
669 
670   result->swap(content);
671   return OK;
672 }
673 
674 //-----------------------------------------------------------------------------
675 // connected callback handler
676 
677 ConnectedHandler::ConnectedHandler() = default;
678 ConnectedHandler::~ConnectedHandler() = default;
679 
680 ConnectedHandler::ConnectedHandler(const ConnectedHandler&) = default;
681 ConnectedHandler& ConnectedHandler::operator=(const ConnectedHandler&) =
682     default;
683 ConnectedHandler::ConnectedHandler(ConnectedHandler&&) = default;
684 ConnectedHandler& ConnectedHandler::operator=(ConnectedHandler&&) = default;
685 
OnConnected(const TransportInfo & info,CompletionOnceCallback callback)686 int ConnectedHandler::OnConnected(const TransportInfo& info,
687                                   CompletionOnceCallback callback) {
688   transports_.push_back(info);
689   if (run_callback_) {
690     base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
691         FROM_HERE, base::BindOnce(std::move(callback), result_));
692     return net::ERR_IO_PENDING;
693   }
694   return result_;
695 }
696 
697 }  // namespace net
698