Socket Pools Refactor 22: Let HttpProxyClientSocket take a StreamSocket.

Previously, an HttpProxyClientSocket could only be created with a
ClientSocketHandle, but this CL adds a new constructor that lets it be
created with a StreamSocket, which doesn't require a SocketPool.

The new constructor is not yet in use. We can switch which constructor
is used, and remove the old constructor in followup CLs.

This is part of an effort to flatten the socket pools.
https://docs.google.com/document/d/1g0EA4iDqaDhNXA_mq-YK3SlSX-xRkoKvZetAQqdRrxM/edit

[email protected], [email protected]

Bug: 472729
Change-Id: I9ff442042142787280421b2afbccf1609f27d048
Reviewed-on: https://chromium-review.googlesource.com/c/1450865
Reviewed-by: Matt Menke <[email protected]>
Reviewed-by: mark a. foltz <[email protected]>
Reviewed-by: Asanka Herath <[email protected]>
Commit-Queue: Matt Menke <[email protected]>
Cr-Commit-Position: refs/heads/master@{#630222}
diff --git a/net/dns/address_sorter_posix_unittest.cc b/net/dns/address_sorter_posix_unittest.cc
index 5e8eabc..8f34bc9 100644
--- a/net/dns/address_sorter_posix_unittest.cc
+++ b/net/dns/address_sorter_posix_unittest.cc
@@ -189,6 +189,21 @@
     NOTIMPLEMENTED();
     return nullptr;
   }
+  std::unique_ptr<ProxyClientSocket> CreateProxyClientSocket(
+      std::unique_ptr<StreamSocket> stream_socket,
+      const std::string& user_agent,
+      const HostPortPair& endpoint,
+      const ProxyServer& proxy_server,
+      HttpAuthController* http_auth_controller,
+      bool tunnel,
+      bool using_spdy,
+      NextProto negotiated_protocol,
+      ProxyDelegate* proxy_delegate,
+      bool is_https_proxy,
+      const NetworkTrafficAnnotationTag& traffic_annotation) override {
+    NOTIMPLEMENTED();
+    return nullptr;
+  }
   void AddMapping(const IPAddress& dst, const IPAddress& src) {
     mapping_[dst] = src;
   }
diff --git a/net/dns/dns_session_unittest.cc b/net/dns/dns_session_unittest.cc
index 80d4d4d..5789ed97 100644
--- a/net/dns/dns_session_unittest.cc
+++ b/net/dns/dns_session_unittest.cc
@@ -78,6 +78,22 @@
     return nullptr;
   }
 
+  std::unique_ptr<ProxyClientSocket> CreateProxyClientSocket(
+      std::unique_ptr<StreamSocket> stream_socket,
+      const std::string& user_agent,
+      const HostPortPair& endpoint,
+      const ProxyServer& proxy_server,
+      HttpAuthController* http_auth_controller,
+      bool tunnel,
+      bool using_spdy,
+      NextProto negotiated_protocol,
+      ProxyDelegate* proxy_delegate,
+      bool is_https_proxy,
+      const NetworkTrafficAnnotationTag& traffic_annotation) override {
+    NOTIMPLEMENTED();
+    return nullptr;
+  }
+
  private:
   std::list<std::unique_ptr<SocketDataProvider>> data_providers_;
 };
diff --git a/net/http/http_proxy_client_socket.cc b/net/http/http_proxy_client_socket.cc
index d5cbf07..6c57135 100644
--- a/net/http/http_proxy_client_socket.cc
+++ b/net/http/http_proxy_client_socket.cc
@@ -23,6 +23,7 @@
 #include "net/log/net_log.h"
 #include "net/log/net_log_event_type.h"
 #include "net/socket/client_socket_handle.h"
