Home | History | Annotate | Download | only in sync
      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/profile_sync_service.h"
      6 
      7 #include <cstddef>
      8 #include <map>
      9 #include <set>
     10 #include <utility>
     11 
     12 #include "base/basictypes.h"
     13 #include "base/bind.h"
     14 #include "base/callback.h"
     15 #include "base/command_line.h"
     16 #include "base/compiler_specific.h"
     17 #include "base/logging.h"
     18 #include "base/memory/ref_counted.h"
     19 #include "base/message_loop/message_loop.h"
     20 #include "base/metrics/histogram.h"
     21 #include "base/strings/string16.h"
     22 #include "base/strings/stringprintf.h"
     23 #include "base/threading/thread_restrictions.h"
     24 #include "build/build_config.h"
     25 #include "chrome/browser/browser_process.h"
     26 #include "chrome/browser/chrome_notification_types.h"
     27 #include "chrome/browser/defaults.h"
     28 #include "chrome/browser/net/chrome_cookie_notification_details.h"
     29 #include "chrome/browser/prefs/pref_service_syncable.h"
     30 #include "chrome/browser/profiles/profile.h"
     31 #include "chrome/browser/signin/about_signin_internals.h"
     32 #include "chrome/browser/signin/about_signin_internals_factory.h"
     33 #include "chrome/browser/signin/profile_oauth2_token_service.h"
     34 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
     35 #include "chrome/browser/signin/signin_manager.h"
     36 #include "chrome/browser/signin/signin_manager_factory.h"
     37 #include "chrome/browser/signin/token_service.h"
     38 #include "chrome/browser/signin/token_service_factory.h"
     39 #include "chrome/browser/sync/backend_migrator.h"
     40 #include "chrome/browser/sync/glue/change_processor.h"
     41 #include "chrome/browser/sync/glue/chrome_encryptor.h"
     42 #include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h"
     43 #include "chrome/browser/sync/glue/data_type_controller.h"
     44 #include "chrome/browser/sync/glue/device_info.h"
     45 #include "chrome/browser/sync/glue/session_data_type_controller.h"
     46 #include "chrome/browser/sync/glue/session_model_associator.h"
     47 #include "chrome/browser/sync/glue/synced_device_tracker.h"
     48 #include "chrome/browser/sync/glue/typed_url_data_type_controller.h"
     49 #include "chrome/browser/sync/profile_sync_components_factory_impl.h"
     50 #include "chrome/browser/sync/sync_global_error.h"
     51 #include "chrome/browser/sync/user_selectable_sync_type.h"
     52 #include "chrome/browser/ui/browser.h"
     53 #include "chrome/browser/ui/browser_list.h"
     54 #include "chrome/browser/ui/browser_window.h"
     55 #include "chrome/browser/ui/global_error/global_error_service.h"
     56 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
     57 #include "chrome/common/chrome_switches.h"
     58 #include "chrome/common/chrome_version_info.h"
     59 #include "chrome/common/pref_names.h"
     60 #include "chrome/common/url_constants.h"
     61 #include "components/user_prefs/pref_registry_syncable.h"
     62 #include "content/public/browser/notification_details.h"
     63 #include "content/public/browser/notification_service.h"
     64 #include "content/public/browser/notification_source.h"
     65 #include "google_apis/gaia/gaia_constants.h"
     66 #include "grit/generated_resources.h"
     67 #include "net/cookies/cookie_monster.h"
     68 #include "net/url_request/url_request_context_getter.h"
     69 #include "sync/api/sync_error.h"
     70 #include "sync/internal_api/public/configure_reason.h"
     71 #include "sync/internal_api/public/sync_encryption_handler.h"
     72 #include "sync/internal_api/public/util/experiments.h"
     73 #include "sync/internal_api/public/util/sync_string_conversions.h"
     74 #include "sync/js/js_arg_list.h"
     75 #include "sync/js/js_event_details.h"
     76 #include "sync/util/cryptographer.h"
     77 #include "ui/base/l10n/l10n_util.h"
     78 #include "ui/base/l10n/time_format.h"
     79 
     80 #if defined(ENABLE_MANAGED_USERS)
     81 #include "chrome/browser/managed_mode/managed_user_service.h"
     82 #endif
     83 
     84 #if defined(OS_ANDROID)
     85 #include "sync/internal_api/public/read_transaction.h"
     86 #endif
     87 
     88 using browser_sync::ChangeProcessor;
     89 using browser_sync::DataTypeController;
     90 using browser_sync::DataTypeManager;
     91 using browser_sync::FailedDataTypesHandler;
     92 using browser_sync::SyncBackendHost;
     93 using syncer::ModelType;
     94 using syncer::ModelTypeSet;
     95 using syncer::JsBackend;
     96 using syncer::JsController;
     97 using syncer::JsEventDetails;
     98 using syncer::JsEventHandler;
     99 using syncer::ModelSafeRoutingInfo;
    100 using syncer::SyncCredentials;
    101 using syncer::SyncProtocolError;
    102 using syncer::WeakHandle;
    103 
    104 typedef GoogleServiceAuthError AuthError;
    105 
    106 const char* ProfileSyncService::kSyncServerUrl =
    107     "https://clients4.google.com/chrome-sync";
    108 
    109 const char* ProfileSyncService::kDevServerUrl =
    110     "https://clients4.google.com/chrome-sync/dev";
    111 
    112 static const int kSyncClearDataTimeoutInSeconds = 60;  // 1 minute.
    113 
    114 static const char* kSyncUnrecoverableErrorHistogram =
    115     "Sync.UnrecoverableErrors";
    116 
    117 const net::BackoffEntry::Policy kRequestAccessTokenBackoffPolicy = {
    118   // Number of initial errors (in sequence) to ignore before applying
    119   // exponential back-off rules.
    120   0,
    121 
    122   // Initial delay for exponential back-off in ms.
    123   2000,
    124 
    125   // Factor by which the waiting time will be multiplied.
    126   2,
    127 
    128   // Fuzzing percentage. ex: 10% will spread requests randomly
    129   // between 90%-100% of the calculated time.
    130   0.2, // 20%
    131 
    132   // Maximum amount of time we are willing to delay our request in ms.
    133   // TODO(pavely): crbug.com/246686 ProfileSyncService should retry
    134   // RequestAccessToken on connection state change after backoff
    135   1000 * 3600 * 4, // 4 hours.
    136 
    137   // Time to keep an entry from being discarded even when it
    138   // has no significant state, -1 to never discard.
    139   -1,
    140 
    141   // Don't use initial delay unless the last request was an error.
    142   false,
    143 };
    144 
    145 bool ShouldShowActionOnUI(
    146     const syncer::SyncProtocolError& error) {
    147   return (error.action != syncer::UNKNOWN_ACTION &&
    148           error.action != syncer::DISABLE_SYNC_ON_CLIENT &&
    149           error.action != syncer::STOP_SYNC_FOR_DISABLED_ACCOUNT);
    150 }
    151 
    152 ProfileSyncService::ProfileSyncService(ProfileSyncComponentsFactory* factory,
    153                                        Profile* profile,
    154                                        SigninManagerBase* signin_manager,
    155                                        StartBehavior start_behavior)
    156     : last_auth_error_(AuthError::AuthErrorNone()),
    157       passphrase_required_reason_(syncer::REASON_PASSPHRASE_NOT_REQUIRED),
    158       factory_(factory),
    159       profile_(profile),
    160       // |profile| may be NULL in unit tests.
    161       sync_prefs_(profile_ ? profile_->GetPrefs() : NULL),
    162       sync_service_url_(kDevServerUrl),
    163       data_type_requested_sync_startup_(false),
    164       is_first_time_sync_configure_(false),
    165       backend_initialized_(false),
    166       sync_disabled_by_admin_(false),
    167       is_auth_in_progress_(false),
    168       signin_(signin_manager),
    169       unrecoverable_error_reason_(ERROR_REASON_UNSET),
    170       weak_factory_(this),
    171       expect_sync_configuration_aborted_(false),
    172       encrypted_types_(syncer::SyncEncryptionHandler::SensitiveTypes()),
    173       encrypt_everything_(false),
    174       encryption_pending_(false),
    175       auto_start_enabled_(start_behavior == AUTO_START),
    176       configure_status_(DataTypeManager::UNKNOWN),
    177       setup_in_progress_(false),
    178       request_access_token_backoff_(&kRequestAccessTokenBackoffPolicy) {
    179   // By default, dev, canary, and unbranded Chromium users will go to the
    180   // development servers. Development servers have more features than standard
    181   // sync servers. Users with officially-branded Chrome stable and beta builds
    182   // will go to the standard sync servers.
    183   //
    184   // GetChannel hits the registry on Windows. See http://crbug.com/70380.
    185   base::ThreadRestrictions::ScopedAllowIO allow_io;
    186   chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
    187   if (channel == chrome::VersionInfo::CHANNEL_STABLE ||
    188       channel == chrome::VersionInfo::CHANNEL_BETA) {
    189     sync_service_url_ = GURL(kSyncServerUrl);
    190   }
    191 }
    192 
    193 ProfileSyncService::~ProfileSyncService() {
    194   sync_prefs_.RemoveSyncPrefObserver(this);
    195   // Shutdown() should have been called before destruction.
    196   CHECK(!backend_initialized_);
    197 }
    198 
    199 bool ProfileSyncService::IsSyncEnabledAndLoggedIn() {
    200   // Exit if sync is disabled.
    201   if (IsManaged() || sync_prefs_.IsStartSuppressed())
    202     return false;
    203 
    204   // Sync is logged in if there is a non-empty effective username.
    205   return !GetEffectiveUsername().empty();
    206 }
    207 
    208 bool ProfileSyncService::IsOAuthRefreshTokenAvailable() {
    209   // Function name doesn't reflect which token is checked. Function checks
    210   // refresh token when use_oauth2_token_ is true (all platforms except android)
    211   // and sync token otherwise (for android).
    212   // TODO(pavely): Remove "else" part once use_oauth2_token_ is gone.
    213   if (use_oauth2_token_) {
    214     ProfileOAuth2TokenService* token_service =
    215         ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
    216     if (!token_service)
    217       return false;
    218     return token_service->RefreshTokenIsAvailable();
    219   } else {
    220     TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
    221     if (!token_service)
    222       return false;
    223     return token_service->HasTokenForService(GaiaConstants::kSyncService);
    224   }
    225 }
    226 
    227 void ProfileSyncService::Initialize() {
    228   if (profile_)
    229     SigninGlobalError::GetForProfile(profile_)->AddProvider(this);
    230 
    231   InitSettings();
    232 
    233   // We clear this here (vs Shutdown) because we want to remember that an error
    234   // happened on shutdown so we can display details (message, location) about it
    235   // in about:sync.
    236   ClearStaleErrors();
    237 
    238   sync_prefs_.AddSyncPrefObserver(this);
    239 
    240   // For now, the only thing we can do through policy is to turn sync off.
    241   if (IsManaged()) {
    242     DisableForUser();
    243     return;
    244   }
    245 
    246   RegisterAuthNotifications();
    247 
    248   if (!HasSyncSetupCompleted() || GetEffectiveUsername().empty()) {
    249     // Clean up in case of previous crash / setup abort / signout.
    250     DisableForUser();
    251   }
    252 
    253   TrySyncDatatypePrefRecovery();
    254 
    255   TryStart();
    256 }
    257 
    258 void ProfileSyncService::TrySyncDatatypePrefRecovery() {
    259   DCHECK(!sync_initialized());
    260   if (!HasSyncSetupCompleted())
    261     return;
    262 
    263   // There was a bug where OnUserChoseDatatypes was not properly called on
    264   // configuration (see crbug.com/154940). We detect this by checking whether
    265   // kSyncKeepEverythingSynced has a default value. If so, and sync setup has
    266   // completed, it means sync was not properly configured, so we manually
    267   // set kSyncKeepEverythingSynced.
    268   PrefService* const pref_service = profile_->GetPrefs();
    269   if (!pref_service)
    270     return;
    271   if (GetPreferredDataTypes().Size() > 1)
    272     return;
    273 
    274   const PrefService::Preference* keep_everything_synced =
    275       pref_service->FindPreference(prefs::kSyncKeepEverythingSynced);
    276   // This will be false if the preference was properly set or if it's controlled
    277   // by policy.
    278   if (!keep_everything_synced->IsDefaultValue())
    279     return;
    280 
    281   // kSyncKeepEverythingSynced was not properly set. Set it and the preferred
    282   // types now, before we configure.
    283   UMA_HISTOGRAM_COUNTS("Sync.DatatypePrefRecovery", 1);
    284   sync_prefs_.SetKeepEverythingSynced(true);
    285   syncer::ModelTypeSet registered_types = GetRegisteredDataTypes();
    286   sync_prefs_.SetPreferredDataTypes(registered_types,
    287                                     registered_types);
    288 }
    289 
    290 void ProfileSyncService::TryStart() {
    291   if (!IsSyncEnabledAndLoggedIn())
    292     return;
    293   TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
    294   if (!token_service)
    295     return;
    296   // Don't start the backend if the token service hasn't finished loading tokens
    297   // yet. Note if the backend is started before the sync token has been loaded,
    298   // GetCredentials() will return bogus credentials. On auto_start platforms
    299   // (like ChromeOS) we don't start sync until tokens are loaded, because the
    300   // user can be "signed in" on those platforms long before the tokens get
    301   // loaded, and we don't want to generate spurious auth errors.
    302   if (!IsOAuthRefreshTokenAvailable() &&
    303       !(!auto_start_enabled_ && token_service->TokensLoadedFromDB())) {
    304     return;
    305   }
    306 
    307   if (use_oauth2_token_) {
    308     // If we got here then tokens are loaded and user logged in and sync is
    309     // enabled. If OAuth refresh token is not available then something is wrong.
    310     // When PSS requests access token, OAuth2TokenService will return error and
    311     // PSS will show error to user asking to reauthenticate.
    312     UMA_HISTOGRAM_BOOLEAN("Sync.RefreshTokenAvailable",
    313         IsOAuthRefreshTokenAvailable());
    314   }
    315 
    316   // If sync setup has completed we always start the backend. If the user is in
    317   // the process of setting up now, we should start the backend to download
    318   // account control state / encryption information). If autostart is enabled,
    319   // but we haven't completed sync setup, we try to start sync anyway, since
    320   // it's possible we crashed/shutdown after logging in but before the backend
    321   // finished initializing the last time.
    322   //
    323   // However, the only time we actually need to start sync _immediately_ is if
    324   // we haven't completed sync setup and the user is in the process of setting
    325   // up - either they just signed in (for the first time) on an auto-start
    326   // platform or they explicitly kicked off sync setup, and e.g we need to
    327   // fetch account details like encryption state to populate UI. Otherwise,
    328   // for performance reasons and maximizing parallelism at chrome startup, we
    329   // defer the heavy lifting for sync init until things have calmed down.
    330   if (HasSyncSetupCompleted()) {
    331     if (!data_type_requested_sync_startup_)
    332       StartUp(STARTUP_BACKEND_DEFERRED);
    333     else if (start_up_time_.is_null())
    334       StartUp(STARTUP_IMMEDIATE);
    335     else
    336       StartUpSlowBackendComponents();
    337   } else if (setup_in_progress_ || auto_start_enabled_) {
    338     // We haven't completed sync setup. Start immediately if the user explicitly
    339     // kicked this off or we're supposed to automatically start syncing.
    340     StartUp(STARTUP_IMMEDIATE);
    341   }
    342 }
    343 
    344 void ProfileSyncService::StartSyncingWithServer() {
    345   if (backend_)
    346     backend_->StartSyncingWithServer();
    347 }
    348 
    349 void ProfileSyncService::RegisterAuthNotifications() {
    350   ProfileOAuth2TokenService* token_service =
    351       ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
    352   token_service->AddObserver(this);
    353 
    354   registrar_.Add(this,
    355                  chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
    356                  content::Source<Profile>(profile_));
    357   registrar_.Add(this,
    358                  chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
    359                  content::Source<Profile>(profile_));
    360 }
    361 
    362 void ProfileSyncService::UnregisterAuthNotifications() {
    363   ProfileOAuth2TokenService* token_service =
    364       ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
    365   token_service->RemoveObserver(this);
    366   registrar_.RemoveAll();
    367 }
    368 
    369 void ProfileSyncService::RegisterDataTypeController(
    370     DataTypeController* data_type_controller) {
    371   DCHECK_EQ(data_type_controllers_.count(data_type_controller->type()), 0U);
    372   data_type_controllers_[data_type_controller->type()] =
    373       data_type_controller;
    374 }
    375 
    376 browser_sync::SessionModelAssociator*
    377     ProfileSyncService::GetSessionModelAssociator() {
    378   if (data_type_controllers_.find(syncer::SESSIONS) ==
    379       data_type_controllers_.end() ||
    380       data_type_controllers_.find(syncer::SESSIONS)->second->state() !=
    381       DataTypeController::RUNNING) {
    382     return NULL;
    383   }
    384   return static_cast<browser_sync::SessionDataTypeController*>(
    385       data_type_controllers_.find(
    386       syncer::SESSIONS)->second.get())->GetModelAssociator();
    387 }
    388 
    389 scoped_ptr<browser_sync::DeviceInfo>
    390 ProfileSyncService::GetLocalDeviceInfo() const {
    391   if (backend_) {
    392     browser_sync::SyncedDeviceTracker* device_tracker =
    393         backend_->GetSyncedDeviceTracker();
    394     if (device_tracker)
    395       return device_tracker->ReadLocalDeviceInfo();
    396   }
    397   return scoped_ptr<browser_sync::DeviceInfo>();
    398 }
    399 
    400 scoped_ptr<browser_sync::DeviceInfo>
    401 ProfileSyncService::GetDeviceInfo(const std::string& client_id) const {
    402   if (backend_) {
    403     browser_sync::SyncedDeviceTracker* device_tracker =
    404         backend_->GetSyncedDeviceTracker();
    405     if (device_tracker)
    406       return device_tracker->ReadDeviceInfo(client_id);
    407   }
    408   return scoped_ptr<browser_sync::DeviceInfo>();
    409 }
    410 
    411 ScopedVector<browser_sync::DeviceInfo>
    412     ProfileSyncService::GetAllSignedInDevices() const {
    413   ScopedVector<browser_sync::DeviceInfo> devices;
    414   if (backend_) {
    415     browser_sync::SyncedDeviceTracker* device_tracker =
    416         backend_->GetSyncedDeviceTracker();
    417     if (device_tracker) {
    418       // TODO(lipalani) - Make device tracker return a scoped vector.
    419       device_tracker->GetAllSyncedDeviceInfo(&devices);
    420     }
    421   }
    422   return devices.Pass();
    423 }
    424 
    425 void ProfileSyncService::GetDataTypeControllerStates(
    426   browser_sync::DataTypeController::StateMap* state_map) const {
    427     for (browser_sync::DataTypeController::TypeMap::const_iterator iter =
    428          data_type_controllers_.begin(); iter != data_type_controllers_.end();
    429          ++iter)
    430       (*state_map)[iter->first] = iter->second.get()->state();
    431 }
    432 
    433 void ProfileSyncService::InitSettings() {
    434   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
    435 
    436   // Override the sync server URL from the command-line, if sync server
    437   // command-line argument exists.
    438   if (command_line.HasSwitch(switches::kSyncServiceURL)) {
    439     std::string value(command_line.GetSwitchValueASCII(
    440         switches::kSyncServiceURL));
    441     if (!value.empty()) {
    442       GURL custom_sync_url(value);
    443       if (custom_sync_url.is_valid()) {
    444         sync_service_url_ = custom_sync_url;
    445       } else {
    446         LOG(WARNING) << "The following sync URL specified at the command-line "
    447                      << "is invalid: " << value;
    448       }
    449     }
    450   }
    451 
    452   use_oauth2_token_ = !command_line.HasSwitch(
    453       switches::kSyncDisableOAuth2Token);
    454 }
    455 
    456 SyncCredentials ProfileSyncService::GetCredentials() {
    457   SyncCredentials credentials;
    458   credentials.email = GetEffectiveUsername();
    459   DCHECK(!credentials.email.empty());
    460   if (use_oauth2_token_) {
    461     credentials.sync_token = access_token_;
    462   } else {
    463     TokenService* service = TokenServiceFactory::GetForProfile(profile_);
    464     if (service->HasTokenForService(GaiaConstants::kSyncService)) {
    465       credentials.sync_token = service->GetTokenForService(
    466           GaiaConstants::kSyncService);
    467     }
    468   }
    469 
    470   if (credentials.sync_token.empty())
    471     credentials.sync_token = "credentials_lost";
    472   return credentials;
    473 }
    474 
    475 void ProfileSyncService::InitializeBackend(bool delete_stale_data) {
    476   if (!backend_) {
    477     NOTREACHED();
    478     return;
    479   }
    480 
    481   SyncCredentials credentials = GetCredentials();
    482 
    483   scoped_refptr<net::URLRequestContextGetter> request_context_getter(
    484       profile_->GetRequestContext());
    485 
    486   if (delete_stale_data)
    487     ClearStaleErrors();
    488 
    489   scoped_ptr<syncer::UnrecoverableErrorHandler>
    490       backend_unrecoverable_error_handler(
    491           new browser_sync::BackendUnrecoverableErrorHandler(
    492               MakeWeakHandle(weak_factory_.GetWeakPtr())));
    493 
    494   backend_->Initialize(
    495       this,
    496       sync_thread_.Pass(),
    497       GetJsEventHandler(),
    498       sync_service_url_,
    499       credentials,
    500       delete_stale_data,
    501       scoped_ptr<syncer::SyncManagerFactory>(
    502           new syncer::SyncManagerFactory).Pass(),
    503       backend_unrecoverable_error_handler.Pass(),
    504       &browser_sync::ChromeReportUnrecoverableError);
    505 }
    506 
    507 void ProfileSyncService::CreateBackend() {
    508   backend_.reset(
    509       new SyncBackendHost(profile_->GetDebugName(),
    510                           profile_, sync_prefs_.AsWeakPtr()));
    511 }
    512 
    513 bool ProfileSyncService::IsEncryptedDatatypeEnabled() const {
    514   if (encryption_pending())
    515     return true;
    516   const syncer::ModelTypeSet preferred_types = GetPreferredDataTypes();
    517   const syncer::ModelTypeSet encrypted_types = GetEncryptedDataTypes();
    518   DCHECK(encrypted_types.Has(syncer::PASSWORDS));
    519   return !Intersection(preferred_types, encrypted_types).Empty();
    520 }
    521 
    522 void ProfileSyncService::OnSyncConfigureRetry() {
    523   // Note: in order to handle auth failures that arise before the backend is
    524   // initialized (e.g. from invalidation notifier, or downloading new control
    525   // types), we have to gracefully handle configuration retries at all times.
    526   // At this point an auth error badge should be shown, which once resolved
    527   // will trigger a new sync cycle.
    528   NotifyObservers();
    529 }
    530 
    531 void ProfileSyncService::StartUp(StartUpDeferredOption deferred_option) {
    532   // Don't start up multiple times.
    533   if (backend_) {
    534     DVLOG(1) << "Skipping bringing up backend host.";
    535     return;
    536   }
    537 
    538   DCHECK(IsSyncEnabledAndLoggedIn());
    539 
    540   if (start_up_time_.is_null()) {
    541     start_up_time_ = base::Time::Now();
    542     last_synced_time_ = sync_prefs_.GetLastSyncedTime();
    543 
    544 #if defined(OS_CHROMEOS)
    545     std::string bootstrap_token = sync_prefs_.GetEncryptionBootstrapToken();
    546     if (bootstrap_token.empty()) {
    547       sync_prefs_.SetEncryptionBootstrapToken(
    548           sync_prefs_.GetSpareBootstrapToken());
    549     }
    550 #endif
    551 
    552     if (!sync_global_error_) {
    553 #if !defined(OS_ANDROID)
    554       sync_global_error_.reset(new SyncGlobalError(this, signin()));
    555 #endif
    556       GlobalErrorServiceFactory::GetForProfile(profile_)->AddGlobalError(
    557           sync_global_error_.get());
    558       AddObserver(sync_global_error_.get());
    559     }
    560   } else {
    561     // We don't care to prevent multiple calls to StartUp in deferred mode
    562     // because it's fast and has no side effects.
    563     DCHECK_EQ(STARTUP_BACKEND_DEFERRED, deferred_option);
    564   }
    565 
    566   if (deferred_option == STARTUP_BACKEND_DEFERRED &&
    567       CommandLine::ForCurrentProcess()->
    568           HasSwitch(switches::kSyncEnableDeferredStartup)) {
    569     return;
    570   }
    571 
    572   StartUpSlowBackendComponents();
    573 }
    574 
    575 void ProfileSyncService::OnDataTypeRequestsSyncStartup(
    576     syncer::ModelType type) {
    577   DCHECK(syncer::UserTypes().Has(type));
    578   if (backend_.get()) {
    579     DVLOG(1) << "A data type requested sync startup, but it looks like "
    580                 "something else beat it to the punch.";
    581     return;
    582   }
    583 
    584   if (!GetActiveDataTypes().Has(type)) {
    585     // We can get here as datatype SyncableServices are typically wired up
    586     // to the native datatype even if sync isn't enabled.
    587     DVLOG(1) << "Dropping sync startup request because type "
    588              << syncer::ModelTypeToString(type) << "not enabled.";
    589     return;
    590   }
    591 
    592   if (CommandLine::ForCurrentProcess()->HasSwitch(
    593           switches::kSyncEnableDeferredStartup)) {
    594     DVLOG(2) << "Data type requesting sync startup: "
    595              << syncer::ModelTypeToString(type);
    596     // Measure the time spent waiting for init and the type that triggered it.
    597     // We could measure the time spent deferred on a per-datatype basis, but
    598     // for now this is probably sufficient.
    599     if (!start_up_time_.is_null()) {
    600       // TODO(tim): Cache |type| and move this tracking to StartUp.  I'd like
    601       // to pull all the complicated init logic and state out of
    602       // ProfileSyncService and have only a StartUp method, though. One step
    603       // at a time. Bug 80149.
    604       base::TimeDelta time_deferred = base::Time::Now() - start_up_time_;
    605       UMA_HISTOGRAM_TIMES("Sync.Startup.TimeDeferred", time_deferred);
    606       UMA_HISTOGRAM_ENUMERATION("Sync.Startup.TypeTriggeringInit",
    607                                 ModelTypeToHistogramInt(type),
    608                                 syncer::MODEL_TYPE_COUNT);
    609     }
    610     data_type_requested_sync_startup_ = true;
    611     TryStart();
    612   }
    613   DVLOG(2) << "Ignoring data type request for sync startup: "
    614            << syncer::ModelTypeToString(type);
    615 }
    616 
    617 void ProfileSyncService::StartUpSlowBackendComponents() {
    618   // Don't start up multiple times.
    619   if (backend_) {
    620     DVLOG(1) << "Skipping bringing up backend host.";
    621     return;
    622   }
    623 
    624   DCHECK(IsSyncEnabledAndLoggedIn());
    625   CreateBackend();
    626 
    627   // Initialize the backend.  Every time we start up a new SyncBackendHost,
    628   // we'll want to start from a fresh SyncDB, so delete any old one that might
    629   // be there.
    630   InitializeBackend(!HasSyncSetupCompleted());
    631 }
    632 
    633 void ProfileSyncService::OnGetTokenSuccess(
    634     const OAuth2TokenService::Request* request,
    635     const std::string& access_token,
    636     const base::Time& expiration_time) {
    637   DCHECK_EQ(access_token_request_, request);
    638   access_token_request_.reset();
    639   // Reset backoff time after successful response.
    640   request_access_token_backoff_.Reset();
    641   access_token_ = access_token;
    642   if (backend_)
    643     backend_->UpdateCredentials(GetCredentials());
    644   else
    645     TryStart();
    646 }
    647 
    648 void ProfileSyncService::OnGetTokenFailure(
    649     const OAuth2TokenService::Request* request,
    650     const GoogleServiceAuthError& error) {
    651   DCHECK_EQ(access_token_request_, request);
    652   DCHECK_NE(error.state(), GoogleServiceAuthError::NONE);
    653   access_token_request_.reset();
    654   switch (error.state()) {
    655     case GoogleServiceAuthError::CONNECTION_FAILED:
    656     case GoogleServiceAuthError::SERVICE_UNAVAILABLE: {
    657       // Transient error. Retry after some time.
    658       request_access_token_backoff_.InformOfRequest(false);
    659       request_access_token_retry_timer_.Start(
    660             FROM_HERE,
    661             request_access_token_backoff_.GetTimeUntilRelease(),
    662             base::Bind(&ProfileSyncService::RequestAccessToken,
    663                         weak_factory_.GetWeakPtr()));
    664       break;
    665     }
    666     case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: {
    667       // Report time since token was issued for invalid credentials error.
    668       // TODO(pavely): crbug.com/246817 Collect UMA histogram for auth token
    669       // rejections from invalidation service.
    670       base::Time auth_token_time =
    671           AboutSigninInternalsFactory::GetForProfile(profile_)->
    672               GetTokenTime(GaiaConstants::kGaiaOAuth2LoginRefreshToken);
    673       if (!auth_token_time.is_null()) {
    674         base::TimeDelta age = base::Time::Now() - auth_token_time;
    675         if (age < base::TimeDelta::FromHours(1)) {
    676           UMA_HISTOGRAM_CUSTOM_TIMES("Sync.AuthServerRejectedTokenAgeShort",
    677                                      age,
    678                                      base::TimeDelta::FromSeconds(1),
    679                                      base::TimeDelta::FromHours(1),
    680                                      50);
    681         }
    682         UMA_HISTOGRAM_COUNTS("Sync.AuthServerRejectedTokenAgeLong",
    683                              age.InDays());
    684       }
    685       // Fallthrough.
    686     }
    687     default: {
    688       // Show error to user.
    689       UpdateAuthErrorState(error);
    690     }
    691   }
    692 }
    693 
    694 void ProfileSyncService::OnRefreshTokenAvailable(
    695     const std::string& account_id) {
    696   OnRefreshTokensLoaded();
    697 }
    698 
    699 void ProfileSyncService::OnRefreshTokenRevoked(
    700     const std::string& account_id,
    701     const GoogleServiceAuthError& error) {
    702   if (!IsOAuthRefreshTokenAvailable()) {
    703     // The additional check around IsOAuthRefreshTokenAvailable() above
    704     // prevents us sounding the alarm if we actually have a valid token but
    705     // a refresh attempt by TokenService failed for any variety of reasons
    706     // (e.g. flaky network). It's possible the token we do have is also
    707     // invalid, but in that case we should already have (or can expect) an
    708     // auth error sent from the sync backend.
    709     UpdateAuthErrorState(error);
    710   }
    711 }
    712 
    713 void ProfileSyncService::OnRefreshTokensLoaded() {
    714   // This notification gets fired when TokenService loads the tokens
    715   // from storage.
    716   // Initialize the backend if sync is enabled. If the sync token was
    717   // not loaded, GetCredentials() will generate invalid credentials to
    718   // cause the backend to generate an auth error (crbug.com/121755).
    719   if (backend_) {
    720     RequestAccessToken();
    721   } else {
    722     TryStart();
    723   }
    724 }
    725 
    726 void ProfileSyncService::OnRefreshTokensCleared() {
    727   access_token_.clear();
    728 }
    729 
    730 void ProfileSyncService::Shutdown() {
    731   UnregisterAuthNotifications();
    732 
    733   if (profile_)
    734     SigninGlobalError::GetForProfile(profile_)->RemoveProvider(this);
    735 
    736   ShutdownImpl(browser_sync::SyncBackendHost::STOP);
    737 
    738   if (sync_thread_)
    739     sync_thread_->Stop();
    740 }
    741 
    742 void ProfileSyncService::ShutdownImpl(
    743     browser_sync::SyncBackendHost::ShutdownOption option) {
    744   if (!backend_)
    745     return;
    746 
    747   // First, we spin down the backend to stop change processing as soon as
    748   // possible.
    749   base::Time shutdown_start_time = base::Time::Now();
    750   backend_->StopSyncingForShutdown();
    751 
    752   // Stop all data type controllers, if needed.  Note that until Stop
    753   // completes, it is possible in theory to have a ChangeProcessor apply a
    754   // change from a native model.  In that case, it will get applied to the sync
    755   // database (which doesn't get destroyed until we destroy the backend below)
    756   // as an unsynced change.  That will be persisted, and committed on restart.
    757   if (data_type_manager_) {
    758     if (data_type_manager_->state() != DataTypeManager::STOPPED) {
    759       // When aborting as part of shutdown, we should expect an aborted sync
    760       // configure result, else we'll dcheck when we try to read the sync error.
    761       expect_sync_configuration_aborted_ = true;
    762       data_type_manager_->Stop();
    763     }
    764     data_type_manager_.reset();
    765   }
    766 
    767   // Shutdown the migrator before the backend to ensure it doesn't pull a null
    768   // snapshot.
    769   migrator_.reset();
    770   sync_js_controller_.AttachJsBackend(WeakHandle<syncer::JsBackend>());
    771 
    772   // Move aside the backend so nobody else tries to use it while we are
    773   // shutting it down.
    774   scoped_ptr<SyncBackendHost> doomed_backend(backend_.release());
    775   if (doomed_backend) {
    776     sync_thread_ = doomed_backend->Shutdown(option);
    777     doomed_backend.reset();
    778   }
    779   base::TimeDelta shutdown_time = base::Time::Now() - shutdown_start_time;
    780   UMA_HISTOGRAM_TIMES("Sync.Shutdown.BackendDestroyedTime", shutdown_time);
    781 
    782   weak_factory_.InvalidateWeakPtrs();
    783 
    784   // Clear various flags.
    785   start_up_time_ = base::Time();
    786   expect_sync_configuration_aborted_ = false;
    787   is_auth_in_progress_ = false;
    788   backend_initialized_ = false;
    789   cached_passphrase_.clear();
    790   encryption_pending_ = false;
    791   encrypt_everything_ = false;
    792   encrypted_types_ = syncer::SyncEncryptionHandler::SensitiveTypes();
    793   passphrase_required_reason_ = syncer::REASON_PASSPHRASE_NOT_REQUIRED;
    794   request_access_token_retry_timer_.Stop();
    795   // Revert to "no auth error".
    796   if (last_auth_error_.state() != GoogleServiceAuthError::NONE)
    797     UpdateAuthErrorState(GoogleServiceAuthError::AuthErrorNone());
    798 
    799   if (sync_global_error_) {
    800     GlobalErrorServiceFactory::GetForProfile(profile_)->RemoveGlobalError(
    801         sync_global_error_.get());
    802     RemoveObserver(sync_global_error_.get());
    803     sync_global_error_.reset(NULL);
    804   }
    805 
    806   NotifyObservers();
    807 }
    808 
    809 void ProfileSyncService::DisableForUser() {
    810   // Clear prefs (including SyncSetupHasCompleted) before shutting down so
    811   // PSS clients don't think we're set up while we're shutting down.
    812   sync_prefs_.ClearPreferences();
    813   ClearUnrecoverableError();
    814   ShutdownImpl(browser_sync::SyncBackendHost::DISABLE_AND_CLAIM_THREAD);
    815 }
    816 
    817 bool ProfileSyncService::HasSyncSetupCompleted() const {
    818   return sync_prefs_.HasSyncSetupCompleted();
    819 }
    820 
    821 void ProfileSyncService::SetSyncSetupCompleted() {
    822   sync_prefs_.SetSyncSetupCompleted();
    823 }
    824 
    825 void ProfileSyncService::UpdateLastSyncedTime() {
    826   last_synced_time_ = base::Time::Now();
    827   sync_prefs_.SetLastSyncedTime(last_synced_time_);
    828 }
    829 
    830 void ProfileSyncService::NotifyObservers() {
    831   FOR_EACH_OBSERVER(ProfileSyncServiceBase::Observer, observers_,
    832                     OnStateChanged());
    833   // TODO(akalin): Make an Observer subclass that listens and does the
    834   // event routing.
    835   sync_js_controller_.HandleJsEvent("onServiceStateChanged", JsEventDetails());
    836 }
    837 
    838 void ProfileSyncService::NotifySyncCycleCompleted() {
    839   FOR_EACH_OBSERVER(ProfileSyncServiceBase::Observer, observers_,
    840                     OnSyncCycleCompleted());
    841   sync_js_controller_.HandleJsEvent(
    842       "onServiceStateChanged", JsEventDetails());
    843 }
    844 
    845 void ProfileSyncService::ClearStaleErrors() {
    846   ClearUnrecoverableError();
    847   last_actionable_error_ = SyncProtocolError();
    848   // Clear the data type errors as well.
    849   failed_data_types_handler_.Reset();
    850 }
    851 
    852 void ProfileSyncService::ClearUnrecoverableError() {
    853   unrecoverable_error_reason_ = ERROR_REASON_UNSET;
    854   unrecoverable_error_message_.clear();
    855   unrecoverable_error_location_ = tracked_objects::Location();
    856 }
    857 
    858 void ProfileSyncService::RegisterNewDataType(syncer::ModelType data_type) {
    859   if (data_type_controllers_.count(data_type) > 0)
    860     return;
    861   NOTREACHED();
    862 }
    863 
    864 // An invariant has been violated.  Transition to an error state where we try
    865 // to do as little work as possible, to avoid further corruption or crashes.
    866 void ProfileSyncService::OnUnrecoverableError(
    867     const tracked_objects::Location& from_here,
    868     const std::string& message) {
    869   // Unrecoverable errors that arrive via the syncer::UnrecoverableErrorHandler
    870   // interface are assumed to originate within the syncer.
    871   unrecoverable_error_reason_ = ERROR_REASON_SYNCER;
    872   OnUnrecoverableErrorImpl(from_here, message, true);
    873 }
    874 
    875 void ProfileSyncService::OnUnrecoverableErrorImpl(
    876     const tracked_objects::Location& from_here,
    877     const std::string& message,
    878     bool delete_sync_database) {
    879   DCHECK(HasUnrecoverableError());
    880   unrecoverable_error_message_ = message;
    881   unrecoverable_error_location_ = from_here;
    882 
    883   UMA_HISTOGRAM_ENUMERATION(kSyncUnrecoverableErrorHistogram,
    884                             unrecoverable_error_reason_,
    885                             ERROR_REASON_LIMIT);
    886   NotifyObservers();
    887   std::string location;
    888   from_here.Write(true, true, &location);
    889   LOG(ERROR)
    890       << "Unrecoverable error detected at " << location
    891       << " -- ProfileSyncService unusable: " << message;
    892 
    893   // Shut all data types down.
    894   base::MessageLoop::current()->PostTask(FROM_HERE,
    895       base::Bind(&ProfileSyncService::ShutdownImpl,
    896                  weak_factory_.GetWeakPtr(),
    897                  delete_sync_database ?
    898                      browser_sync::SyncBackendHost::DISABLE_AND_CLAIM_THREAD :
    899                      browser_sync::SyncBackendHost::STOP_AND_CLAIM_THREAD));
    900 }
    901 
    902 // TODO(zea): Move this logic into the DataTypeController/DataTypeManager.
    903 void ProfileSyncService::DisableBrokenDatatype(
    904     syncer::ModelType type,
    905     const tracked_objects::Location& from_here,
    906     std::string message) {
    907   // First deactivate the type so that no further server changes are
    908   // passed onto the change processor.
    909   DeactivateDataType(type);
    910 
    911   syncer::SyncError error(from_here,
    912                           syncer::SyncError::DATATYPE_ERROR,
    913                           message,
    914                           type);
    915 
    916   std::map<syncer::ModelType, syncer::SyncError> errors;
    917   errors[type] = error;
    918 
    919   // Update this before posting a task. So if a configure happens before
    920   // the task that we are going to post, this type would still be disabled.
    921   failed_data_types_handler_.UpdateFailedDataTypes(errors);
    922 
    923   base::MessageLoop::current()->PostTask(FROM_HERE,
    924       base::Bind(&ProfileSyncService::ReconfigureDatatypeManager,
    925                  weak_factory_.GetWeakPtr()));
    926 }
    927 
    928 void ProfileSyncService::OnBackendInitialized(
    929     const syncer::WeakHandle<syncer::JsBackend>& js_backend,
    930     const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
    931         debug_info_listener,
    932     bool success) {
    933   is_first_time_sync_configure_ = !HasSyncSetupCompleted();
    934 
    935   if (is_first_time_sync_configure_) {
    936     UMA_HISTOGRAM_BOOLEAN("Sync.BackendInitializeFirstTimeSuccess", success);
    937   } else {
    938     UMA_HISTOGRAM_BOOLEAN("Sync.BackendInitializeRestoreSuccess", success);
    939   }
    940 
    941   DCHECK(!start_up_time_.is_null());
    942   base::Time on_backend_initialized_time = base::Time::Now();
    943   base::TimeDelta delta = on_backend_initialized_time - start_up_time_;
    944   if (is_first_time_sync_configure_) {
    945     UMA_HISTOGRAM_LONG_TIMES("Sync.BackendInitializeFirstTime", delta);
    946   } else {
    947     UMA_HISTOGRAM_LONG_TIMES("Sync.BackendInitializeRestoreTime", delta);
    948   }
    949 
    950   if (!success) {
    951     // Something went unexpectedly wrong.  Play it safe: stop syncing at once
    952     // and surface error UI to alert the user sync has stopped.
    953     // Keep the directory around for now so that on restart we will retry
    954     // again and potentially succeed in presence of transient file IO failures
    955     // or permissions issues, etc.
    956     //
    957     // TODO(rlarocque): Consider making this UnrecoverableError less special.
    958     // Unlike every other UnrecoverableError, it does not delete our sync data.
    959     // This exception made sense at the time it was implemented, but our new
    960     // directory corruption recovery mechanism makes it obsolete.  By the time
    961     // we get here, we will have already tried and failed to delete the
    962     // directory.  It would be no big deal if we tried to delete it again.
    963     OnInternalUnrecoverableError(FROM_HERE,
    964                                  "BackendInitialize failure",
    965                                  false,
    966                                  ERROR_REASON_BACKEND_INIT_FAILURE);
    967     return;
    968   }
    969 
    970   backend_initialized_ = true;
    971 
    972   sync_js_controller_.AttachJsBackend(js_backend);
    973   debug_info_listener_ = debug_info_listener;
    974 
    975   // If we have a cached passphrase use it to decrypt/encrypt data now that the
    976   // backend is initialized. We want to call this before notifying observers in
    977   // case this operation affects the "passphrase required" status.
    978   ConsumeCachedPassphraseIfPossible();
    979 
    980   // The very first time the backend initializes is effectively the first time
    981   // we can say we successfully "synced".  last_synced_time_ will only be null
    982   // in this case, because the pref wasn't restored on StartUp.
    983   if (last_synced_time_.is_null()) {
    984     UpdateLastSyncedTime();
    985   }
    986 
    987   if (auto_start_enabled_ && !FirstSetupInProgress()) {
    988     // Backend is initialized but we're not in sync setup, so this must be an
    989     // autostart - mark our sync setup as completed and we'll start syncing
    990     // below.
    991     SetSyncSetupCompleted();
    992   }
    993 
    994   // Check HasSyncSetupCompleted() before NotifyObservers() to avoid spurious
    995   // data type configuration because observer may flag setup as complete and
    996   // trigger data type configuration.
    997   if (HasSyncSetupCompleted()) {
    998     ConfigureDataTypeManager();
    999   } else {
   1000     DCHECK(FirstSetupInProgress());
   1001   }
   1002 
   1003   NotifyObservers();
   1004 }
   1005 
   1006 void ProfileSyncService::OnSyncCycleCompleted() {
   1007   UpdateLastSyncedTime();
   1008   if (GetSessionModelAssociator()) {
   1009     // Trigger garbage collection of old sessions now that we've downloaded
   1010     // any new session data. TODO(zea): Have this be a notification the session
   1011     // model associator listens too. Also consider somehow plumbing the current
   1012     // server time as last reported by CheckServerReachable, so we don't have to
   1013     // rely on the local clock, which may be off significantly.
   1014     base::MessageLoop::current()->PostTask(FROM_HERE,
   1015         base::Bind(&browser_sync::SessionModelAssociator::DeleteStaleSessions,
   1016                    GetSessionModelAssociator()->AsWeakPtr()));
   1017   }
   1018   DVLOG(2) << "Notifying observers sync cycle completed";
   1019   NotifySyncCycleCompleted();
   1020 }
   1021 
   1022 void ProfileSyncService::OnExperimentsChanged(
   1023     const syncer::Experiments& experiments) {
   1024   if (current_experiments_.Matches(experiments))
   1025     return;
   1026 
   1027   // If this is a first time sync for a client, this will be called before
   1028   // OnBackendInitialized() to ensure the new datatypes are available at sync
   1029   // setup. As a result, the migrator won't exist yet. This is fine because for
   1030   // first time sync cases we're only concerned with making the datatype
   1031   // available.
   1032   if (migrator_.get() &&
   1033       migrator_->state() != browser_sync::BackendMigrator::IDLE) {
   1034     DVLOG(1) << "Dropping OnExperimentsChanged due to migrator busy.";
   1035     return;
   1036   }
   1037 
   1038   const syncer::ModelTypeSet registered_types = GetRegisteredDataTypes();
   1039   syncer::ModelTypeSet to_add;
   1040   const syncer::ModelTypeSet to_register =
   1041       Difference(to_add, registered_types);
   1042   DVLOG(2) << "OnExperimentsChanged called with types: "
   1043            << syncer::ModelTypeSetToString(to_add);
   1044   DVLOG(2) << "Enabling types: " << syncer::ModelTypeSetToString(to_register);
   1045 
   1046   for (syncer::ModelTypeSet::Iterator it = to_register.First();
   1047        it.Good(); it.Inc()) {
   1048     // Received notice to enable experimental type. Check if the type is
   1049     // registered, and if not register a new datatype controller.
   1050     RegisterNewDataType(it.Get());
   1051   }
   1052 
   1053   // Check if the user has "Keep Everything Synced" enabled. If so, we want
   1054   // to turn on all experimental types if they're not already on. Otherwise we
   1055   // leave them off.
   1056   // Note: if any types are already registered, we don't turn them on. This
   1057   // covers the case where we're already in the process of reconfiguring
   1058   // to turn an experimental type on.
   1059   if (sync_prefs_.HasKeepEverythingSynced()) {
   1060     // Mark all data types as preferred.
   1061     sync_prefs_.SetPreferredDataTypes(registered_types, registered_types);
   1062 
   1063     // Only automatically turn on types if we have already finished set up.
   1064     // Otherwise, just leave the experimental types on by default.
   1065     if (!to_register.Empty() && HasSyncSetupCompleted() && migrator_) {
   1066       DVLOG(1) << "Dynamically enabling new datatypes: "
   1067                << syncer::ModelTypeSetToString(to_register);
   1068       OnMigrationNeededForTypes(to_register);
   1069     }
   1070   }
   1071 
   1072   current_experiments_ = experiments;
   1073 }
   1074 
   1075 void ProfileSyncService::UpdateAuthErrorState(const AuthError& error) {
   1076   is_auth_in_progress_ = false;
   1077   last_auth_error_ = error;
   1078 
   1079   // Fan the notification out to interested UI-thread components. Notify the
   1080   // SigninGlobalError first so it reflects the latest auth state before we
   1081   // notify observers.
   1082   if (profile_)
   1083     SigninGlobalError::GetForProfile(profile_)->AuthStatusChanged();
   1084 
   1085   NotifyObservers();
   1086 }
   1087 
   1088 namespace {
   1089 
   1090 AuthError ConnectionStatusToAuthError(
   1091     syncer::ConnectionStatus status) {
   1092   switch (status) {
   1093     case syncer::CONNECTION_OK:
   1094       return AuthError::AuthErrorNone();
   1095       break;
   1096     case syncer::CONNECTION_AUTH_ERROR:
   1097       return AuthError(AuthError::INVALID_GAIA_CREDENTIALS);
   1098       break;
   1099     case syncer::CONNECTION_SERVER_ERROR:
   1100       return AuthError(AuthError::CONNECTION_FAILED);
   1101       break;
   1102     default:
   1103       NOTREACHED();
   1104       return AuthError(AuthError::CONNECTION_FAILED);
   1105   }
   1106 }
   1107 
   1108 }  // namespace
   1109 
   1110 void ProfileSyncService::OnConnectionStatusChange(
   1111     syncer::ConnectionStatus status) {
   1112   if (use_oauth2_token_ && status == syncer::CONNECTION_AUTH_ERROR) {
   1113     // Sync server returned error indicating that access token is invalid. It
   1114     // could be either expired or access is revoked. Let's request another
   1115     // access token and if access is revoked then request for token will fail
   1116     // with corresponding error.
   1117     RequestAccessToken();
   1118   } else {
   1119     const GoogleServiceAuthError auth_error =
   1120         ConnectionStatusToAuthError(status);
   1121     DVLOG(1) << "Connection status change: " << auth_error.ToString();
   1122     UpdateAuthErrorState(auth_error);
   1123   }
   1124 }
   1125 
   1126 void ProfileSyncService::OnStopSyncingPermanently() {
   1127   sync_prefs_.SetStartSuppressed(true);
   1128   DisableForUser();
   1129 }
   1130 
   1131 void ProfileSyncService::OnPassphraseRequired(
   1132     syncer::PassphraseRequiredReason reason,
   1133     const sync_pb::EncryptedData& pending_keys) {
   1134   DCHECK(backend_.get());
   1135   DCHECK(backend_->IsNigoriEnabled());
   1136 
   1137   // TODO(lipalani) : add this check to other locations as well.
   1138   if (HasUnrecoverableError()) {
   1139     // When unrecoverable error is detected we post a task to shutdown the
   1140     // backend. The task might not have executed yet.
   1141     return;
   1142   }
   1143 
   1144   DVLOG(1) << "Passphrase required with reason: "
   1145            << syncer::PassphraseRequiredReasonToString(reason);
   1146   passphrase_required_reason_ = reason;
   1147 
   1148   const syncer::ModelTypeSet types = GetPreferredDataTypes();
   1149   if (data_type_manager_) {
   1150     // Reconfigure without the encrypted types (excluded implicitly via the
   1151     // failed datatypes handler).
   1152     data_type_manager_->Configure(types,
   1153                                   syncer::CONFIGURE_REASON_CRYPTO);
   1154   }
   1155 
   1156   // Notify observers that the passphrase status may have changed.
   1157   NotifyObservers();
   1158 }
   1159 
   1160 void ProfileSyncService::OnPassphraseAccepted() {
   1161   DVLOG(1) << "Received OnPassphraseAccepted.";
   1162 
   1163   // If the pending keys were resolved via keystore, it's possible we never
   1164   // consumed our cached passphrase. Clear it now.
   1165   if (!cached_passphrase_.empty())
   1166     cached_passphrase_.clear();
   1167 
   1168   // Reset passphrase_required_reason_ since we know we no longer require the
   1169   // passphrase. We do this here rather than down in ResolvePassphraseRequired()
   1170   // because that can be called by OnPassphraseRequired() if no encrypted data
   1171   // types are enabled, and we don't want to clobber the true passphrase error.
   1172   passphrase_required_reason_ = syncer::REASON_PASSPHRASE_NOT_REQUIRED;
   1173 
   1174   // Make sure the data types that depend on the passphrase are started at
   1175   // this time.
   1176   const syncer::ModelTypeSet types = GetPreferredDataTypes();
   1177   if (data_type_manager_) {
   1178     // Re-enable any encrypted types if necessary.
   1179     data_type_manager_->Configure(types,
   1180                                   syncer::CONFIGURE_REASON_CRYPTO);
   1181   }
   1182 
   1183   NotifyObservers();
   1184 }
   1185 
   1186 void ProfileSyncService::OnEncryptedTypesChanged(
   1187     syncer::ModelTypeSet encrypted_types,
   1188     bool encrypt_everything) {
   1189   encrypted_types_ = encrypted_types;
   1190   encrypt_everything_ = encrypt_everything;
   1191   DVLOG(1) << "Encrypted types changed to "
   1192            << syncer::ModelTypeSetToString(encrypted_types_)
   1193            << " (encrypt everything is set to "
   1194            << (encrypt_everything_ ? "true" : "false") << ")";
   1195   DCHECK(encrypted_types_.Has(syncer::PASSWORDS));
   1196 
   1197   // If sessions are encrypted, full history sync is not possible, and
   1198   // delete directives are unnecessary.
   1199   if (GetActiveDataTypes().Has(syncer::HISTORY_DELETE_DIRECTIVES) &&
   1200       encrypted_types_.Has(syncer::SESSIONS)) {
   1201     DisableBrokenDatatype(syncer::HISTORY_DELETE_DIRECTIVES,
   1202                           FROM_HERE,
   1203                           "Delete directives not supported with encryption.");
   1204   }
   1205 }
   1206 
   1207 void ProfileSyncService::OnEncryptionComplete() {
   1208   DVLOG(1) << "Encryption complete";
   1209   if (encryption_pending_ && encrypt_everything_) {
   1210     encryption_pending_ = false;
   1211     // This is to nudge the integration tests when encryption is
   1212     // finished.
   1213     NotifyObservers();
   1214   }
   1215 }
   1216 
   1217 void ProfileSyncService::OnMigrationNeededForTypes(
   1218     syncer::ModelTypeSet types) {
   1219   DCHECK(backend_initialized_);
   1220   DCHECK(data_type_manager_.get());
   1221 
   1222   // Migrator must be valid, because we don't sync until it is created and this
   1223   // callback originates from a sync cycle.
   1224   migrator_->MigrateTypes(types);
   1225 }
   1226 
   1227 void ProfileSyncService::OnActionableError(const SyncProtocolError& error) {
   1228   last_actionable_error_ = error;
   1229   DCHECK_NE(last_actionable_error_.action,
   1230             syncer::UNKNOWN_ACTION);
   1231   switch (error.action) {
   1232     case syncer::UPGRADE_CLIENT:
   1233     case syncer::CLEAR_USER_DATA_AND_RESYNC:
   1234     case syncer::ENABLE_SYNC_ON_ACCOUNT:
   1235     case syncer::STOP_AND_RESTART_SYNC:
   1236       // TODO(lipalani) : if setup in progress we want to display these
   1237       // actions in the popup. The current experience might not be optimal for
   1238       // the user. We just dismiss the dialog.
   1239       if (setup_in_progress_) {
   1240         OnStopSyncingPermanently();
   1241         expect_sync_configuration_aborted_ = true;
   1242       }
   1243       // Trigger an unrecoverable error to stop syncing.
   1244       OnInternalUnrecoverableError(FROM_HERE,
   1245                                    last_actionable_error_.error_description,
   1246                                    true,
   1247                                    ERROR_REASON_ACTIONABLE_ERROR);
   1248       break;
   1249     case syncer::DISABLE_SYNC_ON_CLIENT:
   1250       OnStopSyncingPermanently();
   1251 #if !defined(OS_CHROMEOS)
   1252       // On desktop Chrome, sign out the user after a dashboard clear.
   1253       // TODO(rsimha): Revisit this for M30. See http://crbug.com/252049.
   1254       if (!auto_start_enabled_)  // Skip sign out on ChromeOS/Android.
   1255         SigninManagerFactory::GetForProfile(profile_)->SignOut();
   1256 #endif
   1257       break;
   1258     case syncer::STOP_SYNC_FOR_DISABLED_ACCOUNT:
   1259       // Sync disabled by domain admin. we should stop syncing until next
   1260       // restart.
   1261       sync_disabled_by_admin_ = true;
   1262       ShutdownImpl(browser_sync::SyncBackendHost::DISABLE_AND_CLAIM_THREAD);
   1263       break;
   1264     default:
   1265       NOTREACHED();
   1266   }
   1267   NotifyObservers();
   1268 }
   1269 
   1270 void ProfileSyncService::OnConfigureDone(
   1271     const browser_sync::DataTypeManager::ConfigureResult& result) {
   1272   // We should have cleared our cached passphrase before we get here (in
   1273   // OnBackendInitialized()).
   1274   DCHECK(cached_passphrase_.empty());
   1275 
   1276   if (!sync_configure_start_time_.is_null()) {
   1277     if (result.status == DataTypeManager::OK ||
   1278         result.status == DataTypeManager::PARTIAL_SUCCESS) {
   1279       base::Time sync_configure_stop_time = base::Time::Now();
   1280       base::TimeDelta delta = sync_configure_stop_time -
   1281           sync_configure_start_time_;
   1282       if (is_first_time_sync_configure_) {
   1283         UMA_HISTOGRAM_LONG_TIMES("Sync.ServiceInitialConfigureTime", delta);
   1284       } else {
   1285         UMA_HISTOGRAM_LONG_TIMES("Sync.ServiceSubsequentConfigureTime",
   1286                                   delta);
   1287       }
   1288     }
   1289     sync_configure_start_time_ = base::Time();
   1290   }
   1291 
   1292   // Notify listeners that configuration is done.
   1293   content::NotificationService::current()->Notify(
   1294       chrome::NOTIFICATION_SYNC_CONFIGURE_DONE,
   1295       content::Source<ProfileSyncService>(this),
   1296       content::NotificationService::NoDetails());
   1297 
   1298   configure_status_ = result.status;
   1299   DVLOG(1) << "PSS OnConfigureDone called with status: " << configure_status_;
   1300   // The possible status values:
   1301   //    ABORT - Configuration was aborted. This is not an error, if
   1302   //            initiated by user.
   1303   //    OK - Everything succeeded.
   1304   //    PARTIAL_SUCCESS - Some datatypes failed to start.
   1305   //    Everything else is an UnrecoverableError. So treat it as such.
   1306 
   1307   // First handle the abort case.
   1308   if (configure_status_ == DataTypeManager::ABORTED &&
   1309       expect_sync_configuration_aborted_) {
   1310     DVLOG(0) << "ProfileSyncService::Observe Sync Configure aborted";
   1311     expect_sync_configuration_aborted_ = false;
   1312     return;
   1313   }
   1314 
   1315   // Handle unrecoverable error.
   1316   if (configure_status_ != DataTypeManager::OK &&
   1317       configure_status_ != DataTypeManager::PARTIAL_SUCCESS) {
   1318     // Something catastrophic had happened. We should only have one
   1319     // error representing it.
   1320     DCHECK_EQ(result.failed_data_types.size(),
   1321               static_cast<unsigned int>(1));
   1322     syncer::SyncError error = result.failed_data_types.begin()->second;
   1323     DCHECK(error.IsSet());
   1324     std::string message =
   1325         "Sync configuration failed with status " +
   1326         DataTypeManager::ConfigureStatusToString(configure_status_) +
   1327         " during " + syncer::ModelTypeToString(error.model_type()) +
   1328         ": " + error.message();
   1329     LOG(ERROR) << "ProfileSyncService error: " << message;
   1330     OnInternalUnrecoverableError(error.location(),
   1331                                  message,
   1332                                  true,
   1333                                  ERROR_REASON_CONFIGURATION_FAILURE);
   1334     return;
   1335   }
   1336 
   1337   // We should never get in a state where we have no encrypted datatypes
   1338   // enabled, and yet we still think we require a passphrase for decryption.
   1339   DCHECK(!(IsPassphraseRequiredForDecryption() &&
   1340            !IsEncryptedDatatypeEnabled()));
   1341 
   1342   // This must be done before we start syncing with the server to avoid
   1343   // sending unencrypted data up on a first time sync.
   1344   if (encryption_pending_)
   1345     backend_->EnableEncryptEverything();
   1346   NotifyObservers();
   1347 
   1348   if (migrator_.get() &&
   1349       migrator_->state() != browser_sync::BackendMigrator::IDLE) {
   1350     // Migration in progress.  Let the migrator know we just finished
   1351     // configuring something.  It will be up to the migrator to call
   1352     // StartSyncingWithServer() if migration is now finished.
   1353     migrator_->OnConfigureDone(result);
   1354   } else {
   1355     StartSyncingWithServer();
   1356   }
   1357 }
   1358 
   1359 void ProfileSyncService::OnConfigureRetry() {
   1360   // We should have cleared our cached passphrase before we get here (in
   1361   // OnBackendInitialized()).
   1362   DCHECK(cached_passphrase_.empty());
   1363 
   1364   OnSyncConfigureRetry();
   1365 }
   1366 
   1367 void ProfileSyncService::OnConfigureStart() {
   1368   sync_configure_start_time_ = base::Time::Now();
   1369   NotifyObservers();
   1370 }
   1371 
   1372 std::string ProfileSyncService::QuerySyncStatusSummary() {
   1373   if (HasUnrecoverableError()) {
   1374     return "Unrecoverable error detected";
   1375   } else if (!backend_) {
   1376     return "Syncing not enabled";
   1377   } else if (backend_.get() && !HasSyncSetupCompleted()) {
   1378     return "First time sync setup incomplete";
   1379   } else if (backend_.get() && HasSyncSetupCompleted() &&
   1380              data_type_manager_.get() &&
   1381              data_type_manager_->state() != DataTypeManager::CONFIGURED) {
   1382     return "Datatypes not fully initialized";
   1383   } else if (ShouldPushChanges()) {
   1384     return "Sync service initialized";
   1385   } else {
   1386     return "Status unknown: Internal error?";
   1387   }
   1388 }
   1389 
   1390 std::string ProfileSyncService::GetBackendInitializationStateString() const {
   1391   if (sync_initialized())
   1392     return "Done";
   1393   else if (!start_up_time_.is_null())
   1394     return "Deferred";
   1395   else
   1396     return "Not started";
   1397 }
   1398 
   1399 bool ProfileSyncService::QueryDetailedSyncStatus(
   1400     SyncBackendHost::Status* result) {
   1401   if (backend_.get() && backend_initialized_) {
   1402     *result = backend_->GetDetailedStatus();
   1403     return true;
   1404   } else {
   1405     SyncBackendHost::Status status;
   1406     status.sync_protocol_error = last_actionable_error_;
   1407     *result = status;
   1408     return false;
   1409   }
   1410 }
   1411 
   1412 const AuthError& ProfileSyncService::GetAuthError() const {
   1413   return last_auth_error_;
   1414 }
   1415 
   1416 GoogleServiceAuthError ProfileSyncService::GetAuthStatus() const {
   1417   return GetAuthError();
   1418 }
   1419 
   1420 bool ProfileSyncService::FirstSetupInProgress() const {
   1421   return !HasSyncSetupCompleted() && setup_in_progress_;
   1422 }
   1423 
   1424 void ProfileSyncService::SetSetupInProgress(bool setup_in_progress) {
   1425   // This method is a no-op if |setup_in_progress_| remains unchanged.
   1426   if (setup_in_progress_ == setup_in_progress)
   1427     return;
   1428 
   1429   setup_in_progress_ = setup_in_progress;
   1430   if (!setup_in_progress && sync_initialized())
   1431     ReconfigureDatatypeManager();
   1432   NotifyObservers();
   1433 }
   1434 
   1435 bool ProfileSyncService::sync_initialized() const {
   1436   return backend_initialized_;
   1437 }
   1438 
   1439 bool ProfileSyncService::waiting_for_auth() const {
   1440   return is_auth_in_progress_;
   1441 }
   1442 
   1443 const syncer::Experiments& ProfileSyncService::current_experiments() const {
   1444   return current_experiments_;
   1445 }
   1446 
   1447 bool ProfileSyncService::HasUnrecoverableError() const {
   1448   return unrecoverable_error_reason_ != ERROR_REASON_UNSET;
   1449 }
   1450 
   1451 bool ProfileSyncService::IsPassphraseRequired() const {
   1452   return passphrase_required_reason_ !=
   1453       syncer::REASON_PASSPHRASE_NOT_REQUIRED;
   1454 }
   1455 
   1456 bool ProfileSyncService::IsPassphraseRequiredForDecryption() const {
   1457   // If there is an encrypted datatype enabled and we don't have the proper
   1458   // passphrase, we must prompt the user for a passphrase. The only way for the
   1459   // user to avoid entering their passphrase is to disable the encrypted types.
   1460   return IsEncryptedDatatypeEnabled() && IsPassphraseRequired();
   1461 }
   1462 
   1463 string16 ProfileSyncService::GetLastSyncedTimeString() const {
   1464   if (last_synced_time_.is_null())
   1465     return l10n_util::GetStringUTF16(IDS_SYNC_TIME_NEVER);
   1466 
   1467   base::TimeDelta last_synced = base::Time::Now() - last_synced_time_;
   1468 
   1469   if (last_synced < base::TimeDelta::FromMinutes(1))
   1470     return l10n_util::GetStringUTF16(IDS_SYNC_TIME_JUST_NOW);
   1471 
   1472   return ui::TimeFormat::TimeElapsed(last_synced);
   1473 }
   1474 
   1475 void ProfileSyncService::UpdateSelectedTypesHistogram(
   1476     bool sync_everything, const syncer::ModelTypeSet chosen_types) const {
   1477   if (!HasSyncSetupCompleted() ||
   1478       sync_everything != sync_prefs_.HasKeepEverythingSynced()) {
   1479     UMA_HISTOGRAM_BOOLEAN("Sync.SyncEverything", sync_everything);
   1480   }
   1481 
   1482   // Only log the data types that are shown in the sync settings ui.
   1483   // Note: the order of these types must match the ordering of
   1484   // the respective types in ModelType
   1485 const browser_sync::user_selectable_type::UserSelectableSyncType
   1486       user_selectable_types[] = {
   1487     browser_sync::user_selectable_type::BOOKMARKS,
   1488     browser_sync::user_selectable_type::PREFERENCES,
   1489     browser_sync::user_selectable_type::PASSWORDS,
   1490     browser_sync::user_selectable_type::AUTOFILL,
   1491     browser_sync::user_selectable_type::THEMES,
   1492     browser_sync::user_selectable_type::TYPED_URLS,
   1493     browser_sync::user_selectable_type::EXTENSIONS,
   1494     browser_sync::user_selectable_type::APPS,
   1495     browser_sync::user_selectable_type::PROXY_TABS
   1496   };
   1497 
   1498   COMPILE_ASSERT(28 == syncer::MODEL_TYPE_COUNT, UpdateCustomConfigHistogram);
   1499 
   1500   if (!sync_everything) {
   1501     const syncer::ModelTypeSet current_types = GetPreferredDataTypes();
   1502 
   1503     syncer::ModelTypeSet type_set = syncer::UserSelectableTypes();
   1504     syncer::ModelTypeSet::Iterator it = type_set.First();
   1505 
   1506     DCHECK_EQ(arraysize(user_selectable_types), type_set.Size());
   1507 
   1508     for (size_t i = 0; i < arraysize(user_selectable_types) && it.Good();
   1509          ++i, it.Inc()) {
   1510       const syncer::ModelType type = it.Get();
   1511       if (chosen_types.Has(type) &&
   1512           (!HasSyncSetupCompleted() || !current_types.Has(type))) {
   1513         // Selected type has changed - log it.
   1514         UMA_HISTOGRAM_ENUMERATION(
   1515             "Sync.CustomSync",
   1516             user_selectable_types[i],
   1517             browser_sync::user_selectable_type::SELECTABLE_DATATYPE_COUNT + 1);
   1518       }
   1519     }
   1520   }
   1521 }
   1522 
   1523 #if defined(OS_CHROMEOS)
   1524 void ProfileSyncService::RefreshSpareBootstrapToken(
   1525     const std::string& passphrase) {
   1526   browser_sync::ChromeEncryptor encryptor;
   1527   syncer::Cryptographer temp_cryptographer(&encryptor);
   1528   // The first 2 params (hostname and username) doesn't have any effect here.
   1529   syncer::KeyParams key_params = {"localhost", "dummy", passphrase};
   1530 
   1531   std::string bootstrap_token;
   1532   if (!temp_cryptographer.AddKey(key_params)) {
   1533     NOTREACHED() << "Failed to add key to cryptographer.";
   1534   }
   1535   temp_cryptographer.GetBootstrapToken(&bootstrap_token);
   1536   sync_prefs_.SetSpareBootstrapToken(bootstrap_token);
   1537 }
   1538 #endif
   1539 
   1540 void ProfileSyncService::OnUserChoseDatatypes(
   1541     bool sync_everything,
   1542     syncer::ModelTypeSet chosen_types) {
   1543   if (!backend_.get() && !HasUnrecoverableError()) {
   1544     NOTREACHED();
   1545     return;
   1546   }
   1547 
   1548   UpdateSelectedTypesHistogram(sync_everything, chosen_types);
   1549   sync_prefs_.SetKeepEverythingSynced(sync_everything);
   1550 
   1551   failed_data_types_handler_.Reset();
   1552   if (GetActiveDataTypes().Has(syncer::HISTORY_DELETE_DIRECTIVES) &&
   1553       encrypted_types_.Has(syncer::SESSIONS)) {
   1554     DisableBrokenDatatype(syncer::HISTORY_DELETE_DIRECTIVES,
   1555                           FROM_HERE,
   1556                           "Delete directives not supported with encryption.");
   1557   }
   1558   ChangePreferredDataTypes(chosen_types);
   1559   AcknowledgeSyncedTypes();
   1560   NotifyObservers();
   1561 }
   1562 
   1563 void ProfileSyncService::ChangePreferredDataTypes(
   1564     syncer::ModelTypeSet preferred_types) {
   1565 
   1566   DVLOG(1) << "ChangePreferredDataTypes invoked";
   1567   const syncer::ModelTypeSet registered_types = GetRegisteredDataTypes();
   1568   const syncer::ModelTypeSet registered_preferred_types =
   1569       Intersection(registered_types, preferred_types);
   1570   sync_prefs_.SetPreferredDataTypes(registered_types,
   1571                                     registered_preferred_types);
   1572 
   1573   // Now reconfigure the DTM.
   1574   ReconfigureDatatypeManager();
   1575 }
   1576 
   1577 syncer::ModelTypeSet ProfileSyncService::GetActiveDataTypes() const {
   1578   const syncer::ModelTypeSet preferred_types = GetPreferredDataTypes();
   1579   const syncer::ModelTypeSet failed_types =
   1580       failed_data_types_handler_.GetFailedTypes();
   1581   return Difference(preferred_types, failed_types);
   1582 }
   1583 
   1584 syncer::ModelTypeSet ProfileSyncService::GetPreferredDataTypes() const {
   1585   const syncer::ModelTypeSet registered_types = GetRegisteredDataTypes();
   1586   const syncer::ModelTypeSet preferred_types =
   1587       sync_prefs_.GetPreferredDataTypes(registered_types);
   1588   return preferred_types;
   1589 }
   1590 
   1591 syncer::ModelTypeSet ProfileSyncService::GetRegisteredDataTypes() const {
   1592   syncer::ModelTypeSet registered_types;
   1593   // The data_type_controllers_ are determined by command-line flags; that's
   1594   // effectively what controls the values returned here.
   1595   for (DataTypeController::TypeMap::const_iterator it =
   1596        data_type_controllers_.begin();
   1597        it != data_type_controllers_.end(); ++it) {
   1598     registered_types.Put(it->first);
   1599   }
   1600   return registered_types;
   1601 }
   1602 
   1603 bool ProfileSyncService::IsUsingSecondaryPassphrase() const {
   1604   syncer::PassphraseType passphrase_type = GetPassphraseType();
   1605   return passphrase_type == syncer::FROZEN_IMPLICIT_PASSPHRASE ||
   1606          passphrase_type == syncer::CUSTOM_PASSPHRASE;
   1607 }
   1608 
   1609 syncer::PassphraseType ProfileSyncService::GetPassphraseType() const {
   1610   return backend_->GetPassphraseType();
   1611 }
   1612 
   1613 base::Time ProfileSyncService::GetExplicitPassphraseTime() const {
   1614   return backend_->GetExplicitPassphraseTime();
   1615 }
   1616 
   1617 bool ProfileSyncService::IsCryptographerReady(
   1618     const syncer::BaseTransaction* trans) const {
   1619   return backend_.get() && backend_->IsCryptographerReady(trans);
   1620 }
   1621 
   1622 SyncBackendHost* ProfileSyncService::GetBackendForTest() {
   1623   // We don't check |backend_initialized_|; we assume the test class
   1624   // knows what it's doing.
   1625   return backend_.get();
   1626 }
   1627 
   1628 void ProfileSyncService::ConfigurePriorityDataTypes() {
   1629   const syncer::ModelTypeSet priority_types =
   1630       Intersection(GetPreferredDataTypes(), syncer::PriorityUserTypes());
   1631   if (!priority_types.Empty()) {
   1632     const syncer::ConfigureReason reason = HasSyncSetupCompleted() ?
   1633         syncer::CONFIGURE_REASON_RECONFIGURATION :
   1634         syncer::CONFIGURE_REASON_NEW_CLIENT;
   1635     data_type_manager_->Configure(priority_types, reason);
   1636   }
   1637 }
   1638 
   1639 void ProfileSyncService::ConfigureDataTypeManager() {
   1640   // Don't configure datatypes if the setup UI is still on the screen - this
   1641   // is to help multi-screen setting UIs (like iOS) where they don't want to
   1642   // start syncing data until the user is done configuring encryption options,
   1643   // etc. ReconfigureDatatypeManager() will get called again once the UI calls
   1644   // SetSetupInProgress(false).
   1645   if (setup_in_progress_)
   1646     return;
   1647 
   1648   bool restart = false;
   1649   if (!data_type_manager_) {
   1650     restart = true;
   1651     data_type_manager_.reset(
   1652         factory_->CreateDataTypeManager(debug_info_listener_,
   1653                                         &data_type_controllers_,
   1654                                         this,
   1655                                         backend_.get(),
   1656                                         this,
   1657                                         &failed_data_types_handler_));
   1658 
   1659     // We create the migrator at the same time.
   1660     migrator_.reset(
   1661         new browser_sync::BackendMigrator(
   1662             profile_->GetDebugName(), GetUserShare(),
   1663             this, data_type_manager_.get(),
   1664             base::Bind(&ProfileSyncService::StartSyncingWithServer,
   1665                        base::Unretained(this))));
   1666   }
   1667 
   1668   const syncer::ModelTypeSet types = GetPreferredDataTypes();
   1669   syncer::ConfigureReason reason = syncer::CONFIGURE_REASON_UNKNOWN;
   1670   if (!HasSyncSetupCompleted()) {
   1671     reason = syncer::CONFIGURE_REASON_NEW_CLIENT;
   1672   } else if (restart) {
   1673     // Datatype downloads on restart are generally due to newly supported
   1674     // datatypes (although it's also possible we're picking up where a failed
   1675     // previous configuration left off).
   1676     // TODO(sync): consider detecting configuration recovery and setting
   1677     // the reason here appropriately.
   1678     reason = syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE;
   1679   } else {
   1680     // The user initiated a reconfiguration (either to add or remove types).
   1681     reason = syncer::CONFIGURE_REASON_RECONFIGURATION;
   1682   }
   1683 
   1684   data_type_manager_->Configure(types, reason);
   1685 }
   1686 
   1687 syncer::UserShare* ProfileSyncService::GetUserShare() const {
   1688   if (backend_.get() && backend_initialized_) {
   1689     return backend_->GetUserShare();
   1690   }
   1691   NOTREACHED();
   1692   return NULL;
   1693 }
   1694 
   1695 syncer::sessions::SyncSessionSnapshot
   1696     ProfileSyncService::GetLastSessionSnapshot() const {
   1697   if (backend_.get() && backend_initialized_) {
   1698     return backend_->GetLastSessionSnapshot();
   1699   }
   1700   NOTREACHED();
   1701   return syncer::sessions::SyncSessionSnapshot();
   1702 }
   1703 
   1704 bool ProfileSyncService::HasUnsyncedItems() const {
   1705   if (backend_.get() && backend_initialized_) {
   1706     return backend_->HasUnsyncedItems();
   1707   }
   1708   NOTREACHED();
   1709   return false;
   1710 }
   1711 
   1712 browser_sync::BackendMigrator*
   1713     ProfileSyncService::GetBackendMigratorForTest() {
   1714   return migrator_.get();
   1715 }
   1716 
   1717 void ProfileSyncService::GetModelSafeRoutingInfo(
   1718     syncer::ModelSafeRoutingInfo* out) const {
   1719   if (backend_.get() && backend_initialized_) {
   1720     backend_->GetModelSafeRoutingInfo(out);
   1721   } else {
   1722     NOTREACHED();
   1723   }
   1724 }
   1725 
   1726 Value* ProfileSyncService::GetTypeStatusMap() const {
   1727   scoped_ptr<ListValue> result(new ListValue());
   1728 
   1729   if (!backend_.get() || !backend_initialized_) {
   1730     return result.release();
   1731   }
   1732 
   1733   FailedDataTypesHandler::TypeErrorMap error_map =
   1734       failed_data_types_handler_.GetAllErrors();
   1735 
   1736   ModelTypeSet active_types;
   1737   ModelTypeSet passive_types;
   1738   ModelSafeRoutingInfo routing_info;
   1739   backend_->GetModelSafeRoutingInfo(&routing_info);
   1740   for (ModelSafeRoutingInfo::const_iterator it = routing_info.begin();
   1741        it != routing_info.end(); ++it) {
   1742     if (it->second == syncer::GROUP_PASSIVE) {
   1743       passive_types.Put(it->first);
   1744     } else {
   1745       active_types.Put(it->first);
   1746     }
   1747   }
   1748 
   1749   SyncBackendHost::Status detailed_status = backend_->GetDetailedStatus();
   1750   ModelTypeSet &throttled_types(detailed_status.throttled_types);
   1751   ModelTypeSet registered = GetRegisteredDataTypes();
   1752   scoped_ptr<DictionaryValue> type_status_header(new DictionaryValue());
   1753 
   1754   type_status_header->SetString("name", "Model Type");
   1755   type_status_header->SetString("status", "header");
   1756   type_status_header->SetString("value", "Group Type");
   1757   type_status_header->SetString("num_entries", "Total Entries");
   1758   type_status_header->SetString("num_live", "Live Entries");
   1759   result->Append(type_status_header.release());
   1760 
   1761   scoped_ptr<DictionaryValue> type_status;
   1762   for (ModelTypeSet::Iterator it = registered.First(); it.Good(); it.Inc()) {
   1763     ModelType type = it.Get();
   1764 
   1765     type_status.reset(new DictionaryValue());
   1766     type_status->SetString("name", ModelTypeToString(type));
   1767 
   1768     if (error_map.find(type) != error_map.end()) {
   1769       const syncer::SyncError &error = error_map.find(type)->second;
   1770       DCHECK(error.IsSet());
   1771       std::string error_text = "Error: " + error.location().ToString() +
   1772           ", " + error.message();
   1773       type_status->SetString("status", "error");
   1774       type_status->SetString("value", error_text);
   1775     } else if (throttled_types.Has(type) && passive_types.Has(type)) {
   1776       type_status->SetString("status", "warning");
   1777       type_status->SetString("value", "Passive, Throttled");
   1778     } else if (passive_types.Has(type)) {
   1779       type_status->SetString("status", "warning");
   1780       type_status->SetString("value", "Passive");
   1781     } else if (throttled_types.Has(type)) {
   1782       type_status->SetString("status", "warning");
   1783       type_status->SetString("value", "Throttled");
   1784     } else if (active_types.Has(type)) {
   1785       type_status->SetString("status", "ok");
   1786       type_status->SetString("value", "Active: " +
   1787                              ModelSafeGroupToString(routing_info[type]));
   1788     } else {
   1789       type_status->SetString("status", "warning");
   1790       type_status->SetString("value", "Disabled by User");
   1791     }
   1792 
   1793     int live_count = detailed_status.num_entries_by_type[type] -
   1794         detailed_status.num_to_delete_entries_by_type[type];
   1795     type_status->SetInteger("num_entries",
   1796                             detailed_status.num_entries_by_type[type]);
   1797     type_status->SetInteger("num_live", live_count);
   1798 
   1799     result->Append(type_status.release());
   1800   }
   1801   return result.release();
   1802 }
   1803 
   1804 void ProfileSyncService::ActivateDataType(
   1805     syncer::ModelType type, syncer::ModelSafeGroup group,
   1806     ChangeProcessor* change_processor) {
   1807   if (!backend_) {
   1808     NOTREACHED();
   1809     return;
   1810   }
   1811   DCHECK(backend_initialized_);
   1812   backend_->ActivateDataType(type, group, change_processor);
   1813 }
   1814 
   1815 void ProfileSyncService::DeactivateDataType(syncer::ModelType type) {
   1816   if (!backend_)
   1817     return;
   1818   backend_->DeactivateDataType(type);
   1819 }
   1820 
   1821 void ProfileSyncService::ConsumeCachedPassphraseIfPossible() {
   1822   // If no cached passphrase, or sync backend hasn't started up yet, just exit.
   1823   // If the backend isn't running yet, OnBackendInitialized() will call this
   1824   // method again after the backend starts up.
   1825   if (cached_passphrase_.empty() || !sync_initialized())
   1826     return;
   1827 
   1828   // Backend is up and running, so we can consume the cached passphrase.
   1829   std::string passphrase = cached_passphrase_;
   1830   cached_passphrase_.clear();
   1831 
   1832   // If we need a passphrase to decrypt data, try the cached passphrase.
   1833   if (passphrase_required_reason() == syncer::REASON_DECRYPTION) {
   1834     if (SetDecryptionPassphrase(passphrase)) {
   1835       DVLOG(1) << "Cached passphrase successfully decrypted pending keys";
   1836       return;
   1837     }
   1838   }
   1839 
   1840   // If we get here, we don't have pending keys (or at least, the passphrase
   1841   // doesn't decrypt them) - just try to re-encrypt using the encryption
   1842   // passphrase.
   1843   if (!IsUsingSecondaryPassphrase())
   1844     SetEncryptionPassphrase(passphrase, IMPLICIT);
   1845 }
   1846 
   1847 void ProfileSyncService::RequestAccessToken() {
   1848   // Only one active request at a time.
   1849   if (access_token_request_ != NULL)
   1850     return;
   1851   request_access_token_retry_timer_.Stop();
   1852   OAuth2TokenService::ScopeSet oauth2_scopes;
   1853   if (profile_->IsManaged()) {
   1854     oauth2_scopes.insert(GaiaConstants::kChromeSyncManagedOAuth2Scope);
   1855   } else {
   1856     oauth2_scopes.insert(GaiaConstants::kChromeSyncOAuth2Scope);
   1857   }
   1858 
   1859   OAuth2TokenService* token_service =
   1860       ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
   1861   // Invalidate previous token, otherwise token service will return the same
   1862   // token again.
   1863   if (!access_token_.empty())
   1864     token_service->InvalidateToken(oauth2_scopes, access_token_);
   1865   access_token_.clear();
   1866   access_token_request_ = token_service->StartRequest(oauth2_scopes, this);
   1867 }
   1868 
   1869 void ProfileSyncService::SetEncryptionPassphrase(const std::string& passphrase,
   1870                                                  PassphraseType type) {
   1871   // This should only be called when the backend has been initialized.
   1872   DCHECK(sync_initialized());
   1873   DCHECK(!(type == IMPLICIT && IsUsingSecondaryPassphrase())) <<
   1874       "Data is already encrypted using an explicit passphrase";
   1875   DCHECK(!(type == EXPLICIT &&
   1876            passphrase_required_reason_ == syncer::REASON_DECRYPTION)) <<
   1877          "Can not set explicit passphrase when decryption is needed.";
   1878 
   1879   DVLOG(1) << "Setting " << (type == EXPLICIT ? "explicit" : "implicit")
   1880            << " passphrase for encryption.";
   1881   if (passphrase_required_reason_ == syncer::REASON_ENCRYPTION) {
   1882     // REASON_ENCRYPTION implies that the cryptographer does not have pending
   1883     // keys. Hence, as long as we're not trying to do an invalid passphrase
   1884     // change (e.g. explicit -> explicit or explicit -> implicit), we know this
   1885     // will succeed. If for some reason a new encryption key arrives via
   1886     // sync later, the SBH will trigger another OnPassphraseRequired().
   1887     passphrase_required_reason_ = syncer::REASON_PASSPHRASE_NOT_REQUIRED;
   1888     NotifyObservers();
   1889   }
   1890   backend_->SetEncryptionPassphrase(passphrase, type == EXPLICIT);
   1891 }
   1892 
   1893 bool ProfileSyncService::SetDecryptionPassphrase(
   1894     const std::string& passphrase) {
   1895   if (IsPassphraseRequired()) {
   1896     DVLOG(1) << "Setting passphrase for decryption.";
   1897     return backend_->SetDecryptionPassphrase(passphrase);
   1898   } else {
   1899     NOTREACHED() << "SetDecryptionPassphrase must not be called when "
   1900                     "IsPassphraseRequired() is false.";
   1901     return false;
   1902   }
   1903 }
   1904 
   1905 void ProfileSyncService::EnableEncryptEverything() {
   1906   // Tests override sync_initialized() to always return true, so we
   1907   // must check that instead of |backend_initialized_|.
   1908   // TODO(akalin): Fix the above. :/
   1909   DCHECK(sync_initialized());
   1910   // TODO(atwilson): Persist the encryption_pending_ flag to address the various
   1911   // problems around cancelling encryption in the background (crbug.com/119649).
   1912   if (!encrypt_everything_)
   1913     encryption_pending_ = true;
   1914 }
   1915 
   1916 bool ProfileSyncService::encryption_pending() const {
   1917   // We may be called during the setup process before we're
   1918   // initialized (via IsEncryptedDatatypeEnabled and
   1919   // IsPassphraseRequiredForDecryption).
   1920   return encryption_pending_;
   1921 }
   1922 
   1923 bool ProfileSyncService::EncryptEverythingEnabled() const {
   1924   DCHECK(backend_initialized_);
   1925   return encrypt_everything_ || encryption_pending_;
   1926 }
   1927 
   1928 syncer::ModelTypeSet ProfileSyncService::GetEncryptedDataTypes() const {
   1929   DCHECK(encrypted_types_.Has(syncer::PASSWORDS));
   1930   // We may be called during the setup process before we're
   1931   // initialized.  In this case, we default to the sensitive types.
   1932   return encrypted_types_;
   1933 }
   1934 
   1935 void ProfileSyncService::OnSyncManagedPrefChange(bool is_sync_managed) {
   1936   NotifyObservers();
   1937   if (is_sync_managed) {
   1938     DisableForUser();
   1939   } else {
   1940     // Sync is no longer disabled by policy. Try starting it up if appropriate.
   1941     TryStart();
   1942   }
   1943 }
   1944 
   1945 void ProfileSyncService::Observe(int type,
   1946                                  const content::NotificationSource& source,
   1947                                  const content::NotificationDetails& details) {
   1948   switch (type) {
   1949     case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL: {
   1950       const GoogleServiceSigninSuccessDetails* successful =
   1951           content::Details<const GoogleServiceSigninSuccessDetails>(
   1952               details).ptr();
   1953       if (!sync_prefs_.IsStartSuppressed() &&
   1954           !successful->password.empty()) {
   1955         cached_passphrase_ = successful->password;
   1956         // Try to consume the passphrase we just cached. If the sync backend
   1957         // is not running yet, the passphrase will remain cached until the
   1958         // backend starts up.
   1959         ConsumeCachedPassphraseIfPossible();
   1960       }
   1961 #if defined(OS_CHROMEOS)
   1962       RefreshSpareBootstrapToken(successful->password);
   1963 #endif
   1964       if (!sync_initialized() ||
   1965           GetAuthError().state() != AuthError::NONE) {
   1966         // Track the fact that we're still waiting for auth to complete.
   1967         is_auth_in_progress_ = true;
   1968       }
   1969       break;
   1970     }
   1971     case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT:
   1972       sync_disabled_by_admin_ = false;
   1973       DisableForUser();
   1974       break;
   1975     default: {
   1976       NOTREACHED();
   1977     }
   1978   }
   1979 }
   1980 
   1981 void ProfileSyncService::AddObserver(
   1982     ProfileSyncServiceBase::Observer* observer) {
   1983   observers_.AddObserver(observer);
   1984 }
   1985 
   1986 void ProfileSyncService::RemoveObserver(
   1987     ProfileSyncServiceBase::Observer* observer) {
   1988   observers_.RemoveObserver(observer);
   1989 }
   1990 
   1991 bool ProfileSyncService::HasObserver(
   1992     ProfileSyncServiceBase::Observer* observer) const {
   1993   return observers_.HasObserver(observer);
   1994 }
   1995 
   1996 base::WeakPtr<syncer::JsController> ProfileSyncService::GetJsController() {
   1997   return sync_js_controller_.AsWeakPtr();
   1998 }
   1999 
   2000 void ProfileSyncService::SyncEvent(SyncEventCodes code) {
   2001   UMA_HISTOGRAM_ENUMERATION("Sync.EventCodes", code, MAX_SYNC_EVENT_CODE);
   2002 }
   2003 
   2004 // static
   2005 bool ProfileSyncService::IsSyncEnabled() {
   2006   // We have switches::kEnableSync just in case we need to change back to
   2007   // sync-disabled-by-default on a platform.
   2008   return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableSync);
   2009 }
   2010 
   2011 bool ProfileSyncService::IsManaged() const {
   2012   return sync_prefs_.IsManaged() || sync_disabled_by_admin_;
   2013 }
   2014 
   2015 bool ProfileSyncService::ShouldPushChanges() {
   2016   // True only after all bootstrapping has succeeded: the sync backend
   2017   // is initialized, all enabled data types are consistent with one
   2018   // another, and no unrecoverable error has transpired.
   2019   if (HasUnrecoverableError())
   2020     return false;
   2021 
   2022   if (!data_type_manager_)
   2023     return false;
   2024 
   2025   return data_type_manager_->state() == DataTypeManager::CONFIGURED;
   2026 }
   2027 
   2028 void ProfileSyncService::StopAndSuppress() {
   2029   sync_prefs_.SetStartSuppressed(true);
   2030   if (backend_) {
   2031     backend_->UnregisterInvalidationIds();
   2032   }
   2033   ShutdownImpl(browser_sync::SyncBackendHost::STOP_AND_CLAIM_THREAD);
   2034 }
   2035 
   2036 bool ProfileSyncService::IsStartSuppressed() const {
   2037   return sync_prefs_.IsStartSuppressed();
   2038 }
   2039 
   2040 void ProfileSyncService::UnsuppressAndStart() {
   2041   DCHECK(profile_);
   2042   sync_prefs_.SetStartSuppressed(false);
   2043   // Set username in SigninManager, as SigninManager::OnGetUserInfoSuccess
   2044   // is never called for some clients.
   2045   if (signin_ && signin_->GetAuthenticatedUsername().empty()) {
   2046     signin_->SetAuthenticatedUsername(sync_prefs_.GetGoogleServicesUsername());
   2047   }
   2048   TryStart();
   2049 }
   2050 
   2051 void ProfileSyncService::AcknowledgeSyncedTypes() {
   2052   sync_prefs_.AcknowledgeSyncedTypes(GetRegisteredDataTypes());
   2053 }
   2054 
   2055 void ProfileSyncService::ReconfigureDatatypeManager() {
   2056   // If we haven't initialized yet, don't configure the DTM as it could cause
   2057   // association to start before a Directory has even been created.
   2058   if (backend_initialized_) {
   2059     DCHECK(backend_.get());
   2060     ConfigureDataTypeManager();
   2061   } else if (HasUnrecoverableError()) {
   2062     // There is nothing more to configure. So inform the listeners,
   2063     NotifyObservers();
   2064 
   2065     DVLOG(1) << "ConfigureDataTypeManager not invoked because of an "
   2066              << "Unrecoverable error.";
   2067   } else {
   2068     DVLOG(0) << "ConfigureDataTypeManager not invoked because backend is not "
   2069              << "initialized";
   2070   }
   2071 }
   2072 
   2073 const FailedDataTypesHandler& ProfileSyncService::failed_data_types_handler()
   2074     const {
   2075   return failed_data_types_handler_;
   2076 }
   2077 
   2078 void ProfileSyncService::OnInternalUnrecoverableError(
   2079     const tracked_objects::Location& from_here,
   2080     const std::string& message,
   2081     bool delete_sync_database,
   2082     UnrecoverableErrorReason reason) {
   2083   DCHECK(!HasUnrecoverableError());
   2084   unrecoverable_error_reason_ = reason;
   2085   OnUnrecoverableErrorImpl(from_here, message, delete_sync_database);
   2086 }
   2087 
   2088 std::string ProfileSyncService::GetEffectiveUsername() {
   2089   if (profile_->IsManaged()) {
   2090 #if defined(ENABLE_MANAGED_USERS)
   2091     DCHECK_EQ(std::string(), signin_->GetAuthenticatedUsername());
   2092     return ManagedUserService::GetManagedUserPseudoEmail();
   2093 #else
   2094     NOTREACHED();
   2095 #endif
   2096   }
   2097 
   2098   return signin_->GetAuthenticatedUsername();
   2099 }
   2100 
   2101 WeakHandle<syncer::JsEventHandler> ProfileSyncService::GetJsEventHandler() {
   2102   return MakeWeakHandle(sync_js_controller_.AsWeakPtr());
   2103 }
   2104