diff options
Diffstat (limited to 'chrome')
6 files changed, 181 insertions, 32 deletions
diff --git a/chrome/browser/sync/glue/synced_device_tracker.cc b/chrome/browser/sync/glue/synced_device_tracker.cc index bf7fa92..e77463e 100644 --- a/chrome/browser/sync/glue/synced_device_tracker.cc +++ b/chrome/browser/sync/glue/synced_device_tracker.cc @@ -13,6 +13,7 @@ #include "sync/internal_api/public/user_share.h" #include "sync/internal_api/public/write_node.h" #include "sync/internal_api/public/write_transaction.h" +#include "sync/util/time.h" namespace browser_sync { @@ -157,25 +158,28 @@ void SyncedDeviceTracker::InitLocalDeviceInfoContinuation( } void SyncedDeviceTracker::WriteLocalDeviceInfo(const DeviceInfo& info) { - sync_pb::DeviceInfoSpecifics specifics; DCHECK_EQ(cache_guid_, info.guid()); - specifics.set_cache_guid(cache_guid_); - specifics.set_client_name(info.client_name()); - specifics.set_chrome_version(info.chrome_version()); - specifics.set_sync_user_agent(info.sync_user_agent()); - specifics.set_device_type(info.device_type()); - - WriteDeviceInfo(specifics, local_device_info_tag_); + WriteDeviceInfo(info, local_device_info_tag_); } -void SyncedDeviceTracker::WriteDeviceInfo( - const sync_pb::DeviceInfoSpecifics& specifics, - const std::string& tag) { +void SyncedDeviceTracker::WriteDeviceInfo(const DeviceInfo& info, + const std::string& tag) { syncer::WriteTransaction trans(FROM_HERE, user_share_); syncer::WriteNode node(&trans); + sync_pb::DeviceInfoSpecifics specifics; + specifics.set_cache_guid(info.guid()); + specifics.set_client_name(info.client_name()); + specifics.set_chrome_version(info.chrome_version()); + specifics.set_sync_user_agent(info.sync_user_agent()); + specifics.set_device_type(info.device_type()); + if (node.InitByClientTagLookup(syncer::DEVICE_INFO, tag) == syncer::BaseNode::INIT_OK) { + const sync_pb::DeviceInfoSpecifics& sync_specifics = + node.GetDeviceInfoSpecifics(); + if (sync_specifics.has_backup_timestamp()) + specifics.set_backup_timestamp(sync_specifics.backup_timestamp()); node.SetDeviceInfoSpecifics(specifics); node.SetTitle(specifics.client_name()); } else { @@ -195,4 +199,33 @@ void SyncedDeviceTracker::WriteDeviceInfo( } } +void SyncedDeviceTracker::UpdateLocalDeviceBackupTime(base::Time backup_time) { + syncer::WriteTransaction trans(FROM_HERE, user_share_); + syncer::WriteNode node(&trans); + + if (node.InitByClientTagLookup(syncer::DEVICE_INFO, local_device_info_tag_) + == syncer::BaseNode::INIT_OK) { + sync_pb::DeviceInfoSpecifics specifics = node.GetDeviceInfoSpecifics(); + int64 new_backup_timestamp = syncer::TimeToProtoTime(backup_time); + if (!specifics.has_backup_timestamp() || + specifics.backup_timestamp() != new_backup_timestamp) { + specifics.set_backup_timestamp(new_backup_timestamp); + node.SetDeviceInfoSpecifics(specifics); + } + } +} + +base::Time SyncedDeviceTracker::GetLocalDeviceBackupTime() const { + syncer::ReadTransaction trans(FROM_HERE, user_share_); + syncer::ReadNode node(&trans); + if (node.InitByClientTagLookup(syncer::DEVICE_INFO, local_device_info_tag_) + == syncer::BaseNode::INIT_OK && + node.GetDeviceInfoSpecifics().has_backup_timestamp()) { + return syncer::ProtoTimeToTime( + node.GetDeviceInfoSpecifics().backup_timestamp()); + } else { + return base::Time(); + } +} + } // namespace browser_sync diff --git a/chrome/browser/sync/glue/synced_device_tracker.h b/chrome/browser/sync/glue/synced_device_tracker.h index 3f0844a..1bc2d66 100644 --- a/chrome/browser/sync/glue/synced_device_tracker.h +++ b/chrome/browser/sync/glue/synced_device_tracker.h @@ -61,6 +61,13 @@ class SyncedDeviceTracker : public ChangeProcessor { void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); + // Update |backup_timestamp| in local device info specifics to |backup_time| + // if different. + void UpdateLocalDeviceBackupTime(base::Time backup_time); + + // Return time derived from |backup_timestamp| in local device info specifics. + base::Time GetLocalDeviceBackupTime() const; + private: friend class SyncedDeviceTrackerTest; @@ -72,8 +79,7 @@ class SyncedDeviceTracker : public ChangeProcessor { // Helper to write arbitrary device info. Useful for writing local device // info and also used by test cases to write arbitrary device infos. - void WriteDeviceInfo(const sync_pb::DeviceInfoSpecifics& specifics, - const std::string& tag); + void WriteDeviceInfo(const DeviceInfo& info, const std::string& tag); syncer::UserShare* user_share_; const std::string cache_guid_; diff --git a/chrome/browser/sync/glue/synced_device_tracker_unittest.cc b/chrome/browser/sync/glue/synced_device_tracker_unittest.cc index 4596b5a1..267d047 100644 --- a/chrome/browser/sync/glue/synced_device_tracker_unittest.cc +++ b/chrome/browser/sync/glue/synced_device_tracker_unittest.cc @@ -20,20 +20,6 @@ namespace browser_sync { -namespace { - -void ConvertDeviceInfoSpecifics( - const DeviceInfo& device_info, - sync_pb::DeviceInfoSpecifics* specifics) { - specifics->set_cache_guid(device_info.guid()); - specifics->set_client_name(device_info.client_name()); - specifics->set_chrome_version(device_info.chrome_version()); - specifics->set_sync_user_agent(device_info.sync_user_agent()); - specifics->set_device_type(device_info.device_type()); -} - -} // namespace - class SyncedDeviceTrackerTest : public ::testing::Test { protected: SyncedDeviceTrackerTest() : transaction_count_baseline_(0) { } @@ -69,9 +55,7 @@ class SyncedDeviceTrackerTest : public ::testing::Test { } void WriteDeviceInfo(const DeviceInfo& device_info) { - sync_pb::DeviceInfoSpecifics specifics; - ConvertDeviceInfoSpecifics(device_info, &specifics); - synced_device_tracker_->WriteDeviceInfo(specifics, device_info.guid()); + synced_device_tracker_->WriteDeviceInfo(device_info, device_info.guid()); } void ResetObservedChangesCounter() { @@ -208,6 +192,35 @@ TEST_F(SyncedDeviceTrackerTest, GetAllDeviceInfo) { EXPECT_TRUE(device_info[1]->Equals(device_info2)); } +TEST_F(SyncedDeviceTrackerTest, DeviceBackupTime) { + DeviceInfo device_info( + user_share()->directory->cache_guid(), + "John’s Device", "XYZ v1", "XYZ SyncAgent v1", + sync_pb::SyncEnums_DeviceType_TYPE_LINUX); + const base::Time test_backup_time = + base::Time::UnixEpoch() + base::TimeDelta::FromDays(10000); + + WriteLocalDeviceInfo(device_info); + synced_device_tracker_->UpdateLocalDeviceBackupTime(test_backup_time); + + // Verify read of device info and backup time. + EXPECT_EQ(test_backup_time, + synced_device_tracker_->GetLocalDeviceBackupTime()); + scoped_ptr<DeviceInfo> device_info_out( + synced_device_tracker_->ReadLocalDeviceInfo()); + ASSERT_TRUE(device_info_out); + EXPECT_TRUE(device_info.Equals(*device_info_out.get())); + + // Verify backup time is not lost after updating device info. + DeviceInfo device_info2( + user_share()->directory->cache_guid(), + "def Device", "XYZ v2", "XYZ SyncAgent v2", + sync_pb::SyncEnums_DeviceType_TYPE_LINUX); + WriteLocalDeviceInfo(device_info2); + EXPECT_EQ(test_backup_time, + synced_device_tracker_->GetLocalDeviceBackupTime()); +} + } // namespace } // namespace browser_sync diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc index cd24db0e..9102c4a 100644 --- a/chrome/browser/sync/profile_sync_service.cc +++ b/chrome/browser/sync/profile_sync_service.cc @@ -76,6 +76,7 @@ #include "components/sync_driver/pref_names.h" #include "components/sync_driver/system_encryptor.h" #include "components/sync_driver/user_selectable_sync_type.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h" @@ -90,6 +91,7 @@ #include "sync/internal_api/public/sync_context_proxy.h" #include "sync/internal_api/public/sync_encryption_handler.h" #include "sync/internal_api/public/util/experiments.h" +#include "sync/internal_api/public/util/sync_db_util.h" #include "sync/internal_api/public/util/sync_string_conversions.h" #include "sync/js/js_event_details.h" #include "sync/util/cryptographer.h" @@ -658,6 +660,8 @@ void ProfileSyncService::StartUpSlowBackendComponents( if (backend_mode_ == ROLLBACK) ClearBrowsingDataSinceFirstSync(); + else if (backend_mode_ == SYNC) + CheckSyncBackupIfNeeded(); base::FilePath sync_folder = backend_mode_ == SYNC ? base::FilePath(kSyncDataFolderName) : @@ -1022,6 +1026,13 @@ void ProfileSyncService::PostBackendInitialization() { // Never get here for backup / restore. DCHECK_EQ(backend_mode_, SYNC); + if (last_backup_time_) { + browser_sync::SyncedDeviceTracker* device_tracker = + backend_->GetSyncedDeviceTracker(); + if (device_tracker) + device_tracker->UpdateLocalDeviceBackupTime(*last_backup_time_); + } + if (protocol_event_observers_.might_have_observers()) { backend_->RequestBufferedProtocolEventsAndEnableForwarding(); } @@ -2597,3 +2608,50 @@ void ProfileSyncService::StartStopBackupForTesting() { else backup_rollback_controller_.Start(base::TimeDelta()); } + +void ProfileSyncService::CheckSyncBackupIfNeeded() { + DCHECK_EQ(backend_mode_, SYNC); + +#if defined(ENABLE_PRE_SYNC_BACKUP) + // Check backup once a day. + if (!last_backup_time_ && + (last_synced_time_.is_null() || + base::Time::Now() - last_synced_time_ >= + base::TimeDelta::FromDays(1))) { + // If sync thread is set, need to serialize check on sync thread after + // closing backup DB. + if (sync_thread_) { + sync_thread_->message_loop_proxy()->PostTask( + FROM_HERE, + base::Bind(syncer::CheckSyncDbLastModifiedTime, + profile_->GetPath().Append(kSyncBackupDataFolderName), + base::MessageLoopProxy::current(), + base::Bind(&ProfileSyncService::CheckSyncBackupCallback, + weak_factory_.GetWeakPtr()))); + } else { + content::BrowserThread::PostTask( + content::BrowserThread::FILE, FROM_HERE, + base::Bind(syncer::CheckSyncDbLastModifiedTime, + profile_->GetPath().Append(kSyncBackupDataFolderName), + base::MessageLoopProxy::current(), + base::Bind(&ProfileSyncService::CheckSyncBackupCallback, + weak_factory_.GetWeakPtr()))); + } + } +#endif +} + +void ProfileSyncService::CheckSyncBackupCallback(base::Time backup_time) { + last_backup_time_.reset(new base::Time(backup_time)); + + if (HasSyncingBackend() && backend_initialized_) { + browser_sync::SyncedDeviceTracker* device_tracker = + backend_->GetSyncedDeviceTracker(); + if (device_tracker) + device_tracker->UpdateLocalDeviceBackupTime(*last_backup_time_); + } +} + +base::Time ProfileSyncService::GetDeviceBackupTimeForTesting() const { + return backend_->GetSyncedDeviceTracker()->GetLocalDeviceBackupTime(); +} diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h index 5b695fb..ccb4606 100644 --- a/chrome/browser/sync/profile_sync_service.h +++ b/chrome/browser/sync/profile_sync_service.h @@ -782,6 +782,8 @@ class ProfileSyncService : public ProfileSyncServiceBase, void StartStopBackupForTesting(); + base::Time GetDeviceBackupTimeForTesting() const; + protected: // Helper to configure the priority data types. void ConfigurePriorityDataTypes(); @@ -957,6 +959,12 @@ class ProfileSyncService : public ProfileSyncServiceBase, // Clear browsing data since first sync during rollback. void ClearBrowsingDataSinceFirstSync(); + // Post background task to check sync backup DB state if needed. + void CheckSyncBackupIfNeeded(); + + // Callback to receive backup DB check result. + void CheckSyncBackupCallback(base::Time backup_time); + // Factory used to create various dependent objects. scoped_ptr<ProfileSyncComponentsFactory> factory_; @@ -1124,6 +1132,10 @@ class ProfileSyncService : public ProfileSyncServiceBase, base::Callback<void(Profile*, base::Time, base::Time)> clear_browsing_data_; + // Last time when pre-sync data was saved. NULL pointer means backup data + // state is unknown. If time value is null, backup data doesn't exist. + scoped_ptr<base::Time> last_backup_time_; + DISALLOW_COPY_AND_ASSIGN(ProfileSyncService); }; diff --git a/chrome/browser/sync/test/integration/single_client_backup_rollback_test.cc b/chrome/browser/sync/test/integration/single_client_backup_rollback_test.cc index 3321669..6de9eb2 100644 --- a/chrome/browser/sync/test/integration/single_client_backup_rollback_test.cc +++ b/chrome/browser/sync/test/integration/single_client_backup_rollback_test.cc @@ -5,6 +5,7 @@ #include "base/command_line.h" #include "base/message_loop/message_loop.h" #include "base/prefs/pref_service.h" +#include "base/run_loop.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/sync/test/integration/bookmarks_helper.h" @@ -14,7 +15,9 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "components/bookmarks/browser/bookmark_model.h" +#include "sync/internal_api/public/util/sync_db_util.h" #include "sync/test/fake_server/fake_server_verifier.h" +#include "sync/util/time.h" using bookmarks_helper::AddFolder; using bookmarks_helper::AddURL; @@ -45,7 +48,26 @@ class SingleClientBackupRollbackTest : public SyncTest { switches::kSyncEnableRollback); } + base::Time GetBackupDbLastModified() { + base::RunLoop run_loop; + + base::Time backup_time; + syncer::CheckSyncDbLastModifiedTime( + GetProfile(0)->GetPath().Append(FILE_PATH_LITERAL("Sync Data Backup")), + base::MessageLoopProxy::current(), + base::Bind(&SingleClientBackupRollbackTest::CheckDbCallback, + base::Unretained(this), &backup_time)); + base::MessageLoopProxy::current()->PostTask( + FROM_HERE, run_loop.QuitClosure()); + run_loop.Run(); + return backup_time; + } + private: + void CheckDbCallback(base::Time* time_out, base::Time time_in) { + *time_out = syncer::ProtoTimeToTime(syncer::TimeToProtoTime(time_in)); + } + DISALLOW_COPY_AND_ASSIGN(SingleClientBackupRollbackTest); }; @@ -188,16 +210,21 @@ IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest, // Setup sync, wait for its completion, and make sure changes were synced. ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; - ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0)))); + ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0))); ASSERT_TRUE(ModelMatchesVerifier(0)); // Made bookmark changes while sync is on. Move(0, tier1_a->GetChild(0), tier1_b, 1); Remove(0, tier1_b, 0); ASSERT_TRUE(AddFolder(0, tier1_b, 1, "tier2_c")); - ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0)))); + ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0))); ASSERT_TRUE(ModelMatchesVerifier(0)); + // Verify backup time is set on device info. + base::Time backup_time = GetBackupDbLastModified(); + ASSERT_FALSE(backup_time.is_null()); + ASSERT_EQ(backup_time, GetSyncService(0)->GetDeviceBackupTimeForTesting()); + // Let server to return rollback command on next sync request. GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK); |