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 <string> | 7 #include <string> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 #include "net/log/net_log_capture_mode.h" | 21 #include "net/log/net_log_capture_mode.h" |
| 22 #include "net/log/net_log_event_type.h" | 22 #include "net/log/net_log_event_type.h" |
| 23 #include "net/log/net_log_source.h" | 23 #include "net/log/net_log_source.h" |
| 24 #include "net/log/net_log_with_source.h" | 24 #include "net/log/net_log_with_source.h" |
| 25 #include "net/proxy/proxy_server.h" | 25 #include "net/proxy/proxy_server.h" |
| 26 #include "net/spdy/chromium/spdy_session.h" | 26 #include "net/spdy/chromium/spdy_session.h" |
| 27 #include "url/url_constants.h" | 27 #include "url/url_constants.h" |
| 28 | 28 |
| 29 namespace net { | 29 namespace net { |
| 30 | 30 |
| 31 namespace { | |
| 32 | |
| 33 // Returns parameters associated with the proxy resolution. | |
| 34 std::unique_ptr<base::Value> NetLogHttpStreamJobProxyServerResolved( | |
| 35 const ProxyServer& proxy_server, | |
| 36 NetLogCaptureMode /* capture_mode */) { | |
| 37 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | |
| 38 | |
| 39 dict->SetString("proxy_server", proxy_server.is_valid() | |
| 40 ? proxy_server.ToPacString() | |
| 41 : std::string()); | |
| 42 return std::move(dict); | |
| 43 } | |
| 44 | |
| 45 } // namespace | |
| 46 | |
| 31 // The maximum time to wait for the alternate job to complete before resuming | 47 // The maximum time to wait for the alternate job to complete before resuming |
| 32 // the main job. | 48 // the main job. |
| 33 const int kMaxDelayTimeForMainJobSecs = 3; | 49 const int kMaxDelayTimeForMainJobSecs = 3; |
| 34 | 50 |
| 35 std::unique_ptr<base::Value> NetLogJobControllerCallback( | 51 std::unique_ptr<base::Value> NetLogJobControllerCallback( |
| 36 const GURL* url, | 52 const GURL* url, |
| 37 bool is_preconnect, | 53 bool is_preconnect, |
| 38 NetLogCaptureMode /* capture_mode */) { | 54 NetLogCaptureMode /* capture_mode */) { |
| 39 auto dict = base::MakeUnique<base::DictionaryValue>(); | 55 auto dict = base::MakeUnique<base::DictionaryValue>(); |
| 40 dict->SetString("url", url->possibly_invalid_spec()); | 56 dict->SetString("url", url->possibly_invalid_spec()); |
| 41 dict->SetBoolean("is_preconnect", is_preconnect); | 57 dict->SetBoolean("is_preconnect", is_preconnect); |
| 42 return std::move(dict); | 58 return std::move(dict); |
| 43 } | 59 } |
| 44 | 60 |
| 45 HttpStreamFactoryImpl::JobController::JobController( | 61 HttpStreamFactoryImpl::JobController::JobController( |
| 46 HttpStreamFactoryImpl* factory, | 62 HttpStreamFactoryImpl* factory, |
| 47 HttpStreamRequest::Delegate* delegate, | 63 HttpStreamRequest::Delegate* delegate, |
| 48 HttpNetworkSession* session, | 64 HttpNetworkSession* session, |
| 49 JobFactory* job_factory, | 65 JobFactory* job_factory, |
| 50 const HttpRequestInfo& request_info, | 66 const HttpRequestInfo& request_info, |
| 51 bool is_preconnect, | 67 bool is_preconnect, |
| 52 bool enable_ip_based_pooling, | 68 bool enable_ip_based_pooling, |
| 53 bool enable_alternative_services) | 69 bool enable_alternative_services, |
| 70 const SSLConfig& server_ssl_config, | |
| 71 const SSLConfig& proxy_ssl_config) | |
| 54 : factory_(factory), | 72 : factory_(factory), |
| 55 session_(session), | 73 session_(session), |
| 56 job_factory_(job_factory), | 74 job_factory_(job_factory), |
| 57 request_(nullptr), | 75 request_(nullptr), |
| 58 delegate_(delegate), | 76 delegate_(delegate), |
| 59 is_preconnect_(is_preconnect), | 77 is_preconnect_(is_preconnect), |
| 60 enable_ip_based_pooling_(enable_ip_based_pooling), | 78 enable_ip_based_pooling_(enable_ip_based_pooling), |
| 61 enable_alternative_services_(enable_alternative_services), | 79 enable_alternative_services_(enable_alternative_services), |
| 62 alternative_job_net_error_(OK), | 80 alternative_job_net_error_(OK), |
| 63 job_bound_(false), | 81 job_bound_(false), |
| 64 main_job_is_blocked_(false), | 82 main_job_is_blocked_(false), |
| 65 main_job_is_resumed_(false), | 83 main_job_is_resumed_(false), |
| 66 bound_job_(nullptr), | 84 bound_job_(nullptr), |
| 67 can_start_alternative_proxy_job_(false), | 85 can_start_alternative_proxy_job_(true), |
| 68 privacy_mode_(PRIVACY_MODE_DISABLED), | 86 next_state_(STATE_RESOLVE_PROXY), |
| 87 pac_request_(nullptr), | |
| 88 io_callback_( | |
| 89 base::Bind(&JobController::OnIOComplete, base::Unretained(this))), | |
| 90 request_info_(request_info), | |
| 91 server_ssl_config_(server_ssl_config), | |
| 92 proxy_ssl_config_(proxy_ssl_config), | |
| 93 num_streams_(0), | |
| 94 priority_(IDLE), | |
| 69 net_log_( | 95 net_log_( |
| 70 NetLogWithSource::Make(session->net_log(), | 96 NetLogWithSource::Make(session->net_log(), |
| 71 NetLogSourceType::HTTP_STREAM_JOB_CONTROLLER)), | 97 NetLogSourceType::HTTP_STREAM_JOB_CONTROLLER)), |
| 72 ptr_factory_(this) { | 98 ptr_factory_(this) { |
| 73 DCHECK(factory); | 99 DCHECK(factory); |
| 74 net_log_.BeginEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER, | 100 net_log_.BeginEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER, |
| 75 base::Bind(&NetLogJobControllerCallback, | 101 base::Bind(&NetLogJobControllerCallback, |
| 76 &request_info.url, is_preconnect)); | 102 &request_info.url, is_preconnect)); |
| 77 } | 103 } |
| 78 | 104 |
| 79 HttpStreamFactoryImpl::JobController::~JobController() { | 105 HttpStreamFactoryImpl::JobController::~JobController() { |
| 80 main_job_.reset(); | 106 main_job_.reset(); |
| 81 alternative_job_.reset(); | 107 alternative_job_.reset(); |
| 82 bound_job_ = nullptr; | 108 bound_job_ = nullptr; |
| 109 if (pac_request_) { | |
| 110 // TODO(mmenke): Convert this to a DCHECK once https://crbug.com/723589 is | |
| 111 // resolved. | |
| 112 CHECK_EQ(STATE_RESOLVE_PROXY_COMPLETE, next_state_); | |
|
mmenke
2017/05/26 17:28:04
Think can change this back to a DCHECK, and remove
xunjieli
2017/05/26 17:35:15
Why? I thought we haven't figured out the root cau
| |
| 113 session_->proxy_service()->CancelPacRequest(pac_request_); | |
| 114 } | |
| 83 net_log_.EndEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER); | 115 net_log_.EndEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER); |
| 84 } | 116 } |
| 85 | 117 |
| 86 bool HttpStreamFactoryImpl::JobController::for_websockets() { | 118 bool HttpStreamFactoryImpl::JobController::for_websockets() { |
| 87 return factory_->for_websockets_; | 119 return factory_->for_websockets_; |
| 88 } | 120 } |
| 89 | 121 |
| 90 HttpStreamFactoryImpl::Request* HttpStreamFactoryImpl::JobController::Start( | 122 std::unique_ptr<HttpStreamFactoryImpl::Request> |
| 91 const HttpRequestInfo& request_info, | 123 HttpStreamFactoryImpl::JobController::Start( |
| 92 HttpStreamRequest::Delegate* delegate, | 124 HttpStreamRequest::Delegate* delegate, |
| 93 WebSocketHandshakeStreamBase::CreateHelper* | 125 WebSocketHandshakeStreamBase::CreateHelper* |
| 94 websocket_handshake_stream_create_helper, | 126 websocket_handshake_stream_create_helper, |
| 95 const NetLogWithSource& source_net_log, | 127 const NetLogWithSource& source_net_log, |
| 96 HttpStreamRequest::StreamType stream_type, | 128 HttpStreamRequest::StreamType stream_type, |
| 97 RequestPriority priority, | 129 RequestPriority priority) { |
| 98 const SSLConfig& server_ssl_config, | |
| 99 const SSLConfig& proxy_ssl_config) { | |
| 100 DCHECK(factory_); | 130 DCHECK(factory_); |
| 101 DCHECK(!request_); | 131 DCHECK(!request_); |
| 102 | 132 |
| 103 privacy_mode_ = request_info.privacy_mode; | 133 stream_type_ = stream_type; |
| 134 priority_ = priority; | |
| 104 | 135 |
| 105 request_ = new Request(request_info.url, this, delegate, | 136 auto request = base::MakeUnique<Request>( |
| 106 websocket_handshake_stream_create_helper, | 137 request_info_.url, this, delegate, |
| 107 source_net_log, stream_type); | 138 websocket_handshake_stream_create_helper, source_net_log, stream_type); |
| 139 // Keep a raw pointer but release ownership of Request instance. | |
| 140 request_ = request.get(); | |
| 141 | |
| 108 // Associates |net_log_| with |source_net_log|. | 142 // Associates |net_log_| with |source_net_log|. |
| 109 source_net_log.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND, | 143 source_net_log.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND, |
| 110 net_log_.source().ToEventParametersCallback()); | 144 net_log_.source().ToEventParametersCallback()); |
| 111 net_log_.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND, | 145 net_log_.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND, |
| 112 source_net_log.source().ToEventParametersCallback()); | 146 source_net_log.source().ToEventParametersCallback()); |
| 113 | 147 |
| 114 CreateJobs(request_info, priority, server_ssl_config, proxy_ssl_config, | 148 RunLoop(OK); |
| 115 delegate, stream_type); | 149 return request; |
| 116 | |
| 117 return request_; | |
| 118 } | 150 } |
| 119 | 151 |
| 120 void HttpStreamFactoryImpl::JobController::Preconnect( | 152 void HttpStreamFactoryImpl::JobController::Preconnect(int num_streams) { |
| 121 int num_streams, | |
| 122 const HttpRequestInfo& request_info, | |
| 123 const SSLConfig& server_ssl_config, | |
| 124 const SSLConfig& proxy_ssl_config) { | |
| 125 DCHECK(!main_job_); | 153 DCHECK(!main_job_); |
| 126 DCHECK(!alternative_job_); | 154 DCHECK(!alternative_job_); |
| 127 DCHECK(is_preconnect_); | 155 DCHECK(is_preconnect_); |
| 128 | 156 |
| 129 privacy_mode_ = request_info.privacy_mode; | 157 stream_type_ = HttpStreamRequest::HTTP_STREAM; |
| 158 num_streams_ = num_streams; | |
| 130 | 159 |
| 131 HostPortPair destination(HostPortPair::FromURL(request_info.url)); | 160 RunLoop(OK); |
| 132 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); | |
| 133 | |
| 134 const AlternativeService alternative_service = | |
| 135 GetAlternativeServiceInfoFor(request_info, nullptr, | |
| 136 HttpStreamRequest::HTTP_STREAM) | |
| 137 .alternative_service; | |
| 138 | |
| 139 if (alternative_service.protocol != kProtoUnknown) { | |
| 140 destination = alternative_service.host_port_pair(); | |
| 141 ignore_result(ApplyHostMappingRules(request_info.url, &destination)); | |
| 142 } | |
| 143 | |
| 144 // Due to how the socket pools handle priorities and idle sockets, only IDLE | |
| 145 // priority currently makes sense for preconnects. The priority for | |
| 146 // preconnects is currently ignored (see RequestSocketsForPool()), but could | |
| 147 // be used at some point for proxy resolution or something. | |
| 148 main_job_.reset(job_factory_->CreateJob( | |
| 149 this, PRECONNECT, session_, request_info, IDLE, server_ssl_config, | |
| 150 proxy_ssl_config, destination, origin_url, alternative_service, | |
| 151 enable_ip_based_pooling_, session_->net_log())); | |
| 152 main_job_->Preconnect(num_streams); | |
| 153 } | 161 } |
| 154 | 162 |
| 155 LoadState HttpStreamFactoryImpl::JobController::GetLoadState() const { | 163 LoadState HttpStreamFactoryImpl::JobController::GetLoadState() const { |
| 156 DCHECK(request_); | 164 DCHECK(request_); |
| 157 DCHECK(main_job_ || alternative_job_); | 165 if (next_state_ == STATE_RESOLVE_PROXY_COMPLETE) |
| 166 return session_->proxy_service()->GetLoadState(pac_request_); | |
| 158 if (bound_job_) | 167 if (bound_job_) |
| 159 return bound_job_->GetLoadState(); | 168 return bound_job_->GetLoadState(); |
| 160 | 169 if (main_job_) |
| 161 // Just pick the first one. | 170 return main_job_->GetLoadState(); |
| 162 return main_job_ ? main_job_->GetLoadState() | 171 if (alternative_job_) |
| 163 : alternative_job_->GetLoadState(); | 172 return alternative_job_->GetLoadState(); |
| 173 // When proxy resolution fails, there is no job created and | |
| 174 // NotifyRequestFailed() is executed one message loop iteration later. | |
| 175 return LOAD_STATE_IDLE; | |
| 164 } | 176 } |
| 165 | 177 |
| 166 void HttpStreamFactoryImpl::JobController::OnRequestComplete() { | 178 void HttpStreamFactoryImpl::JobController::OnRequestComplete() { |
| 167 CancelJobs(); | 179 CancelJobs(); |
| 168 DCHECK(request_); | 180 DCHECK(request_); |
| 169 request_ = nullptr; | 181 request_ = nullptr; |
| 170 if (bound_job_) { | 182 if (bound_job_) { |
| 171 if (bound_job_->job_type() == MAIN) { | 183 if (bound_job_->job_type() == MAIN) { |
| 172 main_job_.reset(); | 184 main_job_.reset(); |
| 173 // |alternative_job_| can be non-null if |main_job_| is resumed after | 185 // |alternative_job_| can be non-null if |main_job_| is resumed after |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 196 if (alternative_job_) { | 208 if (alternative_job_) { |
| 197 alternative_job_->SetPriority(priority); | 209 alternative_job_->SetPriority(priority); |
| 198 } | 210 } |
| 199 } | 211 } |
| 200 | 212 |
| 201 void HttpStreamFactoryImpl::JobController::OnStreamReady( | 213 void HttpStreamFactoryImpl::JobController::OnStreamReady( |
| 202 Job* job, | 214 Job* job, |
| 203 const SSLConfig& used_ssl_config) { | 215 const SSLConfig& used_ssl_config) { |
| 204 DCHECK(job); | 216 DCHECK(job); |
| 205 | 217 |
| 206 factory_->OnStreamReady(job->proxy_info(), privacy_mode_); | 218 factory_->OnStreamReady(job->proxy_info(), request_info_.privacy_mode); |
| 207 | 219 |
| 208 if (IsJobOrphaned(job)) { | 220 if (IsJobOrphaned(job)) { |
| 209 // We have bound a job to the associated Request, |job| has been orphaned. | 221 // We have bound a job to the associated Request, |job| has been orphaned. |
| 210 OnOrphanedJobComplete(job); | 222 OnOrphanedJobComplete(job); |
| 211 return; | 223 return; |
| 212 } | 224 } |
| 213 std::unique_ptr<HttpStream> stream = job->ReleaseStream(); | 225 std::unique_ptr<HttpStream> stream = job->ReleaseStream(); |
| 214 DCHECK(stream); | 226 DCHECK(stream); |
| 215 | 227 |
| 216 MarkRequestComplete(job->was_alpn_negotiated(), job->negotiated_protocol(), | 228 MarkRequestComplete(job->was_alpn_negotiated(), job->negotiated_protocol(), |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 271 request_->OnWebSocketHandshakeStreamReady(used_ssl_config, used_proxy_info, | 283 request_->OnWebSocketHandshakeStreamReady(used_ssl_config, used_proxy_info, |
| 272 stream); | 284 stream); |
| 273 } | 285 } |
| 274 | 286 |
| 275 void HttpStreamFactoryImpl::JobController::OnStreamFailed( | 287 void HttpStreamFactoryImpl::JobController::OnStreamFailed( |
| 276 Job* job, | 288 Job* job, |
| 277 int status, | 289 int status, |
| 278 const SSLConfig& used_ssl_config) { | 290 const SSLConfig& used_ssl_config) { |
| 279 if (job->job_type() == ALTERNATIVE) { | 291 if (job->job_type() == ALTERNATIVE) { |
| 280 DCHECK_EQ(alternative_job_.get(), job); | 292 DCHECK_EQ(alternative_job_.get(), job); |
| 281 OnAlternativeJobFailed(status); | 293 if (alternative_job_->alternative_proxy_server().is_valid()) { |
| 294 OnAlternativeProxyJobFailed(status); | |
| 295 } else { | |
| 296 OnAlternativeServiceJobFailed(status); | |
| 297 } | |
| 282 } | 298 } |
| 283 | 299 |
| 284 MaybeResumeMainJob(job, base::TimeDelta()); | 300 MaybeResumeMainJob(job, base::TimeDelta()); |
| 285 | 301 |
| 286 if (IsJobOrphaned(job)) { | 302 if (IsJobOrphaned(job)) { |
| 287 // We have bound a job to the associated Request, |job| has been orphaned. | 303 // We have bound a job to the associated Request, |job| has been orphaned. |
| 288 OnOrphanedJobComplete(job); | 304 OnOrphanedJobComplete(job); |
| 289 return; | 305 return; |
| 290 } | 306 } |
| 291 | 307 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 303 } else { | 319 } else { |
| 304 DCHECK(job->job_type() == ALTERNATIVE); | 320 DCHECK(job->job_type() == ALTERNATIVE); |
| 305 alternative_job_.reset(); | 321 alternative_job_.reset(); |
| 306 } | 322 } |
| 307 return; | 323 return; |
| 308 } else { | 324 } else { |
| 309 BindJob(job); | 325 BindJob(job); |
| 310 } | 326 } |
| 311 } | 327 } |
| 312 | 328 |
| 329 status = ReconsiderProxyAfterError(job, status); | |
| 330 if (next_state_ == STATE_RESOLVE_PROXY_COMPLETE) { | |
| 331 RunLoop(OK); | |
| 332 return; | |
| 333 } | |
| 313 request_->OnStreamFailed(status, used_ssl_config); | 334 request_->OnStreamFailed(status, used_ssl_config); |
| 314 } | 335 } |
| 315 | 336 |
| 316 void HttpStreamFactoryImpl::JobController::OnCertificateError( | 337 void HttpStreamFactoryImpl::JobController::OnCertificateError( |
| 317 Job* job, | 338 Job* job, |
| 318 int status, | 339 int status, |
| 319 const SSLConfig& used_ssl_config, | 340 const SSLConfig& used_ssl_config, |
| 320 const SSLInfo& ssl_info) { | 341 const SSLInfo& ssl_info) { |
| 321 MaybeResumeMainJob(job, base::TimeDelta()); | 342 MaybeResumeMainJob(job, base::TimeDelta()); |
| 322 | 343 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 393 if (!request_) | 414 if (!request_) |
| 394 return; | 415 return; |
| 395 if (!bound_job_) | 416 if (!bound_job_) |
| 396 BindJob(job); | 417 BindJob(job); |
| 397 request_->OnNeedsProxyAuth(proxy_response, used_ssl_config, used_proxy_info, | 418 request_->OnNeedsProxyAuth(proxy_response, used_ssl_config, used_proxy_info, |
| 398 auth_controller); | 419 auth_controller); |
| 399 } | 420 } |
| 400 | 421 |
| 401 bool HttpStreamFactoryImpl::JobController::OnInitConnection( | 422 bool HttpStreamFactoryImpl::JobController::OnInitConnection( |
| 402 const ProxyInfo& proxy_info) { | 423 const ProxyInfo& proxy_info) { |
| 403 return factory_->OnInitConnection(*this, proxy_info, privacy_mode_); | 424 return factory_->OnInitConnection(*this, proxy_info, |
| 404 } | 425 request_info_.privacy_mode); |
| 405 | |
| 406 void HttpStreamFactoryImpl::JobController::OnResolveProxyComplete( | |
| 407 Job* job, | |
| 408 const HttpRequestInfo& request_info, | |
| 409 RequestPriority priority, | |
| 410 const SSLConfig& server_ssl_config, | |
| 411 const SSLConfig& proxy_ssl_config, | |
| 412 HttpStreamRequest::StreamType stream_type) { | |
| 413 DCHECK(job); | |
| 414 | |
| 415 ProxyServer alternative_proxy_server; | |
| 416 if (!ShouldCreateAlternativeProxyServerJob(job, job->proxy_info(), | |
| 417 request_info.url, | |
| 418 &alternative_proxy_server)) { | |
| 419 return; | |
| 420 } | |
| 421 | |
| 422 DCHECK(main_job_); | |
| 423 DCHECK_EQ(MAIN, job->job_type()); | |
| 424 DCHECK(!alternative_job_); | |
| 425 DCHECK(!main_job_is_blocked_); | |
| 426 | |
| 427 HostPortPair destination(HostPortPair::FromURL(request_info.url)); | |
| 428 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); | |
| 429 | |
| 430 alternative_job_.reset(job_factory_->CreateJob( | |
| 431 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config, | |
| 432 proxy_ssl_config, destination, origin_url, alternative_proxy_server, | |
| 433 enable_ip_based_pooling_, job->net_log().net_log())); | |
| 434 | |
| 435 can_start_alternative_proxy_job_ = false; | |
| 436 main_job_is_blocked_ = true; | |
| 437 | |
| 438 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 439 FROM_HERE, | |
| 440 base::Bind( | |
| 441 &HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob, | |
| 442 ptr_factory_.GetWeakPtr())); | |
| 443 } | 426 } |
| 444 | 427 |
| 445 void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady( | 428 void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady( |
| 446 Job* job, | 429 Job* job, |
| 447 const base::WeakPtr<SpdySession>& spdy_session, | 430 const base::WeakPtr<SpdySession>& spdy_session, |
| 448 bool direct) { | 431 bool direct) { |
| 449 DCHECK(job); | 432 DCHECK(job); |
| 450 DCHECK(job->using_spdy()); | 433 DCHECK(job->using_spdy()); |
| 451 DCHECK(!is_preconnect_); | 434 DCHECK(!is_preconnect_); |
| 452 | 435 |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 681 return base::trace_event::EstimateMemoryUsage(main_job_) + | 664 return base::trace_event::EstimateMemoryUsage(main_job_) + |
| 682 base::trace_event::EstimateMemoryUsage(alternative_job_); | 665 base::trace_event::EstimateMemoryUsage(alternative_job_); |
| 683 } | 666 } |
| 684 | 667 |
| 685 WebSocketHandshakeStreamBase::CreateHelper* HttpStreamFactoryImpl:: | 668 WebSocketHandshakeStreamBase::CreateHelper* HttpStreamFactoryImpl:: |
| 686 JobController::websocket_handshake_stream_create_helper() { | 669 JobController::websocket_handshake_stream_create_helper() { |
| 687 DCHECK(request_); | 670 DCHECK(request_); |
| 688 return request_->websocket_handshake_stream_create_helper(); | 671 return request_->websocket_handshake_stream_create_helper(); |
| 689 } | 672 } |
| 690 | 673 |
| 691 void HttpStreamFactoryImpl::JobController::CreateJobs( | 674 void HttpStreamFactoryImpl::JobController::OnIOComplete(int result) { |
| 692 const HttpRequestInfo& request_info, | 675 RunLoop(result); |
| 693 RequestPriority priority, | 676 } |
| 694 const SSLConfig& server_ssl_config, | 677 |
| 695 const SSLConfig& proxy_ssl_config, | 678 void HttpStreamFactoryImpl::JobController::RunLoop(int result) { |
| 696 HttpStreamRequest::Delegate* delegate, | 679 int rv = DoLoop(result); |
| 697 HttpStreamRequest::StreamType stream_type) { | 680 if (rv == ERR_IO_PENDING) |
| 681 return; | |
| 682 if (rv != OK) { | |
| 683 // DoLoop can only fail during proxy resolution step which happens before | |
| 684 // any jobs are created. Notify |request_| of the failure one message loop | |
| 685 // iteration later to avoid re-entrancy. | |
| 686 DCHECK(!main_job_); | |
| 687 DCHECK(!alternative_job_); | |
| 688 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 689 FROM_HERE, | |
| 690 base::Bind(&HttpStreamFactoryImpl::JobController::NotifyRequestFailed, | |
| 691 ptr_factory_.GetWeakPtr(), rv)); | |
| 692 } | |
| 693 } | |
| 694 | |
| 695 int HttpStreamFactoryImpl::JobController::DoLoop(int rv) { | |
| 696 DCHECK_NE(next_state_, STATE_NONE); | |
| 697 do { | |
| 698 State state = next_state_; | |
| 699 next_state_ = STATE_NONE; | |
| 700 switch (state) { | |
| 701 case STATE_RESOLVE_PROXY: | |
| 702 DCHECK_EQ(OK, rv); | |
| 703 rv = DoResolveProxy(); | |
| 704 break; | |
| 705 case STATE_RESOLVE_PROXY_COMPLETE: | |
| 706 rv = DoResolveProxyComplete(rv); | |
| 707 break; | |
| 708 case STATE_CREATE_JOBS: | |
| 709 DCHECK_EQ(OK, rv); | |
| 710 rv = DoCreateJobs(); | |
| 711 break; | |
| 712 default: | |
| 713 NOTREACHED() << "bad state"; | |
| 714 break; | |
| 715 } | |
| 716 } while (next_state_ != STATE_NONE && rv != ERR_IO_PENDING); | |
| 717 return rv; | |
| 718 } | |
| 719 | |
| 720 int HttpStreamFactoryImpl::JobController::DoResolveProxy() { | |
| 721 // TODO(mmenke): Convert this to a DCHECK once https://crbug.com/723589 is | |
| 722 // resolved. | |
| 723 CHECK(!pac_request_); | |
|
mmenke
2017/05/26 17:28:04
DCHECK, remove TODO.
| |
| 724 DCHECK(session_); | |
| 725 | |
| 726 next_state_ = STATE_RESOLVE_PROXY_COMPLETE; | |
| 727 | |
| 728 if (request_info_.load_flags & LOAD_BYPASS_PROXY) { | |
| 729 proxy_info_.UseDirect(); | |
| 730 return OK; | |
| 731 } | |
| 732 | |
| 733 HostPortPair destination(HostPortPair::FromURL(request_info_.url)); | |
| 734 GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination); | |
| 735 | |
| 736 return session_->proxy_service()->ResolveProxy( | |
| 737 origin_url, request_info_.method, &proxy_info_, io_callback_, | |
| 738 &pac_request_, session_->params().proxy_delegate, net_log_); | |
| 739 } | |
| 740 | |
| 741 int HttpStreamFactoryImpl::JobController::DoResolveProxyComplete(int rv) { | |
| 742 DCHECK_NE(ERR_IO_PENDING, rv); | |
| 743 | |
| 744 pac_request_ = nullptr; | |
| 745 net_log_.AddEvent( | |
| 746 NetLogEventType::HTTP_STREAM_JOB_PROXY_SERVER_RESOLVED, | |
| 747 base::Bind( | |
| 748 &NetLogHttpStreamJobProxyServerResolved, | |
| 749 proxy_info_.is_empty() ? ProxyServer() : proxy_info_.proxy_server())); | |
| 750 | |
| 751 if (rv != OK) | |
| 752 return rv; | |
| 753 // Remove unsupported proxies from the list. | |
| 754 int supported_proxies = ProxyServer::SCHEME_DIRECT | | |
| 755 ProxyServer::SCHEME_HTTP | ProxyServer::SCHEME_HTTPS | | |
| 756 ProxyServer::SCHEME_SOCKS4 | | |
| 757 ProxyServer::SCHEME_SOCKS5; | |
| 758 if (session_->IsQuicEnabled()) | |
| 759 supported_proxies |= ProxyServer::SCHEME_QUIC; | |
| 760 proxy_info_.RemoveProxiesWithoutScheme(supported_proxies); | |
| 761 | |
| 762 if (proxy_info_.is_empty()) { | |
| 763 // No proxies/direct to choose from. | |
| 764 return ERR_NO_SUPPORTED_PROXIES; | |
| 765 } | |
| 766 | |
| 767 next_state_ = STATE_CREATE_JOBS; | |
| 768 return rv; | |
| 769 } | |
| 770 | |
| 771 int HttpStreamFactoryImpl::JobController::DoCreateJobs() { | |
| 698 DCHECK(!main_job_); | 772 DCHECK(!main_job_); |
| 699 DCHECK(!alternative_job_); | 773 DCHECK(!alternative_job_); |
| 700 HostPortPair destination(HostPortPair::FromURL(request_info.url)); | |
| 701 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); | |
| 702 | 774 |
| 703 main_job_.reset(job_factory_->CreateJob( | 775 HostPortPair destination(HostPortPair::FromURL(request_info_.url)); |
| 704 this, MAIN, session_, request_info, priority, server_ssl_config, | 776 GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination); |
| 705 proxy_ssl_config, destination, origin_url, enable_ip_based_pooling_, | |
| 706 net_log_.net_log())); | |
| 707 | 777 |
| 708 // Create an alternative job if alternative service is set up for this domain. | 778 // Create an alternative job if alternative service is set up for this domain. |
| 709 const AlternativeService alternative_service = | 779 const AlternativeService alternative_service = |
| 710 GetAlternativeServiceInfoFor(request_info, delegate, stream_type) | 780 GetAlternativeServiceInfoFor(request_info_, delegate_, stream_type_) |
| 711 .alternative_service; | 781 .alternative_service; |
| 712 | 782 |
| 783 if (is_preconnect_) { | |
| 784 // Due to how the socket pools handle priorities and idle sockets, only IDLE | |
| 785 // priority currently makes sense for preconnects. The priority for | |
| 786 // preconnects is currently ignored (see RequestSocketsForPool()), but could | |
| 787 // be used at some point for proxy resolution or something. | |
| 788 if (alternative_service.protocol != kProtoUnknown) { | |
| 789 HostPortPair alternative_destination( | |
| 790 alternative_service.host_port_pair()); | |
| 791 ignore_result( | |
| 792 ApplyHostMappingRules(request_info_.url, &alternative_destination)); | |
| 793 main_job_ = job_factory_->CreateAltSvcJob( | |
| 794 this, PRECONNECT, session_, request_info_, IDLE, proxy_info_, | |
| 795 server_ssl_config_, proxy_ssl_config_, alternative_destination, | |
| 796 origin_url, alternative_service, enable_ip_based_pooling_, | |
| 797 session_->net_log()); | |
| 798 } else { | |
| 799 main_job_ = job_factory_->CreateMainJob( | |
| 800 this, PRECONNECT, session_, request_info_, IDLE, proxy_info_, | |
| 801 server_ssl_config_, proxy_ssl_config_, destination, origin_url, | |
| 802 enable_ip_based_pooling_, session_->net_log()); | |
| 803 } | |
| 804 main_job_->Preconnect(num_streams_); | |
| 805 return OK; | |
| 806 } | |
| 807 main_job_ = job_factory_->CreateMainJob( | |
| 808 this, MAIN, session_, request_info_, priority_, proxy_info_, | |
| 809 server_ssl_config_, proxy_ssl_config_, destination, origin_url, | |
| 810 enable_ip_based_pooling_, net_log_.net_log()); | |
| 811 // Alternative Service can only be set for HTTPS requests while Alternative | |
| 812 // Proxy is set for HTTP requests. | |
| 713 if (alternative_service.protocol != kProtoUnknown) { | 813 if (alternative_service.protocol != kProtoUnknown) { |
| 714 // Never share connection with other jobs for FTP requests. | 814 // Never share connection with other jobs for FTP requests. |
| 715 DVLOG(1) << "Selected alternative service (host: " | 815 DVLOG(1) << "Selected alternative service (host: " |
| 716 << alternative_service.host_port_pair().host() | 816 << alternative_service.host_port_pair().host() |
| 717 << " port: " << alternative_service.host_port_pair().port() << ")"; | 817 << " port: " << alternative_service.host_port_pair().port() << ")"; |
| 718 | 818 |
| 719 DCHECK(!request_info.url.SchemeIs(url::kFtpScheme)); | 819 DCHECK(!request_info_.url.SchemeIs(url::kFtpScheme)); |
| 720 HostPortPair alternative_destination(alternative_service.host_port_pair()); | 820 HostPortPair alternative_destination(alternative_service.host_port_pair()); |
| 721 ignore_result( | 821 ignore_result( |
| 722 ApplyHostMappingRules(request_info.url, &alternative_destination)); | 822 ApplyHostMappingRules(request_info_.url, &alternative_destination)); |
| 723 | 823 |
| 724 alternative_job_.reset(job_factory_->CreateJob( | 824 alternative_job_ = job_factory_->CreateAltSvcJob( |
| 725 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config, | 825 this, ALTERNATIVE, session_, request_info_, priority_, proxy_info_, |
| 726 proxy_ssl_config, alternative_destination, origin_url, | 826 server_ssl_config_, proxy_ssl_config_, alternative_destination, |
| 727 alternative_service, enable_ip_based_pooling_, net_log_.net_log())); | 827 origin_url, alternative_service, enable_ip_based_pooling_, |
| 828 net_log_.net_log()); | |
| 728 | 829 |
| 729 main_job_is_blocked_ = true; | 830 main_job_is_blocked_ = true; |
| 730 alternative_job_->Start(request_->stream_type()); | 831 alternative_job_->Start(request_->stream_type()); |
| 731 } else { | 832 } else { |
| 732 can_start_alternative_proxy_job_ = true; | 833 ProxyServer alternative_proxy_server; |
| 834 if (ShouldCreateAlternativeProxyServerJob(proxy_info_, request_info_.url, | |
| 835 &alternative_proxy_server)) { | |
| 836 DCHECK(!main_job_is_blocked_); | |
| 837 ProxyInfo alternative_proxy_info; | |
| 838 alternative_proxy_info.UseProxyServer(alternative_proxy_server); | |
| 839 | |
| 840 alternative_job_ = job_factory_->CreateAltProxyJob( | |
| 841 this, ALTERNATIVE, session_, request_info_, priority_, | |
| 842 alternative_proxy_info, server_ssl_config_, proxy_ssl_config_, | |
| 843 destination, origin_url, alternative_proxy_server, | |
| 844 enable_ip_based_pooling_, net_log_.net_log()); | |
| 845 | |
| 846 can_start_alternative_proxy_job_ = false; | |
| 847 main_job_is_blocked_ = true; | |
| 848 alternative_job_->Start(request_->stream_type()); | |
| 849 } | |
| 733 } | 850 } |
| 734 // Even if |alternative_job| has already finished, it will not have notified | 851 // Even if |alternative_job| has already finished, it will not have notified |
| 735 // the request yet, since we defer that to the next iteration of the | 852 // the request yet, since we defer that to the next iteration of the |
| 736 // MessageLoop, so starting |main_job_| is always safe. | 853 // MessageLoop, so starting |main_job_| is always safe. |
| 737 main_job_->Start(request_->stream_type()); | 854 main_job_->Start(request_->stream_type()); |
| 855 return OK; | |
| 738 } | 856 } |
| 739 | 857 |
| 740 void HttpStreamFactoryImpl::JobController::BindJob(Job* job) { | 858 void HttpStreamFactoryImpl::JobController::BindJob(Job* job) { |
| 741 DCHECK(request_); | 859 DCHECK(request_); |
| 742 DCHECK(job); | 860 DCHECK(job); |
| 743 DCHECK(job == alternative_job_.get() || job == main_job_.get()); | 861 DCHECK(job == alternative_job_.get() || job == main_job_.get()); |
| 744 DCHECK(!job_bound_); | 862 DCHECK(!job_bound_); |
| 745 DCHECK(!bound_job_); | 863 DCHECK(!bound_job_); |
| 746 | 864 |
| 747 job_bound_ = true; | 865 job_bound_ = true; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 823 } | 941 } |
| 824 | 942 |
| 825 void HttpStreamFactoryImpl::JobController::MarkRequestComplete( | 943 void HttpStreamFactoryImpl::JobController::MarkRequestComplete( |
| 826 bool was_alpn_negotiated, | 944 bool was_alpn_negotiated, |
| 827 NextProto negotiated_protocol, | 945 NextProto negotiated_protocol, |
| 828 bool using_spdy) { | 946 bool using_spdy) { |
| 829 if (request_) | 947 if (request_) |
| 830 request_->Complete(was_alpn_negotiated, negotiated_protocol, using_spdy); | 948 request_->Complete(was_alpn_negotiated, negotiated_protocol, using_spdy); |
| 831 } | 949 } |
| 832 | 950 |
| 833 void HttpStreamFactoryImpl::JobController::OnAlternativeJobFailed( | 951 void HttpStreamFactoryImpl::JobController::OnAlternativeServiceJobFailed( |
| 834 int net_error) { | 952 int net_error) { |
| 835 DCHECK_EQ(alternative_job_->job_type(), ALTERNATIVE); | 953 DCHECK_EQ(alternative_job_->job_type(), ALTERNATIVE); |
| 836 DCHECK_NE(OK, net_error); | 954 DCHECK_NE(OK, net_error); |
| 955 DCHECK_NE(kProtoUnknown, alternative_job_->alternative_service().protocol); | |
| 837 | 956 |
| 838 alternative_job_net_error_ = net_error; | 957 alternative_job_net_error_ = net_error; |
| 839 | 958 failed_alternative_service_ = alternative_job_->alternative_service(); |
| 840 if (alternative_job_->alternative_proxy_server().is_valid()) { | |
| 841 failed_alternative_proxy_server_ = | |
| 842 alternative_job_->alternative_proxy_server(); | |
| 843 } else { | |
| 844 DCHECK(!failed_alternative_proxy_server_.is_valid()); | |
| 845 failed_alternative_service_ = alternative_job_->alternative_service(); | |
| 846 } | |
| 847 | 959 |
| 848 if (IsJobOrphaned(alternative_job_.get())) { | 960 if (IsJobOrphaned(alternative_job_.get())) { |
| 849 // If |request_| is gone then it must have been successfully served by | 961 // If |request_| is gone then it must have been successfully served by |
| 850 // |main_job_|. | 962 // |main_job_|. |
| 851 // If |request_| is bound to a different job, then it is being | 963 // If |request_| is bound to a different job, then it is being |
| 852 // successfully serverd by the main job. | 964 // successfully serverd by the main job. |
| 853 ReportBrokenAlternativeService(); | 965 ReportBrokenAlternativeService(); |
| 854 } | 966 } |
| 855 } | 967 } |
| 856 | 968 |
| 969 void HttpStreamFactoryImpl::JobController::OnAlternativeProxyJobFailed( | |
| 970 int net_error) { | |
| 971 DCHECK_EQ(alternative_job_->job_type(), ALTERNATIVE); | |
| 972 DCHECK_NE(OK, net_error); | |
| 973 DCHECK(alternative_job_->alternative_proxy_server().is_valid()); | |
| 974 | |
| 975 // Need to mark alt proxy as broken regardless whether the job is bound. | |
| 976 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; | |
| 977 if (proxy_delegate) { | |
| 978 proxy_delegate->OnAlternativeProxyBroken( | |
| 979 alternative_job_->alternative_proxy_server()); | |
| 980 } | |
| 981 } | |
| 982 | |
| 857 void HttpStreamFactoryImpl::JobController::ReportBrokenAlternativeService() { | 983 void HttpStreamFactoryImpl::JobController::ReportBrokenAlternativeService() { |
| 858 DCHECK(failed_alternative_service_.protocol != kProtoUnknown || | 984 DCHECK(failed_alternative_service_.protocol != kProtoUnknown); |
| 859 failed_alternative_proxy_server_.is_valid()); | |
| 860 DCHECK_NE(OK, alternative_job_net_error_); | 985 DCHECK_NE(OK, alternative_job_net_error_); |
| 861 | 986 |
| 862 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.AlternateServiceFailed", | 987 int error_to_report = alternative_job_net_error_; |
| 863 -alternative_job_net_error_); | 988 alternative_job_net_error_ = OK; |
| 989 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.AlternateServiceFailed", -error_to_report); | |
| 864 | 990 |
| 865 if (alternative_job_net_error_ == ERR_NETWORK_CHANGED || | 991 if (error_to_report == ERR_NETWORK_CHANGED || |
| 866 alternative_job_net_error_ == ERR_INTERNET_DISCONNECTED) { | 992 error_to_report == ERR_INTERNET_DISCONNECTED) { |
| 867 // No need to mark alternative service or proxy as broken. | 993 // No need to mark alternative service or proxy as broken. |
| 868 return; | 994 return; |
| 869 } | 995 } |
| 870 | 996 |
| 871 if (failed_alternative_proxy_server_.is_valid()) { | 997 HistogramBrokenAlternateProtocolLocation( |
| 872 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; | 998 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT); |
| 873 if (proxy_delegate) { | 999 session_->http_server_properties()->MarkAlternativeServiceBroken( |
| 874 proxy_delegate->OnAlternativeProxyBroken( | 1000 failed_alternative_service_); |
| 875 failed_alternative_proxy_server_); | |
| 876 } | |
| 877 } else { | |
| 878 HistogramBrokenAlternateProtocolLocation( | |
| 879 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT); | |
| 880 session_->http_server_properties()->MarkAlternativeServiceBroken( | |
| 881 failed_alternative_service_); | |
| 882 } | |
| 883 } | 1001 } |
| 884 | 1002 |
| 885 void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() { | 1003 void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() { |
| 886 if (!request_ && !main_job_ && !alternative_job_) { | 1004 if (!request_ && !main_job_ && !alternative_job_) { |
| 887 DCHECK(!bound_job_); | 1005 DCHECK(!bound_job_); |
| 888 factory_->OnJobControllerComplete(this); | 1006 factory_->OnJobControllerComplete(this); |
| 889 } | 1007 } |
| 890 } | 1008 } |
| 891 | 1009 |
| 1010 void HttpStreamFactoryImpl::JobController::NotifyRequestFailed(int rv) { | |
| 1011 if (!request_) | |
| 1012 return; | |
| 1013 request_->OnStreamFailed(rv, server_ssl_config_); | |
| 1014 } | |
| 1015 | |
| 892 GURL HttpStreamFactoryImpl::JobController::ApplyHostMappingRules( | 1016 GURL HttpStreamFactoryImpl::JobController::ApplyHostMappingRules( |
| 893 const GURL& url, | 1017 const GURL& url, |
| 894 HostPortPair* endpoint) { | 1018 HostPortPair* endpoint) { |
| 895 const HostMappingRules* mapping_rules = session_->params().host_mapping_rules; | 1019 const HostMappingRules* mapping_rules = session_->params().host_mapping_rules; |
| 896 if (mapping_rules && mapping_rules->RewriteHost(endpoint)) { | 1020 if (mapping_rules && mapping_rules->RewriteHost(endpoint)) { |
| 897 url::Replacements<char> replacements; | 1021 url::Replacements<char> replacements; |
| 898 const std::string port_str = base::UintToString(endpoint->port()); | 1022 const std::string port_str = base::UintToString(endpoint->port()); |
| 899 replacements.SetPort(port_str.c_str(), url::Component(0, port_str.size())); | 1023 replacements.SetPort(port_str.c_str(), url::Component(0, port_str.size())); |
| 900 replacements.SetHost(endpoint->host().c_str(), | 1024 replacements.SetHost(endpoint->host().c_str(), |
| 901 url::Component(0, endpoint->host().size())); | 1025 url::Component(0, endpoint->host().size())); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1035 | 1159 |
| 1036 // Ask delegate to mark QUIC as broken for the origin. | 1160 // Ask delegate to mark QUIC as broken for the origin. |
| 1037 if (quic_advertised && quic_all_broken && delegate != nullptr) | 1161 if (quic_advertised && quic_all_broken && delegate != nullptr) |
| 1038 delegate->OnQuicBroken(); | 1162 delegate->OnQuicBroken(); |
| 1039 | 1163 |
| 1040 return first_alternative_service_info; | 1164 return first_alternative_service_info; |
| 1041 } | 1165 } |
| 1042 | 1166 |
| 1043 bool HttpStreamFactoryImpl::JobController:: | 1167 bool HttpStreamFactoryImpl::JobController:: |
| 1044 ShouldCreateAlternativeProxyServerJob( | 1168 ShouldCreateAlternativeProxyServerJob( |
| 1045 Job* job, | |
| 1046 const ProxyInfo& proxy_info, | 1169 const ProxyInfo& proxy_info, |
| 1047 const GURL& url, | 1170 const GURL& url, |
| 1048 ProxyServer* alternative_proxy_server) const { | 1171 ProxyServer* alternative_proxy_server) const { |
| 1049 DCHECK(!alternative_proxy_server->is_valid()); | 1172 DCHECK(!alternative_proxy_server->is_valid()); |
| 1050 | 1173 |
| 1051 if (!enable_alternative_services_) | 1174 if (!enable_alternative_services_) |
| 1052 return false; | 1175 return false; |
| 1053 | 1176 |
| 1054 if (!can_start_alternative_proxy_job_) { | 1177 if (!can_start_alternative_proxy_job_) { |
| 1055 // Either an alternative service job or an alternative proxy server job has | 1178 // Either an alternative service job or an alternative proxy server job has |
| 1056 // already been started. | 1179 // already been started. |
| 1057 return false; | 1180 return false; |
| 1058 } | 1181 } |
| 1059 | 1182 |
| 1060 if (job->job_type() == ALTERNATIVE) { | |
| 1061 // If |job| is using alternative service, then alternative proxy server | |
| 1062 // should not be used. | |
| 1063 return false; | |
| 1064 } | |
| 1065 | |
| 1066 if (is_preconnect_ || job->job_type() == PRECONNECT) { | |
| 1067 // Preconnects should be fetched using only the main job to keep the | |
| 1068 // resource utilization down. | |
| 1069 return false; | |
| 1070 } | |
| 1071 | |
| 1072 if (proxy_info.is_empty() || proxy_info.is_direct() || proxy_info.is_quic()) { | 1183 if (proxy_info.is_empty() || proxy_info.is_direct() || proxy_info.is_quic()) { |
| 1073 // Alternative proxy server job can be created only if |job| fetches the | 1184 // Alternative proxy server job can be created only if |job| fetches the |
| 1074 // |request_| through a non-QUIC proxy. | 1185 // |request_| through a non-QUIC proxy. |
| 1075 return false; | 1186 return false; |
| 1076 } | 1187 } |
| 1077 | 1188 |
| 1078 if (!url.SchemeIs(url::kHttpScheme)) { | 1189 if (!url.SchemeIs(url::kHttpScheme)) { |
| 1079 // Only HTTP URLs can be fetched through alternative proxy server, since the | 1190 // Only HTTP URLs can be fetched through alternative proxy server, since the |
| 1080 // alternative proxy server may not support fetching of URLs with other | 1191 // alternative proxy server may not support fetching of URLs with other |
| 1081 // schemes. | 1192 // schemes. |
| 1082 return false; | 1193 return false; |
| 1083 } | 1194 } |
| 1084 | 1195 |
| 1085 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; | 1196 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; |
| 1086 if (!proxy_delegate) | 1197 if (!proxy_delegate) |
| 1087 return false; | 1198 return false; |
| 1088 | |
| 1089 proxy_delegate->GetAlternativeProxy(url, proxy_info.proxy_server(), | 1199 proxy_delegate->GetAlternativeProxy(url, proxy_info.proxy_server(), |
| 1090 alternative_proxy_server); | 1200 alternative_proxy_server); |
| 1091 | 1201 |
| 1092 if (!alternative_proxy_server->is_valid()) | 1202 if (!alternative_proxy_server->is_valid()) |
| 1093 return false; | 1203 return false; |
| 1094 | 1204 |
| 1095 DCHECK(!(*alternative_proxy_server == proxy_info.proxy_server())); | 1205 DCHECK(!(*alternative_proxy_server == proxy_info.proxy_server())); |
| 1096 | 1206 |
| 1097 if (!alternative_proxy_server->is_https() && | 1207 if (!alternative_proxy_server->is_https() && |
| 1098 !alternative_proxy_server->is_quic()) { | 1208 !alternative_proxy_server->is_quic()) { |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 1126 if (job->using_existing_quic_session()) { | 1236 if (job->using_existing_quic_session()) { |
| 1127 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_NO_RACE, | 1237 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_NO_RACE, |
| 1128 proxy_server_used); | 1238 proxy_server_used); |
| 1129 return; | 1239 return; |
| 1130 } | 1240 } |
| 1131 | 1241 |
| 1132 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE, | 1242 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE, |
| 1133 proxy_server_used); | 1243 proxy_server_used); |
| 1134 } | 1244 } |
| 1135 | 1245 |
| 1136 void HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob() { | |
| 1137 if (!alternative_job_ || !request_) | |
| 1138 return; | |
| 1139 DCHECK(alternative_job_->alternative_proxy_server().is_valid()); | |
| 1140 alternative_job_->Start(request_->stream_type()); | |
| 1141 } | |
| 1142 | |
| 1143 bool HttpStreamFactoryImpl::JobController::IsJobOrphaned(Job* job) const { | 1246 bool HttpStreamFactoryImpl::JobController::IsJobOrphaned(Job* job) const { |
| 1144 return !request_ || (job_bound_ && bound_job_ != job); | 1247 return !request_ || (job_bound_ && bound_job_ != job); |
| 1145 } | 1248 } |
| 1146 | 1249 |
| 1250 int HttpStreamFactoryImpl::JobController::ReconsiderProxyAfterError(Job* job, | |
| 1251 int error) { | |
| 1252 // ReconsiderProxyAfterError() should only be called when the last job fails. | |
| 1253 DCHECK(!(alternative_job_ && main_job_)); | |
| 1254 // TODO(mmenke): Convert this to a DCHECK once https://crbug.com/723589 is | |
| 1255 // resolved. | |
| 1256 CHECK(!pac_request_); | |
| 1257 DCHECK(session_); | |
| 1258 | |
| 1259 if (!job->should_reconsider_proxy()) | |
| 1260 return error; | |
| 1261 | |
| 1262 DCHECK(!job->alternative_proxy_server().is_valid()); | |
| 1263 | |
| 1264 // Do not bypass non-QUIC proxy on ERR_MSG_TOO_BIG. | |
| 1265 if (!proxy_info_.is_quic() && error == ERR_MSG_TOO_BIG) | |
| 1266 return error; | |
| 1267 | |
| 1268 if (request_info_.load_flags & LOAD_BYPASS_PROXY) | |
| 1269 return error; | |
| 1270 | |
| 1271 if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) { | |
| 1272 session_->ssl_client_auth_cache()->Remove( | |
| 1273 proxy_info_.proxy_server().host_port_pair()); | |
| 1274 } | |
| 1275 | |
| 1276 HostPortPair destination(HostPortPair::FromURL(request_info_.url)); | |
| 1277 GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination); | |
| 1278 | |
| 1279 int rv = session_->proxy_service()->ReconsiderProxyAfterError( | |
| 1280 origin_url, request_info_.method, error, &proxy_info_, io_callback_, | |
| 1281 &pac_request_, session_->params().proxy_delegate, net_log_); | |
| 1282 if (rv == OK || rv == ERR_IO_PENDING) { | |
| 1283 RemoveRequestFromSpdySessionRequestMap(); | |
| 1284 // Abandon all Jobs and start over. | |
| 1285 job_bound_ = false; | |
| 1286 bound_job_ = nullptr; | |
| 1287 alternative_job_.reset(); | |
| 1288 main_job_.reset(); | |
| 1289 next_state_ = STATE_RESOLVE_PROXY_COMPLETE; | |
| 1290 } else { | |
| 1291 // If ReconsiderProxyAfterError() failed synchronously, it means | |
| 1292 // there was nothing left to fall-back to, so fail the transaction | |
| 1293 // with the last connection error we got. | |
| 1294 // TODO(eroman): This is a confusing contract, make it more obvious. | |
| 1295 rv = error; | |
| 1296 } | |
| 1297 return rv; | |
| 1298 } | |
| 1299 | |
| 1147 } // namespace net | 1300 } // namespace net |
| OLD | NEW |