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