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