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