Index: net/http/http_stream_factory_impl_job_controller.cc |
diff --git a/net/http/http_stream_factory_impl_job_controller.cc b/net/http/http_stream_factory_impl_job_controller.cc |
index 3978ac26d61d516a09a7fa29d4adda8ccc9ef642..d2f7ae7c5cb9b0e5954b00b5a558f4d987f8dd34 100644 |
--- a/net/http/http_stream_factory_impl_job_controller.cc |
+++ b/net/http/http_stream_factory_impl_job_controller.cc |
@@ -29,6 +29,21 @@ |
namespace net { |
+namespace { |
+// Returns parameters associated with the proxy resolution. |
tbansal1
2017/05/09 20:38:48
nit: linebreak after namespace {
xunjieli
2017/05/10 00:26:24
Done.
|
+std::unique_ptr<base::Value> NetLogHttpStreamJobProxyServerResolved( |
+ const ProxyServer& proxy_server, |
+ NetLogCaptureMode /* capture_mode */) { |
+ std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
+ |
+ dict->SetString("proxy_server", proxy_server.is_valid() |
+ ? proxy_server.ToPacString() |
+ : std::string()); |
+ return std::move(dict); |
+} |
+ |
+} // namespace |
+ |
// The maximum time to wait for the alternate job to complete before resuming |
// the main job. |
const int kMaxDelayTimeForMainJobSecs = 3; |
@@ -51,7 +66,9 @@ HttpStreamFactoryImpl::JobController::JobController( |
const HttpRequestInfo& request_info, |
bool is_preconnect, |
bool enable_ip_based_pooling, |
- bool enable_alternative_services) |
+ bool enable_alternative_services, |
+ const SSLConfig& server_ssl_config, |
+ const SSLConfig& proxy_ssl_config) |
: factory_(factory), |
session_(session), |
job_factory_(job_factory), |
@@ -65,11 +82,20 @@ HttpStreamFactoryImpl::JobController::JobController( |
main_job_is_blocked_(false), |
main_job_is_resumed_(false), |
bound_job_(nullptr), |
- can_start_alternative_proxy_job_(false), |
+ can_start_alternative_proxy_job_(true), |
privacy_mode_(PRIVACY_MODE_DISABLED), |
+ next_state_(STATE_RESOLVE_PROXY), |
+ pac_request_(nullptr), |
net_log_( |
NetLogWithSource::Make(session->net_log(), |
NetLogSourceType::HTTP_STREAM_JOB_CONTROLLER)), |
+ io_callback_( |
+ base::Bind(&JobController::OnIOComplete, base::Unretained(this))), |
+ request_info_(request_info), |
+ server_ssl_config_(server_ssl_config), |
+ proxy_ssl_config_(proxy_ssl_config), |
+ num_streams_(0), |
+ priority_(IDLE), |
ptr_factory_(this) { |
DCHECK(factory); |
net_log_.BeginEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER, |
@@ -81,6 +107,8 @@ HttpStreamFactoryImpl::JobController::~JobController() { |
main_job_.reset(); |
alternative_job_.reset(); |
bound_job_ = nullptr; |
+ if (pac_request_) |
+ session_->proxy_service()->CancelPacRequest(pac_request_); |
net_log_.EndEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER); |
} |
@@ -89,21 +117,20 @@ bool HttpStreamFactoryImpl::JobController::for_websockets() { |
} |
HttpStreamFactoryImpl::Request* HttpStreamFactoryImpl::JobController::Start( |
- const HttpRequestInfo& request_info, |
HttpStreamRequest::Delegate* delegate, |
WebSocketHandshakeStreamBase::CreateHelper* |
websocket_handshake_stream_create_helper, |
const NetLogWithSource& source_net_log, |
HttpStreamRequest::StreamType stream_type, |
- RequestPriority priority, |
- const SSLConfig& server_ssl_config, |
- const SSLConfig& proxy_ssl_config) { |
+ RequestPriority priority) { |
DCHECK(factory_); |
DCHECK(!request_); |
- privacy_mode_ = request_info.privacy_mode; |
+ privacy_mode_ = request_info_.privacy_mode; |
+ stream_type_ = stream_type; |
+ priority_ = priority; |
- request_ = new Request(request_info.url, this, delegate, |
+ request_ = new Request(request_info_.url, this, delegate, |
websocket_handshake_stream_create_helper, |
source_net_log, stream_type); |
// Associates |net_log_| with |source_net_log|. |
@@ -112,47 +139,35 @@ HttpStreamFactoryImpl::Request* HttpStreamFactoryImpl::JobController::Start( |
net_log_.AddEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER_BOUND, |
source_net_log.source().ToEventParametersCallback()); |
- CreateJobs(request_info, priority, server_ssl_config, proxy_ssl_config, |
- delegate, stream_type); |
- |
+ RunLoop(OK); |
return request_; |
} |
-void HttpStreamFactoryImpl::JobController::Preconnect( |
- int num_streams, |
- const HttpRequestInfo& request_info, |
- const SSLConfig& server_ssl_config, |
- const SSLConfig& proxy_ssl_config) { |
+void HttpStreamFactoryImpl::JobController::Preconnect(int num_streams) { |
DCHECK(!main_job_); |
DCHECK(!alternative_job_); |
DCHECK(is_preconnect_); |
- privacy_mode_ = request_info.privacy_mode; |
+ privacy_mode_ = request_info_.privacy_mode; |
+ num_streams_ = num_streams; |
- HostPortPair destination(HostPortPair::FromURL(request_info.url)); |
- GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); |
+ HostPortPair destination(HostPortPair::FromURL(request_info_.url)); |
+ GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination); |
const AlternativeService alternative_service = GetAlternativeServiceFor( |
- request_info, nullptr, HttpStreamRequest::HTTP_STREAM); |
+ request_info_, nullptr, HttpStreamRequest::HTTP_STREAM); |
if (alternative_service.protocol != kProtoUnknown) { |
destination = alternative_service.host_port_pair(); |
- ignore_result(ApplyHostMappingRules(request_info.url, &destination)); |
+ ignore_result(ApplyHostMappingRules(request_info_.url, &destination)); |
} |
- |
- // Due to how the socket pools handle priorities and idle sockets, only IDLE |
- // priority currently makes sense for preconnects. The priority for |
- // preconnects is currently ignored (see RequestSocketsForPool()), but could |
- // be used at some point for proxy resolution or something. |
- main_job_.reset(job_factory_->CreateJob( |
- this, PRECONNECT, session_, request_info, IDLE, server_ssl_config, |
- proxy_ssl_config, destination, origin_url, alternative_service, |
- enable_ip_based_pooling_, session_->net_log())); |
- main_job_->Preconnect(num_streams); |
+ RunLoop(OK); |
} |
LoadState HttpStreamFactoryImpl::JobController::GetLoadState() const { |
DCHECK(request_); |
+ if (next_state_ == STATE_RESOLVE_PROXY_COMPLETE) |
+ return session_->proxy_service()->GetLoadState(pac_request_); |
DCHECK(main_job_ || alternative_job_); |
if (bound_job_) |
return bound_job_->GetLoadState(); |
@@ -187,6 +202,47 @@ int HttpStreamFactoryImpl::JobController::RestartTunnelWithProxyAuth() { |
return bound_job_->RestartTunnelWithProxyAuth(); |
} |
+int HttpStreamFactoryImpl::JobController::ReconsiderProxyAfterError(Job* job, |
tbansal1
2017/05/09 20:38:48
Consider passing |job| as const ref.
xunjieli
2017/05/10 00:26:24
Acknowledged. I will keep it as a raw ptr because
|
+ int error) { |
+ DCHECK(!pac_request_); |
+ DCHECK(session_); |
+ |
+ if (!job->reconsider_proxy()) |
+ return error; |
+ |
tbansal1
2017/05/09 21:16:48
May be add:
DCHECK(!job->alternative_proxy_server(
xunjieli
2017/05/10 00:26:24
Done. Good idea.
|
+ // Do not bypass non-QUIC proxy on ERR_MSG_TOO_BIG. |
+ if (!proxy_info_.is_quic() && error == ERR_MSG_TOO_BIG) |
+ return error; |
+ |
+ if (request_info_.load_flags & LOAD_BYPASS_PROXY) |
+ return error; |
+ |
+ if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) { |
+ session_->ssl_client_auth_cache()->Remove( |
+ proxy_info_.proxy_server().host_port_pair()); |
+ } |
+ |
+ int rv = session_->proxy_service()->ReconsiderProxyAfterError( |
+ request_info_.url, request_info_.method, error, &proxy_info_, |
+ io_callback_, &pac_request_, session_->params().proxy_delegate, net_log_); |
+ if (rv == OK || rv == ERR_IO_PENDING) { |
+ RemoveRequestFromSpdySessionRequestMap(); |
+ // Abandon all Jobs and start over. |
+ job_bound_ = false; |
+ bound_job_ = nullptr; |
+ alternative_job_.reset(); |
tbansal1
2017/05/09 21:16:48
IIUC, this is a functional change? Now, if the mai
xunjieli
2017/05/10 00:26:24
No there is no functional change. This method is o
|
+ main_job_.reset(); |
+ next_state_ = STATE_RESOLVE_PROXY_COMPLETE; |
+ } else { |
+ // If ReconsiderProxyAfterError() failed synchronously, it means |
+ // there was nothing left to fall-back to, so fail the transaction |
+ // with the last connection error we got. |
+ // TODO(eroman): This is a confusing contract, make it more obvious. |
+ rv = error; |
+ } |
+ return rv; |
+} |
+ |
void HttpStreamFactoryImpl::JobController::SetPriority( |
RequestPriority priority) { |
if (main_job_) { |
@@ -278,6 +334,7 @@ void HttpStreamFactoryImpl::JobController::OnStreamFailed( |
if (job->job_type() == ALTERNATIVE) { |
DCHECK_EQ(alternative_job_.get(), job); |
OnAlternativeJobFailed(status); |
+ OnAlternativeProxyJobFailed(status); |
Zhongyi Shi
2017/05/09 20:59:30
an alternative_job_ will be set if an alternative
xunjieli
2017/05/10 00:26:24
Done. Good idea!
|
} |
MaybeResumeMainJob(job, base::TimeDelta()); |
@@ -309,6 +366,11 @@ void HttpStreamFactoryImpl::JobController::OnStreamFailed( |
} |
} |
+ status = ReconsiderProxyAfterError(job, status); |
+ if (next_state_ == STATE_RESOLVE_PROXY_COMPLETE) { |
+ RunLoop(OK); |
+ return; |
+ } |
request_->OnStreamFailed(status, used_ssl_config); |
} |
@@ -402,45 +464,6 @@ bool HttpStreamFactoryImpl::JobController::OnInitConnection( |
return factory_->OnInitConnection(*this, proxy_info, privacy_mode_); |
} |
-void HttpStreamFactoryImpl::JobController::OnResolveProxyComplete( |
- Job* job, |
- const HttpRequestInfo& request_info, |
- RequestPriority priority, |
- const SSLConfig& server_ssl_config, |
- const SSLConfig& proxy_ssl_config, |
- HttpStreamRequest::StreamType stream_type) { |
- DCHECK(job); |
- |
- ProxyServer alternative_proxy_server; |
- if (!ShouldCreateAlternativeProxyServerJob(job, job->proxy_info(), |
- request_info.url, |
- &alternative_proxy_server)) { |
- return; |
- } |
- |
- DCHECK(main_job_); |
- DCHECK_EQ(MAIN, job->job_type()); |
- DCHECK(!alternative_job_); |
- DCHECK(!main_job_is_blocked_); |
- |
- HostPortPair destination(HostPortPair::FromURL(request_info.url)); |
- GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); |
- |
- alternative_job_.reset(job_factory_->CreateJob( |
- this, ALTERNATIVE, session_, request_info, priority, server_ssl_config, |
- proxy_ssl_config, destination, origin_url, alternative_proxy_server, |
- enable_ip_based_pooling_, job->net_log().net_log())); |
- |
- can_start_alternative_proxy_job_ = false; |
- main_job_is_blocked_ = true; |
- |
- base::ThreadTaskRunnerHandle::Get()->PostTask( |
- FROM_HERE, |
- base::Bind( |
- &HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob, |
- ptr_factory_.GetWeakPtr())); |
-} |
- |
void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady( |
Job* job, |
const base::WeakPtr<SpdySession>& spdy_session, |
@@ -689,52 +712,172 @@ WebSocketHandshakeStreamBase::CreateHelper* HttpStreamFactoryImpl:: |
return request_->websocket_handshake_stream_create_helper(); |
} |
-void HttpStreamFactoryImpl::JobController::CreateJobs( |
- const HttpRequestInfo& request_info, |
- RequestPriority priority, |
- const SSLConfig& server_ssl_config, |
- const SSLConfig& proxy_ssl_config, |
- HttpStreamRequest::Delegate* delegate, |
- HttpStreamRequest::StreamType stream_type) { |
+void HttpStreamFactoryImpl::JobController::OnIOComplete(int result) { |
+ RunLoop(result); |
+} |
+ |
+void HttpStreamFactoryImpl::JobController::RunLoop(int result) { |
+ int rv = DoLoop(result); |
+ if (rv == ERR_IO_PENDING) |
+ return; |
+ if (rv != OK) { |
+ DCHECK(!main_job_); |
+ DCHECK(!alternative_job_); |
+ |
+ if (!request_) |
+ return; |
+ request_->OnStreamFailed(rv, server_ssl_config_); |
+ } |
+} |
+ |
+int HttpStreamFactoryImpl::JobController::DoLoop(int rv) { |
+ DCHECK_NE(next_state_, STATE_NONE); |
+ do { |
+ State state = next_state_; |
+ next_state_ = STATE_NONE; |
+ switch (state) { |
+ case STATE_RESOLVE_PROXY: |
+ DCHECK_EQ(OK, rv); |
+ rv = DoResolveProxy(); |
+ break; |
+ case STATE_RESOLVE_PROXY_COMPLETE: |
+ rv = DoResolveProxyComplete(rv); |
+ break; |
+ case STATE_CREATE_JOBS: |
+ DCHECK_EQ(OK, rv); |
+ rv = DoCreateJobs(); |
+ break; |
+ default: |
+ NOTREACHED() << "bad state"; |
+ break; |
+ } |
+ } while (next_state_ != STATE_NONE && rv != ERR_IO_PENDING); |
+ return rv; |
+} |
+ |
+int HttpStreamFactoryImpl::JobController::DoResolveProxy() { |
+ DCHECK(!pac_request_); |
+ DCHECK(session_); |
+ |
+ next_state_ = STATE_RESOLVE_PROXY_COMPLETE; |
+ |
+ if (request_info_.load_flags & LOAD_BYPASS_PROXY) { |
+ proxy_info_.UseDirect(); |
+ return OK; |
+ } |
+ |
+ HostPortPair destination(HostPortPair::FromURL(request_info_.url)); |
+ GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination); |
+ |
+ return session_->proxy_service()->ResolveProxy( |
+ origin_url, request_info_.method, &proxy_info_, io_callback_, |
+ &pac_request_, session_->params().proxy_delegate, net_log_); |
+} |
+ |
+int HttpStreamFactoryImpl::JobController::DoResolveProxyComplete(int rv) { |
+ DCHECK_NE(ERR_IO_PENDING, rv); |
+ |
+ pac_request_ = nullptr; |
+ net_log_.AddEvent( |
+ NetLogEventType::HTTP_STREAM_JOB_PROXY_SERVER_RESOLVED, |
Zhongyi Shi
2017/05/09 20:59:30
optional nit: this will add the log entry to JOB_C
xunjieli
2017/05/10 00:26:24
Acknowledged. Good idea. I will make sure to do th
|
+ base::Bind( |
+ &NetLogHttpStreamJobProxyServerResolved, |
+ proxy_info_.is_empty() ? ProxyServer() : proxy_info_.proxy_server())); |
+ |
+ if (rv == OK) |
+ next_state_ = STATE_CREATE_JOBS; |
+ return rv; |
+} |
+ |
+int HttpStreamFactoryImpl::JobController::DoCreateJobs() { |
DCHECK(!main_job_); |
DCHECK(!alternative_job_); |
- HostPortPair destination(HostPortPair::FromURL(request_info.url)); |
- GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); |
- main_job_.reset(job_factory_->CreateJob( |
- this, MAIN, session_, request_info, priority, server_ssl_config, |
- proxy_ssl_config, destination, origin_url, enable_ip_based_pooling_, |
- net_log_.net_log())); |
+ HostPortPair destination(HostPortPair::FromURL(request_info_.url)); |
+ GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination); |
// Create an alternative job if alternative service is set up for this domain. |
const AlternativeService alternative_service = |
- GetAlternativeServiceFor(request_info, delegate, stream_type); |
- |
- if (alternative_service.protocol != kProtoUnknown) { |
- // Never share connection with other jobs for FTP requests. |
- DVLOG(1) << "Selected alternative service (host: " |
- << alternative_service.host_port_pair().host() |
- << " port: " << alternative_service.host_port_pair().port() << ")"; |
- |
- DCHECK(!request_info.url.SchemeIs(url::kFtpScheme)); |
- HostPortPair alternative_destination(alternative_service.host_port_pair()); |
- ignore_result( |
- ApplyHostMappingRules(request_info.url, &alternative_destination)); |
- |
- alternative_job_.reset(job_factory_->CreateJob( |
- this, ALTERNATIVE, session_, request_info, priority, server_ssl_config, |
- proxy_ssl_config, alternative_destination, origin_url, |
- alternative_service, enable_ip_based_pooling_, net_log_.net_log())); |
- |
- main_job_is_blocked_ = true; |
- alternative_job_->Start(request_->stream_type()); |
+ GetAlternativeServiceFor(request_info_, delegate_, stream_type_); |
tbansal1
2017/05/09 20:38:48
Well, now since the proxy resolution is done ahead
Zhongyi Shi
2017/05/09 20:59:30
nit: this alt svc is only used in non-preconnect c
xunjieli
2017/05/10 00:26:24
I don't quite understand. Are you referring to the
xunjieli
2017/05/10 00:26:24
Alt svc is passed to the preconnect case as well.
Zhongyi Shi
2017/05/10 20:28:15
Acknowledged. *facepalm* I missed the preconnect c
|
+ |
+ // Remove unsupported proxies from the list. ProxyServer::SCHEME_QUIC is not |
+ // yet supported. |
+ int supported_proxies = ProxyServer::SCHEME_DIRECT | |
+ ProxyServer::SCHEME_HTTP | ProxyServer::SCHEME_HTTPS | |
+ ProxyServer::SCHEME_SOCKS4 | |
+ ProxyServer::SCHEME_SOCKS5; |
+ |
+ if (session_->IsQuicEnabled()) |
+ supported_proxies |= ProxyServer::SCHEME_QUIC; |
+ proxy_info_.RemoveProxiesWithoutScheme(supported_proxies); |
+ |
+ if (is_preconnect_) { |
+ // Due to how the socket pools handle priorities and idle sockets, only IDLE |
+ // priority currently makes sense for preconnects. The priority for |
+ // preconnects is currently ignored (see RequestSocketsForPool()), but could |
+ // be used at some point for proxy resolution or something. |
+ main_job_.reset(job_factory_->CreateJob( |
+ this, PRECONNECT, session_, request_info_, IDLE, proxy_info_, |
+ server_ssl_config_, proxy_ssl_config_, destination, origin_url, |
+ alternative_service, enable_ip_based_pooling_, session_->net_log())); |
+ main_job_->Preconnect(num_streams_); |
tbansal1
2017/05/09 20:38:48
may be return OK here, and remove the else below t
xunjieli
2017/05/10 00:26:24
Done. Good idea.
|
} else { |
- can_start_alternative_proxy_job_ = true; |
+ main_job_.reset(job_factory_->CreateJob( |
+ this, MAIN, session_, request_info_, priority_, proxy_info_, |
+ server_ssl_config_, proxy_ssl_config_, destination, origin_url, |
+ enable_ip_based_pooling_, net_log_.net_log())); |
Zhongyi Shi
2017/05/09 20:59:30
optional nit: you might consider move the creation
xunjieli
2017/05/10 00:26:24
Done.
|
+ if (alternative_service.protocol != kProtoUnknown) { |
+ // Never share connection with other jobs for FTP requests. |
+ DVLOG(1) << "Selected alternative service (host: " |
+ << alternative_service.host_port_pair().host() |
+ << " port: " << alternative_service.host_port_pair().port() |
+ << ")"; |
+ |
+ DCHECK(!request_info_.url.SchemeIs(url::kFtpScheme)); |
+ HostPortPair alternative_destination( |
+ alternative_service.host_port_pair()); |
+ ignore_result( |
+ ApplyHostMappingRules(request_info_.url, &alternative_destination)); |
+ |
+ alternative_job_.reset(job_factory_->CreateJob( |
+ this, ALTERNATIVE, session_, request_info_, priority_, proxy_info_, |
+ server_ssl_config_, proxy_ssl_config_, alternative_destination, |
+ origin_url, alternative_service, enable_ip_based_pooling_, |
+ net_log_.net_log())); |
+ |
+ main_job_is_blocked_ = true; |
+ alternative_job_->Start(request_->stream_type()); |
+ } |
Zhongyi Shi
2017/05/09 20:59:30
Could you add some comments here explaining how we
tbansal1
2017/05/09 21:16:48
Right now, the decision is mutually exclusive. The
xunjieli
2017/05/10 00:26:24
Done.
xunjieli
2017/05/10 00:26:24
Acknowledged.
|
+ if (!alternative_job_) { |
+ ProxyServer alternative_proxy_server; |
+ if (ShouldCreateAlternativeProxyServerJob(proxy_info_, request_info_.url, |
+ &alternative_proxy_server)) { |
+ DCHECK(main_job_); |
+ DCHECK(!main_job_is_blocked_); |
+ ProxyInfo alternative_proxy_info; |
+ alternative_proxy_info.UseProxyServer(alternative_proxy_server); |
+ |
+ alternative_job_.reset(job_factory_->CreateJob( |
+ this, ALTERNATIVE, session_, request_info_, priority_, |
+ alternative_proxy_info, server_ssl_config_, proxy_ssl_config_, |
+ destination, origin_url, alternative_proxy_server, |
+ enable_ip_based_pooling_, net_log_.net_log())); |
+ |
+ can_start_alternative_proxy_job_ = false; |
Zhongyi Shi
2017/05/09 20:59:30
Since we explicitly checks whether |alternative_jo
tbansal1
2017/05/09 21:16:48
I think one of the purpose of |can_start_alternati
xunjieli
2017/05/10 00:26:24
Acknowledged.
xunjieli
2017/05/10 00:26:24
we can't get rid of |can_start_alternative_proxy_j
|
+ main_job_is_blocked_ = true; |
+ |
+ base::ThreadTaskRunnerHandle::Get()->PostTask( |
+ FROM_HERE, base::Bind(&HttpStreamFactoryImpl::JobController:: |
+ StartAlternativeProxyServerJob, |
+ ptr_factory_.GetWeakPtr())); |
Zhongyi Shi
2017/05/09 20:59:30
Ummm, this might be a tbansal@ question:
we used t
tbansal1
2017/05/09 21:16:48
Yup, I think this PostTask can be removed. With th
xunjieli
2017/05/10 00:26:24
Done. Good point, Cherie!
xunjieli
2017/05/10 00:26:25
Done. I can't get rid of weak ptr factory, because
|
+ } |
+ } |
+ // Even if |alternative_job| has already finished, it will not have notified |
+ // the request yet, since we defer that to the next iteration of the |
+ // MessageLoop, so starting |main_job_| is always safe. |
+ main_job_->Start(request_->stream_type()); |
} |
- // Even if |alternative_job| has already finished, it will not have notified |
- // the request yet, since we defer that to the next iteration of the |
- // MessageLoop, so starting |main_job_| is always safe. |
- main_job_->Start(request_->stream_type()); |
+ return OK; |
} |
void HttpStreamFactoryImpl::JobController::BindJob(Job* job) { |
@@ -835,15 +978,14 @@ void HttpStreamFactoryImpl::JobController::OnAlternativeJobFailed( |
DCHECK_EQ(alternative_job_->job_type(), ALTERNATIVE); |
DCHECK_NE(OK, net_error); |
+ DCHECK(alternative_job_->alternative_service().protocol != kProtoUnknown || |
+ alternative_job_->alternative_proxy_server().is_valid()); |
+ if (alternative_job_->alternative_proxy_server().is_valid()) |
+ return; |
+ |
alternative_job_net_error_ = net_error; |
- if (alternative_job_->alternative_proxy_server().is_valid()) { |
- failed_alternative_proxy_server_ = |
- alternative_job_->alternative_proxy_server(); |
- } else { |
- DCHECK(!failed_alternative_proxy_server_.is_valid()); |
- failed_alternative_service_ = alternative_job_->alternative_service(); |
- } |
+ failed_alternative_service_ = alternative_job_->alternative_service(); |
if (IsJobOrphaned(alternative_job_.get())) { |
// If |request_| is gone then it must have been successfully served by |
@@ -854,33 +996,40 @@ void HttpStreamFactoryImpl::JobController::OnAlternativeJobFailed( |
} |
} |
+void HttpStreamFactoryImpl::JobController::OnAlternativeProxyJobFailed( |
+ int net_error) { |
+ DCHECK_EQ(alternative_job_->job_type(), ALTERNATIVE); |
+ DCHECK_NE(OK, net_error); |
+ |
+ if (!alternative_job_->alternative_proxy_server().is_valid()) |
+ return; |
+ // Need to mark alt proxy as broken regardless whether the job is bound. |
+ ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; |
+ if (proxy_delegate) { |
+ proxy_delegate->OnAlternativeProxyBroken( |
+ alternative_job_->alternative_proxy_server()); |
+ } |
+} |
+ |
void HttpStreamFactoryImpl::JobController::ReportBrokenAlternativeService() { |
- DCHECK(failed_alternative_service_.protocol != kProtoUnknown || |
- failed_alternative_proxy_server_.is_valid()); |
+ DCHECK(failed_alternative_service_.protocol != kProtoUnknown); |
DCHECK_NE(OK, alternative_job_net_error_); |
- UMA_HISTOGRAM_SPARSE_SLOWLY("Net.AlternateServiceFailed", |
- -alternative_job_net_error_); |
+ int error_to_report = alternative_job_net_error_; |
+ alternative_job_net_error_ = OK; |
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Net.AlternateServiceFailed", -error_to_report); |
if (session_->params().quic_do_not_mark_as_broken_on_network_change && |
- (alternative_job_net_error_ == ERR_NETWORK_CHANGED || |
- alternative_job_net_error_ == ERR_INTERNET_DISCONNECTED)) { |
+ (error_to_report == ERR_NETWORK_CHANGED || |
+ error_to_report == ERR_INTERNET_DISCONNECTED)) { |
// No need to mark alternative service or proxy as broken. |
return; |
} |
- if (failed_alternative_proxy_server_.is_valid()) { |
- ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; |
- if (proxy_delegate) { |
- proxy_delegate->OnAlternativeProxyBroken( |
- failed_alternative_proxy_server_); |
- } |
- } else { |
- HistogramBrokenAlternateProtocolLocation( |
- BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT); |
- session_->http_server_properties()->MarkAlternativeServiceBroken( |
- failed_alternative_service_); |
- } |
+ HistogramBrokenAlternateProtocolLocation( |
+ BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT); |
+ session_->http_server_properties()->MarkAlternativeServiceBroken( |
+ failed_alternative_service_); |
} |
void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() { |
@@ -1033,7 +1182,6 @@ HttpStreamFactoryImpl::JobController::GetAlternativeServiceForInternal( |
bool HttpStreamFactoryImpl::JobController:: |
ShouldCreateAlternativeProxyServerJob( |
- Job* job, |
const ProxyInfo& proxy_info, |
const GURL& url, |
ProxyServer* alternative_proxy_server) const { |
@@ -1048,18 +1196,6 @@ bool HttpStreamFactoryImpl::JobController:: |
return false; |
} |
- if (job->job_type() == ALTERNATIVE) { |
- // If |job| is using alternative service, then alternative proxy server |
- // should not be used. |
- return false; |
- } |
- |
- if (is_preconnect_ || job->job_type() == PRECONNECT) { |
- // Preconnects should be fetched using only the main job to keep the |
- // resource utilization down. |
- return false; |
- } |
- |
if (proxy_info.is_empty() || proxy_info.is_direct() || proxy_info.is_quic()) { |
// Alternative proxy server job can be created only if |job| fetches the |
// |request_| through a non-QUIC proxy. |
@@ -1076,7 +1212,6 @@ bool HttpStreamFactoryImpl::JobController:: |
ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; |
if (!proxy_delegate) |
return false; |
- |
proxy_delegate->GetAlternativeProxy(url, proxy_info.proxy_server(), |
alternative_proxy_server); |