Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(363)

Unified Diff: net/socket/tcp_client_socket.cc

Issue 2447083003: Move fail on suspend logic from URLRequestJob to TcpClientSocket.
Patch Set: . Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/socket/tcp_client_socket.h ('k') | net/socket/transport_client_socket_pool.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/socket/tcp_client_socket.cc
diff --git a/net/socket/tcp_client_socket.cc b/net/socket/tcp_client_socket.cc
index 9e1470ffcdb02e14bff1c1b31a512169231be68b..44a27ee9dc37349be05c9761b334ff50c1186935 100644
--- a/net/socket/tcp_client_socket.cc
+++ b/net/socket/tcp_client_socket.cc
@@ -16,6 +16,10 @@
#include "net/base/net_errors.h"
#include "net/socket/socket_performance_watcher.h"
+#if !defined(OS_NACL)
+#include "base/power_monitor/power_monitor.h"
+#endif
+
namespace net {
class NetLogWithSource;
@@ -33,7 +37,8 @@ TCPClientSocket::TCPClientSocket(
current_address_index_(-1),
next_connect_state_(CONNECT_STATE_NONE),
previously_disconnected_(false),
- total_received_bytes_(0) {}
+ total_received_bytes_(0),
+ weak_ptr_factory_(this) {}
TCPClientSocket::TCPClientSocket(std::unique_ptr<TCPSocket> connected_socket,
const IPEndPoint& peer_address)
@@ -43,7 +48,8 @@ TCPClientSocket::TCPClientSocket(std::unique_ptr<TCPSocket> connected_socket,
current_address_index_(0),
next_connect_state_(CONNECT_STATE_NONE),
previously_disconnected_(false),
- total_received_bytes_(0) {
+ total_received_bytes_(0),
+ weak_ptr_factory_(this) {
DCHECK(socket_);
socket_->SetDefaultOptionsForClient();
@@ -51,6 +57,7 @@ TCPClientSocket::TCPClientSocket(std::unique_ptr<TCPSocket> connected_socket,
}
TCPClientSocket::~TCPClientSocket() {
+ SetFailOnSuspend(false);
Disconnect();
}
@@ -83,6 +90,8 @@ int TCPClientSocket::Connect(const CompletionCallback& callback) {
if (socket_->IsValid() && current_address_index_ >= 0)
return OK;
+ was_disconnected_on_suspend_ = false;
+
socket_->StartLoggingMultipleConnectAttempts(addresses_);
// We will try to connect to each address in addresses_. Start with the
@@ -220,6 +229,14 @@ void TCPClientSocket::Disconnect() {
DoDisconnect();
current_address_index_ = -1;
bind_address_.reset();
+
+ // Cancel any pending callbacks. Not done in Disconnect() because that's
+ // called on connection failure, when the connect callback will need to be
+ // invoked.
+ was_disconnected_on_suspend_ = false;
+ connect_callback_.Reset();
+ read_callback_.Reset();
+ write_callback_.Reset();
}
void TCPClientSocket::DoDisconnect() {
@@ -229,6 +246,10 @@ void TCPClientSocket::DoDisconnect() {
// disconnected.
previously_disconnected_ = socket_->IsValid() && current_address_index_ >= 0;
socket_->Close();
+
+ // Invalidate weak pointers, so if in the middle of a callback in OnSuspend,
+ // and something destroys this, no other callback is invoked.
+ weak_ptr_factory_.InvalidateWeakPtrs();
}
bool TCPClientSocket::IsConnected() const {
@@ -289,6 +310,27 @@ bool TCPClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
return false;
}
+void TCPClientSocket::SetFailOnSuspend(bool disconnect_on_suspend) {
+// Do nothing if building under NaCl.
+#if !defined(OS_NACL)
+ // Do nothing if state is unchanged.
+ if (disconnect_on_suspend_ == disconnect_on_suspend)
+ return;
+
+ // Otherwise, start/stop observing if there's a PowerMonitor configured, as
+ // needed.
+ base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
+ if (!power_monitor)
+ return;
+ disconnect_on_suspend_ = disconnect_on_suspend;
+ if (disconnect_on_suspend_) {
+ power_monitor->AddObserver(this);
+ } else {
+ power_monitor->RemoveObserver(this);
+ }
+#endif // !defined(OS_NACL)
+}
+
int TCPClientSocket::Read(IOBuffer* buf,
int buf_len,
const CompletionCallback& callback) {
@@ -305,14 +347,18 @@ int TCPClientSocket::Write(IOBuffer* buf,
int buf_len,
const CompletionCallback& callback) {
DCHECK(!callback.is_null());
+ DCHECK(write_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::DidCompleteWrite, base::Unretained(this), callback);
+ CompletionCallback write_callback =
+ base::Bind(&TCPClientSocket::DidCompleteWrite, base::Unretained(this));
int result = socket_->Write(buf, buf_len, write_callback);
- if (result > 0)
+ if (result == ERR_IO_PENDING) {
+ write_callback_ = callback;
+ } else if (result > 0) {
use_history_.set_was_used_to_convey_data();
+ }
return result;
}
@@ -322,7 +368,7 @@ int TCPClientSocket::SetReceiveBufferSize(int32_t size) {
}
int TCPClientSocket::SetSendBufferSize(int32_t size) {
- return socket_->SetSendBufferSize(size);
+ return socket_->SetSendBufferSize(size);
}
bool TCPClientSocket::SetKeepAlive(bool enable, int delay) {
@@ -351,6 +397,38 @@ int64_t TCPClientSocket::GetTotalReceivedBytes() const {
return total_received_bytes_;
}
+void TCPClientSocket::OnSuspend() {
+ // If the socket is connected, or connecting, act as if current and future
+ // operations on the socket fail with ERR_NETWORK_IO_SUSPENDED, until the
+ // socket is reconnected.
+ // TODO(mmenke): This doesn't cover sockets created after OnSuspend runs,
+ // just before suspend mode starts. Would it make more sense to do this on
+ // resume?
+
+ if (next_connect_state_ != CONNECT_STATE_NONE) {
+ DidCompleteConnect(ERR_NETWORK_IO_SUSPENDED);
+ return;
+ }
+
+ // Nothing to do.
+ if (!IsConnected())
+ return;
+
+ Disconnect();
+
+ was_disconnected_on_suspend_ = true;
+
+ // Grab a weap pointer just in case calling read callback results in |this|
+ // being destroyed, or disconnected. In either case, should not run the write
+ // callback.
+ base::WeakPtr<TCPClientSocket> weak_this = weak_ptr_factory_.GetWeakPtr();
+
+ if (read_callback_)
+ DidCompleteRead(ERR_NETWORK_IO_SUSPENDED);
+ if (weak_this && write_callback_)
+ DidCompleteWrite(ERR_NETWORK_IO_SUSPENDED);
+}
+
void TCPClientSocket::DidCompleteConnect(int result) {
DCHECK_EQ(next_connect_state_, CONNECT_STATE_CONNECT_COMPLETE);
DCHECK_NE(result, ERR_IO_PENDING);
@@ -363,17 +441,17 @@ void TCPClientSocket::DidCompleteConnect(int result) {
}
}
-void TCPClientSocket::DidCompleteRead(const CompletionCallback& callback,
- int result) {
+void TCPClientSocket::DidCompleteRead(int result) {
+ DCHECK(!read_callback_.is_null());
if (result > 0)
total_received_bytes_ += result;
- DidCompleteReadWrite(callback, result);
+ DidCompleteReadWrite(base::ResetAndReturn(&read_callback_), result);
}
-void TCPClientSocket::DidCompleteWrite(const CompletionCallback& callback,
- int result) {
- DidCompleteReadWrite(callback, result);
+void TCPClientSocket::DidCompleteWrite(int result) {
+ DCHECK(!write_callback_.is_null());
+ DidCompleteReadWrite(base::ResetAndReturn(&write_callback_), result);
}
void TCPClientSocket::DidCompleteReadWrite(const CompletionCallback& callback,
« no previous file with comments | « net/socket/tcp_client_socket.h ('k') | net/socket/transport_client_socket_pool.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698