+#include "net/socket/stream_socket.h"
 #include "url/gurl.h"
 
 namespace net {
@@ -30,7 +31,7 @@
 const int HttpProxyClientSocket::kDrainBodyBufferSize;
 
 HttpProxyClientSocket::HttpProxyClientSocket(
-    std::unique_ptr<ClientSocketHandle> transport_socket,
+    std::unique_ptr<StreamSocket> stream_socket,
     const std::string& user_agent,
     const HostPortPair& endpoint,
     const ProxyServer& proxy_server,
@@ -44,7 +45,9 @@
     : io_callback_(base::BindRepeating(&HttpProxyClientSocket::OnIOComplete,
                                        base::Unretained(this))),
       next_state_(STATE_NONE),
-      transport_(std::move(transport_socket)),
+      stream_socket_(std::move(stream_socket)),
+      socket_(stream_socket_.get()),
+      is_reused_(false),
       endpoint_(endpoint),
       auth_(http_auth_controller),
       tunnel_(tunnel),
@@ -54,8 +57,44 @@
       proxy_server_(proxy_server),
       proxy_delegate_(proxy_delegate),
       traffic_annotation_(traffic_annotation),
-      net_log_(transport_->socket()->NetLog()) {
-  // Synthesize the bits of a request that we actually use.
+      net_log_(socket_->NetLog()) {
+  // Synthesize the bits of a request that are actually used.
+  request_.url = GURL("https://" + endpoint.ToString());
+  request_.method = "CONNECT";
+  if (!user_agent.empty())
+    request_.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
+                                     user_agent);
+}
+
+HttpProxyClientSocket::HttpProxyClientSocket(
+    std::unique_ptr<ClientSocketHandle> client_socket_handle,
+    const std::string& user_agent,
+    const HostPortPair& endpoint,
+    const ProxyServer& proxy_server,
+    HttpAuthController* http_auth_controller,
+    bool tunnel,
+    bool using_spdy,
+    NextProto negotiated_protocol,
+    ProxyDelegate* proxy_delegate,
+    bool is_https_proxy,
+    const NetworkTrafficAnnotationTag& traffic_annotation)
+    : io_callback_(base::BindRepeating(&HttpProxyClientSocket::OnIOComplete,
+                                       base::Unretained(this))),
+      next_state_(STATE_NONE),
+      client_socket_handle_(std::move(client_socket_handle)),
+      socket_(client_socket_handle_->socket()),
+      is_reused_(client_socket_handle_->is_reused()),
+      endpoint_(endpoint),
+      auth_(http_auth_controller),
+      tunnel_(tunnel),
+      using_spdy_(using_spdy),
+      negotiated_protocol_(negotiated_protocol),
+      is_https_proxy_(is_https_proxy),
+      proxy_server_(proxy_server),
+      proxy_delegate_(proxy_delegate),
+      traffic_annotation_(traffic_annotation),
+      net_log_(socket_->NetLog()) {
+  // Synthesize the bits of a request that are actually used.
   request_.url = GURL("https://" + endpoint.ToString());
   request_.method = "CONNECT";
   if (!user_agent.empty())
@@ -102,8 +141,7 @@
 }
 
 int HttpProxyClientSocket::Connect(CompletionOnceCallback callback) {
-  DCHECK(transport_.get());
-  DCHECK(transport_->socket());
+  DCHECK(socket_);
   DCHECK(user_callback_.is_null());
 
   // TODO(rch): figure out the right way to set up a tunnel with SPDY.
@@ -126,8 +164,8 @@
 }
 
 void HttpProxyClientSocket::Disconnect() {
-  if (transport_.get())
-    transport_->socket()->Disconnect();
+  if (socket_)
+    socket_->Disconnect();
 
   // Reset other states to make sure they aren't mistakenly used later.
   // These are the states initialized by Connect().
@@ -136,12 +174,11 @@
 }
 
 bool HttpProxyClientSocket::IsConnected() const {
-  return next_state_ == STATE_DONE && transport_->socket()->IsConnected();
+  return next_state_ == STATE_DONE && socket_->IsConnected();
 }
 
 bool HttpProxyClientSocket::IsConnectedAndIdle() const {
-  return next_state_ == STATE_DONE &&
-    transport_->socket()->IsConnectedAndIdle();
+  return next_state_ == STATE_DONE && socket_->IsConnectedAndIdle();
 }
 
 const NetLogWithSource& HttpProxyClientSocket::NetLog() const {
@@ -149,33 +186,29 @@
 }
 
 bool HttpProxyClientSocket::WasEverUsed() const {
-  if (transport_.get() && transport_->socket()) {
-    return transport_->socket()->WasEverUsed();
-  }
+  if (socket_)
+    return socket_->WasEverUsed();
   NOTREACHED();
   return false;
 }
 
 bool HttpProxyClientSocket::WasAlpnNegotiated() const {
-  if (transport_.get() && transport_->socket()) {
-    return transport_->socket()->WasAlpnNegotiated();
-  }
+  if (socket_)
+    return socket_->WasAlpnNegotiated();
   NOTREACHED();
   return false;
 }
 
 NextProto HttpProxyClientSocket::GetNegotiatedProtocol() const {
-  if (transport_.get() && transport_->socket()) {
-    return transport_->socket()->GetNegotiatedProtocol();
-  }
+  if (socket_)
+    return socket_->GetNegotiatedProtocol();
   NOTREACHED();
   return kProtoUnknown;
 }
 
 bool HttpProxyClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
-  if (transport_.get() && transport_->socket()) {
-    return transport_->socket()->GetSSLInfo(ssl_info);
-  }
+  if (socket_)
+    return socket_->GetSSLInfo(ssl_info);
   NOTREACHED();
   return false;
 }
@@ -186,11 +219,11 @@
 }
 
 int64_t HttpProxyClientSocket::GetTotalReceivedBytes() const {
-  return transport_->socket()->GetTotalReceivedBytes();
+  return socket_->GetTotalReceivedBytes();
 }
 
 void HttpProxyClientSocket::ApplySocketTag(const SocketTag& tag) {
-  return transport_->socket()->ApplySocketTag(tag);
+  return socket_->ApplySocketTag(tag);
 }
 
 int HttpProxyClientSocket::Read(IOBuffer* buf,
@@ -200,7 +233,7 @@
   if (!CheckDone())
     return ERR_TUNNEL_CONNECTION_FAILED;
 
-  return transport_->socket()->Read(buf, buf_len, std::move(callback));
+  return socket_->Read(buf, buf_len, std::move(callback));
 }
 
 int HttpProxyClientSocket::ReadIfReady(IOBuffer* buf,
@@ -210,11 +243,11 @@
   if (!CheckDone())
     return ERR_TUNNEL_CONNECTION_FAILED;
 
-  return transport_->socket()->ReadIfReady(buf, buf_len, std::move(callback));
+  return socket_->ReadIfReady(buf, buf_len, std::move(callback));
 }
 
 int HttpProxyClientSocket::CancelReadIfReady() {
-  return transport_->socket()->CancelReadIfReady();
+  return socket_->CancelReadIfReady();
 }
 
 int HttpProxyClientSocket::Write(
@@ -225,24 +258,23 @@
   DCHECK_EQ(STATE_DONE, next_state_);
   DCHECK(user_callback_.is_null());
 
-  return transport_->socket()->Write(buf, buf_len, std::move(callback),
-                                     traffic_annotation);
+  return socket_->Write(buf, buf_len, std::move(callback), traffic_annotation);
 }
 
 int HttpProxyClientSocket::SetReceiveBufferSize(int32_t size) {
-  return transport_->socket()->SetReceiveBufferSize(size);
+  return socket_->SetReceiveBufferSize(size);
 }
 
 int HttpProxyClientSocket::SetSendBufferSize(int32_t size) {
-  return transport_->socket()->SetSendBufferSize(size);
+  return socket_->SetSendBufferSize(size);
 }
 
 int HttpProxyClientSocket::GetPeerAddress(IPEndPoint* address) const {
-  return transport_->socket()->GetPeerAddress(address);
+  return socket_->GetPeerAddress(address);
 }
 
 int HttpProxyClientSocket::GetLocalAddress(IPEndPoint* address) const {
-  return transport_->socket()->GetLocalAddress(address);
+  return socket_->GetLocalAddress(address);
 }
 
 int HttpProxyClientSocket::PrepareForAuthRestart() {
@@ -253,9 +285,8 @@
   // ERR_UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH.  The request will be retried
   // at a higher layer.
   if (!response_.headers->IsKeepAlive() ||
-      !http_stream_parser_->CanFindEndOfResponse() ||
-      !transport_->socket()->IsConnected()) {
-    transport_->socket()->Disconnect();
+      !http_stream_parser_->CanFindEndOfResponse() || !socket_->IsConnected()) {
+    socket_->Disconnect();
     return ERR_UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH;
   }
 
@@ -271,11 +302,11 @@
 
 int HttpProxyClientSocket::DidDrainBodyForAuthRestart() {
   // Can't reuse the socket if there's still unread data on it.
-  if (!transport_->socket()->IsConnectedAndIdle())
+  if (!socket_->IsConnectedAndIdle())
     return ERR_UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH;
 
   next_state_ = STATE_GENERATE_AUTH_TOKEN;
-  transport_->set_reuse_type(ClientSocketHandle::REUSED_IDLE);
+  is_reused_ = true;
 
   // Reset the other member variables.
   drain_buf_ = nullptr;
@@ -406,9 +437,8 @@
   }
 
   parser_buf_ = base::MakeRefCounted<GrowableIOBuffer>();
-  http_stream_parser_.reset(
-      new HttpStreamParser(transport_->socket(), transport_->is_reused(),
-                           &request_, parser_buf_.get(), net_log_));
+  http_stream_parser_.reset(new HttpStreamParser(socket_, is_reused_, &request_,
+                                                 parser_buf_.get(), net_log_));
   return http_stream_parser_->SendRequest(request_line_, request_headers_,
                                           traffic_annotation_, &response_,
                                           io_callback_);
@@ -473,7 +503,10 @@
         return ERR_TUNNEL_CONNECTION_FAILED;
 
       http_stream_parser_.reset();
-      transport_.reset();
+      client_socket_handle_.reset();
+      stream_socket_.reset();
+      socket_ = nullptr;
+      is_reused_ = false;
       return ERR_HTTPS_PROXY_TUNNEL_RESPONSE;
 
     case 407:  // Proxy Authentication Required
diff --git a/net/http/http_proxy_client_socket.h b/net/http/http_proxy_client_socket.h
index 5c4580f..2585e9a0 100644
--- a/net/http/http_proxy_client_socket.h
+++ b/net/http/http_proxy_client_socket.h
@@ -34,13 +34,15 @@
 class HttpStreamParser;
 class IOBuffer;
 class ProxyDelegate;
+class StreamSocket;
 
 class NET_EXPORT_PRIVATE HttpProxyClientSocket : public ProxyClientSocket {
  public:
-  // Takes ownership of |transport_socket|, which should already be connected
-  // by the time Connect() is called.  If tunnel is true then on Connect()
-  // this socket will establish an Http tunnel.
-  HttpProxyClientSocket(std::unique_ptr<ClientSocketHandle> transport_socket,
+  // Takes ownership of |stream_socket|, which should already be connected
+  // by the time Connect() is called. |stream_socket_| is assumed to be a freash
+  // socket. If tunnel is true then on Connect() this socket will establish an
+  // Http tunnel.
+  HttpProxyClientSocket(std::unique_ptr<StreamSocket> stream_socket,
                         const std::string& user_agent,
                         const HostPortPair& endpoint,
                         const ProxyServer& proxy_server,
@@ -52,6 +54,21 @@
                         bool is_https_proxy,
                         const NetworkTrafficAnnotationTag& traffic_annotation);
 
+  // Same as above, but takes a ClientSocketHandle instead.
+  // TODO(mmenke): Remove in favor of above constructor.
+  HttpProxyClientSocket(
+      std::unique_ptr<ClientSocketHandle> client_socket_handle,
+      const std::string& user_agent,
+      const HostPortPair& endpoint,
+      const ProxyServer& proxy_server,
+      HttpAuthController* http_auth_controller,
+      bool tunnel,
+      bool using_spdy,
+      NextProto negotiated_protocol,
+      ProxyDelegate* proxy_delegate,
+      bool is_https_proxy,
+      const NetworkTrafficAnnotationTag& traffic_annotation);
+
   // On destruction Disconnect() is called.
   ~HttpProxyClientSocket() override;
 
@@ -146,8 +163,16 @@
   std::unique_ptr<HttpStreamParser> http_stream_parser_;
   scoped_refptr<IOBuffer> drain_buf_;
 
-  // Stores the underlying socket.
-  std::unique_ptr<ClientSocketHandle> transport_;
+  // One of these two stores the underlying socket, depending on which
+  // constructor was used.
+  std::unique_ptr<ClientSocketHandle> client_socket_handle_;
+  std::unique_ptr<StreamSocket> stream_socket_;
+  // The underlying socket.
+  StreamSocket* socket_;
+
+  // Whether or not |socket_| has been previously used. Once auth credentials
+  // are sent, set to true.
+  bool is_reused_;
 
   // The hostname and port of the endpoint.  This is not necessarily the one
   // specified by the URL, due to Alternate-Protocol or fixed testing ports.
diff --git a/net/http/http_proxy_client_socket_unittest.cc b/net/http/http_proxy_client_socket_unittest.cc
index d4d11b99..226a671 100644
--- a/net/http/http_proxy_client_socket_unittest.cc
+++ b/net/http/http_proxy_client_socket_unittest.cc
@@ -8,7 +8,6 @@
 #include "net/base/address_list.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/proxy_server.h"
-#include "net/log/test_net_log.h"
 #include "net/socket/next_proto.h"
 #include "net/socket/socket_tag.h"
 #include "net/socket/socket_test_util.h"
@@ -21,18 +20,16 @@
 
 TEST(HttpProxyClientSocketTest, Tag) {
   StaticSocketDataProvider data;
-  TestNetLog log;
   MockTaggingStreamSocket* tagging_sock =
-      new MockTaggingStreamSocket(std::unique_ptr<StreamSocket>(
-          new MockTCPClientSocket(AddressList(), &log, &data)));
+      new MockTaggingStreamSocket(std::make_unique<MockTCPClientSocket>(
+          AddressList(), nullptr /* net_log */, &data));
 
-  std::unique_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
-  // |connection| takes ownership of |tagging_sock|, but keep a
-  // non-owning pointer to it.
-  connection->SetSocket(std::unique_ptr<StreamSocket>(tagging_sock));
-  HttpProxyClientSocket socket(
-      std::move(connection), "", HostPortPair(), ProxyServer(), nullptr, false,
-      false, NextProto(), nullptr, false, TRAFFIC_ANNOTATION_FOR_TESTS);
+  // |socket| takes ownership of |tagging_sock|, but the test keeps a non-owning
+  // pointer to it.
+  HttpProxyClientSocket socket(std::unique_ptr<StreamSocket>(tagging_sock), "",
+                               HostPortPair(), ProxyServer(), nullptr, false,
+                               false, NextProto(), nullptr, false,
+                               TRAFFIC_ANNOTATION_FOR_TESTS);
 
   EXPECT_EQ(tagging_sock->tag(), SocketTag());
 #if defined(OS_ANDROID)
diff --git a/net/proxy_resolution/pac_library_unittest.cc b/net/proxy_resolution/pac_library_unittest.cc
index e78b84b..c32e5b9 100644
--- a/net/proxy_resolution/pac_library_unittest.cc
+++ b/net/proxy_resolution/pac_library_unittest.cc
@@ -284,6 +284,22 @@
     ADD_FAILURE() << "Called CreateProxyClientSocket()";
     return nullptr;
   }
+  std::unique_ptr<ProxyClientSocket> CreateProxyClientSocket(
+      std::unique_ptr<StreamSocket> stream_socket,
+      const std::string& user_agent,
+      const HostPortPair& endpoint,
+      const ProxyServer& proxy_server,
+      HttpAuthController* http_auth_controller,
+      bool tunnel,
+      bool using_spdy,
+      NextProto negotiated_protocol,
+      ProxyDelegate* proxy_delegate,
+      bool is_https_proxy,
+      const NetworkTrafficAnnotationTag& traffic_annotation) override {
+    ADD_FAILURE() << "Called CreateProxyClientSocket()";
+    return nullptr;
+  }
+
  private:
   std::vector<std::unique_ptr<MockUDPSocket>> udp_sockets_;
 
diff --git a/net/socket/client_socket_factory.cc b/net/socket/client_socket_factory.cc
index 62c1579..1b5f7cf 100644
--- a/net/socket/client_socket_factory.cc
+++ b/net/socket/client_socket_factory.cc
@@ -63,6 +63,24 @@
   }
 
   std::unique_ptr<ProxyClientSocket> CreateProxyClientSocket(
+      std::unique_ptr<StreamSocket> stream_socket,
+      const std::string& user_agent,
+      const HostPortPair& endpoint,
+      const ProxyServer& proxy_server,
+      HttpAuthController* http_auth_controller,
+      bool tunnel,
+      bool using_spdy,
+      NextProto negotiated_protocol,
+      ProxyDelegate* proxy_delegate,
+      bool is_https_proxy,
+      const NetworkTrafficAnnotationTag& traffic_annotation) override {
+    return std::make_unique<HttpProxyClientSocket>(
+        std::move(stream_socket), user_agent, endpoint, proxy_server,
+        http_auth_controller, tunnel, using_spdy, negotiated_protocol,
+        proxy_delegate, is_https_proxy, traffic_annotation);
+  }
+
+  std::unique_ptr<ProxyClientSocket> CreateProxyClientSocket(
       std::unique_ptr<ClientSocketHandle> transport_socket,
       const std::string& user_agent,
       const HostPortPair& endpoint,
diff --git a/net/socket/client_socket_factory.h b/net/socket/client_socket_factory.h
index ad90eaa..6ac01e1 100644
--- a/net/socket/client_socket_factory.h
+++ b/net/socket/client_socket_factory.h
@@ -80,6 +80,20 @@
       ProxyDelegate* proxy_delegate,
       bool is_https_proxy,
       const NetworkTrafficAnnotationTag& traffic_annotation) = 0;
+  // Newer version of the above method.
+  // TODO(mmenke): Remove above method in favor of this one.
+  virtual std::unique_ptr<ProxyClientSocket> CreateProxyClientSocket(
+      std::unique_ptr<StreamSocket> stream_socket,
+      const std::string& user_agent,
+      const HostPortPair& endpoint,
+      const ProxyServer& proxy_server,
+      HttpAuthController* http_auth_controller,
+      bool tunnel,
+      bool using_spdy,
+      NextProto negotiated_protocol,
+      ProxyDelegate* proxy_delegate,
+      bool is_https_proxy,
+      const NetworkTrafficAnnotationTag& traffic_annotation) = 0;
 
   // Returns the default ClientSocketFactory.
   static ClientSocketFactory* GetDefaultFactory();
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index e7380c8..e39f164c 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -266,6 +266,22 @@
     return nullptr;
   }
 
+  std::unique_ptr<ProxyClientSocket> CreateProxyClientSocket(
+      std::unique_ptr<StreamSocket> stream_socket,
+      const std::string& user_agent,
+      const HostPortPair& endpoint,
+      const ProxyServer& proxy_server,
+      HttpAuthController* http_auth_controller,
+      bool tunnel,
+      bool using_spdy,
+      NextProto negotiated_protocol,
+      ProxyDelegate* proxy_delegate,
+      bool is_https_proxy,
+      const NetworkTrafficAnnotationTag& traffic_annotation) override {
+    NOTIMPLEMENTED();
+    return nullptr;
+  }
+
   void WaitForSignal(TestConnectJob* job) { waiting_jobs_.push_back(job); }
 
   void SignalJobs();
diff --git a/net/socket/fuzzed_socket_factory.cc b/net/socket/fuzzed_socket_factory.cc
index 5003a10..f9f8634 100644
--- a/net/socket/fuzzed_socket_factory.cc
+++ b/net/socket/fuzzed_socket_factory.cc
@@ -176,4 +176,20 @@
   return nullptr;
 }
 
