diff --git a/net/net.gyp b/net/net.gyp
index 2c6ef1520f479..1cce2a62858ca 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -909,8 +909,6 @@
         'socket/tcp_client_socket.h',
         'socket/tcp_client_socket_libevent.cc',
         'socket/tcp_client_socket_libevent.h',
-        'socket/tcp_client_socket_win.cc',
-        'socket/tcp_client_socket_win.h',
         'socket/tcp_listen_socket.cc',
         'socket/tcp_listen_socket.h',
         'socket/tcp_server_socket.cc',
diff --git a/net/socket/tcp_client_socket.cc b/net/socket/tcp_client_socket.cc
index a91d33d24c8cb..af1c555caa0bd 100644
--- a/net/socket/tcp_client_socket.cc
+++ b/net/socket/tcp_client_socket.cc
@@ -4,8 +4,14 @@
 
 #include "net/socket/tcp_client_socket.h"
 
+#include "base/callback_helpers.h"
 #include "base/file_util.h"
 #include "base/files/file_path.h"
+#include "base/logging.h"
+#include "net/base/io_buffer.h"
+#include "net/base/ip_endpoint.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
 
 namespace net {
 
@@ -56,4 +62,312 @@ bool IsTCPFastOpenEnabled() {
   return g_tcp_fastopen_enabled;
 }
 
+#if defined(OS_WIN)
+
+TCPClientSocket::TCPClientSocket(const AddressList& addresses,
+                                 net::NetLog* net_log,
+                                 const net::NetLog::Source& source)
+    : socket_(new TCPSocket(net_log, source)),
+      addresses_(addresses),
+      current_address_index_(-1),
+      next_connect_state_(CONNECT_STATE_NONE),
+      previously_disconnected_(false) {
+}
+
+TCPClientSocket::TCPClientSocket(scoped_ptr<TCPSocket> connected_socket,
+                                 const IPEndPoint& peer_address)
+    : socket_(connected_socket.Pass()),
+      addresses_(AddressList(peer_address)),
+      current_address_index_(0),
+      next_connect_state_(CONNECT_STATE_NONE),
+      previously_disconnected_(false) {
+  DCHECK(socket_);
+
+  socket_->SetDefaultOptionsForClient();
+  use_history_.set_was_ever_connected();
+}
+
+TCPClientSocket::~TCPClientSocket() {
+}
+
+int TCPClientSocket::Bind(const IPEndPoint& address) {
+  if (current_address_index_ >= 0 || bind_address_) {
+    // Cannot bind the socket if we are already connected or connecting.
+    NOTREACHED();
+    return ERR_UNEXPECTED;
+  }
+
+  int result = OK;
+  if (!socket_->IsValid()) {
+    result = OpenSocket(address.GetFamily());
+    if (result != OK)
+      return result;
+  }
+
+  result = socket_->Bind(address);
+  if (result != OK)
+    return result;
+
+  bind_address_.reset(new IPEndPoint(address));
+  return OK;
+}
+
+int TCPClientSocket::Connect(const CompletionCallback& callback) {
+  DCHECK(!callback.is_null());
+
+  // If connecting or already connected, then just return OK.
+  if (socket_->IsValid() && current_address_index_ >= 0)
+    return OK;
+
+  socket_->StartLoggingMultipleConnectAttempts(addresses_);
+
+  // We will try to connect to each address in addresses_. Start with the
+  // first one in the list.
+  next_connect_state_ = CONNECT_STATE_CONNECT;
+  current_address_index_ = 0;
+
+  int rv = DoConnectLoop(OK);
+  if (rv == ERR_IO_PENDING) {
+    connect_callback_ = callback;
+  } else {
+    socket_->EndLoggingMultipleConnectAttempts(rv);
+  }
+
+  return rv;
+}
+
+int TCPClientSocket::DoConnectLoop(int result) {
+  DCHECK_NE(next_connect_state_, CONNECT_STATE_NONE);
+
+  int rv = result;
+  do {
+    ConnectState state = next_connect_state_;
+    next_connect_state_ = CONNECT_STATE_NONE;
+    switch (state) {
+      case CONNECT_STATE_CONNECT:
+        DCHECK_EQ(OK, rv);
+        rv = DoConnect();
+        break;
+      case CONNECT_STATE_CONNECT_COMPLETE:
+        rv = DoConnectComplete(rv);
+        break;
+      default:
+        NOTREACHED() << "bad state " << state;
+        rv = ERR_UNEXPECTED;
+        break;
+    }
+  } while (rv != ERR_IO_PENDING && next_connect_state_ != CONNECT_STATE_NONE);
+
+  return rv;
+}
+
+int TCPClientSocket::DoConnect() {
+  DCHECK_GE(current_address_index_, 0);
+  DCHECK_LT(current_address_index_, static_cast<int>(addresses_.size()));
+
+  const IPEndPoint& endpoint = addresses_[current_address_index_];
+
+  if (previously_disconnected_) {
+    use_history_.Reset();
+    previously_disconnected_ = false;
+  }
+
+  next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE;
+
+  if (socket_->IsValid()) {
+    DCHECK(bind_address_);
+  } else {
+    int result = OpenSocket(endpoint.GetFamily());
+    if (result != OK)
+      return result;
+
+    if (bind_address_) {
+      result = socket_->Bind(*bind_address_);
+      if (result != OK) {
+        socket_->Close();
+        return result;
+      }
+    }
+  }
+
+  // |socket_| is owned by this class and the callback won't be run once
+  // |socket_| is gone. Therefore, it is safe to use base::Unretained() here.
+  return socket_->Connect(endpoint,
+                          base::Bind(&TCPClientSocket::DidCompleteConnect,
+                                     base::Unretained(this)));
+}
+
+int TCPClientSocket::DoConnectComplete(int result) {
+  if (result == OK) {
+    use_history_.set_was_ever_connected();
+    return OK;  // Done!
+  }
+
+  // Close whatever partially connected socket we currently have.
+  DoDisconnect();
+
+  // Try to fall back to the next address in the list.
+  if (current_address_index_ + 1 < static_cast<int>(addresses_.size())) {
+    next_connect_state_ = CONNECT_STATE_CONNECT;
+    ++current_address_index_;
+    return OK;
+  }
+
+  // Otherwise there is nothing to fall back to, so give up.
+  return result;
+}
+
+void TCPClientSocket::Disconnect() {
+  DoDisconnect();
+  current_address_index_ = -1;
+  bind_address_.reset();
+}
+
+void TCPClientSocket::DoDisconnect() {
+  // If connecting or already connected, record that the socket has been
+  // disconnected.
+  previously_disconnected_ = socket_->IsValid() && current_address_index_ >= 0;
+  socket_->Close();
+}
+
+bool TCPClientSocket::IsConnected() const {
+  return socket_->IsConnected();
+}
+
+bool TCPClientSocket::IsConnectedAndIdle() const {
+  return socket_->IsConnectedAndIdle();
+}
+
+int TCPClientSocket::GetPeerAddress(IPEndPoint* address) const {
+  return socket_->GetPeerAddress(address);
+}
+
+int TCPClientSocket::GetLocalAddress(IPEndPoint* address) const {
+  DCHECK(address);
+
+  if (!socket_->IsValid()) {
+    if (bind_address_) {
+      *address = *bind_address_;
+      return OK;
+    }
+    return ERR_SOCKET_NOT_CONNECTED;
+  }
+
+  return socket_->GetLocalAddress(address);
+}
+
+const BoundNetLog& TCPClientSocket::NetLog() const {
+  return socket_->net_log();
+}
+
+void TCPClientSocket::SetSubresourceSpeculation() {
+  use_history_.set_subresource_speculation();
+}
+
+void TCPClientSocket::SetOmniboxSpeculation() {
+  use_history_.set_omnibox_speculation();
+}
+
+bool TCPClientSocket::WasEverUsed() const {
+  return use_history_.was_used_to_convey_data();
+}
+
+bool TCPClientSocket::UsingTCPFastOpen() const {
+  return socket_->UsingTCPFastOpen();
+}
+
+bool TCPClientSocket::WasNpnNegotiated() const {
+  return false;
+}
+
+NextProto TCPClientSocket::GetNegotiatedProtocol() const {
+  return kProtoUnknown;
+}
+
+bool TCPClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
+  return false;
+}
+
+int TCPClientSocket::Read(IOBuffer* buf,
+                          int buf_len,
+                          const CompletionCallback& callback) {
+  DCHECK(!callback.is_null());
+
+  // |socket_| is owned by this class and the callback won't be run once
+  // |socket_| is gone. Therefore, it is safe to use base::Unretained() here.
+  CompletionCallback read_callback = base::Bind(
+      &TCPClientSocket::DidCompleteReadWrite, base::Unretained(this), callback);
+  int result = socket_->Read(buf, buf_len, read_callback);
+  if (result > 0)
+    use_history_.set_was_used_to_convey_data();
+
+  return result;
+}
+
+int TCPClientSocket::Write(IOBuffer* buf,
+                           int buf_len,
+                           const CompletionCallback& callback) {
+  DCHECK(!callback.is_null());
+
+  // |socket_| is owned by this class and the callback won't be run once
+  // |socket_| is gone. Therefore, it is safe to use base::Unretained() here.
+  CompletionCallback write_callback = base::Bind(
+      &TCPClientSocket::DidCompleteReadWrite, base::Unretained(this), callback);
+  int result = socket_->Write(buf, buf_len, write_callback);
+  if (result > 0)
+    use_history_.set_was_used_to_convey_data();
+
+  return result;
+}
+
+bool TCPClientSocket::SetReceiveBufferSize(int32 size) {
+  return socket_->SetReceiveBufferSize(size);
+}
+
+bool TCPClientSocket::SetSendBufferSize(int32 size) {
+    return socket_->SetSendBufferSize(size);
+}
+
+bool TCPClientSocket::SetKeepAlive(bool enable, int delay) {
+  return socket_->SetKeepAlive(enable, delay);
+}
+
+bool TCPClientSocket::SetNoDelay(bool no_delay) {
+  return socket_->SetNoDelay(no_delay);
+}
+
+void TCPClientSocket::DidCompleteConnect(int result) {
+  DCHECK_EQ(next_connect_state_, CONNECT_STATE_CONNECT_COMPLETE);
+  DCHECK_NE(result, ERR_IO_PENDING);
+  DCHECK(!connect_callback_.is_null());
+
+  result = DoConnectLoop(result);
+  if (result != ERR_IO_PENDING) {
+    socket_->EndLoggingMultipleConnectAttempts(result);
+    base::ResetAndReturn(&connect_callback_).Run(result);
+  }
+}
+
+void TCPClientSocket::DidCompleteReadWrite(const CompletionCallback& callback,
+                                           int result) {
+  if (result > 0)
+    use_history_.set_was_used_to_convey_data();
+
+  callback.Run(result);
+}
+
+int TCPClientSocket::OpenSocket(AddressFamily family) {
+  DCHECK(!socket_->IsValid());
+
+  int result = socket_->Open(family);
+  if (result != OK)
+    return result;
+
+  socket_->SetDefaultOptionsForClient();
+
+  return OK;
+}
+
+#endif
+
 }  // namespace net
diff --git a/net/socket/tcp_client_socket.h b/net/socket/tcp_client_socket.h
index 8a2c0cd73f06f..841bc81b7f31c 100644
--- a/net/socket/tcp_client_socket.h
+++ b/net/socket/tcp_client_socket.h
@@ -8,21 +8,27 @@
 #include "build/build_config.h"
 #include "net/base/net_export.h"
 
-#if defined(OS_WIN)
-#include "net/socket/tcp_client_socket_win.h"
-#elif defined(OS_POSIX)
+// TODO(yzshen): Switch OS_POSIX to use the same platform-independent
+// TCPClientSocket.
+#if defined(OS_POSIX)
+
 #include "net/socket/tcp_client_socket_libevent.h"
