Pull out common code from client and host versions of LogToServer

Also added unittests for client code.

TEST=unittests

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282193 0039d316-1c4b-4281-b951-d872f2087c98
parent 8e1dd185
...@@ -2,20 +2,13 @@ ...@@ -2,20 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "remoting/client/log_to_server.h" #include "remoting/client/client_status_logger.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/rand_util.h" #include "base/rand_util.h"
#include "remoting/base/constants.h"
#include "remoting/client/chromoting_stats.h" #include "remoting/client/chromoting_stats.h"
#include "remoting/client/server_log_entry_client.h" #include "remoting/client/server_log_entry_client.h"
#include "remoting/jingle_glue/iq_sender.h"
#include "remoting/jingle_glue/signal_strategy.h"
#include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
#include "third_party/libjingle/source/talk/xmpp/constants.h"
using buzz::QName;
using buzz::XmlElement;
using remoting::protocol::ConnectionToHost; using remoting::protocol::ConnectionToHost;
namespace { namespace {
...@@ -49,22 +42,16 @@ bool ShouldAddDuration(ConnectionToHost::State state) { ...@@ -49,22 +42,16 @@ bool ShouldAddDuration(ConnectionToHost::State state) {
namespace remoting { namespace remoting {
namespace client { ClientStatusLogger::ClientStatusLogger(ServerLogEntry::Mode mode,
SignalStrategy* signal_strategy,
LogToServer::LogToServer(ServerLogEntry::Mode mode, const std::string& directory_bot_jid)
SignalStrategy* signal_strategy, : log_to_server_(mode, signal_strategy, directory_bot_jid) {
const std::string& directory_bot_jid)
: mode_(mode),
signal_strategy_(signal_strategy),
directory_bot_jid_(directory_bot_jid) {
signal_strategy_->AddListener(this);
} }
LogToServer::~LogToServer() { ClientStatusLogger::~ClientStatusLogger() {
signal_strategy_->RemoveListener(this);
} }
void LogToServer::LogSessionStateChange( void ClientStatusLogger::LogSessionStateChange(
protocol::ConnectionToHost::State state, protocol::ConnectionToHost::State state,
protocol::ErrorCode error) { protocol::ErrorCode error) {
DCHECK(CalledOnValidThread()); DCHECK(CalledOnValidThread());
...@@ -72,7 +59,7 @@ void LogToServer::LogSessionStateChange( ...@@ -72,7 +59,7 @@ void LogToServer::LogSessionStateChange(
scoped_ptr<ServerLogEntry> entry( scoped_ptr<ServerLogEntry> entry(
MakeLogEntryForSessionStateChange(state, error)); MakeLogEntryForSessionStateChange(state, error));
AddClientFieldsToLogEntry(entry.get()); AddClientFieldsToLogEntry(entry.get());
entry->AddModeField(mode_); entry->AddModeField(log_to_server_.mode());
MaybeExpireSessionId(); MaybeExpireSessionId();
if (IsStartOfSession(state)) { if (IsStartOfSession(state)) {
...@@ -100,65 +87,26 @@ void LogToServer::LogSessionStateChange( ...@@ -100,65 +87,26 @@ void LogToServer::LogSessionStateChange(
session_id_.clear(); session_id_.clear();
} }
Log(*entry.get()); log_to_server_.Log(*entry.get());
} }
void LogToServer::LogStatistics(ChromotingStats* statistics) { void ClientStatusLogger::LogStatistics(ChromotingStats* statistics) {
DCHECK(CalledOnValidThread()); DCHECK(CalledOnValidThread());
MaybeExpireSessionId(); MaybeExpireSessionId();
scoped_ptr<ServerLogEntry> entry(MakeLogEntryForStatistics(statistics)); scoped_ptr<ServerLogEntry> entry(MakeLogEntryForStatistics(statistics));
AddClientFieldsToLogEntry(entry.get()); AddClientFieldsToLogEntry(entry.get());
entry->AddModeField(mode_); entry->AddModeField(log_to_server_.mode());
AddSessionIdToLogEntry(entry.get(), session_id_); AddSessionIdToLogEntry(entry.get(), session_id_);
Log(*entry.get()); log_to_server_.Log(*entry.get());
}
void LogToServer::OnSignalStrategyStateChange(SignalStrategy::State state) {
DCHECK(CalledOnValidThread());
if (state == SignalStrategy::CONNECTED) {
iq_sender_.reset(new IqSender(signal_strategy_));
SendPendingEntries();
} else if (state == SignalStrategy::DISCONNECTED) {
iq_sender_.reset();
}
}
bool LogToServer::OnSignalStrategyIncomingStanza(
const buzz::XmlElement* stanza) {
return false;
} }
void LogToServer::Log(const ServerLogEntry& entry) { void ClientStatusLogger::SetSignalingStateForTest(SignalStrategy::State state) {
pending_entries_.push_back(entry); log_to_server_.OnSignalStrategyStateChange(state);
SendPendingEntries();
} }
void LogToServer::SendPendingEntries() { void ClientStatusLogger::GenerateSessionId() {
if (iq_sender_ == NULL) {
return;
}
if (pending_entries_.empty()) {
return;
}
// Make one stanza containing all the pending entries.
scoped_ptr<XmlElement> stanza(ServerLogEntry::MakeStanza());
while (!pending_entries_.empty()) {
ServerLogEntry& entry = pending_entries_.front();
stanza->AddElement(entry.ToStanza().release());
pending_entries_.pop_front();
}
// Send the stanza to the server.
scoped_ptr<IqRequest> req = iq_sender_->SendIq(
buzz::STR_SET, directory_bot_jid_, stanza.Pass(),
IqSender::ReplyCallback());
// We ignore any response, so let the IqRequest be destroyed.
return;
}
void LogToServer::GenerateSessionId() {
session_id_.resize(kSessionIdLength); session_id_.resize(kSessionIdLength);
for (int i = 0; i < kSessionIdLength; i++) { for (int i = 0; i < kSessionIdLength; i++) {
const int alphabet_size = arraysize(kSessionIdAlphabet) - 1; const int alphabet_size = arraysize(kSessionIdAlphabet) - 1;
...@@ -167,7 +115,7 @@ void LogToServer::GenerateSessionId() { ...@@ -167,7 +115,7 @@ void LogToServer::GenerateSessionId() {
session_id_generation_time_ = base::TimeTicks::Now(); session_id_generation_time_ = base::TimeTicks::Now();
} }
void LogToServer::MaybeExpireSessionId() { void ClientStatusLogger::MaybeExpireSessionId() {
if (session_id_.empty()) { if (session_id_.empty()) {
return; return;
} }
...@@ -176,19 +124,17 @@ void LogToServer::MaybeExpireSessionId() { ...@@ -176,19 +124,17 @@ void LogToServer::MaybeExpireSessionId() {
if (base::TimeTicks::Now() - session_id_generation_time_ > max_age) { if (base::TimeTicks::Now() - session_id_generation_time_ > max_age) {
// Log the old session ID. // Log the old session ID.
scoped_ptr<ServerLogEntry> entry(MakeLogEntryForSessionIdOld(session_id_)); scoped_ptr<ServerLogEntry> entry(MakeLogEntryForSessionIdOld(session_id_));
entry->AddModeField(mode_); entry->AddModeField(log_to_server_.mode());
Log(*entry.get()); log_to_server_.Log(*entry.get());
// Generate a new session ID. // Generate a new session ID.
GenerateSessionId(); GenerateSessionId();
// Log the new session ID. // Log the new session ID.
entry = MakeLogEntryForSessionIdNew(session_id_); entry = MakeLogEntryForSessionIdNew(session_id_);
entry->AddModeField(mode_); entry->AddModeField(log_to_server_.mode());
Log(*entry.get()); log_to_server_.Log(*entry.get());
} }
} }
} // namespace client
} // namespace remoting } // namespace remoting
// Copyright 2014 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_CLIENT_CLIENT_STATUS_LOGGER_H_
#define REMOTING_CLIENT_CLIENT_STATUS_LOGGER_H_
#include "base/threading/non_thread_safe.h"
#include "base/time/time.h"
#include "remoting/jingle_glue/log_to_server.h"
#include "remoting/protocol/connection_to_host.h"
#include "remoting/protocol/errors.h"
namespace remoting {
class ChromotingStats;
// ClientStatusLogger sends client log entries to a server.
// The contents of the log entries are described in server_log_entry_client.cc.
// They do not contain any personally identifiable information.
class ClientStatusLogger : public base::NonThreadSafe {
public:
ClientStatusLogger(ServerLogEntry::Mode mode,
SignalStrategy* signal_strategy,
const std::string& directory_bot_jid);
~ClientStatusLogger();
void LogSessionStateChange(protocol::ConnectionToHost::State state,
protocol::ErrorCode error);
void LogStatistics(remoting::ChromotingStats* statistics);
// Allows test code to fake SignalStrategy state change events.
void SetSignalingStateForTest(SignalStrategy::State state);
private:
LogToServer log_to_server_;
// Generates a new random session ID.
void GenerateSessionId();
// Expire the session ID if the maximum duration has been exceeded.
void MaybeExpireSessionId();
// A randomly generated session ID to be attached to log messages. This
// is regenerated at the start of a new session.
std::string session_id_;
// Start time of the session.
base::TimeTicks session_start_time_;
// Time when the session ID was generated.
base::TimeTicks session_id_generation_time_;
DISALLOW_COPY_AND_ASSIGN(ClientStatusLogger);
};
} // namespace remoting
#endif // REMOTING_CLIENT_CLIENT_STATUS_LOGGER_H_
// Copyright 2014 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.
#include "remoting/client/client_status_logger.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
#include "remoting/client/chromoting_stats.h"
#include "remoting/jingle_glue/mock_objects.h"
#include "remoting/jingle_glue/server_log_entry_unittest.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
using buzz::XmlElement;
using buzz::QName;
using remoting::protocol::ConnectionToHost;
using testing::_;
using testing::DeleteArg;
using testing::InSequence;
using testing::Return;
namespace remoting {
namespace {
ACTION_P(QuitMainMessageLoop, message_loop) {
message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
}
const char kTestBotJid[] = "remotingunittest@bot.talk.google.com";
const char kClientJid[] = "host@domain.com/1234";
MATCHER_P2(IsStateChange, new_state, error, "") {
XmlElement* entry = GetSingleLogEntryFromStanza(arg);
if (!entry) {
return false;
}
bool is_state_change = (
entry->Attr(QName(std::string(), "event-name")) == "session-state" &&
entry->Attr(QName(std::string(), "session-state")) == new_state &&
entry->Attr(QName(std::string(), "role")) == "client" &&
entry->Attr(QName(std::string(), "mode")) == "me2me");
if (!std::string(error).empty()) {
is_state_change = is_state_change &&
entry->Attr(QName(std::string(), "connection-error")) == error;
}
return is_state_change;
}
MATCHER(IsStatisticsLog, "") {
XmlElement* entry = GetSingleLogEntryFromStanza(arg);
if (!entry) {
return false;
}
return entry->Attr(QName(std::string(), "event-name")) ==
"connection-statistics";
}
} // namespace
class ClientStatusLoggerTest : public testing::Test {
public:
ClientStatusLoggerTest() {}
virtual void SetUp() OVERRIDE {
EXPECT_CALL(signal_strategy_, AddListener(_));
EXPECT_CALL(signal_strategy_, RemoveListener(_));
message_loop_proxy_ = base::MessageLoopProxy::current();
client_status_logger_.reset(
new ClientStatusLogger(ServerLogEntry::ME2ME,
&signal_strategy_,
kTestBotJid));
}
protected:
base::MessageLoop message_loop_;
scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
MockSignalStrategy signal_strategy_;
scoped_ptr<ClientStatusLogger> client_status_logger_;
};
TEST_F(ClientStatusLoggerTest, LogStateChange) {
{
InSequence s;
EXPECT_CALL(signal_strategy_, GetLocalJid())
.WillRepeatedly(Return(kClientJid));
EXPECT_CALL(signal_strategy_, AddListener(_));
EXPECT_CALL(signal_strategy_, GetNextId());
EXPECT_CALL(signal_strategy_, SendStanzaPtr(
IsStateChange("connected", std::string())))
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
EXPECT_CALL(signal_strategy_, RemoveListener(_))
.WillOnce(QuitMainMessageLoop(&message_loop_))
.RetiresOnSaturation();
}
client_status_logger_->LogSessionStateChange(ConnectionToHost::CONNECTED,
protocol::OK);
// Setting the state to CONNECTED causes the log to be sent. Setting the
// state to DISCONNECTED causes |signal_strategy_| to be cleaned up,
// which removes the listener and terminates the test.
client_status_logger_->SetSignalingStateForTest(SignalStrategy::CONNECTED);
client_status_logger_->SetSignalingStateForTest(SignalStrategy::DISCONNECTED);
message_loop_.Run();
}
TEST_F(ClientStatusLoggerTest, LogStateChangeError) {
{
InSequence s;
EXPECT_CALL(signal_strategy_, GetLocalJid())
.WillRepeatedly(Return(kClientJid));
EXPECT_CALL(signal_strategy_, AddListener(_));
EXPECT_CALL(signal_strategy_, GetNextId());
EXPECT_CALL(signal_strategy_, SendStanzaPtr(
IsStateChange("connection-failed", "host-is-offline")))
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
EXPECT_CALL(signal_strategy_, RemoveListener(_))
.WillOnce(QuitMainMessageLoop(&message_loop_))
.RetiresOnSaturation();
}
client_status_logger_->LogSessionStateChange(ConnectionToHost::FAILED,
protocol::PEER_IS_OFFLINE);
client_status_logger_->SetSignalingStateForTest(SignalStrategy::CONNECTED);
client_status_logger_->SetSignalingStateForTest(SignalStrategy::DISCONNECTED);
message_loop_.Run();
}
TEST_F(ClientStatusLoggerTest, LogStatistics) {
{
InSequence s;
EXPECT_CALL(signal_strategy_, GetLocalJid())
.WillRepeatedly(Return(kClientJid));
EXPECT_CALL(signal_strategy_, AddListener(_));
EXPECT_CALL(signal_strategy_, GetNextId());
EXPECT_CALL(signal_strategy_, SendStanzaPtr(
IsStatisticsLog()))
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
EXPECT_CALL(signal_strategy_, RemoveListener(_))
.WillOnce(QuitMainMessageLoop(&message_loop_))
.RetiresOnSaturation();
}
ChromotingStats stats;
client_status_logger_->LogStatistics(&stats);
client_status_logger_->SetSignalingStateForTest(SignalStrategy::CONNECTED);
client_status_logger_->SetSignalingStateForTest(SignalStrategy::DISCONNECTED);
message_loop_.Run();
}
} // namespace remoting
...@@ -12,9 +12,9 @@ ...@@ -12,9 +12,9 @@
#include "net/socket/client_socket_factory.h" #include "net/socket/client_socket_factory.h"
#include "remoting/base/service_urls.h" #include "remoting/base/service_urls.h"
#include "remoting/client/audio_player.h" #include "remoting/client/audio_player.h"
#include "remoting/client/client_status_logger.h"
#include "remoting/client/jni/android_keymap.h" #include "remoting/client/jni/android_keymap.h"
#include "remoting/client/jni/chromoting_jni_runtime.h" #include "remoting/client/jni/chromoting_jni_runtime.h"
#include "remoting/client/log_to_server.h"
#include "remoting/client/software_video_renderer.h" #include "remoting/client/software_video_renderer.h"
#include "remoting/client/token_fetcher_proxy.h" #include "remoting/client/token_fetcher_proxy.h"
#include "remoting/jingle_glue/chromium_port_allocator.h" #include "remoting/jingle_glue/chromium_port_allocator.h"
...@@ -254,7 +254,7 @@ void ChromotingJniInstance::OnConnectionState( ...@@ -254,7 +254,7 @@ void ChromotingJniInstance::OnConnectionState(
EnableStatsLogging(state == protocol::ConnectionToHost::CONNECTED); EnableStatsLogging(state == protocol::ConnectionToHost::CONNECTED);
log_to_server_->LogSessionStateChange(state, error); client_status_logger_->LogSessionStateChange(state, error);
if (create_pairing_ && state == protocol::ConnectionToHost::CONNECTED) { if (create_pairing_ && state == protocol::ConnectionToHost::CONNECTED) {
protocol::PairingRequest request; protocol::PairingRequest request;
...@@ -378,10 +378,10 @@ void ChromotingJniInstance::ConnectToHostOnNetworkThread() { ...@@ -378,10 +378,10 @@ void ChromotingJniInstance::ConnectToHostOnNetworkThread() {
net::ClientSocketFactory::GetDefaultFactory(), net::ClientSocketFactory::GetDefaultFactory(),
jni_runtime_->url_requester(), xmpp_config_)); jni_runtime_->url_requester(), xmpp_config_));
log_to_server_.reset( client_status_logger_.reset(
new client::LogToServer(ServerLogEntry::ME2ME, new ClientStatusLogger(ServerLogEntry::ME2ME,
signaling_.get(), signaling_.get(),
ServiceUrls::GetInstance()->directory_bot_jid())); ServiceUrls::GetInstance()->directory_bot_jid()));
NetworkSettings network_settings(NetworkSettings::NAT_TRAVERSAL_FULL); NetworkSettings network_settings(NetworkSettings::NAT_TRAVERSAL_FULL);
...@@ -409,7 +409,7 @@ void ChromotingJniInstance::DisconnectFromHostOnNetworkThread() { ...@@ -409,7 +409,7 @@ void ChromotingJniInstance::DisconnectFromHostOnNetworkThread() {
// |client_| must be torn down before |signaling_|. // |client_| must be torn down before |signaling_|.
connection_.reset(); connection_.reset();
client_.reset(); client_.reset();
log_to_server_.reset(); client_status_logger_.reset();
} }
void ChromotingJniInstance::FetchSecret( void ChromotingJniInstance::FetchSecret(
...@@ -488,7 +488,7 @@ void ChromotingJniInstance::LogPerfStats() { ...@@ -488,7 +488,7 @@ void ChromotingJniInstance::LogPerfStats() {
stats->video_paint_ms()->Average(), stats->video_paint_ms()->Average(),
stats->round_trip_ms()->Average()); stats->round_trip_ms()->Average());
log_to_server_->LogStatistics(stats); client_status_logger_->LogStatistics(stats);
jni_runtime_->network_task_runner()->PostDelayedTask( jni_runtime_->network_task_runner()->PostDelayedTask(
FROM_HERE, base::Bind(&ChromotingJniInstance::LogPerfStats, this), FROM_HERE, base::Bind(&ChromotingJniInstance::LogPerfStats, this),
......
...@@ -29,10 +29,7 @@ class ClipboardEvent; ...@@ -29,10 +29,7 @@ class ClipboardEvent;
class CursorShapeInfo; class CursorShapeInfo;
} // namespace protocol } // namespace protocol
namespace client { class ClientStatusLogger;
class LogToServer;
}
class VideoRenderer; class VideoRenderer;
class TokenFetcherProxy; class TokenFetcherProxy;
...@@ -166,7 +163,7 @@ class ChromotingJniInstance ...@@ -166,7 +163,7 @@ class ChromotingJniInstance
scoped_ptr<ChromotingClient> client_; scoped_ptr<ChromotingClient> client_;
XmppSignalStrategy::XmppServerConfig xmpp_config_; XmppSignalStrategy::XmppServerConfig xmpp_config_;
scoped_ptr<XmppSignalStrategy> signaling_; // Must outlive client_ scoped_ptr<XmppSignalStrategy> signaling_; // Must outlive client_
scoped_ptr<client::LogToServer> log_to_server_; scoped_ptr<ClientStatusLogger> client_status_logger_;
base::WeakPtr<TokenFetcherProxy> token_fetcher_proxy_; base::WeakPtr<TokenFetcherProxy> token_fetcher_proxy_;
// Pass this the user's PIN once we have it. To be assigned and accessed on // Pass this the user's PIN once we have it. To be assigned and accessed on
......
// Copyright 2014 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.
#include "remoting/host/host_status_logger.h"
#include "base/bind.h"
#include "base/message_loop/message_loop_proxy.h"
#include "remoting/base/constants.h"
#include "remoting/host/host_status_monitor.h"
#include "remoting/host/server_log_entry_host.h"
#include "remoting/jingle_glue/server_log_entry.h"
#include "remoting/protocol/transport.h"
namespace remoting {
HostStatusLogger::HostStatusLogger(base::WeakPtr<HostStatusMonitor> monitor,
ServerLogEntry::Mode mode,
SignalStrategy* signal_strategy,
const std::string& directory_bot_jid)
: log_to_server_(mode, signal_strategy, directory_bot_jid),
monitor_(monitor) {
monitor_->AddStatusObserver(this);
}
HostStatusLogger::~HostStatusLogger() {
if (monitor_.get())
monitor_->RemoveStatusObserver(this);
}
void HostStatusLogger::LogSessionStateChange(const std::string& jid,
bool connected) {
DCHECK(CalledOnValidThread());
scoped_ptr<ServerLogEntry> entry(
MakeLogEntryForSessionStateChange(connected));
AddHostFieldsToLogEntry(entry.get());
entry->AddModeField(log_to_server_.mode());
if (connected) {
DCHECK_EQ(connection_route_type_.count(jid), 1u);
AddConnectionTypeToLogEntry(entry.get(), connection_route_type_[jid]);
}
log_to_server_.Log(*entry.get());
}
void HostStatusLogger::OnClientConnected(const std::string& jid) {
DCHECK(CalledOnValidThread());
LogSessionStateChange(jid, true);
}
void HostStatusLogger::OnClientDisconnected(const std::string& jid) {
DCHECK(CalledOnValidThread());
LogSessionStateChange(jid, false);
connection_route_type_.erase(jid);
}
void HostStatusLogger::OnClientRouteChange(
const std::string& jid,
const std::string& channel_name,
const protocol::TransportRoute& route) {
// Store connection type for the video channel. It is logged later
// when client authentication is finished.
if (channel_name == kVideoChannelName) {
connection_route_type_[jid] = route.type;
}
}
void HostStatusLogger::SetSignalingStateForTest(SignalStrategy::State state) {
log_to_server_.OnSignalStrategyStateChange(state);
}
} // namespace remoting
// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef REMOTING_HOST_LOG_TO_SERVER_H_ #ifndef REMOTING_HOST_HOST_STATUS_LOGGER_H_
#define REMOTING_HOST_LOG_TO_SERVER_H_ #define REMOTING_HOST_HOST_STATUS_LOGGER_H_
#include <deque>
#include <map> #include <map>
#include <string>
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/threading/non_thread_safe.h" #include "base/threading/non_thread_safe.h"
#include "remoting/host/host_status_observer.h" #include "remoting/host/host_status_observer.h"
#include "remoting/jingle_glue/server_log_entry.h" #include "remoting/jingle_glue/log_to_server.h"
#include "remoting/jingle_glue/signal_strategy.h"
#include "remoting/protocol/transport.h" #include "remoting/protocol/transport.h"
namespace base {
class MessageLoopProxy;
} // namespace base
namespace buzz {
class XmlElement;
} // namespace buzz
namespace remoting { namespace remoting {
class HostStatusMonitor; class HostStatusMonitor;
class IqSender;
// LogToServer sends log entries to a server. // HostStatusLogger sends host log entries to a server.
// The contents of the log entries are described in server_log_entry.cc. // The contents of the log entries are described in server_log_entry_host.cc.
// They do not contain any personally identifiable information. // They do not contain any personally identifiable information.
class LogToServer : public base::NonThreadSafe, class HostStatusLogger : public HostStatusObserver,
public HostStatusObserver, public base::NonThreadSafe {
public SignalStrategy::Listener {
public: public:
explicit LogToServer(base::WeakPtr<HostStatusMonitor> monitor, HostStatusLogger(base::WeakPtr<HostStatusMonitor> monitor,
ServerLogEntry::Mode mode, ServerLogEntry::Mode mode,
SignalStrategy* signal_strategy, SignalStrategy* signal_strategy,
const std::string& directory_bot_jid); const std::string& directory_bot_jid);
virtual ~LogToServer(); virtual ~HostStatusLogger();
// Logs a session state change. Currently, this is either // Logs a session state change. Currently, this is either
// connection or disconnection. // connection or disconnection.
void LogSessionStateChange(const std::string& jid, bool connected); void LogSessionStateChange(const std::string& jid, bool connected);
// SignalStrategy::Listener interface.
virtual void OnSignalStrategyStateChange(
SignalStrategy::State state) OVERRIDE;
virtual bool OnSignalStrategyIncomingStanza(
const buzz::XmlElement* stanza) OVERRIDE;
// HostStatusObserver interface. // HostStatusObserver interface.
virtual void OnClientConnected(const std::string& jid) OVERRIDE; virtual void OnClientConnected(const std::string& jid) OVERRIDE;
virtual void OnClientDisconnected(const std::string& jid) OVERRIDE; virtual void OnClientDisconnected(const std::string& jid) OVERRIDE;
...@@ -61,25 +41,22 @@ class LogToServer : public base::NonThreadSafe, ...@@ -61,25 +41,22 @@ class LogToServer : public base::NonThreadSafe,
const std::string& channel_name, const std::string& channel_name,
const protocol::TransportRoute& route) OVERRIDE; const protocol::TransportRoute& route) OVERRIDE;
// Allows test code to fake SignalStrategy state change events.
void SetSignalingStateForTest(SignalStrategy::State state);
private: private:
void Log(const ServerLogEntry& entry); LogToServer log_to_server_;
void SendPendingEntries();
base::WeakPtr<HostStatusMonitor> monitor_; base::WeakPtr<HostStatusMonitor> monitor_;
ServerLogEntry::Mode mode_;
SignalStrategy* signal_strategy_;
scoped_ptr<IqSender> iq_sender_;
std::string directory_bot_jid_;
// A map from client JID to the route type of that client's connection to // A map from client JID to the route type of that client's connection to
// this host. // this host.
std::map<std::string, protocol::TransportRoute::RouteType> std::map<std::string, protocol::TransportRoute::RouteType>
connection_route_type_; connection_route_type_;
std::deque<ServerLogEntry> pending_entries_;
DISALLOW_COPY_AND_ASSIGN(LogToServer); DISALLOW_COPY_AND_ASSIGN(HostStatusLogger);
}; };
} // namespace remoting } // namespace remoting
#endif // REMOTING_HOST_LOG_TO_SERVER_H_ #endif // REMOTING_HOST_HOST_STATUS_LOGGER_H_
// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "remoting/host/host_status_logger.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h" #include "base/message_loop/message_loop_proxy.h"
#include "remoting/host/host_status_monitor_fake.h" #include "remoting/host/host_status_monitor_fake.h"
#include "remoting/host/log_to_server.h"
#include "remoting/jingle_glue/mock_objects.h" #include "remoting/jingle_glue/mock_objects.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gmock_mutant.h" #include "testing/gmock_mutant.h"
...@@ -49,7 +50,7 @@ MATCHER_P(IsClientConnected, connection_type, "") { ...@@ -49,7 +50,7 @@ MATCHER_P(IsClientConnected, connection_type, "") {
return false; return false;
} }
buzz::XmlElement* log_stanza = arg->FirstChild()->AsElement(); buzz::XmlElement* log_stanza = arg->FirstChild()->AsElement();
if (log_stanza->Name() !=QName(kChromotingNamespace, "log")) { if (log_stanza->Name() != QName(kChromotingNamespace, "log")) {
return false; return false;
} }
if (log_stanza->NextChild()) { if (log_stanza->NextChild()) {
...@@ -70,7 +71,7 @@ MATCHER_P2(IsTwoClientsConnected, connection_type1, connection_type2, "") { ...@@ -70,7 +71,7 @@ MATCHER_P2(IsTwoClientsConnected, connection_type1, connection_type2, "") {
return false; return false;
} }
buzz::XmlElement* log_stanza = arg->FirstChild()->AsElement(); buzz::XmlElement* log_stanza = arg->FirstChild()->AsElement();
if (log_stanza->Name() !=QName(kChromotingNamespace, "log")) { if (log_stanza->Name() != QName(kChromotingNamespace, "log")) {
return false; return false;
} }
if (log_stanza->NextChild()) { if (log_stanza->NextChild()) {
...@@ -121,17 +122,17 @@ MATCHER(IsClientDisconnected, "") { ...@@ -121,17 +122,17 @@ MATCHER(IsClientDisconnected, "") {
} // namespace } // namespace
class LogToServerTest : public testing::Test { class HostStatusLoggerTest : public testing::Test {
public: public:
LogToServerTest() {} HostStatusLoggerTest() {}
virtual void SetUp() OVERRIDE { virtual void SetUp() OVERRIDE {
message_loop_proxy_ = base::MessageLoopProxy::current(); message_loop_proxy_ = base::MessageLoopProxy::current();
EXPECT_CALL(signal_strategy_, AddListener(_)); EXPECT_CALL(signal_strategy_, AddListener(_));
log_to_server_.reset( host_status_logger_.reset(
new LogToServer(host_status_monitor_.AsWeakPtr(), new HostStatusLogger(host_status_monitor_.AsWeakPtr(),
ServerLogEntry::ME2ME, ServerLogEntry::ME2ME,
&signal_strategy_, &signal_strategy_,
kTestBotJid)); kTestBotJid));
EXPECT_CALL(signal_strategy_, RemoveListener(_)); EXPECT_CALL(signal_strategy_, RemoveListener(_));
} }
...@@ -139,11 +140,11 @@ class LogToServerTest : public testing::Test { ...@@ -139,11 +140,11 @@ class LogToServerTest : public testing::Test {
base::MessageLoop message_loop_; base::MessageLoop message_loop_;
scoped_refptr<base::MessageLoopProxy> message_loop_proxy_; scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
MockSignalStrategy signal_strategy_; MockSignalStrategy signal_strategy_;
scoped_ptr<LogToServer> log_to_server_; scoped_ptr<HostStatusLogger> host_status_logger_;
HostStatusMonitorFake host_status_monitor_; HostStatusMonitorFake host_status_monitor_;
}; };
TEST_F(LogToServerTest, SendNow) { TEST_F(HostStatusLoggerTest, SendNow) {
{ {
InSequence s; InSequence s;
EXPECT_CALL(signal_strategy_, GetLocalJid()) EXPECT_CALL(signal_strategy_, GetLocalJid())
...@@ -156,22 +157,23 @@ TEST_F(LogToServerTest, SendNow) { ...@@ -156,22 +157,23 @@ TEST_F(LogToServerTest, SendNow) {
.WillOnce(QuitMainMessageLoop(&message_loop_)) .WillOnce(QuitMainMessageLoop(&message_loop_))
.RetiresOnSaturation(); .RetiresOnSaturation();
} }
log_to_server_->OnSignalStrategyStateChange(SignalStrategy::CONNECTED); host_status_logger_->SetSignalingStateForTest(SignalStrategy::CONNECTED);
protocol::TransportRoute route; protocol::TransportRoute route;
route.type = protocol::TransportRoute::DIRECT; route.type = protocol::TransportRoute::DIRECT;
log_to_server_->OnClientRouteChange(kClientJid1, "video", route); host_status_logger_->OnClientRouteChange(kClientJid1, "video", route);
log_to_server_->OnClientAuthenticated(kClientJid1); host_status_logger_->OnClientAuthenticated(kClientJid1);
log_to_server_->OnClientConnected(kClientJid1); host_status_logger_->OnClientConnected(kClientJid1);
log_to_server_->OnSignalStrategyStateChange(SignalStrategy::DISCONNECTED); host_status_logger_->SetSignalingStateForTest(
SignalStrategy::DISCONNECTED);
message_loop_.Run(); message_loop_.Run();
} }
TEST_F(LogToServerTest, SendLater) { TEST_F(HostStatusLoggerTest, SendLater) {
protocol::TransportRoute route; protocol::TransportRoute route;
route.type = protocol::TransportRoute::DIRECT; route.type = protocol::TransportRoute::DIRECT;
log_to_server_->OnClientRouteChange(kClientJid1, "video", route); host_status_logger_->OnClientRouteChange(kClientJid1, "video", route);
log_to_server_->OnClientAuthenticated(kClientJid1); host_status_logger_->OnClientAuthenticated(kClientJid1);
log_to_server_->OnClientConnected(kClientJid1); host_status_logger_->OnClientConnected(kClientJid1);
{ {
InSequence s; InSequence s;
EXPECT_CALL(signal_strategy_, GetLocalJid()) EXPECT_CALL(signal_strategy_, GetLocalJid())
...@@ -184,41 +186,41 @@ TEST_F(LogToServerTest, SendLater) { ...@@ -184,41 +186,41 @@ TEST_F(LogToServerTest, SendLater) {
.WillOnce(QuitMainMessageLoop(&message_loop_)) .WillOnce(QuitMainMessageLoop(&message_loop_))
.RetiresOnSaturation(); .RetiresOnSaturation();
} }
log_to_server_->OnSignalStrategyStateChange(SignalStrategy::CONNECTED); host_status_logger_->SetSignalingStateForTest(SignalStrategy::CONNECTED);
log_to_server_->OnSignalStrategyStateChange(SignalStrategy::DISCONNECTED); host_status_logger_->SetSignalingStateForTest(SignalStrategy::DISCONNECTED);
message_loop_.Run(); message_loop_.Run();
} }
TEST_F(LogToServerTest, SendTwoEntriesLater) { TEST_F(HostStatusLoggerTest, SendTwoEntriesLater) {
protocol::TransportRoute route1; protocol::TransportRoute route1;
route1.type = protocol::TransportRoute::DIRECT; route1.type = protocol::TransportRoute::DIRECT;
log_to_server_->OnClientRouteChange(kClientJid1, "video", route1); host_status_logger_->OnClientRouteChange(kClientJid1, "video", route1);
log_to_server_->OnClientAuthenticated(kClientJid1); host_status_logger_->OnClientAuthenticated(kClientJid1);
log_to_server_->OnClientConnected(kClientJid1); host_status_logger_->OnClientConnected(kClientJid1);
protocol::TransportRoute route2; protocol::TransportRoute route2;
route2.type = protocol::TransportRoute::STUN; route2.type = protocol::TransportRoute::STUN;
log_to_server_->OnClientRouteChange(kClientJid2, "video", route2); host_status_logger_->OnClientRouteChange(kClientJid2, "video", route2);
log_to_server_->OnClientAuthenticated(kClientJid2); host_status_logger_->OnClientAuthenticated(kClientJid2);
log_to_server_->OnClientConnected(kClientJid2); host_status_logger_->OnClientConnected(kClientJid2);
{ {
InSequence s; InSequence s;
EXPECT_CALL(signal_strategy_, GetLocalJid()) EXPECT_CALL(signal_strategy_, GetLocalJid())
.WillRepeatedly(Return(kHostJid)); .WillRepeatedly(Return(kHostJid));
EXPECT_CALL(signal_strategy_, AddListener(_)); EXPECT_CALL(signal_strategy_, AddListener(_));
EXPECT_CALL(signal_strategy_, GetNextId()); EXPECT_CALL(signal_strategy_, GetNextId());
EXPECT_CALL(signal_strategy_, SendStanzaPtr( EXPECT_CALL(signal_strategy_,
IsTwoClientsConnected("direct", "stun"))) SendStanzaPtr(IsTwoClientsConnected("direct", "stun")))
.WillOnce(DoAll(DeleteArg<0>(), Return(true))); .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
EXPECT_CALL(signal_strategy_, RemoveListener(_)) EXPECT_CALL(signal_strategy_, RemoveListener(_))
.WillOnce(QuitMainMessageLoop(&message_loop_)) .WillOnce(QuitMainMessageLoop(&message_loop_))
.RetiresOnSaturation(); .RetiresOnSaturation();
} }
log_to_server_->OnSignalStrategyStateChange(SignalStrategy::CONNECTED); host_status_logger_->SetSignalingStateForTest(SignalStrategy::CONNECTED);
log_to_server_->OnSignalStrategyStateChange(SignalStrategy::DISCONNECTED); host_status_logger_->SetSignalingStateForTest(SignalStrategy::DISCONNECTED);
message_loop_.Run(); message_loop_.Run();
} }
TEST_F(LogToServerTest, HandleRouteChangeInUnusualOrder) { TEST_F(HostStatusLoggerTest, HandleRouteChangeInUnusualOrder) {
{ {
InSequence s; InSequence s;
EXPECT_CALL(signal_strategy_, GetLocalJid()) EXPECT_CALL(signal_strategy_, GetLocalJid())
...@@ -237,19 +239,19 @@ TEST_F(LogToServerTest, HandleRouteChangeInUnusualOrder) { ...@@ -237,19 +239,19 @@ TEST_F(LogToServerTest, HandleRouteChangeInUnusualOrder) {
.WillOnce(QuitMainMessageLoop(&message_loop_)) .WillOnce(QuitMainMessageLoop(&message_loop_))
.RetiresOnSaturation(); .RetiresOnSaturation();
} }
log_to_server_->OnSignalStrategyStateChange(SignalStrategy::CONNECTED); host_status_logger_->SetSignalingStateForTest(SignalStrategy::CONNECTED);
protocol::TransportRoute route1; protocol::TransportRoute route1;
route1.type = protocol::TransportRoute::DIRECT; route1.type = protocol::TransportRoute::DIRECT;
log_to_server_->OnClientRouteChange(kClientJid1, "video", route1); host_status_logger_->OnClientRouteChange(kClientJid1, "video", route1);
log_to_server_->OnClientAuthenticated(kClientJid1); host_status_logger_->OnClientAuthenticated(kClientJid1);
log_to_server_->OnClientConnected(kClientJid1); host_status_logger_->OnClientConnected(kClientJid1);
protocol::TransportRoute route2; protocol::TransportRoute route2;
route2.type = protocol::TransportRoute::STUN; route2.type = protocol::TransportRoute::STUN;
log_to_server_->OnClientRouteChange(kClientJid2, "video", route2); host_status_logger_->OnClientRouteChange(kClientJid2, "video", route2);
log_to_server_->OnClientDisconnected(kClientJid1); host_status_logger_->OnClientDisconnected(kClientJid1);
log_to_server_->OnClientAuthenticated(kClientJid2); host_status_logger_->OnClientAuthenticated(kClientJid2);
log_to_server_->OnClientConnected(kClientJid2); host_status_logger_->OnClientConnected(kClientJid2);
log_to_server_->OnSignalStrategyStateChange(SignalStrategy::DISCONNECTED); host_status_logger_->SetSignalingStateForTest(SignalStrategy::DISCONNECTED);
message_loop_.Run(); message_loop_.Run();
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "remoting/host/chromoting_host_context.h" #include "remoting/host/chromoting_host_context.h"
#include "remoting/host/host_event_logger.h" #include "remoting/host/host_event_logger.h"
#include "remoting/host/host_secret.h" #include "remoting/host/host_secret.h"
#include "remoting/host/host_status_logger.h"
#include "remoting/host/it2me_desktop_environment.h" #include "remoting/host/it2me_desktop_environment.h"
#include "remoting/host/policy_hack/policy_watcher.h" #include "remoting/host/policy_hack/policy_watcher.h"
#include "remoting/host/register_support_host_request.h" #include "remoting/host/register_support_host_request.h"
...@@ -205,9 +206,9 @@ void It2MeHost::FinishConnect() { ...@@ -205,9 +206,9 @@ void It2MeHost::FinishConnect() {
host_context_->network_task_runner(), host_context_->network_task_runner(),
host_context_->ui_task_runner())); host_context_->ui_task_runner()));
host_->AddStatusObserver(this); host_->AddStatusObserver(this);
log_to_server_.reset( host_status_logger_.reset(
new LogToServer(host_->AsWeakPtr(), ServerLogEntry::IT2ME, new HostStatusLogger(host_->AsWeakPtr(), ServerLogEntry::IT2ME,
signal_strategy_.get(), directory_bot_jid_)); signal_strategy_.get(), directory_bot_jid_));
// Disable audio by default. // Disable audio by default.
// TODO(sergeyu): Add UI to enable it. // TODO(sergeyu): Add UI to enable it.
...@@ -239,7 +240,7 @@ void It2MeHost::ShutdownOnNetworkThread() { ...@@ -239,7 +240,7 @@ void It2MeHost::ShutdownOnNetworkThread() {
host_.reset(); host_.reset();
register_request_.reset(); register_request_.reset();
log_to_server_.reset(); host_status_logger_.reset();
signal_strategy_.reset(); signal_strategy_.reset();
SetState(kDisconnected); SetState(kDisconnected);
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "remoting/host/log_to_server.h" #include "remoting/host/host_status_observer.h"
#include "remoting/jingle_glue/xmpp_signal_strategy.h" #include "remoting/jingle_glue/xmpp_signal_strategy.h"
namespace base { namespace base {
...@@ -23,6 +23,7 @@ class ChromotingHostContext; ...@@ -23,6 +23,7 @@ class ChromotingHostContext;
class DesktopEnvironmentFactory; class DesktopEnvironmentFactory;
class HostEventLogger; class HostEventLogger;
class HostNPScriptObject; class HostNPScriptObject;
class HostStatusLogger;
class RegisterSupportHostRequest; class RegisterSupportHostRequest;
class RsaKeyPair; class RsaKeyPair;
...@@ -46,11 +47,9 @@ enum It2MeHostState { ...@@ -46,11 +47,9 @@ enum It2MeHostState {
}; };
// Internal implementation of the plugin's It2Me host function. // Internal implementation of the plugin's It2Me host function.
class It2MeHost class It2MeHost : public base::RefCountedThreadSafe<It2MeHost>,
: public base::RefCountedThreadSafe<It2MeHost>, public HostStatusObserver {
public HostStatusObserver {
public: public:
class Observer { class Observer {
public: public:
virtual void OnClientAuthenticated(const std::string& client_username) = 0; virtual void OnClientAuthenticated(const std::string& client_username) = 0;
...@@ -146,7 +145,7 @@ class It2MeHost ...@@ -146,7 +145,7 @@ class It2MeHost
scoped_refptr<RsaKeyPair> host_key_pair_; scoped_refptr<RsaKeyPair> host_key_pair_;
scoped_ptr<SignalStrategy> signal_strategy_; scoped_ptr<SignalStrategy> signal_strategy_;
scoped_ptr<RegisterSupportHostRequest> register_request_; scoped_ptr<RegisterSupportHostRequest> register_request_;
scoped_ptr<LogToServer> log_to_server_; scoped_ptr<HostStatusLogger> host_status_logger_;
scoped_ptr<DesktopEnvironmentFactory> desktop_environment_factory_; scoped_ptr<DesktopEnvironmentFactory> desktop_environment_factory_;
scoped_ptr<HostEventLogger> host_event_logger_; scoped_ptr<HostEventLogger> host_event_logger_;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "base/strings/stringize_macros.h" #include "base/strings/stringize_macros.h"
#include "base/threading/thread.h" #include "base/threading/thread.h"
#include "base/values.h" #include "base/values.h"
#include "net/base/net_util.h"
#include "net/url_request/url_fetcher.h" #include "net/url_request/url_fetcher.h"
#include "remoting/base/auth_token_util.h" #include "remoting/base/auth_token_util.h"
#include "remoting/base/service_urls.h" #include "remoting/base/service_urls.h"
......
...@@ -53,12 +53,12 @@ ...@@ -53,12 +53,12 @@
#include "remoting/host/host_event_logger.h" #include "remoting/host/host_event_logger.h"
#include "remoting/host/host_exit_codes.h" #include "remoting/host/host_exit_codes.h"
#include "remoting/host/host_main.h" #include "remoting/host/host_main.h"
#include "remoting/host/host_status_logger.h"
#include "remoting/host/host_status_sender.h" #include "remoting/host/host_status_sender.h"
#include "remoting/host/ipc_constants.h" #include "remoting/host/ipc_constants.h"
#include "remoting/host/ipc_desktop_environment.h" #include "remoting/host/ipc_desktop_environment.h"
#include "remoting/host/ipc_host_event_logger.h" #include "remoting/host/ipc_host_event_logger.h"
#include "remoting/host/json_host_config.h" #include "remoting/host/json_host_config.h"
#include "remoting/host/log_to_server.h"
#include "remoting/host/logging.h" #include "remoting/host/logging.h"
#include "remoting/host/me2me_desktop_environment.h" #include "remoting/host/me2me_desktop_environment.h"
#include "remoting/host/pairing_registry_delegate.h" #include "remoting/host/pairing_registry_delegate.h"
...@@ -308,7 +308,7 @@ class HostProcess ...@@ -308,7 +308,7 @@ class HostProcess
scoped_ptr<HeartbeatSender> heartbeat_sender_; scoped_ptr<HeartbeatSender> heartbeat_sender_;
scoped_ptr<HostStatusSender> host_status_sender_; scoped_ptr<HostStatusSender> host_status_sender_;
scoped_ptr<HostChangeNotificationListener> host_change_notification_listener_; scoped_ptr<HostChangeNotificationListener> host_change_notification_listener_;
scoped_ptr<LogToServer> log_to_server_; scoped_ptr<HostStatusLogger> host_status_logger_;
scoped_ptr<HostEventLogger> host_event_logger_; scoped_ptr<HostEventLogger> host_event_logger_;
scoped_ptr<ChromotingHost> host_; scoped_ptr<ChromotingHost> host_;
...@@ -1220,9 +1220,9 @@ void HostProcess::StartHost() { ...@@ -1220,9 +1220,9 @@ void HostProcess::StartHost() {
host_change_notification_listener_.reset(new HostChangeNotificationListener( host_change_notification_listener_.reset(new HostChangeNotificationListener(
this, host_id_, signal_strategy_.get(), directory_bot_jid_)); this, host_id_, signal_strategy_.get(), directory_bot_jid_));
log_to_server_.reset( host_status_logger_.reset(
new LogToServer(host_->AsWeakPtr(), ServerLogEntry::ME2ME, new HostStatusLogger(host_->AsWeakPtr(), ServerLogEntry::ME2ME,
signal_strategy_.get(), directory_bot_jid_)); signal_strategy_.get(), directory_bot_jid_));
// Set up repoting the host status notifications. // Set up repoting the host status notifications.
#if defined(REMOTING_MULTI_PROCESS) #if defined(REMOTING_MULTI_PROCESS)
...@@ -1294,7 +1294,7 @@ void HostProcess::ShutdownOnNetworkThread() { ...@@ -1294,7 +1294,7 @@ void HostProcess::ShutdownOnNetworkThread() {
host_.reset(); host_.reset();
host_event_logger_.reset(); host_event_logger_.reset();
log_to_server_.reset(); host_status_logger_.reset();
heartbeat_sender_.reset(); heartbeat_sender_.reset();
host_status_sender_.reset(); host_status_sender_.reset();
host_change_notification_listener_.reset(); host_change_notification_listener_.reset();
......
// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "remoting/host/log_to_server.h" #include "remoting/jingle_glue/log_to_server.h"
#include "base/bind.h"
#include "base/message_loop/message_loop_proxy.h"
#include "remoting/base/constants.h" #include "remoting/base/constants.h"
#include "remoting/host/host_status_monitor.h"
#include "remoting/host/server_log_entry_host.h"
#include "remoting/jingle_glue/iq_sender.h" #include "remoting/jingle_glue/iq_sender.h"
#include "remoting/jingle_glue/server_log_entry.h"
#include "remoting/jingle_glue/signal_strategy.h" #include "remoting/jingle_glue/signal_strategy.h"
#include "remoting/protocol/transport.h"
#include "third_party/libjingle/source/talk/xmllite/xmlelement.h" #include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
#include "third_party/libjingle/source/talk/xmpp/constants.h" #include "third_party/libjingle/source/talk/xmpp/constants.h"
...@@ -21,38 +15,17 @@ using buzz::XmlElement; ...@@ -21,38 +15,17 @@ using buzz::XmlElement;
namespace remoting { namespace remoting {
LogToServer::LogToServer(base::WeakPtr<HostStatusMonitor> monitor, LogToServer::LogToServer(ServerLogEntry::Mode mode,
ServerLogEntry::Mode mode,
SignalStrategy* signal_strategy, SignalStrategy* signal_strategy,
const std::string& directory_bot_jid) const std::string& directory_bot_jid)
: monitor_(monitor), : mode_(mode),
mode_(mode),
signal_strategy_(signal_strategy), signal_strategy_(signal_strategy),
directory_bot_jid_(directory_bot_jid) { directory_bot_jid_(directory_bot_jid) {
monitor_->AddStatusObserver(this);
signal_strategy_->AddListener(this); signal_strategy_->AddListener(this);
} }
LogToServer::~LogToServer() { LogToServer::~LogToServer() {
signal_strategy_->RemoveListener(this); signal_strategy_->RemoveListener(this);
if (monitor_.get())
monitor_->RemoveStatusObserver(this);
}
void LogToServer::LogSessionStateChange(const std::string& jid,
bool connected) {
DCHECK(CalledOnValidThread());
scoped_ptr<ServerLogEntry> entry(
MakeLogEntryForSessionStateChange(connected));
AddHostFieldsToLogEntry(entry.get());
entry->AddModeField(mode_);
if (connected) {
DCHECK(connection_route_type_.count(jid) == 1);
AddConnectionTypeToLogEntry(entry.get(), connection_route_type_[jid]);
}
Log(*entry.get());
} }
void LogToServer::OnSignalStrategyStateChange(SignalStrategy::State state) { void LogToServer::OnSignalStrategyStateChange(SignalStrategy::State state) {
...@@ -71,27 +44,6 @@ bool LogToServer::OnSignalStrategyIncomingStanza( ...@@ -71,27 +44,6 @@ bool LogToServer::OnSignalStrategyIncomingStanza(
return false; return false;
} }
void LogToServer::OnClientConnected(const std::string& jid) {
DCHECK(CalledOnValidThread());
LogSessionStateChange(jid, true);
}
void LogToServer::OnClientDisconnected(const std::string& jid) {
DCHECK(CalledOnValidThread());
LogSessionStateChange(jid, false);
connection_route_type_.erase(jid);
}
void LogToServer::OnClientRouteChange(const std::string& jid,
const std::string& channel_name,
const protocol::TransportRoute& route) {
// Store connection type for the video channel. It is logged later
// when client authentication is finished.
if (channel_name == kVideoChannelName) {
connection_route_type_[jid] = route.type;
}
}
void LogToServer::Log(const ServerLogEntry& entry) { void LogToServer::Log(const ServerLogEntry& entry) {
pending_entries_.push_back(entry); pending_entries_.push_back(entry);
SendPendingEntries(); SendPendingEntries();
......
...@@ -2,19 +2,16 @@ ...@@ -2,19 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef REMOTING_CLIENT_LOG_TO_SERVER_H_ #ifndef REMOTING_JINGLE_GLUE_LOG_TO_SERVER_H_
#define REMOTING_CLIENT_LOG_TO_SERVER_H_ #define REMOTING_JINGLE_GLUE_LOG_TO_SERVER_H_
#include <deque> #include <deque>
#include <map> #include <map>
#include <string> #include <string>
#include "base/threading/non_thread_safe.h" #include "base/threading/non_thread_safe.h"
#include "base/time/time.h"
#include "remoting/jingle_glue/server_log_entry.h" #include "remoting/jingle_glue/server_log_entry.h"
#include "remoting/jingle_glue/signal_strategy.h" #include "remoting/jingle_glue/signal_strategy.h"
#include "remoting/protocol/connection_to_host.h"
#include "remoting/protocol/errors.h"
namespace buzz { namespace buzz {
class XmlElement; class XmlElement;
...@@ -22,15 +19,8 @@ class XmlElement; ...@@ -22,15 +19,8 @@ class XmlElement;
namespace remoting { namespace remoting {
class ChromotingStats;
class IqSender; class IqSender;
// Temporary namespace to prevent conflict with the same-named class in
// remoting/host when linking unittests.
//
// TODO(lambroslambrou): Remove this and factor out any shared code.
namespace client {
// LogToServer sends log entries to a server. // LogToServer sends log entries to a server.
// The contents of the log entries are described in server_log_entry.cc. // The contents of the log entries are described in server_log_entry.cc.
// They do not contain any personally identifiable information. // They do not contain any personally identifiable information.
...@@ -42,26 +32,18 @@ class LogToServer : public base::NonThreadSafe, ...@@ -42,26 +32,18 @@ class LogToServer : public base::NonThreadSafe,
const std::string& directory_bot_jid); const std::string& directory_bot_jid);
virtual ~LogToServer(); virtual ~LogToServer();
// Logs a session state change.
void LogSessionStateChange(protocol::ConnectionToHost::State state,
protocol::ErrorCode error);
void LogStatistics(remoting::ChromotingStats* statistics);
// SignalStrategy::Listener interface. // SignalStrategy::Listener interface.
virtual void OnSignalStrategyStateChange( virtual void OnSignalStrategyStateChange(
SignalStrategy::State state) OVERRIDE; SignalStrategy::State state) OVERRIDE;
virtual bool OnSignalStrategyIncomingStanza( virtual bool OnSignalStrategyIncomingStanza(
const buzz::XmlElement* stanza) OVERRIDE; const buzz::XmlElement* stanza) OVERRIDE;
private:
void Log(const ServerLogEntry& entry); void Log(const ServerLogEntry& entry);
void SendPendingEntries();
// Generates a new random session ID. ServerLogEntry::Mode mode() { return mode_; }
void GenerateSessionId();
// Expire the session ID if the maximum duration has been exceeded. private:
void MaybeExpireSessionId(); void SendPendingEntries();
ServerLogEntry::Mode mode_; ServerLogEntry::Mode mode_;
SignalStrategy* signal_strategy_; SignalStrategy* signal_strategy_;
...@@ -70,21 +52,9 @@ class LogToServer : public base::NonThreadSafe, ...@@ -70,21 +52,9 @@ class LogToServer : public base::NonThreadSafe,
std::deque<ServerLogEntry> pending_entries_; std::deque<ServerLogEntry> pending_entries_;
// A randomly generated session ID to be attached to log messages. This
// is regenerated at the start of a new session.
std::string session_id_;
// Start time of the session.
base::TimeTicks session_start_time_;
// Time when the session ID was generated.
base::TimeTicks session_id_generation_time_;
DISALLOW_COPY_AND_ASSIGN(LogToServer); DISALLOW_COPY_AND_ASSIGN(LogToServer);
}; };
} // namespace client
} // namespace remoting } // namespace remoting
#endif // REMOTING_CLIENT_LOG_TO_SERVER_H_ #endif // REMOTING_JINGLE_GLUE_LOG_TO_SERVER_H_
// Copyright 2014 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.
#include "remoting/jingle_glue/log_to_server.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "remoting/jingle_glue/mock_objects.h"
#include "remoting/jingle_glue/server_log_entry_unittest.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using buzz::XmlElement;
using buzz::QName;
using testing::_;
using testing::DeleteArg;
using testing::InSequence;
using testing::Return;
namespace remoting {
namespace {
const char kTestBotJid[] = "remotingunittest@bot.talk.google.com";
const char kClientJid[] = "host@domain.com/1234";
MATCHER_P2(IsLogEntry, key, value, "") {
XmlElement* entry = GetSingleLogEntryFromStanza(arg);
if (!entry) {
return false;
}
return entry->Attr(QName(std::string(), key)) == value;
}
} // namespace
class LogToServerTest : public testing::Test {
public:
LogToServerTest() {}
virtual void SetUp() OVERRIDE {
EXPECT_CALL(signal_strategy_, AddListener(_));
EXPECT_CALL(signal_strategy_, RemoveListener(_));
log_to_server_.reset(
new LogToServer(ServerLogEntry::ME2ME, &signal_strategy_, kTestBotJid));
}
protected:
base::MessageLoop message_loop_;
base::RunLoop run_loop_;
MockSignalStrategy signal_strategy_;
scoped_ptr<LogToServer> log_to_server_;
};
TEST_F(LogToServerTest, LogWhenConnected) {
{
InSequence s;
EXPECT_CALL(signal_strategy_, GetLocalJid())
.WillRepeatedly(Return(kClientJid));
EXPECT_CALL(signal_strategy_, AddListener(_));
EXPECT_CALL(signal_strategy_, GetNextId());
EXPECT_CALL(signal_strategy_, SendStanzaPtr(IsLogEntry("a", "1")))
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
EXPECT_CALL(signal_strategy_, GetNextId());
EXPECT_CALL(signal_strategy_, SendStanzaPtr(IsLogEntry("b", "2")))
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
EXPECT_CALL(signal_strategy_, RemoveListener(_))
.RetiresOnSaturation();
}
ServerLogEntry entry1;
ServerLogEntry entry2;
entry1.Set("a", "1");
entry2.Set("b", "2");
log_to_server_->Log(entry1);
log_to_server_->OnSignalStrategyStateChange(SignalStrategy::CONNECTED);
log_to_server_->Log(entry2);
run_loop_.RunUntilIdle();
}
TEST_F(LogToServerTest, DontLogWhenDisconnected) {
EXPECT_CALL(signal_strategy_, GetLocalJid())
.WillRepeatedly(Return(kClientJid));
EXPECT_CALL(signal_strategy_, SendStanzaPtr(_)).Times(0);
ServerLogEntry entry;
entry.Set("foo", "bar");
log_to_server_->Log(entry);
run_loop_.RunUntilIdle();
}
} // namespace remoting
...@@ -6,13 +6,53 @@ ...@@ -6,13 +6,53 @@
#include <sstream> #include <sstream>
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/libjingle/source/talk/xmllite/xmlelement.h" #include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
using buzz::QName;
using buzz::XmlAttr; using buzz::XmlAttr;
using buzz::XmlElement; using buzz::XmlElement;
namespace remoting { namespace remoting {
const char kJabberClientNamespace[] = "jabber:client";
const char kChromotingNamespace[] = "google:remoting";
XmlElement* GetLogElementFromStanza(XmlElement* stanza) {
if (stanza->Name() != QName(kJabberClientNamespace, "iq")) {
ADD_FAILURE() << "Expected element 'iq'";
return NULL;
}
XmlElement* log_element = stanza->FirstChild()->AsElement();
if (log_element->Name() != QName(kChromotingNamespace, "log")) {
ADD_FAILURE() << "Expected element 'log'";
return NULL;
}
if (log_element->NextChild()) {
ADD_FAILURE() << "Expected only 1 child of 'iq'";
return NULL;
}
return log_element;
}
XmlElement* GetSingleLogEntryFromStanza(XmlElement* stanza) {
XmlElement* log_element = GetLogElementFromStanza(stanza);
if (!log_element) {
// Test failure already recorded, so just return NULL here.
return NULL;
}
XmlElement* entry = log_element->FirstChild()->AsElement();
if (entry->Name() != QName(kChromotingNamespace, "entry")) {
ADD_FAILURE() << "Expected element 'entry'";
return NULL;
}
if (entry->NextChild()) {
ADD_FAILURE() << "Expected only 1 child of 'log'";
return NULL;
}
return entry;
}
bool VerifyStanza( bool VerifyStanza(
const std::map<std::string, std::string>& key_value_pairs, const std::map<std::string, std::string>& key_value_pairs,
const std::set<std::string> keys, const std::set<std::string> keys,
......
...@@ -12,6 +12,17 @@ class XmlElement; ...@@ -12,6 +12,17 @@ class XmlElement;
namespace remoting { namespace remoting {
extern const char kJabberClientNamespace[];
extern const char kChromotingNamespace[];
// Verifies that |stanza| contains a <log> element and returns it. Otherwise
// returns NULL and records a test failure.
buzz::XmlElement* GetLogElementFromStanza(buzz::XmlElement* stanza);
// Verifies that |stanza| contains only 1 log entry, and returns the <entry>
// element. Otherwise returns NULL and records a test failure.
buzz::XmlElement* GetSingleLogEntryFromStanza(buzz::XmlElement* stanza);
// Verifies a logging stanza. // Verifies a logging stanza.
// |keyValuePairs| lists the keys that must have specified values, and |keys| // |keyValuePairs| lists the keys that must have specified values, and |keys|
// lists the keys that must be present, but may have arbitrary values. // lists the keys that must be present, but may have arbitrary values.
......
...@@ -141,6 +141,8 @@ ...@@ -141,6 +141,8 @@
'host/host_extension_session.h', 'host/host_extension_session.h',
'host/host_secret.cc', 'host/host_secret.cc',
'host/host_secret.h', 'host/host_secret.h',
'host/host_status_logger.cc',
'host/host_status_logger.h',
'host/host_status_monitor.h', 'host/host_status_monitor.h',
'host/host_status_observer.h', 'host/host_status_observer.h',
'host/host_status_sender.cc', 'host/host_status_sender.cc',
...@@ -187,8 +189,6 @@ ...@@ -187,8 +189,6 @@
'host/local_input_monitor_linux.cc', 'host/local_input_monitor_linux.cc',
'host/local_input_monitor_mac.mm', 'host/local_input_monitor_mac.mm',
'host/local_input_monitor_win.cc', 'host/local_input_monitor_win.cc',
'host/log_to_server.cc',
'host/log_to_server.h',
'host/logging.h', 'host/logging.h',
'host/logging_posix.cc', 'host/logging_posix.cc',
'host/logging_win.cc', 'host/logging_win.cc',
......
...@@ -75,6 +75,8 @@ ...@@ -75,6 +75,8 @@
'jingle_glue/iq_sender.h', 'jingle_glue/iq_sender.h',
'jingle_glue/jingle_info_request.cc', 'jingle_glue/jingle_info_request.cc',
'jingle_glue/jingle_info_request.h', 'jingle_glue/jingle_info_request.h',
'jingle_glue/log_to_server.cc',
'jingle_glue/log_to_server.h',
'jingle_glue/network_settings.cc', 'jingle_glue/network_settings.cc',
'jingle_glue/network_settings.h', 'jingle_glue/network_settings.h',
'jingle_glue/server_log_entry.cc', 'jingle_glue/server_log_entry.cc',
...@@ -209,6 +211,8 @@ ...@@ -209,6 +211,8 @@
'client/client_config.h', 'client/client_config.h',
'client/client_context.cc', 'client/client_context.cc',
'client/client_context.h', 'client/client_context.h',
'client/client_status_logger.cc',
'client/client_status_logger.h',
'client/client_user_interface.h', 'client/client_user_interface.h',
'client/frame_consumer.h', 'client/frame_consumer.h',
'client/frame_consumer_proxy.cc', 'client/frame_consumer_proxy.cc',
...@@ -216,8 +220,6 @@ ...@@ -216,8 +220,6 @@
'client/frame_producer.h', 'client/frame_producer.h',
'client/key_event_mapper.cc', 'client/key_event_mapper.cc',
'client/key_event_mapper.h', 'client/key_event_mapper.h',
'client/log_to_server.cc',
'client/log_to_server.h',
'client/server_log_entry_client.cc', 'client/server_log_entry_client.cc',
'client/server_log_entry_client.h', 'client/server_log_entry_client.h',
'client/software_video_renderer.cc', 'client/software_video_renderer.cc',
......
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
'base/typed_buffer_unittest.cc', 'base/typed_buffer_unittest.cc',
'base/util_unittest.cc', 'base/util_unittest.cc',
'client/audio_player_unittest.cc', 'client/audio_player_unittest.cc',
'client/client_status_logger_unittest.cc',
'client/key_event_mapper_unittest.cc', 'client/key_event_mapper_unittest.cc',
'client/plugin/normalizing_input_filter_cros_unittest.cc', 'client/plugin/normalizing_input_filter_cros_unittest.cc',
'client/plugin/normalizing_input_filter_mac_unittest.cc', 'client/plugin/normalizing_input_filter_mac_unittest.cc',
...@@ -80,6 +81,7 @@ ...@@ -80,6 +81,7 @@
'host/heartbeat_sender_unittest.cc', 'host/heartbeat_sender_unittest.cc',
'host/host_change_notification_listener_unittest.cc', 'host/host_change_notification_listener_unittest.cc',
'host/host_mock_objects.cc', 'host/host_mock_objects.cc',
'host/host_status_logger_unittest.cc',
'host/host_status_monitor_fake.h', 'host/host_status_monitor_fake.h',
'host/host_status_sender_unittest.cc', 'host/host_status_sender_unittest.cc',
'host/ipc_desktop_environment_unittest.cc', 'host/ipc_desktop_environment_unittest.cc',
...@@ -89,7 +91,6 @@ ...@@ -89,7 +91,6 @@
'host/linux/unicode_to_keysym_unittest.cc', 'host/linux/unicode_to_keysym_unittest.cc',
'host/linux/x_server_clipboard_unittest.cc', 'host/linux/x_server_clipboard_unittest.cc',
'host/local_input_monitor_unittest.cc', 'host/local_input_monitor_unittest.cc',
'host/log_to_server_unittest.cc',
'host/native_messaging/native_messaging_reader_unittest.cc', 'host/native_messaging/native_messaging_reader_unittest.cc',
'host/native_messaging/native_messaging_writer_unittest.cc', 'host/native_messaging/native_messaging_writer_unittest.cc',
'host/pairing_registry_delegate_linux_unittest.cc', 'host/pairing_registry_delegate_linux_unittest.cc',
...@@ -124,6 +125,7 @@ ...@@ -124,6 +125,7 @@
'jingle_glue/fake_signal_strategy.cc', 'jingle_glue/fake_signal_strategy.cc',
'jingle_glue/fake_signal_strategy.h', 'jingle_glue/fake_signal_strategy.h',
'jingle_glue/iq_sender_unittest.cc', 'jingle_glue/iq_sender_unittest.cc',
'jingle_glue/log_to_server_unittest.cc',
'jingle_glue/mock_objects.cc', 'jingle_glue/mock_objects.cc',
'jingle_glue/mock_objects.h', 'jingle_glue/mock_objects.h',
'jingle_glue/network_settings_unittest.cc', 'jingle_glue/network_settings_unittest.cc',
......
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