+std::unique_ptr<ProxyClientSocket> FuzzedSocketFactory::CreateProxyClientSocket(
+    std::unique_ptr<StreamSocket> stream_socket,
+    const std::string& user_agent,
+    const HostPortPair& endpoint,
+    const ProxyServer& proxy_server,
+    HttpAuthController* http_auth_controller,
+    bool tunnel,
+    bool using_spdy,
+    NextProto negotiated_protocol,
+    ProxyDelegate* proxy_delegate,
+    bool is_https_proxy,
+    const NetworkTrafficAnnotationTag& traffic_annotation) {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
 }  // namespace net
diff --git a/net/socket/fuzzed_socket_factory.h b/net/socket/fuzzed_socket_factory.h
index 695bbbcc..42f949e 100644
--- a/net/socket/fuzzed_socket_factory.h
+++ b/net/socket/fuzzed_socket_factory.h
@@ -6,6 +6,7 @@
 #define NET_SOCKET_FUZZED_SOCKET_FACTORY_H_
 
 #include <memory>
+#include <string>
 
 #include "base/macros.h"
 #include "net/socket/client_socket_factory.h"
@@ -71,6 +72,19 @@
       bool is_https_proxy,
       const NetworkTrafficAnnotationTag& traffic_annotation) override;
 