+
+#elif defined(OS_WIN)
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/base/address_list.h"
+#include "net/base/completion_callback.h"
+#include "net/base/net_log.h"
+#include "net/socket/stream_socket.h"
+#include "net/socket/tcp_socket.h"
+
 #endif
 
 namespace net {
 
-// A client socket that uses TCP as the transport layer.
-#if defined(OS_WIN)
-typedef TCPClientSocketWin TCPClientSocket;
-#elif defined(OS_POSIX)
-typedef TCPClientSocketLibevent TCPClientSocket;
-#endif
-
 // Enable/disable experimental TCP FastOpen option.
 // Not thread safe.  Must be called during initialization/startup only.
 NET_EXPORT void SetTCPFastOpenEnabled(bool value);
@@ -30,6 +36,111 @@ NET_EXPORT void SetTCPFastOpenEnabled(bool value);
 // Check if the TCP FastOpen option is enabled.
 bool IsTCPFastOpenEnabled();
 
+// A client socket that uses TCP as the transport layer.
+#if defined(OS_POSIX)
+typedef TCPClientSocketLibevent TCPClientSocket;
+#elif defined(OS_WIN)
+
+class NET_EXPORT TCPClientSocket : public StreamSocket {
+ public:
+  // The IP address(es) and port number to connect to.  The TCP socket will try
+  // each IP address in the list until it succeeds in establishing a
+  // connection.
+  TCPClientSocket(const AddressList& addresses,
+                  net::NetLog* net_log,
+                  const net::NetLog::Source& source);
+
+  // Adopts the given, connected socket and then acts as if Connect() had been
+  // called. This function is used by TCPServerSocket and for testing.
+  TCPClientSocket(scoped_ptr<TCPSocket> connected_socket,
+                  const IPEndPoint& peer_address);
+
+  virtual ~TCPClientSocket();
+
+  // Binds the socket to a local IP address and port.
+  int Bind(const IPEndPoint& address);
+
+  // StreamSocket implementation.
+  virtual int Connect(const CompletionCallback& callback) OVERRIDE;
+  virtual void Disconnect() OVERRIDE;
+  virtual bool IsConnected() const OVERRIDE;
+  virtual bool IsConnectedAndIdle() const OVERRIDE;
+  virtual int GetPeerAddress(IPEndPoint* address) const OVERRIDE;
+  virtual int GetLocalAddress(IPEndPoint* address) const OVERRIDE;
+  virtual const BoundNetLog& NetLog() const OVERRIDE;
+  virtual void SetSubresourceSpeculation() OVERRIDE;
+  virtual void SetOmniboxSpeculation() OVERRIDE;
+  virtual bool WasEverUsed() const OVERRIDE;
+  virtual bool UsingTCPFastOpen() const OVERRIDE;
+  virtual bool WasNpnNegotiated() const OVERRIDE;
+  virtual NextProto GetNegotiatedProtocol() const OVERRIDE;
+  virtual bool GetSSLInfo(SSLInfo* ssl_info) OVERRIDE;
+
+  // Socket implementation.
+  // Multiple outstanding requests are not supported.
+  // Full duplex mode (reading and writing at the same time) is supported.
+  virtual int Read(IOBuffer* buf, int buf_len,
+                   const CompletionCallback& callback) OVERRIDE;
+  virtual int Write(IOBuffer* buf, int buf_len,
+                    const CompletionCallback& callback) OVERRIDE;
+  virtual bool SetReceiveBufferSize(int32 size) OVERRIDE;
+  virtual bool SetSendBufferSize(int32 size) OVERRIDE;
+
+  virtual bool SetKeepAlive(bool enable, int delay);
+  virtual bool SetNoDelay(bool no_delay);
+
+ private:
+  // State machine for connecting the socket.
+  enum ConnectState {
+    CONNECT_STATE_CONNECT,
+    CONNECT_STATE_CONNECT_COMPLETE,
+    CONNECT_STATE_NONE,
+  };
+
+  // State machine used by Connect().
+  int DoConnectLoop(int result);
+  int DoConnect();
+  int DoConnectComplete(int result);
+
+  // Helper used by Disconnect(), which disconnects minus resetting
+  // current_address_index_ and bind_address_.
+  void DoDisconnect();
+
+  void DidCompleteConnect(int result);
+  void DidCompleteReadWrite(const CompletionCallback& callback, int result);
+
+  int OpenSocket(AddressFamily family);
+
+  scoped_ptr<TCPSocket> socket_;
+
+  // Local IP address and port we are bound to. Set to NULL if Bind()
+  // wasn't called (in that case OS chooses address/port).
+  scoped_ptr<IPEndPoint> bind_address_;
+
+  // The list of addresses we should try in order to establish a connection.
+  AddressList addresses_;
+
+  // Where we are in above list. Set to -1 if uninitialized.
+  int current_address_index_;
+
+  // External callback; called when connect is complete.
+  CompletionCallback connect_callback_;
+
+  // The next state for the Connect() state machine.
+  ConnectState next_connect_state_;
+
+  // This socket was previously disconnected and has not been re-connected.
+  bool previously_disconnected_;
+
+  // Record of connectivity and transmissions, for use in speculative connection
+  // histograms.
+  UseHistory use_history_;
+
+  DISALLOW_COPY_AND_ASSIGN(TCPClientSocket);
+};
+
+#endif
+
 }  // namespace net
 
 #endif  // NET_SOCKET_TCP_CLIENT_SOCKET_H_
