1 // Copyright 2013 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.
5 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
14 #include "base/base64.h"
15 #include "base/bind.h"
16 #include "base/command_line.h"
17 #include "base/compiler_specific.h"
18 #include "base/json/json_writer.h"
19 #include "base/location.h"
20 #include "base/logging.h"
21 #include "base/message_loop/message_loop.h"
22 #include "base/prefs/pref_service.h"
23 #include "base/strings/stringprintf.h"
24 #include "base/timer/timer.h"
25 #include "chrome/browser/chrome_notification_types.h"
26 #include "chrome/browser/invalidation/p2p_invalidation_service.h"
27 #include "chrome/browser/profiles/profile.h"
28 #include "chrome/browser/signin/profile_oauth2_token_service.h"
29 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
30 #include "chrome/browser/signin/signin_manager_base.h"
31 #include "chrome/browser/sync/about_sync_util.h"
32 #include "chrome/browser/sync/backend_migrator.h"
33 #include "chrome/browser/sync/profile_sync_service_factory.h"
34 #include "chrome/browser/sync/test/integration/status_change_checker.h"
35 #include "chrome/common/chrome_switches.h"
36 #include "chrome/common/pref_names.h"
37 #include "components/sync_driver/data_type_controller.h"
38 #include "content/public/browser/notification_service.h"
39 #include "google_apis/gaia/gaia_constants.h"
40 #include "sync/internal_api/public/base/progress_marker_map.h"
41 #include "sync/internal_api/public/sessions/sync_session_snapshot.h"
42 #include "sync/internal_api/public/util/sync_string_conversions.h"
44 #if defined(ENABLE_MANAGED_USERS)
45 #include "chrome/browser/managed_mode/managed_user_constants.h"
48 using syncer::sessions::SyncSessionSnapshot;
49 using invalidation::P2PInvalidationService;
51 // The amount of time for which we wait for a sync operation to complete.
52 // TODO(sync): This timeout must eventually be made less than the default 45
53 // second timeout for integration tests so that in case a sync operation times
54 // out, it is able to log a useful failure message before the test is killed.
55 static const int kSyncOperationTimeoutMs = 45000;
59 // Checks if a desired change in the state of the sync engine has taken place by
60 // running the callback passed to it.
61 class CallbackStatusChecker : public StatusChangeChecker {
63 CallbackStatusChecker(base::Callback<bool()> callback,
64 const std::string& source)
65 : StatusChangeChecker(source),
69 virtual ~CallbackStatusChecker() {
72 virtual bool IsExitConditionSatisfied() OVERRIDE {
73 return callback_.Run();
77 // Callback that evaluates whether the condition we are waiting on has been
79 base::Callback<bool()> callback_;
81 DISALLOW_COPY_AND_ASSIGN(CallbackStatusChecker);
84 // Helper function which returns true if the sync backend has been initialized,
85 // or if backend initialization was blocked for some reason.
86 bool DoneWaitingForBackendInitialization(
87 const ProfileSyncServiceHarness* harness) {
89 // Backend is initialized.
90 if (harness->service()->sync_initialized())
92 // Backend initialization is blocked by an auth error.
93 if (harness->HasAuthError())
95 // Backend initialization is blocked by a failure to fetch Oauth2 tokens.
96 if (harness->service()->IsRetryingAccessTokenFetchForTest())
98 // Still waiting on backend initialization.
102 // Helper function which returns true if sync setup is complete, or in case
103 // it is blocked for some reason.
104 bool DoneWaitingForSyncSetup(const ProfileSyncServiceHarness* harness) {
106 // Sync setup is complete, and the client is ready to sync new changes.
107 if (harness->ServiceIsPushingChanges())
109 // Sync is blocked because a custom passphrase is required.
110 if (harness->service()->passphrase_required_reason() ==
111 syncer::REASON_DECRYPTION) {
114 // Sync is blocked by an auth error.
115 if (harness->HasAuthError())
117 // Still waiting on sync setup.
121 // Helper function which returns true if the sync client requires a custom
122 // passphrase to be entered for decryption.
123 bool IsPassphraseRequired(const ProfileSyncServiceHarness* harness) {
125 return harness->service()->IsPassphraseRequired();
128 // Helper function which returns true if the custom passphrase entered was
130 bool IsPassphraseAccepted(const ProfileSyncServiceHarness* harness) {
132 return (!harness->service()->IsPassphraseRequired() &&
133 harness->service()->IsUsingSecondaryPassphrase());
139 ProfileSyncServiceHarness* ProfileSyncServiceHarness::Create(
141 const std::string& username,
142 const std::string& password) {
143 return new ProfileSyncServiceHarness(profile, username, password, NULL);
147 ProfileSyncServiceHarness* ProfileSyncServiceHarness::CreateForIntegrationTest(
149 const std::string& username,
150 const std::string& password,
151 P2PInvalidationService* p2p_invalidation_service) {
152 return new ProfileSyncServiceHarness(profile,
155 p2p_invalidation_service);
158 ProfileSyncServiceHarness::ProfileSyncServiceHarness(
160 const std::string& username,
161 const std::string& password,
162 P2PInvalidationService* p2p_invalidation_service)
164 service_(ProfileSyncServiceFactory::GetForProfile(profile)),
165 p2p_invalidation_service_(p2p_invalidation_service),
166 progress_marker_partner_(NULL),
169 oauth2_refesh_token_number_(0),
170 profile_debug_name_(profile->GetDebugName()),
171 status_change_checker_(NULL) {
174 ProfileSyncServiceHarness::~ProfileSyncServiceHarness() {
175 if (service()->HasObserver(this))
176 service()->RemoveObserver(this);
179 void ProfileSyncServiceHarness::SetCredentials(const std::string& username,
180 const std::string& password) {
181 username_ = username;
182 password_ = password;
185 bool ProfileSyncServiceHarness::SetupSync() {
186 bool result = SetupSync(syncer::ModelTypeSet::All());
187 if (result == false) {
188 std::string status = GetServiceStatus();
189 LOG(ERROR) << profile_debug_name_
190 << ": SetupSync failed. Syncer status:\n" << status;
192 DVLOG(1) << profile_debug_name_ << ": SetupSync successful.";
197 bool ProfileSyncServiceHarness::SetupSync(
198 syncer::ModelTypeSet synced_datatypes) {
199 // Initialize the sync client's profile sync service object.
200 if (service() == NULL) {
201 LOG(ERROR) << "SetupSync(): service() is null.";
205 // Subscribe sync client to notifications from the profile sync service.
206 if (!service()->HasObserver(this))
207 service()->AddObserver(this);
209 // Tell the sync service that setup is in progress so we don't start syncing
210 // until we've finished configuration.
211 service()->SetSetupInProgress(true);
213 // Authenticate sync client using GAIA credentials.
214 service()->signin()->SetAuthenticatedUsername(username_);
215 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
217 GoogleServiceSigninSuccessDetails details(username_, password_);
218 content::NotificationService::current()->Notify(
219 chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
220 content::Source<Profile>(profile_),
221 content::Details<const GoogleServiceSigninSuccessDetails>(&details));
223 #if defined(ENABLE_MANAGED_USERS)
224 std::string account_id = profile_->IsManaged() ?
225 managed_users::kManagedUserPseudoEmail : username_;
227 std::string account_id = username_;
229 DCHECK(!account_id.empty());
230 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)->
231 UpdateCredentials(account_id, GenerateFakeOAuth2RefreshTokenString());
233 // Wait for the OnBackendInitialized() callback.
234 if (!AwaitBackendInitialized()) {
235 LOG(ERROR) << "OnBackendInitialized() not seen after "
236 << kSyncOperationTimeoutMs / 1000
241 // Make sure that initial sync wasn't blocked by a missing passphrase.
242 if (service()->passphrase_required_reason() == syncer::REASON_DECRYPTION) {
243 LOG(ERROR) << "A passphrase is required for decryption. Sync cannot proceed"
244 " until SetDecryptionPassphrase is called.";
248 // Make sure that initial sync wasn't blocked by rejected credentials.
249 if (HasAuthError()) {
250 LOG(ERROR) << "Credentials were rejected. Sync cannot proceed.";
254 // Choose the datatypes to be synced. If all datatypes are to be synced,
255 // set sync_everything to true; otherwise, set it to false.
256 bool sync_everything =
257 synced_datatypes.Equals(syncer::ModelTypeSet::All());
258 service()->OnUserChoseDatatypes(sync_everything, synced_datatypes);
260 // Notify ProfileSyncService that we are done with configuration.
263 // Set an implicit passphrase for encryption if an explicit one hasn't already
264 // been set. If an explicit passphrase has been set, immediately return false,
265 // since a decryption passphrase is required.
266 if (!service()->IsUsingSecondaryPassphrase()) {
267 service()->SetEncryptionPassphrase(password_, ProfileSyncService::IMPLICIT);
269 LOG(ERROR) << "A passphrase is required for decryption. Sync cannot proceed"
270 " until SetDecryptionPassphrase is called.";
274 // Wait for initial sync cycle to be completed.
275 DCHECK(service()->sync_initialized());
276 if (!AwaitSyncSetupCompletion()) {
277 LOG(ERROR) << "Initial sync cycle did not complete after "
278 << kSyncOperationTimeoutMs / 1000
283 // Make sure that initial sync wasn't blocked by a missing passphrase.
284 if (service()->passphrase_required_reason() == syncer::REASON_DECRYPTION) {
285 LOG(ERROR) << "A passphrase is required for decryption. Sync cannot proceed"
286 " until SetDecryptionPassphrase is called.";
290 // Make sure that initial sync wasn't blocked by rejected credentials.
291 if (service()->GetAuthError().state() ==
292 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS) {
293 LOG(ERROR) << "Credentials were rejected. Sync cannot proceed.";
300 void ProfileSyncServiceHarness::QuitMessageLoop() {
301 base::MessageLoop::current()->QuitWhenIdle();
304 void ProfileSyncServiceHarness::OnStateChanged() {
305 if (!status_change_checker_)
308 DVLOG(1) << GetClientInfoString(status_change_checker_->source());
309 if (status_change_checker_->IsExitConditionSatisfied())
313 void ProfileSyncServiceHarness::OnSyncCycleCompleted() {
314 // Integration tests still use p2p notifications.
315 const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
316 bool is_notifiable_commit =
317 (snap.model_neutral_state().num_successful_commits > 0);
318 if (is_notifiable_commit && p2p_invalidation_service_) {
319 syncer::ModelTypeSet model_types =
320 snap.model_neutral_state().commit_request_types;
321 syncer::ObjectIdSet ids = ModelTypeSetToObjectIdSet(model_types);
322 p2p_invalidation_service_->SendInvalidation(ids);
327 bool ProfileSyncServiceHarness::AwaitPassphraseRequired() {
328 DVLOG(1) << GetClientInfoString("AwaitPassphraseRequired");
329 CallbackStatusChecker passphrase_required_checker(
330 base::Bind(&::IsPassphraseRequired, base::Unretained(this)),
331 "IsPassphraseRequired");
332 return AwaitStatusChange(&passphrase_required_checker,
333 "AwaitPassphraseRequired");
336 bool ProfileSyncServiceHarness::AwaitPassphraseAccepted() {
337 CallbackStatusChecker passphrase_accepted_checker(
338 base::Bind(&::IsPassphraseAccepted, base::Unretained(this)),
339 "IsPassphraseAccepted");
340 bool return_value = AwaitStatusChange(&passphrase_accepted_checker,
341 "AwaitPassphraseAccepted");
347 bool ProfileSyncServiceHarness::AwaitBackendInitialized() {
348 DVLOG(1) << GetClientInfoString("AwaitBackendInitialized");
349 CallbackStatusChecker backend_initialized_checker(
350 base::Bind(&DoneWaitingForBackendInitialization,
351 base::Unretained(this)),
352 "DoneWaitingForBackendInitialization");
353 AwaitStatusChange(&backend_initialized_checker, "AwaitBackendInitialized");
354 return service()->sync_initialized();
357 // TODO(sync): As of today, we wait for a client to finish its commit activity
358 // by checking if its progress markers are up to date. In future, once we have
359 // an in-process C++ server, this function can be reimplemented without relying
360 // on progress markers.
361 bool ProfileSyncServiceHarness::AwaitCommitActivityCompletion() {
362 DVLOG(1) << GetClientInfoString("AwaitCommitActivityCompletion");
363 CallbackStatusChecker latest_progress_markers_checker(
364 base::Bind(&ProfileSyncServiceHarness::HasLatestProgressMarkers,
365 base::Unretained(this)),
366 "HasLatestProgressMarkers");
367 AwaitStatusChange(&latest_progress_markers_checker,
368 "AwaitCommitActivityCompletion");
369 return HasLatestProgressMarkers();
372 bool ProfileSyncServiceHarness::AwaitSyncDisabled() {
373 DCHECK(service()->HasSyncSetupCompleted());
374 DCHECK(!IsSyncDisabled());
375 CallbackStatusChecker sync_disabled_checker(
376 base::Bind(&ProfileSyncServiceHarness::IsSyncDisabled,
377 base::Unretained(this)),
379 return AwaitStatusChange(&sync_disabled_checker, "AwaitSyncDisabled");
382 bool ProfileSyncServiceHarness::AwaitSyncSetupCompletion() {
383 CallbackStatusChecker sync_setup_complete_checker(
384 base::Bind(&DoneWaitingForSyncSetup, base::Unretained(this)),
385 "DoneWaitingForSyncSetup");
386 return AwaitStatusChange(&sync_setup_complete_checker,
387 "AwaitSyncSetupCompletion");
390 bool ProfileSyncServiceHarness::AwaitMutualSyncCycleCompletion(
391 ProfileSyncServiceHarness* partner) {
392 DVLOG(1) << GetClientInfoString("AwaitMutualSyncCycleCompletion");
393 if (!AwaitCommitActivityCompletion())
395 return partner->WaitUntilProgressMarkersMatch(this);
398 bool ProfileSyncServiceHarness::AwaitGroupSyncCycleCompletion(
399 std::vector<ProfileSyncServiceHarness*>& partners) {
400 DVLOG(1) << GetClientInfoString("AwaitGroupSyncCycleCompletion");
401 if (!AwaitCommitActivityCompletion())
403 bool return_value = true;
404 for (std::vector<ProfileSyncServiceHarness*>::iterator it =
405 partners.begin(); it != partners.end(); ++it) {
406 if ((this != *it) && (!(*it)->IsSyncDisabled())) {
407 return_value = return_value &&
408 (*it)->WaitUntilProgressMarkersMatch(this);
415 bool ProfileSyncServiceHarness::AwaitQuiescence(
416 std::vector<ProfileSyncServiceHarness*>& clients) {
417 DVLOG(1) << "AwaitQuiescence.";
418 bool return_value = true;
419 for (std::vector<ProfileSyncServiceHarness*>::iterator it =
420 clients.begin(); it != clients.end(); ++it) {
421 if (!(*it)->IsSyncDisabled()) {
422 return_value = return_value &&
423 (*it)->AwaitGroupSyncCycleCompletion(clients);
429 bool ProfileSyncServiceHarness::WaitUntilProgressMarkersMatch(
430 ProfileSyncServiceHarness* partner) {
431 DVLOG(1) << GetClientInfoString("WaitUntilProgressMarkersMatch");
433 // TODO(rsimha): Replace the mechanism of matching up progress markers with
434 // one that doesn't require every client to have the same progress markers.
435 DCHECK(!progress_marker_partner_);
436 progress_marker_partner_ = partner;
437 bool return_value = false;
438 if (MatchesPartnerClient()) {
439 // Progress markers already match; don't wait.
442 partner->service()->AddObserver(this);
443 CallbackStatusChecker matches_other_client_checker(
444 base::Bind(&ProfileSyncServiceHarness::MatchesPartnerClient,
445 base::Unretained(this)),
446 "MatchesPartnerClient");
447 return_value = AwaitStatusChange(&matches_other_client_checker,
448 "WaitUntilProgressMarkersMatch");
449 partner->service()->RemoveObserver(this);
451 progress_marker_partner_ = NULL;
455 bool ProfileSyncServiceHarness::AwaitStatusChange(
456 StatusChangeChecker* checker, const std::string& source) {
457 DVLOG(1) << GetClientInfoString("AwaitStatusChange");
459 if (IsSyncDisabled()) {
460 LOG(ERROR) << "Sync disabled for " << profile_debug_name_ << ".";
465 if (checker->IsExitConditionSatisfied()) {
466 DVLOG(1) << GetClientInfoString("AwaitStatusChange exiting early because "
467 "condition is already satisfied");
471 DCHECK(status_change_checker_ == NULL);
472 status_change_checker_ = checker;
474 base::OneShotTimer<ProfileSyncServiceHarness> timer;
475 timer.Start(FROM_HERE,
476 base::TimeDelta::FromMilliseconds(kSyncOperationTimeoutMs),
477 base::Bind(&ProfileSyncServiceHarness::QuitMessageLoop,
478 base::Unretained(this)));
480 base::MessageLoop* loop = base::MessageLoop::current();
481 base::MessageLoop::ScopedNestableTaskAllower allow(loop);
485 status_change_checker_ = NULL;
487 if (timer.IsRunning()) {
488 DVLOG(1) << GetClientInfoString("AwaitStatusChange succeeded");
491 LOG(ERROR) << GetClientInfoString(base::StringPrintf(
492 "AwaitStatusChange called from %s timed out", source.c_str()));
493 CHECK(false) << "Ending test because of timeout.";
498 std::string ProfileSyncServiceHarness::GenerateFakeOAuth2RefreshTokenString() {
499 return base::StringPrintf("oauth2_refresh_token_%d",
500 ++oauth2_refesh_token_number_);
503 ProfileSyncService::Status ProfileSyncServiceHarness::GetStatus() const {
504 DCHECK(service() != NULL) << "GetStatus(): service() is NULL.";
505 ProfileSyncService::Status result;
506 service()->QueryDetailedSyncStatus(&result);
510 bool ProfileSyncServiceHarness::IsSyncDisabled() const {
511 return !service()->setup_in_progress() &&
512 !service()->HasSyncSetupCompleted();
515 bool ProfileSyncServiceHarness::HasAuthError() const {
516 return service()->GetAuthError().state() ==
517 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS ||
518 service()->GetAuthError().state() ==
519 GoogleServiceAuthError::SERVICE_ERROR ||
520 service()->GetAuthError().state() ==
521 GoogleServiceAuthError::REQUEST_CANCELED;
524 // TODO(sync): Remove this method once we stop relying on self notifications and
525 // comparing progress markers.
526 bool ProfileSyncServiceHarness::HasLatestProgressMarkers() const {
527 const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
528 return snap.model_neutral_state().num_successful_commits == 0 &&
529 !service()->HasUnsyncedItems();
532 void ProfileSyncServiceHarness::FinishSyncSetup() {
533 service()->SetSetupInProgress(false);
534 service()->SetSyncSetupCompleted();
537 bool ProfileSyncServiceHarness::AutoStartEnabled() {
538 return service()->auto_start_enabled();
541 bool ProfileSyncServiceHarness::MatchesPartnerClient() const {
542 DCHECK(progress_marker_partner_);
544 // Only look for a match if we have at least one enabled datatype in
545 // common with the partner client.
546 const syncer::ModelTypeSet common_types =
547 Intersection(service()->GetActiveDataTypes(),
548 progress_marker_partner_->service()->GetActiveDataTypes());
550 DVLOG(2) << profile_debug_name_ << ", "
551 << progress_marker_partner_->profile_debug_name_
552 << ": common types are "
553 << syncer::ModelTypeSetToString(common_types);
555 for (syncer::ModelTypeSet::Iterator i = common_types.First();
557 const std::string marker = GetSerializedProgressMarker(i.Get());
558 const std::string partner_marker =
559 progress_marker_partner_->GetSerializedProgressMarker(i.Get());
560 if (marker != partner_marker) {
562 std::string marker_base64, partner_marker_base64;
563 base::Base64Encode(marker, &marker_base64);
564 base::Base64Encode(partner_marker, &partner_marker_base64);
565 DVLOG(2) << syncer::ModelTypeToString(i.Get()) << ": "
566 << profile_debug_name_ << " progress marker = "
567 << marker_base64 << ", "
568 << progress_marker_partner_->profile_debug_name_
569 << " partner progress marker = "
570 << partner_marker_base64;
578 SyncSessionSnapshot ProfileSyncServiceHarness::GetLastSessionSnapshot() const {
579 DCHECK(service() != NULL) << "Sync service has not yet been set up.";
580 if (service()->sync_initialized()) {
581 return service()->GetLastSessionSnapshot();
583 return SyncSessionSnapshot();
586 bool ProfileSyncServiceHarness::EnableSyncForDatatype(
587 syncer::ModelType datatype) {
588 DVLOG(1) << GetClientInfoString(
589 "EnableSyncForDatatype("
590 + std::string(syncer::ModelTypeToString(datatype)) + ")");
592 if (IsSyncDisabled())
593 return SetupSync(syncer::ModelTypeSet(datatype));
595 if (service() == NULL) {
596 LOG(ERROR) << "EnableSyncForDatatype(): service() is null.";
600 syncer::ModelTypeSet synced_datatypes = service()->GetPreferredDataTypes();
601 if (synced_datatypes.Has(datatype)) {
602 DVLOG(1) << "EnableSyncForDatatype(): Sync already enabled for datatype "
603 << syncer::ModelTypeToString(datatype)
604 << " on " << profile_debug_name_ << ".";
608 synced_datatypes.Put(syncer::ModelTypeFromInt(datatype));
609 service()->OnUserChoseDatatypes(false, synced_datatypes);
610 if (AwaitSyncSetupCompletion()) {
611 DVLOG(1) << "EnableSyncForDatatype(): Enabled sync for datatype "
612 << syncer::ModelTypeToString(datatype)
613 << " on " << profile_debug_name_ << ".";
617 DVLOG(0) << GetClientInfoString("EnableSyncForDatatype failed");
621 bool ProfileSyncServiceHarness::DisableSyncForDatatype(
622 syncer::ModelType datatype) {
623 DVLOG(1) << GetClientInfoString(
624 "DisableSyncForDatatype("
625 + std::string(syncer::ModelTypeToString(datatype)) + ")");
627 if (service() == NULL) {
628 LOG(ERROR) << "DisableSyncForDatatype(): service() is null.";
632 syncer::ModelTypeSet synced_datatypes = service()->GetPreferredDataTypes();
633 if (!synced_datatypes.Has(datatype)) {
634 DVLOG(1) << "DisableSyncForDatatype(): Sync already disabled for datatype "
635 << syncer::ModelTypeToString(datatype)
636 << " on " << profile_debug_name_ << ".";
640 synced_datatypes.RetainAll(syncer::UserSelectableTypes());
641 synced_datatypes.Remove(datatype);
642 service()->OnUserChoseDatatypes(false, synced_datatypes);
643 if (AwaitSyncSetupCompletion()) {
644 DVLOG(1) << "DisableSyncForDatatype(): Disabled sync for datatype "
645 << syncer::ModelTypeToString(datatype)
646 << " on " << profile_debug_name_ << ".";
650 DVLOG(0) << GetClientInfoString("DisableSyncForDatatype failed");
654 bool ProfileSyncServiceHarness::EnableSyncForAllDatatypes() {
655 DVLOG(1) << GetClientInfoString("EnableSyncForAllDatatypes");
657 if (IsSyncDisabled())
660 if (service() == NULL) {
661 LOG(ERROR) << "EnableSyncForAllDatatypes(): service() is null.";
665 service()->OnUserChoseDatatypes(true, syncer::ModelTypeSet::All());
666 if (AwaitSyncSetupCompletion()) {
667 DVLOG(1) << "EnableSyncForAllDatatypes(): Enabled sync for all datatypes "
668 << "on " << profile_debug_name_ << ".";
672 DVLOG(0) << GetClientInfoString("EnableSyncForAllDatatypes failed");
676 bool ProfileSyncServiceHarness::DisableSyncForAllDatatypes() {
677 DVLOG(1) << GetClientInfoString("DisableSyncForAllDatatypes");
679 if (service() == NULL) {
680 LOG(ERROR) << "DisableSyncForAllDatatypes(): service() is null.";
684 service()->DisableForUser();
686 DVLOG(1) << "DisableSyncForAllDatatypes(): Disabled sync for all "
687 << "datatypes on " << profile_debug_name_;
691 std::string ProfileSyncServiceHarness::GetSerializedProgressMarker(
692 syncer::ModelType model_type) const {
693 const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
694 const syncer::ProgressMarkerMap& markers_map =
695 snap.download_progress_markers();
697 syncer::ProgressMarkerMap::const_iterator it =
698 markers_map.find(model_type);
699 return (it != markers_map.end()) ? it->second : std::string();
702 // TODO(sync): Clean up this method in a separate CL. Remove all snapshot fields
703 // and log shorter, more meaningful messages.
704 std::string ProfileSyncServiceHarness::GetClientInfoString(
705 const std::string& message) const {
706 std::stringstream os;
707 os << profile_debug_name_ << ": " << message << ": ";
709 const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
710 const ProfileSyncService::Status& status = GetStatus();
711 // Capture select info from the sync session snapshot and syncer status.
712 os << ", has_unsynced_items: "
713 << (service()->sync_initialized() ? service()->HasUnsyncedItems() : 0)
715 << (snap.model_neutral_state().num_successful_commits == 0 &&
716 snap.model_neutral_state().commit_result == syncer::SYNCER_OK)
717 << ", encryption conflicts: "
718 << snap.num_encryption_conflicts()
719 << ", hierarchy conflicts: "
720 << snap.num_hierarchy_conflicts()
721 << ", server conflicts: "
722 << snap.num_server_conflicts()
723 << ", num_updates_downloaded : "
724 << snap.model_neutral_state().num_updates_downloaded_total
725 << ", passphrase_required_reason: "
726 << syncer::PassphraseRequiredReasonToString(
727 service()->passphrase_required_reason())
728 << ", notifications_enabled: "
729 << status.notifications_enabled
730 << ", service_is_pushing_changes: "
731 << ServiceIsPushingChanges();
733 os << "Sync service not available";
738 bool ProfileSyncServiceHarness::EnableEncryption() {
739 if (IsEncryptionComplete())
741 service()->EnableEncryptEverything();
743 // In order to kick off the encryption we have to reconfigure. Just grab the
744 // currently synced types and use them.
745 const syncer::ModelTypeSet synced_datatypes =
746 service()->GetPreferredDataTypes();
747 bool sync_everything =
748 synced_datatypes.Equals(syncer::ModelTypeSet::All());
749 service()->OnUserChoseDatatypes(sync_everything, synced_datatypes);
751 // Wait some time to let the enryption finish.
752 return WaitForEncryption();
755 bool ProfileSyncServiceHarness::WaitForEncryption() {
756 if (IsEncryptionComplete()) {
757 // Encryption is already complete; do not wait.
761 CallbackStatusChecker encryption_complete_checker(
762 base::Bind(&ProfileSyncServiceHarness::IsEncryptionComplete,
763 base::Unretained(this)),
764 "IsEncryptionComplete");
765 return AwaitStatusChange(&encryption_complete_checker, "WaitForEncryption");
768 bool ProfileSyncServiceHarness::IsEncryptionComplete() const {
769 bool is_encryption_complete = service()->EncryptEverythingEnabled() &&
770 !service()->encryption_pending();
771 DVLOG(2) << "Encryption is "
772 << (is_encryption_complete ? "" : "not ")
773 << "complete; Encrypted types = "
774 << syncer::ModelTypeSetToString(service()->GetEncryptedDataTypes());
775 return is_encryption_complete;
778 bool ProfileSyncServiceHarness::IsTypeRunning(syncer::ModelType type) {
779 browser_sync::DataTypeController::StateMap state_map;
780 service()->GetDataTypeControllerStates(&state_map);
781 return (state_map.count(type) != 0 &&
782 state_map[type] == browser_sync::DataTypeController::RUNNING);
785 bool ProfileSyncServiceHarness::IsTypePreferred(syncer::ModelType type) {
786 return service()->GetPreferredDataTypes().Has(type);
789 size_t ProfileSyncServiceHarness::GetNumEntries() const {
790 return GetLastSessionSnapshot().num_entries();
793 size_t ProfileSyncServiceHarness::GetNumDatatypes() const {
794 browser_sync::DataTypeController::StateMap state_map;
795 service()->GetDataTypeControllerStates(&state_map);
796 return state_map.size();
799 std::string ProfileSyncServiceHarness::GetServiceStatus() {
800 scoped_ptr<base::DictionaryValue> value(
801 sync_ui_util::ConstructAboutInformation(service()));
802 std::string service_status;
803 base::JSONWriter::WriteWithOptions(value.get(),
804 base::JSONWriter::OPTIONS_PRETTY_PRINT,
806 return service_status;