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), | |
| 42 alternative_proxy_server_is_broken_(false), | |
| 41 job_bound_(false), | 43 job_bound_(false), |
| 42 main_job_is_blocked_(false), | 44 main_job_is_blocked_(false), |
| 43 bound_job_(nullptr), | 45 bound_job_(nullptr), |
| 44 can_start_alternative_proxy_job_(false), | 46 can_start_alternative_proxy_job_(false), |
| 45 ptr_factory_(this) { | 47 ptr_factory_(this) { |
| 46 DCHECK(factory); | 48 DCHECK(factory); |
| 47 } | 49 } |
| 48 | 50 |
| 49 HttpStreamFactoryImpl::JobController::~JobController() { | 51 HttpStreamFactoryImpl::JobController::~JobController() { |
| 50 main_job_.reset(); | 52 main_job_.reset(); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 153 void HttpStreamFactoryImpl::JobController::SetPriority( | 155 void HttpStreamFactoryImpl::JobController::SetPriority( |
| 154 RequestPriority priority) { | 156 RequestPriority priority) { |
| 155 if (main_job_) { | 157 if (main_job_) { |
| 156 main_job_->SetPriority(priority); | 158 main_job_->SetPriority(priority); |
| 157 } | 159 } |
| 158 if (alternative_job_) { | 160 if (alternative_job_) { |
| 159 alternative_job_->SetPriority(priority); | 161 alternative_job_->SetPriority(priority); |
| 160 } | 162 } |
| 161 } | 163 } |
| 162 | 164 |
| 165 void HttpStreamFactoryImpl::JobController::OnAlternativeServiceBroken( | |
| 166 Job* job) { | |
| 167 DCHECK_EQ(job, alternative_job_.get()); | |
| 168 alternative_service_is_broken_ = true; | |
| 169 broken_alternative_service_ = job->alternative_service(); | |
| 170 } | |
| 171 | |
| 172 void HttpStreamFactoryImpl::JobController::OnAlternativeProxyServerBroken( | |
| 173 Job* job) { | |
| 174 DCHECK_EQ(job, alternative_job_.get()); | |
| 175 alternative_proxy_server_is_broken_ = true; | |
| 176 broken_alternative_proxy_server_ = job->alternative_proxy_server(); | |
| 177 } | |
| 178 | |
| 163 void HttpStreamFactoryImpl::JobController::OnStreamReady( | 179 void HttpStreamFactoryImpl::JobController::OnStreamReady( |
| 164 Job* job, | 180 Job* job, |
| 165 const SSLConfig& used_ssl_config, | 181 const SSLConfig& used_ssl_config, |
| 166 const ProxyInfo& used_proxy_info) { | 182 const ProxyInfo& used_proxy_info) { |
| 167 DCHECK(job); | 183 DCHECK(job); |
| 184 MaybeMarkAlternativeServiceBroken(); | |
| 168 | 185 |
| 169 if (job_bound_ && bound_job_ != job) { | 186 if (job_bound_ && bound_job_ != job) { |
| 170 // We have bound a job to the associated Request, |job| has been orphaned. | 187 // We have bound a job to the associated Request, |job| has been orphaned. |
| 171 OnOrphanedJobComplete(job); | 188 OnOrphanedJobComplete(job); |
| 172 return; | 189 return; |
| 173 } | 190 } |
| 174 std::unique_ptr<HttpStream> stream = job->ReleaseStream(); | 191 std::unique_ptr<HttpStream> stream = job->ReleaseStream(); |
| 175 DCHECK(stream); | 192 DCHECK(stream); |
| 176 | 193 |
| 177 MarkRequestComplete(job->was_npn_negotiated(), job->negotiated_protocol(), | 194 MarkRequestComplete(job->was_npn_negotiated(), job->negotiated_protocol(), |
| 178 job->using_spdy()); | 195 job->using_spdy()); |
| 179 | 196 |
| 180 if (!request_) | 197 if (!request_) |
| 181 return; | 198 return; |
| 182 DCHECK(!factory_->for_websockets_); | 199 DCHECK(!factory_->for_websockets_); |
| 183 DCHECK_EQ(HttpStreamRequest::HTTP_STREAM, request_->stream_type()); | 200 DCHECK_EQ(HttpStreamRequest::HTTP_STREAM, request_->stream_type()); |
| 184 OnJobSucceeded(job); | 201 OnJobSucceeded(job); |
| 185 request_->OnStreamReady(used_ssl_config, used_proxy_info, stream.release()); | 202 request_->OnStreamReady(used_ssl_config, used_proxy_info, stream.release()); |
| 186 } | 203 } |
| 187 | 204 |
| 188 void HttpStreamFactoryImpl::JobController::OnBidirectionalStreamImplReady( | 205 void HttpStreamFactoryImpl::JobController::OnBidirectionalStreamImplReady( |
| 189 Job* job, | 206 Job* job, |
| 190 const SSLConfig& used_ssl_config, | 207 const SSLConfig& used_ssl_config, |
| 191 const ProxyInfo& used_proxy_info) { | 208 const ProxyInfo& used_proxy_info) { |
| 192 DCHECK(job); | 209 DCHECK(job); |
| 210 MaybeMarkAlternativeServiceBroken(); | |
| 193 | 211 |
| 194 if (job_bound_ && bound_job_ != job) { | 212 if (job_bound_ && bound_job_ != job) { |
| 195 // We have bound a job to the associated Request, |job| has been orphaned. | 213 // We have bound a job to the associated Request, |job| has been orphaned. |
| 196 OnOrphanedJobComplete(job); | 214 OnOrphanedJobComplete(job); |
| 197 return; | 215 return; |
| 198 } | 216 } |
| 199 | 217 |
| 200 MarkRequestComplete(job->was_npn_negotiated(), job->negotiated_protocol(), | 218 MarkRequestComplete(job->was_npn_negotiated(), job->negotiated_protocol(), |
| 201 job->using_spdy()); | 219 job->using_spdy()); |
| 202 | 220 |
| 203 if (!request_) | 221 if (!request_) |
| 204 return; | 222 return; |
| 205 std::unique_ptr<BidirectionalStreamImpl> stream = | 223 std::unique_ptr<BidirectionalStreamImpl> stream = |
| 206 job->ReleaseBidirectionalStream(); | 224 job->ReleaseBidirectionalStream(); |
| 207 DCHECK(stream); | 225 DCHECK(stream); |
| 208 DCHECK(!factory_->for_websockets_); | 226 DCHECK(!factory_->for_websockets_); |
| 209 DCHECK_EQ(HttpStreamRequest::BIDIRECTIONAL_STREAM, request_->stream_type()); | 227 DCHECK_EQ(HttpStreamRequest::BIDIRECTIONAL_STREAM, request_->stream_type()); |
| 210 | 228 |
| 211 OnJobSucceeded(job); | 229 OnJobSucceeded(job); |
| 212 request_->OnBidirectionalStreamImplReady(used_ssl_config, used_proxy_info, | 230 request_->OnBidirectionalStreamImplReady(used_ssl_config, used_proxy_info, |
| 213 stream.release()); | 231 stream.release()); |
| 214 } | 232 } |
| 215 | 233 |
| 216 void HttpStreamFactoryImpl::JobController::OnWebSocketHandshakeStreamReady( | 234 void HttpStreamFactoryImpl::JobController::OnWebSocketHandshakeStreamReady( |
| 217 Job* job, | 235 Job* job, |
| 218 const SSLConfig& used_ssl_config, | 236 const SSLConfig& used_ssl_config, |
| 219 const ProxyInfo& used_proxy_info, | 237 const ProxyInfo& used_proxy_info, |
| 220 WebSocketHandshakeStreamBase* stream) { | 238 WebSocketHandshakeStreamBase* stream) { |
| 221 DCHECK(job); | 239 DCHECK(job); |
| 240 MaybeMarkAlternativeServiceBroken(); | |
| 222 | 241 |
| 223 MarkRequestComplete(job->was_npn_negotiated(), job->negotiated_protocol(), | 242 MarkRequestComplete(job->was_npn_negotiated(), job->negotiated_protocol(), |
| 224 job->using_spdy()); | 243 job->using_spdy()); |
| 225 | 244 |
| 226 if (!request_) | 245 if (!request_) |
| 227 return; | 246 return; |
| 228 DCHECK(factory_->for_websockets_); | 247 DCHECK(factory_->for_websockets_); |
| 229 DCHECK_EQ(HttpStreamRequest::HTTP_STREAM, request_->stream_type()); | 248 DCHECK_EQ(HttpStreamRequest::HTTP_STREAM, request_->stream_type()); |
| 230 DCHECK(stream); | 249 DCHECK(stream); |
| 231 | 250 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 249 if (!request_) | 268 if (!request_) |
| 250 return; | 269 return; |
| 251 DCHECK_NE(OK, status); | 270 DCHECK_NE(OK, status); |
| 252 DCHECK(job); | 271 DCHECK(job); |
| 253 | 272 |
| 254 if (!bound_job_) { | 273 if (!bound_job_) { |
| 255 if (main_job_ && alternative_job_) { | 274 if (main_job_ && alternative_job_) { |
| 256 // Hey, we've got other jobs! Maybe one of them will succeed, let's just | 275 // Hey, we've got other jobs! Maybe one of them will succeed, let's just |
| 257 // ignore this failure. | 276 // ignore this failure. |
| 258 factory_->request_map_.erase(job); | 277 factory_->request_map_.erase(job); |
| 259 // Notify all the other jobs that this one failed. | |
| 260 if (job->job_type() == MAIN) { | 278 if (job->job_type() == MAIN) { |
| 261 alternative_job_->MarkOtherJobComplete(*job); | |
| 262 main_job_.reset(); | 279 main_job_.reset(); |
| 263 } else { | 280 } else { |
| 264 DCHECK(job->job_type() == ALTERNATIVE); | 281 DCHECK(job->job_type() == ALTERNATIVE); |
| 265 main_job_->MarkOtherJobComplete(*job); | |
| 266 alternative_job_.reset(); | 282 alternative_job_.reset(); |
| 267 } | 283 } |
| 268 return; | 284 return; |
| 269 } else { | 285 } else { |
| 270 BindJob(job); | 286 BindJob(job); |
| 271 } | 287 } |
| 272 } | 288 } |
| 273 | 289 |
| 274 request_->OnStreamFailed(status, used_ssl_config); | 290 request_->OnStreamFailed(status, used_ssl_config); |
| 275 } | 291 } |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 397 base::Unretained(alternative_job_.get()), | 413 base::Unretained(alternative_job_.get()), |
| 398 request_->stream_type())); | 414 request_->stream_type())); |
| 399 } | 415 } |
| 400 | 416 |
| 401 void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady( | 417 void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady( |
| 402 Job* job, | 418 Job* job, |
| 403 const base::WeakPtr<SpdySession>& spdy_session, | 419 const base::WeakPtr<SpdySession>& spdy_session, |
| 404 bool direct) { | 420 bool direct) { |
| 405 DCHECK(job); | 421 DCHECK(job); |
| 406 DCHECK(job->using_spdy()); | 422 DCHECK(job->using_spdy()); |
| 423 MaybeMarkAlternativeServiceBroken(); | |
| 407 | 424 |
| 408 bool is_job_orphaned = job_bound_ && bound_job_ != job; | 425 bool is_job_orphaned = job_bound_ && bound_job_ != job; |
| 409 | 426 |
| 410 // Cache these values in case the job gets deleted. | 427 // Cache these values in case the job gets deleted. |
| 411 const SSLConfig used_ssl_config = job->server_ssl_config(); | 428 const SSLConfig used_ssl_config = job->server_ssl_config(); |
| 412 const ProxyInfo used_proxy_info = job->proxy_info(); | 429 const ProxyInfo used_proxy_info = job->proxy_info(); |
| 413 const bool was_npn_negotiated = job->was_npn_negotiated(); | 430 const bool was_npn_negotiated = job->was_npn_negotiated(); |
| 414 const NextProto negotiated_protocol = job->negotiated_protocol(); | 431 const NextProto negotiated_protocol = job->negotiated_protocol(); |
| 415 const bool using_spdy = job->using_spdy(); | 432 const bool using_spdy = job->using_spdy(); |
| 416 const BoundNetLog net_log = job->net_log(); | 433 const BoundNetLog net_log = job->net_log(); |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 725 // another Job completes first. | 742 // another Job completes first. |
| 726 // TODO(mbelshe): Revisit this when we implement ip connection pooling of | 743 // 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 | 744 // 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 | 745 // 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 | 746 // we've already got one available for a different hostname where the ip |
| 730 // address matches up? | 747 // address matches up? |
| 731 CancelJobs(); | 748 CancelJobs(); |
| 732 return; | 749 return; |
| 733 } | 750 } |
| 734 if (!bound_job_) { | 751 if (!bound_job_) { |
| 735 if (main_job_ && alternative_job_) { | 752 if (main_job_ && alternative_job_) |
| 736 job->ReportJobSucceededForRequest(); | 753 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); | 754 BindJob(job); |
| 746 return; | 755 return; |
| 747 } | 756 } |
| 748 DCHECK(bound_job_); | 757 DCHECK(bound_job_); |
| 749 } | 758 } |
| 750 | 759 |
| 751 void HttpStreamFactoryImpl::JobController::MarkRequestComplete( | 760 void HttpStreamFactoryImpl::JobController::MarkRequestComplete( |
| 752 bool was_npn_negotiated, | 761 bool was_npn_negotiated, |
| 753 NextProto negotiated_protocol, | 762 NextProto negotiated_protocol, |
| 754 bool using_spdy) { | 763 bool using_spdy) { |
| 755 if (request_) | 764 if (request_) |
| 756 request_->Complete(was_npn_negotiated, negotiated_protocol, using_spdy); | 765 request_->Complete(was_npn_negotiated, negotiated_protocol, using_spdy); |
| 757 } | 766 } |
| 758 | 767 |
| 768 void HttpStreamFactoryImpl::JobController::MaybeMarkAlternativeServiceBroken() { | |
| 769 if (!alternative_service_is_broken_ && !alternative_proxy_server_is_broken_) | |
| 770 return; | |
| 771 | |
| 772 DCHECK(!alternative_service_is_broken_ || | |
| 773 !alternative_proxy_server_is_broken_); | |
| 774 if (alternative_service_is_broken_) { | |
| 775 HistogramBrokenAlternateProtocolLocation( | |
| 776 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT); | |
| 777 session_->http_server_properties()->MarkAlternativeServiceBroken( | |
| 778 broken_alternative_service_); | |
| 779 } else { | |
| 780 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; | |
| 781 if (proxy_delegate) | |
| 782 proxy_delegate->OnAlternativeProxyBroken( | |
|
tbansal1
2016/09/13 05:06:45
nit: missing parenthesis.
| |
| 783 broken_alternative_proxy_server_); | |
| 784 } | |
| 785 session_->quic_stream_factory()->OnTcpJobCompleted(true); | |
| 786 } | |
| 787 | |
| 759 void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() { | 788 void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() { |
| 760 if (!request_ && !main_job_ && !alternative_job_) { | 789 if (!request_ && !main_job_ && !alternative_job_) { |
| 761 DCHECK(!bound_job_); | 790 DCHECK(!bound_job_); |
| 762 factory_->OnJobControllerComplete(this); | 791 factory_->OnJobControllerComplete(this); |
| 763 } | 792 } |
| 764 } | 793 } |
| 765 | 794 |
| 766 GURL HttpStreamFactoryImpl::JobController::ApplyHostMappingRules( | 795 GURL HttpStreamFactoryImpl::JobController::ApplyHostMappingRules( |
| 767 const GURL& url, | 796 const GURL& url, |
| 768 HostPortPair* endpoint) { | 797 HostPortPair* endpoint) { |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1003 if (!session_->params().enable_quic || | 1032 if (!session_->params().enable_quic || |
| 1004 session_->quic_stream_factory()->IsQuicDisabled( | 1033 session_->quic_stream_factory()->IsQuicDisabled( |
| 1005 alternative_proxy_server->host_port_pair().port())) { | 1034 alternative_proxy_server->host_port_pair().port())) { |
| 1006 return false; | 1035 return false; |
| 1007 } | 1036 } |
| 1008 } | 1037 } |
| 1009 | 1038 |
| 1010 return true; | 1039 return true; |
| 1011 } | 1040 } |
| 1012 } | 1041 } |
| OLD | NEW |