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