Index: chrome/browser/extensions/api/cast_channel/cast_socket.cc |
diff --git a/chrome/browser/extensions/api/cast_channel/cast_socket.cc b/chrome/browser/extensions/api/cast_channel/cast_socket.cc |
index 6130d92e18755dc825880177b785f7536baf5afc..04fd7343313fb5559fe989e81ea8eb67f3b0973b 100644 |
--- a/chrome/browser/extensions/api/cast_channel/cast_socket.cc |
+++ b/chrome/browser/extensions/api/cast_channel/cast_socket.cc |
@@ -67,7 +67,8 @@ CastSocket::CastSocket(const std::string& owner_extension_id, |
const net::IPEndPoint& ip_endpoint, |
ChannelAuthType channel_auth, |
CastSocket::Delegate* delegate, |
- net::NetLog* net_log) : |
+ net::NetLog* net_log, |
+ int64 timeout_ms) : |
ApiResource(owner_extension_id), |
channel_id_(0), |
ip_endpoint_(ip_endpoint), |
@@ -80,7 +81,9 @@ CastSocket::CastSocket(const std::string& owner_extension_id, |
write_state_(WRITE_STATE_NONE), |
read_state_(READ_STATE_NONE), |
error_state_(CHANNEL_ERROR_NONE), |
- ready_state_(READY_STATE_NONE) { |
+ ready_state_(READY_STATE_NONE), |
+ timeout_interval_ms_(timeout_ms), |
+ timed_out_(false) { |
DCHECK(net_log_); |
DCHECK(channel_auth_ == CHANNEL_AUTH_TYPE_SSL || |
channel_auth_ == CHANNEL_AUTH_TYPE_SSL_VERIFIED); |
@@ -171,6 +174,13 @@ void CastSocket::Connect(const net::CompletionCallback& callback) { |
ready_state_ = READY_STATE_CONNECTING; |
connect_callback_ = callback; |
connect_state_ = CONN_STATE_TCP_CONNECT; |
+ |
+ timeout_callback_.Reset(base::Bind(&CastSocket::Timeout, AsWeakPtr())); |
+ base::MessageLoop::current()->PostDelayedTask( |
+ FROM_HERE, |
+ timeout_callback_.callback(), |
+ base::TimeDelta::FromMilliseconds(timeout_interval_ms_)); |
+ |
DoConnectLoop(net::OK); |
} |
@@ -181,11 +191,23 @@ void CastSocket::PostTaskToStartConnectLoop(int result) { |
base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr(), result)); |
} |
+void CastSocket::Timeout() { |
+ VLOG(1) << "Timeout while establishing connection."; |
+ CloseWithError(CHANNEL_ERROR_CONNECT_ERROR); |
mark a. foltz
2014/07/15 22:18:15
I would be in favor of adding an error enum CHANNE
Kevin M
2014/07/16 22:59:41
Done.
|
+ timed_out_ = true; |
mark a. foltz
2014/07/15 22:18:15
Is timed_out_ used anywhere?
Kevin M
2014/07/16 22:59:41
No, I ended up using the error state instead. Remo
|
+ DoConnectCallback(net::ERR_TIMED_OUT); |
+} |
+ |
// This method performs the state machine transitions for connection flow. |
// There are two entry points to this method: |
// 1. Connect method: this starts the flow |
// 2. Callback from network operations that finish asynchronously |
void CastSocket::DoConnectLoop(int result) { |
+ if (error_state_ != CHANNEL_ERROR_NONE) { |
+ VLOG(1) << "Connection timeout; DoConnectLoop aborted."; |
mark a. foltz
2014/07/15 22:18:15
Is this the only possible way error_state_ can be
Kevin M
2014/07/16 22:59:41
Good idea, done.
|
+ return; |
+ } |
+ |
// Network operations can either finish synchronously or asynchronously. |
// This method executes the state machine transitions in a loop so that |
// correct state transitions happen even when network operations finish |
@@ -229,8 +251,10 @@ void CastSocket::DoConnectLoop(int result) { |
// b. The Do* method called did not change state |
// Connect loop is finished: if there is no pending IO invoke the callback. |
- if (rv != net::ERR_IO_PENDING) |
+ if (rv != net::ERR_IO_PENDING) { |
+ timeout_callback_.Cancel(); |
DoConnectCallback(rv); |
+ } |
} |
int CastSocket::DoTcpConnect() { |
@@ -682,7 +706,7 @@ bool CastSocket::Serialize(const CastMessage& message_proto, |
header.SetMessageSize(message_size); |
header.PrependToString(message_data); |
return true; |
-}; |
+} |
void CastSocket::CloseWithError(ChannelError error) { |
DCHECK(CalledOnValidThread()); |