Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/http/http_stream_factory_impl_job_controller.h" | 5 #include "net/http/http_stream_factory_impl_job_controller.h" |
| 6 | 6 |
| 7 #include "net/http/bidirectional_stream_impl.h" | 7 #include "net/http/bidirectional_stream_impl.h" |
| 8 #include "net/http/http_stream_factory_impl_job.h" | 8 #include "net/http/http_stream_factory_impl_job.h" |
| 9 #include "net/http/http_stream_factory_impl_request.h" | 9 #include "net/http/http_stream_factory_impl_request.h" |
| 10 #include "net/spdy/spdy_session.h" | 10 #include "net/spdy/spdy_session.h" |
| 11 | 11 |
| 12 namespace net { | 12 namespace net { |
| 13 | 13 |
| 14 HttpStreamFactoryImpl::JobController::JobController( | 14 HttpStreamFactoryImpl::JobController::JobController( |
| 15 HttpStreamFactoryImpl* factory) | 15 HttpStreamFactoryImpl* factory) |
| 16 : factory_(factory), | 16 : factory_(factory), |
| 17 request_(NULL), | 17 request_(NULL), |
| 18 main_job_(NULL), | 18 main_job_(NULL), |
| 19 alternative_job_(NULL) { | 19 alternative_job_(NULL), |
| 20 racing_(false) { | |
| 20 DCHECK(factory); | 21 DCHECK(factory); |
| 21 } | 22 } |
| 22 | 23 |
| 23 HttpStreamFactoryImpl::JobController::~JobController() { | 24 HttpStreamFactoryImpl::JobController::~JobController() { |
| 25 DCHECK(jobs_.empty()); | |
| 26 DCHECK(!bound_job_.get()); | |
| 24 std::set<const Job*> tmp_job_set; | 27 std::set<const Job*> tmp_job_set; |
| 25 tmp_job_set.swap(orphaned_job_set_); | 28 tmp_job_set.swap(orphaned_job_set_); |
| 26 STLDeleteContainerPointers(tmp_job_set.begin(), tmp_job_set.end()); | 29 STLDeleteContainerPointers(tmp_job_set.begin(), tmp_job_set.end()); |
| 27 DCHECK(orphaned_job_set_.empty()); | 30 DCHECK(orphaned_job_set_.empty()); |
| 28 } | 31 } |
| 29 | 32 |
| 30 HttpStreamFactoryImpl::Request* | 33 HttpStreamFactoryImpl::Request* |
| 31 HttpStreamFactoryImpl::JobController::CreatRequest( | 34 HttpStreamFactoryImpl::JobController::CreatRequest( |
| 32 const HttpRequestInfo& request_info, | 35 const HttpRequestInfo& request_info, |
| 33 HttpStreamRequest::Delegate* delegate, | 36 HttpStreamRequest::Delegate* delegate, |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 52 const SSLConfig& proxy_ssl_config, | 55 const SSLConfig& proxy_ssl_config, |
| 53 HttpStreamRequest::Delegate* delegate, | 56 HttpStreamRequest::Delegate* delegate, |
| 54 HttpStreamRequest::StreamType stream_type, | 57 HttpStreamRequest::StreamType stream_type, |
| 55 const BoundNetLog& net_log) { | 58 const BoundNetLog& net_log) { |
| 56 DCHECK(!main_job_); | 59 DCHECK(!main_job_); |
| 57 DCHECK(!alternative_job_); | 60 DCHECK(!alternative_job_); |
| 58 HostPortPair destination(HostPortPair::FromURL(request_info.url)); | 61 HostPortPair destination(HostPortPair::FromURL(request_info.url)); |
| 59 GURL origin_url = | 62 GURL origin_url = |
| 60 factory_->ApplyHostMappingRules(request_info.url, &destination); | 63 factory_->ApplyHostMappingRules(request_info.url, &destination); |
| 61 | 64 |
| 62 main_job_ = | 65 main_job_ = new Job(this, NON_ALTERNATIVE, session, request_info, priority, |
| 63 new Job(this, session, request_info, priority, server_ssl_config, | 66 server_ssl_config, proxy_ssl_config, destination, |
| 64 proxy_ssl_config, destination, origin_url, net_log.net_log()); | 67 origin_url, net_log.net_log()); |
| 65 jobs_.insert(main_job_); | 68 jobs_.insert(main_job_); |
| 66 AttachJob(main_job_); | 69 AttachJob(main_job_); |
| 67 | 70 |
| 68 // Create an alternative job if alternative service is set up for this domain. | 71 // Create an alternative job if alternative service is set up for this domain. |
| 69 const AlternativeService alternative_service = | 72 const AlternativeService alternative_service = |
| 70 factory_->GetAlternativeServiceFor(request_info, delegate, stream_type); | 73 factory_->GetAlternativeServiceFor(request_info, delegate, stream_type); |
| 71 | 74 |
| 72 if (alternative_service.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) { | 75 if (alternative_service.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) { |
| 73 // Never share connection with other jobs for FTP requests. | 76 // Never share connection with other jobs for FTP requests. |
| 74 DVLOG(1) << "Selected alternative service (host: " | 77 DVLOG(1) << "Selected alternative service (host: " |
| 75 << alternative_service.host_port_pair().host() | 78 << alternative_service.host_port_pair().host() |
| 76 << " port: " << alternative_service.host_port_pair().port() << ")"; | 79 << " port: " << alternative_service.host_port_pair().port() << ")"; |
| 77 | 80 |
| 78 DCHECK(!request_info.url.SchemeIs("ftp")); | 81 DCHECK(!request_info.url.SchemeIs("ftp")); |
| 79 HostPortPair alternative_destination(alternative_service.host_port_pair()); | 82 HostPortPair alternative_destination(alternative_service.host_port_pair()); |
| 80 ignore_result(factory_->ApplyHostMappingRules(request_info.url, | 83 ignore_result(factory_->ApplyHostMappingRules(request_info.url, |
| 81 &alternative_destination)); | 84 &alternative_destination)); |
| 82 | 85 |
| 83 alternative_job_ = | 86 alternative_job_ = |
| 84 new Job(this, session, request_info, priority, server_ssl_config, | 87 new Job(this, ALTERNATIVE, session, request_info, priority, |
| 85 proxy_ssl_config, alternative_destination, origin_url, | 88 server_ssl_config, proxy_ssl_config, alternative_destination, |
| 86 alternative_service, net_log.net_log()); | 89 origin_url, alternative_service, net_log.net_log()); |
| 87 jobs_.insert(alternative_job_); | 90 jobs_.insert(alternative_job_); |
| 88 AttachJob(alternative_job_); | 91 AttachJob(alternative_job_); |
| 89 | 92 racing_ = true; |
| 90 main_job_->WaitFor(alternative_job_); | |
| 91 // Make sure to wait until we call WaitFor(), before starting | |
| 92 // |alternative_job|, otherwise |alternative_job| will not notify |job| | |
| 93 // appropriately. | |
| 94 alternative_job_->Start(request_); | 93 alternative_job_->Start(request_); |
| 95 } | 94 } |
| 96 // Even if |alternative_job| has already finished, it will not have notified | 95 // Even if |alternative_job| has already finished, it will not have notified |
| 97 // the request yet, since we defer that to the next iteration of the | 96 // the request yet, since we defer that to the next iteration of the |
| 98 // MessageLoop, so starting |job| is always safe. | 97 // MessageLoop, so starting |job| is always safe. |
| 99 main_job_->Start(request_); | 98 main_job_->Start(request_); |
| 100 } | 99 } |
| 101 | 100 |
| 102 void HttpStreamFactoryImpl::JobController::Preconnect( | 101 void HttpStreamFactoryImpl::JobController::Preconnect( |
| 103 int num_streams, | 102 int num_streams, |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 126 } | 125 } |
| 127 destination = alternative_service.host_port_pair(); | 126 destination = alternative_service.host_port_pair(); |
| 128 ignore_result( | 127 ignore_result( |
| 129 factory_->ApplyHostMappingRules(request_info.url, &destination)); | 128 factory_->ApplyHostMappingRules(request_info.url, &destination)); |
| 130 } | 129 } |
| 131 | 130 |
| 132 // Due to how the socket pools handle priorities and idle sockets, only IDLE | 131 // Due to how the socket pools handle priorities and idle sockets, only IDLE |
| 133 // priority currently makes sense for preconnects. The priority for | 132 // priority currently makes sense for preconnects. The priority for |
| 134 // preconnects is currently ignored (see RequestSocketsForPool()), but could | 133 // preconnects is currently ignored (see RequestSocketsForPool()), but could |
| 135 // be used at some point for proxy resolution or something. | 134 // be used at some point for proxy resolution or something. |
| 136 main_job_ = new Job(this, session, request_info, IDLE, server_ssl_config, | 135 main_job_ = new Job(this, PRECONNECT, session, request_info, IDLE, |
| 137 proxy_ssl_config, destination, origin_url, | 136 server_ssl_config, proxy_ssl_config, destination, |
| 138 alternative_service, session->net_log()); | 137 origin_url, alternative_service, session->net_log()); |
| 139 jobs_.insert(main_job_); | 138 jobs_.insert(main_job_); |
| 140 main_job_->Preconnect(num_streams); | 139 main_job_->Preconnect(num_streams); |
| 141 } | 140 } |
| 142 | 141 |
| 143 LoadState HttpStreamFactoryImpl::JobController::GetLoadState() const { | 142 LoadState HttpStreamFactoryImpl::JobController::GetLoadState() const { |
| 144 DCHECK(request_); | 143 DCHECK(request_); |
| 145 if (bound_job_.get()) | 144 if (bound_job_.get()) |
| 146 return bound_job_->GetLoadState(); | 145 return bound_job_->GetLoadState(); |
| 147 DCHECK(!jobs_.empty()); | 146 DCHECK(!jobs_.empty()); |
| 148 | 147 |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 333 return; | 332 return; |
| 334 DCHECK_NE(OK, status); | 333 DCHECK_NE(OK, status); |
| 335 DCHECK(job); | 334 DCHECK(job); |
| 336 | 335 |
| 337 if (!bound_job_.get()) { | 336 if (!bound_job_.get()) { |
| 338 if (jobs_.size() > 1) { | 337 if (jobs_.size() > 1) { |
| 339 // Hey, we've got other jobs! Maybe one of them will succeed, let's just | 338 // Hey, we've got other jobs! Maybe one of them will succeed, let's just |
| 340 // ignore this failure. | 339 // ignore this failure. |
| 341 jobs_.erase(job); | 340 jobs_.erase(job); |
| 342 factory_->request_map_.erase(job); | 341 factory_->request_map_.erase(job); |
| 342 DCHECK_EQ(jobs_.size(), 1u); | |
| 343 // Notify all the other jobs that this one failed. | 343 // Notify all the other jobs that this one failed. |
| 344 for (std::set<Job*>::iterator it = jobs_.begin(); it != jobs_.end(); ++it) | 344 for (std::set<Job*>::iterator it = jobs_.begin(); it != jobs_.end(); ++it) |
| 345 (*it)->MarkOtherJobComplete(*job); | 345 (*it)->MarkOtherJobComplete(*job); |
| 346 delete job; | 346 delete job; |
| 347 return; | 347 return; |
| 348 } else { | 348 } else { |
| 349 BindJob(job); | 349 BindJob(job); |
| 350 } | 350 } |
| 351 } else { | 351 } else { |
| 352 DCHECK(jobs_.empty()); | 352 DCHECK(jobs_.empty()); |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 472 MaybeNotifyFactoryOfCompletion(); | 472 MaybeNotifyFactoryOfCompletion(); |
| 473 } | 473 } |
| 474 | 474 |
| 475 void HttpStreamFactoryImpl::JobController::OnOrphanedJobComplete( | 475 void HttpStreamFactoryImpl::JobController::OnOrphanedJobComplete( |
| 476 const Job* job) { | 476 const Job* job) { |
| 477 orphaned_job_set_.erase(job); | 477 orphaned_job_set_.erase(job); |
| 478 delete job; | 478 delete job; |
| 479 MaybeNotifyFactoryOfCompletion(); | 479 MaybeNotifyFactoryOfCompletion(); |
| 480 } | 480 } |
| 481 | 481 |
| 482 void HttpStreamFactoryImpl::JobController::OnJobDeletion(Job* job) { | |
| 483 DCHECK(!ContainsKey(jobs_, job)); | |
| 484 DCHECK(job); | |
| 485 if (job == main_job_) { | |
| 486 main_job_ = NULL; | |
|
Ryan Hamilton
2016/05/06 21:33:14
nullptr is cool now, NULL is *so* 2015 :>
Zhongyi Shi
2016/05/13 00:31:25
Acknowledged.
| |
| 487 } else if (job == alternative_job_) { | |
| 488 alternative_job_ = NULL; | |
| 489 } else { | |
| 490 NOTREACHED(); | |
| 491 } | |
| 492 } | |
| 493 | |
| 482 void HttpStreamFactoryImpl::JobController::AddConnectionAttemptsToRequest( | 494 void HttpStreamFactoryImpl::JobController::AddConnectionAttemptsToRequest( |
| 483 const ConnectionAttempts& attempts) { | 495 const ConnectionAttempts& attempts) { |
| 484 DCHECK(request_); | 496 DCHECK(request_); |
| 485 request_->AddConnectionAttempts(attempts); | 497 request_->AddConnectionAttempts(attempts); |
| 486 } | 498 } |
| 487 | 499 |
| 488 void HttpStreamFactoryImpl::JobController::SetSpdySessionKey( | 500 void HttpStreamFactoryImpl::JobController::SetSpdySessionKey( |
| 489 const SpdySessionKey& spdy_session_key) { | 501 const SpdySessionKey& spdy_session_key) { |
| 490 DCHECK(request_); | 502 DCHECK(request_); |
| 491 if (!request_->HasSpdySessionKey()) { | 503 if (!request_->HasSpdySessionKey()) { |
| 492 request_->SetSpdySessionKey(spdy_session_key); | 504 request_->SetSpdySessionKey(spdy_session_key); |
| 493 } | 505 } |
| 494 } | 506 } |
| 495 | 507 |
| 496 void HttpStreamFactoryImpl::JobController:: | 508 void HttpStreamFactoryImpl::JobController:: |
| 497 RemoveRequestFromSpdySessionRequestMap() { | 509 RemoveRequestFromSpdySessionRequestMap() { |
| 498 DCHECK(request_); | 510 DCHECK(request_); |
| 499 request_->RemoveRequestFromSpdySessionRequestMap(); | 511 request_->RemoveRequestFromSpdySessionRequestMap(); |
| 500 } | 512 } |
| 501 | 513 |
| 502 void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() { | 514 void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() { |
| 503 if (!request_ && jobs_.empty() && orphaned_job_set_.empty()) { | 515 if (!request_ && jobs_.empty() && orphaned_job_set_.empty()) { |
| 504 DCHECK(jobs_.empty()); | 516 DCHECK(jobs_.empty()); |
| 505 factory_->OnJobControllerComplete(this); | 517 factory_->OnJobControllerComplete(this); |
| 506 } | 518 } |
| 507 } | 519 } |
| 508 | 520 |
| 521 void HttpStreamFactoryImpl::JobController::MaybeResumeOtherJob( | |
| 522 Job* job, | |
| 523 const base::TimeDelta& delay) { | |
| 524 if (!racing_) | |
| 525 return; | |
| 526 | |
| 527 if (job == alternative_job_ && main_job_) { | |
| 528 main_job_->Resume(delay); | |
| 529 } else if (job != main_job_ && job != alternative_job_) { | |
| 530 NOTREACHED(); | |
| 531 } | |
| 532 racing_ = false; | |
| 533 } | |
| 534 | |
| 509 const BoundNetLog& HttpStreamFactoryImpl::JobController::GetNetLogFromRequest() | 535 const BoundNetLog& HttpStreamFactoryImpl::JobController::GetNetLogFromRequest() |
| 510 const { | 536 const { |
| 511 DCHECK(request_); | 537 DCHECK(request_); |
| 512 return request_->net_log(); | 538 return request_->net_log(); |
| 513 } | 539 } |
| 514 | 540 |
| 515 WebSocketHandshakeStreamBase::CreateHelper* HttpStreamFactoryImpl:: | 541 WebSocketHandshakeStreamBase::CreateHelper* HttpStreamFactoryImpl:: |
| 516 JobController::websocket_handshake_stream_create_helper() { | 542 JobController::websocket_handshake_stream_create_helper() { |
| 517 DCHECK(request_); | 543 DCHECK(request_); |
| 518 return request_->websocket_handshake_stream_create_helper(); | 544 return request_->websocket_handshake_stream_create_helper(); |
| 519 } | 545 } |
| 520 } | 546 } |
| OLD | NEW |