| 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..fda2186193ef6d1aefce1d124d7d41d98dfd6ade 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,
|
| + int 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),
|
| + connect_timeout_timer_(new base::OneShotTimer<CastSocket>) {
|
| DCHECK(net_log_);
|
| DCHECK(channel_auth_ == CHANNEL_AUTH_TYPE_SSL ||
|
| channel_auth_ == CHANNEL_AUTH_TYPE_SSL_VERIFIED);
|
| @@ -171,16 +174,32 @@ void CastSocket::Connect(const net::CompletionCallback& callback) {
|
| ready_state_ = READY_STATE_CONNECTING;
|
| connect_callback_ = callback;
|
| connect_state_ = CONN_STATE_TCP_CONNECT;
|
| + if (timeout_interval_ms_ > 0) {
|
| + connect_timeout_timer_->Start(
|
| + FROM_HERE,
|
| + base::TimeDelta::FromMilliseconds(timeout_interval_ms_),
|
| + base::Bind(&CastSocket::CancelConnect, AsWeakPtr()));
|
| + }
|
| DoConnectLoop(net::OK);
|
| }
|
|
|
| void CastSocket::PostTaskToStartConnectLoop(int result) {
|
| DCHECK(CalledOnValidThread());
|
| - base::MessageLoop::current()->PostTask(
|
| + task_tracker_.PostTask(
|
| + base::MessageLoop::current()->task_runner(),
|
| FROM_HERE,
|
| base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr(), result));
|
| }
|
|
|
| +void CastSocket::CancelConnect() {
|
| + DCHECK(CalledOnValidThread());
|
| + // Stop all pending connection setup tasks and report back to the client.
|
| + VLOG(1) << "Timeout while establishing a connection.";
|
| + task_tracker_.TryCancelAll();
|
| + CloseWithError(CHANNEL_ERROR_CONNECT_TIMEOUT);
|
| + 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
|
| @@ -229,8 +248,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) {
|
| + connect_timeout_timer_->Stop();
|
| DoConnectCallback(rv);
|
| + }
|
| }
|
|
|
| int CastSocket::DoTcpConnect() {
|
| @@ -282,7 +303,8 @@ int CastSocket::DoAuthChallengeSend() {
|
| // Post a task to send auth challenge so that DoWriteLoop is not nested inside
|
| // DoConnectLoop. This is not strictly necessary but keeps the write loop
|
| // code decoupled from connect loop code.
|
| - base::MessageLoop::current()->PostTask(
|
| + task_tracker_.PostTask(
|
| + base::MessageLoop::current()->task_runner(),
|
| FROM_HERE,
|
| base::Bind(&CastSocket::SendCastMessageInternal, AsWeakPtr(),
|
| challenge_message,
|
| @@ -316,8 +338,13 @@ int CastSocket::DoAuthChallengeReplyComplete(int result) {
|
|
|
| void CastSocket::DoConnectCallback(int result) {
|
| ready_state_ = (result == net::OK) ? READY_STATE_OPEN : READY_STATE_CLOSED;
|
| - error_state_ = (result == net::OK) ?
|
| - CHANNEL_ERROR_NONE : CHANNEL_ERROR_CONNECT_ERROR;
|
| + if (result == net::OK) {
|
| + error_state_ = CHANNEL_ERROR_NONE;
|
| + } else if (result == net::ERR_TIMED_OUT) {
|
| + error_state_ = CHANNEL_ERROR_CONNECT_TIMEOUT;
|
| + } else {
|
| + error_state_ = CHANNEL_ERROR_CONNECT_ERROR;
|
| + }
|
| if (result == net::OK) // Start the read loop
|
| PostTaskToStartReadLoop();
|
| base::ResetAndReturn(&connect_callback_).Run(result);
|
| @@ -496,7 +523,8 @@ int CastSocket::DoWriteError(int result) {
|
|
|
| void CastSocket::PostTaskToStartReadLoop() {
|
| DCHECK(CalledOnValidThread());
|
| - base::MessageLoop::current()->PostTask(
|
| + task_tracker_.PostTask(
|
| + base::MessageLoop::current()->task_runner(),
|
| FROM_HERE,
|
| base::Bind(&CastSocket::StartReadLoop, AsWeakPtr()));
|
| }
|
| @@ -682,7 +710,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());
|
| @@ -702,6 +730,10 @@ bool CastSocket::CalledOnValidThread() const {
|
| return thread_checker_.CalledOnValidThread();
|
| }
|
|
|
| +void CastSocket::InjectTimerForTesting(scoped_ptr<base::Timer> injected_timer) {
|
| + connect_timeout_timer_ = injected_timer.Pass();
|
| +}
|
| +
|
| CastSocket::MessageHeader::MessageHeader() : message_size(0) { }
|
|
|
| void CastSocket::MessageHeader::SetMessageSize(size_t size) {
|
|
|