+  std::unique_ptr<ProxyClientSocket> CreateProxyClientSocket(
+      std::unique_ptr<StreamSocket> stream_socket,
+      const std::string& user_agent,
+      const HostPortPair& endpoint,
+      const ProxyServer& proxy_server,
+      HttpAuthController* http_auth_controller,
+      bool tunnel,
+      bool using_spdy,
+      NextProto negotiated_protocol,
+      ProxyDelegate* proxy_delegate,
+      bool is_https_proxy,
+      const NetworkTrafficAnnotationTag& traffic_annotation) override;
+
   // Sets whether Connect()ions on returned sockets can be asynchronously
   // delayed or outright fail. Defaults to true.
   void set_fuzz_connect_result(bool v) { fuzz_connect_result_ = v; }
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index 5260c894..c63941b0e 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -837,6 +837,31 @@
   }
 }
 
+std::unique_ptr<ProxyClientSocket>
+MockClientSocketFactory::CreateProxyClientSocket(
+    std::unique_ptr<StreamSocket> stream_socket,
+    const std::string& user_agent,
+    const HostPortPair& endpoint,
+    const ProxyServer& proxy_server,
+    HttpAuthController* http_auth_controller,
+    bool tunnel,
+    bool using_spdy,
+    NextProto negotiated_protocol,
+    ProxyDelegate* proxy_delegate,
+    bool is_https_proxy,
+    const NetworkTrafficAnnotationTag& traffic_annotation) {
+  if (use_mock_proxy_client_sockets_) {
+    ProxyClientSocketDataProvider* next_proxy_data = mock_proxy_data_.GetNext();
+    return std::make_unique<MockProxyClientSocket>(
+        std::move(stream_socket), http_auth_controller, next_proxy_data);
+  } else {
+    return GetDefaultFactory()->CreateProxyClientSocket(
+        std::move(stream_socket), user_agent, endpoint, proxy_server,
+        http_auth_controller, tunnel, using_spdy, negotiated_protocol,
+        proxy_delegate, is_https_proxy, traffic_annotation);
+  }
+}
+
 MockClientSocket::MockClientSocket(const NetLogWithSource& net_log)
     : connected_(false), net_log_(net_log), weak_factory_(this) {
   local_addr_ = IPEndPoint(IPAddress(192, 0, 2, 33), 123);
@@ -1277,11 +1302,25 @@
 }
 
 MockProxyClientSocket::MockProxyClientSocket(
-    std::unique_ptr<ClientSocketHandle> transport_socket,
+    std::unique_ptr<StreamSocket> stream_socket,
     HttpAuthController* auth_controller,
     ProxyClientSocketDataProvider* data)
