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

Side by Side Diff: chrome/browser/sync/about_sync_util.cc

Issue 10696107: sync: Track validity of about:sync fields (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Update Created 8 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « chrome/browser/sync/about_sync_util.h ('k') | chrome/browser/sync/about_sync_util_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "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
OLDNEW
« no previous file with comments | « chrome/browser/sync/about_sync_util.h ('k') | chrome/browser/sync/about_sync_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698