summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhaitaol@chromium.org <haitaol@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-05 21:16:28 +0000
committerhaitaol@chromium.org <haitaol@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-05 21:16:28 +0000
commitff08e5c278d265f7a1f407e9aa4c09201d009af5 (patch)
treee76f7313cfd1f01581ff91fa3e157e69edca6bdc
parent6e7737988af7c5217d8b66877aae39221b80d198 (diff)
downloadchromium_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.cc53
-rw-r--r--chrome/browser/sync/profile_sync_service.h11
-rw-r--r--chrome/browser/sync/profile_sync_service_unittest.cc101
-rw-r--r--components/sync_driver/pref_names.cc3
-rw-r--r--components/sync_driver/pref_names.h1
-rw-r--r--components/sync_driver/sync_prefs.cc17
-rw-r--r--components/sync_driver/sync_prefs.h6
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);