| Index: net/http/http_stream_factory_impl_job.cc
|
| diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc
|
| index 34bab8a3b29b3e3d24bcffb09cf42dae0a3c802b..c6c5ce24ca0bb51875b526615ffe1d7b9b138d29 100644
|
| --- a/net/http/http_stream_factory_impl_job.cc
|
| +++ b/net/http/http_stream_factory_impl_job.cc
|
| @@ -12,7 +12,6 @@
|
| #include "base/feature_list.h"
|
| #include "base/location.h"
|
| #include "base/logging.h"
|
| -#include "base/memory/ptr_util.h"
|
| #include "base/metrics/histogram_macros.h"
|
| #include "base/metrics/sparse_histogram.h"
|
| #include "base/profiler/scoped_tracker.h"
|
| @@ -149,12 +148,23 @@ std::unique_ptr<base::Value> NetLogHttpStreamProtoCallback(
|
| return std::move(dict);
|
| }
|
|
|
| +// Returns parameters associated with the proxy resolution.
|
| +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);
|
| +}
|
| +
|
| HttpStreamFactoryImpl::Job::Job(Delegate* delegate,
|
| JobType job_type,
|
| HttpNetworkSession* session,
|
| const HttpRequestInfo& request_info,
|
| RequestPriority priority,
|
| - const ProxyInfo& proxy_info,
|
| const SSLConfig& server_ssl_config,
|
| const SSLConfig& proxy_ssl_config,
|
| HostPortPair destination,
|
| @@ -166,7 +176,6 @@ HttpStreamFactoryImpl::Job::Job(Delegate* delegate,
|
| session,
|
| request_info,
|
| priority,
|
| - proxy_info,
|
| server_ssl_config,
|
| proxy_ssl_config,
|
| destination,
|
| @@ -181,7 +190,6 @@ HttpStreamFactoryImpl::Job::Job(Delegate* delegate,
|
| HttpNetworkSession* session,
|
| const HttpRequestInfo& request_info,
|
| RequestPriority priority,
|
| - const ProxyInfo& proxy_info,
|
| const SSLConfig& server_ssl_config,
|
| const SSLConfig& proxy_ssl_config,
|
| HostPortPair destination,
|
| @@ -192,7 +200,6 @@ HttpStreamFactoryImpl::Job::Job(Delegate* delegate,
|
| NetLog* net_log)
|
| : request_info_(request_info),
|
| priority_(priority),
|
| - proxy_info_(proxy_info),
|
| server_ssl_config_(server_ssl_config),
|
| proxy_ssl_config_(proxy_ssl_config),
|
| net_log_(
|
| @@ -202,6 +209,7 @@ HttpStreamFactoryImpl::Job::Job(Delegate* delegate,
|
| session_(session),
|
| state_(STATE_NONE),
|
| next_state_(STATE_NONE),
|
| + pac_request_(NULL),
|
| destination_(destination),
|
| origin_url_(origin_url),
|
| alternative_service_(alternative_service),
|
| @@ -213,7 +221,6 @@ HttpStreamFactoryImpl::Job::Job(Delegate* delegate,
|
| origin_url_.SchemeIs(url::kWssScheme)),
|
| using_spdy_(false),
|
| using_quic_(false),
|
| - should_reconsider_proxy_(false),
|
| quic_request_(session_->quic_stream_factory()),
|
| using_existing_quic_session_(false),
|
| establishing_tunnel_(false),
|
| @@ -262,6 +269,9 @@ HttpStreamFactoryImpl::Job::~Job() {
|
| connection_.reset();
|
| }
|
|
|
| + if (pac_request_)
|
| + session_->proxy_service()->CancelPacRequest(pac_request_);
|
| +
|
| // The stream could be in a partial state. It is not reusable.
|
| if (stream_.get() && next_state_ != STATE_DONE)
|
| stream_->Close(true /* not reusable */);
|
| @@ -306,6 +316,8 @@ int HttpStreamFactoryImpl::Job::RestartTunnelWithProxyAuth() {
|
|
|
| LoadState HttpStreamFactoryImpl::Job::GetLoadState() const {
|
| switch (next_state_) {
|
| + case STATE_RESOLVE_PROXY_COMPLETE:
|
| + return session_->proxy_service()->GetLoadState(pac_request_);
|
| case STATE_INIT_CONNECTION_COMPLETE:
|
| case STATE_CREATE_STREAM_COMPLETE:
|
| return using_quic_ ? LOAD_STATE_CONNECTING : connection_->GetLoadState();
|
| @@ -402,8 +414,8 @@ SpdySessionKey HttpStreamFactoryImpl::Job::GetSpdySessionKey() const {
|
| return SpdySessionKey(proxy_info_.proxy_server().host_port_pair(),
|
| ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
|
| }
|
| - return SpdySessionKey(HostPortPair::FromURL(origin_url_),
|
| - proxy_info_.proxy_server(), request_info_.privacy_mode);
|
| + return SpdySessionKey(destination_, proxy_info_.proxy_server(),
|
| + request_info_.privacy_mode);
|
| }
|
|
|
| bool HttpStreamFactoryImpl::Job::CanUseExistingSpdySession() const {
|
| @@ -676,6 +688,13 @@ int HttpStreamFactoryImpl::Job::DoLoop(int result) {
|
| DCHECK_EQ(OK, rv);
|
| rv = DoStart();
|
| break;
|
| + case STATE_RESOLVE_PROXY:
|
| + DCHECK_EQ(OK, rv);
|
| + rv = DoResolveProxy();
|
| + break;
|
| + case STATE_RESOLVE_PROXY_COMPLETE:
|
| + rv = DoResolveProxyComplete(rv);
|
| + break;
|
| case STATE_WAIT:
|
| DCHECK_EQ(OK, rv);
|
| rv = DoWait();
|
| @@ -742,7 +761,75 @@ int HttpStreamFactoryImpl::Job::DoStart() {
|
| return ERR_UNSAFE_PORT;
|
| }
|
|
|
| + next_state_ = STATE_RESOLVE_PROXY;
|
| + return OK;
|
| +}
|
| +
|
| +int HttpStreamFactoryImpl::Job::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;
|
| + }
|
| +
|
| + // If an alternative proxy server was provided, use that.
|
| + if (alternative_proxy_server_.is_valid()) {
|
| + proxy_info_.UseProxyServer(alternative_proxy_server_);
|
| + return OK;
|
| + }
|
| +
|
| + return session_->proxy_service()->ResolveProxy(
|
| + origin_url_, request_info_.method, &proxy_info_, io_callback_,
|
| + &pac_request_, session_->params().proxy_delegate, net_log_);
|
| +}
|
| +
|
| +int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) {
|
| + pac_request_ = NULL;
|
| +
|
| + net_log_.AddEvent(
|
| + NetLogEventType::HTTP_STREAM_JOB_PROXY_SERVER_RESOLVED,
|
| + base::Bind(
|
| + &NetLogHttpStreamJobProxyServerResolved,
|
| + proxy_info_.is_empty() ? ProxyServer() : proxy_info_.proxy_server()));
|
| +
|
| + if (result == OK) {
|
| + // Remove unsupported proxies from the list.
|
| + 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 (proxy_info_.is_empty()) {
|
| + // No proxies/direct to choose from. This happens when we don't support
|
| + // any of the proxies in the returned list.
|
| + result = ERR_NO_SUPPORTED_PROXIES;
|
| + } else if (using_quic_ &&
|
| + (!proxy_info_.is_quic() && !proxy_info_.is_direct())) {
|
| + // QUIC can not be spoken to non-QUIC proxies. This error should not be
|
| + // user visible, because the non-alternative Job should be resumed.
|
| + result = ERR_NO_SUPPORTED_PROXIES;
|
| + }
|
| + }
|
| +
|
| + if (result != OK) {
|
| + return result;
|
| + }
|
| +
|
| next_state_ = STATE_WAIT;
|
| +
|
| + delegate_->OnResolveProxyComplete(this, request_info_, priority_,
|
| + server_ssl_config_, proxy_ssl_config_,
|
| + stream_type_);
|
| +
|
| return OK;
|
| }
|
|
|
| @@ -788,13 +875,6 @@ int HttpStreamFactoryImpl::Job::DoInitConnectionImpl() {
|
| FROM_HERE_WITH_EXPLICIT_FUNCTION(
|
| "462812 HttpStreamFactoryImpl::Job::DoInitConnection"));
|
| DCHECK(!connection_->is_initialized());
|
| -
|
| - if (using_quic_ && !proxy_info_.is_quic() && !proxy_info_.is_direct()) {
|
| - // QUIC can not be spoken to non-QUIC proxies. This error should not be
|
| - // user visible, because the non-alternative Job should be resumed.
|
| - return ERR_NO_SUPPORTED_PROXIES;
|
| - }
|
| -
|
| DCHECK(proxy_info_.proxy_server().is_valid());
|
| next_state_ = STATE_INIT_CONNECTION_COMPLETE;
|
|
|
| @@ -1066,7 +1146,6 @@ int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) {
|
|
|
| if (result < 0 && !ssl_started)
|
| return ReconsiderProxyAfterError(result);
|
| -
|
| establishing_tunnel_ = false;
|
|
|
| // Handle SSL errors below.
|
| @@ -1334,6 +1413,17 @@ void HttpStreamFactoryImpl::Job::InitSSLConfig(SSLConfig* ssl_config,
|
| }
|
|
|
| int HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError(int error) {
|
| + DCHECK(!pac_request_);
|
| + DCHECK(session_);
|
| +
|
| + // A failure to resolve the hostname or any error related to establishing a
|
| + // TCP connection could be grounds for trying a new proxy configuration.
|
| + //
|
| + // Why do this when a hostname cannot be resolved? Some URLs only make sense
|
| + // to proxy servers. The hostname in those URLs might fail to resolve if we
|
| + // are still using a non-proxy config. We need to check if a proxy config
|
| + // now exists that corresponds to a proxy server that could load the URL.
|
| + //
|
| switch (error) {
|
| case ERR_PROXY_CONNECTION_FAILED:
|
| case ERR_NAME_NOT_RESOLVED:
|
| @@ -1372,16 +1462,46 @@ int HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError(int error) {
|
| return error;
|
| }
|
|
|
| + // 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;
|
| +
|
| // Alternative proxy server job should not use fallback proxies, and instead
|
| // return. This would resume the main job (if possible) which may try the
|
| // fallback proxies.
|
| - if (alternative_proxy_server().is_valid()) {
|
| + if (alternative_proxy_server_.is_valid()) {
|
| DCHECK_EQ(STATE_NONE, next_state_);
|
| return error;
|
| }
|
|
|
| - should_reconsider_proxy_ = true;
|
| - 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) {
|
| + // If the error was during connection setup, there is no socket to
|
| + // disconnect.
|
| + if (connection_->socket())
|
| + connection_->socket()->Disconnect();
|
| + connection_->Reset();
|
| + delegate_->RemoveRequestFromSpdySessionRequestMapForJob(this);
|
| + 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;
|
| }
|
|
|
| int HttpStreamFactoryImpl::Job::HandleCertificateError(int error) {
|
| @@ -1443,71 +1563,4 @@ void HttpStreamFactoryImpl::Job::
|
| delegate_->AddConnectionAttemptsToRequest(this, socket_attempts);
|
| }
|
|
|
| -HttpStreamFactoryImpl::JobFactory::JobFactory() {}
|
| -
|
| -HttpStreamFactoryImpl::JobFactory::~JobFactory() {}
|
| -
|
| -std::unique_ptr<HttpStreamFactoryImpl::Job>
|
| -HttpStreamFactoryImpl::JobFactory::CreateMainJob(
|
| - HttpStreamFactoryImpl::Job::Delegate* delegate,
|
| - HttpStreamFactoryImpl::JobType job_type,
|
| - HttpNetworkSession* session,
|
| - const HttpRequestInfo& request_info,
|
| - RequestPriority priority,
|
| - const ProxyInfo& proxy_info,
|
| - const SSLConfig& server_ssl_config,
|
| - const SSLConfig& proxy_ssl_config,
|
| - HostPortPair destination,
|
| - GURL origin_url,
|
| - bool enable_ip_based_pooling,
|
| - NetLog* net_log) {
|
| - return base::MakeUnique<HttpStreamFactoryImpl::Job>(
|
| - delegate, job_type, session, request_info, priority, proxy_info,
|
| - server_ssl_config, proxy_ssl_config, destination, origin_url,
|
| - enable_ip_based_pooling, net_log);
|
| -}
|
| -
|
| -std::unique_ptr<HttpStreamFactoryImpl::Job>
|
| -HttpStreamFactoryImpl::JobFactory::CreateAltSvcJob(
|
| - HttpStreamFactoryImpl::Job::Delegate* delegate,
|
| - HttpStreamFactoryImpl::JobType job_type,
|
| - HttpNetworkSession* session,
|
| - const HttpRequestInfo& request_info,
|
| - RequestPriority priority,
|
| - const ProxyInfo& proxy_info,
|
| - const SSLConfig& server_ssl_config,
|
| - const SSLConfig& proxy_ssl_config,
|
| - HostPortPair destination,
|
| - GURL origin_url,
|
| - AlternativeService alternative_service,
|
| - bool enable_ip_based_pooling,
|
| - NetLog* net_log) {
|
| - return base::MakeUnique<HttpStreamFactoryImpl::Job>(
|
| - delegate, job_type, session, request_info, priority, proxy_info,
|
| - server_ssl_config, proxy_ssl_config, destination, origin_url,
|
| - alternative_service, ProxyServer(), enable_ip_based_pooling, net_log);
|
| -}
|
| -
|
| -std::unique_ptr<HttpStreamFactoryImpl::Job>
|
| -HttpStreamFactoryImpl::JobFactory::CreateAltProxyJob(
|
| - HttpStreamFactoryImpl::Job::Delegate* delegate,
|
| - HttpStreamFactoryImpl::JobType job_type,
|
| - HttpNetworkSession* session,
|
| - const HttpRequestInfo& request_info,
|
| - RequestPriority priority,
|
| - const ProxyInfo& proxy_info,
|
| - const SSLConfig& server_ssl_config,
|
| - const SSLConfig& proxy_ssl_config,
|
| - HostPortPair destination,
|
| - GURL origin_url,
|
| - const ProxyServer& alternative_proxy_server,
|
| - bool enable_ip_based_pooling,
|
| - NetLog* net_log) {
|
| - return base::MakeUnique<HttpStreamFactoryImpl::Job>(
|
| - delegate, job_type, session, request_info, priority, proxy_info,
|
| - server_ssl_config, proxy_ssl_config, destination, origin_url,
|
| - AlternativeService(), alternative_proxy_server, enable_ip_based_pooling,
|
| - net_log);
|
| -}
|
| -
|
| } // namespace net
|
|
|