summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-03 20:07:40 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-03 20:07:40 +0000
commitf6bca1f6a634474c59cdb8a6b4a87a89c1451837 (patch)
tree7fd190788bbd316ce8ca24dc4d3d45ef4849b46b
parente2ceaa490a05d70fbac05b8ecef71469dc868eb4 (diff)
downloadchromium_src-f6bca1f6a634474c59cdb8a6b4a87a89c1451837.zip
chromium_src-f6bca1f6a634474c59cdb8a6b4a87a89c1451837.tar.gz
chromium_src-f6bca1f6a634474c59cdb8a6b4a87a89c1451837.tar.bz2
Add HostObserverInterface and decouple HeartbeatSender and ChromotingHost.
BUG=None TEST=Everything still works. Review URL: http://codereview.chromium.org/6911024 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@83951 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/service/remoting/chromoting_host_manager.cc11
-rw-r--r--remoting/host/chromoting_host.cc64
-rw-r--r--remoting/host/chromoting_host.h12
-rw-r--r--remoting/host/heartbeat_sender.cc76
-rw-r--r--remoting/host/heartbeat_sender.h31
-rw-r--r--remoting/host/heartbeat_sender_unittest.cc27
-rw-r--r--remoting/host/host_status_observer.h34
-rw-r--r--remoting/host/simple_host_process.cc8
-rw-r--r--remoting/jingle_glue/jingle_client.h1
-rw-r--r--remoting/jingle_glue/jingle_thread.h2
-rw-r--r--remoting/remoting.gyp1
11 files changed, 155 insertions, 112 deletions
diff --git a/chrome/service/remoting/chromoting_host_manager.cc b/chrome/service/remoting/chromoting_host_manager.cc
index 12b2adc..39fdd70 100644
--- a/chrome/service/remoting/chromoting_host_manager.cc
+++ b/chrome/service/remoting/chromoting_host_manager.cc
@@ -11,6 +11,8 @@
#include "net/base/net_util.h"
#include "remoting/base/constants.h"
#include "remoting/host/chromoting_host_context.h"
+#include "remoting/host/heartbeat_sender.h"
+#include "remoting/host/host_key_pair.h"
#include "remoting/host/json_host_config.h"
namespace remoting {
@@ -179,6 +181,15 @@ void ChromotingHostManager::Start() {
chromoting_host_ = remoting::ChromotingHost::Create(chromoting_context_.get(),
chromoting_config_);
+ // Initialize HeartbeatSender.
+ scoped_refptr<remoting::HeartbeatSender> heartbeat_sender =
+ new remoting::HeartbeatSender(chromoting_context_->network_message_loop(),
+ chromoting_config_);
+ if (!heartbeat_sender->Init())
+ LOG(ERROR) << "Failed to initialize heartbeat sender.";
+ chromoting_host_->AddStatusObserver(heartbeat_sender);
+
+
// Then start the chromoting host.
// When ChromotingHost is shutdown because of failure or a request that
// we made OnChromotingShutdown() is calls.
diff --git a/remoting/host/chromoting_host.cc b/remoting/host/chromoting_host.cc
index ea55f6d..6ca4b70 100644
--- a/remoting/host/chromoting_host.cc
+++ b/remoting/host/chromoting_host.cc
@@ -107,14 +107,6 @@ void ChromotingHost::Start(Task* shutdown_task) {
NULL,
this);
jingle_client_->Init();
-
- heartbeat_sender_ =
- new HeartbeatSender(context_->jingle_thread()->message_loop(),
- jingle_client_.get(), config_);
- if (!heartbeat_sender_->Init()) {
- LOG(ERROR) << "Failed to initialize HeartbeatSender.";
- return;
- }
}
// This method is called when we need to destroy the host process.
@@ -147,9 +139,10 @@ void ChromotingHost::Shutdown() {
}
clients_.clear();
- // Stop the heartbeat sender.
- if (heartbeat_sender_) {
- heartbeat_sender_->Stop();
+ // Notify observers.
+ for (StatusObserverList::iterator it = status_observers_.begin();
+ it != status_observers_.end(); ++it) {
+ (*it)->OnShutdown();
}
// Stop chromotocol session manager.
@@ -171,6 +164,12 @@ void ChromotingHost::Shutdown() {
}
}
+void ChromotingHost::AddStatusObserver(
+ const scoped_refptr<HostStatusObserver>& observer) {
+ DCHECK_EQ(state_, kInitial);
+ status_observers_.push_back(observer);
+}
+
////////////////////////////////////////////////////////////////////////////
// protocol::ConnectionToClient::EventHandler implementations
void ChromotingHost::OnConnectionOpened(ConnectionToClient* connection) {
@@ -203,35 +202,39 @@ void ChromotingHost::OnConnectionFailed(ConnectionToClient* connection) {
void ChromotingHost::OnStateChange(JingleClient* jingle_client,
JingleClient::State state) {
if (state == JingleClient::CONNECTED) {
+ std::string jid = jingle_client->GetFullJid();
+
DCHECK_EQ(jingle_client_.get(), jingle_client);
- VLOG(1) << "Host connected as " << jingle_client->GetFullJid();
+ VLOG(1) << "Host connected as " << jid;
// Create and start session manager.
protocol::JingleSessionManager* server =
new protocol::JingleSessionManager(context_->jingle_thread());
+ // TODO(ajwong): Make this a command switch when we're more stable.
+ server->set_allow_local_ips(true);
// Assign key and certificate to server.
HostKeyPair key_pair;
CHECK(key_pair.Load(config_))
<< "Failed to load server authentication data";
- // TODO(ajwong): Make this a command switch when we're more stable.
- server->set_allow_local_ips(true);
- server->Init(jingle_client->GetFullJid(),
- jingle_client->session_manager(),
+ server->Init(jid, jingle_client->session_manager(),
NewCallback(this, &ChromotingHost::OnNewClientSession),
- key_pair.CopyPrivateKey(),
- key_pair.GenerateCertificate());
+ key_pair.CopyPrivateKey(), key_pair.GenerateCertificate());
session_manager_ = server;
- // Start heartbeating.
- heartbeat_sender_->Start();
+
+ for (StatusObserverList::iterator it = status_observers_.begin();
+ it != status_observers_.end(); ++it) {
+ (*it)->OnSignallingConnected(signal_strategy_.get(), jid);
+ }
} else if (state == JingleClient::CLOSED) {
VLOG(1) << "Host disconnected from talk network.";
- // Stop heartbeating.
- heartbeat_sender_->Stop();
-
+ for (StatusObserverList::iterator it = status_observers_.begin();
+ it != status_observers_.end(); ++it) {
+ (*it)->OnSignallingDisconnected();
+ }
// TODO(sergeyu): We should try reconnecting here instead of terminating
// the host.
Shutdown();
@@ -310,8 +313,9 @@ void ChromotingHost::OnClientDisconnected(ConnectionToClient* connection) {
DCHECK_EQ(context_->main_message_loop(), MessageLoop::current());
// Find the client session corresponding to the given connection.
- std::vector<scoped_refptr<ClientSession> >::iterator client;
- for (client = clients_.begin(); client != clients_.end(); ++client) {
+ ClientList::iterator client;
+ for (client = clients_.begin(); client != clients_.end();
+ ++client) {
if (client->get()->connection() == connection)
break;
}
@@ -366,8 +370,8 @@ std::string ChromotingHost::GenerateHostAuthToken(
}
bool ChromotingHost::HasAuthenticatedClients() const {
- std::vector<scoped_refptr<ClientSession> >::const_iterator it;
- for (it = clients_.begin(); it != clients_.end(); ++it) {
+ for (ClientList::const_iterator it = clients_.begin(); it != clients_.end();
+ ++it) {
if (it->get()->authenticated())
return true;
}
@@ -402,9 +406,9 @@ void ChromotingHost::LocalLoginSucceeded(
// Disconnect all other clients.
// Iterate over a copy of the list of clients, to avoid mutating the list
// while iterating over it.
- std::vector<scoped_refptr<ClientSession> > clients_copy(clients_);
- std::vector<scoped_refptr<ClientSession> >::const_iterator client;
- for (client = clients_copy.begin(); client != clients_copy.end(); client++) {
+ ClientList clients_copy(clients_);
+ for (ClientList::const_iterator client = clients_copy.begin();
+ client != clients_copy.end(); client++) {
ConnectionToClient* connection_other = client->get()->connection();
if (connection_other != connection) {
OnClientDisconnected(connection_other);
diff --git a/remoting/host/chromoting_host.h b/remoting/host/chromoting_host.h
index 132e7b5..53fc6c3 100644
--- a/remoting/host/chromoting_host.h
+++ b/remoting/host/chromoting_host.h
@@ -14,7 +14,7 @@
#include "remoting/host/capturer.h"
#include "remoting/host/client_session.h"
#include "remoting/host/desktop_environment.h"
-#include "remoting/host/heartbeat_sender.h"
+#include "remoting/host/host_status_observer.h"
#include "remoting/jingle_glue/jingle_client.h"
#include "remoting/jingle_glue/jingle_thread.h"
#include "remoting/protocol/session_manager.h"
@@ -89,6 +89,8 @@ class ChromotingHost : public base::RefCountedThreadSafe<ChromotingHost>,
// Asynchronously shutdown the host process.
void Shutdown();
+ void AddStatusObserver(const scoped_refptr<HostStatusObserver>& observer);
+
////////////////////////////////////////////////////////////////////////////
// protocol::ConnectionToClient::EventHandler implementations
virtual void OnConnectionOpened(protocol::ConnectionToClient* client);
@@ -119,6 +121,9 @@ class ChromotingHost : public base::RefCountedThreadSafe<ChromotingHost>,
friend class base::RefCountedThreadSafe<ChromotingHost>;
friend class ChromotingHostTest;
+ typedef std::vector<scoped_refptr<HostStatusObserver> > StatusObserverList;
+ typedef std::vector<scoped_refptr<ClientSession> > ClientList;
+
ChromotingHost(ChromotingHostContext* context, MutableHostConfig* config,
DesktopEnvironment* environment);
virtual ~ChromotingHost();
@@ -159,13 +164,12 @@ class ChromotingHost : public base::RefCountedThreadSafe<ChromotingHost>,
scoped_refptr<protocol::SessionManager> session_manager_;
- // Objects that takes care of sending heartbeats to the chromoting bot.
- scoped_refptr<HeartbeatSender> heartbeat_sender_;
+ StatusObserverList status_observers_;
AccessVerifier access_verifier_;
// The connections to remote clients.
- std::vector<scoped_refptr<ClientSession> > clients_;
+ ClientList clients_;
// Session manager for the host process.
scoped_refptr<ScreenRecorder> recorder_;
diff --git a/remoting/host/heartbeat_sender.cc b/remoting/host/heartbeat_sender.cc
index 56ec751..5ef02b7 100644
--- a/remoting/host/heartbeat_sender.cc
+++ b/remoting/host/heartbeat_sender.cc
@@ -34,15 +34,12 @@ const int64 kDefaultHeartbeatIntervalMs = 5 * 60 * 1000; // 5 minutes.
}
HeartbeatSender::HeartbeatSender(MessageLoop* message_loop,
- JingleClient* jingle_client,
MutableHostConfig* config)
: state_(CREATED),
message_loop_(message_loop),
- jingle_client_(jingle_client),
config_(config),
interval_ms_(kDefaultHeartbeatIntervalMs) {
- DCHECK(jingle_client_);
DCHECK(config_);
}
@@ -67,56 +64,42 @@ bool HeartbeatSender::Init() {
return true;
}
-void HeartbeatSender::Start() {
- if (MessageLoop::current() != message_loop_) {
- message_loop_->PostTask(
- FROM_HERE, NewRunnableMethod(this, &HeartbeatSender::Start));
- return;
- }
-
- DCHECK_EQ(INITIALIZED, state_);
+void HeartbeatSender::OnSignallingConnected(SignalStrategy* signal_strategy,
+ const std::string& full_jid) {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ DCHECK(state_ == INITIALIZED || state_ == STOPPED);
state_ = STARTED;
- request_.reset(jingle_client_->CreateIqRequest());
+ full_jid_ = full_jid;
+ request_.reset(signal_strategy->CreateIqRequest());
request_->set_callback(NewCallback(this, &HeartbeatSender::ProcessResponse));
- message_loop_->PostTask(
- FROM_HERE, NewRunnableMethod(this, &HeartbeatSender::DoSendStanza));
+ DoSendStanza();
+ timer_.Start(base::TimeDelta::FromMilliseconds(interval_ms_), this,
+ &HeartbeatSender::DoSendStanza);
}
-void HeartbeatSender::Stop() {
- if (MessageLoop::current() != message_loop_) {
- message_loop_->PostTask(
- FROM_HERE, NewRunnableMethod(this, &HeartbeatSender::Stop));
- return;
- }
-
- // We may call Stop() even if we have not started.
- if (state_ != STARTED)
- return;
+void HeartbeatSender::OnSignallingDisconnected() {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ DCHECK_EQ(state_, STARTED);
state_ = STOPPED;
request_.reset(NULL);
}
-void HeartbeatSender::DoSendStanza() {
- if (state_ == STARTED) {
- // |jingle_client_| may be already destroyed if |state_| is set to
- // |STOPPED|, so don't touch it here unless we are in |STARTED| state.
- DCHECK(MessageLoop::current() == message_loop_);
-
- VLOG(1) << "Sending heartbeat stanza to " << kChromotingBotJid;
+void HeartbeatSender::OnShutdown() {
+}
- request_->SendIq(buzz::STR_SET, kChromotingBotJid,
- CreateHeartbeatMessage());
+void HeartbeatSender::DoSendStanza() {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ DCHECK_EQ(state_, STARTED);
- // Schedule next heartbeat.
- message_loop_->PostDelayedTask(
- FROM_HERE, NewRunnableMethod(this, &HeartbeatSender::DoSendStanza),
- interval_ms_);
- }
+ VLOG(1) << "Sending heartbeat stanza to " << kChromotingBotJid;
+ request_->SendIq(buzz::STR_SET, kChromotingBotJid, CreateHeartbeatMessage());
}
void HeartbeatSender::ProcessResponse(const XmlElement* response) {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+
std::string type = response->Attr(buzz::QN_TYPE);
if (type == buzz::STR_ERROR) {
LOG(ERROR) << "Received error in response to heartbeat: "
@@ -140,12 +123,25 @@ void HeartbeatSender::ProcessResponse(const XmlElement* response) {
LOG(ERROR) << "Received invalid set-interval: "
<< set_interval_element->Str();
} else {
- interval_ms_ = interval * base::Time::kMillisecondsPerSecond;
+ SetInterval(interval * base::Time::kMillisecondsPerSecond);
}
}
}
}
+void HeartbeatSender::SetInterval(int interval) {
+ if (interval != interval_ms_) {
+ interval_ms_ = interval;
+
+ // Restart the timer with the new interval.
+ if (state_ == STARTED) {
+ timer_.Stop();
+ timer_.Start(base::TimeDelta::FromMilliseconds(interval_ms_), this,
+ &HeartbeatSender::DoSendStanza);
+ }
+ }
+}
+
XmlElement* HeartbeatSender::CreateHeartbeatMessage() {
XmlElement* query = new XmlElement(
QName(kChromotingXmlNamespace, kHeartbeatQueryTag));
@@ -163,7 +159,7 @@ XmlElement* HeartbeatSender::CreateSignature() {
signature_tag->AddAttr(
QName(kChromotingXmlNamespace, kSignatureTimeAttr), time_str);
- std::string message = jingle_client_->GetFullJid() + ' ' + time_str;
+ std::string message = full_jid_ + ' ' + time_str;
std::string signature(key_pair_.GetSignature(message));
signature_tag->AddText(signature);
diff --git a/remoting/host/heartbeat_sender.h b/remoting/host/heartbeat_sender.h
index 1105179..016db0f 100644
--- a/remoting/host/heartbeat_sender.h
+++ b/remoting/host/heartbeat_sender.h
@@ -7,9 +7,12 @@
#include <string>
+#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/timer.h"
#include "remoting/host/host_key_pair.h"
+#include "remoting/host/host_status_observer.h"
#include "remoting/jingle_glue/iq_request.h"
#include "testing/gtest/include/gtest/gtest_prod.h"
@@ -17,8 +20,6 @@ namespace remoting {
class IqRequest;
class HostKeyPair;
-class JingleClient;
-class JingleThread;
class MutableHostConfig;
// HeartbeatSender periodically sends heartbeat stanzas to the Chromoting Bot.
@@ -55,10 +56,9 @@ class MutableHostConfig;
// server.
//
// TODO(sergeyu): Is it enough to sign JID and nothing else?
-class HeartbeatSender : public base::RefCountedThreadSafe<HeartbeatSender> {
+class HeartbeatSender : public HostStatusObserver {
public:
HeartbeatSender(MessageLoop* main_loop,
- JingleClient* jingle_client,
MutableHostConfig* config);
virtual ~HeartbeatSender();
@@ -66,15 +66,11 @@ class HeartbeatSender : public base::RefCountedThreadSafe<HeartbeatSender> {
// false if the config is invalid (e.g. private key cannot be parsed).
bool Init();
- // Starts heart-beating. Must be called after init.
- void Start();
-
- // Stops heart-beating. Must be called before corresponding JingleClient
- // is destroyed. This object will not be deleted until Stop() is called,
- // and it may (and will) crash after JingleClient is destroyed. Heartbeating
- // cannot be restarted after it has been stopped, A new sender must be created
- // instead.
- void Stop();
+ // HostStatusObserver implementation.
+ virtual void OnSignallingConnected(SignalStrategy* signal_strategy,
+ const std::string& full_jid) OVERRIDE;
+ virtual void OnSignallingDisconnected() OVERRIDE;
+ virtual void OnShutdown() OVERRIDE;
private:
FRIEND_TEST_ALL_PREFIXES(HeartbeatSenderTest, DoSendStanza);
@@ -89,22 +85,23 @@ class HeartbeatSender : public base::RefCountedThreadSafe<HeartbeatSender> {
};
void DoSendStanza();
+ void ProcessResponse(const buzz::XmlElement* response);
+ void SetInterval(int interval);
// Helper methods used by DoSendStanza() to generate heartbeat stanzas.
// Caller owns the result.
buzz::XmlElement* CreateHeartbeatMessage();
buzz::XmlElement* CreateSignature();
- void ProcessResponse(const buzz::XmlElement* response);
-
State state_;
MessageLoop* message_loop_;
- JingleClient* jingle_client_;
scoped_refptr<MutableHostConfig> config_;
- scoped_ptr<IqRequest> request_;
std::string host_id_;
HostKeyPair key_pair_;
+ std::string full_jid_;
+ scoped_ptr<IqRequest> request_;
int interval_ms_;
+ base::RepeatingTimer<HeartbeatSender> timer_;
DISALLOW_COPY_AND_ASSIGN(HeartbeatSender);
};
diff --git a/remoting/host/heartbeat_sender_unittest.cc b/remoting/host/heartbeat_sender_unittest.cc
index e02cc35..9d2fe4d 100644
--- a/remoting/host/heartbeat_sender_unittest.cc
+++ b/remoting/host/heartbeat_sender_unittest.cc
@@ -75,18 +75,9 @@ class HeartbeatSenderTest : public testing::Test {
config_ = new InMemoryHostConfig();
config_->SetString(kHostIdConfigPath, kHostId);
config_->SetString(kPrivateKeyConfigPath, kTestHostKeyPair);
-
- jingle_thread_.message_loop_ = &message_loop_;
-
- signal_strategy_.reset(new MockSignalStrategy());
- jingle_client_ =
- new JingleClient(&jingle_thread_, signal_strategy_.get(), NULL, NULL);
- jingle_client_->full_jid_ = kTestJid;
}
- JingleThread jingle_thread_;
- scoped_ptr<MockSignalStrategy> signal_strategy_;
- scoped_refptr<JingleClient> jingle_client_;
+ MockSignalStrategy signal_strategy_;
MessageLoop message_loop_;
scoped_refptr<InMemoryHostConfig> config_;
};
@@ -101,32 +92,32 @@ TEST_F(HeartbeatSenderTest, DoSendStanza) {
EXPECT_CALL(*iq_request, set_callback(_)).Times(1);
scoped_refptr<HeartbeatSender> heartbeat_sender(
- new HeartbeatSender(&message_loop_, jingle_client_.get(), config_));
+ new HeartbeatSender(&message_loop_, config_));
ASSERT_TRUE(heartbeat_sender->Init());
- EXPECT_CALL(*signal_strategy_, CreateIqRequest())
+ EXPECT_CALL(signal_strategy_, CreateIqRequest())
.WillOnce(Return(iq_request));
EXPECT_CALL(*iq_request, SendIq(buzz::STR_SET, kChromotingBotJid, NotNull()))
.WillOnce(DoAll(DeleteArg<2>(), Return()));
- heartbeat_sender->Start();
+ heartbeat_sender->OnSignallingConnected(&signal_strategy_, kTestJid);
message_loop_.RunAllPending();
- heartbeat_sender->Stop();
+ heartbeat_sender->OnSignallingDisconnected();
message_loop_.RunAllPending();
}
// Validate format of the heartbeat stanza.
TEST_F(HeartbeatSenderTest, CreateHeartbeatMessage) {
scoped_refptr<HeartbeatSender> heartbeat_sender(
- new HeartbeatSender(&message_loop_, jingle_client_.get(), config_));
+ new HeartbeatSender(&message_loop_, config_));
ASSERT_TRUE(heartbeat_sender->Init());
int64 start_time = static_cast<int64>(base::Time::Now().ToDoubleT());
- scoped_ptr<XmlElement> stanza(
- heartbeat_sender->CreateHeartbeatMessage());
+ heartbeat_sender->full_jid_ = kTestJid;
+ scoped_ptr<XmlElement> stanza(heartbeat_sender->CreateHeartbeatMessage());
ASSERT_TRUE(stanza.get() != NULL);
EXPECT_TRUE(QName(kChromotingXmlNamespace, "heartbeat") ==
@@ -171,7 +162,7 @@ TEST_F(HeartbeatSenderTest, ProcessResponse) {
set_interval->AddText(base::IntToString(kTestInterval));
scoped_refptr<HeartbeatSender> heartbeat_sender(
- new HeartbeatSender(&message_loop_, jingle_client_.get(), config_));
+ new HeartbeatSender(&message_loop_, config_));
heartbeat_sender->ProcessResponse(response.get());
EXPECT_EQ(kTestInterval * 1000, heartbeat_sender->interval_ms_);
diff --git a/remoting/host/host_status_observer.h b/remoting/host/host_status_observer.h
new file mode 100644
index 0000000..dd0ae85
--- /dev/null
+++ b/remoting/host/host_status_observer.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2011 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 REMOTING_HOST_STATUS_OBSERVER_H_
+#define REMOTING_HOST_STATUS_OBSERVER_H_
+
+#include "base/memory/ref_counted.h"
+
+namespace remoting {
+
+class SignalStrategy;
+
+class HostStatusObserver
+ : public base::RefCountedThreadSafe<HostStatusObserver> {
+ public:
+ HostStatusObserver() { }
+
+ // Called on the network thread when status of the XMPP changes.
+ virtual void OnSignallingConnected(SignalStrategy* signal_strategy,
+ const std::string& full_jid) = 0;
+ virtual void OnSignallingDisconnected() = 0;
+
+ // Called on the main thread when the host shuts down.
+ virtual void OnShutdown() = 0;
+
+ protected:
+ friend class base::RefCountedThreadSafe<HostStatusObserver>;
+ virtual ~HostStatusObserver() { }
+};
+
+} // namespace remoting
+
+#endif // REMOTING_HOST_STATUS_OBSERVER_H_
diff --git a/remoting/host/simple_host_process.cc b/remoting/host/simple_host_process.cc
index c10c2c5..1e188d5 100644
--- a/remoting/host/simple_host_process.cc
+++ b/remoting/host/simple_host_process.cc
@@ -36,6 +36,7 @@
#include "remoting/host/curtain.h"
#include "remoting/host/desktop_environment.h"
#include "remoting/host/event_executor.h"
+#include "remoting/host/heartbeat_sender.h"
#include "remoting/host/json_host_config.h"
#include "remoting/proto/video.pb.h"
@@ -172,6 +173,13 @@ int main(int argc, char** argv) {
mock_cr_app::RegisterMockCrApp();
#endif // OS_MACOSX
+ // Initialize HeartbeatSender.
+ scoped_refptr<remoting::HeartbeatSender> heartbeat_sender =
+ new remoting::HeartbeatSender(context.network_message_loop(), config);
+ if (!heartbeat_sender->Init())
+ return 1;
+ host->AddStatusObserver(heartbeat_sender);
+
// Let the chromoting host run until the shutdown task is executed.
host->Start(NewRunnableFunction(&ShutdownTask, &message_loop));
message_loop.MessageLoop::Run();
diff --git a/remoting/jingle_glue/jingle_client.h b/remoting/jingle_glue/jingle_client.h
index 027a8d3..fececea 100644
--- a/remoting/jingle_glue/jingle_client.h
+++ b/remoting/jingle_glue/jingle_client.h
@@ -177,7 +177,6 @@ class JingleClient : public base::RefCountedThreadSafe<JingleClient>,
MessageLoop* message_loop();
private:
- friend class HeartbeatSenderTest;
friend class JingleClientTest;
void DoInitialize();
diff --git a/remoting/jingle_glue/jingle_thread.h b/remoting/jingle_glue/jingle_thread.h
index be64f00..a7201e1 100644
--- a/remoting/jingle_glue/jingle_thread.h
+++ b/remoting/jingle_glue/jingle_thread.h
@@ -59,8 +59,6 @@ class JingleThread : public talk_base::Thread,
class JingleMessageLoop;
class JingleMessagePump;
- friend class HeartbeatSenderTest;
-
virtual void OnMessage(talk_base::Message* msg);
TaskPump* task_pump_;
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index b349603..e4d0169c 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -228,6 +228,7 @@
'host/host_config.h',
'host/host_key_pair.cc',
'host/host_key_pair.h',
+ 'host/host_status_observer.h',
'host/in_memory_host_config.cc',
'host/in_memory_host_config.h',
'host/json_host_config.cc',