Commit c31e1b57 authored by zea@chromium.org's avatar zea@chromium.org

[GCM] Add ConnectionListener support, and hook up to debug page

The ConnectionFactory::ConnectionListener gets informed of connection events,
including the actual ip endpoint with which a connection was established. This
will eventually be hooked up to app handlers to allow services to act on
connection changes. For now it just allows the debug page to more accurately
reflect the connection state.

BUG=377882

Review URL: https://codereview.chromium.org/317723004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@276800 0039d316-1c4b-4281-b951-d872f2087c98
parent 0ec86f59
...@@ -341,6 +341,7 @@ void GCMClientImpl::InitializeMCSClient( ...@@ -341,6 +341,7 @@ void GCMClientImpl::InitializeMCSClient(
network_session_, network_session_,
net_log_.net_log(), net_log_.net_log(),
&recorder_); &recorder_);
connection_factory_->SetConnectionListener(this);
mcs_client_ = internals_builder_->BuildMCSClient( mcs_client_ = internals_builder_->BuildMCSClient(
chrome_build_info_.version, chrome_build_info_.version,
clock_.get(), clock_.get(),
...@@ -711,8 +712,9 @@ GCMClient::GCMStatistics GCMClientImpl::GetStatistics() const { ...@@ -711,8 +712,9 @@ GCMClient::GCMStatistics GCMClientImpl::GetStatistics() const {
stats.is_recording = recorder_.is_recording(); stats.is_recording = recorder_.is_recording();
stats.gcm_client_state = GetStateString(); stats.gcm_client_state = GetStateString();
stats.connection_client_created = mcs_client_.get() != NULL; stats.connection_client_created = mcs_client_.get() != NULL;
if (connection_factory_.get())
stats.connection_state = connection_factory_->GetConnectionStateString();
if (mcs_client_.get()) { if (mcs_client_.get()) {
stats.connection_state = mcs_client_->GetStateString();
stats.send_queue_size = mcs_client_->GetSendQueueSize(); stats.send_queue_size = mcs_client_->GetSendQueueSize();
stats.resend_queue_size = mcs_client_->GetResendQueueSize(); stats.resend_queue_size = mcs_client_->GetResendQueueSize();
} }
...@@ -731,6 +733,17 @@ void GCMClientImpl::OnActivityRecorded() { ...@@ -731,6 +733,17 @@ void GCMClientImpl::OnActivityRecorded() {
delegate_->OnActivityRecorded(); delegate_->OnActivityRecorded();
} }
void GCMClientImpl::OnConnected(const GURL& current_server,
const net::IPEndPoint& ip_endpoint) {
// TODO(zea): inform GCMClient::Delegate and app handlers as well.
delegate_->OnActivityRecorded();
}
void GCMClientImpl::OnDisconnected() {
// TODO(zea): inform GCMClient::Delegate and app handlers as well.
delegate_->OnActivityRecorded();
}
void GCMClientImpl::OnMessageReceivedFromMCS(const gcm::MCSMessage& message) { void GCMClientImpl::OnMessageReceivedFromMCS(const gcm::MCSMessage& message) {
switch (message.tag()) { switch (message.tag()) {
case kLoginResponseTag: case kLoginResponseTag:
......
...@@ -74,12 +74,13 @@ class GCMInternalsBuilder { ...@@ -74,12 +74,13 @@ class GCMInternalsBuilder {
// Checkins. It also allows for registering user delegates that host // Checkins. It also allows for registering user delegates that host
// applications that send and receive messages. // applications that send and receive messages.
class GCMClientImpl class GCMClientImpl
: public GCMClient, public GCMStatsRecorder::Delegate { : public GCMClient, public GCMStatsRecorder::Delegate,
public ConnectionFactory::ConnectionListener {
public: public:
explicit GCMClientImpl(scoped_ptr<GCMInternalsBuilder> internals_builder); explicit GCMClientImpl(scoped_ptr<GCMInternalsBuilder> internals_builder);
virtual ~GCMClientImpl(); virtual ~GCMClientImpl();
// Overridden from GCMClient: // GCMClient implementation.
virtual void Initialize( virtual void Initialize(
const ChromeBuildInfo& chrome_build_info, const ChromeBuildInfo& chrome_build_info,
const base::FilePath& store_path, const base::FilePath& store_path,
...@@ -101,8 +102,15 @@ class GCMClientImpl ...@@ -101,8 +102,15 @@ class GCMClientImpl
virtual void SetRecording(bool recording) OVERRIDE; virtual void SetRecording(bool recording) OVERRIDE;
virtual void ClearActivityLogs() OVERRIDE; virtual void ClearActivityLogs() OVERRIDE;
virtual GCMStatistics GetStatistics() const OVERRIDE; virtual GCMStatistics GetStatistics() const OVERRIDE;
// GCMStatsRecorder::Delegate implemenation.
virtual void OnActivityRecorded() OVERRIDE; virtual void OnActivityRecorded() OVERRIDE;
// ConnectionFactory::ConnectionListener implementation.
virtual void OnConnected(const GURL& current_server,
const net::IPEndPoint& ip_endpoint) OVERRIDE;
virtual void OnDisconnected() OVERRIDE;
private: private:
// State representation of the GCMClient. // State representation of the GCMClient.
// Any change made to this enum should have corresponding change in the // Any change made to this enum should have corresponding change in the
......
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
namespace gcm { namespace gcm {
ConnectionFactory::ConnectionListener::ConnectionListener() {}
ConnectionFactory::ConnectionListener::~ConnectionListener() {}
ConnectionFactory::ConnectionFactory() {} ConnectionFactory::ConnectionFactory() {}
ConnectionFactory::~ConnectionFactory() {} ConnectionFactory::~ConnectionFactory() {}
......
...@@ -5,10 +5,18 @@ ...@@ -5,10 +5,18 @@
#ifndef GOOGLE_APIS_GCM_ENGINE_CONNECTION_FACTORY_H_ #ifndef GOOGLE_APIS_GCM_ENGINE_CONNECTION_FACTORY_H_
#define GOOGLE_APIS_GCM_ENGINE_CONNECTION_FACTORY_H_ #define GOOGLE_APIS_GCM_ENGINE_CONNECTION_FACTORY_H_
#include <string>
#include "base/time/time.h" #include "base/time/time.h"
#include "google_apis/gcm/base/gcm_export.h" #include "google_apis/gcm/base/gcm_export.h"
#include "google_apis/gcm/engine/connection_handler.h" #include "google_apis/gcm/engine/connection_handler.h"
class GURL;
namespace net {
class IPEndPoint;
}
namespace mcs_proto { namespace mcs_proto {
class LoginRequest; class LoginRequest;
} }
...@@ -36,6 +44,22 @@ class GCM_EXPORT ConnectionFactory { ...@@ -36,6 +44,22 @@ class GCM_EXPORT ConnectionFactory {
CONNECTION_RESET_COUNT, CONNECTION_RESET_COUNT,
}; };
// Listener interface to be notified of endpoint connection events.
class GCM_EXPORT ConnectionListener {
public:
ConnectionListener();
virtual ~ConnectionListener();
// Notifies the listener that GCM has performed a handshake with and is now
// actively connected to |current_server|. |ip_endpoint| is the resolved
// ip address/port through which the connection is being made.
virtual void OnConnected(const GURL& current_server,
const net::IPEndPoint& ip_endpoint) = 0;
// Notifies the listener that the connection has been interrupted.
virtual void OnDisconnected() = 0;
};
ConnectionFactory(); ConnectionFactory();
virtual ~ConnectionFactory(); virtual ~ConnectionFactory();
...@@ -66,6 +90,9 @@ class GCM_EXPORT ConnectionFactory { ...@@ -66,6 +90,9 @@ class GCM_EXPORT ConnectionFactory {
// connection. // connection.
virtual bool IsEndpointReachable() const = 0; virtual bool IsEndpointReachable() const = 0;
// Returns a debug string describing the connection state.
virtual std::string GetConnectionStateString() const = 0;
// If in backoff, the time at which the next retry will be made. Otherwise, // If in backoff, the time at which the next retry will be made. Otherwise,
// a null time, indicating either no attempt to connect has been made or no // a null time, indicating either no attempt to connect has been made or no
// backoff is in progress. // backoff is in progress.
...@@ -76,6 +103,11 @@ class GCM_EXPORT ConnectionFactory { ...@@ -76,6 +103,11 @@ class GCM_EXPORT ConnectionFactory {
// If the last connection was made within kConnectionResetWindowSecs, the old // If the last connection was made within kConnectionResetWindowSecs, the old
// backoff is restored, else a new backoff kicks off. // backoff is restored, else a new backoff kicks off.
virtual void SignalConnectionReset(ConnectionResetReason reason) = 0; virtual void SignalConnectionReset(ConnectionResetReason reason) = 0;
// Sets the current connection listener. Only one listener is supported at a
// time, and the listener must either outlive the connection factory or
// call SetConnectionListener(NULL) upon destruction.
virtual void SetConnectionListener(ConnectionListener* listener) = 0;
}; };
} // namespace gcm } // namespace gcm
......
...@@ -59,6 +59,7 @@ ConnectionFactoryImpl::ConnectionFactoryImpl( ...@@ -59,6 +59,7 @@ ConnectionFactoryImpl::ConnectionFactoryImpl(
waiting_for_backoff_(false), waiting_for_backoff_(false),
logging_in_(false), logging_in_(false),
recorder_(recorder), recorder_(recorder),
listener_(NULL),
weak_ptr_factory_(this) { weak_ptr_factory_(this) {
DCHECK_GE(mcs_endpoints_.size(), 1U); DCHECK_GE(mcs_endpoints_.size(), 1U);
} }
...@@ -140,6 +141,18 @@ bool ConnectionFactoryImpl::IsEndpointReachable() const { ...@@ -140,6 +141,18 @@ bool ConnectionFactoryImpl::IsEndpointReachable() const {
return connection_handler_ && connection_handler_->CanSendMessage(); return connection_handler_ && connection_handler_->CanSendMessage();
} }
std::string ConnectionFactoryImpl::GetConnectionStateString() const {
if (IsEndpointReachable())
return "CONNECTED";
if (logging_in_)
return "LOGGING IN";
if (connecting_)
return "CONNECTING";
if (waiting_for_backoff_)
return "WAITING FOR BACKOFF";
return "NOT CONNECTED";
}
void ConnectionFactoryImpl::SignalConnectionReset( void ConnectionFactoryImpl::SignalConnectionReset(
ConnectionResetReason reason) { ConnectionResetReason reason) {
// A failure can trigger multiple resets, so no need to do anything if a // A failure can trigger multiple resets, so no need to do anything if a
...@@ -149,6 +162,9 @@ void ConnectionFactoryImpl::SignalConnectionReset( ...@@ -149,6 +162,9 @@ void ConnectionFactoryImpl::SignalConnectionReset(
return; return;
} }
if (listener_)
listener_->OnDisconnected();
UMA_HISTOGRAM_ENUMERATION("GCM.ConnectionResetReason", UMA_HISTOGRAM_ENUMERATION("GCM.ConnectionResetReason",
reason, reason,
CONNECTION_RESET_COUNT); CONNECTION_RESET_COUNT);
...@@ -202,6 +218,11 @@ void ConnectionFactoryImpl::SignalConnectionReset( ...@@ -202,6 +218,11 @@ void ConnectionFactoryImpl::SignalConnectionReset(
Connect(); Connect();
} }
void ConnectionFactoryImpl::SetConnectionListener(
ConnectionListener* listener) {
listener_ = listener;
}
base::TimeTicks ConnectionFactoryImpl::NextRetryAttempt() const { base::TimeTicks ConnectionFactoryImpl::NextRetryAttempt() const {
if (!backoff_entry_) if (!backoff_entry_)
return base::TimeTicks(); return base::TimeTicks();
...@@ -234,6 +255,18 @@ GURL ConnectionFactoryImpl::GetCurrentEndpoint() const { ...@@ -234,6 +255,18 @@ GURL ConnectionFactoryImpl::GetCurrentEndpoint() const {
return mcs_endpoints_[next_endpoint_]; return mcs_endpoints_[next_endpoint_];
} }
net::IPEndPoint ConnectionFactoryImpl::GetPeerIP() {
if (!socket_handle_.socket())
return net::IPEndPoint();
net::IPEndPoint ip_endpoint;
int result = socket_handle_.socket()->GetPeerAddress(&ip_endpoint);
if (result != net::OK)
return net::IPEndPoint();
return ip_endpoint;
}
void ConnectionFactoryImpl::ConnectImpl() { void ConnectionFactoryImpl::ConnectImpl() {
DCHECK(!IsEndpointReachable()); DCHECK(!IsEndpointReachable());
DCHECK(!socket_handle_.socket()); DCHECK(!socket_handle_.socket());
...@@ -348,6 +381,9 @@ void ConnectionFactoryImpl::ConnectionHandlerCallback(int result) { ...@@ -348,6 +381,9 @@ void ConnectionFactoryImpl::ConnectionHandlerCallback(int result) {
previous_backoff_.swap(backoff_entry_); previous_backoff_.swap(backoff_entry_);
backoff_entry_->Reset(); backoff_entry_->Reset();
logging_in_ = false; logging_in_ = false;
if (listener_)
listener_->OnConnected(GetCurrentEndpoint(), GetPeerIP());
} }
// This has largely been copied from // This has largely been copied from
......
...@@ -48,8 +48,10 @@ class GCM_EXPORT ConnectionFactoryImpl : ...@@ -48,8 +48,10 @@ class GCM_EXPORT ConnectionFactoryImpl :
virtual ConnectionHandler* GetConnectionHandler() const OVERRIDE; virtual ConnectionHandler* GetConnectionHandler() const OVERRIDE;
virtual void Connect() OVERRIDE; virtual void Connect() OVERRIDE;
virtual bool IsEndpointReachable() const OVERRIDE; virtual bool IsEndpointReachable() const OVERRIDE;
virtual std::string GetConnectionStateString() const OVERRIDE;
virtual base::TimeTicks NextRetryAttempt() const OVERRIDE; virtual base::TimeTicks NextRetryAttempt() const OVERRIDE;
virtual void SignalConnectionReset(ConnectionResetReason reason) OVERRIDE; virtual void SignalConnectionReset(ConnectionResetReason reason) OVERRIDE;
virtual void SetConnectionListener(ConnectionListener* listener) OVERRIDE;
// NetworkChangeNotifier observer implementations. // NetworkChangeNotifier observer implementations.
virtual void OnConnectionTypeChanged( virtual void OnConnectionTypeChanged(
...@@ -61,6 +63,10 @@ class GCM_EXPORT ConnectionFactoryImpl : ...@@ -61,6 +63,10 @@ class GCM_EXPORT ConnectionFactoryImpl :
// attempt will be made. // attempt will be made.
GURL GetCurrentEndpoint() const; GURL GetCurrentEndpoint() const;
// Returns the IPEndpoint to which the factory is currently connected. If no
// connection is active, returns an empty IPEndpoint.
net::IPEndPoint GetPeerIP();
protected: protected:
// Implementation of Connect(..). If not in backoff, uses |login_request_| // Implementation of Connect(..). If not in backoff, uses |login_request_|
// in attempting a connection/handshake. On connection/handshake failure, goes // in attempting a connection/handshake. On connection/handshake failure, goes
...@@ -161,6 +167,9 @@ class GCM_EXPORT ConnectionFactoryImpl : ...@@ -161,6 +167,9 @@ class GCM_EXPORT ConnectionFactoryImpl :
// Recorder that records GCM activities for debugging purpose. Not owned. // Recorder that records GCM activities for debugging purpose. Not owned.
GCMStatsRecorder* recorder_; GCMStatsRecorder* recorder_;
// Listener for connection change events.
ConnectionListener* listener_;
base::WeakPtrFactory<ConnectionFactoryImpl> weak_ptr_factory_; base::WeakPtrFactory<ConnectionFactoryImpl> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ConnectionFactoryImpl); DISALLOW_COPY_AND_ASSIGN(ConnectionFactoryImpl);
......
...@@ -254,27 +254,40 @@ void TestConnectionFactoryImpl::SetDelayLogin(bool delay_login) { ...@@ -254,27 +254,40 @@ void TestConnectionFactoryImpl::SetDelayLogin(bool delay_login) {
fake_handler_->set_fail_login(delay_login_); fake_handler_->set_fail_login(delay_login_);
} }
class ConnectionFactoryImplTest : public testing::Test { } // namespace
class ConnectionFactoryImplTest
: public testing::Test,
public ConnectionFactory::ConnectionListener {
public: public:
ConnectionFactoryImplTest(); ConnectionFactoryImplTest();
virtual ~ConnectionFactoryImplTest(); virtual ~ConnectionFactoryImplTest();
TestConnectionFactoryImpl* factory() { return &factory_; } TestConnectionFactoryImpl* factory() { return &factory_; }
GURL& connected_server() { return connected_server_; }
void WaitForConnections(); void WaitForConnections();
// ConnectionFactory::ConnectionListener
virtual void OnConnected(const GURL& current_server,
const net::IPEndPoint& ip_endpoint) OVERRIDE;
virtual void OnDisconnected() OVERRIDE;
private: private:
void ConnectionsComplete(); void ConnectionsComplete();
TestConnectionFactoryImpl factory_; TestConnectionFactoryImpl factory_;
base::MessageLoop message_loop_; base::MessageLoop message_loop_;
scoped_ptr<base::RunLoop> run_loop_; scoped_ptr<base::RunLoop> run_loop_;
GURL connected_server_;
}; };
ConnectionFactoryImplTest::ConnectionFactoryImplTest() ConnectionFactoryImplTest::ConnectionFactoryImplTest()
: factory_(base::Bind(&ConnectionFactoryImplTest::ConnectionsComplete, : factory_(base::Bind(&ConnectionFactoryImplTest::ConnectionsComplete,
base::Unretained(this))), base::Unretained(this))),
run_loop_(new base::RunLoop()) { run_loop_(new base::RunLoop()) {
factory()->SetConnectionListener(this);
factory()->Initialize( factory()->Initialize(
ConnectionFactory::BuildLoginRequestCallback(), ConnectionFactory::BuildLoginRequestCallback(),
ConnectionHandler::ProtoReceivedCallback(), ConnectionHandler::ProtoReceivedCallback(),
...@@ -293,11 +306,22 @@ void ConnectionFactoryImplTest::ConnectionsComplete() { ...@@ -293,11 +306,22 @@ void ConnectionFactoryImplTest::ConnectionsComplete() {
run_loop_->Quit(); run_loop_->Quit();
} }
void ConnectionFactoryImplTest::OnConnected(
const GURL& current_server,
const net::IPEndPoint& ip_endpoint) {
connected_server_ = current_server;
}
void ConnectionFactoryImplTest::OnDisconnected() {
connected_server_ = GURL();
}
// Verify building a connection handler works. // Verify building a connection handler works.
TEST_F(ConnectionFactoryImplTest, Initialize) { TEST_F(ConnectionFactoryImplTest, Initialize) {
ConnectionHandler* handler = factory()->GetConnectionHandler(); ConnectionHandler* handler = factory()->GetConnectionHandler();
ASSERT_TRUE(handler); ASSERT_TRUE(handler);
EXPECT_FALSE(factory()->IsEndpointReachable()); EXPECT_FALSE(factory()->IsEndpointReachable());
EXPECT_FALSE(connected_server().is_valid());
} }
// An initial successful connection should not result in backoff. // An initial successful connection should not result in backoff.
...@@ -307,6 +331,7 @@ TEST_F(ConnectionFactoryImplTest, ConnectSuccess) { ...@@ -307,6 +331,7 @@ TEST_F(ConnectionFactoryImplTest, ConnectSuccess) {
EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
EXPECT_EQ(factory()->GetCurrentEndpoint(), BuildEndpoints()[0]); EXPECT_EQ(factory()->GetCurrentEndpoint(), BuildEndpoints()[0]);
EXPECT_TRUE(factory()->IsEndpointReachable()); EXPECT_TRUE(factory()->IsEndpointReachable());
EXPECT_TRUE(connected_server().is_valid());
} }
// A connection failure should result in backoff, and attempting the fallback // A connection failure should result in backoff, and attempting the fallback
...@@ -317,6 +342,7 @@ TEST_F(ConnectionFactoryImplTest, ConnectFail) { ...@@ -317,6 +342,7 @@ TEST_F(ConnectionFactoryImplTest, ConnectFail) {
EXPECT_FALSE(factory()->NextRetryAttempt().is_null()); EXPECT_FALSE(factory()->NextRetryAttempt().is_null());
EXPECT_EQ(factory()->GetCurrentEndpoint(), BuildEndpoints()[1]); EXPECT_EQ(factory()->GetCurrentEndpoint(), BuildEndpoints()[1]);
EXPECT_FALSE(factory()->IsEndpointReachable()); EXPECT_FALSE(factory()->IsEndpointReachable());
EXPECT_FALSE(connected_server().is_valid());
} }
// A connection success after a failure should reset backoff. // A connection success after a failure should reset backoff.
...@@ -326,6 +352,7 @@ TEST_F(ConnectionFactoryImplTest, FailThenSucceed) { ...@@ -326,6 +352,7 @@ TEST_F(ConnectionFactoryImplTest, FailThenSucceed) {
factory()->Connect(); factory()->Connect();
WaitForConnections(); WaitForConnections();
EXPECT_FALSE(factory()->IsEndpointReachable()); EXPECT_FALSE(factory()->IsEndpointReachable());
EXPECT_FALSE(connected_server().is_valid());
base::TimeTicks retry_time = factory()->NextRetryAttempt(); base::TimeTicks retry_time = factory()->NextRetryAttempt();
EXPECT_FALSE(retry_time.is_null()); EXPECT_FALSE(retry_time.is_null());
EXPECT_GE((retry_time - connect_time).InMilliseconds(), CalculateBackoff(1)); EXPECT_GE((retry_time - connect_time).InMilliseconds(), CalculateBackoff(1));
...@@ -333,6 +360,7 @@ TEST_F(ConnectionFactoryImplTest, FailThenSucceed) { ...@@ -333,6 +360,7 @@ TEST_F(ConnectionFactoryImplTest, FailThenSucceed) {
WaitForConnections(); WaitForConnections();
EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
EXPECT_TRUE(factory()->IsEndpointReachable()); EXPECT_TRUE(factory()->IsEndpointReachable());
EXPECT_TRUE(connected_server().is_valid());
} }
// Multiple connection failures should retry with an exponentially increasing // Multiple connection failures should retry with an exponentially increasing
...@@ -346,6 +374,7 @@ TEST_F(ConnectionFactoryImplTest, MultipleFailuresThenSucceed) { ...@@ -346,6 +374,7 @@ TEST_F(ConnectionFactoryImplTest, MultipleFailuresThenSucceed) {
factory()->Connect(); factory()->Connect();
WaitForConnections(); WaitForConnections();
EXPECT_FALSE(factory()->IsEndpointReachable()); EXPECT_FALSE(factory()->IsEndpointReachable());
EXPECT_FALSE(connected_server().is_valid());
base::TimeTicks retry_time = factory()->NextRetryAttempt(); base::TimeTicks retry_time = factory()->NextRetryAttempt();
EXPECT_FALSE(retry_time.is_null()); EXPECT_FALSE(retry_time.is_null());
EXPECT_GE((retry_time - connect_time).InMilliseconds(), EXPECT_GE((retry_time - connect_time).InMilliseconds(),
...@@ -355,6 +384,7 @@ TEST_F(ConnectionFactoryImplTest, MultipleFailuresThenSucceed) { ...@@ -355,6 +384,7 @@ TEST_F(ConnectionFactoryImplTest, MultipleFailuresThenSucceed) {
WaitForConnections(); WaitForConnections();
EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
EXPECT_TRUE(factory()->IsEndpointReachable()); EXPECT_TRUE(factory()->IsEndpointReachable());
EXPECT_TRUE(connected_server().is_valid());
} }
// IP events should trigger canary connections. // IP events should trigger canary connections.
...@@ -408,12 +438,15 @@ TEST_F(ConnectionFactoryImplTest, CanarySucceedsThenDisconnects) { ...@@ -408,12 +438,15 @@ TEST_F(ConnectionFactoryImplTest, CanarySucceedsThenDisconnects) {
net::NetworkChangeNotifier::CONNECTION_WIFI); net::NetworkChangeNotifier::CONNECTION_WIFI);
WaitForConnections(); WaitForConnections();
EXPECT_TRUE(factory()->IsEndpointReachable()); EXPECT_TRUE(factory()->IsEndpointReachable());
EXPECT_TRUE(connected_server().is_valid());
factory()->SetConnectResult(net::OK); factory()->SetConnectResult(net::OK);
factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE); factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
EXPECT_FALSE(factory()->IsEndpointReachable()); EXPECT_FALSE(factory()->IsEndpointReachable());
EXPECT_FALSE(connected_server().is_valid());
WaitForConnections(); WaitForConnections();
EXPECT_TRUE(factory()->IsEndpointReachable()); EXPECT_TRUE(factory()->IsEndpointReachable());
EXPECT_TRUE(connected_server().is_valid());
} }
// Verify that if a canary connects, but hasn't finished the handshake, a // Verify that if a canary connects, but hasn't finished the handshake, a
...@@ -486,6 +519,7 @@ TEST_F(ConnectionFactoryImplTest, SignalResetRestoresBackoff) { ...@@ -486,6 +519,7 @@ TEST_F(ConnectionFactoryImplTest, SignalResetRestoresBackoff) {
factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE); factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
EXPECT_FALSE(factory()->IsEndpointReachable()); EXPECT_FALSE(factory()->IsEndpointReachable());
EXPECT_FALSE(connected_server().is_valid());
EXPECT_NE(retry_time, factory()->NextRetryAttempt()); EXPECT_NE(retry_time, factory()->NextRetryAttempt());
retry_time = factory()->NextRetryAttempt(); retry_time = factory()->NextRetryAttempt();
EXPECT_FALSE(retry_time.is_null()); EXPECT_FALSE(retry_time.is_null());
...@@ -499,6 +533,7 @@ TEST_F(ConnectionFactoryImplTest, SignalResetRestoresBackoff) { ...@@ -499,6 +533,7 @@ TEST_F(ConnectionFactoryImplTest, SignalResetRestoresBackoff) {
WaitForConnections(); WaitForConnections();
EXPECT_TRUE(factory()->NextRetryAttempt().is_null()); EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
EXPECT_TRUE(factory()->IsEndpointReachable()); EXPECT_TRUE(factory()->IsEndpointReachable());
EXPECT_TRUE(connected_server().is_valid());
factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE); factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
EXPECT_NE(retry_time, factory()->NextRetryAttempt()); EXPECT_NE(retry_time, factory()->NextRetryAttempt());
...@@ -507,7 +542,7 @@ TEST_F(ConnectionFactoryImplTest, SignalResetRestoresBackoff) { ...@@ -507,7 +542,7 @@ TEST_F(ConnectionFactoryImplTest, SignalResetRestoresBackoff) {
EXPECT_GE((retry_time - connect_time).InMilliseconds(), EXPECT_GE((retry_time - connect_time).InMilliseconds(),
CalculateBackoff(3)); CalculateBackoff(3));
EXPECT_FALSE(factory()->IsEndpointReachable()); EXPECT_FALSE(factory()->IsEndpointReachable());
EXPECT_FALSE(connected_server().is_valid());
} }
} // namespace
} // namespace gcm } // namespace gcm
...@@ -41,6 +41,10 @@ bool FakeConnectionFactory::IsEndpointReachable() const { ...@@ -41,6 +41,10 @@ bool FakeConnectionFactory::IsEndpointReachable() const {
return connection_handler_.get() && connection_handler_->CanSendMessage(); return connection_handler_.get() && connection_handler_->CanSendMessage();
} }
std::string FakeConnectionFactory::GetConnectionStateString() const {
return "";
}
base::TimeTicks FakeConnectionFactory::NextRetryAttempt() const { base::TimeTicks FakeConnectionFactory::NextRetryAttempt() const {
return base::TimeTicks(); return base::TimeTicks();
} }
...@@ -53,4 +57,8 @@ void FakeConnectionFactory::SignalConnectionReset( ...@@ -53,4 +57,8 @@ void FakeConnectionFactory::SignalConnectionReset(
reconnect_pending_ = true; reconnect_pending_ = true;
} }
void FakeConnectionFactory::SetConnectionListener(
ConnectionListener* listener) {
}
} // namespace gcm } // namespace gcm
...@@ -27,8 +27,10 @@ class FakeConnectionFactory : public ConnectionFactory { ...@@ -27,8 +27,10 @@ class FakeConnectionFactory : public ConnectionFactory {
virtual ConnectionHandler* GetConnectionHandler() const OVERRIDE; virtual ConnectionHandler* GetConnectionHandler() const OVERRIDE;
virtual void Connect() OVERRIDE; virtual void Connect() OVERRIDE;
virtual bool IsEndpointReachable() const OVERRIDE; virtual bool IsEndpointReachable() const OVERRIDE;
virtual std::string GetConnectionStateString() const OVERRIDE;
virtual base::TimeTicks NextRetryAttempt() const OVERRIDE; virtual base::TimeTicks NextRetryAttempt() const OVERRIDE;
virtual void SignalConnectionReset(ConnectionResetReason reason) OVERRIDE; virtual void SignalConnectionReset(ConnectionResetReason reason) OVERRIDE;
virtual void SetConnectionListener(ConnectionListener* listener) OVERRIDE;
// Whether a connection reset has been triggered and is yet to run. // Whether a connection reset has been triggered and is yet to run.
bool reconnect_pending() const { return reconnect_pending_; } bool reconnect_pending() const { return reconnect_pending_; }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment