http_transaction_test_util.cc 19 KB

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