Make ScriptInjections share more logic
[chromium-blink-merge.git] / remoting / client / log_to_server.cc
blobe29de13584babf3a25cc8cf46d6c87a54063303d
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "remoting/client/log_to_server.h"
7 #include "base/macros.h"
8 #include "base/rand_util.h"
9 #include "remoting/base/constants.h"
10 #include "remoting/client/chromoting_stats.h"
11 #include "remoting/client/server_log_entry_client.h"
12 #include "remoting/jingle_glue/iq_sender.h"
13 #include "remoting/jingle_glue/signal_strategy.h"
14 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
15 #include "third_party/libjingle/source/talk/xmpp/constants.h"
17 using buzz::QName;
18 using buzz::XmlElement;
19 using remoting::protocol::ConnectionToHost;
21 namespace {
23 const char kSessionIdAlphabet[] =
24 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
25 const int kSessionIdLength = 20;
27 const int kMaxSessionIdAgeDays = 1;
29 bool IsStartOfSession(ConnectionToHost::State state) {
30 return state == ConnectionToHost::INITIALIZING ||
31 state == ConnectionToHost::CONNECTING ||
32 state == ConnectionToHost::AUTHENTICATED ||
33 state == ConnectionToHost::CONNECTED;
36 bool IsEndOfSession(ConnectionToHost::State state) {
37 return state == ConnectionToHost::FAILED ||
38 state == ConnectionToHost::CLOSED;
41 bool ShouldAddDuration(ConnectionToHost::State state) {
42 // Duration is added to log entries at the end of the session, as well as at
43 // some intermediate states where it is relevant (e.g. to determine how long
44 // it took for a session to become CONNECTED).
45 return IsEndOfSession(state) || state == ConnectionToHost::CONNECTED;
48 } // namespace
50 namespace remoting {
52 namespace client {
54 LogToServer::LogToServer(ServerLogEntry::Mode mode,
55 SignalStrategy* signal_strategy,
56 const std::string& directory_bot_jid)
57 : mode_(mode),
58 signal_strategy_(signal_strategy),
59 directory_bot_jid_(directory_bot_jid) {
60 signal_strategy_->AddListener(this);
63 LogToServer::~LogToServer() {
64 signal_strategy_->RemoveListener(this);
67 void LogToServer::LogSessionStateChange(
68 protocol::ConnectionToHost::State state,
69 protocol::ErrorCode error) {
70 DCHECK(CalledOnValidThread());
72 scoped_ptr<ServerLogEntry> entry(
73 MakeLogEntryForSessionStateChange(state, error));
74 AddClientFieldsToLogEntry(entry.get());
75 entry->AddModeField(mode_);
77 MaybeExpireSessionId();
78 if (IsStartOfSession(state)) {
79 // Maybe set the session ID and start time.
80 if (session_id_.empty()) {
81 GenerateSessionId();
83 if (session_start_time_.is_null()) {
84 session_start_time_ = base::TimeTicks::Now();
88 if (!session_id_.empty()) {
89 AddSessionIdToLogEntry(entry.get(), session_id_);
92 // Maybe clear the session start time and log the session duration.
93 if (ShouldAddDuration(state) && !session_start_time_.is_null()) {
94 AddSessionDurationToLogEntry(entry.get(),
95 base::TimeTicks::Now() - session_start_time_);
98 if (IsEndOfSession(state)) {
99 session_start_time_ = base::TimeTicks();
100 session_id_.clear();
103 Log(*entry.get());
106 void LogToServer::LogStatistics(ChromotingStats* statistics) {
107 DCHECK(CalledOnValidThread());
109 MaybeExpireSessionId();
111 scoped_ptr<ServerLogEntry> entry(MakeLogEntryForStatistics(statistics));
112 AddClientFieldsToLogEntry(entry.get());
113 entry->AddModeField(mode_);
114 AddSessionIdToLogEntry(entry.get(), session_id_);
115 Log(*entry.get());
118 void LogToServer::OnSignalStrategyStateChange(SignalStrategy::State state) {
119 DCHECK(CalledOnValidThread());
121 if (state == SignalStrategy::CONNECTED) {
122 iq_sender_.reset(new IqSender(signal_strategy_));
123 SendPendingEntries();
124 } else if (state == SignalStrategy::DISCONNECTED) {
125 iq_sender_.reset();
129 bool LogToServer::OnSignalStrategyIncomingStanza(
130 const buzz::XmlElement* stanza) {
131 return false;
134 void LogToServer::Log(const ServerLogEntry& entry) {
135 pending_entries_.push_back(entry);
136 SendPendingEntries();
139 void LogToServer::SendPendingEntries() {
140 if (iq_sender_ == NULL) {
141 return;
143 if (pending_entries_.empty()) {
144 return;
146 // Make one stanza containing all the pending entries.
147 scoped_ptr<XmlElement> stanza(ServerLogEntry::MakeStanza());
148 while (!pending_entries_.empty()) {
149 ServerLogEntry& entry = pending_entries_.front();
150 stanza->AddElement(entry.ToStanza().release());
151 pending_entries_.pop_front();
153 // Send the stanza to the server.
154 scoped_ptr<IqRequest> req = iq_sender_->SendIq(
155 buzz::STR_SET, directory_bot_jid_, stanza.Pass(),
156 IqSender::ReplyCallback());
157 // We ignore any response, so let the IqRequest be destroyed.
158 return;
161 void LogToServer::GenerateSessionId() {
162 session_id_.resize(kSessionIdLength);
163 for (int i = 0; i < kSessionIdLength; i++) {
164 const int alphabet_size = arraysize(kSessionIdAlphabet) - 1;
165 session_id_[i] = kSessionIdAlphabet[base::RandGenerator(alphabet_size)];
167 session_id_generation_time_ = base::TimeTicks::Now();
170 void LogToServer::MaybeExpireSessionId() {
171 if (session_id_.empty()) {
172 return;
175 base::TimeDelta max_age = base::TimeDelta::FromDays(kMaxSessionIdAgeDays);
176 if (base::TimeTicks::Now() - session_id_generation_time_ > max_age) {
177 // Log the old session ID.
178 scoped_ptr<ServerLogEntry> entry(MakeLogEntryForSessionIdOld(session_id_));
179 entry->AddModeField(mode_);
180 Log(*entry.get());
182 // Generate a new session ID.
183 GenerateSessionId();
185 // Log the new session ID.
186 entry = MakeLogEntryForSessionIdNew(session_id_);
187 entry->AddModeField(mode_);
188 Log(*entry.get());
192 } // namespace client
194 } // namespace remoting