1// Copyright (c) 2012 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.
4
5#include "sync/internal_api/debug_info_event_listener.h"
6
7#include "sync/util/cryptographer.h"
8
9namespace syncer {
10
11using sessions::SyncSessionSnapshot;
12
13DebugInfoEventListener::DebugInfoEventListener()
14    : events_dropped_(false),
15      cryptographer_has_pending_keys_(false),
16      cryptographer_ready_(false),
17      weak_ptr_factory_(this) {
18}
19
20DebugInfoEventListener::~DebugInfoEventListener() {
21}
22
23void DebugInfoEventListener::OnSyncCycleCompleted(
24    const SyncSessionSnapshot& snapshot) {
25  DCHECK(thread_checker_.CalledOnValidThread());
26  sync_pb::DebugEventInfo event_info;
27  sync_pb::SyncCycleCompletedEventInfo* sync_completed_event_info =
28      event_info.mutable_sync_cycle_completed_event_info();
29
30  sync_completed_event_info->set_num_encryption_conflicts(
31      snapshot.num_encryption_conflicts());
32  sync_completed_event_info->set_num_hierarchy_conflicts(
33      snapshot.num_hierarchy_conflicts());
34  sync_completed_event_info->set_num_server_conflicts(
35      snapshot.num_server_conflicts());
36
37  sync_completed_event_info->set_num_updates_downloaded(
38      snapshot.model_neutral_state().num_updates_downloaded_total);
39  sync_completed_event_info->set_num_reflected_updates_downloaded(
40      snapshot.model_neutral_state().num_reflected_updates_downloaded_total);
41  sync_completed_event_info->mutable_caller_info()->set_source(
42      snapshot.legacy_updates_source());
43  sync_completed_event_info->mutable_caller_info()->set_notifications_enabled(
44      snapshot.notifications_enabled());
45
46  AddEventToQueue(event_info);
47}
48
49void DebugInfoEventListener::OnInitializationComplete(
50    const WeakHandle<JsBackend>& js_backend,
51    const WeakHandle<DataTypeDebugInfoListener>& debug_listener,
52    bool success, ModelTypeSet restored_types) {
53  DCHECK(thread_checker_.CalledOnValidThread());
54  CreateAndAddEvent(sync_pb::SyncEnums::INITIALIZATION_COMPLETE);
55}
56
57void DebugInfoEventListener::OnConnectionStatusChange(
58    ConnectionStatus status) {
59  DCHECK(thread_checker_.CalledOnValidThread());
60  CreateAndAddEvent(sync_pb::SyncEnums::CONNECTION_STATUS_CHANGE);
61}
62
63void DebugInfoEventListener::OnPassphraseRequired(
64    PassphraseRequiredReason reason,
65    const sync_pb::EncryptedData& pending_keys) {
66  DCHECK(thread_checker_.CalledOnValidThread());
67  CreateAndAddEvent(sync_pb::SyncEnums::PASSPHRASE_REQUIRED);
68}
69
70void DebugInfoEventListener::OnPassphraseAccepted() {
71  DCHECK(thread_checker_.CalledOnValidThread());
72  CreateAndAddEvent(sync_pb::SyncEnums::PASSPHRASE_ACCEPTED);
73}
74
75void DebugInfoEventListener::OnBootstrapTokenUpdated(
76    const std::string& bootstrap_token, BootstrapTokenType type) {
77  DCHECK(thread_checker_.CalledOnValidThread());
78  if (type == PASSPHRASE_BOOTSTRAP_TOKEN) {
79    CreateAndAddEvent(sync_pb::SyncEnums::BOOTSTRAP_TOKEN_UPDATED);
80    return;
81  }
82  DCHECK_EQ(type, KEYSTORE_BOOTSTRAP_TOKEN);
83  CreateAndAddEvent(sync_pb::SyncEnums::KEYSTORE_TOKEN_UPDATED);
84}
85
86void DebugInfoEventListener::OnEncryptedTypesChanged(
87    ModelTypeSet encrypted_types,
88    bool encrypt_everything) {
89  DCHECK(thread_checker_.CalledOnValidThread());
90  CreateAndAddEvent(sync_pb::SyncEnums::ENCRYPTED_TYPES_CHANGED);
91}
92
93void DebugInfoEventListener::OnEncryptionComplete() {
94  DCHECK(thread_checker_.CalledOnValidThread());
95  CreateAndAddEvent(sync_pb::SyncEnums::ENCRYPTION_COMPLETE);
96}
97
98void DebugInfoEventListener::OnCryptographerStateChanged(
99    Cryptographer* cryptographer) {
100  DCHECK(thread_checker_.CalledOnValidThread());
101  cryptographer_has_pending_keys_ = cryptographer->has_pending_keys();
102  cryptographer_ready_ = cryptographer->is_ready();
103}
104
105void DebugInfoEventListener::OnPassphraseTypeChanged(
106    PassphraseType type,
107    base::Time explicit_passphrase_time) {
108  DCHECK(thread_checker_.CalledOnValidThread());
109  CreateAndAddEvent(sync_pb::SyncEnums::PASSPHRASE_TYPE_CHANGED);
110}
111
112void DebugInfoEventListener::OnActionableError(
113    const SyncProtocolError& sync_error) {
114  DCHECK(thread_checker_.CalledOnValidThread());
115  CreateAndAddEvent(sync_pb::SyncEnums::ACTIONABLE_ERROR);
116}
117
118void DebugInfoEventListener::OnMigrationRequested(ModelTypeSet types) {}
119
120void DebugInfoEventListener::OnProtocolEvent(const ProtocolEvent& event) {}
121
122void DebugInfoEventListener::OnNudgeFromDatatype(ModelType datatype) {
123  DCHECK(thread_checker_.CalledOnValidThread());
124  sync_pb::DebugEventInfo event_info;
125  event_info.set_nudging_datatype(
126      GetSpecificsFieldNumberFromModelType(datatype));
127  AddEventToQueue(event_info);
128}
129
130void DebugInfoEventListener::GetDebugInfo(sync_pb::DebugInfo* debug_info) {
131  DCHECK(thread_checker_.CalledOnValidThread());
132  DCHECK_LE(events_.size(), kMaxEntries);
133
134  for (DebugEventInfoQueue::const_iterator iter = events_.begin();
135       iter != events_.end();
136       ++iter) {
137    sync_pb::DebugEventInfo* event_info = debug_info->add_events();
138    event_info->CopyFrom(*iter);
139  }
140
141  debug_info->set_events_dropped(events_dropped_);
142  debug_info->set_cryptographer_ready(cryptographer_ready_);
143  debug_info->set_cryptographer_has_pending_keys(
144      cryptographer_has_pending_keys_);
145}
146
147void DebugInfoEventListener::ClearDebugInfo() {
148  DCHECK(thread_checker_.CalledOnValidThread());
149  DCHECK_LE(events_.size(), kMaxEntries);
150
151  events_.clear();
152  events_dropped_ = false;
153}
154
155base::WeakPtr<DataTypeDebugInfoListener> DebugInfoEventListener::GetWeakPtr() {
156  DCHECK(thread_checker_.CalledOnValidThread());
157  return weak_ptr_factory_.GetWeakPtr();
158}
159
160void DebugInfoEventListener::OnDataTypeConfigureComplete(
161    const std::vector<DataTypeConfigurationStats>& configuration_stats) {
162  DCHECK(thread_checker_.CalledOnValidThread());
163
164  for (size_t i = 0; i < configuration_stats.size(); ++i) {
165    DCHECK(ProtocolTypes().Has(configuration_stats[i].model_type));
166    const DataTypeAssociationStats& association_stats =
167        configuration_stats[i].association_stats;
168
169    sync_pb::DebugEventInfo association_event;
170    sync_pb::DatatypeAssociationStats* datatype_stats =
171        association_event.mutable_datatype_association_stats();
172    datatype_stats->set_data_type_id(
173        GetSpecificsFieldNumberFromModelType(
174            configuration_stats[i].model_type));
175    datatype_stats->set_num_local_items_before_association(
176        association_stats.num_local_items_before_association);
177    datatype_stats->set_num_sync_items_before_association(
178        association_stats.num_sync_items_before_association);
179    datatype_stats->set_num_local_items_after_association(
180        association_stats.num_local_items_after_association);
181    datatype_stats->set_num_sync_items_after_association(
182        association_stats.num_sync_items_after_association);
183    datatype_stats->set_num_local_items_added(
184        association_stats.num_local_items_added);
185    datatype_stats->set_num_local_items_deleted(
186        association_stats.num_local_items_deleted);
187    datatype_stats->set_num_local_items_modified(
188        association_stats.num_local_items_modified);
189    datatype_stats->set_num_sync_items_added(
190        association_stats.num_sync_items_added);
191    datatype_stats->set_num_sync_items_deleted(
192        association_stats.num_sync_items_deleted);
193    datatype_stats->set_num_sync_items_modified(
194        association_stats.num_sync_items_modified);
195    datatype_stats->set_local_version_pre_association(
196        association_stats.local_version_pre_association);
197    datatype_stats->set_sync_version_pre_association(
198        association_stats.sync_version_pre_association);
199    datatype_stats->set_had_error(association_stats.had_error);
200    datatype_stats->set_association_wait_time_for_same_priority_us(
201          association_stats.association_wait_time.InMicroseconds());
202    datatype_stats->set_association_time_us(
203        association_stats.association_time.InMicroseconds());
204    datatype_stats->set_download_wait_time_us(
205        configuration_stats[i].download_wait_time.InMicroseconds());
206    datatype_stats->set_download_time_us(
207        configuration_stats[i].download_time.InMicroseconds());
208    datatype_stats->set_association_wait_time_for_high_priority_us(
209        configuration_stats[i].association_wait_time_for_high_priority
210            .InMicroseconds());
211
212    for (ModelTypeSet::Iterator it =
213             configuration_stats[i].high_priority_types_configured_before
214                 .First();
215         it.Good(); it.Inc()) {
216      datatype_stats->add_high_priority_type_configured_before(
217          GetSpecificsFieldNumberFromModelType(it.Get()));
218    }
219
220    for (ModelTypeSet::Iterator it =
221             configuration_stats[i].same_priority_types_configured_before
222                 .First();
223        it.Good(); it.Inc()) {
224      datatype_stats->add_same_priority_type_configured_before(
225          GetSpecificsFieldNumberFromModelType(it.Get()));
226    }
227
228    AddEventToQueue(association_event);
229  }
230}
231
232void DebugInfoEventListener::CreateAndAddEvent(
233    sync_pb::SyncEnums::SingletonDebugEventType type) {
234  DCHECK(thread_checker_.CalledOnValidThread());
235  sync_pb::DebugEventInfo event_info;
236  event_info.set_singleton_event(type);
237  AddEventToQueue(event_info);
238}
239
240void DebugInfoEventListener::AddEventToQueue(
241  const sync_pb::DebugEventInfo& event_info) {
242  DCHECK(thread_checker_.CalledOnValidThread());
243  if (events_.size() >= kMaxEntries) {
244    DVLOG(1) << "DebugInfoEventListener::AddEventToQueue Dropping an old event "
245             << "because of full queue";
246
247    events_.pop_front();
248    events_dropped_ = true;
249  }
250  events_.push_back(event_info);
251}
252
253}  // namespace syncer
254