-    : net_log_(transport_socket->socket()->NetLog()),
-      transport_(std::move(transport_socket)),
+    : net_log_(stream_socket->NetLog()),
+      stream_socket_(std::move(stream_socket)),
+      socket_(stream_socket_.get()),
+      data_(data),
+      auth_controller_(auth_controller),
+      weak_factory_(this) {
+  DCHECK(data_);
+}
+
+MockProxyClientSocket::MockProxyClientSocket(
+    std::unique_ptr<ClientSocketHandle> client_socket_handle,
+    HttpAuthController* auth_controller,
+    ProxyClientSocketDataProvider* data)
+    : net_log_(client_socket_handle->socket()->NetLog()),
+      client_socket_handle_(std::move(client_socket_handle)),
+      socket_(client_socket_handle_->socket()),
       data_(data),
       auth_controller_(auth_controller),
       weak_factory_(this) {
@@ -1315,13 +1354,13 @@
 int MockProxyClientSocket::Read(IOBuffer* buf,
                                 int buf_len,
                                 CompletionOnceCallback callback) {
-  return transport_->socket()->Read(buf, buf_len, std::move(callback));
+  return socket_->Read(buf, buf_len, std::move(callback));
 }
 
 int MockProxyClientSocket::ReadIfReady(IOBuffer* buf,
                                        int buf_len,
                                        CompletionOnceCallback callback) {
-  return transport_->socket()->ReadIfReady(buf, buf_len, std::move(callback));
+  return socket_->ReadIfReady(buf, buf_len, std::move(callback));
 }
 
 int MockProxyClientSocket::Write(
@@ -1329,12 +1368,11 @@
     int buf_len,
     CompletionOnceCallback callback,
     const NetworkTrafficAnnotationTag& traffic_annotation) {
-  return transport_->socket()->Write(buf, buf_len, std::move(callback),
-                                     traffic_annotation);
+  return socket_->Write(buf, buf_len, std::move(callback), traffic_annotation);
 }
 
 int MockProxyClientSocket::Connect(CompletionOnceCallback callback) {
-  DCHECK(transport_->socket()->IsConnected());
+  DCHECK(socket_->IsConnected());
   if (data_->connect.mode == ASYNC) {
     RunCallbackAsync(std::move(callback), data_->connect.result);
     return ERR_IO_PENDING;
@@ -1343,20 +1381,20 @@
 }
 
 void MockProxyClientSocket::Disconnect() {
-  if (transport_->socket() != NULL)
-    transport_->socket()->Disconnect();
+  if (socket_)
+    socket_->Disconnect();
 }
 
 bool MockProxyClientSocket::IsConnected() const {
-  return transport_->socket()->IsConnected();
+  return socket_->IsConnected();
 }
 
 bool MockProxyClientSocket::IsConnectedAndIdle() const {
-  return transport_->socket()->IsConnectedAndIdle();
+  return socket_->IsConnectedAndIdle();
 }
 
 bool MockProxyClientSocket::WasEverUsed() const {
-  return transport_->socket()->WasEverUsed();
+  return socket_->WasEverUsed();
 }
 
 int MockProxyClientSocket::GetLocalAddress(IPEndPoint* address) const {
@@ -1365,7 +1403,7 @@
 }
 
 int MockProxyClientSocket::GetPeerAddress(IPEndPoint* address) const {
-  return transport_->socket()->GetPeerAddress(address);
+  return socket_->GetPeerAddress(address);
 }
 
 bool MockProxyClientSocket::WasAlpnNegotiated() const {
@@ -1383,7 +1421,7 @@
 }
 
 void MockProxyClientSocket::ApplySocketTag(const SocketTag& tag) {
-  return transport_->socket()->ApplySocketTag(tag);
+  return socket_->ApplySocketTag(tag);
 }
 
 const NetLogWithSource& MockProxyClientSocket::NetLog() const {
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h
index 7f8d71e..7e5c52e7 100644
--- a/net/socket/socket_test_util.h
+++ b/net/socket/socket_test_util.h
@@ -643,6 +643,18 @@
       ProxyDelegate* proxy_delegate,
       bool is_https_proxy,
       const NetworkTrafficAnnotationTag& traffic_annotation) override;
+  std::unique_ptr<ProxyClientSocket> CreateProxyClientSocket(
+      std::unique_ptr<StreamSocket> stream_socket,
+      const std::string& user_agent,
+      const HostPortPair& endpoint,
+      const ProxyServer& proxy_server,
+      HttpAuthController* http_auth_controller,
+      bool tunnel,
+      bool using_spdy,
+      NextProto negotiated_protocol,
+      ProxyDelegate* proxy_delegate,
+      bool is_https_proxy,
+      const NetworkTrafficAnnotationTag& traffic_annotation) override;
   const std::vector<uint16_t>& udp_client_socket_ports() const {
     return udp_client_socket_ports_;
   }
@@ -817,7 +829,12 @@
 
 class MockProxyClientSocket : public AsyncSocket, public ProxyClientSocket {
  public:
-  MockProxyClientSocket(std::unique_ptr<ClientSocketHandle> transport_socket,
+  // TODO(mmenke): Remove this constructor.
+  MockProxyClientSocket(
+      std::unique_ptr<ClientSocketHandle> client_socket_handle,
+      HttpAuthController* auth_controller,
+      ProxyClientSocketDataProvider* data);
+  MockProxyClientSocket(std::unique_ptr<StreamSocket> stream_socket,
                         HttpAuthController* auth_controller,
                         ProxyClientSocketDataProvider* data);
   ~MockProxyClientSocket() override;
@@ -871,7 +888,9 @@
   void RunCallbackAsync(CompletionOnceCallback callback, int result);
 
   NetLogWithSource net_log_;
-  std::unique_ptr<ClientSocketHandle> transport_;
+  std::unique_ptr<ClientSocketHandle> client_socket_handle_;
+  std::unique_ptr<StreamSocket> stream_socket_;
+  StreamSocket* socket_;
   ProxyClientSocketDataProvider* data_;
   scoped_refptr<HttpAuthController> auth_controller_;
 
diff --git a/net/socket/transport_client_socket_pool_test_util.cc b/net/socket/transport_client_socket_pool_test_util.cc
index 6eef9bf..edb87f1 100644
--- a/net/socket/transport_client_socket_pool_test_util.cc
+++ b/net/socket/transport_client_socket_pool_test_util.cc
@@ -479,6 +479,23 @@
   return nullptr;
 }
 
+std::unique_ptr<ProxyClientSocket>
+MockTransportClientSocketFactory::CreateProxyClientSocket(
+    std::unique_ptr<StreamSocket> stream_socket,
+    const std::string& user_agent,
+    const HostPortPair& endpoint,
+    const ProxyServer& proxy_server,
+    HttpAuthController* http_auth_controller,
+    bool tunnel,
+    bool using_spdy,
+    NextProto negotiated_protocol,
+    ProxyDelegate* proxy_delegate,
+    bool is_https_proxy,
+    const NetworkTrafficAnnotationTag& traffic_annotation) {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
 void MockTransportClientSocketFactory::set_client_socket_types(
     ClientSocketType* type_list,
     int num_types) {
diff --git a/net/socket/transport_client_socket_pool_test_util.h b/net/socket/transport_client_socket_pool_test_util.h
index 71b4a72..eeb7d03 100644
--- a/net/socket/transport_client_socket_pool_test_util.h
+++ b/net/socket/transport_client_socket_pool_test_util.h
@@ -111,6 +111,19 @@
       bool is_https_proxy,
       const NetworkTrafficAnnotationTag& traffic_annotation) override;
 
+  std::unique_ptr<ProxyClientSocket> CreateProxyClientSocket(
+      std::unique_ptr<StreamSocket> stream_socket,
+      const std::string& user_agent,
+      const HostPortPair& endpoint,
+      const ProxyServer& proxy_server,
+      HttpAuthController* http_auth_controller,
+      bool tunnel,
+      bool using_spdy,
+      NextProto negotiated_protocol,
+      ProxyDelegate* proxy_delegate,
+      bool is_https_proxy,
+      const NetworkTrafficAnnotationTag& traffic_annotation) override;
+
   int allocation_count() const { return allocation_count_; }
 
   // Set the default ClientSocketType.