Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(721)

Side by Side Diff: components/sync_driver/about_sync_util.cc

Issue 2203673002: [Sync] Move //components/sync_driver to //components/sync/driver. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@sd-a
Patch Set: Full change rebased on static lib. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 "components/sync_driver/about_sync_util.h"
6
7 #include <string>
8 #include <utility>
9
10 #include "base/location.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/values.h"
14 #include "components/signin/core/browser/signin_manager_base.h"
15 #include "components/sync/api/time.h"
16 #include "components/sync/base/sync_string_conversions.h"
17 #include "components/sync/engine/sync_status.h"
18 #include "components/sync/protocol/proto_enum_conversions.h"
19 #include "components/sync/sessions/sync_session_snapshot.h"
20 #include "components/sync_driver/sync_service.h"
21 #include "components/version_info/version_info.h"
22
23 using base::DictionaryValue;
24 using base::ListValue;
25
26 namespace sync_driver {
27
28 namespace sync_ui_util {
29
30 const char kIdentityTitle[] = "Identity";
31 const char kDetailsKey[] = "details";
32
33 // Resource paths.
34 const char kAboutJS[] = "about.js";
35 const char kChromeSyncJS[] = "chrome_sync.js";
36 const char kDataJS[] = "data.js";
37 const char kEventsJS[] = "events.js";
38 const char kSearchJS[] = "search.js";
39 const char kSyncIndexJS[] = "sync_index.js";
40 const char kSyncLogJS[] = "sync_log.js";
41 const char kSyncNodeBrowserJS[] = "sync_node_browser.js";
42 const char kSyncSearchJS[] = "sync_search.js";
43 const char kTypesJS[] = "types.js";
44
45 // Message handlers.
46 const char kDispatchEvent[] = "chrome.sync.dispatchEvent";
47 const char kGetAllNodes[] = "getAllNodes";
48 const char kGetAllNodesCallback[] = "chrome.sync.getAllNodesCallback";
49 const char kRegisterForEvents[] = "registerForEvents";
50 const char kRegisterForPerTypeCounters[] = "registerForPerTypeCounters";
51 const char kRequestListOfTypes[] = "requestListOfTypes";
52 const char kRequestUpdatedAboutInfo[] = "requestUpdatedAboutInfo";
53
54 // Other strings.
55 const char kCommit[] = "commit";
56 const char kCounters[] = "counters";
57 const char kCounterType[] = "counterType";
58 const char kModelType[] = "modelType";
59 const char kOnAboutInfoUpdated[] = "onAboutInfoUpdated";
60 const char kOnCountersUpdated[] = "onCountersUpdated";
61 const char kOnProtocolEvent[] = "onProtocolEvent";
62 const char kOnReceivedListOfTypes[] = "onReceivedListOfTypes";
63 const char kStatus[] = "status";
64 const char kTypes[] = "types";
65 const char kUpdate[] = "update";
66
67 namespace {
68
69 // Creates a 'section' for display on about:sync, consisting of a title and a
70 // list of fields. Returns a pointer to the new section. Note that
71 // |parent_list|, not the caller, owns the newly added section.
72 base::ListValue* AddSection(base::ListValue* parent_list,
73 const std::string& title) {
74 std::unique_ptr<base::DictionaryValue> section(new base::DictionaryValue());
75 base::ListValue* section_contents = new base::ListValue();
76 section->SetString("title", title);
77 section->Set("data", section_contents);
78 section->SetBoolean("is_sensitive", false);
79 parent_list->Append(std::move(section));
80 return section_contents;
81 }
82
83 // Same as AddSection, but for data that should be elided when dumped into text
84 // form and posted in a public forum (e.g. unique identifiers).
85 base::ListValue* AddSensitiveSection(base::ListValue* parent_list,
86 const std::string& title) {
87 std::unique_ptr<base::DictionaryValue> section(new base::DictionaryValue());
88 base::ListValue* section_contents = new base::ListValue();
89 section->SetString("title", title);
90 section->Set("data", section_contents);
91 section->SetBoolean("is_sensitive", true);
92 parent_list->Append(std::move(section));
93 return section_contents;
94 }
95
96 // The following helper classes help manage the about:sync fields which will be
97 // populated in method in ConstructAboutInformation.
98 //
99 // Each instance of one of thse classes indicates a field in about:sync. Each
100 // field will be serialized to a DictionaryValue with entries for 'stat_name',
101 // 'stat_value' and 'is_valid'.
102
103 class StringSyncStat {
104 public:
105 StringSyncStat(base::ListValue* section, const std::string& key);
106 void SetValue(const std::string& value);
107 void SetValue(const base::string16& value);
108
109 private:
110 // Owned by the |section| passed in during construction.
111 base::DictionaryValue* stat_;
112 };
113
114 StringSyncStat::StringSyncStat(base::ListValue* section,
115 const std::string& key) {
116 stat_ = new base::DictionaryValue();
117 stat_->SetString("stat_name", key);
118 stat_->SetString("stat_value", "Uninitialized");
119 stat_->SetBoolean("is_valid", false);
120 section->Append(stat_);
121 }
122
123 void StringSyncStat::SetValue(const std::string& value) {
124 stat_->SetString("stat_value", value);
125 stat_->SetBoolean("is_valid", true);
126 }
127
128 void StringSyncStat::SetValue(const base::string16& value) {
129 stat_->SetString("stat_value", value);
130 stat_->SetBoolean("is_valid", true);
131 }
132
133 class BoolSyncStat {
134 public:
135 BoolSyncStat(base::ListValue* section, const std::string& key);
136 void SetValue(bool value);
137
138 private:
139 // Owned by the |section| passed in during construction.
140 base::DictionaryValue* stat_;
141 };
142
143 BoolSyncStat::BoolSyncStat(base::ListValue* section, const std::string& key) {
144 stat_ = new base::DictionaryValue();
145 stat_->SetString("stat_name", key);
146 stat_->SetBoolean("stat_value", false);
147 stat_->SetBoolean("is_valid", false);
148 section->Append(stat_);
149 }
150
151 void BoolSyncStat::SetValue(bool value) {
152 stat_->SetBoolean("stat_value", value);
153 stat_->SetBoolean("is_valid", true);
154 }
155
156 class IntSyncStat {
157 public:
158 IntSyncStat(base::ListValue* section, const std::string& key);
159 void SetValue(int value);
160
161 private:
162 // Owned by the |section| passed in during construction.
163 base::DictionaryValue* stat_;
164 };
165
166 IntSyncStat::IntSyncStat(base::ListValue* section, const std::string& key) {
167 stat_ = new base::DictionaryValue();
168 stat_->SetString("stat_name", key);
169 stat_->SetInteger("stat_value", 0);
170 stat_->SetBoolean("is_valid", false);
171 section->Append(stat_);
172 }
173
174 void IntSyncStat::SetValue(int value) {
175 stat_->SetInteger("stat_value", value);
176 stat_->SetBoolean("is_valid", true);
177 }
178
179 // Returns a string describing the chrome version environment. Version format:
180 // <Build Info> <OS> <Version number> (<Last change>)<channel or "-devel">
181 // If version information is unavailable, returns "invalid."
182 // TODO(zea): this approximately matches MakeUserAgentForSyncApi in
183 // sync_backend_host.cc. Unify the two if possible.
184 std::string GetVersionString(version_info::Channel channel) {
185 // Build a version string that matches MakeUserAgentForSyncApi with the
186 // addition of channel info and proper OS names.
187 // chrome::GetChannelString() returns empty string for stable channel or
188 // unofficial builds, the channel string otherwise. We want to have "-devel"
189 // for unofficial builds only.
190 std::string version_modifier = version_info::GetChannelString(channel);
191 if (version_modifier.empty()) {
192 if (channel != version_info::Channel::STABLE) {
193 version_modifier = "-devel";
194 }
195 } else {
196 version_modifier = " " + version_modifier;
197 }
198 return version_info::GetProductName() + " " + version_info::GetOSType() +
199 " " + version_info::GetVersionNumber() + " (" +
200 version_info::GetLastChange() + ")" + version_modifier;
201 }
202
203 std::string GetTimeStr(base::Time time, const std::string& default_msg) {
204 std::string time_str;
205 if (time.is_null())
206 time_str = default_msg;
207 else
208 time_str = syncer::GetTimeDebugString(time);
209 return time_str;
210 }
211
212 std::string GetConnectionStatus(
213 const sync_driver::SyncService::SyncTokenStatus& status) {
214 std::string message;
215 switch (status.connection_status) {
216 case syncer::CONNECTION_NOT_ATTEMPTED:
217 base::StringAppendF(&message, "not attempted");
218 break;
219 case syncer::CONNECTION_OK:
220 base::StringAppendF(
221 &message, "OK since %s",
222 GetTimeStr(status.connection_status_update_time, "n/a").c_str());
223 break;
224 case syncer::CONNECTION_AUTH_ERROR:
225 base::StringAppendF(
226 &message, "auth error since %s",
227 GetTimeStr(status.connection_status_update_time, "n/a").c_str());
228 break;
229 case syncer::CONNECTION_SERVER_ERROR:
230 base::StringAppendF(
231 &message, "server error since %s",
232 GetTimeStr(status.connection_status_update_time, "n/a").c_str());
233 break;
234 default:
235 NOTREACHED();
236 }
237 return message;
238 }
239
240 } // namespace
241
242 // This function both defines the structure of the message to be returned and
243 // its contents. Most of the message consists of simple fields in about:sync
244 // which are grouped into sections and populated with the help of the SyncStat
245 // classes defined above.
246 std::unique_ptr<base::DictionaryValue> ConstructAboutInformation(
247 sync_driver::SyncService* service,
248 SigninManagerBase* signin,
249 version_info::Channel channel) {
250 std::unique_ptr<base::DictionaryValue> about_info(
251 new base::DictionaryValue());
252
253 // 'details': A list of sections.
254 base::ListValue* stats_list = new base::ListValue();
255
256 // The following lines define the sections and their fields. For each field,
257 // a class is instantiated, which allows us to reference the fields in
258 // 'setter' code later on in this function.
259 base::ListValue* section_summary = AddSection(stats_list, "Summary");
260 StringSyncStat summary_string(section_summary, "Summary");
261
262 base::ListValue* section_version = AddSection(stats_list, "Version Info");
263 StringSyncStat client_version(section_version, "Client Version");
264 StringSyncStat server_url(section_version, "Server URL");
265
266 base::ListValue* section_identity =
267 AddSensitiveSection(stats_list, kIdentityTitle);
268 StringSyncStat sync_id(section_identity, "Sync Client ID");
269 StringSyncStat invalidator_id(section_identity, "Invalidator Client ID");
270 StringSyncStat username(section_identity, "Username");
271
272 base::ListValue* section_credentials = AddSection(stats_list, "Credentials");
273 StringSyncStat request_token_time(section_credentials, "Requested Token");
274 StringSyncStat receive_token_time(section_credentials, "Received Token");
275 StringSyncStat token_request_status(section_credentials,
276 "Token Request Status");
277 StringSyncStat next_token_request(section_credentials,
278 "Next Token Request");
279
280 base::ListValue* section_local = AddSection(stats_list, "Local State");
281 StringSyncStat server_connection(section_local,
282 "Server Connection");
283 StringSyncStat last_synced(section_local, "Last Synced");
284 BoolSyncStat is_setup_complete(section_local,
285 "Sync First-Time Setup Complete");
286 StringSyncStat backend_initialization(section_local,
287 "Sync Backend Initialization");
288 BoolSyncStat is_syncing(section_local, "Syncing");
289
290 base::ListValue* section_network = AddSection(stats_list, "Network");
291 BoolSyncStat is_throttled(section_network, "Throttled");
292 StringSyncStat retry_time(section_network, "Retry time (maybe stale)");
293 BoolSyncStat are_notifications_enabled(section_network,
294 "Notifications Enabled");
295
296 base::ListValue* section_encryption = AddSection(stats_list, "Encryption");
297 BoolSyncStat is_using_explicit_passphrase(section_encryption,
298 "Explicit Passphrase");
299 BoolSyncStat is_passphrase_required(section_encryption,
300 "Passphrase Required");
301 BoolSyncStat is_cryptographer_ready(section_encryption,
302 "Cryptographer Ready");
303 BoolSyncStat has_pending_keys(section_encryption,
304 "Cryptographer Has Pending Keys");
305 StringSyncStat encrypted_types(section_encryption, "Encrypted Types");
306 BoolSyncStat has_keystore_key(section_encryption, "Has Keystore Key");
307 StringSyncStat keystore_migration_time(section_encryption,
308 "Keystore Migration Time");
309 StringSyncStat passphrase_type(section_encryption,
310 "Passphrase Type");
311 StringSyncStat passphrase_time(section_encryption,
312 "Passphrase Time");
313
314 base::ListValue* section_last_session = AddSection(
315 stats_list, "Status from Last Completed Session");
316 StringSyncStat session_source(section_last_session, "Sync Source");
317 StringSyncStat get_key_result(section_last_session, "GetKey Step Result");
318 StringSyncStat download_result(section_last_session, "Download Step Result");
319 StringSyncStat commit_result(section_last_session, "Commit Step Result");
320
321 base::ListValue* section_counters = AddSection(stats_list, "Running Totals");
322 IntSyncStat notifications_received(section_counters,
323 "Notifications Received");
324 IntSyncStat updates_received(section_counters, "Updates Downloaded");
325 IntSyncStat tombstone_updates(section_counters, "Tombstone Updates");
326 IntSyncStat reflected_updates(section_counters, "Reflected Updates");
327 IntSyncStat successful_commits(section_counters, "Successful Commits");
328 IntSyncStat conflicts_resolved_local_wins(section_counters,
329 "Conflicts Resolved: Client Wins");
330 IntSyncStat conflicts_resolved_server_wins(section_counters,
331 "Conflicts Resolved: Server Wins");
332
333 base::ListValue *section_this_cycle = AddSection(stats_list,
334 "Transient Counters (this cycle)");
335 IntSyncStat encryption_conflicts(section_this_cycle, "Encryption Conflicts");
336 IntSyncStat hierarchy_conflicts(section_this_cycle, "Hierarchy Conflicts");
337 IntSyncStat server_conflicts(section_this_cycle, "Server Conflicts");
338 IntSyncStat committed_items(section_this_cycle, "Committed Items");
339
340 base::ListValue* section_that_cycle = AddSection(
341 stats_list, "Transient Counters (last cycle of last completed session)");
342 IntSyncStat updates_downloaded(section_that_cycle, "Updates Downloaded");
343 IntSyncStat committed_count(section_that_cycle, "Committed Count");
344 IntSyncStat entries(section_that_cycle, "Entries");
345
346 base::ListValue* section_nudge_info = AddSection(
347 stats_list, "Nudge Source Counters");
348 IntSyncStat nudge_source_notification(
349 section_nudge_info, "Server Invalidations");
350 IntSyncStat nudge_source_local(section_nudge_info, "Local Changes");
351 IntSyncStat nudge_source_local_refresh(section_nudge_info, "Local Refreshes");
352
353 // This list of sections belongs in the 'details' field of the returned
354 // message.
355 about_info->Set(kDetailsKey, stats_list);
356
357 // Populate all the fields we declared above.
358 client_version.SetValue(GetVersionString(channel));
359
360 if (!service) {
361 summary_string.SetValue("Sync service does not exist");
362 return about_info;
363 }
364
365 syncer::SyncStatus full_status;
366 bool is_status_valid = service->QueryDetailedSyncStatus(&full_status);
367 bool sync_active = service->IsSyncActive();
368 const syncer::sessions::SyncSessionSnapshot& snapshot =
369 service->GetLastSessionSnapshot();
370
371 if (is_status_valid)
372 summary_string.SetValue(service->QuerySyncStatusSummaryString());
373
374 server_url.SetValue(service->sync_service_url().spec());
375
376 if (is_status_valid && !full_status.sync_id.empty())
377 sync_id.SetValue(full_status.sync_id);
378 if (is_status_valid && !full_status.invalidator_client_id.empty())
379 invalidator_id.SetValue(full_status.invalidator_client_id);
380 if (signin)
381 username.SetValue(signin->GetAuthenticatedAccountInfo().email);
382
383 const sync_driver::SyncService::SyncTokenStatus& token_status =
384 service->GetSyncTokenStatus();
385 server_connection.SetValue(GetConnectionStatus(token_status));
386 request_token_time.SetValue(GetTimeStr(token_status.token_request_time,
387 "n/a"));
388 receive_token_time.SetValue(GetTimeStr(token_status.token_receive_time,
389 "n/a"));
390 std::string err = token_status.last_get_token_error.error_message();
391 token_request_status.SetValue(err.empty() ? "OK" : err);
392 next_token_request.SetValue(
393 GetTimeStr(token_status.next_token_request_time, "not scheduled"));
394
395 last_synced.SetValue(service->GetLastSyncedTimeString());
396 is_setup_complete.SetValue(service->IsFirstSetupComplete());
397 backend_initialization.SetValue(
398 service->GetBackendInitializationStateString());
399 if (is_status_valid) {
400 is_syncing.SetValue(full_status.syncing);
401 retry_time.SetValue(GetTimeStr(full_status.retry_time,
402 "Scheduler is not in backoff or throttled"));
403 }
404
405 if (snapshot.is_initialized())
406 is_throttled.SetValue(snapshot.is_silenced());
407 if (is_status_valid) {
408 are_notifications_enabled.SetValue(
409 full_status.notifications_enabled);
410 }
411
412 if (sync_active) {
413 is_using_explicit_passphrase.SetValue(
414 service->IsUsingSecondaryPassphrase());
415 is_passphrase_required.SetValue(service->IsPassphraseRequired());
416 passphrase_time.SetValue(
417 GetTimeStr(service->GetExplicitPassphraseTime(), "No Passphrase Time"));
418 }
419 if (is_status_valid) {
420 is_cryptographer_ready.SetValue(full_status.cryptographer_ready);
421 has_pending_keys.SetValue(full_status.crypto_has_pending_keys);
422 encrypted_types.SetValue(
423 ModelTypeSetToString(full_status.encrypted_types));
424 has_keystore_key.SetValue(full_status.has_keystore_key);
425 keystore_migration_time.SetValue(
426 GetTimeStr(full_status.keystore_migration_time, "Not Migrated"));
427 passphrase_type.SetValue(
428 PassphraseTypeToString(full_status.passphrase_type));
429 }
430
431 if (snapshot.is_initialized()) {
432 if (snapshot.legacy_updates_source() !=
433 sync_pb::GetUpdatesCallerInfo::UNKNOWN) {
434 session_source.SetValue(
435 syncer::GetUpdatesSourceString(snapshot.legacy_updates_source()));
436 }
437 get_key_result.SetValue(
438 GetSyncerErrorString(
439 snapshot.model_neutral_state().last_get_key_result));
440 download_result.SetValue(
441 GetSyncerErrorString(
442 snapshot.model_neutral_state().last_download_updates_result));
443 commit_result.SetValue(
444 GetSyncerErrorString(
445 snapshot.model_neutral_state().commit_result));
446 }
447
448 if (is_status_valid) {
449 notifications_received.SetValue(full_status.notifications_received);
450 updates_received.SetValue(full_status.updates_received);
451 tombstone_updates.SetValue(full_status.tombstone_updates_received);
452 reflected_updates.SetValue(full_status.reflected_updates_received);
453 successful_commits.SetValue(full_status.num_commits_total);
454 conflicts_resolved_local_wins.SetValue(
455 full_status.num_local_overwrites_total);
456 conflicts_resolved_server_wins.SetValue(
457 full_status.num_server_overwrites_total);
458 }
459
460 if (is_status_valid) {
461 encryption_conflicts.SetValue(full_status.encryption_conflicts);
462 hierarchy_conflicts.SetValue(full_status.hierarchy_conflicts);
463 server_conflicts.SetValue(full_status.server_conflicts);
464 committed_items.SetValue(full_status.committed_count);
465 }
466
467 if (is_status_valid) {
468 nudge_source_notification.SetValue(full_status.nudge_source_notification);
469 nudge_source_local.SetValue(full_status.nudge_source_local);
470 nudge_source_local_refresh.SetValue(full_status.nudge_source_local_refresh);
471 }
472
473 if (snapshot.is_initialized()) {
474 updates_downloaded.SetValue(
475 snapshot.model_neutral_state().num_updates_downloaded_total);
476 committed_count.SetValue(
477 snapshot.model_neutral_state().num_successful_commits);
478 entries.SetValue(snapshot.num_entries());
479 }
480
481 // The values set from this point onwards do not belong in the
482 // details list.
483
484 // We don't need to check is_status_valid here.
485 // full_status.sync_protocol_error is exported directly from the
486 // ProfileSyncService, even if the backend doesn't exist.
487 const bool actionable_error_detected =
488 full_status.sync_protocol_error.error_type != syncer::UNKNOWN_ERROR &&
489 full_status.sync_protocol_error.error_type != syncer::SYNC_SUCCESS;
490
491 about_info->SetBoolean("actionable_error_detected",
492 actionable_error_detected);
493
494 // NOTE: We won't bother showing any of the following values unless
495 // actionable_error_detected is set.
496
497 base::ListValue* actionable_error = new base::ListValue();
498 about_info->Set("actionable_error", actionable_error);
499
500 StringSyncStat error_type(actionable_error, "Error Type");
501 StringSyncStat action(actionable_error, "Action");
502 StringSyncStat url(actionable_error, "URL");
503 StringSyncStat description(actionable_error, "Error Description");
504
505 if (actionable_error_detected) {
506 error_type.SetValue(syncer::GetSyncErrorTypeString(
507 full_status.sync_protocol_error.error_type));
508 action.SetValue(syncer::GetClientActionString(
509 full_status.sync_protocol_error.action));
510 url.SetValue(full_status.sync_protocol_error.url);
511 description.SetValue(full_status.sync_protocol_error.error_description);
512 }
513
514 about_info->SetBoolean("unrecoverable_error_detected",
515 service->HasUnrecoverableError());
516
517 if (service->HasUnrecoverableError()) {
518 tracked_objects::Location loc(service->unrecoverable_error_location());
519 std::string location_str;
520 loc.Write(true, true, &location_str);
521 std::string unrecoverable_error_message =
522 "Unrecoverable error detected at " + location_str +
523 ": " + service->unrecoverable_error_message();
524 about_info->SetString("unrecoverable_error_message",
525 unrecoverable_error_message);
526 }
527
528 about_info->Set("type_status", service->GetTypeStatusMap());
529
530 return about_info;
531 }
532
533 } // namespace sync_ui_util
534
535 } // namespace sync_driver
OLDNEW
« no previous file with comments | « components/sync_driver/about_sync_util.h ('k') | components/sync_driver/about_sync_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698