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

Side by Side Diff: components/browser_sync/browser/profile_sync_service.cc

Issue 2345843003: [Sync] Merge //components/browser_sync into one directory. (Closed)
Patch Set: Address comment + rebase. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/browser_sync/browser/profile_sync_service.h"
6
7 #include <stddef.h>
8
9 #include <cstddef>
10 #include <map>
11 #include <utility>
12 #include <vector>
13
14 #include "base/bind.h"
15 #include "base/bind_helpers.h"
16 #include "base/callback.h"
17 #include "base/command_line.h"
18 #include "base/compiler_specific.h"
19 #include "base/feature_list.h"
20 #include "base/files/file_util.h"
21 #include "base/logging.h"
22 #include "base/macros.h"
23 #include "base/memory/ptr_util.h"
24 #include "base/memory/ref_counted.h"
25 #include "base/metrics/histogram.h"
26 #include "base/profiler/scoped_tracker.h"
27 #include "base/single_thread_task_runner.h"
28 #include "base/strings/string16.h"
29 #include "base/strings/stringprintf.h"
30 #include "base/threading/thread_restrictions.h"
31 #include "base/threading/thread_task_runner_handle.h"
32 #include "base/time/time.h"
33 #include "build/build_config.h"
34 #include "components/autofill/core/common/autofill_pref_names.h"
35 #include "components/browser_sync/common/browser_sync_switches.h"
36 #include "components/history/core/browser/typed_url_data_type_controller.h"
37 #include "components/invalidation/impl/invalidation_prefs.h"
38 #include "components/invalidation/public/invalidation_service.h"
39 #include "components/pref_registry/pref_registry_syncable.h"
40 #include "components/prefs/json_pref_store.h"
41 #include "components/signin/core/browser/about_signin_internals.h"
42 #include "components/signin/core/browser/profile_oauth2_token_service.h"
43 #include "components/signin/core/browser/signin_manager.h"
44 #include "components/signin/core/browser/signin_metrics.h"
45 #include "components/strings/grit/components_strings.h"
46 #include "components/sync/api/model_type_store.h"
47 #include "components/sync/api/sync_error.h"
48 #include "components/sync/base/cryptographer.h"
49 #include "components/sync/base/experiments.h"
50 #include "components/sync/base/passphrase_type.h"
51 #include "components/sync/base/stop_source.h"
52 #include "components/sync/base/sync_db_util.h"
53 #include "components/sync/core/configure_reason.h"
54 #include "components/sync/core/http_bridge_network_resources.h"
55 #include "components/sync/core/network_resources.h"
56 #include "components/sync/core/shared_model_type_processor.h"
57 #include "components/sync/core/shutdown_reason.h"
58 #include "components/sync/core/sync_encryption_handler.h"
59 #include "components/sync/device_info/device_info.h"
60 #include "components/sync/device_info/device_info_service.h"
61 #include "components/sync/device_info/device_info_sync_service.h"
62 #include "components/sync/device_info/device_info_tracker.h"
63 #include "components/sync/driver/backend_migrator.h"
64 #include "components/sync/driver/change_processor.h"
65 #include "components/sync/driver/data_type_controller.h"
66 #include "components/sync/driver/directory_data_type_controller.h"
67 #include "components/sync/driver/glue/chrome_report_unrecoverable_error.h"
68 #include "components/sync/driver/glue/sync_backend_host.h"
69 #include "components/sync/driver/glue/sync_backend_host_impl.h"
70 #include "components/sync/driver/pref_names.h"
71 #include "components/sync/driver/signin_manager_wrapper.h"
72 #include "components/sync/driver/sync_api_component_factory.h"
73 #include "components/sync/driver/sync_client.h"
74 #include "components/sync/driver/sync_driver_switches.h"
75 #include "components/sync/driver/sync_error_controller.h"
76 #include "components/sync/driver/sync_stopped_reporter.h"
77 #include "components/sync/driver/sync_type_preference_provider.h"
78 #include "components/sync/driver/sync_util.h"
79 #include "components/sync/driver/system_encryptor.h"
80 #include "components/sync/driver/user_selectable_sync_type.h"
81 #include "components/sync/engine/cycle/model_neutral_state.h"
82 #include "components/sync/engine/cycle/type_debug_info_observer.h"
83 #include "components/sync/engine/sync_string_conversions.h"
84 #include "components/sync/js/js_event_details.h"
85 #include "components/sync/protocol/sync.pb.h"
86 #include "components/sync/syncable/directory.h"
87 #include "components/sync/syncable/syncable_read_transaction.h"
88 #include "components/sync_sessions/favicon_cache.h"
89 #include "components/sync_sessions/session_data_type_controller.h"
90 #include "components/sync_sessions/sessions_sync_manager.h"
91 #include "components/sync_sessions/sync_sessions_client.h"
92 #include "components/syncable_prefs/pref_service_syncable.h"
93 #include "components/version_info/version_info_values.h"
94 #include "net/cookies/cookie_monster.h"
95 #include "net/url_request/url_request_context_getter.h"
96 #include "ui/base/l10n/l10n_util.h"
97 #include "ui/base/l10n/time_format.h"
98
99 #if defined(OS_ANDROID)
100 #include "components/sync/core/read_transaction.h"
101 #endif
102
103 using browser_sync::SyncBackendHost;
104 using sync_driver::ChangeProcessor;
105 using sync_driver::DataTypeController;
106 using sync_driver::DataTypeManager;
107 using sync_driver::DataTypeStatusTable;
108 using sync_driver::DeviceInfoSyncService;
109 using sync_driver_v2::DeviceInfoService;
110 using sync_sessions::SessionsSyncManager;
111 using syncer::ModelType;
112 using syncer::ModelTypeSet;
113 using syncer::JsBackend;
114 using syncer::JsController;
115 using syncer::JsEventDetails;
116 using syncer::JsEventHandler;
117 using syncer::ModelSafeRoutingInfo;
118 using syncer::SyncCredentials;
119 using syncer::SyncProtocolError;
120 using syncer::WeakHandle;
121 using syncer_v2::ModelTypeStore;
122 using syncer_v2::SharedModelTypeProcessor;
123
124 typedef GoogleServiceAuthError AuthError;
125
126 const char kSyncUnrecoverableErrorHistogram[] =
127 "Sync.UnrecoverableErrors";
128
129 const net::BackoffEntry::Policy kRequestAccessTokenBackoffPolicy = {
130 // Number of initial errors (in sequence) to ignore before applying
131 // exponential back-off rules.
132 0,
133
134 // Initial delay for exponential back-off in ms.
135 2000,
136
137 // Factor by which the waiting time will be multiplied.
138 2,
139
140 // Fuzzing percentage. ex: 10% will spread requests randomly
141 // between 90%-100% of the calculated time.
142 0.2, // 20%
143
144 // Maximum amount of time we are willing to delay our request in ms.
145 // TODO(pavely): crbug.com/246686 ProfileSyncService should retry
146 // RequestAccessToken on connection state change after backoff
147 1000 * 3600 * 4, // 4 hours.
148
149 // Time to keep an entry from being discarded even when it
150 // has no significant state, -1 to never discard.
151 -1,
152
153 // Don't use initial delay unless the last request was an error.
154 false,
155 };
156
157 static const base::FilePath::CharType kSyncDataFolderName[] =
158 FILE_PATH_LITERAL("Sync Data");
159 static const base::FilePath::CharType kLevelDBFolderName[] =
160 FILE_PATH_LITERAL("LevelDB");
161
162 namespace {
163
164 // Perform the actual sync data folder deletion.
165 // This should only be called on the sync thread.
166 void DeleteSyncDataFolder(const base::FilePath& directory_path) {
167 if (base::DirectoryExists(directory_path)) {
168 if (!base::DeleteFile(directory_path, true))
169 LOG(DFATAL) << "Could not delete the Sync Data folder.";
170 }
171 }
172
173 } // namespace
174
175 bool ShouldShowActionOnUI(
176 const syncer::SyncProtocolError& error) {
177 return (error.action != syncer::UNKNOWN_ACTION &&
178 error.action != syncer::DISABLE_SYNC_ON_CLIENT &&
179 error.action != syncer::STOP_SYNC_FOR_DISABLED_ACCOUNT &&
180 error.action != syncer::RESET_LOCAL_SYNC_DATA);
181 }
182
183 ProfileSyncService::InitParams::InitParams() = default;
184 ProfileSyncService::InitParams::~InitParams() = default;
185 ProfileSyncService::InitParams::InitParams(InitParams&& other) // NOLINT
186 : sync_client(std::move(other.sync_client)),
187 signin_wrapper(std::move(other.signin_wrapper)),
188 oauth2_token_service(other.oauth2_token_service),
189 gaia_cookie_manager_service(other.gaia_cookie_manager_service),
190 start_behavior(other.start_behavior),
191 network_time_update_callback(
192 std::move(other.network_time_update_callback)),
193 base_directory(std::move(other.base_directory)),
194 url_request_context(std::move(other.url_request_context)),
195 debug_identifier(std::move(other.debug_identifier)),
196 channel(other.channel),
197 db_thread(std::move(other.db_thread)),
198 file_thread(std::move(other.file_thread)),
199 blocking_pool(other.blocking_pool) {}
200
201 ProfileSyncService::ProfileSyncService(InitParams init_params)
202 : OAuth2TokenService::Consumer("sync"),
203 last_auth_error_(AuthError::AuthErrorNone()),
204 passphrase_required_reason_(syncer::REASON_PASSPHRASE_NOT_REQUIRED),
205 sync_client_(std::move(init_params.sync_client)),
206 sync_prefs_(sync_client_->GetPrefService()),
207 sync_service_url_(
208 GetSyncServiceURL(*base::CommandLine::ForCurrentProcess(),
209 init_params.channel)),
210 network_time_update_callback_(
211 std::move(init_params.network_time_update_callback)),
212 base_directory_(init_params.base_directory),
213 url_request_context_(init_params.url_request_context),
214 debug_identifier_(std::move(init_params.debug_identifier)),
215 channel_(init_params.channel),
216 db_thread_(init_params.db_thread),
217 file_thread_(init_params.file_thread),
218 blocking_pool_(init_params.blocking_pool),
219 is_first_time_sync_configure_(false),
220 backend_initialized_(false),
221 sync_disabled_by_admin_(false),
222 is_auth_in_progress_(false),
223 signin_(std::move(init_params.signin_wrapper)),
224 unrecoverable_error_reason_(ERROR_REASON_UNSET),
225 expect_sync_configuration_aborted_(false),
226 encrypted_types_(syncer::SyncEncryptionHandler::SensitiveTypes()),
227 encrypt_everything_allowed_(true),
228 encrypt_everything_(false),
229 encryption_pending_(false),
230 configure_status_(DataTypeManager::UNKNOWN),
231 oauth2_token_service_(init_params.oauth2_token_service),
232 request_access_token_backoff_(&kRequestAccessTokenBackoffPolicy),
233 connection_status_(syncer::CONNECTION_NOT_ATTEMPTED),
234 last_get_token_error_(GoogleServiceAuthError::AuthErrorNone()),
235 gaia_cookie_manager_service_(init_params.gaia_cookie_manager_service),
236 network_resources_(new syncer::HttpBridgeNetworkResources),
237 start_behavior_(init_params.start_behavior),
238 directory_path_(
239 base_directory_.Append(base::FilePath(kSyncDataFolderName))),
240 catch_up_configure_in_progress_(false),
241 passphrase_prompt_triggered_by_version_(false),
242 sync_enabled_weak_factory_(this),
243 weak_factory_(this) {
244 DCHECK(thread_checker_.CalledOnValidThread());
245 DCHECK(sync_client_);
246 std::string last_version = sync_prefs_.GetLastRunVersion();
247 std::string current_version = PRODUCT_VERSION;
248 sync_prefs_.SetLastRunVersion(current_version);
249
250 // Check for a major version change. Note that the versions have format
251 // MAJOR.MINOR.BUILD.PATCH.
252 if (last_version.substr(0, last_version.find('.')) !=
253 current_version.substr(0, current_version.find('.'))) {
254 passphrase_prompt_triggered_by_version_ = true;
255 }
256 }
257
258 ProfileSyncService::~ProfileSyncService() {
259 if (gaia_cookie_manager_service_)
260 gaia_cookie_manager_service_->RemoveObserver(this);
261 sync_prefs_.RemoveSyncPrefObserver(this);
262 // Shutdown() should have been called before destruction.
263 CHECK(!backend_initialized_);
264 }
265
266 bool ProfileSyncService::CanSyncStart() const {
267 return IsSyncAllowed() && IsSyncRequested() && IsSignedIn();
268 }
269
270 void ProfileSyncService::Initialize() {
271 sync_client_->Initialize();
272
273 // We don't pass StartupController an Unretained reference to future-proof
274 // against the controller impl changing to post tasks.
275 startup_controller_.reset(new browser_sync::StartupController(
276 &sync_prefs_,
277 base::Bind(&ProfileSyncService::CanBackendStart, base::Unretained(this)),
278 base::Bind(&ProfileSyncService::StartUpSlowBackendComponents,
279 weak_factory_.GetWeakPtr())));
280 std::unique_ptr<sync_sessions::LocalSessionEventRouter> router(
281 sync_client_->GetSyncSessionsClient()->GetLocalSessionEventRouter());
282 local_device_ = sync_client_->GetSyncApiComponentFactory()
283 ->CreateLocalDeviceInfoProvider();
284 sync_stopped_reporter_.reset(new browser_sync::SyncStoppedReporter(
285 sync_service_url_, local_device_->GetSyncUserAgent(),
286 url_request_context_,
287 browser_sync::SyncStoppedReporter::ResultCallback()));
288 sessions_sync_manager_.reset(new SessionsSyncManager(
289 sync_client_->GetSyncSessionsClient(), &sync_prefs_, local_device_.get(),
290 std::move(router),
291 base::Bind(&ProfileSyncService::NotifyForeignSessionUpdated,
292 sync_enabled_weak_factory_.GetWeakPtr()),
293 base::Bind(&ProfileSyncService::TriggerRefresh,
294 sync_enabled_weak_factory_.GetWeakPtr(),
295 syncer::ModelTypeSet(syncer::SESSIONS))));
296
297 if (base::FeatureList::IsEnabled(switches::kSyncUSSDeviceInfo)) {
298 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner(
299 blocking_pool_->GetSequencedTaskRunnerWithShutdownBehavior(
300 blocking_pool_->GetSequenceToken(),
301 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
302 // TODO(skym): Stop creating leveldb files when signed out.
303 // TODO(skym): Verify using AsUTF8Unsafe is okay here. Should work as long
304 // as the Local State file is guaranteed to be UTF-8.
305 device_info_service_.reset(new DeviceInfoService(
306 local_device_.get(),
307 base::Bind(&ModelTypeStore::CreateStore, syncer::DEVICE_INFO,
308 directory_path_.Append(base::FilePath(kLevelDBFolderName))
309 .AsUTF8Unsafe(),
310 blocking_task_runner),
311 base::Bind(&SharedModelTypeProcessor::CreateAsChangeProcessor)));
312 } else {
313 device_info_sync_service_.reset(
314 new DeviceInfoSyncService(local_device_.get()));
315 }
316
317 sync_driver::SyncApiComponentFactory::RegisterDataTypesMethod
318 register_platform_types_callback =
319 sync_client_->GetRegisterPlatformTypesCallback();
320 sync_client_->GetSyncApiComponentFactory()->RegisterDataTypes(
321 this, register_platform_types_callback);
322
323 if (gaia_cookie_manager_service_)
324 gaia_cookie_manager_service_->AddObserver(this);
325
326 // We clear this here (vs Shutdown) because we want to remember that an error
327 // happened on shutdown so we can display details (message, location) about it
328 // in about:sync.
329 ClearStaleErrors();
330
331 sync_prefs_.AddSyncPrefObserver(this);
332
333 SyncInitialState sync_state = CAN_START;
334 if (!IsSignedIn()) {
335 sync_state = NOT_SIGNED_IN;
336 } else if (IsManaged()) {
337 sync_state = IS_MANAGED;
338 } else if (!IsSyncAllowedByPlatform()) {
339 // This case should currently never be hit, as Android's master sync isn't
340 // plumbed into PSS until after this function. See http://crbug.com/568771.
341 sync_state = NOT_ALLOWED_BY_PLATFORM;
342 } else if (!IsSyncRequested()) {
343 if (IsFirstSetupComplete()) {
344 sync_state = NOT_REQUESTED;
345 } else {
346 sync_state = NOT_REQUESTED_NOT_SETUP;
347 }
348 } else if (!IsFirstSetupComplete()) {
349 sync_state = NEEDS_CONFIRMATION;
350 }
351 UMA_HISTOGRAM_ENUMERATION("Sync.InitialState", sync_state,
352 SYNC_INITIAL_STATE_LIMIT);
353
354 // If sync isn't allowed, the only thing to do is to turn it off.
355 if (!IsSyncAllowed()) {
356 // Only clear data if disallowed by policy.
357 RequestStop(IsManaged() ? CLEAR_DATA : KEEP_DATA);
358 return;
359 }
360
361 RegisterAuthNotifications();
362
363 if (!IsSignedIn()) {
364 // Clean up in case of previous crash during signout.
365 StopImpl(CLEAR_DATA);
366 }
367
368 #if defined(OS_CHROMEOS)
369 std::string bootstrap_token = sync_prefs_.GetEncryptionBootstrapToken();
370 if (bootstrap_token.empty()) {
371 sync_prefs_.SetEncryptionBootstrapToken(
372 sync_prefs_.GetSpareBootstrapToken());
373 }
374 #endif
375
376 #if !defined(OS_ANDROID)
377 DCHECK(sync_error_controller_ == NULL)
378 << "Initialize() called more than once.";
379 sync_error_controller_.reset(new SyncErrorController(this));
380 AddObserver(sync_error_controller_.get());
381 #endif
382
383 memory_pressure_listener_.reset(new base::MemoryPressureListener(
384 base::Bind(&ProfileSyncService::OnMemoryPressure,
385 sync_enabled_weak_factory_.GetWeakPtr())));
386 startup_controller_->Reset(GetRegisteredDataTypes());
387
388 // Auto-start means means the first time the profile starts up, sync should
389 // start up immediately.
390 if (start_behavior_ == AUTO_START && IsSyncRequested() &&
391 !IsFirstSetupComplete()) {
392 startup_controller_->TryStartImmediately();
393 } else {
394 startup_controller_->TryStart();
395 }
396 }
397
398 void ProfileSyncService::StartSyncingWithServer() {
399 DCHECK(thread_checker_.CalledOnValidThread());
400
401 if (base::FeatureList::IsEnabled(
402 switches::kSyncClearDataOnPassphraseEncryption) &&
403 sync_prefs_.GetPassphraseEncryptionTransitionInProgress()) {
404 BeginConfigureCatchUpBeforeClear();
405 return;
406 }
407
408 if (backend_)
409 backend_->StartSyncingWithServer();
410 }
411
412 void ProfileSyncService::RegisterAuthNotifications() {
413 oauth2_token_service_->AddObserver(this);
414 if (signin())
415 signin()->AddObserver(this);
416 }
417
418 void ProfileSyncService::UnregisterAuthNotifications() {
419 if (signin())
420 signin()->RemoveObserver(this);
421 oauth2_token_service_->RemoveObserver(this);
422 }
423
424 void ProfileSyncService::RegisterDataTypeController(
425 std::unique_ptr<sync_driver::DataTypeController> data_type_controller) {
426 DCHECK_EQ(data_type_controllers_.count(data_type_controller->type()), 0U);
427 data_type_controllers_[data_type_controller->type()] =
428 std::move(data_type_controller);
429 }
430
431 bool ProfileSyncService::IsDataTypeControllerRunning(
432 syncer::ModelType type) const {
433 DataTypeController::TypeMap::const_iterator iter =
434 data_type_controllers_.find(type);
435 if (iter == data_type_controllers_.end()) {
436 return false;
437 }
438 return iter->second->state() == DataTypeController::RUNNING;
439 }
440
441 sync_sessions::OpenTabsUIDelegate* ProfileSyncService::GetOpenTabsUIDelegate() {
442 if (!IsDataTypeControllerRunning(syncer::SESSIONS))
443 return NULL;
444 return sessions_sync_manager_.get();
445 }
446
447 sync_sessions::FaviconCache* ProfileSyncService::GetFaviconCache() {
448 return sessions_sync_manager_->GetFaviconCache();
449 }
450
451 sync_driver::DeviceInfoTracker* ProfileSyncService::GetDeviceInfoTracker()
452 const {
453 // One of the two should always be non-null after initialization is done.
454 if (device_info_service_) {
455 return device_info_service_.get();
456 } else {
457 return device_info_sync_service_.get();
458 }
459 }
460
461 sync_driver::LocalDeviceInfoProvider*
462 ProfileSyncService::GetLocalDeviceInfoProvider() const {
463 return local_device_.get();
464 }
465
466 void ProfileSyncService::GetDataTypeControllerStates(
467 DataTypeController::StateMap* state_map) const {
468 for (DataTypeController::TypeMap::const_iterator iter =
469 data_type_controllers_.begin();
470 iter != data_type_controllers_.end(); ++iter)
471 (*state_map)[iter->first] = iter->second.get()->state();
472 }
473
474 void ProfileSyncService::OnSessionRestoreComplete() {
475 DataTypeController::TypeMap::const_iterator iter =
476 data_type_controllers_.find(syncer::SESSIONS);
477 if (iter == data_type_controllers_.end()) {
478 return;
479 }
480 DCHECK(iter->second);
481
482 static_cast<sync_sessions::SessionDataTypeController*>(iter->second.get())
483 ->OnSessionRestoreComplete();
484 }
485
486 SyncCredentials ProfileSyncService::GetCredentials() {
487 SyncCredentials credentials;
488 credentials.account_id = signin_->GetAccountIdToUse();
489 DCHECK(!credentials.account_id.empty());
490 credentials.email = signin_->GetEffectiveUsername();
491 credentials.sync_token = access_token_;
492
493 if (credentials.sync_token.empty())
494 credentials.sync_token = "credentials_lost";
495
496 credentials.scope_set.insert(signin_->GetSyncScopeToUse());
497
498 return credentials;
499 }
500
501 bool ProfileSyncService::ShouldDeleteSyncFolder() {
502 return !IsFirstSetupComplete();
503 }
504
505 void ProfileSyncService::InitializeBackend(bool delete_stale_data) {
506 if (!backend_) {
507 NOTREACHED();
508 return;
509 }
510
511 SyncCredentials credentials = GetCredentials();
512
513 if (delete_stale_data)
514 ClearStaleErrors();
515
516 SyncBackendHost::HttpPostProviderFactoryGetter
517 http_post_provider_factory_getter =
518 base::Bind(&syncer::NetworkResources::GetHttpPostProviderFactory,
519 base::Unretained(network_resources_.get()),
520 url_request_context_,
521 network_time_update_callback_);
522
523 backend_->Initialize(
524 this, std::move(sync_thread_), db_thread_, file_thread_,
525 GetJsEventHandler(), sync_service_url_, local_device_->GetSyncUserAgent(),
526 credentials, delete_stale_data,
527 std::unique_ptr<syncer::SyncManagerFactory>(
528 new syncer::SyncManagerFactory()),
529 MakeWeakHandle(sync_enabled_weak_factory_.GetWeakPtr()),
530 base::Bind(browser_sync::ChromeReportUnrecoverableError, channel_),
531 http_post_provider_factory_getter, std::move(saved_nigori_state_));
532 }
533
534 bool ProfileSyncService::IsEncryptedDatatypeEnabled() const {
535 if (encryption_pending())
536 return true;
537 const syncer::ModelTypeSet preferred_types = GetPreferredDataTypes();
538 const syncer::ModelTypeSet encrypted_types = GetEncryptedDataTypes();
539 DCHECK(encrypted_types.Has(syncer::PASSWORDS));
540 return !Intersection(preferred_types, encrypted_types).Empty();
541 }
542
543 void ProfileSyncService::OnProtocolEvent(
544 const syncer::ProtocolEvent& event) {
545 FOR_EACH_OBSERVER(browser_sync::ProtocolEventObserver,
546 protocol_event_observers_,
547 OnProtocolEvent(event));
548 }
549
550 void ProfileSyncService::OnDirectoryTypeCommitCounterUpdated(
551 syncer::ModelType type,
552 const syncer::CommitCounters& counters) {
553 FOR_EACH_OBSERVER(syncer::TypeDebugInfoObserver,
554 type_debug_info_observers_,
555 OnCommitCountersUpdated(type, counters));
556 }
557
558 void ProfileSyncService::OnDirectoryTypeUpdateCounterUpdated(
559 syncer::ModelType type,
560 const syncer::UpdateCounters& counters) {
561 FOR_EACH_OBSERVER(syncer::TypeDebugInfoObserver,
562 type_debug_info_observers_,
563 OnUpdateCountersUpdated(type, counters));
564 }
565
566 void ProfileSyncService::OnDirectoryTypeStatusCounterUpdated(
567 syncer::ModelType type,
568 const syncer::StatusCounters& counters) {
569 FOR_EACH_OBSERVER(syncer::TypeDebugInfoObserver,
570 type_debug_info_observers_,
571 OnStatusCountersUpdated(type, counters));
572 }
573
574 void ProfileSyncService::OnDataTypeRequestsSyncStartup(
575 syncer::ModelType type) {
576 DCHECK(syncer::UserTypes().Has(type));
577
578 if (!GetPreferredDataTypes().Has(type)) {
579 // We can get here as datatype SyncableServices are typically wired up
580 // to the native datatype even if sync isn't enabled.
581 DVLOG(1) << "Dropping sync startup request because type "
582 << syncer::ModelTypeToString(type) << "not enabled.";
583 return;
584 }
585
586 // If this is a data type change after a major version update, reset the
587 // passphrase prompted state and notify observers.
588 if (IsPassphraseRequired() && passphrase_prompt_triggered_by_version_) {
589 // The major version has changed and a local syncable change was made.
590 // Reset the passphrase prompt state.
591 passphrase_prompt_triggered_by_version_ = false;
592 sync_prefs_.SetPassphrasePrompted(false);
593 NotifyObservers();
594 }
595
596 if (backend_.get()) {
597 DVLOG(1) << "A data type requested sync startup, but it looks like "
598 "something else beat it to the punch.";
599 return;
600 }
601
602 startup_controller_->OnDataTypeRequestsSyncStartup(type);
603 }
604
605 void ProfileSyncService::StartUpSlowBackendComponents() {
606 invalidation::InvalidationService* invalidator =
607 sync_client_->GetInvalidationService();
608
609 backend_.reset(
610 sync_client_->GetSyncApiComponentFactory()->CreateSyncBackendHost(
611 debug_identifier_, invalidator, sync_prefs_.AsWeakPtr(),
612 directory_path_));
613
614 // Initialize the backend. Every time we start up a new SyncBackendHost,
615 // we'll want to start from a fresh SyncDB, so delete any old one that might
616 // be there.
617 InitializeBackend(ShouldDeleteSyncFolder());
618
619 UpdateFirstSyncTimePref();
620
621 ReportPreviousSessionMemoryWarningCount();
622 }
623
624 void ProfileSyncService::OnGetTokenSuccess(
625 const OAuth2TokenService::Request* request,
626 const std::string& access_token,
627 const base::Time& expiration_time) {
628 DCHECK_EQ(access_token_request_.get(), request);
629 access_token_request_.reset();
630 access_token_ = access_token;
631 token_receive_time_ = base::Time::Now();
632 last_get_token_error_ = GoogleServiceAuthError::AuthErrorNone();
633
634 if (sync_prefs_.SyncHasAuthError()) {
635 sync_prefs_.SetSyncAuthError(false);
636 }
637
638 if (HasSyncingBackend())
639 backend_->UpdateCredentials(GetCredentials());
640 else
641 startup_controller_->TryStart();
642 }
643
644 void ProfileSyncService::OnGetTokenFailure(
645 const OAuth2TokenService::Request* request,
646 const GoogleServiceAuthError& error) {
647 DCHECK_EQ(access_token_request_.get(), request);
648 DCHECK_NE(error.state(), GoogleServiceAuthError::NONE);
649 access_token_request_.reset();
650 last_get_token_error_ = error;
651 switch (error.state()) {
652 case GoogleServiceAuthError::CONNECTION_FAILED:
653 case GoogleServiceAuthError::REQUEST_CANCELED:
654 case GoogleServiceAuthError::SERVICE_ERROR:
655 case GoogleServiceAuthError::SERVICE_UNAVAILABLE: {
656 // Transient error. Retry after some time.
657 request_access_token_backoff_.InformOfRequest(false);
658 next_token_request_time_ = base::Time::Now() +
659 request_access_token_backoff_.GetTimeUntilRelease();
660 request_access_token_retry_timer_.Start(
661 FROM_HERE, request_access_token_backoff_.GetTimeUntilRelease(),
662 base::Bind(&ProfileSyncService::RequestAccessToken,
663 sync_enabled_weak_factory_.GetWeakPtr()));
664 NotifyObservers();
665 break;
666 }
667 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: {
668 if (!sync_prefs_.SyncHasAuthError()) {
669 sync_prefs_.SetSyncAuthError(true);
670 UMA_HISTOGRAM_ENUMERATION("Sync.SyncAuthError",
671 AUTH_ERROR_ENCOUNTERED,
672 AUTH_ERROR_LIMIT);
673 }
674 // Fallthrough.
675 }
676 default: {
677 if (error.state() != GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS) {
678 LOG(ERROR) << "Unexpected persistent error: " << error.ToString();
679 }
680 // Show error to user.
681 UpdateAuthErrorState(error);
682 }
683 }
684 }
685
686 void ProfileSyncService::OnRefreshTokenAvailable(
687 const std::string& account_id) {
688 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
689 // fixed.
690 tracked_objects::ScopedTracker tracking_profile(
691 FROM_HERE_WITH_EXPLICIT_FUNCTION(
692 "422460 ProfileSyncService::OnRefreshTokenAvailable"));
693
694 if (account_id == signin_->GetAccountIdToUse())
695 OnRefreshTokensLoaded();
696 }
697
698 void ProfileSyncService::OnRefreshTokenRevoked(
699 const std::string& account_id) {
700 if (account_id == signin_->GetAccountIdToUse()) {
701 access_token_.clear();
702 UpdateAuthErrorState(
703 GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
704 }
705 }
706
707 void ProfileSyncService::OnRefreshTokensLoaded() {
708 // This notification gets fired when OAuth2TokenService loads the tokens
709 // from storage.
710 // Initialize the backend if sync is enabled. If the sync token was
711 // not loaded, GetCredentials() will generate invalid credentials to
712 // cause the backend to generate an auth error (crbug.com/121755).
713 if (HasSyncingBackend()) {
714 RequestAccessToken();
715 } else {
716 startup_controller_->TryStart();
717 }
718 }
719
720 void ProfileSyncService::Shutdown() {
721 UnregisterAuthNotifications();
722
723 ShutdownImpl(syncer::BROWSER_SHUTDOWN);
724 if (sync_error_controller_) {
725 // Destroy the SyncErrorController when the service shuts down for good.
726 RemoveObserver(sync_error_controller_.get());
727 sync_error_controller_.reset();
728 }
729
730 if (sync_thread_)
731 sync_thread_->Stop();
732 }
733
734 void ProfileSyncService::ShutdownImpl(syncer::ShutdownReason reason) {
735 if (!backend_) {
736 if (reason == syncer::ShutdownReason::DISABLE_SYNC && sync_thread_) {
737 // If the backend is already shut down when a DISABLE_SYNC happens,
738 // the data directory needs to be cleaned up here.
739 sync_thread_->task_runner()->PostTask(
740 FROM_HERE, base::Bind(&DeleteSyncDataFolder, directory_path_));
741 }
742 return;
743 }
744
745 if (reason == syncer::ShutdownReason::STOP_SYNC
746 || reason == syncer::ShutdownReason::DISABLE_SYNC) {
747 RemoveClientFromServer();
748 }
749
750 // First, we spin down the backend to stop change processing as soon as
751 // possible.
752 base::Time shutdown_start_time = base::Time::Now();
753 backend_->StopSyncingForShutdown();
754
755 // Stop all data type controllers, if needed. Note that until Stop
756 // completes, it is possible in theory to have a ChangeProcessor apply a
757 // change from a native model. In that case, it will get applied to the sync
758 // database (which doesn't get destroyed until we destroy the backend below)
759 // as an unsynced change. That will be persisted, and committed on restart.
760 if (data_type_manager_) {
761 if (data_type_manager_->state() != DataTypeManager::STOPPED) {
762 // When aborting as part of shutdown, we should expect an aborted sync
763 // configure result, else we'll dcheck when we try to read the sync error.
764 expect_sync_configuration_aborted_ = true;
765 data_type_manager_->Stop();
766 }
767 data_type_manager_.reset();
768 }
769
770 // Shutdown the migrator before the backend to ensure it doesn't pull a null
771 // snapshot.
772 migrator_.reset();
773 sync_js_controller_.AttachJsBackend(WeakHandle<syncer::JsBackend>());
774
775 // Move aside the backend so nobody else tries to use it while we are
776 // shutting it down.
777 std::unique_ptr<SyncBackendHost> doomed_backend(backend_.release());
778 if (doomed_backend) {
779 sync_thread_ = doomed_backend->Shutdown(reason);
780 doomed_backend.reset();
781 }
782 base::TimeDelta shutdown_time = base::Time::Now() - shutdown_start_time;
783 UMA_HISTOGRAM_TIMES("Sync.Shutdown.BackendDestroyedTime", shutdown_time);
784
785 sync_enabled_weak_factory_.InvalidateWeakPtrs();
786
787 startup_controller_->Reset(GetRegisteredDataTypes());
788
789 // If the sync DB is getting destroyed, the local DeviceInfo is no longer
790 // valid and should be cleared from the cache.
791 if (reason == syncer::ShutdownReason::DISABLE_SYNC) {
792 local_device_->Clear();
793 }
794
795 // Clear various flags.
796 expect_sync_configuration_aborted_ = false;
797 is_auth_in_progress_ = false;
798 backend_initialized_ = false;
799 cached_passphrase_.clear();
800 encryption_pending_ = false;
801 encrypt_everything_ = false;
802 encrypted_types_ = syncer::SyncEncryptionHandler::SensitiveTypes();
803 passphrase_required_reason_ = syncer::REASON_PASSPHRASE_NOT_REQUIRED;
804 catch_up_configure_in_progress_ = false;
805 access_token_.clear();
806 request_access_token_retry_timer_.Stop();
807 // Revert to "no auth error".
808 if (last_auth_error_.state() != GoogleServiceAuthError::NONE)
809 UpdateAuthErrorState(GoogleServiceAuthError::AuthErrorNone());
810
811 NotifyObservers();
812
813 // Mark this as a clean shutdown(without crash).
814 sync_prefs_.SetCleanShutdown(true);
815 }
816
817 void ProfileSyncService::StopImpl(SyncStopDataFate data_fate) {
818 switch (data_fate) {
819 case KEEP_DATA:
820 // TODO(maxbogue): Investigate whether this logic can/should be moved
821 // into ShutdownImpl or SyncBackendHost itself.
822 if (HasSyncingBackend()) {
823 backend_->UnregisterInvalidationIds();
824 }
825 ShutdownImpl(syncer::STOP_SYNC);
826 break;
827 case CLEAR_DATA:
828 // Clear prefs (including SyncSetupHasCompleted) before shutting down so
829 // PSS clients don't think we're set up while we're shutting down.
830 sync_prefs_.ClearPreferences();
831 ClearUnrecoverableError();
832 ShutdownImpl(syncer::DISABLE_SYNC);
833 break;
834 }
835 }
836
837 bool ProfileSyncService::IsFirstSetupComplete() const {
838 return sync_prefs_.IsFirstSetupComplete();
839 }
840
841 void ProfileSyncService::SetFirstSetupComplete() {
842 sync_prefs_.SetFirstSetupComplete();
843 if (IsBackendInitialized()) {
844 ReconfigureDatatypeManager();
845 }
846 }
847
848 void ProfileSyncService::UpdateLastSyncedTime() {
849 sync_prefs_.SetLastSyncedTime(base::Time::Now());
850 }
851
852 void ProfileSyncService::NotifyObservers() {
853 FOR_EACH_OBSERVER(sync_driver::SyncServiceObserver, observers_,
854 OnStateChanged());
855 }
856
857 void ProfileSyncService::NotifySyncCycleCompleted() {
858 FOR_EACH_OBSERVER(sync_driver::SyncServiceObserver, observers_,
859 OnSyncCycleCompleted());
860 }
861
862 void ProfileSyncService::NotifyForeignSessionUpdated() {
863 FOR_EACH_OBSERVER(sync_driver::SyncServiceObserver, observers_,
864 OnForeignSessionUpdated());
865 }
866
867 void ProfileSyncService::ClearStaleErrors() {
868 ClearUnrecoverableError();
869 last_actionable_error_ = SyncProtocolError();
870 // Clear the data type errors as well.
871 if (data_type_manager_.get())
872 data_type_manager_->ResetDataTypeErrors();
873 }
874
875 void ProfileSyncService::ClearUnrecoverableError() {
876 unrecoverable_error_reason_ = ERROR_REASON_UNSET;
877 unrecoverable_error_message_.clear();
878 unrecoverable_error_location_ = tracked_objects::Location();
879 }
880
881 // An invariant has been violated. Transition to an error state where we try
882 // to do as little work as possible, to avoid further corruption or crashes.
883 void ProfileSyncService::OnUnrecoverableError(
884 const tracked_objects::Location& from_here,
885 const std::string& message) {
886 // Unrecoverable errors that arrive via the syncer::UnrecoverableErrorHandler
887 // interface are assumed to originate within the syncer.
888 unrecoverable_error_reason_ = ERROR_REASON_SYNCER;
889 OnUnrecoverableErrorImpl(from_here, message, true);
890 }
891
892 void ProfileSyncService::OnUnrecoverableErrorImpl(
893 const tracked_objects::Location& from_here,
894 const std::string& message,
895 bool delete_sync_database) {
896 DCHECK(HasUnrecoverableError());
897 unrecoverable_error_message_ = message;
898 unrecoverable_error_location_ = from_here;
899
900 UMA_HISTOGRAM_ENUMERATION(kSyncUnrecoverableErrorHistogram,
901 unrecoverable_error_reason_,
902 ERROR_REASON_LIMIT);
903 std::string location;
904 from_here.Write(true, true, &location);
905 LOG(ERROR)
906 << "Unrecoverable error detected at " << location
907 << " -- ProfileSyncService unusable: " << message;
908
909 // Shut all data types down.
910 base::ThreadTaskRunnerHandle::Get()->PostTask(
911 FROM_HERE, base::Bind(&ProfileSyncService::ShutdownImpl,
912 sync_enabled_weak_factory_.GetWeakPtr(),
913 delete_sync_database ? syncer::DISABLE_SYNC
914 : syncer::STOP_SYNC));
915 }
916
917 void ProfileSyncService::ReenableDatatype(syncer::ModelType type) {
918 if (!backend_initialized_ || !data_type_manager_)
919 return;
920 data_type_manager_->ReenableType(type);
921 }
922
923 void ProfileSyncService::UpdateBackendInitUMA(bool success) {
924 is_first_time_sync_configure_ = !IsFirstSetupComplete();
925
926 if (is_first_time_sync_configure_) {
927 UMA_HISTOGRAM_BOOLEAN("Sync.BackendInitializeFirstTimeSuccess", success);
928 } else {
929 UMA_HISTOGRAM_BOOLEAN("Sync.BackendInitializeRestoreSuccess", success);
930 }
931
932 base::Time on_backend_initialized_time = base::Time::Now();
933 base::TimeDelta delta = on_backend_initialized_time -
934 startup_controller_->start_backend_time();
935 if (is_first_time_sync_configure_) {
936 UMA_HISTOGRAM_LONG_TIMES("Sync.BackendInitializeFirstTime", delta);
937 } else {
938 UMA_HISTOGRAM_LONG_TIMES("Sync.BackendInitializeRestoreTime", delta);
939 }
940 }
941
942 void ProfileSyncService::PostBackendInitialization() {
943 if (protocol_event_observers_.might_have_observers()) {
944 backend_->RequestBufferedProtocolEventsAndEnableForwarding();
945 }
946
947 if (type_debug_info_observers_.might_have_observers()) {
948 backend_->EnableDirectoryTypeDebugInfoForwarding();
949 }
950
951 // If we have a cached passphrase use it to decrypt/encrypt data now that the
952 // backend is initialized. We want to call this before notifying observers in
953 // case this operation affects the "passphrase required" status.
954 ConsumeCachedPassphraseIfPossible();
955
956 // The very first time the backend initializes is effectively the first time
957 // we can say we successfully "synced". LastSyncedTime will only be null in
958 // this case, because the pref wasn't restored on StartUp.
959 if (sync_prefs_.GetLastSyncedTime().is_null()) {
960 UpdateLastSyncedTime();
961 }
962
963 // Auto-start means IsFirstSetupComplete gets set automatically.
964 if (start_behavior_ == AUTO_START && !IsFirstSetupComplete()) {
965 // This will trigger a configure if it completes setup.
966 SetFirstSetupComplete();
967 } else if (CanConfigureDataTypes()) {
968 ConfigureDataTypeManager();
969 }
970
971 // Check for a cookie jar mismatch.
972 std::vector<gaia::ListedAccount> accounts;
973 std::vector<gaia::ListedAccount> signed_out_accounts;
974 GoogleServiceAuthError error(GoogleServiceAuthError::NONE);
975 if (gaia_cookie_manager_service_ &&
976 gaia_cookie_manager_service_->ListAccounts(
977 &accounts, &signed_out_accounts, "ChromiumProfileSyncService")) {
978 OnGaiaAccountsInCookieUpdated(accounts, signed_out_accounts, error);
979 }
980
981 NotifyObservers();
982 }
983
984 void ProfileSyncService::OnBackendInitialized(
985 const syncer::WeakHandle<syncer::JsBackend>& js_backend,
986 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
987 debug_info_listener,
988 const std::string& cache_guid,
989 bool success) {
990 UpdateBackendInitUMA(success);
991
992 if (!success) {
993 // Something went unexpectedly wrong. Play it safe: stop syncing at once
994 // and surface error UI to alert the user sync has stopped.
995 // Keep the directory around for now so that on restart we will retry
996 // again and potentially succeed in presence of transient file IO failures
997 // or permissions issues, etc.
998 //
999 // TODO(rlarocque): Consider making this UnrecoverableError less special.
1000 // Unlike every other UnrecoverableError, it does not delete our sync data.
1001 // This exception made sense at the time it was implemented, but our new
1002 // directory corruption recovery mechanism makes it obsolete. By the time
1003 // we get here, we will have already tried and failed to delete the
1004 // directory. It would be no big deal if we tried to delete it again.
1005 OnInternalUnrecoverableError(FROM_HERE,
1006 "BackendInitialize failure",
1007 false,
1008 ERROR_REASON_BACKEND_INIT_FAILURE);
1009 return;
1010 }
1011
1012 backend_initialized_ = true;
1013
1014 sync_js_controller_.AttachJsBackend(js_backend);
1015 debug_info_listener_ = debug_info_listener;
1016
1017 SigninClient* signin_client = signin_->GetOriginal()->signin_client();
1018 DCHECK(signin_client);
1019 std::string signin_scoped_device_id =
1020 signin_client->GetSigninScopedDeviceId();
1021
1022 // Initialize local device info.
1023 local_device_->Initialize(cache_guid, signin_scoped_device_id,
1024 blocking_pool_);
1025
1026 PostBackendInitialization();
1027 }
1028
1029 void ProfileSyncService::OnSyncCycleCompleted() {
1030 UpdateLastSyncedTime();
1031 const syncer::SyncCycleSnapshot snapshot = GetLastCycleSnapshot();
1032 if (IsDataTypeControllerRunning(syncer::SESSIONS) &&
1033 snapshot.model_neutral_state().get_updates_request_types.Has(
1034 syncer::SESSIONS) &&
1035 !syncer::HasSyncerError(snapshot.model_neutral_state())) {
1036 // Trigger garbage collection of old sessions now that we've downloaded
1037 // any new session data.
1038 base::ThreadTaskRunnerHandle::Get()->PostTask(
1039 FROM_HERE, base::Bind(&SessionsSyncManager::DoGarbageCollection,
1040 base::AsWeakPtr(sessions_sync_manager_.get())));
1041 }
1042 DVLOG(2) << "Notifying observers sync cycle completed";
1043 NotifySyncCycleCompleted();
1044 }
1045
1046 void ProfileSyncService::OnExperimentsChanged(
1047 const syncer::Experiments& experiments) {
1048 if (current_experiments_.Matches(experiments))
1049 return;
1050
1051 current_experiments_ = experiments;
1052
1053 sync_client_->GetPrefService()->SetBoolean(
1054 invalidation::prefs::kInvalidationServiceUseGCMChannel,
1055 experiments.gcm_invalidations_enabled);
1056 }
1057
1058 void ProfileSyncService::UpdateAuthErrorState(const AuthError& error) {
1059 is_auth_in_progress_ = false;
1060 last_auth_error_ = error;
1061
1062 NotifyObservers();
1063 }
1064
1065 namespace {
1066
1067 AuthError ConnectionStatusToAuthError(
1068 syncer::ConnectionStatus status) {
1069 switch (status) {
1070 case syncer::CONNECTION_OK:
1071 return AuthError::AuthErrorNone();
1072 break;
1073 case syncer::CONNECTION_AUTH_ERROR:
1074 return AuthError(AuthError::INVALID_GAIA_CREDENTIALS);
1075 break;
1076 case syncer::CONNECTION_SERVER_ERROR:
1077 return AuthError(AuthError::CONNECTION_FAILED);
1078 break;
1079 default:
1080 NOTREACHED();
1081 return AuthError(AuthError::CONNECTION_FAILED);
1082 }
1083 }
1084
1085 } // namespace
1086
1087 void ProfileSyncService::OnConnectionStatusChange(
1088 syncer::ConnectionStatus status) {
1089 connection_status_update_time_ = base::Time::Now();
1090 connection_status_ = status;
1091 if (status == syncer::CONNECTION_AUTH_ERROR) {
1092 // Sync server returned error indicating that access token is invalid. It
1093 // could be either expired or access is revoked. Let's request another
1094 // access token and if access is revoked then request for token will fail
1095 // with corresponding error. If access token is repeatedly reported
1096 // invalid, there may be some issues with server, e.g. authentication
1097 // state is inconsistent on sync and token server. In that case, we
1098 // backoff token requests exponentially to avoid hammering token server
1099 // too much and to avoid getting same token due to token server's caching
1100 // policy. |request_access_token_retry_timer_| is used to backoff request
1101 // triggered by both auth error and failure talking to GAIA server.
1102 // Therefore, we're likely to reach the backoff ceiling more quickly than
1103 // you would expect from looking at the BackoffPolicy if both types of
1104 // errors happen. We shouldn't receive two errors back-to-back without
1105 // attempting a token/sync request in between, thus crank up request delay
1106 // unnecessary. This is because we won't make a sync request if we hit an
1107 // error until GAIA succeeds at sending a new token, and we won't request
1108 // a new token unless sync reports a token failure. But to be safe, don't
1109 // schedule request if this happens.
1110 if (request_access_token_retry_timer_.IsRunning()) {
1111 // The timer to perform a request later is already running; nothing
1112 // further needs to be done at this point.
1113 } else if (request_access_token_backoff_.failure_count() == 0) {
1114 // First time request without delay. Currently invalid token is used
1115 // to initialize sync backend and we'll always end up here. We don't
1116 // want to delay initialization.
1117 request_access_token_backoff_.InformOfRequest(false);
1118 RequestAccessToken();
1119 } else {
1120 request_access_token_backoff_.InformOfRequest(false);
1121 request_access_token_retry_timer_.Start(
1122 FROM_HERE, request_access_token_backoff_.GetTimeUntilRelease(),
1123 base::Bind(&ProfileSyncService::RequestAccessToken,
1124 sync_enabled_weak_factory_.GetWeakPtr()));
1125 }
1126 } else {
1127 // Reset backoff time after successful connection.
1128 if (status == syncer::CONNECTION_OK) {
1129 // Request shouldn't be scheduled at this time. But if it is, it's
1130 // possible that sync flips between OK and auth error states rapidly,
1131 // thus hammers token server. To be safe, only reset backoff delay when
1132 // no scheduled request.
1133 if (!request_access_token_retry_timer_.IsRunning()) {
1134 request_access_token_backoff_.Reset();
1135 }
1136 }
1137
1138 const GoogleServiceAuthError auth_error =
1139 ConnectionStatusToAuthError(status);
1140 DVLOG(1) << "Connection status change: " << auth_error.ToString();
1141 UpdateAuthErrorState(auth_error);
1142 }
1143 }
1144
1145 void ProfileSyncService::OnPassphraseRequired(
1146 syncer::PassphraseRequiredReason reason,
1147 const sync_pb::EncryptedData& pending_keys) {
1148 DCHECK(backend_.get());
1149 DCHECK(backend_->IsNigoriEnabled());
1150
1151 // TODO(lipalani) : add this check to other locations as well.
1152 if (HasUnrecoverableError()) {
1153 // When unrecoverable error is detected we post a task to shutdown the
1154 // backend. The task might not have executed yet.
1155 return;
1156 }
1157
1158 DVLOG(1) << "Passphrase required with reason: "
1159 << syncer::PassphraseRequiredReasonToString(reason);
1160 passphrase_required_reason_ = reason;
1161
1162 // TODO(stanisc): http://crbug.com/351005: Does this support USS types?
1163 const syncer::ModelTypeSet types = GetPreferredDataTypes();
1164 if (data_type_manager_) {
1165 // Reconfigure without the encrypted types (excluded implicitly via the
1166 // failed datatypes handler).
1167 data_type_manager_->Configure(types, syncer::CONFIGURE_REASON_CRYPTO);
1168 }
1169
1170 // Notify observers that the passphrase status may have changed.
1171 NotifyObservers();
1172 }
1173
1174 void ProfileSyncService::OnPassphraseAccepted() {
1175 DVLOG(1) << "Received OnPassphraseAccepted.";
1176
1177 // If the pending keys were resolved via keystore, it's possible we never
1178 // consumed our cached passphrase. Clear it now.
1179 if (!cached_passphrase_.empty())
1180 cached_passphrase_.clear();
1181
1182 // Reset passphrase_required_reason_ since we know we no longer require the
1183 // passphrase. We do this here rather than down in ResolvePassphraseRequired()
1184 // because that can be called by OnPassphraseRequired() if no encrypted data
1185 // types are enabled, and we don't want to clobber the true passphrase error.
1186 passphrase_required_reason_ = syncer::REASON_PASSPHRASE_NOT_REQUIRED;
1187
1188 // Make sure the data types that depend on the passphrase are started at
1189 // this time.
1190 // TODO(stanisc): http://crbug.com/351005: Does this support USS types?
1191 const syncer::ModelTypeSet types = GetPreferredDataTypes();
1192 if (data_type_manager_) {
1193 // Re-enable any encrypted types if necessary.
1194 data_type_manager_->Configure(types, syncer::CONFIGURE_REASON_CRYPTO);
1195 }
1196
1197 NotifyObservers();
1198 }
1199
1200 void ProfileSyncService::OnEncryptedTypesChanged(
1201 syncer::ModelTypeSet encrypted_types,
1202 bool encrypt_everything) {
1203 encrypted_types_ = encrypted_types;
1204 encrypt_everything_ = encrypt_everything;
1205 DCHECK(encrypt_everything_allowed_ || !encrypt_everything_);
1206 DVLOG(1) << "Encrypted types changed to "
1207 << syncer::ModelTypeSetToString(encrypted_types_)
1208 << " (encrypt everything is set to "
1209 << (encrypt_everything_ ? "true" : "false") << ")";
1210 DCHECK(encrypted_types_.Has(syncer::PASSWORDS));
1211
1212 NotifyObservers();
1213 }
1214
1215 void ProfileSyncService::OnEncryptionComplete() {
1216 DVLOG(1) << "Encryption complete";
1217 if (encryption_pending_ && encrypt_everything_) {
1218 encryption_pending_ = false;
1219 // This is to nudge the integration tests when encryption is
1220 // finished.
1221 NotifyObservers();
1222 }
1223 }
1224
1225 void ProfileSyncService::OnMigrationNeededForTypes(
1226 syncer::ModelTypeSet types) {
1227 DCHECK(backend_initialized_);
1228 DCHECK(data_type_manager_.get());
1229
1230 // Migrator must be valid, because we don't sync until it is created and this
1231 // callback originates from a sync cycle.
1232 migrator_->MigrateTypes(types);
1233 }
1234
1235 void ProfileSyncService::OnActionableError(const SyncProtocolError& error) {
1236 last_actionable_error_ = error;
1237 DCHECK_NE(last_actionable_error_.action,
1238 syncer::UNKNOWN_ACTION);
1239 switch (error.action) {
1240 case syncer::UPGRADE_CLIENT:
1241 case syncer::CLEAR_USER_DATA_AND_RESYNC:
1242 case syncer::ENABLE_SYNC_ON_ACCOUNT:
1243 case syncer::STOP_AND_RESTART_SYNC:
1244 // TODO(lipalani) : if setup in progress we want to display these
1245 // actions in the popup. The current experience might not be optimal for
1246 // the user. We just dismiss the dialog.
1247 if (startup_controller_->IsSetupInProgress()) {
1248 RequestStop(CLEAR_DATA);
1249 expect_sync_configuration_aborted_ = true;
1250 }
1251 // Trigger an unrecoverable error to stop syncing.
1252 OnInternalUnrecoverableError(FROM_HERE,
1253 last_actionable_error_.error_description,
1254 true,
1255 ERROR_REASON_ACTIONABLE_ERROR);
1256 break;
1257 case syncer::DISABLE_SYNC_ON_CLIENT:
1258 if (error.error_type == syncer::NOT_MY_BIRTHDAY) {
1259 UMA_HISTOGRAM_ENUMERATION("Sync.StopSource", syncer::BIRTHDAY_ERROR,
1260 syncer::STOP_SOURCE_LIMIT);
1261 }
1262 RequestStop(CLEAR_DATA);
1263 #if !defined(OS_CHROMEOS)
1264 // On every platform except ChromeOS, sign out the user after a dashboard
1265 // clear.
1266 static_cast<SigninManager*>(signin_->GetOriginal())
1267 ->SignOut(signin_metrics::SERVER_FORCED_DISABLE,
1268 signin_metrics::SignoutDelete::IGNORE_METRIC);
1269 #endif
1270 break;
1271 case syncer::STOP_SYNC_FOR_DISABLED_ACCOUNT:
1272 // Sync disabled by domain admin. we should stop syncing until next
1273 // restart.
1274 sync_disabled_by_admin_ = true;
1275 ShutdownImpl(syncer::DISABLE_SYNC);
1276 break;
1277 case syncer::RESET_LOCAL_SYNC_DATA:
1278 ShutdownImpl(syncer::DISABLE_SYNC);
1279 startup_controller_->TryStart();
1280 break;
1281 default:
1282 NOTREACHED();
1283 }
1284 NotifyObservers();
1285 }
1286
1287 void ProfileSyncService::OnLocalSetPassphraseEncryption(
1288 const syncer::SyncEncryptionHandler::NigoriState& nigori_state) {
1289 DCHECK(thread_checker_.CalledOnValidThread());
1290 if (!base::FeatureList::IsEnabled(
1291 switches::kSyncClearDataOnPassphraseEncryption))
1292 return;
1293
1294 // At this point the user has set a custom passphrase and we have received the
1295 // updated nigori state. Time to cache the nigori state, and catch up the
1296 // active data types.
1297 sync_prefs_.SetSavedNigoriStateForPassphraseEncryptionTransition(
1298 nigori_state);
1299 sync_prefs_.SetPassphraseEncryptionTransitionInProgress(true);
1300 BeginConfigureCatchUpBeforeClear();
1301 }
1302
1303 void ProfileSyncService::BeginConfigureCatchUpBeforeClear() {
1304 DCHECK(data_type_manager_);
1305 DCHECK(!saved_nigori_state_);
1306 saved_nigori_state_ =
1307 sync_prefs_.GetSavedNigoriStateForPassphraseEncryptionTransition();
1308 const syncer::ModelTypeSet types = GetActiveDataTypes();
1309 catch_up_configure_in_progress_ = true;
1310 data_type_manager_->Configure(types, syncer::CONFIGURE_REASON_CATCH_UP);
1311 }
1312
1313 void ProfileSyncService::ClearAndRestartSyncForPassphraseEncryption() {
1314 DCHECK(thread_checker_.CalledOnValidThread());
1315 backend_->ClearServerData(
1316 base::Bind(&ProfileSyncService::OnClearServerDataDone,
1317 sync_enabled_weak_factory_.GetWeakPtr()));
1318 }
1319
1320 void ProfileSyncService::OnClearServerDataDone() {
1321 DCHECK(sync_prefs_.GetPassphraseEncryptionTransitionInProgress());
1322 sync_prefs_.SetPassphraseEncryptionTransitionInProgress(false);
1323
1324 // Call to ClearServerData generates new keystore key on the server. This
1325 // makes keystore bootstrap token invalid. Let's clear it from preferences.
1326 sync_prefs_.SetKeystoreEncryptionBootstrapToken(std::string());
1327
1328 // Shutdown sync, delete the Directory, then restart, restoring the cached
1329 // nigori state.
1330 ShutdownImpl(syncer::DISABLE_SYNC);
1331 startup_controller_->TryStart();
1332 }
1333
1334 void ProfileSyncService::OnConfigureDone(
1335 const DataTypeManager::ConfigureResult& result) {
1336 configure_status_ = result.status;
1337 data_type_status_table_ = result.data_type_status_table;
1338
1339 // We should have cleared our cached passphrase before we get here (in
1340 // OnBackendInitialized()).
1341 DCHECK(cached_passphrase_.empty());
1342
1343 if (!sync_configure_start_time_.is_null()) {
1344 if (result.status == DataTypeManager::OK) {
1345 base::Time sync_configure_stop_time = base::Time::Now();
1346 base::TimeDelta delta = sync_configure_stop_time -
1347 sync_configure_start_time_;
1348 if (is_first_time_sync_configure_) {
1349 UMA_HISTOGRAM_LONG_TIMES("Sync.ServiceInitialConfigureTime", delta);
1350 } else {
1351 UMA_HISTOGRAM_LONG_TIMES("Sync.ServiceSubsequentConfigureTime",
1352 delta);
1353 }
1354 }
1355 sync_configure_start_time_ = base::Time();
1356 }
1357
1358 // Notify listeners that configuration is done.
1359 FOR_EACH_OBSERVER(sync_driver::SyncServiceObserver, observers_,
1360 OnSyncConfigurationCompleted());
1361
1362 DVLOG(1) << "PSS OnConfigureDone called with status: " << configure_status_;
1363 // The possible status values:
1364 // ABORT - Configuration was aborted. This is not an error, if
1365 // initiated by user.
1366 // OK - Some or all types succeeded.
1367 // Everything else is an UnrecoverableError. So treat it as such.
1368
1369 // First handle the abort case.
1370 if (configure_status_ == DataTypeManager::ABORTED &&
1371 expect_sync_configuration_aborted_) {
1372 DVLOG(0) << "ProfileSyncService::Observe Sync Configure aborted";
1373 expect_sync_configuration_aborted_ = false;
1374 return;
1375 }
1376
1377 // Handle unrecoverable error.
1378 if (configure_status_ != DataTypeManager::OK) {
1379 // Something catastrophic had happened. We should only have one
1380 // error representing it.
1381 syncer::SyncError error =
1382 data_type_status_table_.GetUnrecoverableError();
1383 DCHECK(error.IsSet());
1384 std::string message =
1385 "Sync configuration failed with status " +
1386 DataTypeManager::ConfigureStatusToString(configure_status_) +
1387 " caused by " +
1388 syncer::ModelTypeSetToString(
1389 data_type_status_table_.GetUnrecoverableErrorTypes()) +
1390 ": " + error.message();
1391 LOG(ERROR) << "ProfileSyncService error: " << message;
1392 OnInternalUnrecoverableError(error.location(),
1393 message,
1394 true,
1395 ERROR_REASON_CONFIGURATION_FAILURE);
1396 return;
1397 }
1398
1399 DCHECK_EQ(DataTypeManager::OK, configure_status_);
1400
1401 // We should never get in a state where we have no encrypted datatypes
1402 // enabled, and yet we still think we require a passphrase for decryption.
1403 DCHECK(!(IsPassphraseRequiredForDecryption() &&
1404 !IsEncryptedDatatypeEnabled()));
1405
1406 // This must be done before we start syncing with the server to avoid
1407 // sending unencrypted data up on a first time sync.
1408 if (encryption_pending_)
1409 backend_->EnableEncryptEverything();
1410 NotifyObservers();
1411
1412 if (migrator_.get() &&
1413 migrator_->state() != browser_sync::BackendMigrator::IDLE) {
1414 // Migration in progress. Let the migrator know we just finished
1415 // configuring something. It will be up to the migrator to call
1416 // StartSyncingWithServer() if migration is now finished.
1417 migrator_->OnConfigureDone(result);
1418 return;
1419 }
1420
1421 if (catch_up_configure_in_progress_) {
1422 catch_up_configure_in_progress_ = false;
1423 ClearAndRestartSyncForPassphraseEncryption();
1424 return;
1425 }
1426
1427 StartSyncingWithServer();
1428 }
1429
1430 void ProfileSyncService::OnConfigureStart() {
1431 sync_configure_start_time_ = base::Time::Now();
1432 NotifyObservers();
1433 }
1434
1435 ProfileSyncService::SyncStatusSummary
1436 ProfileSyncService::QuerySyncStatusSummary() {
1437 if (HasUnrecoverableError()) {
1438 return UNRECOVERABLE_ERROR;
1439 } else if (!backend_) {
1440 return NOT_ENABLED;
1441 } else if (backend_.get() && !IsFirstSetupComplete()) {
1442 return SETUP_INCOMPLETE;
1443 } else if (backend_ && IsFirstSetupComplete() && data_type_manager_ &&
1444 data_type_manager_->state() == DataTypeManager::STOPPED) {
1445 return DATATYPES_NOT_INITIALIZED;
1446 } else if (IsSyncActive()) {
1447 return INITIALIZED;
1448 }
1449 return UNKNOWN_ERROR;
1450 }
1451
1452 std::string ProfileSyncService::QuerySyncStatusSummaryString() {
1453 SyncStatusSummary status = QuerySyncStatusSummary();
1454
1455 std::string config_status_str =
1456 configure_status_ != DataTypeManager::UNKNOWN ?
1457 DataTypeManager::ConfigureStatusToString(configure_status_) : "";
1458
1459 switch (status) {
1460 case UNRECOVERABLE_ERROR:
1461 return "Unrecoverable error detected";
1462 case NOT_ENABLED:
1463 return "Syncing not enabled";
1464 case SETUP_INCOMPLETE:
1465 return "First time sync setup incomplete";
1466 case DATATYPES_NOT_INITIALIZED:
1467 return "Datatypes not fully initialized";
1468 case INITIALIZED:
1469 return "Sync service initialized";
1470 default:
1471 return "Status unknown: Internal error?";
1472 }
1473 }
1474
1475 std::string ProfileSyncService::GetBackendInitializationStateString() const {
1476 return startup_controller_->GetBackendInitializationStateString();
1477 }
1478
1479 bool ProfileSyncService::IsSetupInProgress() const {
1480 return startup_controller_->IsSetupInProgress();
1481 }
1482
1483 bool ProfileSyncService::QueryDetailedSyncStatus(
1484 SyncBackendHost::Status* result) {
1485 if (backend_.get() && backend_initialized_) {
1486 *result = backend_->GetDetailedStatus();
1487 return true;
1488 } else {
1489 SyncBackendHost::Status status;
1490 status.sync_protocol_error = last_actionable_error_;
1491 *result = status;
1492 return false;
1493 }
1494 }
1495
1496 const AuthError& ProfileSyncService::GetAuthError() const {
1497 return last_auth_error_;
1498 }
1499
1500 bool ProfileSyncService::CanConfigureDataTypes() const {
1501 return IsFirstSetupComplete() && !IsSetupInProgress();
1502 }
1503
1504 bool ProfileSyncService::IsFirstSetupInProgress() const {
1505 return !IsFirstSetupComplete() && startup_controller_->IsSetupInProgress();
1506 }
1507
1508 std::unique_ptr<sync_driver::SyncSetupInProgressHandle>
1509 ProfileSyncService::GetSetupInProgressHandle() {
1510 if (++outstanding_setup_in_progress_handles_ == 1) {
1511 DCHECK(!startup_controller_->IsSetupInProgress());
1512 startup_controller_->SetSetupInProgress(true);
1513
1514 NotifyObservers();
1515 }
1516
1517 return std::unique_ptr<sync_driver::SyncSetupInProgressHandle>(
1518 new sync_driver::SyncSetupInProgressHandle(
1519 base::Bind(&ProfileSyncService::OnSetupInProgressHandleDestroyed,
1520 weak_factory_.GetWeakPtr())));
1521 }
1522
1523 bool ProfileSyncService::IsSyncAllowed() const {
1524 return IsSyncAllowedByFlag() && !IsManaged() && IsSyncAllowedByPlatform();
1525 }
1526
1527 bool ProfileSyncService::IsSyncActive() const {
1528 return backend_initialized_ && data_type_manager_ &&
1529 data_type_manager_->state() != DataTypeManager::STOPPED;
1530 }
1531
1532 void ProfileSyncService::TriggerRefresh(const syncer::ModelTypeSet& types) {
1533 if (backend_initialized_)
1534 backend_->TriggerRefresh(types);
1535 }
1536
1537 bool ProfileSyncService::IsSignedIn() const {
1538 // Sync is logged in if there is a non-empty effective account id.
1539 return !signin_->GetAccountIdToUse().empty();
1540 }
1541
1542 bool ProfileSyncService::CanBackendStart() const {
1543 return CanSyncStart() && oauth2_token_service_ &&
1544 oauth2_token_service_->RefreshTokenIsAvailable(
1545 signin_->GetAccountIdToUse());
1546 }
1547
1548 bool ProfileSyncService::IsBackendInitialized() const {
1549 return backend_initialized_;
1550 }
1551
1552 bool ProfileSyncService::ConfigurationDone() const {
1553 return data_type_manager_ &&
1554 data_type_manager_->state() == DataTypeManager::CONFIGURED;
1555 }
1556
1557 bool ProfileSyncService::waiting_for_auth() const {
1558 return is_auth_in_progress_;
1559 }
1560
1561 const syncer::Experiments& ProfileSyncService::current_experiments() const {
1562 return current_experiments_;
1563 }
1564
1565 bool ProfileSyncService::HasUnrecoverableError() const {
1566 return unrecoverable_error_reason_ != ERROR_REASON_UNSET;
1567 }
1568
1569 bool ProfileSyncService::IsPassphraseRequired() const {
1570 return passphrase_required_reason_ !=
1571 syncer::REASON_PASSPHRASE_NOT_REQUIRED;
1572 }
1573
1574 bool ProfileSyncService::IsPassphraseRequiredForDecryption() const {
1575 // If there is an encrypted datatype enabled and we don't have the proper
1576 // passphrase, we must prompt the user for a passphrase. The only way for the
1577 // user to avoid entering their passphrase is to disable the encrypted types.
1578 return IsEncryptedDatatypeEnabled() && IsPassphraseRequired();
1579 }
1580
1581 base::string16 ProfileSyncService::GetLastSyncedTimeString() const {
1582 const base::Time last_synced_time = sync_prefs_.GetLastSyncedTime();
1583 if (last_synced_time.is_null())
1584 return l10n_util::GetStringUTF16(IDS_SYNC_TIME_NEVER);
1585
1586 base::TimeDelta time_since_last_sync = base::Time::Now() - last_synced_time;
1587
1588 if (time_since_last_sync < base::TimeDelta::FromMinutes(1))
1589 return l10n_util::GetStringUTF16(IDS_SYNC_TIME_JUST_NOW);
1590
1591 return ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_ELAPSED,
1592 ui::TimeFormat::LENGTH_SHORT,
1593 time_since_last_sync);
1594 }
1595
1596 void ProfileSyncService::UpdateSelectedTypesHistogram(
1597 bool sync_everything, const syncer::ModelTypeSet chosen_types) const {
1598 if (!IsFirstSetupComplete() ||
1599 sync_everything != sync_prefs_.HasKeepEverythingSynced()) {
1600 UMA_HISTOGRAM_BOOLEAN("Sync.SyncEverything", sync_everything);
1601 }
1602
1603 // Only log the data types that are shown in the sync settings ui.
1604 // Note: the order of these types must match the ordering of
1605 // the respective types in ModelType
1606 const sync_driver::user_selectable_type::UserSelectableSyncType
1607 user_selectable_types[] = {
1608 sync_driver::user_selectable_type::BOOKMARKS,
1609 sync_driver::user_selectable_type::PREFERENCES,
1610 sync_driver::user_selectable_type::PASSWORDS,
1611 sync_driver::user_selectable_type::AUTOFILL,
1612 sync_driver::user_selectable_type::THEMES,
1613 sync_driver::user_selectable_type::TYPED_URLS,
1614 sync_driver::user_selectable_type::EXTENSIONS,
1615 sync_driver::user_selectable_type::APPS,
1616 sync_driver::user_selectable_type::PROXY_TABS,
1617 };
1618
1619 static_assert(38 == syncer::MODEL_TYPE_COUNT,
1620 "custom config histogram must be updated");
1621
1622 if (!sync_everything) {
1623 const syncer::ModelTypeSet current_types = GetPreferredDataTypes();
1624
1625 syncer::ModelTypeSet type_set = syncer::UserSelectableTypes();
1626 syncer::ModelTypeSet::Iterator it = type_set.First();
1627
1628 DCHECK_EQ(arraysize(user_selectable_types), type_set.Size());
1629
1630 for (size_t i = 0; i < arraysize(user_selectable_types) && it.Good();
1631 ++i, it.Inc()) {
1632 const syncer::ModelType type = it.Get();
1633 if (chosen_types.Has(type) &&
1634 (!IsFirstSetupComplete() || !current_types.Has(type))) {
1635 // Selected type has changed - log it.
1636 UMA_HISTOGRAM_ENUMERATION(
1637 "Sync.CustomSync",
1638 user_selectable_types[i],
1639 sync_driver::user_selectable_type::SELECTABLE_DATATYPE_COUNT + 1);
1640 }
1641 }
1642 }
1643 }
1644
1645 #if defined(OS_CHROMEOS)
1646 void ProfileSyncService::RefreshSpareBootstrapToken(
1647 const std::string& passphrase) {
1648 sync_driver::SystemEncryptor encryptor;
1649 syncer::Cryptographer temp_cryptographer(&encryptor);
1650 // The first 2 params (hostname and username) doesn't have any effect here.
1651 syncer::KeyParams key_params = {"localhost", "dummy", passphrase};
1652
1653 std::string bootstrap_token;
1654 if (!temp_cryptographer.AddKey(key_params)) {
1655 NOTREACHED() << "Failed to add key to cryptographer.";
1656 }
1657 temp_cryptographer.GetBootstrapToken(&bootstrap_token);
1658 sync_prefs_.SetSpareBootstrapToken(bootstrap_token);
1659 }
1660 #endif
1661
1662 void ProfileSyncService::OnUserChoseDatatypes(
1663 bool sync_everything,
1664 syncer::ModelTypeSet chosen_types) {
1665 DCHECK(syncer::UserSelectableTypes().HasAll(chosen_types));
1666
1667 if (!backend_.get() && !HasUnrecoverableError()) {
1668 NOTREACHED();
1669 return;
1670 }
1671
1672 UpdateSelectedTypesHistogram(sync_everything, chosen_types);
1673 sync_prefs_.SetKeepEverythingSynced(sync_everything);
1674
1675 if (data_type_manager_)
1676 data_type_manager_->ResetDataTypeErrors();
1677 ChangePreferredDataTypes(chosen_types);
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 // Will only enable those types that are registered and preferred.
1686 sync_prefs_.SetPreferredDataTypes(registered_types, preferred_types);
1687
1688 // Now reconfigure the DTM.
1689 ReconfigureDatatypeManager();
1690 }
1691
1692 syncer::ModelTypeSet ProfileSyncService::GetActiveDataTypes() const {
1693 if (!IsSyncActive() || !ConfigurationDone())
1694 return syncer::ModelTypeSet();
1695 const syncer::ModelTypeSet preferred_types = GetPreferredDataTypes();
1696 const syncer::ModelTypeSet failed_types =
1697 data_type_status_table_.GetFailedTypes();
1698 return Difference(preferred_types, failed_types);
1699 }
1700
1701 sync_driver::SyncClient* ProfileSyncService::GetSyncClient() const {
1702 return sync_client_.get();
1703 }
1704
1705 syncer::ModelTypeSet ProfileSyncService::GetPreferredDataTypes() const {
1706 const syncer::ModelTypeSet registered_types = GetRegisteredDataTypes();
1707 const syncer::ModelTypeSet preferred_types =
1708 Union(sync_prefs_.GetPreferredDataTypes(registered_types),
1709 syncer::ControlTypes());
1710 const syncer::ModelTypeSet enforced_types =
1711 Intersection(GetDataTypesFromPreferenceProviders(), registered_types);
1712 return Union(preferred_types, enforced_types);
1713 }
1714
1715 syncer::ModelTypeSet ProfileSyncService::GetForcedDataTypes() const {
1716 // TODO(treib,zea): When SyncPrefs also implements SyncTypePreferenceProvider,
1717 // we'll need another way to distinguish user-choosable types from
1718 // programmatically-enabled types.
1719 return GetDataTypesFromPreferenceProviders();
1720 }
1721
1722 syncer::ModelTypeSet ProfileSyncService::GetRegisteredDataTypes() const {
1723 syncer::ModelTypeSet registered_types;
1724 // The data_type_controllers_ are determined by command-line flags;
1725 // that's effectively what controls the values returned here.
1726 for (DataTypeController::TypeMap::const_iterator it =
1727 data_type_controllers_.begin();
1728 it != data_type_controllers_.end(); ++it) {
1729 registered_types.Put(it->first);
1730 }
1731 return registered_types;
1732 }
1733
1734 bool ProfileSyncService::IsUsingSecondaryPassphrase() const {
1735 syncer::PassphraseType passphrase_type = GetPassphraseType();
1736 return passphrase_type ==
1737 syncer::PassphraseType::FROZEN_IMPLICIT_PASSPHRASE ||
1738 passphrase_type == syncer::PassphraseType::CUSTOM_PASSPHRASE;
1739 }
1740
1741 std::string ProfileSyncService::GetCustomPassphraseKey() const {
1742 sync_driver::SystemEncryptor encryptor;
1743 syncer::Cryptographer cryptographer(&encryptor);
1744 cryptographer.Bootstrap(sync_prefs_.GetEncryptionBootstrapToken());
1745 return cryptographer.GetDefaultNigoriKeyData();
1746 }
1747
1748 syncer::PassphraseType ProfileSyncService::GetPassphraseType() const {
1749 return backend_->GetPassphraseType();
1750 }
1751
1752 base::Time ProfileSyncService::GetExplicitPassphraseTime() const {
1753 return backend_->GetExplicitPassphraseTime();
1754 }
1755
1756 bool ProfileSyncService::IsCryptographerReady(
1757 const syncer::BaseTransaction* trans) const {
1758 return backend_.get() && backend_->IsCryptographerReady(trans);
1759 }
1760
1761 void ProfileSyncService::SetPlatformSyncAllowedProvider(
1762 const PlatformSyncAllowedProvider& platform_sync_allowed_provider) {
1763 platform_sync_allowed_provider_ = platform_sync_allowed_provider;
1764 }
1765
1766 void ProfileSyncService::ConfigureDataTypeManager() {
1767 // Don't configure datatypes if the setup UI is still on the screen - this
1768 // is to help multi-screen setting UIs (like iOS) where they don't want to
1769 // start syncing data until the user is done configuring encryption options,
1770 // etc. ReconfigureDatatypeManager() will get called again once the UI calls
1771 // SetSetupInProgress(false).
1772 if (!CanConfigureDataTypes()) {
1773 // If we can't configure the data type manager yet, we should still notify
1774 // observers. This is to support multiple setup UIs being open at once.
1775 NotifyObservers();
1776 return;
1777 }
1778
1779 bool restart = false;
1780 if (!data_type_manager_) {
1781 restart = true;
1782 data_type_manager_.reset(
1783 sync_client_->GetSyncApiComponentFactory()->CreateDataTypeManager(
1784 debug_info_listener_, &data_type_controllers_, this, backend_.get(),
1785 this));
1786
1787 // We create the migrator at the same time.
1788 migrator_.reset(new browser_sync::BackendMigrator(
1789 debug_identifier_, GetUserShare(), this, data_type_manager_.get(),
1790 base::Bind(&ProfileSyncService::StartSyncingWithServer,
1791 base::Unretained(this))));
1792 }
1793
1794 syncer::ModelTypeSet types;
1795 syncer::ConfigureReason reason = syncer::CONFIGURE_REASON_UNKNOWN;
1796 types = GetPreferredDataTypes();
1797 if (restart) {
1798 // Datatype downloads on restart are generally due to newly supported
1799 // datatypes (although it's also possible we're picking up where a failed
1800 // previous configuration left off).
1801 // TODO(sync): consider detecting configuration recovery and setting
1802 // the reason here appropriately.
1803 reason = syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE;
1804 } else {
1805 // The user initiated a reconfiguration (either to add or remove types).
1806 reason = syncer::CONFIGURE_REASON_RECONFIGURATION;
1807 }
1808
1809 data_type_manager_->Configure(types, reason);
1810 }
1811
1812 syncer::UserShare* ProfileSyncService::GetUserShare() const {
1813 if (backend_.get() && backend_initialized_) {
1814 return backend_->GetUserShare();
1815 }
1816 NOTREACHED();
1817 return NULL;
1818 }
1819
1820 syncer::SyncCycleSnapshot ProfileSyncService::GetLastCycleSnapshot() const {
1821 if (backend_)
1822 return backend_->GetLastCycleSnapshot();
1823 return syncer::SyncCycleSnapshot();
1824 }
1825
1826 bool ProfileSyncService::HasUnsyncedItems() const {
1827 if (HasSyncingBackend() && backend_initialized_) {
1828 return backend_->HasUnsyncedItems();
1829 }
1830 NOTREACHED();
1831 return false;
1832 }
1833
1834 browser_sync::BackendMigrator*
1835 ProfileSyncService::GetBackendMigratorForTest() {
1836 return migrator_.get();
1837 }
1838
1839 void ProfileSyncService::GetModelSafeRoutingInfo(
1840 syncer::ModelSafeRoutingInfo* out) const {
1841 if (backend_.get() && backend_initialized_) {
1842 backend_->GetModelSafeRoutingInfo(out);
1843 } else {
1844 NOTREACHED();
1845 }
1846 }
1847
1848 base::Value* ProfileSyncService::GetTypeStatusMap() const {
1849 std::unique_ptr<base::ListValue> result(new base::ListValue());
1850
1851 if (!backend_.get() || !backend_initialized_) {
1852 return result.release();
1853 }
1854
1855 DataTypeStatusTable::TypeErrorMap error_map =
1856 data_type_status_table_.GetAllErrors();
1857 ModelTypeSet active_types;
1858 ModelTypeSet passive_types;
1859 ModelSafeRoutingInfo routing_info;
1860 backend_->GetModelSafeRoutingInfo(&routing_info);
1861 for (ModelSafeRoutingInfo::const_iterator it = routing_info.begin();
1862 it != routing_info.end(); ++it) {
1863 if (it->second == syncer::GROUP_PASSIVE) {
1864 passive_types.Put(it->first);
1865 } else {
1866 active_types.Put(it->first);
1867 }
1868 }
1869
1870 SyncBackendHost::Status detailed_status = backend_->GetDetailedStatus();
1871 ModelTypeSet& throttled_types(detailed_status.throttled_types);
1872 ModelTypeSet registered = GetRegisteredDataTypes();
1873 std::unique_ptr<base::DictionaryValue> type_status_header(
1874 new base::DictionaryValue());
1875
1876 type_status_header->SetString("name", "Model Type");
1877 type_status_header->SetString("status", "header");
1878 type_status_header->SetString("value", "Group Type");
1879 type_status_header->SetString("num_entries", "Total Entries");
1880 type_status_header->SetString("num_live", "Live Entries");
1881 result->Append(std::move(type_status_header));
1882
1883 std::unique_ptr<base::DictionaryValue> type_status;
1884 for (ModelTypeSet::Iterator it = registered.First(); it.Good(); it.Inc()) {
1885 ModelType type = it.Get();
1886
1887 type_status.reset(new base::DictionaryValue());
1888 type_status->SetString("name", ModelTypeToString(type));
1889
1890 if (error_map.find(type) != error_map.end()) {
1891 const syncer::SyncError &error = error_map.find(type)->second;
1892 DCHECK(error.IsSet());
1893 switch (error.GetSeverity()) {
1894 case syncer::SyncError::SYNC_ERROR_SEVERITY_ERROR: {
1895 std::string error_text = "Error: " + error.location().ToString() +
1896 ", " + error.GetMessagePrefix() + error.message();
1897 type_status->SetString("status", "error");
1898 type_status->SetString("value", error_text);
1899 }
1900 break;
1901 case syncer::SyncError::SYNC_ERROR_SEVERITY_INFO:
1902 type_status->SetString("status", "disabled");
1903 type_status->SetString("value", error.message());
1904 break;
1905 default:
1906 NOTREACHED() << "Unexpected error severity.";
1907 break;
1908 }
1909 } else if (syncer::IsProxyType(type) && passive_types.Has(type)) {
1910 // Show a proxy type in "ok" state unless it is disabled by user.
1911 DCHECK(!throttled_types.Has(type));
1912 type_status->SetString("status", "ok");
1913 type_status->SetString("value", "Passive");
1914 } else if (throttled_types.Has(type) && passive_types.Has(type)) {
1915 type_status->SetString("status", "warning");
1916 type_status->SetString("value", "Passive, Throttled");
1917 } else if (passive_types.Has(type)) {
1918 type_status->SetString("status", "warning");
1919 type_status->SetString("value", "Passive");
1920 } else if (throttled_types.Has(type)) {
1921 type_status->SetString("status", "warning");
1922 type_status->SetString("value", "Throttled");
1923 } else if (active_types.Has(type)) {
1924 type_status->SetString("status", "ok");
1925 type_status->SetString("value", "Active: " +
1926 ModelSafeGroupToString(routing_info[type]));
1927 } else {
1928 type_status->SetString("status", "warning");
1929 type_status->SetString("value", "Disabled by User");
1930 }
1931
1932 int live_count = detailed_status.num_entries_by_type[type] -
1933 detailed_status.num_to_delete_entries_by_type[type];
1934 type_status->SetInteger("num_entries",
1935 detailed_status.num_entries_by_type[type]);
1936 type_status->SetInteger("num_live", live_count);
1937
1938 result->Append(std::move(type_status));
1939 }
1940 return result.release();
1941 }
1942
1943 void ProfileSyncService::ConsumeCachedPassphraseIfPossible() {
1944 // If no cached passphrase, or sync backend hasn't started up yet, just exit.
1945 // If the backend isn't running yet, OnBackendInitialized() will call this
1946 // method again after the backend starts up.
1947 if (cached_passphrase_.empty() || !IsBackendInitialized())
1948 return;
1949
1950 // Backend is up and running, so we can consume the cached passphrase.
1951 std::string passphrase = cached_passphrase_;
1952 cached_passphrase_.clear();
1953
1954 // If we need a passphrase to decrypt data, try the cached passphrase.
1955 if (passphrase_required_reason() == syncer::REASON_DECRYPTION) {
1956 if (SetDecryptionPassphrase(passphrase)) {
1957 DVLOG(1) << "Cached passphrase successfully decrypted pending keys";
1958 return;
1959 }
1960 }
1961
1962 // If we get here, we don't have pending keys (or at least, the passphrase
1963 // doesn't decrypt them) - just try to re-encrypt using the encryption
1964 // passphrase.
1965 if (!IsUsingSecondaryPassphrase())
1966 SetEncryptionPassphrase(passphrase, IMPLICIT);
1967 }
1968
1969 void ProfileSyncService::RequestAccessToken() {
1970 // Only one active request at a time.
1971 if (access_token_request_ != NULL)
1972 return;
1973 request_access_token_retry_timer_.Stop();
1974 OAuth2TokenService::ScopeSet oauth2_scopes;
1975 oauth2_scopes.insert(signin_->GetSyncScopeToUse());
1976
1977 // Invalidate previous token, otherwise token service will return the same
1978 // token again.
1979 const std::string& account_id = signin_->GetAccountIdToUse();
1980 if (!access_token_.empty()) {
1981 oauth2_token_service_->InvalidateAccessToken(account_id, oauth2_scopes,
1982 access_token_);
1983 }
1984
1985 access_token_.clear();
1986
1987 token_request_time_ = base::Time::Now();
1988 token_receive_time_ = base::Time();
1989 next_token_request_time_ = base::Time();
1990 access_token_request_ =
1991 oauth2_token_service_->StartRequest(account_id, oauth2_scopes, this);
1992 }
1993
1994 void ProfileSyncService::SetEncryptionPassphrase(const std::string& passphrase,
1995 PassphraseType type) {
1996 // This should only be called when the backend has been initialized.
1997 DCHECK(IsBackendInitialized());
1998 DCHECK(!(type == IMPLICIT && IsUsingSecondaryPassphrase())) <<
1999 "Data is already encrypted using an explicit passphrase";
2000 DCHECK(!(type == EXPLICIT &&
2001 passphrase_required_reason_ == syncer::REASON_DECRYPTION)) <<
2002 "Can not set explicit passphrase when decryption is needed.";
2003
2004 DVLOG(1) << "Setting " << (type == EXPLICIT ? "explicit" : "implicit")
2005 << " passphrase for encryption.";
2006 if (passphrase_required_reason_ == syncer::REASON_ENCRYPTION) {
2007 // REASON_ENCRYPTION implies that the cryptographer does not have pending
2008 // keys. Hence, as long as we're not trying to do an invalid passphrase
2009 // change (e.g. explicit -> explicit or explicit -> implicit), we know this
2010 // will succeed. If for some reason a new encryption key arrives via
2011 // sync later, the SBH will trigger another OnPassphraseRequired().
2012 passphrase_required_reason_ = syncer::REASON_PASSPHRASE_NOT_REQUIRED;
2013 NotifyObservers();
2014 }
2015 backend_->SetEncryptionPassphrase(passphrase, type == EXPLICIT);
2016 }
2017
2018 bool ProfileSyncService::SetDecryptionPassphrase(
2019 const std::string& passphrase) {
2020 if (IsPassphraseRequired()) {
2021 DVLOG(1) << "Setting passphrase for decryption.";
2022 bool result = backend_->SetDecryptionPassphrase(passphrase);
2023 UMA_HISTOGRAM_BOOLEAN("Sync.PassphraseDecryptionSucceeded", result);
2024 return result;
2025 } else {
2026 NOTREACHED() << "SetDecryptionPassphrase must not be called when "
2027 "IsPassphraseRequired() is false.";
2028 return false;
2029 }
2030 }
2031
2032 bool ProfileSyncService::IsEncryptEverythingAllowed() const {
2033 return encrypt_everything_allowed_;
2034 }
2035
2036 void ProfileSyncService::SetEncryptEverythingAllowed(bool allowed) {
2037 DCHECK(allowed || !IsBackendInitialized() || !IsEncryptEverythingEnabled());
2038 encrypt_everything_allowed_ = allowed;
2039 }
2040
2041 void ProfileSyncService::EnableEncryptEverything() {
2042 DCHECK(IsEncryptEverythingAllowed());
2043
2044 // Tests override IsBackendInitialized() to always return true, so we
2045 // must check that instead of |backend_initialized_|.
2046 // TODO(akalin): Fix the above. :/
2047 DCHECK(IsBackendInitialized());
2048 // TODO(atwilson): Persist the encryption_pending_ flag to address the various
2049 // problems around cancelling encryption in the background (crbug.com/119649).
2050 if (!encrypt_everything_)
2051 encryption_pending_ = true;
2052 }
2053
2054 bool ProfileSyncService::encryption_pending() const {
2055 // We may be called during the setup process before we're
2056 // initialized (via IsEncryptedDatatypeEnabled and
2057 // IsPassphraseRequiredForDecryption).
2058 return encryption_pending_;
2059 }
2060
2061 bool ProfileSyncService::IsEncryptEverythingEnabled() const {
2062 DCHECK(backend_initialized_);
2063 return encrypt_everything_ || encryption_pending_;
2064 }
2065
2066 syncer::ModelTypeSet ProfileSyncService::GetEncryptedDataTypes() const {
2067 DCHECK(encrypted_types_.Has(syncer::PASSWORDS));
2068 // We may be called during the setup process before we're
2069 // initialized. In this case, we default to the sensitive types.
2070 return encrypted_types_;
2071 }
2072
2073 void ProfileSyncService::OnSyncManagedPrefChange(bool is_sync_managed) {
2074 if (is_sync_managed) {
2075 StopImpl(CLEAR_DATA);
2076 } else {
2077 // Sync is no longer disabled by policy. Try starting it up if appropriate.
2078 startup_controller_->TryStart();
2079 }
2080 }
2081
2082 void ProfileSyncService::GoogleSigninSucceeded(const std::string& account_id,
2083 const std::string& username,
2084 const std::string& password) {
2085 if (IsSyncRequested() && !password.empty()) {
2086 cached_passphrase_ = password;
2087 // Try to consume the passphrase we just cached. If the sync backend
2088 // is not running yet, the passphrase will remain cached until the
2089 // backend starts up.
2090 ConsumeCachedPassphraseIfPossible();
2091 }
2092 #if defined(OS_CHROMEOS)
2093 RefreshSpareBootstrapToken(password);
2094 #endif
2095 if (!IsBackendInitialized() || GetAuthError().state() != AuthError::NONE) {
2096 // Track the fact that we're still waiting for auth to complete.
2097 is_auth_in_progress_ = true;
2098 }
2099 }
2100
2101 void ProfileSyncService::GoogleSignedOut(const std::string& account_id,
2102 const std::string& username) {
2103 sync_disabled_by_admin_ = false;
2104 UMA_HISTOGRAM_ENUMERATION("Sync.StopSource", syncer::SIGN_OUT,
2105 syncer::STOP_SOURCE_LIMIT);
2106 RequestStop(CLEAR_DATA);
2107 }
2108
2109 void ProfileSyncService::OnGaiaAccountsInCookieUpdated(
2110 const std::vector<gaia::ListedAccount>& accounts,
2111 const std::vector<gaia::ListedAccount>& signed_out_accounts,
2112 const GoogleServiceAuthError& error) {
2113 if (!IsBackendInitialized())
2114 return;
2115
2116 bool cookie_jar_mismatch = true;
2117 bool cookie_jar_empty = accounts.size() == 0;
2118 std::string account_id = signin_->GetAccountIdToUse();
2119
2120 // Iterate through list of accounts, looking for current sync account.
2121 for (const auto& account : accounts) {
2122 if (account.id == account_id) {
2123 cookie_jar_mismatch = false;
2124 break;
2125 }
2126 }
2127
2128 DVLOG(1) << "Cookie jar mismatch: " << cookie_jar_mismatch;
2129 DVLOG(1) << "Cookie jar empty: " << cookie_jar_empty;
2130 backend_->OnCookieJarChanged(cookie_jar_mismatch, cookie_jar_empty);
2131 }
2132
2133 void ProfileSyncService::AddObserver(
2134 sync_driver::SyncServiceObserver* observer) {
2135 observers_.AddObserver(observer);
2136 }
2137
2138 void ProfileSyncService::RemoveObserver(
2139 sync_driver::SyncServiceObserver* observer) {
2140 observers_.RemoveObserver(observer);
2141 }
2142
2143 void ProfileSyncService::AddProtocolEventObserver(
2144 browser_sync::ProtocolEventObserver* observer) {
2145 protocol_event_observers_.AddObserver(observer);
2146 if (HasSyncingBackend()) {
2147 backend_->RequestBufferedProtocolEventsAndEnableForwarding();
2148 }
2149 }
2150
2151 void ProfileSyncService::RemoveProtocolEventObserver(
2152 browser_sync::ProtocolEventObserver* observer) {
2153 protocol_event_observers_.RemoveObserver(observer);
2154 if (HasSyncingBackend() &&
2155 !protocol_event_observers_.might_have_observers()) {
2156 backend_->DisableProtocolEventForwarding();
2157 }
2158 }
2159
2160 void ProfileSyncService::AddTypeDebugInfoObserver(
2161 syncer::TypeDebugInfoObserver* type_debug_info_observer) {
2162 type_debug_info_observers_.AddObserver(type_debug_info_observer);
2163 if (type_debug_info_observers_.might_have_observers() &&
2164 backend_initialized_) {
2165 backend_->EnableDirectoryTypeDebugInfoForwarding();
2166 }
2167 }
2168
2169 void ProfileSyncService::RemoveTypeDebugInfoObserver(
2170 syncer::TypeDebugInfoObserver* type_debug_info_observer) {
2171 type_debug_info_observers_.RemoveObserver(type_debug_info_observer);
2172 if (!type_debug_info_observers_.might_have_observers() &&
2173 backend_initialized_) {
2174 backend_->DisableDirectoryTypeDebugInfoForwarding();
2175 }
2176 }
2177
2178 void ProfileSyncService::AddPreferenceProvider(
2179 SyncTypePreferenceProvider* provider) {
2180 DCHECK(!HasPreferenceProvider(provider))
2181 << "Providers may only be added once!";
2182 preference_providers_.insert(provider);
2183 }
2184
2185 void ProfileSyncService::RemovePreferenceProvider(
2186 SyncTypePreferenceProvider* provider) {
2187 DCHECK(HasPreferenceProvider(provider))
2188 << "Only providers that have been added before can be removed!";
2189 preference_providers_.erase(provider);
2190 }
2191
2192 bool ProfileSyncService::HasPreferenceProvider(
2193 SyncTypePreferenceProvider* provider) const {
2194 return preference_providers_.count(provider) > 0;
2195 }
2196
2197 namespace {
2198
2199 class GetAllNodesRequestHelper
2200 : public base::RefCountedThreadSafe<GetAllNodesRequestHelper> {
2201 public:
2202 GetAllNodesRequestHelper(
2203 syncer::ModelTypeSet requested_types,
2204 const base::Callback<void(std::unique_ptr<base::ListValue>)>& callback);
2205
2206 void OnReceivedNodesForType(const syncer::ModelType type,
2207 std::unique_ptr<base::ListValue> node_list);
2208
2209 private:
2210 friend class base::RefCountedThreadSafe<GetAllNodesRequestHelper>;
2211 virtual ~GetAllNodesRequestHelper();
2212
2213 std::unique_ptr<base::ListValue> result_accumulator_;
2214
2215 syncer::ModelTypeSet awaiting_types_;
2216 base::Callback<void(std::unique_ptr<base::ListValue>)> callback_;
2217 };
2218
2219 GetAllNodesRequestHelper::GetAllNodesRequestHelper(
2220 syncer::ModelTypeSet requested_types,
2221 const base::Callback<void(std::unique_ptr<base::ListValue>)>& callback)
2222 : result_accumulator_(new base::ListValue()),
2223 awaiting_types_(requested_types),
2224 callback_(callback) {}
2225
2226 GetAllNodesRequestHelper::~GetAllNodesRequestHelper() {
2227 if (!awaiting_types_.Empty()) {
2228 DLOG(WARNING)
2229 << "GetAllNodesRequest deleted before request was fulfilled. "
2230 << "Missing types are: " << ModelTypeSetToString(awaiting_types_);
2231 }
2232 }
2233
2234 // Called when the set of nodes for a type has been returned.
2235 // Only return one type of nodes each time.
2236 void GetAllNodesRequestHelper::OnReceivedNodesForType(
2237 const syncer::ModelType type,
2238 std::unique_ptr<base::ListValue> node_list) {
2239 // Add these results to our list.
2240 std::unique_ptr<base::DictionaryValue> type_dict(new base::DictionaryValue());
2241 type_dict->SetString("type", ModelTypeToString(type));
2242 type_dict->Set("nodes", std::move(node_list));
2243 result_accumulator_->Append(std::move(type_dict));
2244
2245 // Remember that this part of the request is satisfied.
2246 awaiting_types_.Remove(type);
2247
2248 if (awaiting_types_.Empty()) {
2249 callback_.Run(std::move(result_accumulator_));
2250 callback_.Reset();
2251 }
2252 }
2253
2254 } // namespace
2255
2256 void ProfileSyncService::GetAllNodes(
2257 const base::Callback<void(std::unique_ptr<base::ListValue>)>& callback) {
2258 // TODO(stanisc): crbug.com/328606: Make this work for USS datatypes.
2259 ModelTypeSet all_types = GetActiveDataTypes();
2260 all_types.PutAll(syncer::ControlTypes());
2261 scoped_refptr<GetAllNodesRequestHelper> helper =
2262 new GetAllNodesRequestHelper(all_types, callback);
2263
2264 if (!backend_initialized_) {
2265 // If there's no backend available to fulfill the request, handle it here.
2266 for (ModelTypeSet::Iterator it = all_types.First(); it.Good(); it.Inc()) {
2267 helper->OnReceivedNodesForType(it.Get(),
2268 base::MakeUnique<base::ListValue>());
2269 }
2270 return;
2271 }
2272
2273 for (ModelTypeSet::Iterator it = all_types.First(); it.Good(); it.Inc()) {
2274 const auto& dtc_iter = data_type_controllers_.find(it.Get());
2275 if (dtc_iter != data_type_controllers_.end()) {
2276 dtc_iter->second->GetAllNodes(base::Bind(
2277 &GetAllNodesRequestHelper::OnReceivedNodesForType, helper));
2278 } else {
2279 // Control Types
2280 helper->OnReceivedNodesForType(
2281 it.Get(), sync_driver::DirectoryDataTypeController::
2282 GetAllNodesForTypeFromDirectory(
2283 it.Get(), GetUserShare()->directory.get()));
2284 }
2285 }
2286 }
2287
2288 bool ProfileSyncService::HasObserver(
2289 const sync_driver::SyncServiceObserver* observer) const {
2290 return observers_.HasObserver(observer);
2291 }
2292
2293 base::WeakPtr<syncer::JsController> ProfileSyncService::GetJsController() {
2294 return sync_js_controller_.AsWeakPtr();
2295 }
2296
2297 void ProfileSyncService::SyncEvent(SyncEventCodes code) {
2298 UMA_HISTOGRAM_ENUMERATION("Sync.EventCodes", code, MAX_SYNC_EVENT_CODE);
2299 }
2300
2301 // static
2302 bool ProfileSyncService::IsSyncAllowedByFlag() {
2303 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
2304 switches::kDisableSync);
2305 }
2306
2307 bool ProfileSyncService::IsSyncAllowedByPlatform() const {
2308 return platform_sync_allowed_provider_.is_null() ||
2309 platform_sync_allowed_provider_.Run();
2310 }
2311
2312 bool ProfileSyncService::IsManaged() const {
2313 return sync_prefs_.IsManaged() || sync_disabled_by_admin_;
2314 }
2315
2316 void ProfileSyncService::RequestStop(SyncStopDataFate data_fate) {
2317 sync_prefs_.SetSyncRequested(false);
2318 StopImpl(data_fate);
2319 }
2320
2321 bool ProfileSyncService::IsSyncRequested() const {
2322 return sync_prefs_.IsSyncRequested();
2323 }
2324
2325 SigninManagerBase* ProfileSyncService::signin() const {
2326 if (!signin_)
2327 return NULL;
2328 return signin_->GetOriginal();
2329 }
2330
2331 void ProfileSyncService::RequestStart() {
2332 if (!IsSyncAllowed()) {
2333 // Sync cannot be requested if it's not allowed.
2334 return;
2335 }
2336 DCHECK(sync_client_);
2337 if (!IsSyncRequested()) {
2338 sync_prefs_.SetSyncRequested(true);
2339 NotifyObservers();
2340 }
2341 startup_controller_->TryStartImmediately();
2342 }
2343
2344 void ProfileSyncService::ReconfigureDatatypeManager() {
2345 // If we haven't initialized yet, don't configure the DTM as it could cause
2346 // association to start before a Directory has even been created.
2347 if (backend_initialized_) {
2348 DCHECK(backend_.get());
2349 ConfigureDataTypeManager();
2350 } else if (HasUnrecoverableError()) {
2351 // There is nothing more to configure. So inform the listeners,
2352 NotifyObservers();
2353
2354 DVLOG(1) << "ConfigureDataTypeManager not invoked because of an "
2355 << "Unrecoverable error.";
2356 } else {
2357 DVLOG(0) << "ConfigureDataTypeManager not invoked because backend is not "
2358 << "initialized";
2359 }
2360 }
2361
2362 syncer::ModelTypeSet ProfileSyncService::GetDataTypesFromPreferenceProviders()
2363 const {
2364 syncer::ModelTypeSet types;
2365 for (std::set<SyncTypePreferenceProvider*>::const_iterator it =
2366 preference_providers_.begin();
2367 it != preference_providers_.end();
2368 ++it) {
2369 types.PutAll((*it)->GetPreferredDataTypes());
2370 }
2371 return types;
2372 }
2373
2374 const DataTypeStatusTable& ProfileSyncService::data_type_status_table()
2375 const {
2376 return data_type_status_table_;
2377 }
2378
2379 void ProfileSyncService::OnInternalUnrecoverableError(
2380 const tracked_objects::Location& from_here,
2381 const std::string& message,
2382 bool delete_sync_database,
2383 UnrecoverableErrorReason reason) {
2384 DCHECK(!HasUnrecoverableError());
2385 unrecoverable_error_reason_ = reason;
2386 OnUnrecoverableErrorImpl(from_here, message, delete_sync_database);
2387 }
2388
2389 bool ProfileSyncService::IsRetryingAccessTokenFetchForTest() const {
2390 return request_access_token_retry_timer_.IsRunning();
2391 }
2392
2393 std::string ProfileSyncService::GetAccessTokenForTest() const {
2394 return access_token_;
2395 }
2396
2397 WeakHandle<syncer::JsEventHandler> ProfileSyncService::GetJsEventHandler() {
2398 return MakeWeakHandle(sync_js_controller_.AsWeakPtr());
2399 }
2400
2401 syncer::SyncableService* ProfileSyncService::GetSessionsSyncableService() {
2402 return sessions_sync_manager_.get();
2403 }
2404
2405 syncer::SyncableService* ProfileSyncService::GetDeviceInfoSyncableService() {
2406 return device_info_sync_service_.get();
2407 }
2408
2409 syncer_v2::ModelTypeService* ProfileSyncService::GetDeviceInfoService() {
2410 return device_info_service_.get();
2411 }
2412
2413 sync_driver::SyncService::SyncTokenStatus
2414 ProfileSyncService::GetSyncTokenStatus() const {
2415 SyncTokenStatus status;
2416 status.connection_status_update_time = connection_status_update_time_;
2417 status.connection_status = connection_status_;
2418 status.token_request_time = token_request_time_;
2419 status.token_receive_time = token_receive_time_;
2420 status.last_get_token_error = last_get_token_error_;
2421 if (request_access_token_retry_timer_.IsRunning())
2422 status.next_token_request_time = next_token_request_time_;
2423 return status;
2424 }
2425
2426 void ProfileSyncService::OverrideNetworkResourcesForTest(
2427 std::unique_ptr<syncer::NetworkResources> network_resources) {
2428 network_resources_ = std::move(network_resources);
2429 }
2430
2431 bool ProfileSyncService::HasSyncingBackend() const {
2432 return backend_ != NULL;
2433 }
2434
2435 void ProfileSyncService::UpdateFirstSyncTimePref() {
2436 if (!IsSignedIn()) {
2437 sync_prefs_.ClearFirstSyncTime();
2438 } else if (sync_prefs_.GetFirstSyncTime().is_null()) {
2439 // Set if not set before and it's syncing now.
2440 sync_prefs_.SetFirstSyncTime(base::Time::Now());
2441 }
2442 }
2443
2444 void ProfileSyncService::FlushDirectory() const {
2445 // backend_initialized_ implies backend_ isn't NULL and the manager exists.
2446 // If sync is not initialized yet, we fail silently.
2447 if (backend_initialized_)
2448 backend_->FlushDirectory();
2449 }
2450
2451 base::FilePath ProfileSyncService::GetDirectoryPathForTest() const {
2452 return directory_path_;
2453 }
2454
2455 base::MessageLoop* ProfileSyncService::GetSyncLoopForTest() const {
2456 if (sync_thread_) {
2457 return sync_thread_->message_loop();
2458 } else if (backend_) {
2459 return backend_->GetSyncLoopForTesting();
2460 } else {
2461 return NULL;
2462 }
2463 }
2464
2465 void ProfileSyncService::RefreshTypesForTest(syncer::ModelTypeSet types) {
2466 if (backend_initialized_)
2467 backend_->RefreshTypesForTest(types);
2468 }
2469
2470 void ProfileSyncService::RemoveClientFromServer() const {
2471 if (!backend_initialized_) return;
2472 const std::string cache_guid = local_device_->GetLocalSyncCacheGUID();
2473 std::string birthday;
2474 syncer::UserShare* user_share = GetUserShare();
2475 if (user_share && user_share->directory.get()) {
2476 birthday = user_share->directory->store_birthday();
2477 }
2478 if (!access_token_.empty() && !cache_guid.empty() && !birthday.empty()) {
2479 sync_stopped_reporter_->ReportSyncStopped(
2480 access_token_, cache_guid, birthday);
2481 }
2482 }
2483
2484 void ProfileSyncService::OnMemoryPressure(
2485 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
2486 if (memory_pressure_level ==
2487 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
2488 sync_prefs_.SetMemoryPressureWarningCount(
2489 sync_prefs_.GetMemoryPressureWarningCount() + 1);
2490 }
2491 }
2492
2493 void ProfileSyncService::ReportPreviousSessionMemoryWarningCount() {
2494 int warning_received = sync_prefs_.GetMemoryPressureWarningCount();
2495
2496 if (-1 != warning_received) {
2497 // -1 means it is new client.
2498 if (!sync_prefs_.DidSyncShutdownCleanly()) {
2499 UMA_HISTOGRAM_COUNTS("Sync.MemoryPressureWarningBeforeUncleanShutdown",
2500 warning_received);
2501 } else {
2502 UMA_HISTOGRAM_COUNTS("Sync.MemoryPressureWarningBeforeCleanShutdown",
2503 warning_received);
2504 }
2505 }
2506 sync_prefs_.SetMemoryPressureWarningCount(0);
2507 // Will set to true during a clean shutdown, so crash or something else will
2508 // remain this as false.
2509 sync_prefs_.SetCleanShutdown(false);
2510 }
2511
2512 const GURL& ProfileSyncService::sync_service_url() const {
2513 return sync_service_url_;
2514 }
2515
2516 std::string ProfileSyncService::unrecoverable_error_message() const {
2517 return unrecoverable_error_message_;
2518 }
2519
2520 tracked_objects::Location ProfileSyncService::unrecoverable_error_location()
2521 const {
2522 return unrecoverable_error_location_;
2523 }
2524
2525 void ProfileSyncService::OnSetupInProgressHandleDestroyed() {
2526 DCHECK_GT(outstanding_setup_in_progress_handles_, 0);
2527
2528 // Don't re-start Sync until all outstanding handles are destroyed.
2529 if (--outstanding_setup_in_progress_handles_ != 0)
2530 return;
2531
2532 DCHECK(startup_controller_->IsSetupInProgress());
2533 startup_controller_->SetSetupInProgress(false);
2534
2535 if (IsBackendInitialized())
2536 ReconfigureDatatypeManager();
2537 NotifyObservers();
2538 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698