diff options
author | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-24 06:04:12 +0000 |
---|---|---|
committer | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-24 06:04:12 +0000 |
commit | 57d2dfa3c2de8b33fc5ca2555897f70c8c769429 (patch) | |
tree | 841fd25d0ed79b34cbde5a7438ba52d33a542c22 /net | |
parent | 5225cdaa6b88b35a663f2b8fec47e921959b087f (diff) | |
download | chromium_src-57d2dfa3c2de8b33fc5ca2555897f70c8c769429.zip chromium_src-57d2dfa3c2de8b33fc5ca2555897f70c8c769429.tar.gz chromium_src-57d2dfa3c2de8b33fc5ca2555897f70c8c769429.tar.bz2 |
Use a dummy HttpStream for proxy redirects
We synthesize the response headers and ignore the body anyway, so there's
no point to using a real one.
This lets us avoid having to call SetDelegate() twice on a SpdyStream,
so remove support for that.
BUG=252433
Review URL: https://chromiumcodereview.appspot.com/17068018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@208144 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/http/http_network_transaction_unittest.cc | 1 | ||||
-rw-r--r-- | net/http/http_proxy_client_socket.cc | 15 | ||||
-rw-r--r-- | net/http/http_proxy_client_socket.h | 5 | ||||
-rw-r--r-- | net/http/http_proxy_client_socket_pool_spdy2_unittest.cc | 1 | ||||
-rw-r--r-- | net/http/http_proxy_client_socket_pool_spdy3_unittest.cc | 1 | ||||
-rw-r--r-- | net/http/proxy_connect_redirect_http_stream.cc | 122 | ||||
-rw-r--r-- | net/http/proxy_connect_redirect_http_stream.h | 72 | ||||
-rw-r--r-- | net/net.gyp | 2 | ||||
-rw-r--r-- | net/spdy/spdy_http_stream.cc | 12 | ||||
-rw-r--r-- | net/spdy/spdy_http_stream.h | 12 | ||||
-rw-r--r-- | net/spdy/spdy_http_stream_unittest.cc | 11 | ||||
-rw-r--r-- | net/spdy/spdy_proxy_client_socket.cc | 18 | ||||
-rw-r--r-- | net/spdy/spdy_proxy_client_socket.h | 5 | ||||
-rw-r--r-- | net/spdy/spdy_stream.cc | 8 | ||||
-rw-r--r-- | net/spdy/spdy_stream.h | 3 |
15 files changed, 253 insertions, 35 deletions
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 54f58a7..fa36e6b 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -5722,6 +5722,7 @@ TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) { spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); MockWrite data_writes[] = { CreateMockWrite(*conn.get(), 0, SYNCHRONOUS), + CreateMockWrite(*goaway.get(), 3, SYNCHRONOUS), }; static const char* const kExtraHeaders[] = { diff --git a/net/http/http_proxy_client_socket.cc b/net/http/http_proxy_client_socket.cc index 9352312..81f6ff4 100644 --- a/net/http/http_proxy_client_socket.cc +++ b/net/http/http_proxy_client_socket.cc @@ -19,6 +19,7 @@ #include "net/http/http_request_info.h" #include "net/http/http_response_headers.h" #include "net/http/http_stream_parser.h" +#include "net/http/proxy_connect_redirect_http_stream.h" #include "net/socket/client_socket_handle.h" namespace net { @@ -51,6 +52,7 @@ HttpProxyClientSocket::HttpProxyClientSocket( using_spdy_(using_spdy), protocol_negotiated_(protocol_negotiated), is_https_proxy_(is_https_proxy), + redirect_has_load_timing_info_(false), net_log_(transport_socket->socket()->NetLog()) { // Synthesize the bits of a request that we actually use. request_.url = request_url; @@ -99,8 +101,8 @@ const HttpResponseInfo* HttpProxyClientSocket::GetConnectResponseInfo() const { } HttpStream* HttpProxyClientSocket::CreateConnectResponseStream() { - return new HttpBasicStream(transport_.release(), - http_stream_parser_.release(), false); + return new ProxyConnectRedirectHttpStream( + redirect_has_load_timing_info_ ? &redirect_load_timing_info_ : NULL); } @@ -466,8 +468,15 @@ int HttpProxyClientSocket::DoReadHeadersComplete(int result) { // sanitize the response. This still allows a rogue HTTPS proxy to // redirect an HTTPS site load to a similar-looking site, but no longer // allows it to impersonate the site the user requested. - if (is_https_proxy_ && SanitizeProxyRedirect(&response_, request_.url)) + if (is_https_proxy_ && SanitizeProxyRedirect(&response_, request_.url)) { + bool is_connection_reused = http_stream_parser_->IsConnectionReused(); + redirect_has_load_timing_info_ = + transport_->GetLoadTimingInfo( + is_connection_reused, &redirect_load_timing_info_); + transport_.reset(); + http_stream_parser_.reset(); return ERR_HTTPS_PROXY_TUNNEL_RESPONSE; + } // We're not using an HTTPS proxy, or we couldn't sanitize the redirect. LogBlockedTunnelResponse(); diff --git a/net/http/http_proxy_client_socket.h b/net/http/http_proxy_client_socket.h index 6cab666..fca054f 100644 --- a/net/http/http_proxy_client_socket.h +++ b/net/http/http_proxy_client_socket.h @@ -11,6 +11,7 @@ #include "base/memory/ref_counted.h" #include "net/base/completion_callback.h" #include "net/base/host_port_pair.h" +#include "net/base/load_timing_info.h" #include "net/base/net_log.h" #include "net/http/http_auth_controller.h" #include "net/http/http_request_headers.h" @@ -158,6 +159,10 @@ class HttpProxyClientSocket : public ProxyClientSocket { std::string request_line_; HttpRequestHeaders request_headers_; + // Used only for redirects. + bool redirect_has_load_timing_info_; + LoadTimingInfo redirect_load_timing_info_; + const BoundNetLog net_log_; DISALLOW_COPY_AND_ASSIGN(HttpProxyClientSocket); diff --git a/net/http/http_proxy_client_socket_pool_spdy2_unittest.cc b/net/http/http_proxy_client_socket_pool_spdy2_unittest.cc index f6558ed..57f3668 100644 --- a/net/http/http_proxy_client_socket_pool_spdy2_unittest.cc +++ b/net/http/http_proxy_client_socket_pool_spdy2_unittest.cc @@ -555,6 +555,7 @@ TEST_P(HttpProxyClientSocketPoolSpdy2Test, TunnelSetupRedirect) { MockWrite spdy_writes[] = { CreateMockWrite(*req, 0, ASYNC), + CreateMockWrite(*rst, 3, ASYNC), }; const char* const responseHeaders[] = { diff --git a/net/http/http_proxy_client_socket_pool_spdy3_unittest.cc b/net/http/http_proxy_client_socket_pool_spdy3_unittest.cc index 167cd3f..a1436ef 100644 --- a/net/http/http_proxy_client_socket_pool_spdy3_unittest.cc +++ b/net/http/http_proxy_client_socket_pool_spdy3_unittest.cc @@ -556,6 +556,7 @@ TEST_P(HttpProxyClientSocketPoolSpdy3Test, TunnelSetupRedirect) { MockWrite spdy_writes[] = { CreateMockWrite(*req, 0, ASYNC), + CreateMockWrite(*rst, 3, ASYNC), }; const char* const responseHeaders[] = { diff --git a/net/http/proxy_connect_redirect_http_stream.cc b/net/http/proxy_connect_redirect_http_stream.cc new file mode 100644 index 0000000..f30f33c --- /dev/null +++ b/net/http/proxy_connect_redirect_http_stream.cc @@ -0,0 +1,122 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/http/proxy_connect_redirect_http_stream.h" + +#include <cstddef> + +#include "base/logging.h" +#include "net/base/net_errors.h" + +namespace net { + +ProxyConnectRedirectHttpStream::ProxyConnectRedirectHttpStream( + LoadTimingInfo* load_timing_info) + : has_load_timing_info_(load_timing_info != NULL) { + if (has_load_timing_info_) + load_timing_info_ = *load_timing_info; +} + +ProxyConnectRedirectHttpStream::~ProxyConnectRedirectHttpStream() {} + +int ProxyConnectRedirectHttpStream::InitializeStream( + const HttpRequestInfo* request_info, + RequestPriority priority, + const BoundNetLog& net_log, + const CompletionCallback& callback) { + NOTREACHED(); + return OK; +} + +int ProxyConnectRedirectHttpStream::SendRequest( + const HttpRequestHeaders& request_headers, + HttpResponseInfo* response, + const CompletionCallback& callback) { + NOTREACHED(); + return OK; +} + +int ProxyConnectRedirectHttpStream::ReadResponseHeaders( + const CompletionCallback& callback) { + NOTREACHED(); + return OK; +} + +const HttpResponseInfo* +ProxyConnectRedirectHttpStream::GetResponseInfo() const { + NOTREACHED(); + return NULL; +} + +int ProxyConnectRedirectHttpStream::ReadResponseBody( + IOBuffer* buf, + int buf_len, + const CompletionCallback& callback) { + NOTREACHED(); + return OK; +} + +void ProxyConnectRedirectHttpStream::Close(bool not_reusable) {} + +bool ProxyConnectRedirectHttpStream::IsResponseBodyComplete() const { + NOTREACHED(); + return true; +} + +bool ProxyConnectRedirectHttpStream::CanFindEndOfResponse() const { + return true; +} + +bool ProxyConnectRedirectHttpStream::IsConnectionReused() const { + NOTREACHED(); + return false; +} + +void ProxyConnectRedirectHttpStream::SetConnectionReused() { + NOTREACHED(); +} + +bool ProxyConnectRedirectHttpStream::IsConnectionReusable() const { + NOTREACHED(); + return false; +} + +bool ProxyConnectRedirectHttpStream::GetLoadTimingInfo( + LoadTimingInfo* load_timing_info) const { + if (!has_load_timing_info_) + return false; + + *load_timing_info = load_timing_info_; + return true; +} + +void ProxyConnectRedirectHttpStream::GetSSLInfo(SSLInfo* ssl_info) { + NOTREACHED(); +} + +void ProxyConnectRedirectHttpStream::GetSSLCertRequestInfo( + SSLCertRequestInfo* cert_request_info) { + NOTREACHED(); +} + +bool ProxyConnectRedirectHttpStream::IsSpdyHttpStream() const { + NOTREACHED(); + return false; +} + +void ProxyConnectRedirectHttpStream::Drain(HttpNetworkSession* session) { + NOTREACHED(); +} + +UploadProgress ProxyConnectRedirectHttpStream::GetUploadProgress() const { + NOTREACHED(); + return UploadProgress(); +} + +HttpStream* ProxyConnectRedirectHttpStream::RenewStreamForAuth() { + NOTREACHED(); + return NULL; +} + +} // namespace diff --git a/net/http/proxy_connect_redirect_http_stream.h b/net/http/proxy_connect_redirect_http_stream.h new file mode 100644 index 0000000..f39ec76 --- /dev/null +++ b/net/http/proxy_connect_redirect_http_stream.h @@ -0,0 +1,72 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_HTTP_PROXY_CONNECT_REDIRECT_HTTP_STREAM_H_ +#define NET_HTTP_PROXY_CONNECT_REDIRECT_HTTP_STREAM_H_ + +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "net/base/load_timing_info.h" +#include "net/http/http_stream.h" + +namespace net { + +// A dummy HttpStream with no body used when a redirect is returned +// from a proxy. +class ProxyConnectRedirectHttpStream : public HttpStream { + public: + // |load_timing_info| is the info that should be returned by + // GetLoadTimingInfo(), or NULL if there is none. Does not take + // ownership of |load_timing_info|. + explicit ProxyConnectRedirectHttpStream(LoadTimingInfo* load_timing_info); + virtual ~ProxyConnectRedirectHttpStream(); + + // All functions below are expected not to be called except for the + // marked one. + + virtual int InitializeStream(const HttpRequestInfo* request_info, + RequestPriority priority, + const BoundNetLog& net_log, + const CompletionCallback& callback) OVERRIDE; + virtual int SendRequest(const HttpRequestHeaders& request_headers, + HttpResponseInfo* response, + const CompletionCallback& callback) OVERRIDE; + virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE; + virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE; + virtual int ReadResponseBody(IOBuffer* buf, + int buf_len, + const CompletionCallback& callback) OVERRIDE; + + // This function may be called. + virtual void Close(bool not_reusable) OVERRIDE; + + virtual bool IsResponseBodyComplete() const OVERRIDE; + + // This function may be called. + virtual bool CanFindEndOfResponse() const OVERRIDE; + + virtual bool IsConnectionReused() const OVERRIDE; + virtual void SetConnectionReused() OVERRIDE; + virtual bool IsConnectionReusable() const OVERRIDE; + + // This function may be called. + virtual bool GetLoadTimingInfo( + LoadTimingInfo* load_timing_info) const OVERRIDE; + + virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE; + virtual void GetSSLCertRequestInfo( + SSLCertRequestInfo* cert_request_info) OVERRIDE; + virtual bool IsSpdyHttpStream() const OVERRIDE; + virtual void Drain(HttpNetworkSession* session) OVERRIDE; + virtual UploadProgress GetUploadProgress() const OVERRIDE; + virtual HttpStream* RenewStreamForAuth() OVERRIDE; + + private: + bool has_load_timing_info_; + LoadTimingInfo load_timing_info_; +}; + +} // namespace net + +#endif // NET_HTTP_PROXY_CONNECT_REDIRECT_HTTP_STREAM_H_ diff --git a/net/net.gyp b/net/net.gyp index 1d6d0d0..ee09c60 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -605,6 +605,8 @@ 'http/partial_data.h', 'http/proxy_client_socket.h', 'http/proxy_client_socket.cc', + 'http/proxy_connect_redirect_http_stream.h', + 'http/proxy_connect_redirect_http_stream.cc', 'http/transport_security_state.cc', 'http/transport_security_state.h', 'http/transport_security_state_static.h', diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc index e10aaa6..9241424 100644 --- a/net/spdy/spdy_http_stream.cc +++ b/net/spdy/spdy_http_stream.cc @@ -25,8 +25,7 @@ namespace net { -SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, - bool direct) +SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, bool direct) : weak_factory_(this), spdy_session_(spdy_session), stream_closed_(false), @@ -39,13 +38,8 @@ SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, request_body_buf_size_(0), buffered_read_callback_pending_(false), more_read_data_pending_(false), - direct_(direct) {} - -void SpdyHttpStream::InitializeWithExistingStream( - const base::WeakPtr<SpdyStream>& spdy_stream) { - stream_ = spdy_stream; - stream_->SetDelegate(this); - response_headers_received_ = true; + direct_(direct) { + DCHECK(spdy_session_); } SpdyHttpStream::~SpdyHttpStream() { diff --git a/net/spdy/spdy_http_stream.h b/net/spdy/spdy_http_stream.h index 1ad8576..1ce0290 100644 --- a/net/spdy/spdy_http_stream.h +++ b/net/spdy/spdy_http_stream.h @@ -30,18 +30,10 @@ class UploadDataStream; class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate, public HttpStream { public: - // |spdy_session| may be NULL, but in that case some functions must - // not be called (see comments below). + // |spdy_session| must not be NULL. SpdyHttpStream(SpdySession* spdy_session, bool direct); virtual ~SpdyHttpStream(); - // Initializes this SpdyHttpStream by wrapping an existing - // SpdyStream. In particular, this must be called instead of - // InitializeStream() if a NULL SpdySession was passed into the - // constructor. - void InitializeWithExistingStream( - const base::WeakPtr<SpdyStream>& spdy_stream); - SpdyStream* stream() { return stream_.get(); } // Cancels any callbacks from being invoked and deletes the stream. @@ -49,8 +41,6 @@ class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate, // HttpStream implementation. - // Must not be called if a NULL SpdySession was passed into the - // constructor. virtual int InitializeStream(const HttpRequestInfo* request_info, RequestPriority priority, const BoundNetLog& net_log, diff --git a/net/spdy/spdy_http_stream_unittest.cc b/net/spdy/spdy_http_stream_unittest.cc index 88b279f..5c29484 100644 --- a/net/spdy/spdy_http_stream_unittest.cc +++ b/net/spdy/spdy_http_stream_unittest.cc @@ -176,7 +176,16 @@ TEST_P(SpdyHttpStreamTest, GetUploadProgressBeforeInitialization) { if (GetParam() > kProtoSPDY3) return; - SpdyHttpStream stream(NULL, false); + MockRead reads[] = { + MockRead(ASYNC, 0, 0) // EOF + }; + + HostPortPair host_port_pair("www.google.com", 80); + SpdySessionKey key(host_port_pair, ProxyServer::Direct(), + kPrivacyModeDisabled); + EXPECT_EQ(OK, InitSession(reads, arraysize(reads), NULL, 0, host_port_pair)); + + SpdyHttpStream stream(session_, false); UploadProgress progress = stream.GetUploadProgress(); EXPECT_EQ(0u, progress.size()); EXPECT_EQ(0u, progress.position()); diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc index 2c8ea6f..641637a 100644 --- a/net/spdy/spdy_proxy_client_socket.cc +++ b/net/spdy/spdy_proxy_client_socket.cc @@ -19,6 +19,7 @@ #include "net/http/http_auth_cache.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_response_headers.h" +#include "net/http/proxy_connect_redirect_http_stream.h" #include "net/spdy/spdy_http_utils.h" namespace net { @@ -42,6 +43,8 @@ SpdyProxyClientSocket::SpdyProxyClientSocket( auth_handler_factory)), user_buffer_len_(0), write_buffer_len_(0), + was_ever_used_(false), + redirect_has_load_timing_info_(false), weak_factory_(this), net_log_(BoundNetLog::Make(spdy_stream->net_log().net_log(), NetLog::SOURCE_PROXY_CLIENT_SOCKET)) { @@ -98,8 +101,8 @@ NextProto SpdyProxyClientSocket::GetProtocolNegotiated() const { } HttpStream* SpdyProxyClientSocket::CreateConnectResponseStream() { - DCHECK(response_stream_.get()); - return response_stream_.release(); + return new ProxyConnectRedirectHttpStream( + redirect_has_load_timing_info_ ? &redirect_load_timing_info_ : NULL); } // Sends a SYN_STREAM frame to the proxy with a CONNECT request @@ -405,14 +408,9 @@ int SpdyProxyClientSocket::DoReadReplyComplete(int result) { // Try to return a sanitized response so we can follow auth redirects. // If we can't, fail the tunnel connection. if (SanitizeProxyRedirect(&response_, request_.url)) { - // Immediately hand off our SpdyStream to a newly created - // SpdyHttpStream so that any subsequent SpdyFrames are processed in - // the context of the HttpStream, not the socket. - DCHECK(spdy_stream_.get()); - base::WeakPtr<SpdyStream> stream = spdy_stream_; - spdy_stream_.reset(); - response_stream_.reset(new SpdyHttpStream(NULL, false)); - response_stream_->InitializeWithExistingStream(stream); + redirect_has_load_timing_info_ = + spdy_stream_->GetLoadTimingInfo(&redirect_load_timing_info_); + spdy_stream_->DetachDelegate(); next_state_ = STATE_DISCONNECTED; return ERR_HTTPS_PROXY_TUNNEL_RESPONSE; } else { diff --git a/net/spdy/spdy_proxy_client_socket.h b/net/spdy/spdy_proxy_client_socket.h index d80e1d8..be0ed69 100644 --- a/net/spdy/spdy_proxy_client_socket.h +++ b/net/spdy/spdy_proxy_client_socket.h @@ -13,6 +13,7 @@ #include "base/memory/weak_ptr.h" #include "net/base/completion_callback.h" #include "net/base/host_port_pair.h" +#include "net/base/load_timing_info.h" #include "net/base/net_log.h" #include "net/http/http_auth_controller.h" #include "net/http/http_request_headers.h" @@ -159,7 +160,9 @@ class NET_EXPORT_PRIVATE SpdyProxyClientSocket : public ProxyClientSocket, // True if the transport socket has ever sent data. bool was_ever_used_; - scoped_ptr<SpdyHttpStream> response_stream_; + // Used only for redirects. + bool redirect_has_load_timing_info_; + LoadTimingInfo redirect_load_timing_info_; base::WeakPtrFactory<SpdyProxyClientSocket> weak_factory_; diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc index 190e175..2c2749b 100644 --- a/net/spdy/spdy_stream.cc +++ b/net/spdy/spdy_stream.cc @@ -125,6 +125,7 @@ SpdyStream::~SpdyStream() { } void SpdyStream::SetDelegate(Delegate* delegate) { + CHECK(!delegate_); CHECK(delegate); delegate_ = delegate; @@ -659,6 +660,13 @@ GURL SpdyStream::GetUrl() const { type_ == SPDY_PUSH_STREAM); } +bool SpdyStream::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const { + if (stream_id_ == 0) + return false; + + return session_->GetLoadTimingInfo(stream_id_, load_timing_info); +} + void SpdyStream::OnGetDomainBoundCertComplete(int result) { DCHECK_EQ(io_state_, STATE_GET_DOMAIN_BOUND_CERT_COMPLETE); DoLoop(result); diff --git a/net/spdy/spdy_stream.h b/net/spdy/spdy_stream.h index 28eaf40..b410226 100644 --- a/net/spdy/spdy_stream.h +++ b/net/spdy/spdy_stream.h @@ -32,6 +32,7 @@ namespace net { class AddressList; class IPEndPoint; +struct LoadTimingInfo; class SSLCertRequestInfo; class SSLInfo; class SpdySession; @@ -325,6 +326,8 @@ class NET_EXPORT_PRIVATE SpdyStream { int response_status() const { return response_status_; } + bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const; + // Returns true if the URL for this stream is known. bool HasUrl() const; |