15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/about_sync_util.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h"
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/strings/stringprintf.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_service.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_version_info.h"
14e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "components/signin/core/browser/signin_manager.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/api/time.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/util/sync_string_conversions.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/protocol/proto_enum_conversions.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::DictionaryValue;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::ListValue;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const char kIdentityTitle[] = "Identity";
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDetailsKey[] = "details";
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates a 'section' for display on about:sync, consisting of a title and a
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// list of fields.  Returns a pointer to the new section.  Note that
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |parent_list|, not the caller, owns the newly added section.
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::ListValue* AddSection(base::ListValue* parent_list,
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            const std::string& title) {
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* section = new base::DictionaryValue();
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* section_contents = new base::ListValue();
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  section->SetString("title", title);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  section->Set("data", section_contents);
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  section->SetBoolean("is_sensitive", false);
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  parent_list->Append(section);
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return section_contents;
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Same as AddSection, but for data that should be elided when dumped into text
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// form and posted in a public forum (e.g. unique identifiers).
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::ListValue* AddSensitiveSection(base::ListValue* parent_list,
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     const std::string& title) {
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* section = new base::DictionaryValue();
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* section_contents = new base::ListValue();
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  section->SetString("title", title);
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  section->Set("data", section_contents);
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  section->SetBoolean("is_sensitive", true);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parent_list->Append(section);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return section_contents;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following helper classes help manage the about:sync fields which will be
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// populated in method in ConstructAboutInformation.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Each instance of one of thse classes indicates a field in about:sync.  Each
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// field will be serialized to a DictionaryValue with entries for 'stat_name',
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 'stat_value' and 'is_valid'.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class StringSyncStat {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StringSyncStat(base::ListValue* section, const std::string& key);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetValue(const std::string& value);
65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void SetValue(const base::string16& value);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Owned by the |section| passed in during construction.
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* stat_;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)StringSyncStat::StringSyncStat(base::ListValue* section,
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               const std::string& key) {
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stat_ = new base::DictionaryValue();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stat_->SetString("stat_name", key);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stat_->SetString("stat_value", "Uninitialized");
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stat_->SetBoolean("is_valid", false);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  section->Append(stat_);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StringSyncStat::SetValue(const std::string& value) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stat_->SetString("stat_value", value);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stat_->SetBoolean("is_valid", true);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void StringSyncStat::SetValue(const base::string16& value) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stat_->SetString("stat_value", value);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stat_->SetBoolean("is_valid", true);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BoolSyncStat {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BoolSyncStat(base::ListValue* section, const std::string& key);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetValue(bool value);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Owned by the |section| passed in during construction.
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* stat_;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)BoolSyncStat::BoolSyncStat(base::ListValue* section, const std::string& key) {
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stat_ = new base::DictionaryValue();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stat_->SetString("stat_name", key);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stat_->SetBoolean("stat_value", false);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stat_->SetBoolean("is_valid", false);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  section->Append(stat_);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BoolSyncStat::SetValue(bool value) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stat_->SetBoolean("stat_value", value);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stat_->SetBoolean("is_valid", true);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IntSyncStat {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  IntSyncStat(base::ListValue* section, const std::string& key);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetValue(int value);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Owned by the |section| passed in during construction.
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* stat_;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)IntSyncStat::IntSyncStat(base::ListValue* section, const std::string& key) {
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stat_ = new base::DictionaryValue();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stat_->SetString("stat_name", key);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stat_->SetInteger("stat_value", 0);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stat_->SetBoolean("is_valid", false);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  section->Append(stat_);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IntSyncStat::SetValue(int value) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stat_->SetInteger("stat_value", value);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stat_->SetBoolean("is_valid", true);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a string describing the chrome version environment. Version format:
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// <Build Info> <OS> <Version number> (<Last change>)<channel or "-devel">
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If version information is unavailable, returns "invalid."
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(zea): this approximately matches MakeUserAgentForSyncApi in
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sync_backend_host.cc. Unify the two if possible.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetVersionString() {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Build a version string that matches MakeUserAgentForSyncApi with the
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // addition of channel info and proper OS names.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome::VersionInfo chrome_version;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!chrome_version.is_valid())
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "invalid";
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GetVersionStringModifier returns empty string for stable channel or
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // unofficial builds, the channel string otherwise. We want to have "-devel"
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for unofficial builds only.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string version_modifier =
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::VersionInfo::GetVersionStringModifier();
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (version_modifier.empty()) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (chrome::VersionInfo::GetChannel() !=
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            chrome::VersionInfo::CHANNEL_STABLE) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version_modifier = "-devel";
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    version_modifier = " " + version_modifier;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return chrome_version.Name() + " " + chrome_version.OSType() + " " +
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome_version.Version() + " (" + chrome_version.LastChange() + ")" +
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version_modifier;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetTimeStr(base::Time time, const std::string& default_msg) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string time_str;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (time.is_null())
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    time_str = default_msg;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    time_str = syncer::GetTimeDebugString(time);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return time_str;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)std::string GetConnectionStatus(
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const ProfileSyncService::SyncTokenStatus& status) {
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string message;
178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  switch (status.connection_status) {
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case syncer::CONNECTION_NOT_ATTEMPTED:
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::StringAppendF(&message, "not attempted");
181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      break;
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case syncer::CONNECTION_OK:
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::StringAppendF(
184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          &message, "OK since %s",
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          GetTimeStr(status.connection_status_update_time, "n/a").c_str());
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      break;
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case syncer::CONNECTION_AUTH_ERROR:
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::StringAppendF(
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          &message, "auth error since %s",
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          GetTimeStr(status.connection_status_update_time, "n/a").c_str());
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      break;
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case syncer::CONNECTION_SERVER_ERROR:
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::StringAppendF(
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          &message, "server error since %s",
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          GetTimeStr(status.connection_status_update_time, "n/a").c_str());
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      break;
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    default:
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      NOTREACHED();
199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return message;
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sync_ui_util {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function both defines the structure of the message to be returned and
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// its contents.  Most of the message consists of simple fields in about:sync
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which are grouped into sections and populated with the help of the SyncStat
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// classes defined above.
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<base::DictionaryValue> ConstructAboutInformation(
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProfileSyncService* service) {
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> about_info(new base::DictionaryValue());
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // 'details': A list of sections.
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* stats_list = new base::ListValue();
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The following lines define the sections and their fields.  For each field,
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a class is instantiated, which allows us to reference the fields in
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 'setter' code later on in this function.
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* section_summary = AddSection(stats_list, "Summary");
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringSyncStat summary_string(section_summary, "Summary");
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* section_version = AddSection(stats_list, "Version Info");
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringSyncStat client_version(section_version, "Client Version");
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringSyncStat server_url(section_version, "Server URL");
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* section_identity =
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      AddSensitiveSection(stats_list, kIdentityTitle);
230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StringSyncStat sync_id(section_identity, "Sync Client ID");
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StringSyncStat invalidator_id(section_identity, "Invalidator Client ID");
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StringSyncStat username(section_identity, "Username");
233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* section_credentials = AddSection(stats_list, "Credentials");
235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StringSyncStat request_token_time(section_credentials, "Requested Token");
236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StringSyncStat receive_token_time(section_credentials, "Received Token");
237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StringSyncStat token_request_status(section_credentials,
238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                      "Token Request Status");
239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StringSyncStat next_token_request(section_credentials,
240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                    "Next Token Request");
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* section_local = AddSection(stats_list, "Local State");
243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StringSyncStat server_connection(section_local,
244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                   "Server Connection");
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringSyncStat last_synced(section_local, "Last Synced");
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoolSyncStat is_setup_complete(section_local,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "Sync First-Time Setup Complete");
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StringSyncStat backend_initialization(section_local,
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        "Sync Backend Initialization");
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoolSyncStat is_syncing(section_local, "Syncing");
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* section_network = AddSection(stats_list, "Network");
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoolSyncStat is_throttled(section_network, "Throttled");
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StringSyncStat retry_time(section_network, "Retry time (maybe stale)");
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoolSyncStat are_notifications_enabled(section_network,
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         "Notifications Enabled");
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* section_encryption = AddSection(stats_list, "Encryption");
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoolSyncStat is_using_explicit_passphrase(section_encryption,
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            "Explicit Passphrase");
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoolSyncStat is_passphrase_required(section_encryption,
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      "Passphrase Required");
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoolSyncStat is_cryptographer_ready(section_encryption,
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      "Cryptographer Ready");
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoolSyncStat has_pending_keys(section_encryption,
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                "Cryptographer Has Pending Keys");
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringSyncStat encrypted_types(section_encryption, "Encrypted Types");
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoolSyncStat has_keystore_key(section_encryption, "Has Keystore Key");
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringSyncStat keystore_migration_time(section_encryption,
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         "Keystore Migration Time");
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringSyncStat passphrase_type(section_encryption,
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "Passphrase Type");
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringSyncStat passphrase_time(section_encryption,
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "Passphrase Time");
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* section_last_session = AddSection(
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stats_list, "Status from Last Completed Session");
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringSyncStat session_source(section_last_session, "Sync Source");
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringSyncStat get_key_result(section_last_session, "GetKey Step Result");
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringSyncStat download_result(section_last_session, "Download Step Result");
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringSyncStat commit_result(section_last_session, "Commit Step Result");
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* section_counters = AddSection(stats_list, "Running Totals");
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSyncStat notifications_received(section_counters,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     "Notifications Received");
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSyncStat updates_received(section_counters, "Updates Downloaded");
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSyncStat tombstone_updates(section_counters, "Tombstone Updates");
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSyncStat reflected_updates(section_counters, "Reflected Updates");
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSyncStat successful_commits(section_counters, "Successful Commits");
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSyncStat conflicts_resolved_local_wins(section_counters,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     "Conflicts Resolved: Client Wins");
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSyncStat conflicts_resolved_server_wins(section_counters,
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      "Conflicts Resolved: Server Wins");
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue *section_this_cycle = AddSection(stats_list,
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             "Transient Counters (this cycle)");
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSyncStat encryption_conflicts(section_this_cycle, "Encryption Conflicts");
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSyncStat hierarchy_conflicts(section_this_cycle, "Hierarchy Conflicts");
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSyncStat server_conflicts(section_this_cycle, "Server Conflicts");
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSyncStat committed_items(section_this_cycle, "Committed Items");
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* section_that_cycle = AddSection(
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stats_list, "Transient Counters (last cycle of last completed session)");
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSyncStat updates_downloaded(section_that_cycle, "Updates Downloaded");
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSyncStat committed_count(section_that_cycle, "Committed Count");
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSyncStat entries(section_that_cycle, "Entries");
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* section_nudge_info = AddSection(
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stats_list, "Nudge Source Counters");
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSyncStat nudge_source_notification(
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      section_nudge_info, "Server Invalidations");
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSyncStat nudge_source_local(section_nudge_info, "Local Changes");
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSyncStat nudge_source_local_refresh(section_nudge_info, "Local Refreshes");
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This list of sections belongs in the 'details' field of the returned
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // message.
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  about_info->Set(kDetailsKey, stats_list);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Populate all the fields we declared above.
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_version.SetValue(GetVersionString());
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!service) {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    summary_string.SetValue("Sync service does not exist");
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return about_info.Pass();
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::SyncStatus full_status;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_status_valid = service->QueryDetailedSyncStatus(&full_status);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool sync_initialized = service->sync_initialized();
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const syncer::sessions::SyncSessionSnapshot& snapshot =
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sync_initialized ?
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service->GetLastSessionSnapshot() :
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      syncer::sessions::SyncSessionSnapshot();
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_status_valid)
336d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    summary_string.SetValue(service->QuerySyncStatusSummaryString());
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server_url.SetValue(service->sync_service_url().spec());
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (is_status_valid && !full_status.sync_id.empty())
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_id.SetValue(full_status.sync_id);
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (is_status_valid && !full_status.invalidator_client_id.empty())
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    invalidator_id.SetValue(full_status.invalidator_client_id);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service->signin())
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    username.SetValue(service->signin()->GetAuthenticatedUsername());
346f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
347f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const ProfileSyncService::SyncTokenStatus& token_status =
348f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      service->GetSyncTokenStatus();
349f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  server_connection.SetValue(GetConnectionStatus(token_status));
350f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  request_token_time.SetValue(GetTimeStr(token_status.token_request_time,
351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                         "n/a"));
352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  receive_token_time.SetValue(GetTimeStr(token_status.token_receive_time,
353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                         "n/a"));
354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string err = token_status.last_get_token_error.error_message();
355f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  token_request_status.SetValue(err.empty() ? "OK" : err);
356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  next_token_request.SetValue(
357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      GetTimeStr(token_status.next_token_request_time, "not scheduled"));
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_synced.SetValue(service->GetLastSyncedTimeString());
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_setup_complete.SetValue(service->HasSyncSetupCompleted());
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  backend_initialization.SetValue(
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      service->GetBackendInitializationStateString());
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_status_valid) {
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_syncing.SetValue(full_status.syncing);
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    retry_time.SetValue(GetTimeStr(full_status.retry_time,
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "Scheduler is not in backoff or throttled"));
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (snapshot.is_initialized())
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_throttled.SetValue(snapshot.is_silenced());
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_status_valid) {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    are_notifications_enabled.SetValue(
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        full_status.notifications_enabled);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sync_initialized) {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_using_explicit_passphrase.SetValue(
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        service->IsUsingSecondaryPassphrase());
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_passphrase_required.SetValue(service->IsPassphraseRequired());
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    passphrase_time.SetValue(
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetTimeStr(service->GetExplicitPassphraseTime(), "No Passphrase Time"));
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_status_valid) {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_cryptographer_ready.SetValue(full_status.cryptographer_ready);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_pending_keys.SetValue(full_status.crypto_has_pending_keys);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    encrypted_types.SetValue(
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ModelTypeSetToString(full_status.encrypted_types));
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_keystore_key.SetValue(full_status.has_keystore_key);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    keystore_migration_time.SetValue(
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetTimeStr(full_status.keystore_migration_time, "Not Migrated"));
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    passphrase_type.SetValue(
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PassphraseTypeToString(full_status.passphrase_type));
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (snapshot.is_initialized()) {
396a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (snapshot.legacy_updates_source() !=
397a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        sync_pb::GetUpdatesCallerInfo::UNKNOWN) {
398a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      session_source.SetValue(
399a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          syncer::GetUpdatesSourceString(snapshot.legacy_updates_source()));
400a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    get_key_result.SetValue(
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetSyncerErrorString(
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            snapshot.model_neutral_state().last_get_key_result));
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    download_result.SetValue(
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetSyncerErrorString(
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            snapshot.model_neutral_state().last_download_updates_result));
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    commit_result.SetValue(
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetSyncerErrorString(
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            snapshot.model_neutral_state().commit_result));
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_status_valid) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notifications_received.SetValue(full_status.notifications_received);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    updates_received.SetValue(full_status.updates_received);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tombstone_updates.SetValue(full_status.tombstone_updates_received);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reflected_updates.SetValue(full_status.reflected_updates_received);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    successful_commits.SetValue(full_status.num_commits_total);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    conflicts_resolved_local_wins.SetValue(
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        full_status.num_local_overwrites_total);
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    conflicts_resolved_server_wins.SetValue(
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        full_status.num_server_overwrites_total);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_status_valid) {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    encryption_conflicts.SetValue(full_status.encryption_conflicts);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hierarchy_conflicts.SetValue(full_status.hierarchy_conflicts);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_conflicts.SetValue(full_status.server_conflicts);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    committed_items.SetValue(full_status.committed_count);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_status_valid) {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nudge_source_notification.SetValue(full_status.nudge_source_notification);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nudge_source_local.SetValue(full_status.nudge_source_local);
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nudge_source_local_refresh.SetValue(full_status.nudge_source_local_refresh);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (snapshot.is_initialized()) {
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    updates_downloaded.SetValue(
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        snapshot.model_neutral_state().num_updates_downloaded_total);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    committed_count.SetValue(
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        snapshot.model_neutral_state().num_successful_commits);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entries.SetValue(snapshot.num_entries());
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The values set from this point onwards do not belong in the
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // details list.
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't need to check is_status_valid here.
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // full_status.sync_protocol_error is exported directly from the
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ProfileSyncService, even if the backend doesn't exist.
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool actionable_error_detected =
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      full_status.sync_protocol_error.error_type != syncer::UNKNOWN_ERROR &&
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      full_status.sync_protocol_error.error_type != syncer::SYNC_SUCCESS;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  about_info->SetBoolean("actionable_error_detected",
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         actionable_error_detected);
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: We won't bother showing any of the following values unless
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // actionable_error_detected is set.
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* actionable_error = new base::ListValue();
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  about_info->Set("actionable_error", actionable_error);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringSyncStat error_type(actionable_error, "Error Type");
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringSyncStat action(actionable_error, "Action");
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringSyncStat url(actionable_error, "URL");
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringSyncStat description(actionable_error, "Error Description");
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (actionable_error_detected) {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_type.SetValue(syncer::GetSyncErrorTypeString(
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            full_status.sync_protocol_error.error_type));
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    action.SetValue(syncer::GetClientActionString(
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            full_status.sync_protocol_error.action));
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    url.SetValue(full_status.sync_protocol_error.url);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    description.SetValue(full_status.sync_protocol_error.error_description);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  about_info->SetBoolean("unrecoverable_error_detected",
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         service->HasUnrecoverableError());
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service->HasUnrecoverableError()) {
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tracked_objects::Location loc(service->unrecoverable_error_location());
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string location_str;
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loc.Write(true, true, &location_str);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string unrecoverable_error_message =
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Unrecoverable error detected at " + location_str +
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ": " + service->unrecoverable_error_message();
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    about_info->SetString("unrecoverable_error_message",
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       unrecoverable_error_message);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  about_info->Set("type_status", service->GetTypeStatusMap());
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return about_info.Pass();
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace sync_ui_util
498