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