Revert 168224 - Update V8 to version 3.15.4.
[chromium-blink-merge.git] / chrome / browser / sync / about_sync_util.cc
blobad32c065a1a37bb040d5cacd4499ead3e5014f15
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.
5 #include "chrome/browser/sync/about_sync_util.h"
7 #include <string>
9 #include "base/string16.h"
10 #include "base/values.h"
11 #include "chrome/browser/signin/signin_manager.h"
12 #include "chrome/browser/sync/profile_sync_service.h"
13 #include "chrome/common/chrome_version_info.h"
14 #include "sync/api/time.h"
15 #include "sync/internal_api/public/util/sync_string_conversions.h"
16 #include "sync/protocol/proto_enum_conversions.h"
18 using base::DictionaryValue;
19 using base::ListValue;
21 const char kCredentialsTitle[] = "Credentials";
22 const char kDetailsKey[] = "details";
24 namespace {
26 // Creates a 'section' for display on about:sync, consisting of a title and a
27 // list of fields. Returns a pointer to the new section. Note that
28 // |parent_list|, not the caller, owns the newly added section.
29 ListValue* AddSection(ListValue* parent_list, const std::string& title) {
30 DictionaryValue* section = new DictionaryValue();
31 ListValue* section_contents = new ListValue();
32 section->SetString("title", title);
33 section->Set("data", section_contents);
34 parent_list->Append(section);
35 return section_contents;
38 // The following helper classes help manage the about:sync fields which will be
39 // populated in method in ConstructAboutInformation.
41 // Each instance of one of thse classes indicates a field in about:sync. Each
42 // field will be serialized to a DictionaryValue with entries for 'stat_name',
43 // 'stat_value' and 'is_valid'.
45 class StringSyncStat {
46 public:
47 StringSyncStat(ListValue* section, const std::string& key);
48 void SetValue(const std::string& value);
49 void SetValue(const string16& value);
51 private:
52 // Owned by the |section| passed in during construction.
53 DictionaryValue* stat_;
56 StringSyncStat::StringSyncStat(ListValue* section, const std::string& key) {
57 stat_ = new DictionaryValue();
58 stat_->SetString("stat_name", key);
59 stat_->SetString("stat_value", "Uninitialized");
60 stat_->SetBoolean("is_valid", false);
61 section->Append(stat_);
64 void StringSyncStat::SetValue(const std::string& value) {
65 stat_->SetString("stat_value", value);
66 stat_->SetBoolean("is_valid", true);
69 void StringSyncStat::SetValue(const string16& value) {
70 stat_->SetString("stat_value", value);
71 stat_->SetBoolean("is_valid", true);
74 class BoolSyncStat {
75 public:
76 BoolSyncStat(ListValue* section, const std::string& key);
77 void SetValue(bool value);
79 private:
80 // Owned by the |section| passed in during construction.
81 DictionaryValue* stat_;
84 BoolSyncStat::BoolSyncStat(ListValue* section, const std::string& key) {
85 stat_ = new DictionaryValue();
86 stat_->SetString("stat_name", key);
87 stat_->SetBoolean("stat_value", false);
88 stat_->SetBoolean("is_valid", false);
89 section->Append(stat_);
92 void BoolSyncStat::SetValue(bool value) {
93 stat_->SetBoolean("stat_value", value);
94 stat_->SetBoolean("is_valid", true);
97 class IntSyncStat {
98 public:
99 IntSyncStat(ListValue* section, const std::string& key);
100 void SetValue(int value);
102 private:
103 // Owned by the |section| passed in during construction.
104 DictionaryValue* stat_;
107 IntSyncStat::IntSyncStat(ListValue* section, const std::string& key) {
108 stat_ = new DictionaryValue();
109 stat_->SetString("stat_name", key);
110 stat_->SetInteger("stat_value", 0);
111 stat_->SetBoolean("is_valid", false);
112 section->Append(stat_);
115 void IntSyncStat::SetValue(int value) {
116 stat_->SetInteger("stat_value", value);
117 stat_->SetBoolean("is_valid", true);
120 // Returns a string describing the chrome version environment. Version format:
121 // <Build Info> <OS> <Version number> (<Last change>)<channel or "-devel">
122 // If version information is unavailable, returns "invalid."
123 // TODO(zea): this approximately matches MakeUserAgentForSyncApi in
124 // sync_backend_host.cc. Unify the two if possible.
125 std::string GetVersionString() {
126 // Build a version string that matches MakeUserAgentForSyncApi with the
127 // addition of channel info and proper OS names.
128 chrome::VersionInfo chrome_version;
129 if (!chrome_version.is_valid())
130 return "invalid";
131 // GetVersionStringModifier returns empty string for stable channel or
132 // unofficial builds, the channel string otherwise. We want to have "-devel"
133 // for unofficial builds only.
134 std::string version_modifier =
135 chrome::VersionInfo::GetVersionStringModifier();
136 if (version_modifier.empty()) {
137 if (chrome::VersionInfo::GetChannel() !=
138 chrome::VersionInfo::CHANNEL_STABLE) {
139 version_modifier = "-devel";
141 } else {
142 version_modifier = " " + version_modifier;
144 return chrome_version.Name() + " " + chrome_version.OSType() + " " +
145 chrome_version.Version() + " (" + chrome_version.LastChange() + ")" +
146 version_modifier;
149 std::string GetTimeStr(base::Time time, const std::string& default_msg) {
150 std::string time_str;
151 if (time.is_null())
152 time_str = default_msg;
153 else
154 time_str = syncer::GetTimeDebugString(time);
155 return time_str;
158 } // namespace
160 namespace sync_ui_util {
162 // This function both defines the structure of the message to be returned and
163 // its contents. Most of the message consists of simple fields in about:sync
164 // which are grouped into sections and populated with the help of the SyncStat
165 // classes defined above.
166 scoped_ptr<DictionaryValue> ConstructAboutInformation(
167 ProfileSyncService* service) {
168 scoped_ptr<DictionaryValue> about_info(new DictionaryValue());
169 ListValue* stats_list = new ListValue(); // 'details': A list of sections.
171 // The following lines define the sections and their fields. For each field,
172 // a class is instantiated, which allows us to reference the fields in
173 // 'setter' code later on in this function.
174 ListValue* section_summary = AddSection(stats_list, "Summary");
175 StringSyncStat summary_string(section_summary, "Summary");
177 ListValue* section_version = AddSection(stats_list, "Version Info");
178 StringSyncStat client_version(section_version, "Client Version");
179 StringSyncStat server_url(section_version, "Server URL");
181 ListValue* section_credentials = AddSection(stats_list, kCredentialsTitle);
182 StringSyncStat client_id(section_credentials, "Client ID");
183 StringSyncStat username(section_credentials, "Username");
184 BoolSyncStat is_token_available(section_credentials, "Sync Token Available");
186 ListValue* section_local = AddSection(stats_list, "Local State");
187 StringSyncStat last_synced(section_local, "Last Synced");
188 BoolSyncStat is_setup_complete(section_local,
189 "Sync First-Time Setup Complete");
190 BoolSyncStat is_backend_initialized(section_local,
191 "Sync Backend Initialized");
192 BoolSyncStat is_download_complete(section_local, "Initial Download Complete");
193 BoolSyncStat is_syncing(section_local, "Syncing");
195 ListValue* section_network = AddSection(stats_list, "Network");
196 BoolSyncStat is_throttled(section_network, "Throttled");
197 BoolSyncStat are_notifications_enabled(section_network,
198 "Notifications Enabled");
200 ListValue* section_encryption = AddSection(stats_list, "Encryption");
201 BoolSyncStat is_using_explicit_passphrase(section_encryption,
202 "Explicit Passphrase");
203 BoolSyncStat is_passphrase_required(section_encryption,
204 "Passphrase Required");
205 BoolSyncStat is_cryptographer_ready(section_encryption,
206 "Cryptographer Ready");
207 BoolSyncStat has_pending_keys(section_encryption,
208 "Cryptographer Has Pending Keys");
209 StringSyncStat encrypted_types(section_encryption, "Encrypted Types");
210 BoolSyncStat has_keystore_key(section_encryption, "Has Keystore Key");
211 StringSyncStat keystore_migration_time(section_encryption,
212 "Keystore Migration Time");
213 StringSyncStat passphrase_type(section_encryption,
214 "Passphrase Type");
215 StringSyncStat passphrase_time(section_encryption,
216 "Passphrase Time");
218 ListValue* section_last_session = AddSection(
219 stats_list, "Status from Last Completed Session");
220 StringSyncStat session_source(section_last_session, "Sync Source");
221 StringSyncStat get_key_result(section_last_session, "GetKey Step Result");
222 StringSyncStat download_result(section_last_session, "Download Step Result");
223 StringSyncStat commit_result(section_last_session, "Commit Step Result");
225 ListValue* section_counters = AddSection(stats_list, "Running Totals");
226 IntSyncStat notifications_received(section_counters,
227 "Notifications Received");
228 IntSyncStat empty_get_updates(section_counters, "Cycles Without Updates");
229 IntSyncStat non_empty_get_updates(section_counters, "Cycles With Updated");
230 IntSyncStat sync_cycles_without_commits(section_counters,
231 "Cycles Without Commits");
232 IntSyncStat sync_cycles_with_commits(section_counters, "Cycles With Commits");
233 IntSyncStat useless_sync_cycles(section_counters,
234 "Cycles Without Commits or Updates");
235 IntSyncStat useful_sync_cycles(section_counters,
236 "Cycles With Commit or Update");
237 IntSyncStat updates_received(section_counters, "Updates Downloaded");
238 IntSyncStat tombstone_updates(section_counters, "Tombstone Updates");
239 IntSyncStat reflected_updates(section_counters, "Reflected Updates");
240 IntSyncStat successful_commits(section_counters, "Successful Commits");
241 IntSyncStat conflicts_resolved_local_wins(section_counters,
242 "Conflicts Resolved: Client Wins");
243 IntSyncStat conflicts_resolved_server_wins(section_counters,
244 "Conflicts Resolved: Server Wins");
246 ListValue *section_this_cycle = AddSection(stats_list,
247 "Transient Counters (this cycle)");
248 IntSyncStat encryption_conflicts(section_this_cycle, "Encryption Conflicts");
249 IntSyncStat hierarchy_conflicts(section_this_cycle, "Hierarchy Conflicts");
250 IntSyncStat server_conflicts(section_this_cycle, "Server Conflicts");
251 IntSyncStat committed_items(section_this_cycle, "Committed Items");
252 IntSyncStat updates_remaining(section_this_cycle, "Updates Remaining");
254 ListValue* section_that_cycle = AddSection(
255 stats_list, "Transient Counters (last cycle of last completed session)");
256 IntSyncStat updates_downloaded(section_that_cycle, "Updates Downloaded");
257 IntSyncStat committed_count(section_that_cycle, "Committed Count");
258 IntSyncStat entries(section_that_cycle, "Entries");
260 ListValue* section_nudge_info = AddSection(
261 stats_list, "Nudge Source Counters");
262 IntSyncStat nudge_source_notification(
263 section_nudge_info, "Server Invalidations");
264 IntSyncStat nudge_source_local(section_nudge_info, "Local Changes");
265 IntSyncStat nudge_source_local_refresh(section_nudge_info, "Local Refreshes");
267 // This list of sections belongs in the 'details' field of the returned
268 // message.
269 about_info->Set(kDetailsKey, stats_list);
271 // Populate all the fields we declared above.
272 client_version.SetValue(GetVersionString());
274 if (!service) {
275 summary_string.SetValue("Sync service does not exist");
276 return about_info.Pass();
279 syncer::SyncStatus full_status;
280 bool is_status_valid = service->QueryDetailedSyncStatus(&full_status);
281 bool sync_initialized = service->sync_initialized();
282 const syncer::sessions::SyncSessionSnapshot& snapshot =
283 sync_initialized ?
284 service->GetLastSessionSnapshot() :
285 syncer::sessions::SyncSessionSnapshot();
287 if (is_status_valid)
288 summary_string.SetValue(service->QuerySyncStatusSummary());
290 server_url.SetValue(service->sync_service_url().spec());
292 if (is_status_valid && !full_status.unique_id.empty())
293 client_id.SetValue(full_status.unique_id);
294 if (service->signin())
295 username.SetValue(service->signin()->GetAuthenticatedUsername());
296 is_token_available.SetValue(service->IsSyncTokenAvailable());
298 last_synced.SetValue(service->GetLastSyncedTimeString());
299 is_setup_complete.SetValue(service->HasSyncSetupCompleted());
300 is_backend_initialized.SetValue(sync_initialized);
301 if (is_status_valid) {
302 is_download_complete.SetValue(full_status.initial_sync_ended);
303 is_syncing.SetValue(full_status.syncing);
306 if (snapshot.is_initialized())
307 is_throttled.SetValue(snapshot.is_silenced());
308 if (is_status_valid) {
309 are_notifications_enabled.SetValue(
310 full_status.notifications_enabled);
313 if (sync_initialized) {
314 is_using_explicit_passphrase.SetValue(
315 service->IsUsingSecondaryPassphrase());
316 is_passphrase_required.SetValue(service->IsPassphraseRequired());
317 passphrase_time.SetValue(
318 GetTimeStr(service->GetExplicitPassphraseTime(), "No Passphrase Time"));
320 if (is_status_valid) {
321 is_cryptographer_ready.SetValue(full_status.cryptographer_ready);
322 has_pending_keys.SetValue(full_status.crypto_has_pending_keys);
323 encrypted_types.SetValue(
324 ModelTypeSetToString(full_status.encrypted_types));
325 has_keystore_key.SetValue(full_status.has_keystore_key);
326 keystore_migration_time.SetValue(
327 GetTimeStr(full_status.keystore_migration_time, "Not Migrated"));
328 passphrase_type.SetValue(
329 PassphraseTypeToString(full_status.passphrase_type));
332 if (snapshot.is_initialized()) {
333 session_source.SetValue(
334 syncer::GetUpdatesSourceString(snapshot.source().updates_source));
335 get_key_result.SetValue(
336 GetSyncerErrorString(
337 snapshot.model_neutral_state().last_get_key_result));
338 download_result.SetValue(
339 GetSyncerErrorString(
340 snapshot.model_neutral_state().last_download_updates_result));
341 commit_result.SetValue(
342 GetSyncerErrorString(
343 snapshot.model_neutral_state().commit_result));
346 if (is_status_valid) {
347 notifications_received.SetValue(full_status.notifications_received);
348 empty_get_updates.SetValue(full_status.empty_get_updates);
349 non_empty_get_updates.SetValue(full_status.nonempty_get_updates);
350 sync_cycles_without_commits.SetValue(
351 full_status.sync_cycles_without_commits);
352 sync_cycles_with_commits.SetValue(
353 full_status.sync_cycles_with_commits);
354 useless_sync_cycles.SetValue(full_status.useless_sync_cycles);
355 useful_sync_cycles.SetValue(full_status.useful_sync_cycles);
356 updates_received.SetValue(full_status.updates_received);
357 tombstone_updates.SetValue(full_status.tombstone_updates_received);
358 reflected_updates.SetValue(full_status.reflected_updates_received);
359 successful_commits.SetValue(full_status.num_commits_total);
360 conflicts_resolved_local_wins.SetValue(
361 full_status.num_local_overwrites_total);
362 conflicts_resolved_server_wins.SetValue(
363 full_status.num_server_overwrites_total);
366 if (is_status_valid) {
367 encryption_conflicts.SetValue(full_status.encryption_conflicts);
368 hierarchy_conflicts.SetValue(full_status.hierarchy_conflicts);
369 server_conflicts.SetValue(full_status.server_conflicts);
370 committed_items.SetValue(full_status.committed_count);
371 updates_remaining.SetValue(full_status.updates_available);
374 if (is_status_valid) {
375 nudge_source_notification.SetValue(full_status.nudge_source_notification);
376 nudge_source_local.SetValue(full_status.nudge_source_local);
377 nudge_source_local_refresh.SetValue(full_status.nudge_source_local_refresh);
380 if (snapshot.is_initialized()) {
381 updates_downloaded.SetValue(
382 snapshot.model_neutral_state().num_updates_downloaded_total);
383 committed_count.SetValue(
384 snapshot.model_neutral_state().num_successful_commits);
385 entries.SetValue(snapshot.num_entries());
388 // The values set from this point onwards do not belong in the
389 // details list.
391 // We don't need to check is_status_valid here.
392 // full_status.sync_protocol_error is exported directly from the
393 // ProfileSyncService, even if the backend doesn't exist.
394 const bool actionable_error_detected =
395 full_status.sync_protocol_error.error_type != syncer::UNKNOWN_ERROR &&
396 full_status.sync_protocol_error.error_type != syncer::SYNC_SUCCESS;
398 about_info->SetBoolean("actionable_error_detected",
399 actionable_error_detected);
401 // NOTE: We won't bother showing any of the following values unless
402 // actionable_error_detected is set.
404 ListValue* actionable_error = new ListValue();
405 about_info->Set("actionable_error", actionable_error);
407 StringSyncStat error_type(actionable_error, "Error Type");
408 StringSyncStat action(actionable_error, "Action");
409 StringSyncStat url(actionable_error, "URL");
410 StringSyncStat description(actionable_error, "Error Description");
412 if (actionable_error_detected) {
413 error_type.SetValue(syncer::GetSyncErrorTypeString(
414 full_status.sync_protocol_error.error_type));
415 action.SetValue(syncer::GetClientActionString(
416 full_status.sync_protocol_error.action));
417 url.SetValue(full_status.sync_protocol_error.url);
418 description.SetValue(full_status.sync_protocol_error.error_description);
421 about_info->SetBoolean("unrecoverable_error_detected",
422 service->HasUnrecoverableError());
424 if (service->HasUnrecoverableError()) {
425 tracked_objects::Location loc(service->unrecoverable_error_location());
426 std::string location_str;
427 loc.Write(true, true, &location_str);
428 std::string unrecoverable_error_message =
429 "Unrecoverable error detected at " + location_str +
430 ": " + service->unrecoverable_error_message();
431 about_info->SetString("unrecoverable_error_message",
432 unrecoverable_error_message);
435 about_info->Set("type_status", service->GetTypeStatusMap());
437 return about_info.Pass();
440 } // namespace sync_ui_util