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 "base/metrics/histogram_macros.h" | 7 #include "base/metrics/histogram_macros.h" |
| 8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
| 9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
| 10 #include "base/values.h" | 10 #include "base/values.h" |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 31 HttpStreamFactoryImpl* factory, | 31 HttpStreamFactoryImpl* factory, |
| 32 HttpStreamRequest::Delegate* delegate, | 32 HttpStreamRequest::Delegate* delegate, |
| 33 HttpNetworkSession* session, | 33 HttpNetworkSession* session, |
| 34 JobFactory* job_factory) | 34 JobFactory* job_factory) |
| 35 : factory_(factory), | 35 : factory_(factory), |
| 36 session_(session), | 36 session_(session), |
| 37 job_factory_(job_factory), | 37 job_factory_(job_factory), |
| 38 request_(nullptr), | 38 request_(nullptr), |
| 39 delegate_(delegate), | 39 delegate_(delegate), |
| 40 is_preconnect_(false), | 40 is_preconnect_(false), |
| 41 alternative_service_is_broken_(false), | |
| 41 job_bound_(false), | 42 job_bound_(false), |
| 42 main_job_is_blocked_(false), | 43 main_job_is_blocked_(false), |
| 43 bound_job_(nullptr), | 44 bound_job_(nullptr), |
| 44 can_start_alternative_proxy_job_(false), | 45 can_start_alternative_proxy_job_(false), |
| 45 ptr_factory_(this) { | 46 ptr_factory_(this) { |
| 46 DCHECK(factory); | 47 DCHECK(factory); |
| 47 } | 48 } |
| 48 | 49 |
| 49 HttpStreamFactoryImpl::JobController::~JobController() { | 50 HttpStreamFactoryImpl::JobController::~JobController() { |
| 50 main_job_.reset(); | 51 main_job_.reset(); |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 212 request_->OnBidirectionalStreamImplReady(used_ssl_config, used_proxy_info, | 213 request_->OnBidirectionalStreamImplReady(used_ssl_config, used_proxy_info, |
| 213 stream.release()); | 214 stream.release()); |
| 214 } | 215 } |
| 215 | 216 |
| 216 void HttpStreamFactoryImpl::JobController::OnWebSocketHandshakeStreamReady( | 217 void HttpStreamFactoryImpl::JobController::OnWebSocketHandshakeStreamReady( |
| 217 Job* job, | 218 Job* job, |
| 218 const SSLConfig& used_ssl_config, | 219 const SSLConfig& used_ssl_config, |
| 219 const ProxyInfo& used_proxy_info, | 220 const ProxyInfo& used_proxy_info, |
| 220 WebSocketHandshakeStreamBase* stream) { | 221 WebSocketHandshakeStreamBase* stream) { |
| 221 DCHECK(job); | 222 DCHECK(job); |
| 222 | |
| 223 MarkRequestComplete(job->was_npn_negotiated(), job->negotiated_protocol(), | 223 MarkRequestComplete(job->was_npn_negotiated(), job->negotiated_protocol(), |
| 224 job->using_spdy()); | 224 job->using_spdy()); |
| 225 | 225 |
| 226 if (!request_) | 226 if (!request_) |
| 227 return; | 227 return; |
| 228 DCHECK(factory_->for_websockets_); | 228 DCHECK(factory_->for_websockets_); |
| 229 DCHECK_EQ(HttpStreamRequest::HTTP_STREAM, request_->stream_type()); | 229 DCHECK_EQ(HttpStreamRequest::HTTP_STREAM, request_->stream_type()); |
| 230 DCHECK(stream); | 230 DCHECK(stream); |
| 231 | 231 |
| 232 OnJobSucceeded(job); | 232 OnJobSucceeded(job); |
| 233 request_->OnWebSocketHandshakeStreamReady(used_ssl_config, used_proxy_info, | 233 request_->OnWebSocketHandshakeStreamReady(used_ssl_config, used_proxy_info, |
| 234 stream); | 234 stream); |
| 235 } | 235 } |
| 236 | 236 |
| 237 void HttpStreamFactoryImpl::JobController::OnStreamFailed( | 237 void HttpStreamFactoryImpl::JobController::OnStreamFailed( |
| 238 Job* job, | 238 Job* job, |
| 239 int status, | 239 int status, |
| 240 const SSLConfig& used_ssl_config) { | 240 const SSLConfig& used_ssl_config) { |
| 241 if (job->job_type() == ALTERNATIVE) | |
| 242 MarkAlternativeServiceBroken(job); | |
| 243 | |
| 241 MaybeResumeMainJob(job, base::TimeDelta()); | 244 MaybeResumeMainJob(job, base::TimeDelta()); |
| 242 | 245 |
| 243 if (job_bound_ && bound_job_ != job) { | 246 if ((job_bound_ && bound_job_ != job) || !request_) { |
| 244 // We have bound a job to the associated Request, |job| has been orphaned. | 247 if (job->job_type() == ALTERNATIVE) |
| 245 OnOrphanedJobComplete(job); | 248 ReportAlternativeServiceBroken(job); |
| 249 if (request_) { | |
|
Ryan Hamilton
2016/09/14 21:45:42
I'm having a hard time following this. I think tha
Zhongyi Shi
2016/09/14 23:07:07
Yup. I have moved the logic up to OnAlternativeJob
| |
| 250 // We have bound a job to the associated Request, |job| has been orphaned. | |
| 251 OnOrphanedJobComplete(job); | |
| 252 } | |
| 246 return; | 253 return; |
| 247 } | 254 } |
| 248 | |
| 249 if (!request_) | |
| 250 return; | |
| 251 DCHECK_NE(OK, status); | 255 DCHECK_NE(OK, status); |
| 252 DCHECK(job); | 256 DCHECK(job); |
| 253 | 257 |
| 254 if (!bound_job_) { | 258 if (!bound_job_) { |
| 255 if (main_job_ && alternative_job_) { | 259 if (main_job_ && alternative_job_) { |
| 256 // Hey, we've got other jobs! Maybe one of them will succeed, let's just | 260 // Hey, we've got other jobs! Maybe one of them will succeed, let's just |
| 257 // ignore this failure. | 261 // ignore this failure. |
| 258 factory_->request_map_.erase(job); | 262 factory_->request_map_.erase(job); |
| 259 // Notify all the other jobs that this one failed. | |
| 260 if (job->job_type() == MAIN) { | 263 if (job->job_type() == MAIN) { |
| 261 alternative_job_->MarkOtherJobComplete(*job); | |
| 262 main_job_.reset(); | 264 main_job_.reset(); |
| 263 } else { | 265 } else { |
| 264 DCHECK(job->job_type() == ALTERNATIVE); | 266 DCHECK(job->job_type() == ALTERNATIVE); |
| 265 main_job_->MarkOtherJobComplete(*job); | |
| 266 alternative_job_.reset(); | 267 alternative_job_.reset(); |
| 267 } | 268 } |
| 268 return; | 269 return; |
| 269 } else { | 270 } else { |
| 270 BindJob(job); | 271 BindJob(job); |
| 271 } | 272 } |
| 272 } | 273 } |
| 273 | 274 |
| 274 request_->OnStreamFailed(status, used_ssl_config); | 275 request_->OnStreamFailed(status, used_ssl_config); |
| 275 } | 276 } |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 413 const bool was_npn_negotiated = job->was_npn_negotiated(); | 414 const bool was_npn_negotiated = job->was_npn_negotiated(); |
| 414 const NextProto negotiated_protocol = job->negotiated_protocol(); | 415 const NextProto negotiated_protocol = job->negotiated_protocol(); |
| 415 const bool using_spdy = job->using_spdy(); | 416 const bool using_spdy = job->using_spdy(); |
| 416 const BoundNetLog net_log = job->net_log(); | 417 const BoundNetLog net_log = job->net_log(); |
| 417 | 418 |
| 418 // Cache this so we can still use it if the JobController is deleted. | 419 // Cache this so we can still use it if the JobController is deleted. |
| 419 HttpStreamFactoryImpl* factory = factory_; | 420 HttpStreamFactoryImpl* factory = factory_; |
| 420 | 421 |
| 421 // Notify |request_|. | 422 // Notify |request_|. |
| 422 if (!is_preconnect_ && !is_job_orphaned) { | 423 if (!is_preconnect_ && !is_job_orphaned) { |
| 424 if (job->job_type() == MAIN && alternative_service_is_broken_) { | |
| 425 // Report alternative service marked as broken. | |
| 426 ReportAlternativeServiceBroken(job); | |
| 427 } | |
| 428 | |
| 423 DCHECK(request_); | 429 DCHECK(request_); |
| 424 | 430 |
| 425 // The first case is the usual case. | 431 // The first case is the usual case. |
| 426 if (!job_bound_) { | 432 if (!job_bound_) { |
| 427 BindJob(job); | 433 BindJob(job); |
| 428 } | 434 } |
| 429 | 435 |
| 430 MarkRequestComplete(was_npn_negotiated, negotiated_protocol, using_spdy); | 436 MarkRequestComplete(was_npn_negotiated, negotiated_protocol, using_spdy); |
| 431 | 437 |
| 432 std::unique_ptr<HttpStream> stream; | 438 std::unique_ptr<HttpStream> stream; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 497 base::Bind(&NetLogHttpStreamJobDelayCallback, main_job_wait_time_)); | 503 base::Bind(&NetLogHttpStreamJobDelayCallback, main_job_wait_time_)); |
| 498 | 504 |
| 499 main_job_->Resume(); | 505 main_job_->Resume(); |
| 500 main_job_wait_time_ = base::TimeDelta(); | 506 main_job_wait_time_ = base::TimeDelta(); |
| 501 } | 507 } |
| 502 | 508 |
| 503 void HttpStreamFactoryImpl::JobController::MaybeResumeMainJob( | 509 void HttpStreamFactoryImpl::JobController::MaybeResumeMainJob( |
| 504 Job* job, | 510 Job* job, |
| 505 const base::TimeDelta& delay) { | 511 const base::TimeDelta& delay) { |
| 506 DCHECK(job == main_job_.get() || job == alternative_job_.get()); | 512 DCHECK(job == main_job_.get() || job == alternative_job_.get()); |
| 513 | |
| 507 if (!main_job_is_blocked_ || job != alternative_job_.get() || !main_job_) | 514 if (!main_job_is_blocked_ || job != alternative_job_.get() || !main_job_) |
| 508 return; | 515 return; |
| 509 | 516 |
| 510 main_job_is_blocked_ = false; | 517 main_job_is_blocked_ = false; |
| 511 | 518 |
| 512 if (!main_job_->is_waiting()) | 519 if (!main_job_->is_waiting()) |
| 513 return; | 520 return; |
| 514 | 521 |
| 515 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 522 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 516 FROM_HERE, | 523 FROM_HERE, |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 724 // because we *WANT* to cancel the unnecessary Jobs from other requests if | 731 // because we *WANT* to cancel the unnecessary Jobs from other requests if |
| 725 // another Job completes first. | 732 // another Job completes first. |
| 726 // TODO(mbelshe): Revisit this when we implement ip connection pooling of | 733 // TODO(mbelshe): Revisit this when we implement ip connection pooling of |
| 727 // SpdySessions. Do we want to orphan the jobs for a different hostname so | 734 // SpdySessions. Do we want to orphan the jobs for a different hostname so |
| 728 // they complete? Or do we want to prevent connecting a new SpdySession if | 735 // they complete? Or do we want to prevent connecting a new SpdySession if |
| 729 // we've already got one available for a different hostname where the ip | 736 // we've already got one available for a different hostname where the ip |
| 730 // address matches up? | 737 // address matches up? |
| 731 CancelJobs(); | 738 CancelJobs(); |
| 732 return; | 739 return; |
| 733 } | 740 } |
| 741 | |
| 742 if (job->job_type() == MAIN && alternative_service_is_broken_) { | |
| 743 ReportAlternativeServiceBroken(job); | |
| 744 } | |
| 745 | |
| 734 if (!bound_job_) { | 746 if (!bound_job_) { |
| 735 if (main_job_ && alternative_job_) { | 747 if (main_job_ && alternative_job_) |
| 736 job->ReportJobSucceededForRequest(); | 748 job->ReportJobSucceededForRequest(); |
| 737 // Notify all the other jobs that this one succeeded. | |
| 738 if (job->job_type() == MAIN) { | |
| 739 alternative_job_->MarkOtherJobComplete(*job); | |
| 740 } else { | |
| 741 DCHECK(job->job_type() == ALTERNATIVE); | |
| 742 main_job_->MarkOtherJobComplete(*job); | |
| 743 } | |
| 744 } | |
| 745 BindJob(job); | 749 BindJob(job); |
| 746 return; | 750 return; |
| 747 } | 751 } |
| 748 DCHECK(bound_job_); | 752 DCHECK(bound_job_); |
| 749 } | 753 } |
| 750 | 754 |
| 751 void HttpStreamFactoryImpl::JobController::MarkRequestComplete( | 755 void HttpStreamFactoryImpl::JobController::MarkRequestComplete( |
| 752 bool was_npn_negotiated, | 756 bool was_npn_negotiated, |
| 753 NextProto negotiated_protocol, | 757 NextProto negotiated_protocol, |
| 754 bool using_spdy) { | 758 bool using_spdy) { |
| 755 if (request_) | 759 if (request_) |
| 756 request_->Complete(was_npn_negotiated, negotiated_protocol, using_spdy); | 760 request_->Complete(was_npn_negotiated, negotiated_protocol, using_spdy); |
| 757 } | 761 } |
| 758 | 762 |
| 763 void HttpStreamFactoryImpl::JobController::MarkAlternativeServiceBroken( | |
| 764 Job* job) { | |
| 765 DCHECK_EQ(job->job_type(), ALTERNATIVE); | |
| 766 | |
| 767 alternative_service_is_broken_ = true; | |
| 768 | |
| 769 if (job->alternative_proxy_server().is_valid()) { | |
| 770 broken_alternative_proxy_server_ = job->alternative_proxy_server(); | |
| 771 } else { | |
| 772 DCHECK(!broken_alternative_proxy_server_.is_valid()); | |
| 773 broken_alternative_service_ = job->alternative_service(); | |
| 774 } | |
| 775 } | |
| 776 | |
| 777 void HttpStreamFactoryImpl::JobController::ReportAlternativeServiceBroken( | |
| 778 Job* job) { | |
|
Ryan Hamilton
2016/09/14 21:45:42
This |job| argument is unused, right? If so, it's
Zhongyi Shi
2016/09/14 23:07:07
Done.
| |
| 779 DCHECK(broken_alternative_service_.protocol != | |
| 780 UNINITIALIZED_ALTERNATE_PROTOCOL || | |
| 781 broken_alternative_proxy_server_.is_valid()); | |
| 782 | |
| 783 if (broken_alternative_proxy_server_.is_valid()) { | |
| 784 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; | |
| 785 if (proxy_delegate) | |
| 786 proxy_delegate->OnAlternativeProxyBroken( | |
| 787 broken_alternative_proxy_server_); | |
| 788 } else { | |
| 789 HistogramBrokenAlternateProtocolLocation( | |
| 790 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT); | |
| 791 session_->http_server_properties()->MarkAlternativeServiceBroken( | |
| 792 broken_alternative_service_); | |
| 793 } | |
| 794 session_->quic_stream_factory()->OnTcpJobCompleted(true); | |
| 795 } | |
| 796 | |
| 759 void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() { | 797 void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() { |
| 760 if (!request_ && !main_job_ && !alternative_job_) { | 798 if (!request_ && !main_job_ && !alternative_job_) { |
| 761 DCHECK(!bound_job_); | 799 DCHECK(!bound_job_); |
| 762 factory_->OnJobControllerComplete(this); | 800 factory_->OnJobControllerComplete(this); |
| 763 } | 801 } |
| 764 } | 802 } |
| 765 | 803 |
| 766 GURL HttpStreamFactoryImpl::JobController::ApplyHostMappingRules( | 804 GURL HttpStreamFactoryImpl::JobController::ApplyHostMappingRules( |
| 767 const GURL& url, | 805 const GURL& url, |
| 768 HostPortPair* endpoint) { | 806 HostPortPair* endpoint) { |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1000 // Check that QUIC is enabled globally, and it is not disabled. | 1038 // Check that QUIC is enabled globally, and it is not disabled. |
| 1001 if (!session_->params().enable_quic || | 1039 if (!session_->params().enable_quic || |
| 1002 session_->quic_stream_factory()->IsQuicDisabled()) { | 1040 session_->quic_stream_factory()->IsQuicDisabled()) { |
| 1003 return false; | 1041 return false; |
| 1004 } | 1042 } |
| 1005 } | 1043 } |
| 1006 | 1044 |
| 1007 return true; | 1045 return true; |
| 1008 } | 1046 } |
| 1009 } | 1047 } |
| OLD | NEW |