diff --git a/net/socket/tcp_client_socket_win.cc b/net/socket/tcp_client_socket_win.cc
deleted file mode 100644
index f1334e78a468b..0000000000000
--- a/net/socket/tcp_client_socket_win.cc
+++ /dev/null
@@ -1,956 +0,0 @@
-// Copyright (c) 2012 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/socket/tcp_client_socket_win.h"
-
-#include <mstcpip.h>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/metrics/stats_counters.h"
-#include "base/strings/string_util.h"
-#include "base/win/object_watcher.h"
-#include "base/win/windows_version.h"
-#include "net/base/connection_type_histograms.h"
-#include "net/base/io_buffer.h"
-#include "net/base/ip_endpoint.h"
-#include "net/base/net_errors.h"
-#include "net/base/net_log.h"
-#include "net/base/net_util.h"
-#include "net/base/network_change_notifier.h"
-#include "net/base/winsock_init.h"
-#include "net/base/winsock_util.h"
-#include "net/socket/socket_descriptor.h"
-#include "net/socket/socket_net_log_params.h"
-
-namespace net {
-
-namespace {
-
-const int kTCPKeepAliveSeconds = 45;
-bool g_disable_overlapped_reads = false;
-
-bool SetSocketReceiveBufferSize(SOCKET socket, int32 size) {
-  int rv = setsockopt(socket, SOL_SOCKET, SO_RCVBUF,
-                      reinterpret_cast<const char*>(&size), sizeof(size));
-  DCHECK(!rv) << "Could not set socket receive buffer size: " << GetLastError();
-  return rv == 0;
-}
-
-bool SetSocketSendBufferSize(SOCKET socket, int32 size) {
-  int rv = setsockopt(socket, SOL_SOCKET, SO_SNDBUF,
-                      reinterpret_cast<const char*>(&size), sizeof(size));
-  DCHECK(!rv) << "Could not set socket send buffer size: " << GetLastError();
-  return rv == 0;
-}
-
-// Disable Nagle.
-// The Nagle implementation on windows is governed by RFC 896.  The idea
-// behind Nagle is to reduce small packets on the network.  When Nagle is
-// enabled, if a partial packet has been sent, the TCP stack will disallow
-// further *partial* packets until an ACK has been received from the other
-// side.  Good applications should always strive to send as much data as
-// possible and avoid partial-packet sends.  However, in most real world
-// applications, there are edge cases where this does not happen, and two
-// partial packets may be sent back to back.  For a browser, it is NEVER
-// a benefit to delay for an RTT before the second packet is sent.
-//
-// As a practical example in Chromium today, consider the case of a small
-// POST.  I have verified this:
-//     Client writes 649 bytes of header  (partial packet #1)
-//     Client writes 50 bytes of POST data (partial packet #2)
-// In the above example, with Nagle, a RTT delay is inserted between these
-// two sends due to nagle.  RTTs can easily be 100ms or more.  The best
-// fix is to make sure that for POSTing data, we write as much data as
-// possible and minimize partial packets.  We will fix that.  But disabling
-// Nagle also ensure we don't run into this delay in other edge cases.
-// See also:
-//    http://technet.microsoft.com/en-us/library/bb726981.aspx
-bool DisableNagle(SOCKET socket, bool disable) {
-  BOOL val = disable ? TRUE : FALSE;
-  int rv = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY,
-                      reinterpret_cast<const char*>(&val),
-                      sizeof(val));
-  DCHECK(!rv) << "Could not disable nagle";
-  return rv == 0;
-}
-
-// Enable TCP Keep-Alive to prevent NAT routers from timing out TCP
-// connections. See http://crbug.com/27400 for details.
-bool SetTCPKeepAlive(SOCKET socket, BOOL enable, int delay_secs) {
-  int delay = delay_secs * 1000;
-  struct tcp_keepalive keepalive_vals = {
-    enable ? 1 : 0,  // TCP keep-alive on.
-    delay,  // Delay seconds before sending first TCP keep-alive packet.
-    delay,  // Delay seconds between sending TCP keep-alive packets.
-  };
-  DWORD bytes_returned = 0xABAB;
-  int rv = WSAIoctl(socket, SIO_KEEPALIVE_VALS, &keepalive_vals,
-                sizeof(keepalive_vals), NULL, 0,
-                &bytes_returned, NULL, NULL);
-  DCHECK(!rv) << "Could not enable TCP Keep-Alive for socket: " << socket
-              << " [error: " << WSAGetLastError() << "].";
-
-  // Disregard any failure in disabling nagle or enabling TCP Keep-Alive.
-  return rv == 0;
-}
-
-// Sets socket parameters. Returns the OS error code (or 0 on
-// success).
-int SetupSocket(SOCKET socket) {
-  // Increase the socket buffer sizes from the default sizes for WinXP.  In
-  // performance testing, there is substantial benefit by increasing from 8KB
-  // to 64KB.
-  // See also:
-  //    http://support.microsoft.com/kb/823764/EN-US
-  // On Vista, if we manually set these sizes, Vista turns off its receive
-  // window auto-tuning feature.
-  //    http://blogs.msdn.com/wndp/archive/2006/05/05/Winhec-blog-tcpip-2.aspx
-  // Since Vista's auto-tune is better than any static value we can could set,
-  // only change these on pre-vista machines.
-  if (base::win::GetVersion() < base::win::VERSION_VISTA) {
-    const int32 kSocketBufferSize = 64 * 1024;
-    SetSocketReceiveBufferSize(socket, kSocketBufferSize);
-    SetSocketSendBufferSize(socket, kSocketBufferSize);
-  }
-
-  DisableNagle(socket, true);
-  SetTCPKeepAlive(socket, true, kTCPKeepAliveSeconds);
-  return 0;
-}
-
-// Creates a new socket and sets default parameters for it. Returns
-// the OS error code (or 0 on success).
-int CreateSocket(int family, SOCKET* socket) {
-  *socket = CreatePlatformSocket(family, SOCK_STREAM, IPPROTO_TCP);
-  if (*socket == INVALID_SOCKET) {
-    int os_error = WSAGetLastError();
-    LOG(ERROR) << "CreatePlatformSocket failed: " << os_error;
-    return os_error;
-  }
-  int error = SetupSocket(*socket);
-  if (error) {
-    if (closesocket(*socket) < 0)
-      PLOG(ERROR) << "closesocket";
-    *socket = INVALID_SOCKET;
-    return error;
-  }
-  return 0;
-}
-
-int MapConnectError(int os_error) {
-  switch (os_error) {
-    // connect fails with WSAEACCES when Windows Firewall blocks the
-    // connection.
-    case WSAEACCES:
-      return ERR_NETWORK_ACCESS_DENIED;
-    case WSAETIMEDOUT:
-      return ERR_CONNECTION_TIMED_OUT;
-    default: {
-      int net_error = MapSystemError(os_error);
-      if (net_error == ERR_FAILED)
-        return ERR_CONNECTION_FAILED;  // More specific than ERR_FAILED.
-
-      // Give a more specific error when the user is offline.
-      if (net_error == ERR_ADDRESS_UNREACHABLE &&
-          NetworkChangeNotifier::IsOffline()) {
-        return ERR_INTERNET_DISCONNECTED;
-      }
-
-      return net_error;
-    }
-  }
-}
-
-}  // namespace
-
-//-----------------------------------------------------------------------------
-
-// This class encapsulates all the state that has to be preserved as long as
-// there is a network IO operation in progress. If the owner TCPClientSocketWin
-// is destroyed while an operation is in progress, the Core is detached and it
-// lives until the operation completes and the OS doesn't reference any resource
-// declared on this class anymore.
-class TCPClientSocketWin::Core : public base::RefCounted<Core> {
- public:
-  explicit Core(TCPClientSocketWin* socket);
-
-  // Start watching for the end of a read or write operation.
-  void WatchForRead();
-  void WatchForWrite();
-
-  // The TCPClientSocketWin is going away.
-  void Detach() { socket_ = NULL; }
-
-  // The separate OVERLAPPED variables for asynchronous operation.
-  // |read_overlapped_| is used for both Connect() and Read().
-  // |write_overlapped_| is only used for Write();
-  OVERLAPPED read_overlapped_;
-  OVERLAPPED write_overlapped_;
-
-  // The buffers used in Read() and Write().
-  scoped_refptr<IOBuffer> read_iobuffer_;
-  scoped_refptr<IOBuffer> write_iobuffer_;
-  int read_buffer_length_;
-  int write_buffer_length_;
-
-  bool non_blocking_reads_initialized_;
-
- private:
-  friend class base::RefCounted<Core>;
-
-  class ReadDelegate : public base::win::ObjectWatcher::Delegate {
-   public:
-    explicit ReadDelegate(Core* core) : core_(core) {}
-    virtual ~ReadDelegate() {}
-
-    // base::ObjectWatcher::Delegate methods:
-    virtual void OnObjectSignaled(HANDLE object);
-
-   private:
-    Core* const core_;
-  };
-
-  class WriteDelegate : public base::win::ObjectWatcher::Delegate {
-   public:
-    explicit WriteDelegate(Core* core) : core_(core) {}
-    virtual ~WriteDelegate() {}
-
-    // base::ObjectWatcher::Delegate methods:
-    virtual void OnObjectSignaled(HANDLE object);
-
-   private:
-    Core* const core_;
-  };
-
-  ~Core();
-
-  // The socket that created this object.
-  TCPClientSocketWin* socket_;
-
-  // |reader_| handles the signals from |read_watcher_|.
-  ReadDelegate reader_;
-  // |writer_| handles the signals from |write_watcher_|.
-  WriteDelegate writer_;
-
-  // |read_watcher_| watches for events from Connect() and Read().
-  base::win::ObjectWatcher read_watcher_;
-  // |write_watcher_| watches for events from Write();
-  base::win::ObjectWatcher write_watcher_;
-
-  DISALLOW_COPY_AND_ASSIGN(Core);
-};
-
-TCPClientSocketWin::Core::Core(
-    TCPClientSocketWin* socket)
-    : read_buffer_length_(0),
-      write_buffer_length_(0),
-      non_blocking_reads_initialized_(false),
-      socket_(socket),
-      reader_(this),
-      writer_(this) {
-  memset(&read_overlapped_, 0, sizeof(read_overlapped_));
-  memset(&write_overlapped_, 0, sizeof(write_overlapped_));
-
-  read_overlapped_.hEvent = WSACreateEvent();
-  write_overlapped_.hEvent = WSACreateEvent();
-}
-
-TCPClientSocketWin::Core::~Core() {
-  // Make sure the message loop is not watching this object anymore.
-  read_watcher_.StopWatching();
-  write_watcher_.StopWatching();
-
-  WSACloseEvent(read_overlapped_.hEvent);
-  memset(&read_overlapped_, 0xaf, sizeof(read_overlapped_));
-  WSACloseEvent(write_overlapped_.hEvent);
-  memset(&write_overlapped_, 0xaf, sizeof(write_overlapped_));
-}
-
-void TCPClientSocketWin::Core::WatchForRead() {
-  // We grab an extra reference because there is an IO operation in progress.
-  // Balanced in ReadDelegate::OnObjectSignaled().
-  AddRef();
-  read_watcher_.StartWatching(read_overlapped_.hEvent, &reader_);
-}
-
-void TCPClientSocketWin::Core::WatchForWrite() {
-  // We grab an extra reference because there is an IO operation in progress.
-  // Balanced in WriteDelegate::OnObjectSignaled().
-  AddRef();
-  write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_);
-}
-
-void TCPClientSocketWin::Core::ReadDelegate::OnObjectSignaled(
-    HANDLE object) {
-  DCHECK_EQ(object, core_->read_overlapped_.hEvent);
-  if (core_->socket_) {
-    if (core_->socket_->waiting_connect())
-      core_->socket_->DidCompleteConnect();
-    else
-      core_->socket_->DidSignalRead();
-  }
-
-  core_->Release();
-}
-
-void TCPClientSocketWin::Core::WriteDelegate::OnObjectSignaled(
-    HANDLE object) {
-  DCHECK_EQ(object, core_->write_overlapped_.hEvent);
-  if (core_->socket_)
-    core_->socket_->DidCompleteWrite();
-
-  core_->Release();
-}
-
-//-----------------------------------------------------------------------------
-
-TCPClientSocketWin::TCPClientSocketWin(const AddressList& addresses,
-                                       net::NetLog* net_log,
-                                       const net::NetLog::Source& source)
-    : socket_(INVALID_SOCKET),
-      bound_socket_(INVALID_SOCKET),
-      addresses_(addresses),
-      current_address_index_(-1),
-      waiting_read_(false),
-      waiting_write_(false),
-      next_connect_state_(CONNECT_STATE_NONE),
-      connect_os_error_(0),
-      net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)),
-      previously_disconnected_(false) {
-  net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE,
-                      source.ToEventParametersCallback());
-  EnsureWinsockInit();
-}
-
-TCPClientSocketWin::~TCPClientSocketWin() {
-  Disconnect();
-  net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
-}
-
-int TCPClientSocketWin::AdoptSocket(SOCKET socket) {
-  DCHECK_EQ(socket_, INVALID_SOCKET);
-
-  int error = SetupSocket(socket);
-  if (error)
-    return MapSystemError(error);
-
-  socket_ = socket;
-  SetNonBlocking(socket_);
-
-  core_ = new Core(this);
-  current_address_index_ = 0;
-  use_history_.set_was_ever_connected();
-
-  return OK;
-}
-
-int TCPClientSocketWin::Bind(const IPEndPoint& address) {
-  if (current_address_index_ >= 0 || bind_address_.get()) {
-    // Cannot bind the socket if we are already connected or connecting.
-    return ERR_UNEXPECTED;
-  }
-
-  SockaddrStorage storage;
-  if (!address.ToSockAddr(storage.addr, &storage.addr_len))
-    return ERR_INVALID_ARGUMENT;
-
-  // Create |bound_socket_| and try to bind it to |address|.
-  int error = CreateSocket(address.GetSockAddrFamily(), &bound_socket_);
-  if (error)
-    return MapSystemError(error);
-
-  if (bind(bound_socket_, storage.addr, storage.addr_len)) {
-    error = errno;
-    if (closesocket(bound_socket_) < 0)
-      PLOG(ERROR) << "closesocket";
-    bound_socket_ = INVALID_SOCKET;
-    return MapSystemError(error);
-  }
-
-  bind_address_.reset(new IPEndPoint(address));
-
-  return 0;
-}
-
-
-int TCPClientSocketWin::Connect(const CompletionCallback& callback) {
-  DCHECK(CalledOnValidThread());
-
-  // If already connected, then just return OK.
-  if (socket_ != INVALID_SOCKET)
-    return OK;
-
-  base::StatsCounter connects("tcp.connect");
-  connects.Increment();
-
-  net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT,
-                      addresses_.CreateNetLogCallback());
-
-  // We will try to connect to each address in addresses_. Start with the
-  // first one in the list.
-  next_connect_state_ = CONNECT_STATE_CONNECT;
-  current_address_index_ = 0;
-
-  int rv = DoConnectLoop(OK);
-  if (rv == ERR_IO_PENDING) {
-    // Synchronous operation not supported.
-    DCHECK(!callback.is_null());
-    // TODO(ajwong): Is setting read_callback_ the right thing to do here??
-    read_callback_ = callback;
-  } else {
-    LogConnectCompletion(rv);
-  }
-
-  return rv;
-}
-
-int TCPClientSocketWin::DoConnectLoop(int result) {
-  DCHECK_NE(next_connect_state_, CONNECT_STATE_NONE);
-
-  int rv = result;
-  do {
-    ConnectState state = next_connect_state_;
-    next_connect_state_ = CONNECT_STATE_NONE;
-    switch (state) {
-      case CONNECT_STATE_CONNECT:
-        DCHECK_EQ(OK, rv);
-        rv = DoConnect();
-        break;
-      case CONNECT_STATE_CONNECT_COMPLETE:
-        rv = DoConnectComplete(rv);
-        break;
-      default:
-        LOG(DFATAL) << "bad state " << state;
-        rv = ERR_UNEXPECTED;
-        break;
-    }
-  } while (rv != ERR_IO_PENDING && next_connect_state_ != CONNECT_STATE_NONE);
-
-  return rv;
-}
-
-int TCPClientSocketWin::DoConnect() {
-  DCHECK_GE(current_address_index_, 0);
-  DCHECK_LT(current_address_index_, static_cast<int>(addresses_.size()));
-  DCHECK_EQ(0, connect_os_error_);
-
-  const IPEndPoint& endpoint = addresses_[current_address_index_];
-
-  if (previously_disconnected_) {
-    use_history_.Reset();
-    previously_disconnected_ = false;
-  }
-
-  net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT,
-                      CreateNetLogIPEndPointCallback(&endpoint));
-
-  next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE;
-
-  if (bound_socket_ != INVALID_SOCKET) {
-    DCHECK(bind_address_.get());
-    socket_ = bound_socket_;
-    bound_socket_ = INVALID_SOCKET;
-  } else {
-    connect_os_error_ = CreateSocket(endpoint.GetSockAddrFamily(), &socket_);
-    if (connect_os_error_ != 0)
-      return MapSystemError(connect_os_error_);
-
-    if (bind_address_.get()) {
-      SockaddrStorage storage;
-      if (!bind_address_->ToSockAddr(storage.addr, &storage.addr_len))
-        return ERR_INVALID_ARGUMENT;
-      if (bind(socket_, storage.addr, storage.addr_len))
-        return MapSystemError(errno);
-    }
-  }
-
-  DCHECK(!core_);
-  core_ = new Core(this);
-  // WSAEventSelect sets the socket to non-blocking mode as a side effect.
-  // Our connect() and recv() calls require that the socket be non-blocking.
-  WSAEventSelect(socket_, core_->read_overlapped_.hEvent, FD_CONNECT);
-
-  SockaddrStorage storage;
-  if (!endpoint.ToSockAddr(storage.addr, &storage.addr_len))
-    return ERR_INVALID_ARGUMENT;
-  if (!connect(socket_, storage.addr, storage.addr_len)) {
-    // Connected without waiting!
-    //
-    // The MSDN page for connect says:
-    //   With a nonblocking socket, the connection attempt cannot be completed
-    //   immediately. In this case, connect will return SOCKET_ERROR, and
-    //   WSAGetLastError will return WSAEWOULDBLOCK.
-    // which implies that for a nonblocking socket, connect never returns 0.
-    // It's not documented whether the event object will be signaled or not
-    // if connect does return 0.  So the code below is essentially dead code
-    // and we don't know if it's correct.
-    NOTREACHED();
-
-    if (ResetEventIfSignaled(core_->read_overlapped_.hEvent))
-      return OK;
-  } else {
-    int os_error = WSAGetLastError();
-    if (os_error != WSAEWOULDBLOCK) {
-      LOG(ERROR) << "connect failed: " << os_error;
-      connect_os_error_ = os_error;
-      return MapConnectError(os_error);
-    }
-  }
-
-  core_->WatchForRead();
-  return ERR_IO_PENDING;
-}
-
-int TCPClientSocketWin::DoConnectComplete(int result) {
-  // Log the end of this attempt (and any OS error it threw).
-  int os_error = connect_os_error_;
-  connect_os_error_ = 0;
-  if (result != OK) {
-    net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT,
-                      NetLog::IntegerCallback("os_error", os_error));
-  } else {
-    net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT);
-  }
-
-  if (result == OK) {
-    use_history_.set_was_ever_connected();
-    return OK;  // Done!
-  }
-
-  // Close whatever partially connected socket we currently have.
-  DoDisconnect();
-
-  // Try to fall back to the next address in the list.
-  if (current_address_index_ + 1 < static_cast<int>(addresses_.size())) {
-    next_connect_state_ = CONNECT_STATE_CONNECT;
-    ++current_address_index_;
-    return OK;
-  }
-
-  // Otherwise there is nothing to fall back to, so give up.
-  return result;
-}
-
-void TCPClientSocketWin::Disconnect() {
-  DCHECK(CalledOnValidThread());
-
-  DoDisconnect();
-  current_address_index_ = -1;
-  bind_address_.reset();
-}
-
-void TCPClientSocketWin::DoDisconnect() {
-  DCHECK(CalledOnValidThread());
-
-  if (socket_ == INVALID_SOCKET)
-    return;
-
-  // Note: don't use CancelIo to cancel pending IO because it doesn't work
-  // when there is a Winsock layered service provider.
-
-  // In most socket implementations, closing a socket results in a graceful
-  // connection shutdown, but in Winsock we have to call shutdown explicitly.
-  // See the MSDN page "Graceful Shutdown, Linger Options, and Socket Closure"
-  // at http://msdn.microsoft.com/en-us/library/ms738547.aspx
-  shutdown(socket_, SD_SEND);
-
-  // This cancels any pending IO.
-  closesocket(socket_);
-  socket_ = INVALID_SOCKET;
-
-  if (waiting_connect()) {
-    // We closed the socket, so this notification will never come.
-    // From MSDN' WSAEventSelect documentation:
-    // "Closing a socket with closesocket also cancels the association and
-    // selection of network events specified in WSAEventSelect for the socket".
-    core_->Release();
-  }
-
-  waiting_read_ = false;
-  waiting_write_ = false;
-
-  core_->Detach();
-  core_ = NULL;
-
-  previously_disconnected_ = true;
-}
-
-bool TCPClientSocketWin::IsConnected() const {
-  DCHECK(CalledOnValidThread());
-
-  if (socket_ == INVALID_SOCKET || waiting_connect())
-    return false;
-
-  if (waiting_read_)
-    return true;
-
-  // Check if connection is alive.
-  char c;
-  int rv = recv(socket_, &c, 1, MSG_PEEK);
-  if (rv == 0)
-    return false;
-  if (rv == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
-    return false;
-
-  return true;
-}
-
-bool TCPClientSocketWin::IsConnectedAndIdle() const {
-  DCHECK(CalledOnValidThread());
-
-  if (socket_ == INVALID_SOCKET || waiting_connect())
-    return false;
-
-  if (waiting_read_)
-    return true;
-
-  // Check if connection is alive and we haven't received any data
-  // unexpectedly.
-  char c;
-  int rv = recv(socket_, &c, 1, MSG_PEEK);
-  if (rv >= 0)
-    return false;
-  if (WSAGetLastError() != WSAEWOULDBLOCK)
-    return false;
-
-  return true;
-}
-
-int TCPClientSocketWin::GetPeerAddress(IPEndPoint* address) const {
-  DCHECK(CalledOnValidThread());
-  DCHECK(address);
-  if (!IsConnected())
-    return ERR_SOCKET_NOT_CONNECTED;
-  *address = addresses_[current_address_index_];
-  return OK;
-}
-
-int TCPClientSocketWin::GetLocalAddress(IPEndPoint* address) const {
-  DCHECK(CalledOnValidThread());
-  DCHECK(address);
-  if (socket_ == INVALID_SOCKET) {
-    if (bind_address_.get()) {
-      *address = *bind_address_;
-      return OK;
-    }
-    return ERR_SOCKET_NOT_CONNECTED;
-  }
-
-  struct sockaddr_storage addr_storage;
-  socklen_t addr_len = sizeof(addr_storage);
-  struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
-  if (getsockname(socket_, addr, &addr_len))
-    return MapSystemError(WSAGetLastError());
-  if (!address->FromSockAddr(addr, addr_len))
-    return ERR_FAILED;
-  return OK;
-}
-
-void TCPClientSocketWin::SetSubresourceSpeculation() {
-  use_history_.set_subresource_speculation();
-}
-
-void TCPClientSocketWin::SetOmniboxSpeculation() {
-  use_history_.set_omnibox_speculation();
-}
-
-bool TCPClientSocketWin::WasEverUsed() const {
-  return use_history_.was_used_to_convey_data();
-}
-
-bool TCPClientSocketWin::UsingTCPFastOpen() const {
-  // Not supported on windows.
-  return false;
-}
-
-bool TCPClientSocketWin::WasNpnNegotiated() const {
-  return false;
-}
-
-NextProto TCPClientSocketWin::GetNegotiatedProtocol() const {
-  return kProtoUnknown;
-}
-
-bool TCPClientSocketWin::GetSSLInfo(SSLInfo* ssl_info) {
-  return false;
-}
-
-int TCPClientSocketWin::Read(IOBuffer* buf,
-                             int buf_len,
-                             const CompletionCallback& callback) {
-  DCHECK(CalledOnValidThread());
-  DCHECK_NE(socket_, INVALID_SOCKET);
-  DCHECK(!waiting_read_);
-  DCHECK(read_callback_.is_null());
-  DCHECK(!core_->read_iobuffer_);
-
-  return DoRead(buf, buf_len, callback);
-}
-
-int TCPClientSocketWin::Write(IOBuffer* buf,
-                              int buf_len,
-                              const CompletionCallback& callback) {
-  DCHECK(CalledOnValidThread());
-  DCHECK_NE(socket_, INVALID_SOCKET);
-  DCHECK(!waiting_write_);
-  DCHECK(write_callback_.is_null());
-  DCHECK_GT(buf_len, 0);
-  DCHECK(!core_->write_iobuffer_);
-
-  base::StatsCounter writes("tcp.writes");
-  writes.Increment();
-
-  WSABUF write_buffer;
-  write_buffer.len = buf_len;
-  write_buffer.buf = buf->data();
-
-  // TODO(wtc): Remove the assertion after enough testing.
-  AssertEventNotSignaled(core_->write_overlapped_.hEvent);
-  DWORD num;
-  int rv = WSASend(socket_, &write_buffer, 1, &num, 0,
-                   &core_->write_overlapped_, NULL);
-  if (rv == 0) {
-    if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) {
-      rv = static_cast<int>(num);
-      if (rv > buf_len || rv < 0) {
-        // It seems that some winsock interceptors report that more was written
-        // than was available. Treat this as an error.  http://crbug.com/27870
-        LOG(ERROR) << "Detected broken LSP: Asked to write " << buf_len
-                   << " bytes, but " << rv << " bytes reported.";
-        return ERR_WINSOCK_UNEXPECTED_WRITTEN_BYTES;
-      }
-      base::StatsCounter write_bytes("tcp.write_bytes");
-      write_bytes.Add(rv);
-      if (rv > 0)
-        use_history_.set_was_used_to_convey_data();
-      net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, rv,
-                                    buf->data());
-      return rv;
-    }
-  } else {
-    int os_error = WSAGetLastError();
-    if (os_error != WSA_IO_PENDING) {
-      int net_error = MapSystemError(os_error);
-      net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR,
-                        CreateNetLogSocketErrorCallback(net_error, os_error));
-      return net_error;
-    }
-  }
-  waiting_write_ = true;
-  write_callback_ = callback;
-  core_->write_iobuffer_ = buf;
-  core_->write_buffer_length_ = buf_len;
-  core_->WatchForWrite();
-  return ERR_IO_PENDING;
-}
-
-bool TCPClientSocketWin::SetReceiveBufferSize(int32 size) {
-  DCHECK(CalledOnValidThread());
-  return SetSocketReceiveBufferSize(socket_, size);
-}
-
-bool TCPClientSocketWin::SetSendBufferSize(int32 size) {
-  DCHECK(CalledOnValidThread());
-  return SetSocketSendBufferSize(socket_, size);
-}
-
-bool TCPClientSocketWin::SetKeepAlive(bool enable, int delay) {
-  return SetTCPKeepAlive(socket_, enable, delay);
-}
-
-bool TCPClientSocketWin::SetNoDelay(bool no_delay) {
-  return DisableNagle(socket_, no_delay);
-}
-
-void TCPClientSocketWin::LogConnectCompletion(int net_error) {
-  if (net_error == OK)
-    UpdateConnectionTypeHistograms(CONNECTION_ANY);
-
-  if (net_error != OK) {
-    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error);
-    return;
-  }
-
-  struct sockaddr_storage source_address;
-  socklen_t addrlen = sizeof(source_address);
-  int rv = getsockname(
-      socket_, reinterpret_cast<struct sockaddr*>(&source_address), &addrlen);
-  if (rv != 0) {
-    LOG(ERROR) << "getsockname() [rv: " << rv
-               << "] error: " << WSAGetLastError();
-    NOTREACHED();
-    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv);
-    return;
-  }
-
-  net_log_.EndEvent(
-      NetLog::TYPE_TCP_CONNECT,
-      CreateNetLogSourceAddressCallback(
-          reinterpret_cast<const struct sockaddr*>(&source_address),
-          sizeof(source_address)));
-}
-
-int TCPClientSocketWin::DoRead(IOBuffer* buf, int buf_len,
-                               const CompletionCallback& callback) {
-  if (!core_->non_blocking_reads_initialized_) {
-    WSAEventSelect(socket_, core_->read_overlapped_.hEvent,
-                   FD_READ | FD_CLOSE);
-    core_->non_blocking_reads_initialized_ = true;
-  }
-  int rv = recv(socket_, buf->data(), buf_len, 0);
-  if (rv == SOCKET_ERROR) {
-    int os_error = WSAGetLastError();
-    if (os_error != WSAEWOULDBLOCK) {
-      int net_error = MapSystemError(os_error);
-      net_log_.AddEvent(
-          NetLog::TYPE_SOCKET_READ_ERROR,
-          CreateNetLogSocketErrorCallback(net_error, os_error));
-      return net_error;
-    }
-  } else {
-    base::StatsCounter read_bytes("tcp.read_bytes");
-    if (rv > 0) {
-      use_history_.set_was_used_to_convey_data();
-      read_bytes.Add(rv);
-    }
-    net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, rv,
-                                  buf->data());
-    return rv;
-  }
-
-  waiting_read_ = true;
-  read_callback_ = callback;
-  core_->read_iobuffer_ = buf;
-  core_->read_buffer_length_ = buf_len;
-  core_->WatchForRead();
-  return ERR_IO_PENDING;
-}
-
-void TCPClientSocketWin::DoReadCallback(int rv) {
-  DCHECK_NE(rv, ERR_IO_PENDING);
-  DCHECK(!read_callback_.is_null());
-
-  // Since Run may result in Read being called, clear read_callback_ up front.
-  CompletionCallback c = read_callback_;
-  read_callback_.Reset();
-  c.Run(rv);
-}
-
-void TCPClientSocketWin::DoWriteCallback(int rv) {
-  DCHECK_NE(rv, ERR_IO_PENDING);
-  DCHECK(!write_callback_.is_null());
-
-  // Since Run may result in Write being called, clear write_callback_ up front.
-  CompletionCallback c = write_callback_;
-  write_callback_.Reset();
-  c.Run(rv);
-}
-
-void TCPClientSocketWin::DidCompleteConnect() {
-  DCHECK_EQ(next_connect_state_, CONNECT_STATE_CONNECT_COMPLETE);
-  int result;
-
-  WSANETWORKEVENTS events;
-  int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent,
-                                &events);
-  int os_error = 0;
-  if (rv == SOCKET_ERROR) {
-    NOTREACHED();
-    os_error = WSAGetLastError();
-    result = MapSystemError(os_error);
-  } else if (events.lNetworkEvents & FD_CONNECT) {
-    os_error = events.iErrorCode[FD_CONNECT_BIT];
-    result = MapConnectError(os_error);
-  } else {
-    NOTREACHED();
-    result = ERR_UNEXPECTED;
-  }
-
-  connect_os_error_ = os_error;
-  rv = DoConnectLoop(result);
-  if (rv != ERR_IO_PENDING) {
-    LogConnectCompletion(rv);
-    DoReadCallback(rv);
-  }
-}
-
-void TCPClientSocketWin::DidCompleteWrite() {
-  DCHECK(waiting_write_);
-
-  DWORD num_bytes, flags;
-  BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_,
-                                   &num_bytes, FALSE, &flags);
-  WSAResetEvent(core_->write_overlapped_.hEvent);
-  waiting_write_ = false;
-  int rv;
-  if (!ok) {
-    int os_error = WSAGetLastError();
-    rv = MapSystemError(os_error);
-    net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR,
-                      CreateNetLogSocketErrorCallback(rv, os_error));
-  } else {
-    rv = static_cast<int>(num_bytes);
-    if (rv > core_->write_buffer_length_ || rv < 0) {
-      // It seems that some winsock interceptors report that more was written
-      // than was available. Treat this as an error.  http://crbug.com/27870
-      LOG(ERROR) << "Detected broken LSP: Asked to write "
-                 << core_->write_buffer_length_ << " bytes, but " << rv
-                 << " bytes reported.";
-      rv = ERR_WINSOCK_UNEXPECTED_WRITTEN_BYTES;
-    } else {
-      base::StatsCounter write_bytes("tcp.write_bytes");
-      write_bytes.Add(num_bytes);
-      if (num_bytes > 0)
-        use_history_.set_was_used_to_convey_data();
-      net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, num_bytes,
-                                    core_->write_iobuffer_->data());
-    }
-  }
-  core_->write_iobuffer_ = NULL;
-  DoWriteCallback(rv);
-}
-
-void TCPClientSocketWin::DidSignalRead() {
-  DCHECK(waiting_read_);
-  int os_error = 0;
-  WSANETWORKEVENTS network_events;
-  int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent,
-                                &network_events);
-  if (rv == SOCKET_ERROR) {
-    os_error = WSAGetLastError();
-    rv = MapSystemError(os_error);
-  } else if (network_events.lNetworkEvents) {
-    DCHECK_EQ(network_events.lNetworkEvents & ~(FD_READ | FD_CLOSE), 0);
-    // If network_events.lNetworkEvents is FD_CLOSE and
-    // network_events.iErrorCode[FD_CLOSE_BIT] is 0, it is a graceful
-    // connection closure. It is tempting to directly set rv to 0 in
-    // this case, but the MSDN pages for WSAEventSelect and
-    // WSAAsyncSelect recommend we still call DoRead():
-    //   FD_CLOSE should only be posted after all data is read from a
-    //   socket, but an application should check for remaining data upon
-    //   receipt of FD_CLOSE to avoid any possibility of losing data.
-    //
-    // If network_events.iErrorCode[FD_READ_BIT] or
-    // network_events.iErrorCode[FD_CLOSE_BIT] is nonzero, still call
-    // DoRead() because recv() reports a more accurate error code
-    // (WSAECONNRESET vs. WSAECONNABORTED) when the connection was
-    // reset.
-    rv = DoRead(core_->read_iobuffer_, core_->read_buffer_length_,
-                read_callback_);
-    if (rv == ERR_IO_PENDING)
-      return;
-  } else {
-    // This may happen because Read() may succeed synchronously and
-    // consume all the received data without resetting the event object.
-    core_->WatchForRead();
-    return;
-  }
-  waiting_read_ = false;
-  core_->read_iobuffer_ = NULL;
-  core_->read_buffer_length_ = 0;
-  DoReadCallback(rv);
-}
-
-}  // namespace net
diff --git a/net/socket/tcp_client_socket_win.h b/net/socket/tcp_client_socket_win.h
deleted file mode 100644
index c899f27e70359..0000000000000
--- a/net/socket/tcp_client_socket_win.h
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright (c) 2012 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_SOCKET_TCP_CLIENT_SOCKET_WIN_H_
-#define NET_SOCKET_TCP_CLIENT_SOCKET_WIN_H_
-
-#include <winsock2.h>
-
-#include "base/memory/scoped_ptr.h"
-#include "base/threading/non_thread_safe.h"
-#include "net/base/address_list.h"
-#include "net/base/completion_callback.h"
-#include "net/base/net_log.h"
-#include "net/socket/stream_socket.h"
-
-namespace net {
-
-class BoundNetLog;
-
-class NET_EXPORT TCPClientSocketWin : public StreamSocket,
-                                      NON_EXPORTED_BASE(base::NonThreadSafe) {
- public:
-  // The IP address(es) and port number to connect to.  The TCP socket will try
-  // each IP address in the list until it succeeds in establishing a
-  // connection.
-  TCPClientSocketWin(const AddressList& addresses,
-                     net::NetLog* net_log,
-                     const net::NetLog::Source& source);
-
-  virtual ~TCPClientSocketWin();
-
-  // AdoptSocket causes the given, connected socket to be adopted as a TCP
-  // socket. This object must not be connected. This object takes ownership of
-  // the given socket and then acts as if Connect() had been called. This
-  // function is used by TCPServerSocket() to adopt accepted connections
-  // and for testing.
-  int AdoptSocket(SOCKET socket);
-
-  // Binds the socket to a local IP address and port.
-  int Bind(const IPEndPoint& address);
-
-  // StreamSocket implementation.
-  virtual int Connect(const CompletionCallback& callback);
-  virtual void Disconnect();
-  virtual bool IsConnected() const;
-  virtual bool IsConnectedAndIdle() const;
-  virtual int GetPeerAddress(IPEndPoint* address) const;
-  virtual int GetLocalAddress(IPEndPoint* address) const;
-  virtual const BoundNetLog& NetLog() const { return net_log_; }
-  virtual void SetSubresourceSpeculation();
-  virtual void SetOmniboxSpeculation();
-  virtual bool WasEverUsed() const;
-  virtual bool UsingTCPFastOpen() const;
-  virtual bool WasNpnNegotiated() const OVERRIDE;
-  virtual NextProto GetNegotiatedProtocol() const OVERRIDE;
-  virtual bool GetSSLInfo(SSLInfo* ssl_info) OVERRIDE;
-
-  // Socket implementation.
-  // Multiple outstanding requests are not supported.
-  // Full duplex mode (reading and writing at the same time) is supported
-  virtual int Read(IOBuffer* buf, int buf_len,
-                   const CompletionCallback& callback);
-  virtual int Write(IOBuffer* buf, int buf_len,
-                    const CompletionCallback& callback);
-
-  virtual bool SetReceiveBufferSize(int32 size);
-  virtual bool SetSendBufferSize(int32 size);
-
-  virtual bool SetKeepAlive(bool enable, int delay);
-  virtual bool SetNoDelay(bool no_delay);
-
- private:
-  // State machine for connecting the socket.
-  enum ConnectState {
-    CONNECT_STATE_CONNECT,
-    CONNECT_STATE_CONNECT_COMPLETE,
-    CONNECT_STATE_NONE,
-  };
-
-  class Core;
-
-  // State machine used by Connect().
-  int DoConnectLoop(int result);
-  int DoConnect();
-  int DoConnectComplete(int result);
-
-  // Helper used by Disconnect(), which disconnects minus the logging and
-  // resetting of current_address_index_.
-  void DoDisconnect();
-
-  // Returns true if a Connect() is in progress.
-  bool waiting_connect() const {
-    return next_connect_state_ != CONNECT_STATE_NONE;
-  }
-
-  // Called after Connect() has completed with |net_error|.
-  void LogConnectCompletion(int net_error);
-
-  int DoRead(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
-  void DoReadCallback(int rv);
-  void DoWriteCallback(int rv);
-  void DidCompleteConnect();
-  void DidCompleteWrite();
-  void DidSignalRead();
-
-  SOCKET socket_;
-
-  // Local IP address and port we are bound to. Set to NULL if Bind()
-  // was't called (in that cases OS chooses address/port).
-  scoped_ptr<IPEndPoint> bind_address_;
-
-  // Stores bound socket between Bind() and Connect() calls.
-  SOCKET bound_socket_;
-
-  // The list of addresses we should try in order to establish a connection.
-  AddressList addresses_;
-
-  // Where we are in above list. Set to -1 if uninitialized.
-  int current_address_index_;
-
-  // The various states that the socket could be in.
-  bool waiting_read_;
-  bool waiting_write_;
-
-  // The core of the socket that can live longer than the socket itself. We pass
-  // resources to the Windows async IO functions and we have to make sure that
-  // they are not destroyed while the OS still references them.
-  scoped_refptr<Core> core_;
-
-  // External callback; called when connect or read is complete.
-  CompletionCallback read_callback_;
-
-  // External callback; called when write is complete.
-  CompletionCallback write_callback_;
-
-  // The next state for the Connect() state machine.
-  ConnectState next_connect_state_;
-
-  // The OS error that CONNECT_STATE_CONNECT last completed with.
-  int connect_os_error_;
-
-  BoundNetLog net_log_;
-
-  // This socket was previously disconnected and has not been re-connected.
-  bool previously_disconnected_;
-
-  // Record of connectivity and transmissions, for use in speculative connection
-  // histograms.
-  UseHistory use_history_;
-
-  DISALLOW_COPY_AND_ASSIGN(TCPClientSocketWin);
-};
-
-}  // namespace net
-
-#endif  // NET_SOCKET_TCP_CLIENT_SOCKET_WIN_H_
diff --git a/net/socket/tcp_server_socket.cc b/net/socket/tcp_server_socket.cc
index 13e9de1e59638..63cb2cf8875c5 100644
--- a/net/socket/tcp_server_socket.cc
+++ b/net/socket/tcp_server_socket.cc
@@ -22,7 +22,7 @@ TCPServerSocket::~TCPServerSocket() {
 }
 
 int TCPServerSocket::Listen(const IPEndPoint& address, int backlog) {
-  int result = socket_.Create(address.GetFamily());
+  int result = socket_.Open(address.GetFamily());
   if (result != OK)
     return result;
 
@@ -88,17 +88,17 @@ int TCPServerSocket::ConvertAcceptedSocket(
   if (result != OK)
     return result;
 
+  // TODO(yzshen): Once we switch TCPClientSocketLibevent to take a connected
+  // TCPSocket object, we don't need to do platform-specific handling.
+#if defined(OS_WIN)
+  scoped_ptr<TCPClientSocket> client_socket(new TCPClientSocket(
+      temp_accepted_socket.Pass(), accepted_address_));
+#elif defined(OS_POSIX)
   scoped_ptr<TCPClientSocket> client_socket(new TCPClientSocket(
       AddressList(accepted_address_),
       temp_accepted_socket->net_log().net_log(),
       temp_accepted_socket->net_log().source()));
-  // TODO(yzshen): Once we switch TCPClientSocket::AdoptSocket() to take a
-  // TCPSocket object, we don't need to do platform-specific handling.
-#if defined(OS_WIN)
-  SOCKET raw_socket = temp_accepted_socket->Release();
-#elif defined(OS_POSIX)
   int raw_socket = temp_accepted_socket->Release();
-#endif
   result = client_socket->AdoptSocket(raw_socket);
   if (result != OK) {
     // |client_socket| won't take ownership of |raw_socket| on failure.
@@ -106,6 +106,7 @@ int TCPServerSocket::ConvertAcceptedSocket(
     temp_accepted_socket->Adopt(raw_socket);
     return result;
   }
+#endif
 
   *output_accepted_socket = client_socket.Pass();
   return OK;
diff --git a/net/socket/tcp_socket_libevent.cc b/net/socket/tcp_socket_libevent.cc
index 0bceaa49a88d1..486113374963d 100644
--- a/net/socket/tcp_socket_libevent.cc
+++ b/net/socket/tcp_socket_libevent.cc
@@ -41,7 +41,7 @@ TCPSocketLibevent::~TCPSocketLibevent() {
   net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
 }
 
-int TCPSocketLibevent::Create(AddressFamily family) {
+int TCPSocketLibevent::Open(AddressFamily family) {
   DCHECK(CalledOnValidThread());
   DCHECK_EQ(socket_, kInvalidSocket);
 
diff --git a/net/socket/tcp_socket_libevent.h b/net/socket/tcp_socket_libevent.h
index 91a3738f9c0c8..610e48939164b 100644
--- a/net/socket/tcp_socket_libevent.h
+++ b/net/socket/tcp_socket_libevent.h
@@ -28,7 +28,7 @@ class NET_EXPORT TCPSocketLibevent : public base::NonThreadSafe,
   TCPSocketLibevent(NetLog* net_log, const NetLog::Source& source);
   virtual ~TCPSocketLibevent();
 
-  int Create(AddressFamily family);
+  int Open(AddressFamily family);
   // Takes ownership of |socket|.
   int Adopt(int socket);
   // Returns a socket file descriptor. The ownership is transferred to the
diff --git a/net/socket/tcp_socket_unittest.cc b/net/socket/tcp_socket_unittest.cc
index e20bdd875846b..0eb3083df661d 100644
--- a/net/socket/tcp_socket_unittest.cc
+++ b/net/socket/tcp_socket_unittest.cc
@@ -4,10 +4,16 @@
 
 #include "net/socket/tcp_socket.h"
 
-#include <string>
+#include <string.h>
 
+#include <string>
+#include <vector>
+
+#include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "build/build_config.h"
 #include "net/base/address_list.h"
+#include "net/base/io_buffer.h"
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_errors.h"
 #include "net/base/test_completion_callback.h"
@@ -29,7 +35,7 @@ class TCPSocketTest : public PlatformTest {
     IPEndPoint address;
     ParseAddress("127.0.0.1", 0, &address);
 
-    ASSERT_EQ(OK, socket_.Create(ADDRESS_FAMILY_IPV4));
+    ASSERT_EQ(OK, socket_.Open(ADDRESS_FAMILY_IPV4));
     ASSERT_EQ(OK, socket_.Bind(address));
     ASSERT_EQ(OK, socket_.Listen(kListenBacklog));
     ASSERT_EQ(OK, socket_.GetLocalAddress(&local_address_));
@@ -40,7 +46,7 @@ class TCPSocketTest : public PlatformTest {
     IPEndPoint address;
     ParseAddress("::1", 0, &address);
 
-    if (socket_.Create(ADDRESS_FAMILY_IPV6) != OK ||
+    if (socket_.Open(ADDRESS_FAMILY_IPV6) != OK ||
         socket_.Bind(address) != OK ||
         socket_.Listen(kListenBacklog) != OK) {
       LOG(ERROR) << "Failed to listen on ::1 - probably because IPv6 is "
@@ -194,5 +200,71 @@ TEST_F(TCPSocketTest, AcceptIPv6) {
   EXPECT_EQ(OK, connect_callback.WaitForResult());
 }
 
+// TODO(yzshen): Enable it for other platforms once TCPSocketLibevent supports
+// client socket operations.
+#if defined(OS_WIN)
+
+TEST_F(TCPSocketTest, ReadWrite) {
+  ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4());
+
+  TestCompletionCallback connect_callback;
+  TCPSocket connecting_socket(NULL, NetLog::Source());
+  int result = connecting_socket.Open(ADDRESS_FAMILY_IPV4);
+  ASSERT_EQ(OK, result);
+  connecting_socket.Connect(local_address_, connect_callback.callback());
+
+  TestCompletionCallback accept_callback;
+  scoped_ptr<TCPSocket> accepted_socket;
+  IPEndPoint accepted_address;
+  result = socket_.Accept(&accepted_socket, &accepted_address,
+                          accept_callback.callback());
+  ASSERT_EQ(OK, accept_callback.GetResult(result));
+
+  ASSERT_TRUE(accepted_socket.get());
+
+  // Both sockets should be on the loopback network interface.
+  EXPECT_EQ(accepted_address.address(), local_address_.address());
+
+  EXPECT_EQ(OK, connect_callback.WaitForResult());
+
+  const std::string message("test message");
+  std::vector<char> buffer(message.size());
+
+  size_t bytes_written = 0;
+  while (bytes_written < message.size()) {
+    scoped_refptr<IOBufferWithSize> write_buffer(
+        new IOBufferWithSize(message.size() - bytes_written));
+    memmove(write_buffer->data(), message.data() + bytes_written,
+            message.size() - bytes_written);
+
+    TestCompletionCallback write_callback;
+    int write_result = accepted_socket->Write(
+        write_buffer.get(), write_buffer->size(), write_callback.callback());
+    write_result = write_callback.GetResult(write_result);
+    ASSERT_TRUE(write_result >= 0);
+    bytes_written += write_result;
+    ASSERT_TRUE(bytes_written <= message.size());
+  }
+
+  size_t bytes_read = 0;
+  while (bytes_read < message.size()) {
+    scoped_refptr<IOBufferWithSize> read_buffer(
+        new IOBufferWithSize(message.size() - bytes_read));
+    TestCompletionCallback read_callback;
+    int read_result = connecting_socket.Read(
+        read_buffer.get(), read_buffer->size(), read_callback.callback());
+    read_result = read_callback.GetResult(read_result);
+    ASSERT_TRUE(read_result >= 0);
+    ASSERT_TRUE(bytes_read + read_result <= message.size());
+    memmove(&buffer[bytes_read], read_buffer->data(), read_result);
+    bytes_read += read_result;
+  }
+
+  std::string received_message(buffer.begin(), buffer.end());
+  ASSERT_EQ(message, received_message);
+}
+
+#endif
+
 }  // namespace
 }  // namespace net
diff --git a/net/socket/tcp_socket_win.cc b/net/socket/tcp_socket_win.cc
index f69c7609e7989..1b28124c2536d 100644
--- a/net/socket/tcp_socket_win.cc
+++ b/net/socket/tcp_socket_win.cc
@@ -6,10 +6,17 @@
 
 #include <mstcpip.h>
 
+#include "base/callback_helpers.h"
 #include "base/logging.h"
+#include "base/metrics/stats_counters.h"
+#include "base/win/windows_version.h"
+#include "net/base/address_list.h"
+#include "net/base/connection_type_histograms.h"
+#include "net/base/io_buffer.h"
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_errors.h"
 #include "net/base/net_util.h"
+#include "net/base/network_change_notifier.h"
 #include "net/base/winsock_init.h"
 #include "net/base/winsock_util.h"
 #include "net/socket/socket_descriptor.h"
@@ -17,12 +24,251 @@
 
 namespace net {
 
+namespace {
+
+const int kTCPKeepAliveSeconds = 45;
+
+bool SetSocketReceiveBufferSize(SOCKET socket, int32 size) {
+  int rv = setsockopt(socket, SOL_SOCKET, SO_RCVBUF,
+                      reinterpret_cast<const char*>(&size), sizeof(size));
+  DCHECK(!rv) << "Could not set socket receive buffer size: " << GetLastError();
+  return rv == 0;
+}
+
+bool SetSocketSendBufferSize(SOCKET socket, int32 size) {
+  int rv = setsockopt(socket, SOL_SOCKET, SO_SNDBUF,
+                      reinterpret_cast<const char*>(&size), sizeof(size));
+  DCHECK(!rv) << "Could not set socket send buffer size: " << GetLastError();
+  return rv == 0;
+}
+
+// Disable Nagle.
+// The Nagle implementation on windows is governed by RFC 896.  The idea
+// behind Nagle is to reduce small packets on the network.  When Nagle is
+// enabled, if a partial packet has been sent, the TCP stack will disallow
+// further *partial* packets until an ACK has been received from the other
+// side.  Good applications should always strive to send as much data as
+// possible and avoid partial-packet sends.  However, in most real world
+// applications, there are edge cases where this does not happen, and two
+// partial packets may be sent back to back.  For a browser, it is NEVER
+// a benefit to delay for an RTT before the second packet is sent.
+//
+// As a practical example in Chromium today, consider the case of a small
+// POST.  I have verified this:
+//     Client writes 649 bytes of header  (partial packet #1)
+//     Client writes 50 bytes of POST data (partial packet #2)
+// In the above example, with Nagle, a RTT delay is inserted between these
+// two sends due to nagle.  RTTs can easily be 100ms or more.  The best
+// fix is to make sure that for POSTing data, we write as much data as
+// possible and minimize partial packets.  We will fix that.  But disabling
+// Nagle also ensure we don't run into this delay in other edge cases.
+// See also:
+//    http://technet.microsoft.com/en-us/library/bb726981.aspx
+bool DisableNagle(SOCKET socket, bool disable) {
+  BOOL val = disable ? TRUE : FALSE;
+  int rv = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY,
+                      reinterpret_cast<const char*>(&val),
+                      sizeof(val));
+  DCHECK(!rv) << "Could not disable nagle";
+  return rv == 0;
+}
+
+// Enable TCP Keep-Alive to prevent NAT routers from timing out TCP
+// connections. See http://crbug.com/27400 for details.
+bool SetTCPKeepAlive(SOCKET socket, BOOL enable, int delay_secs) {
+  int delay = delay_secs * 1000;
+  struct tcp_keepalive keepalive_vals = {
+    enable ? 1 : 0,  // TCP keep-alive on.
+    delay,  // Delay seconds before sending first TCP keep-alive packet.
+    delay,  // Delay seconds between sending TCP keep-alive packets.
+  };
+  DWORD bytes_returned = 0xABAB;
+  int rv = WSAIoctl(socket, SIO_KEEPALIVE_VALS, &keepalive_vals,
+                    sizeof(keepalive_vals), NULL, 0,
+                    &bytes_returned, NULL, NULL);
+  DCHECK(!rv) << "Could not enable TCP Keep-Alive for socket: " << socket
+              << " [error: " << WSAGetLastError() << "].";
+
+  // Disregard any failure in disabling nagle or enabling TCP Keep-Alive.
+  return rv == 0;
+}
+
+int MapConnectError(int os_error) {
+  switch (os_error) {
+    // connect fails with WSAEACCES when Windows Firewall blocks the
+    // connection.
+    case WSAEACCES:
+      return ERR_NETWORK_ACCESS_DENIED;
+    case WSAETIMEDOUT:
+      return ERR_CONNECTION_TIMED_OUT;
+    default: {
+      int net_error = MapSystemError(os_error);
+      if (net_error == ERR_FAILED)
+        return ERR_CONNECTION_FAILED;  // More specific than ERR_FAILED.
+
+      // Give a more specific error when the user is offline.
+      if (net_error == ERR_ADDRESS_UNREACHABLE &&
+          NetworkChangeNotifier::IsOffline()) {
+        return ERR_INTERNET_DISCONNECTED;
+      }
+
+      return net_error;
+    }
+  }
+}
+
+}  // namespace
+
+//-----------------------------------------------------------------------------
+
+// This class encapsulates all the state that has to be preserved as long as
+// there is a network IO operation in progress. If the owner TCPSocketWin is
+// destroyed while an operation is in progress, the Core is detached and it
+// lives until the operation completes and the OS doesn't reference any resource
+// declared on this class anymore.
+class TCPSocketWin::Core : public base::RefCounted<Core> {
+ public:
+  explicit Core(TCPSocketWin* socket);
+
+  // Start watching for the end of a read or write operation.
+  void WatchForRead();
+  void WatchForWrite();
+
+  // The TCPSocketWin is going away.
+  void Detach() { socket_ = NULL; }
+
+  // The separate OVERLAPPED variables for asynchronous operation.
+  // |read_overlapped_| is used for both Connect() and Read().
+  // |write_overlapped_| is only used for Write();
+  OVERLAPPED read_overlapped_;
+  OVERLAPPED write_overlapped_;
+
+  // The buffers used in Read() and Write().
+  scoped_refptr<IOBuffer> read_iobuffer_;
+  scoped_refptr<IOBuffer> write_iobuffer_;
+  int read_buffer_length_;
+  int write_buffer_length_;
+
+  bool non_blocking_reads_initialized_;
+
+ private:
+  friend class base::RefCounted<Core>;
+
+  class ReadDelegate : public base::win::ObjectWatcher::Delegate {
+   public:
+    explicit ReadDelegate(Core* core) : core_(core) {}
+    virtual ~ReadDelegate() {}
+
+    // base::ObjectWatcher::Delegate methods:
+    virtual void OnObjectSignaled(HANDLE object);
+
+   private:
+    Core* const core_;
+  };
+
+  class WriteDelegate : public base::win::ObjectWatcher::Delegate {
+   public:
+    explicit WriteDelegate(Core* core) : core_(core) {}
+    virtual ~WriteDelegate() {}
+
+    // base::ObjectWatcher::Delegate methods:
+    virtual void OnObjectSignaled(HANDLE object);
+
+   private:
+    Core* const core_;
+  };
+
+  ~Core();
+
+  // The socket that created this object.
+  TCPSocketWin* socket_;
+
+  // |reader_| handles the signals from |read_watcher_|.
+  ReadDelegate reader_;
+  // |writer_| handles the signals from |write_watcher_|.
+  WriteDelegate writer_;
+
+  // |read_watcher_| watches for events from Connect() and Read().
+  base::win::ObjectWatcher read_watcher_;
+  // |write_watcher_| watches for events from Write();
+  base::win::ObjectWatcher write_watcher_;
+
+  DISALLOW_COPY_AND_ASSIGN(Core);
+};
+
+TCPSocketWin::Core::Core(TCPSocketWin* socket)
+    : read_buffer_length_(0),
+      write_buffer_length_(0),
+      non_blocking_reads_initialized_(false),
+      socket_(socket),
+      reader_(this),
+      writer_(this) {
+  memset(&read_overlapped_, 0, sizeof(read_overlapped_));
+  memset(&write_overlapped_, 0, sizeof(write_overlapped_));
+
+  read_overlapped_.hEvent = WSACreateEvent();
+  write_overlapped_.hEvent = WSACreateEvent();
+}
+
+TCPSocketWin::Core::~Core() {
+  // Make sure the message loop is not watching this object anymore.
+  read_watcher_.StopWatching();
+  write_watcher_.StopWatching();
+
+  WSACloseEvent(read_overlapped_.hEvent);
+  memset(&read_overlapped_, 0xaf, sizeof(read_overlapped_));
+  WSACloseEvent(write_overlapped_.hEvent);
+  memset(&write_overlapped_, 0xaf, sizeof(write_overlapped_));
+}
+
+void TCPSocketWin::Core::WatchForRead() {
+  // We grab an extra reference because there is an IO operation in progress.
+  // Balanced in ReadDelegate::OnObjectSignaled().
+  AddRef();
+  read_watcher_.StartWatching(read_overlapped_.hEvent, &reader_);
+}
+
+void TCPSocketWin::Core::WatchForWrite() {
+  // We grab an extra reference because there is an IO operation in progress.
+  // Balanced in WriteDelegate::OnObjectSignaled().
+  AddRef();
+  write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_);
+}
+
+void TCPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object) {
+  DCHECK_EQ(object, core_->read_overlapped_.hEvent);
+  if (core_->socket_) {
+    if (core_->socket_->waiting_connect_)
+      core_->socket_->DidCompleteConnect();
+    else
+      core_->socket_->DidSignalRead();
+  }
+
+  core_->Release();
+}
+
+void TCPSocketWin::Core::WriteDelegate::OnObjectSignaled(
+    HANDLE object) {
+  DCHECK_EQ(object, core_->write_overlapped_.hEvent);
+  if (core_->socket_)
+    core_->socket_->DidCompleteWrite();
+
+  core_->Release();
+}
+
+//-----------------------------------------------------------------------------
+
 TCPSocketWin::TCPSocketWin(net::NetLog* net_log,
                            const net::NetLog::Source& source)
     : socket_(INVALID_SOCKET),
-      socket_event_(WSA_INVALID_EVENT),
+      accept_event_(WSA_INVALID_EVENT),
       accept_socket_(NULL),
       accept_address_(NULL),
+      waiting_connect_(false),
+      waiting_read_(false),
+      waiting_write_(false),
+      connect_os_error_(0),
+      logging_multiple_connect_attempts_(false),
       net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {
   net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE,
                       source.ToEventParametersCallback());
@@ -34,7 +280,7 @@ TCPSocketWin::~TCPSocketWin() {
   net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
 }
 
-int TCPSocketWin::Create(AddressFamily family) {
+int TCPSocketWin::Open(AddressFamily family) {
   DCHECK(CalledOnValidThread());
   DCHECK_EQ(socket_, INVALID_SOCKET);
 
@@ -54,9 +300,11 @@ int TCPSocketWin::Create(AddressFamily family) {
   return OK;
 }
 
-int TCPSocketWin::Adopt(SOCKET socket) {
+int TCPSocketWin::AdoptConnectedSocket(SOCKET socket,
+                                       const IPEndPoint& peer_address) {
   DCHECK(CalledOnValidThread());
   DCHECK_EQ(socket_, INVALID_SOCKET);
+  DCHECK(!core_);
 
   socket_ = socket;
 
@@ -66,19 +314,12 @@ int TCPSocketWin::Adopt(SOCKET socket) {
     return result;
   }
 
+  core_ = new Core(this);
+  peer_address_.reset(new IPEndPoint(peer_address));
+
   return OK;
 }
 
-SOCKET TCPSocketWin::Release() {
-  DCHECK(CalledOnValidThread());
-  DCHECK_EQ(socket_event_, WSA_INVALID_EVENT);
-  DCHECK(accept_callback_.is_null());
-
-  SOCKET result = socket_;
-  socket_ = INVALID_SOCKET;
-  return result;
-}
-
 int TCPSocketWin::Bind(const IPEndPoint& address) {
   DCHECK(CalledOnValidThread());
   DCHECK_NE(socket_, INVALID_SOCKET);
@@ -96,36 +337,22 @@ int TCPSocketWin::Bind(const IPEndPoint& address) {
   return OK;
 }
 
-int TCPSocketWin::GetLocalAddress(IPEndPoint* address) const {
-  DCHECK(CalledOnValidThread());
-  DCHECK(address);
-
-  SockaddrStorage storage;
-  if (getsockname(socket_, storage.addr, &storage.addr_len))
-    return MapSystemError(WSAGetLastError());
-  if (!address->FromSockAddr(storage.addr, storage.addr_len))
-    return ERR_FAILED;
-
-  return OK;
-}
-
 int TCPSocketWin::Listen(int backlog) {
   DCHECK(CalledOnValidThread());
   DCHECK_GT(backlog, 0);
   DCHECK_NE(socket_, INVALID_SOCKET);
-  DCHECK_EQ(socket_event_, WSA_INVALID_EVENT);
+  DCHECK_EQ(accept_event_, WSA_INVALID_EVENT);
 
-  socket_event_ = WSACreateEvent();
-  if (socket_event_ == WSA_INVALID_EVENT) {
+  accept_event_ = WSACreateEvent();
+  if (accept_event_ == WSA_INVALID_EVENT) {
     PLOG(ERROR) << "WSACreateEvent()";
-    return ERR_FAILED;
+    return MapSystemError(WSAGetLastError());
   }
 
   int result = listen(socket_, backlog);
   if (result < 0) {
     PLOG(ERROR) << "listen() returned an error";
-    result = MapSystemError(WSAGetLastError());
-    return result;
+    return MapSystemError(WSAGetLastError());
   }
 
   return OK;
@@ -146,8 +373,8 @@ int TCPSocketWin::Accept(scoped_ptr<TCPSocketWin>* socket,
 
   if (result == ERR_IO_PENDING) {
     // Start watching.
-    WSAEventSelect(socket_, socket_event_, FD_ACCEPT);
-    accept_watcher_.StartWatching(socket_event_, this);
+    WSAEventSelect(socket_, accept_event_, FD_ACCEPT);
+    accept_watcher_.StartWatching(accept_event_, this);
 
     accept_socket_ = socket;
     accept_address_ = address;
@@ -157,10 +384,195 @@ int TCPSocketWin::Accept(scoped_ptr<TCPSocketWin>* socket,
   return result;
 }
 
+int TCPSocketWin::Connect(const IPEndPoint& address,
+                          const CompletionCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  DCHECK_NE(socket_, INVALID_SOCKET);
+  DCHECK(!waiting_connect_);
+
+  // |peer_address_| and |core_| will be non-NULL if Connect() has been called.
+  // Unless Close() is called to reset the internal state, a second call to
+  // Connect() is not allowed.
+  // Please note that we enforce this even if the previous Connect() has
+  // completed and failed. Although it is allowed to connect the same |socket_|
+  // again after a connection attempt failed on Windows, it results in
+  // unspecified behavior according to POSIX. Therefore, we make it behave in
+  // the same way as TCPSocketLibevent.
+  DCHECK(!peer_address_ && !core_);
+
+  if (!logging_multiple_connect_attempts_)
+    LogConnectBegin(AddressList(address));
+
+  peer_address_.reset(new IPEndPoint(address));
+
+  int rv = DoConnect();
+  if (rv == ERR_IO_PENDING) {
+    // Synchronous operation not supported.
+    DCHECK(!callback.is_null());
+    read_callback_ = callback;
+    waiting_connect_ = true;
+  } else {
+    DoConnectComplete(rv);
+  }
+
+  return rv;
+}
+
+bool TCPSocketWin::IsConnected() const {
+  DCHECK(CalledOnValidThread());
+
+  if (socket_ == INVALID_SOCKET || waiting_connect_)
+    return false;
+
+  if (waiting_read_)
+    return true;
+
+  // Check if connection is alive.
+  char c;
+  int rv = recv(socket_, &c, 1, MSG_PEEK);
+  if (rv == 0)
+    return false;
+  if (rv == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
+    return false;
+
+  return true;
+}
+
+bool TCPSocketWin::IsConnectedAndIdle() const {
+  DCHECK(CalledOnValidThread());
+
+  if (socket_ == INVALID_SOCKET || waiting_connect_)
+    return false;
+
+  if (waiting_read_)
+    return true;
+
+  // Check if connection is alive and we haven't received any data
+  // unexpectedly.
+  char c;
+  int rv = recv(socket_, &c, 1, MSG_PEEK);
+  if (rv >= 0)
+    return false;
+  if (WSAGetLastError() != WSAEWOULDBLOCK)
+    return false;
+
+  return true;
+}
+
+int TCPSocketWin::Read(IOBuffer* buf,
+                       int buf_len,
+                       const CompletionCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  DCHECK_NE(socket_, INVALID_SOCKET);
+  DCHECK(!waiting_read_);
+  DCHECK(read_callback_.is_null());
+  DCHECK(!core_->read_iobuffer_);
+
+  return DoRead(buf, buf_len, callback);
+}
+
+int TCPSocketWin::Write(IOBuffer* buf,
+                        int buf_len,
+                        const CompletionCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  DCHECK_NE(socket_, INVALID_SOCKET);
+  DCHECK(!waiting_write_);
+  DCHECK(write_callback_.is_null());
+  DCHECK_GT(buf_len, 0);
+  DCHECK(!core_->write_iobuffer_);
+
+  base::StatsCounter writes("tcp.writes");
+  writes.Increment();
+
+  WSABUF write_buffer;
+  write_buffer.len = buf_len;
+  write_buffer.buf = buf->data();
+
+  // TODO(wtc): Remove the assertion after enough testing.
+  AssertEventNotSignaled(core_->write_overlapped_.hEvent);
+  DWORD num;
+  int rv = WSASend(socket_, &write_buffer, 1, &num, 0,
+                   &core_->write_overlapped_, NULL);
+  if (rv == 0) {
+    if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) {
+      rv = static_cast<int>(num);
+      if (rv > buf_len || rv < 0) {
+        // It seems that some winsock interceptors report that more was written
+        // than was available. Treat this as an error.  http://crbug.com/27870
+        LOG(ERROR) << "Detected broken LSP: Asked to write " << buf_len
+                   << " bytes, but " << rv << " bytes reported.";
+        return ERR_WINSOCK_UNEXPECTED_WRITTEN_BYTES;
+      }
+      base::StatsCounter write_bytes("tcp.write_bytes");
+      write_bytes.Add(rv);
+      net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, rv,
+                                    buf->data());
+      return rv;
+    }
+  } else {
+    int os_error = WSAGetLastError();
+    if (os_error != WSA_IO_PENDING) {
+      int net_error = MapSystemError(os_error);
+      net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR,
+                        CreateNetLogSocketErrorCallback(net_error, os_error));
+      return net_error;
+    }
+  }
+  waiting_write_ = true;
+  write_callback_ = callback;
+  core_->write_iobuffer_ = buf;
+  core_->write_buffer_length_ = buf_len;
+  core_->WatchForWrite();
+  return ERR_IO_PENDING;
+}
+
+int TCPSocketWin::GetLocalAddress(IPEndPoint* address) const {
+  DCHECK(CalledOnValidThread());
+  DCHECK(address);
+
+  SockaddrStorage storage;
+  if (getsockname(socket_, storage.addr, &storage.addr_len))
+    return MapSystemError(WSAGetLastError());
+  if (!address->FromSockAddr(storage.addr, storage.addr_len))
+    return ERR_ADDRESS_INVALID;
+
+  return OK;
+}
+
+int TCPSocketWin::GetPeerAddress(IPEndPoint* address) const {
+  DCHECK(CalledOnValidThread());
+  DCHECK(address);
+  if (!IsConnected())
+    return ERR_SOCKET_NOT_CONNECTED;
+  *address = *peer_address_;
+  return OK;
+}
+
 int TCPSocketWin::SetDefaultOptionsForServer() {
   return SetExclusiveAddrUse();
 }
 
+void TCPSocketWin::SetDefaultOptionsForClient() {
+  // Increase the socket buffer sizes from the default sizes for WinXP.  In
+  // performance testing, there is substantial benefit by increasing from 8KB
+  // to 64KB.
+  // See also:
+  //    http://support.microsoft.com/kb/823764/EN-US
+  // On Vista, if we manually set these sizes, Vista turns off its receive
+  // window auto-tuning feature.
+  //    http://blogs.msdn.com/wndp/archive/2006/05/05/Winhec-blog-tcpip-2.aspx
+  // Since Vista's auto-tune is better than any static value we can could set,
+  // only change these on pre-vista machines.
+  if (base::win::GetVersion() < base::win::VERSION_VISTA) {
+    const int32 kSocketBufferSize = 64 * 1024;
+    SetSocketReceiveBufferSize(socket_, kSocketBufferSize);
+    SetSocketSendBufferSize(socket_, kSocketBufferSize);
+  }
+
+  DisableNagle(socket_, true);
+  SetTCPKeepAlive(socket_, true, kTCPKeepAliveSeconds);
+}
+
 int TCPSocketWin::SetExclusiveAddrUse() {
   // On Windows, a bound end point can be hijacked by another process by
   // setting SO_REUSEADDR. Therefore a Windows-only option SO_EXCLUSIVEADDRUSE
@@ -187,16 +599,99 @@ int TCPSocketWin::SetExclusiveAddrUse() {
   return OK;
 }
 
+bool TCPSocketWin::SetReceiveBufferSize(int32 size) {
+  DCHECK(CalledOnValidThread());
+  return SetSocketReceiveBufferSize(socket_, size);
+}
+
+bool TCPSocketWin::SetSendBufferSize(int32 size) {
+  DCHECK(CalledOnValidThread());
+  return SetSocketSendBufferSize(socket_, size);
+}
+
+bool TCPSocketWin::SetKeepAlive(bool enable, int delay) {
+  return SetTCPKeepAlive(socket_, enable, delay);
+}
+
+bool TCPSocketWin::SetNoDelay(bool no_delay) {
+  return DisableNagle(socket_, no_delay);
+}
+
 void TCPSocketWin::Close() {
+  DCHECK(CalledOnValidThread());
+
   if (socket_ != INVALID_SOCKET) {
+    // Note: don't use CancelIo to cancel pending IO because it doesn't work
+    // when there is a Winsock layered service provider.
+
+    // In most socket implementations, closing a socket results in a graceful
+    // connection shutdown, but in Winsock we have to call shutdown explicitly.
+    // See the MSDN page "Graceful Shutdown, Linger Options, and Socket Closure"
+    // at http://msdn.microsoft.com/en-us/library/ms738547.aspx
+    shutdown(socket_, SD_SEND);
+
+    // This cancels any pending IO.
     if (closesocket(socket_) < 0)
       PLOG(ERROR) << "closesocket";
     socket_ = INVALID_SOCKET;
   }
 
-  if (socket_event_) {
-    WSACloseEvent(socket_event_);
-    socket_event_ = WSA_INVALID_EVENT;
+  if (accept_event_) {
+    WSACloseEvent(accept_event_);
+    accept_event_ = WSA_INVALID_EVENT;
+  }
+
+  if (!accept_callback_.is_null()) {
+    accept_watcher_.StopWatching();
+    accept_socket_ = NULL;
+    accept_address_ = NULL;
+    accept_callback_.Reset();
+  }
+
+  if (core_) {
+    if (waiting_connect_) {
+      // We closed the socket, so this notification will never come.
+      // From MSDN' WSAEventSelect documentation:
+      // "Closing a socket with closesocket also cancels the association and
+      // selection of network events specified in WSAEventSelect for the
+      // socket".
+      core_->Release();
+    }
+    core_->Detach();
+    core_ = NULL;
+  }
+
+  waiting_connect_ = false;
+  waiting_read_ = false;
+  waiting_write_ = false;
+
+  read_callback_.Reset();
+  write_callback_.Reset();
+  peer_address_.reset();
+  connect_os_error_ = 0;
+}
+
+bool TCPSocketWin::UsingTCPFastOpen() const {
+  // Not supported on windows.
+  return false;
+}
+
+void TCPSocketWin::StartLoggingMultipleConnectAttempts(
+    const AddressList& addresses) {
+  if (!logging_multiple_connect_attempts_) {
+    logging_multiple_connect_attempts_ = true;
+    LogConnectBegin(addresses);
+  } else {
+    NOTREACHED();
+  }
+}
+
+void TCPSocketWin::EndLoggingMultipleConnectAttempts(int net_error) {
+  if (logging_multiple_connect_attempts_) {
+    LogConnectEnd(net_error);
+    logging_multiple_connect_attempts_ = false;
+  } else {
+    NOTREACHED();
   }
 }
 
@@ -221,7 +716,7 @@ int TCPSocketWin::AcceptInternal(scoped_ptr<TCPSocketWin>* socket,
   }
   scoped_ptr<TCPSocketWin> tcp_socket(new TCPSocketWin(
       net_log_.net_log(), net_log_.source()));
-  int adopt_result = tcp_socket->Adopt(new_socket);
+  int adopt_result = tcp_socket->AdoptConnectedSocket(new_socket, ip_end_point);
   if (adopt_result != OK) {
     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, adopt_result);
     return adopt_result;
@@ -235,7 +730,7 @@ int TCPSocketWin::AcceptInternal(scoped_ptr<TCPSocketWin>* socket,
 
 void TCPSocketWin::OnObjectSignaled(HANDLE object) {
   WSANETWORKEVENTS ev;
-  if (WSAEnumNetworkEvents(socket_, socket_event_, &ev) == SOCKET_ERROR) {
+  if (WSAEnumNetworkEvents(socket_, accept_event_, &ev) == SOCKET_ERROR) {
     PLOG(ERROR) << "WSAEnumNetworkEvents()";
     return;
   }
@@ -245,11 +740,251 @@ void TCPSocketWin::OnObjectSignaled(HANDLE object) {
     if (result != ERR_IO_PENDING) {
       accept_socket_ = NULL;
       accept_address_ = NULL;
-      CompletionCallback callback = accept_callback_;
-      accept_callback_.Reset();
-      callback.Run(result);
+      base::ResetAndReturn(&accept_callback_).Run(result);
     }
   }
 }
 
+int TCPSocketWin::DoConnect() {
+  DCHECK_EQ(connect_os_error_, 0);
+  DCHECK(!core_);
+
+  net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT,
+                      CreateNetLogIPEndPointCallback(peer_address_.get()));
+
+  core_ = new Core(this);
+  // WSAEventSelect sets the socket to non-blocking mode as a side effect.
+  // Our connect() and recv() calls require that the socket be non-blocking.
+  WSAEventSelect(socket_, core_->read_overlapped_.hEvent, FD_CONNECT);
+
+  SockaddrStorage storage;
+  if (!peer_address_->ToSockAddr(storage.addr, &storage.addr_len))
+    return ERR_INVALID_ARGUMENT;
+  if (!connect(socket_, storage.addr, storage.addr_len)) {
+    // Connected without waiting!
+    //
+    // The MSDN page for connect says:
+    //   With a nonblocking socket, the connection attempt cannot be completed
+    //   immediately. In this case, connect will return SOCKET_ERROR, and
+    //   WSAGetLastError will return WSAEWOULDBLOCK.
+    // which implies that for a nonblocking socket, connect never returns 0.
+    // It's not documented whether the event object will be signaled or not
+    // if connect does return 0.  So the code below is essentially dead code
+    // and we don't know if it's correct.
+    NOTREACHED();
+
+    if (ResetEventIfSignaled(core_->read_overlapped_.hEvent))
+      return OK;
+  } else {
+    int os_error = WSAGetLastError();
+    if (os_error != WSAEWOULDBLOCK) {
+      LOG(ERROR) << "connect failed: " << os_error;
+      connect_os_error_ = os_error;
+      return MapConnectError(os_error);
+    }
+  }
+
+  core_->WatchForRead();
+  return ERR_IO_PENDING;
+}
+
+void TCPSocketWin::DoConnectComplete(int result) {
+  // Log the end of this attempt (and any OS error it threw).
+  int os_error = connect_os_error_;
+  connect_os_error_ = 0;
+  if (result != OK) {
+    net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT,
+                      NetLog::IntegerCallback("os_error", os_error));
+  } else {
+    net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT);
+  }
+
+  if (!logging_multiple_connect_attempts_)
+    LogConnectEnd(result);
+}
+
+void TCPSocketWin::LogConnectBegin(const AddressList& addresses) {
+  base::StatsCounter connects("tcp.connect");
+  connects.Increment();
+
+  net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT,
+                      addresses.CreateNetLogCallback());
+}
+
+void TCPSocketWin::LogConnectEnd(int net_error) {
+  if (net_error == OK)
+    UpdateConnectionTypeHistograms(CONNECTION_ANY);
+
+  if (net_error != OK) {
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error);
+    return;
+  }
+
+  struct sockaddr_storage source_address;
+  socklen_t addrlen = sizeof(source_address);
+  int rv = getsockname(
+      socket_, reinterpret_cast<struct sockaddr*>(&source_address), &addrlen);
+  if (rv != 0) {
+    LOG(ERROR) << "getsockname() [rv: " << rv
+               << "] error: " << WSAGetLastError();
+    NOTREACHED();
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv);
+    return;
+  }
+
+  net_log_.EndEvent(
+      NetLog::TYPE_TCP_CONNECT,
+      CreateNetLogSourceAddressCallback(
+          reinterpret_cast<const struct sockaddr*>(&source_address),
+          sizeof(source_address)));
+}
+
+int TCPSocketWin::DoRead(IOBuffer* buf, int buf_len,
+                         const CompletionCallback& callback) {
+  if (!core_->non_blocking_reads_initialized_) {
+    WSAEventSelect(socket_, core_->read_overlapped_.hEvent,
+                   FD_READ | FD_CLOSE);
+    core_->non_blocking_reads_initialized_ = true;
+  }
+  int rv = recv(socket_, buf->data(), buf_len, 0);
+  if (rv == SOCKET_ERROR) {
+    int os_error = WSAGetLastError();
+    if (os_error != WSAEWOULDBLOCK) {
+      int net_error = MapSystemError(os_error);
+      net_log_.AddEvent(
+          NetLog::TYPE_SOCKET_READ_ERROR,
+          CreateNetLogSocketErrorCallback(net_error, os_error));
+      return net_error;
+    }
+  } else {
+    base::StatsCounter read_bytes("tcp.read_bytes");
+    if (rv > 0)
+      read_bytes.Add(rv);
+    net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, rv,
+                                  buf->data());
+    return rv;
+  }
+
+  waiting_read_ = true;
+  read_callback_ = callback;
+  core_->read_iobuffer_ = buf;
+  core_->read_buffer_length_ = buf_len;
+  core_->WatchForRead();
+  return ERR_IO_PENDING;
+}
+
+void TCPSocketWin::DidCompleteConnect() {
+  DCHECK(waiting_connect_);
+  DCHECK(!read_callback_.is_null());
+  int result;
+
+  WSANETWORKEVENTS events;
+  int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent,
+                                &events);
+  int os_error = 0;
+  if (rv == SOCKET_ERROR) {
+    NOTREACHED();
+    os_error = WSAGetLastError();
+    result = MapSystemError(os_error);
+  } else if (events.lNetworkEvents & FD_CONNECT) {
+    os_error = events.iErrorCode[FD_CONNECT_BIT];
+    result = MapConnectError(os_error);
+  } else {
+    NOTREACHED();
+    result = ERR_UNEXPECTED;
+  }
+
+  connect_os_error_ = os_error;
+  DoConnectComplete(result);
+  waiting_connect_ = false;
+
+  DCHECK_NE(result, ERR_IO_PENDING);
+  base::ResetAndReturn(&read_callback_).Run(result);
+}
+
+void TCPSocketWin::DidCompleteWrite() {
+  DCHECK(waiting_write_);
+  DCHECK(!write_callback_.is_null());
+
+  DWORD num_bytes, flags;
+  BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_,
+                                   &num_bytes, FALSE, &flags);
+  WSAResetEvent(core_->write_overlapped_.hEvent);
+  waiting_write_ = false;
+  int rv;
+  if (!ok) {
+    int os_error = WSAGetLastError();
+    rv = MapSystemError(os_error);
+    net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR,
+                      CreateNetLogSocketErrorCallback(rv, os_error));
+  } else {
+    rv = static_cast<int>(num_bytes);
+    if (rv > core_->write_buffer_length_ || rv < 0) {
+      // It seems that some winsock interceptors report that more was written
+      // than was available. Treat this as an error.  http://crbug.com/27870
+      LOG(ERROR) << "Detected broken LSP: Asked to write "
+                 << core_->write_buffer_length_ << " bytes, but " << rv
+                 << " bytes reported.";
+      rv = ERR_WINSOCK_UNEXPECTED_WRITTEN_BYTES;
+    } else {
+      base::StatsCounter write_bytes("tcp.write_bytes");
+      write_bytes.Add(num_bytes);
+      net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, num_bytes,
+                                    core_->write_iobuffer_->data());
+    }
+  }
+
+  core_->write_iobuffer_ = NULL;
+
+  DCHECK_NE(rv, ERR_IO_PENDING);
+  base::ResetAndReturn(&write_callback_).Run(rv);
+}
+
+void TCPSocketWin::DidSignalRead() {
+  DCHECK(waiting_read_);
+  DCHECK(!read_callback_.is_null());
+
+  int os_error = 0;
+  WSANETWORKEVENTS network_events;
+  int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent,
+                                &network_events);
+  if (rv == SOCKET_ERROR) {
+    os_error = WSAGetLastError();
+    rv = MapSystemError(os_error);
+  } else if (network_events.lNetworkEvents) {
+    DCHECK_EQ(network_events.lNetworkEvents & ~(FD_READ | FD_CLOSE), 0);
+    // If network_events.lNetworkEvents is FD_CLOSE and
+    // network_events.iErrorCode[FD_CLOSE_BIT] is 0, it is a graceful
+    // connection closure. It is tempting to directly set rv to 0 in
+    // this case, but the MSDN pages for WSAEventSelect and
+    // WSAAsyncSelect recommend we still call DoRead():
+    //   FD_CLOSE should only be posted after all data is read from a
+    //   socket, but an application should check for remaining data upon
+    //   receipt of FD_CLOSE to avoid any possibility of losing data.
+    //
+    // If network_events.iErrorCode[FD_READ_BIT] or
+    // network_events.iErrorCode[FD_CLOSE_BIT] is nonzero, still call
+    // DoRead() because recv() reports a more accurate error code
+    // (WSAECONNRESET vs. WSAECONNABORTED) when the connection was
+    // reset.
+    rv = DoRead(core_->read_iobuffer_, core_->read_buffer_length_,
+                read_callback_);
+    if (rv == ERR_IO_PENDING)
+      return;
+  } else {
+    // This may happen because Read() may succeed synchronously and
+    // consume all the received data without resetting the event object.
+    core_->WatchForRead();
+    return;
+  }
+
+  waiting_read_ = false;
+  core_->read_iobuffer_ = NULL;
+  core_->read_buffer_length_ = 0;
+
+  DCHECK_NE(rv, ERR_IO_PENDING);
+  base::ResetAndReturn(&read_callback_).Run(rv);
+}
+
 }  // namespace net
+
diff --git a/net/socket/tcp_socket_win.h b/net/socket/tcp_socket_win.h
index 044e5e058520b..df5fbf09aecc9 100644
--- a/net/socket/tcp_socket_win.h
+++ b/net/socket/tcp_socket_win.h
@@ -9,8 +9,8 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
 #include "base/threading/non_thread_safe.h"
 #include "base/win/object_watcher.h"
 #include "net/base/address_family.h"
@@ -20,50 +20,125 @@
 
 namespace net {
 
+class AddressList;
+class IOBuffer;
 class IPEndPoint;
 
-// TODO(yzshen): This class is incomplete. TCP client operations (Connect/Read/
-// Write/etc.) will be added. And TCPClientSocket will be changed to be a
-// wrapper around TCPSocket.
 class NET_EXPORT TCPSocketWin : NON_EXPORTED_BASE(public base::NonThreadSafe),
                                 public base::win::ObjectWatcher::Delegate  {
  public:
   TCPSocketWin(NetLog* net_log, const NetLog::Source& source);
   virtual ~TCPSocketWin();
 
-  int Create(AddressFamily family);
+  int Open(AddressFamily family);
   // Takes ownership of |socket|.
-  int Adopt(SOCKET socket);
-  // Returns a socket descriptor. The ownership is transferred to the caller.
-  SOCKET Release();
+  int AdoptConnectedSocket(SOCKET socket, const IPEndPoint& peer_address);
+
   int Bind(const IPEndPoint& address);
-  int GetLocalAddress(IPEndPoint* address) const;
+
   int Listen(int backlog);
   int Accept(scoped_ptr<TCPSocketWin>* socket,
              IPEndPoint* address,
              const CompletionCallback& callback);
+
+  int Connect(const IPEndPoint& address, const CompletionCallback& callback);
+  bool IsConnected() const;
+  bool IsConnectedAndIdle() const;
+
+  // Multiple outstanding requests are not supported.
+  // Full duplex mode (reading and writing at the same time) is supported.
+  int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
+  int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
+
+  int GetLocalAddress(IPEndPoint* address) const;
+  int GetPeerAddress(IPEndPoint* address) const;
+
+  // Sets various socket options.
+  // The commonly used options for server listening sockets:
+  // - SetExclusiveAddrUse().
   int SetDefaultOptionsForServer();
+  // The commonly used options for client sockets and accepted sockets:
+  // - Increase the socket buffer sizes for WinXP;
+  // - SetNoDelay(true);
+  // - SetKeepAlive(true, 45).
+  void SetDefaultOptionsForClient();
   int SetExclusiveAddrUse();
+  bool SetReceiveBufferSize(int32 size);
+  bool SetSendBufferSize(int32 size);
+  bool SetKeepAlive(bool enable, int delay);
+  bool SetNoDelay(bool no_delay);
+
   void Close();
 
+  bool UsingTCPFastOpen() const;
+  bool IsValid() const { return socket_ != INVALID_SOCKET; }
+
+  // Marks the start/end of a series of connect attempts for logging purpose.
+  //
+  // TCPClientSocket may attempt to connect to multiple addresses until it
+  // succeeds in establishing a connection. The corresponding log will have
+  // multiple NetLog::TYPE_TCP_CONNECT_ATTEMPT entries nested within a
+  // NetLog::TYPE_TCP_CONNECT. These methods set the start/end of
+  // NetLog::TYPE_TCP_CONNECT.
+  //
+  // TODO(yzshen): Change logging format and let TCPClientSocket log the
+  // start/end of a series of connect attempts itself.
+  void StartLoggingMultipleConnectAttempts(const AddressList& addresses);
+  void EndLoggingMultipleConnectAttempts(int net_error);
+
   const BoundNetLog& net_log() const { return net_log_; }
 
+ private:
+  class Core;
+
   // base::ObjectWatcher::Delegate implementation.
   virtual void OnObjectSignaled(HANDLE object) OVERRIDE;
 
- private:
   int AcceptInternal(scoped_ptr<TCPSocketWin>* socket,
                      IPEndPoint* address);
 
-  SOCKET socket_;
-  HANDLE socket_event_;
+  int DoConnect();
+  void DoConnectComplete(int result);
 
+  void LogConnectBegin(const AddressList& addresses);
+  void LogConnectEnd(int net_error);
+
+  int DoRead(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
+  void DidCompleteConnect();
+  void DidCompleteWrite();
+  void DidSignalRead();
+
+  SOCKET socket_;
+
+  HANDLE accept_event_;
   base::win::ObjectWatcher accept_watcher_;
 
   scoped_ptr<TCPSocketWin>* accept_socket_;
   IPEndPoint* accept_address_;
   CompletionCallback accept_callback_;
 
+  // The various states that the socket could be in.
+  bool waiting_connect_;
+  bool waiting_read_;
+  bool waiting_write_;
+
+  // The core of the socket that can live longer than the socket itself. We pass
+  // resources to the Windows async IO functions and we have to make sure that
+  // they are not destroyed while the OS still references them.
+  scoped_refptr<Core> core_;
+
+  // External callback; called when connect or read is complete.
+  CompletionCallback read_callback_;
+
+  // External callback; called when write is complete.
+  CompletionCallback write_callback_;
+
+  scoped_ptr<IPEndPoint> peer_address_;
+  // The OS error that a connect attempt last completed with.
+  int connect_os_error_;
+
+  bool logging_multiple_connect_attempts_;
+
   BoundNetLog net_log_;
 
   DISALLOW_COPY_AND_ASSIGN(TCPSocketWin);
@@ -72,3 +147,4 @@ class NET_EXPORT TCPSocketWin : NON_EXPORTED_BASE(public base::NonThreadSafe),
 }  // namespace net
 
 #endif  // NET_SOCKET_TCP_SOCKET_WIN_H_
+