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