diff options
author | haitaol@chromium.org <haitaol@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-05 21:16:28 +0000 |
---|---|---|
committer | haitaol@chromium.org <haitaol@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-05 21:16:28 +0000 |
commit | ff08e5c278d265f7a1f407e9aa4c09201d009af5 (patch) | |
tree | e76f7313cfd1f01581ff91fa3e157e69edca6bdc | |
parent | 6e7737988af7c5217d8b66877aae39221b80d198 (diff) | |
download | chromium_src-ff08e5c278d265f7a1f407e9aa4c09201d009af5.zip chromium_src-ff08e5c278d265f7a1f407e9aa4c09201d009af5.tar.gz chromium_src-ff08e5c278d265f7a1f407e9aa4c09201d009af5.tar.bz2 |
Record first sync time and clear browsing data since first sync time during
rollback.
BUG=362679
Review URL: https://codereview.chromium.org/316563003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@275243 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/sync/profile_sync_service.cc | 53 | ||||
-rw-r--r-- | chrome/browser/sync/profile_sync_service.h | 11 | ||||
-rw-r--r-- | chrome/browser/sync/profile_sync_service_unittest.cc | 101 | ||||
-rw-r--r-- | components/sync_driver/pref_names.cc | 3 | ||||
-rw-r--r-- | components/sync_driver/pref_names.h | 1 | ||||
-rw-r--r-- | components/sync_driver/sync_prefs.cc | 17 | ||||
-rw-r--r-- | components/sync_driver/sync_prefs.h | 6 |
7 files changed, 188 insertions, 4 deletions
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc index c60ec46..b4ce8b1 100644 --- a/chrome/browser/sync/profile_sync_service.cc +++ b/chrome/browser/sync/profile_sync_service.cc @@ -25,6 +25,8 @@ #include "build/build_config.h" #include "chrome/browser/bookmarks/enhanced_bookmarks_features.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/browsing_data/browsing_data_helper.h" +#include "chrome/browser/browsing_data/browsing_data_remover.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/defaults.h" #include "chrome/browser/invalidation/invalidation_service_factory.h" @@ -160,6 +162,18 @@ static const base::FilePath::CharType kSyncBackupDataFolderName[] = // Default delay in seconds to start backup/rollback backend. const int kBackupStartDelay = 10; +namespace { + +void ClearBrowsingData(Profile* profile, base::Time start, base::Time end) { + // BrowsingDataRemover deletes itself when it's done. + BrowsingDataRemover* remover = BrowsingDataRemover::CreateForRange( + profile, start, end); + remover->Remove(BrowsingDataRemover::REMOVE_ALL, + BrowsingDataHelper::ALL); +} + +} // anonymous namespace + bool ShouldShowActionOnUI( const syncer::SyncProtocolError& error) { return (error.action != syncer::UNKNOWN_ACTION && @@ -215,7 +229,8 @@ ProfileSyncService::ProfileSyncService( startup_controller_weak_factory_.GetWeakPtr(), ROLLBACK)), backend_mode_(IDLE), - backup_start_delay_(base::TimeDelta::FromSeconds(kBackupStartDelay)) { + backup_start_delay_(base::TimeDelta::FromSeconds(kBackupStartDelay)), + clear_browsing_data_(base::Bind(&ClearBrowsingData)) { DCHECK(profile); // By default, dev, canary, and unbranded Chromium users will go to the // development servers. Development servers have more features than standard @@ -524,6 +539,13 @@ SyncCredentials ProfileSyncService::GetCredentials() { bool ProfileSyncService::ShouldDeleteSyncFolder() { if (backend_mode_ == SYNC) return !HasSyncSetupCompleted(); + + // Start fresh if it's the first time backup after user stopped syncing. + // This is needed because backup DB may contain items deleted by user during + // sync period and can cause back-from-dead issues. + if (backend_mode_ == BACKUP && !sync_prefs_.GetFirstSyncTime().is_null()) + return true; + return false; } @@ -643,6 +665,9 @@ void ProfileSyncService::StartUpSlowBackendComponents( backend_mode_ = mode; + if (backend_mode_ == ROLLBACK) + ClearBrowsingDataSinceFirstSync(); + base::FilePath sync_folder = backend_mode_ == SYNC ? base::FilePath(kSyncDataFolderName) : base::FilePath(kSyncBackupDataFolderName); @@ -663,6 +688,8 @@ void ProfileSyncService::StartUpSlowBackendComponents( // we'll want to start from a fresh SyncDB, so delete any old one that might // be there. InitializeBackend(ShouldDeleteSyncFolder()); + + UpdateFirstSyncTimePref(); } void ProfileSyncService::OnGetTokenSuccess( @@ -2475,3 +2502,27 @@ bool ProfileSyncService::HasSyncingBackend() const { void ProfileSyncService::SetBackupStartDelayForTest(base::TimeDelta delay) { backup_start_delay_ = delay; } + +void ProfileSyncService::UpdateFirstSyncTimePref() { + if (signin_->GetEffectiveUsername().empty()) { + // Clear if user's not signed in and rollback is done. + if (backend_mode_ == BACKUP) + sync_prefs_.ClearFirstSyncTime(); + } else if (sync_prefs_.GetFirstSyncTime().is_null()) { + // Set if user is signed in and time was not set before. + sync_prefs_.SetFirstSyncTime(base::Time::Now()); + } +} + +void ProfileSyncService::ClearBrowsingDataSinceFirstSync() { + base::Time first_sync_time = sync_prefs_.GetFirstSyncTime(); + if (first_sync_time.is_null()) + return; + + clear_browsing_data_.Run(profile_, first_sync_time, base::Time::Now()); +} + +void ProfileSyncService::SetClearingBrowseringDataForTesting( + base::Callback<void(Profile*, base::Time, base::Time)> c) { + clear_browsing_data_ = c; +} diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h index 14882ba..0bdde68 100644 --- a/chrome/browser/sync/profile_sync_service.h +++ b/chrome/browser/sync/profile_sync_service.h @@ -766,6 +766,9 @@ class ProfileSyncService : public ProfileSyncServiceBase, return backend_mode_; } + void SetClearingBrowseringDataForTesting( + base::Callback<void(Profile*, base::Time, base::Time)> c); + protected: // Helper to configure the priority data types. void ConfigurePriorityDataTypes(); @@ -935,6 +938,12 @@ class ProfileSyncService : public ProfileSyncServiceBase, // True if a syncing backend exists. bool HasSyncingBackend() const; + // Update first sync time stored in preferences + void UpdateFirstSyncTimePref(); + + // Clear browsing data since first sync during rollback. + void ClearBrowsingDataSinceFirstSync(); + // Factory used to create various dependent objects. scoped_ptr<ProfileSyncComponentsFactory> factory_; @@ -1099,6 +1108,8 @@ class ProfileSyncService : public ProfileSyncServiceBase, // time. base::TimeDelta backup_start_delay_; + base::Callback<void(Profile*, base::Time, base::Time)> clear_browsing_data_; + DISALLOW_COPY_AND_ASSIGN(ProfileSyncService); }; diff --git a/chrome/browser/sync/profile_sync_service_unittest.cc b/chrome/browser/sync/profile_sync_service_unittest.cc index c951e37..efa178e 100644 --- a/chrome/browser/sync/profile_sync_service_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_unittest.cc @@ -27,6 +27,7 @@ #include "components/signin/core/browser/signin_manager.h" #include "components/sync_driver/data_type_manager_impl.h" #include "components/sync_driver/pref_names.h" +#include "components/sync_driver/sync_prefs.h" #include "content/public/test/test_browser_thread_bundle.h" #include "google_apis/gaia/gaia_constants.h" #include "testing/gmock/include/gmock/gmock.h" @@ -46,6 +47,7 @@ ACTION(ReturnNewDataTypeManager) { arg5); } +using testing::Return; using testing::StrictMock; using testing::_; @@ -80,6 +82,37 @@ class SyncBackendHostNoReturn : public SyncBackendHostMock { syncer::NetworkResources* network_resources) OVERRIDE {} }; +class SyncBackendHostMockCollectDeleteDirParam : public SyncBackendHostMock { + public: + SyncBackendHostMockCollectDeleteDirParam(std::vector<bool>* delete_dir_param) + : delete_dir_param_(delete_dir_param) {} + + virtual void Initialize( + SyncFrontend* frontend, + scoped_ptr<base::Thread> sync_thread, + const syncer::WeakHandle<syncer::JsEventHandler>& event_handler, + const GURL& service_url, + const syncer::SyncCredentials& credentials, + bool delete_sync_data_folder, + scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory, + scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler, + syncer::ReportUnrecoverableErrorFunction + report_unrecoverable_error_function, + syncer::NetworkResources* network_resources) OVERRIDE { + delete_dir_param_->push_back(delete_sync_data_folder); + SyncBackendHostMock::Initialize(frontend, sync_thread.Pass(), + event_handler, service_url, credentials, + delete_sync_data_folder, + sync_manager_factory.Pass(), + unrecoverable_error_handler.Pass(), + report_unrecoverable_error_function, + network_resources); + } + + private: + std::vector<bool>* delete_dir_param_; +}; + ACTION(ReturnNewSyncBackendHostMock) { return new browser_sync::SyncBackendHostMock(); } @@ -88,6 +121,11 @@ ACTION(ReturnNewSyncBackendHostNoReturn) { return new browser_sync::SyncBackendHostNoReturn(); } +ACTION_P(ReturnNewMockHostCollectDeleteDirParam, delete_dir_param) { + return new browser_sync::SyncBackendHostMockCollectDeleteDirParam( + delete_dir_param); +} + // A test harness that uses a real ProfileSyncService and in most cases a // MockSyncBackendHost. // @@ -152,6 +190,9 @@ class ProfileSyncServiceTest : public ::testing::Test { new ManagedUserSigninManagerWrapper(profile_, signin), oauth2_token_service, behavior)); + service_->SetClearingBrowseringDataForTesting( + base::Bind(&ProfileSyncServiceTest::ClearBrowsingDataCallback, + base::Unretained(this))); } #if defined(OS_WIN) || defined(OS_MACOSX) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) @@ -185,6 +226,14 @@ class ProfileSyncServiceTest : public ::testing::Test { .WillRepeatedly(ReturnNewSyncBackendHostMock()); } + void ExpectSyncBackendHostCreationCollectDeleteDir( + int times, std::vector<bool> *delete_dir_param) { + EXPECT_CALL(*components_factory_, CreateSyncBackendHost(_, _, _, _, _)) + .Times(times) + .WillRepeatedly(ReturnNewMockHostCollectDeleteDirParam( + delete_dir_param)); + } + void PrepareDelayedInitSyncBackendHost() { EXPECT_CALL(*components_factory_, CreateSyncBackendHost(_, _, _, _, _)). WillOnce(ReturnNewSyncBackendHostNoReturn()); @@ -202,6 +251,16 @@ class ProfileSyncServiceTest : public ::testing::Test { return components_factory_; } + void ClearBrowsingDataCallback(Profile* profile, base::Time start, + base::Time end) { + EXPECT_EQ(profile_, profile); + clear_browsing_data_start_ = start; + } + + protected: + // The requested start time when ClearBrowsingDataCallback is called. + base::Time clear_browsing_data_start_; + private: content::TestBrowserThreadBundle thread_bundle_; TestingProfileManager profile_manager_; @@ -427,7 +486,8 @@ void QuitLoop() { TEST_F(ProfileSyncServiceTest, StartBackup) { CreateServiceWithoutSignIn(); ExpectDataTypeManagerCreation(1); - ExpectSyncBackendHostCreation(1); + std::vector<bool> delete_dir_param; + ExpectSyncBackendHostCreationCollectDeleteDir(1, &delete_dir_param); Initialize(); EXPECT_EQ(ProfileSyncService::IDLE, service()->backend_mode()); base::MessageLoop::current()->PostDelayedTask( @@ -435,46 +495,81 @@ TEST_F(ProfileSyncServiceTest, StartBackup) { base::TimeDelta::FromMilliseconds(100)); base::MessageLoop::current()->Run(); EXPECT_EQ(ProfileSyncService::BACKUP, service()->backend_mode()); + + EXPECT_EQ(1u, delete_dir_param.size()); + EXPECT_FALSE(delete_dir_param[0]); } TEST_F(ProfileSyncServiceTest, BackupAfterSyncDisabled) { CreateService(browser_sync::MANUAL_START); service()->SetSyncSetupCompleted(); ExpectDataTypeManagerCreation(2); - ExpectSyncBackendHostCreation(2); + std::vector<bool> delete_dir_param; + ExpectSyncBackendHostCreationCollectDeleteDir(2, &delete_dir_param); IssueTestTokens(); Initialize(); base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&QuitLoop)); EXPECT_TRUE(service()->sync_initialized()); EXPECT_EQ(ProfileSyncService::SYNC, service()->backend_mode()); + // First sync time should be recorded. + sync_driver::SyncPrefs sync_prefs(service()->profile()->GetPrefs()); + EXPECT_FALSE(sync_prefs.GetFirstSyncTime().is_null()); + syncer::SyncProtocolError client_cmd; client_cmd.action = syncer::DISABLE_SYNC_ON_CLIENT; service()->OnActionableError(client_cmd); EXPECT_EQ(ProfileSyncService::BACKUP, service()->backend_mode()); + + // Browsing data is not cleared because rollback is skipped. + EXPECT_TRUE(clear_browsing_data_start_.is_null()); + + // First sync time is erased once backup starts. + EXPECT_TRUE(sync_prefs.GetFirstSyncTime().is_null()); + + EXPECT_EQ(2u, delete_dir_param.size()); + EXPECT_FALSE(delete_dir_param[0]); + EXPECT_TRUE(delete_dir_param[1]); } TEST_F(ProfileSyncServiceTest, RollbackThenBackup) { CreateService(browser_sync::MANUAL_START); service()->SetSyncSetupCompleted(); ExpectDataTypeManagerCreation(3); - ExpectSyncBackendHostCreation(3); + std::vector<bool> delete_dir_param; + ExpectSyncBackendHostCreationCollectDeleteDir(3, &delete_dir_param); IssueTestTokens(); Initialize(); base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&QuitLoop)); EXPECT_TRUE(service()->sync_initialized()); EXPECT_EQ(ProfileSyncService::SYNC, service()->backend_mode()); + // First sync time should be recorded. + sync_driver::SyncPrefs sync_prefs(service()->profile()->GetPrefs()); + base::Time first_sync_time = sync_prefs.GetFirstSyncTime(); + EXPECT_FALSE(first_sync_time.is_null()); + syncer::SyncProtocolError client_cmd; client_cmd.action = syncer::DISABLE_SYNC_AND_ROLLBACK; service()->OnActionableError(client_cmd); EXPECT_TRUE(service()->sync_initialized()); EXPECT_EQ(ProfileSyncService::ROLLBACK, service()->backend_mode()); + // Browser data should be cleared during rollback. + EXPECT_EQ(first_sync_time, clear_browsing_data_start_); + client_cmd.action = syncer::ROLLBACK_DONE; service()->OnActionableError(client_cmd); EXPECT_TRUE(service()->sync_initialized()); EXPECT_EQ(ProfileSyncService::BACKUP, service()->backend_mode()); + + // First sync time is erased once backup starts. + EXPECT_TRUE(sync_prefs.GetFirstSyncTime().is_null()); + + EXPECT_EQ(3u, delete_dir_param.size()); + EXPECT_FALSE(delete_dir_param[0]); + EXPECT_FALSE(delete_dir_param[1]); + EXPECT_TRUE(delete_dir_param[2]); } #endif diff --git a/components/sync_driver/pref_names.cc b/components/sync_driver/pref_names.cc index c8cafc2..c542c64 100644 --- a/components/sync_driver/pref_names.cc +++ b/components/sync_driver/pref_names.cc @@ -98,6 +98,9 @@ const char kSyncSpareBootstrapToken[] = "sync.spare_bootstrap_token"; // Stores how many times to try rollback before giving up. const char kSyncRemainingRollbackTries[] = "sync.remaining_rollback_tries"; +// Stores the timestamp of first sync. +const char kSyncFirstSyncTime[] = "sync.first_sync_time"; + } // namespace prefs } // namespace sync_driver diff --git a/components/sync_driver/pref_names.h b/components/sync_driver/pref_names.h index f31f8e3..d7e8f80 100644 --- a/components/sync_driver/pref_names.h +++ b/components/sync_driver/pref_names.h @@ -62,6 +62,7 @@ extern const char kSyncSpareBootstrapToken[]; #endif // defined(OS_CHROMEOS) extern const char kSyncRemainingRollbackTries[]; +extern const char kSyncFirstSyncTime[]; } // namespace prefs diff --git a/components/sync_driver/sync_prefs.cc b/components/sync_driver/sync_prefs.cc index 272915d..2a9f590 100644 --- a/components/sync_driver/sync_prefs.cc +++ b/components/sync_driver/sync_prefs.cc @@ -48,6 +48,10 @@ void SyncPrefs::RegisterProfilePrefs( prefs::kSyncLastSyncedTime, 0, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterInt64Pref( + prefs::kSyncFirstSyncTime, + 0, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); // All datatypes are on by default, but this gets set explicitly // when you configure sync (when turning it on), in @@ -485,4 +489,17 @@ syncer::ModelTypeSet SyncPrefs::ResolvePrefGroups( return types_with_groups; } +base::Time SyncPrefs::GetFirstSyncTime() const { + return base::Time::FromInternalValue( + pref_service_->GetInt64(prefs::kSyncFirstSyncTime)); +} + +void SyncPrefs::SetFirstSyncTime(base::Time time) { + pref_service_->SetInt64(prefs::kSyncFirstSyncTime, time.ToInternalValue()); +} + +void SyncPrefs::ClearFirstSyncTime() { + pref_service_->ClearPref(prefs::kSyncFirstSyncTime); +} + } // namespace browser_sync diff --git a/components/sync_driver/sync_prefs.h b/components/sync_driver/sync_prefs.h index da94c5b..3400824 100644 --- a/components/sync_driver/sync_prefs.h +++ b/components/sync_driver/sync_prefs.h @@ -131,6 +131,12 @@ class SyncPrefs : NON_EXPORTED_BASE(public base::NonThreadSafe), virtual int GetRemainingRollbackTries() const; virtual void SetRemainingRollbackTries(int times); + // Get/set/clear first sync time of current user. Used to roll back browsing + // data later when user signs out. + base::Time GetFirstSyncTime() const; + void SetFirstSyncTime(base::Time time); + void ClearFirstSyncTime(); + // For testing. void SetManagedForTest(bool is_managed); |