diff options
Diffstat (limited to 'components/sync_driver')
-rw-r--r-- | components/sync_driver/BUILD.gn | 8 | ||||
-rw-r--r-- | components/sync_driver/device_info.cc | 113 | ||||
-rw-r--r-- | components/sync_driver/device_info.h | 101 | ||||
-rw-r--r-- | components/sync_driver/device_info_data_type_controller.cc | 48 | ||||
-rw-r--r-- | components/sync_driver/device_info_data_type_controller.h | 40 | ||||
-rw-r--r-- | components/sync_driver/device_info_sync_service.cc | 343 | ||||
-rw-r--r-- | components/sync_driver/device_info_sync_service.h | 108 | ||||
-rw-r--r-- | components/sync_driver/device_info_tracker.h | 40 | ||||
-rw-r--r-- | components/sync_driver/local_device_info_provider.h | 50 |
9 files changed, 851 insertions, 0 deletions
diff --git a/components/sync_driver/BUILD.gn b/components/sync_driver/BUILD.gn index 04dcc74..5a04237 100644 --- a/components/sync_driver/BUILD.gn +++ b/components/sync_driver/BUILD.gn @@ -20,10 +20,18 @@ static_library("sync_driver") { "data_type_manager_observer.h", "data_type_status_table.cc", "data_type_status_table.h", + "device_info.cc", + "device_info.h", + "device_info_data_type_controller.cc", + "device_info_data_type_controller.h", + "device_info_sync_service.cc", + "device_info_sync_service.h", + "device_info_tracker.h", "generic_change_processor.cc", "generic_change_processor.h", "generic_change_processor_factory.cc", "generic_change_processor_factory.h", + "local_device_info_provider.h", "model_association_manager.cc", "model_association_manager.h", "model_associator.h", diff --git a/components/sync_driver/device_info.cc b/components/sync_driver/device_info.cc new file mode 100644 index 0000000..c80a157 --- /dev/null +++ b/components/sync_driver/device_info.cc @@ -0,0 +1,113 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/values.h" +#include "components/sync_driver/device_info.h" + +namespace sync_driver { + +DeviceInfo::DeviceInfo(const std::string& guid, + const std::string& client_name, + const std::string& chrome_version, + const std::string& sync_user_agent, + const sync_pb::SyncEnums::DeviceType device_type, + const std::string& signin_scoped_device_id) + : guid_(guid), + client_name_(client_name), + chrome_version_(chrome_version), + sync_user_agent_(sync_user_agent), + device_type_(device_type), + signin_scoped_device_id_(signin_scoped_device_id) { +} + +DeviceInfo::~DeviceInfo() { } + +const std::string& DeviceInfo::guid() const { + return guid_; +} + +const std::string& DeviceInfo::client_name() const { + return client_name_; +} + +const std::string& DeviceInfo::chrome_version() const { + return chrome_version_; +} + +const std::string& DeviceInfo::sync_user_agent() const { + return sync_user_agent_; +} + +const std::string& DeviceInfo::public_id() const { + return public_id_; +} + +sync_pb::SyncEnums::DeviceType DeviceInfo::device_type() const { + return device_type_; +} + +const std::string& DeviceInfo::signin_scoped_device_id() const { + return signin_scoped_device_id_; +} + +std::string DeviceInfo::GetOSString() const { + switch (device_type_) { + case sync_pb::SyncEnums_DeviceType_TYPE_WIN: + return "win"; + case sync_pb::SyncEnums_DeviceType_TYPE_MAC: + return "mac"; + case sync_pb::SyncEnums_DeviceType_TYPE_LINUX: + return "linux"; + case sync_pb::SyncEnums_DeviceType_TYPE_CROS: + return "chrome_os"; + case sync_pb::SyncEnums_DeviceType_TYPE_PHONE: + case sync_pb::SyncEnums_DeviceType_TYPE_TABLET: + // TODO(lipalani): crbug.com/170375. Add support for ios + // phones and tablets. + return "android"; + default: + return "unknown"; + } +} + +std::string DeviceInfo::GetDeviceTypeString() const { + switch (device_type_) { + case sync_pb::SyncEnums_DeviceType_TYPE_WIN: + case sync_pb::SyncEnums_DeviceType_TYPE_MAC: + case sync_pb::SyncEnums_DeviceType_TYPE_LINUX: + case sync_pb::SyncEnums_DeviceType_TYPE_CROS: + return "desktop_or_laptop"; + case sync_pb::SyncEnums_DeviceType_TYPE_PHONE: + return "phone"; + case sync_pb::SyncEnums_DeviceType_TYPE_TABLET: + return "tablet"; + default: + return "unknown"; + } +} + +bool DeviceInfo::Equals(const DeviceInfo& other) const { + return this->guid() == other.guid() && + this->client_name() == other.client_name() && + this->chrome_version() == other.chrome_version() && + this->sync_user_agent() == other.sync_user_agent() && + this->device_type() == other.device_type() && + this->signin_scoped_device_id() == other.signin_scoped_device_id(); +} + +base::DictionaryValue* DeviceInfo::ToValue() { + base::DictionaryValue* value = new base::DictionaryValue(); + value->SetString("name", client_name_); + value->SetString("id", public_id_); + value->SetString("os", GetOSString()); + value->SetString("type", GetDeviceTypeString()); + value->SetString("chromeVersion", chrome_version_); + return value; +} + +void DeviceInfo::set_public_id(std::string id) { + public_id_ = id; +} + +} // namespace sync_driver diff --git a/components/sync_driver/device_info.h b/components/sync_driver/device_info.h new file mode 100644 index 0000000..d2a8f49 --- /dev/null +++ b/components/sync_driver/device_info.h @@ -0,0 +1,101 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SYNC_DRIVER_DEVICE_INFO_H_ +#define COMPONENTS_SYNC_DRIVER_DEVICE_INFO_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "sync/protocol/sync.pb.h" + +namespace base { +class DictionaryValue; +} + +namespace sync_driver { + +// A class that holds information regarding the properties of a device. +class DeviceInfo { + public: + DeviceInfo(const std::string& guid, + const std::string& client_name, + const std::string& chrome_version, + const std::string& sync_user_agent, + const sync_pb::SyncEnums::DeviceType device_type, + const std::string& signin_scoped_device_id); + ~DeviceInfo(); + + // Sync specific unique identifier for the device. Note if a device + // is wiped and sync is set up again this id WILL be different. + // The same device might have more than 1 guid if the device has multiple + // accounts syncing. + const std::string& guid() const; + + // The host name for the client. + const std::string& client_name() const; + + // Chrome version string. + const std::string& chrome_version() const; + + // The user agent is the combination of OS type, chrome version and which + // channel of chrome(stable or beta). For more information see + // |LocalDeviceInfoProviderImpl::MakeUserAgentForSyncApi|. + const std::string& sync_user_agent() const; + + // Third party visible id for the device. See |public_id_| for more details. + const std::string& public_id() const; + + // Device Type. + sync_pb::SyncEnums::DeviceType device_type() const; + + // Device_id that is stable until user signs out. This device_id is used for + // annotating login scoped refresh token. + const std::string& signin_scoped_device_id() const; + + // Gets the OS in string form. + std::string GetOSString() const; + + // Gets the device type in string form. + std::string GetDeviceTypeString() const; + + // Compares this object's fields with another's. + bool Equals(const DeviceInfo& other) const; + + // Apps can set ids for a device that is meaningful to them but + // not unique enough so the user can be tracked. Exposing |guid| + // would lead to a stable unique id for a device which can potentially + // be used for tracking. + void set_public_id(std::string id); + + // Converts the |DeviceInfo| values to a JS friendly DictionaryValue, + // which extension APIs can expose to third party apps. + base::DictionaryValue* ToValue(); + + private: + const std::string guid_; + + const std::string client_name_; + + const std::string chrome_version_; + + const std::string sync_user_agent_; + + const sync_pb::SyncEnums::DeviceType device_type_; + + std::string signin_scoped_device_id_; + + // Exposing |guid| would lead to a stable unique id for a device which + // can potentially be used for tracking. Public ids are privacy safe + // ids in that the same device will have different id for different apps + // and they are also reset when app/extension is uninstalled. + std::string public_id_; + + DISALLOW_COPY_AND_ASSIGN(DeviceInfo); +}; + +} // namespace sync_driver + +#endif // COMPONENTS_SYNC_DRIVER_DEVICE_INFO_H_ diff --git a/components/sync_driver/device_info_data_type_controller.cc b/components/sync_driver/device_info_data_type_controller.cc new file mode 100644 index 0000000..592633d --- /dev/null +++ b/components/sync_driver/device_info_data_type_controller.cc @@ -0,0 +1,48 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/sync_driver/device_info_data_type_controller.h" + +#include "base/callback.h" +#include "components/sync_driver/local_device_info_provider.h" + +namespace sync_driver { + +DeviceInfoDataTypeController::DeviceInfoDataTypeController( + const scoped_refptr<base::MessageLoopProxy>& ui_thread, + const base::Closure& error_callback, + SyncApiComponentFactory* sync_factory, + LocalDeviceInfoProvider* local_device_info_provider) + : UIDataTypeController( + ui_thread, + error_callback, + syncer::DEVICE_INFO, + sync_factory), + local_device_info_provider_(local_device_info_provider) { +} + +DeviceInfoDataTypeController::~DeviceInfoDataTypeController() { +} + +bool DeviceInfoDataTypeController::StartModels() { + // Start the data type as soon as the local device info gets available. + if (local_device_info_provider_->GetLocalDeviceInfo()) { + return true; + } + + subscription_ = local_device_info_provider_->RegisterOnInitializedCallback( + base::Bind(&DeviceInfoDataTypeController::OnLocalDeviceInfoLoaded, this)); + + return false; +} + +void DeviceInfoDataTypeController::OnLocalDeviceInfoLoaded() { + DCHECK_EQ(state_, MODEL_STARTING); + DCHECK(local_device_info_provider_->GetLocalDeviceInfo()); + + subscription_.reset(); + OnModelLoaded(); +} + +} // namespace sync_driver diff --git a/components/sync_driver/device_info_data_type_controller.h b/components/sync_driver/device_info_data_type_controller.h new file mode 100644 index 0000000..aa1b067 --- /dev/null +++ b/components/sync_driver/device_info_data_type_controller.h @@ -0,0 +1,40 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SYNC_DRIVER_DEVICE_INFO_DATA_TYPE_CONTROLLER_H_ +#define COMPONENTS_SYNC_DRIVER_DEVICE_INFO_DATA_TYPE_CONTROLLER_H_ + +#include "base/memory/scoped_ptr.h" +#include "components/sync_driver/local_device_info_provider.h" +#include "components/sync_driver/ui_data_type_controller.h" + +namespace sync_driver { + +// DataTypeController for DEVICE_INFO model type. +class DeviceInfoDataTypeController : public UIDataTypeController { + public: + DeviceInfoDataTypeController( + const scoped_refptr<base::MessageLoopProxy>& ui_thread, + const base::Closure& error_callback, + SyncApiComponentFactory* sync_factory, + LocalDeviceInfoProvider* local_device_info_provider); + + private: + virtual ~DeviceInfoDataTypeController(); + + // UIDataTypeController implementations. + virtual bool StartModels() OVERRIDE; + + // Called by LocalDeviceInfoProvider when the local device into becomes + // available. + void OnLocalDeviceInfoLoaded(); + + LocalDeviceInfoProvider* const local_device_info_provider_; + scoped_ptr<LocalDeviceInfoProvider::Subscription> subscription_; + DISALLOW_COPY_AND_ASSIGN(DeviceInfoDataTypeController); +}; + +} // namespace sync_driver + +#endif // COMPONENTS_SYNC_DRIVER_DEVICE_INFO_DATA_TYPE_CONTROLLER_H_ diff --git a/components/sync_driver/device_info_sync_service.cc b/components/sync_driver/device_info_sync_service.cc new file mode 100644 index 0000000..cdb98e1 --- /dev/null +++ b/components/sync_driver/device_info_sync_service.cc @@ -0,0 +1,343 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/sync_driver/device_info_sync_service.h" + +#include "base/strings/stringprintf.h" +#include "components/sync_driver/local_device_info_provider.h" +#include "sync/api/sync_change.h" +#include "sync/protocol/sync.pb.h" +#include "sync/util/time.h" + +namespace sync_driver { + +using syncer::ModelType; +using syncer::SyncChange; +using syncer::SyncChangeList; +using syncer::SyncChangeProcessor; +using syncer::SyncData; +using syncer::SyncDataList; +using syncer::SyncErrorFactory; +using syncer::SyncMergeResult; + +DeviceInfoSyncService::DeviceInfoSyncService( + LocalDeviceInfoProvider* local_device_info_provider) + : local_device_backup_time_(-1), + local_device_info_provider_(local_device_info_provider) { + DCHECK(local_device_info_provider); +} + +DeviceInfoSyncService::~DeviceInfoSyncService() { +} + +SyncMergeResult DeviceInfoSyncService::MergeDataAndStartSyncing( + ModelType type, + const SyncDataList& initial_sync_data, + scoped_ptr<SyncChangeProcessor> sync_processor, + scoped_ptr<SyncErrorFactory> error_handler) { + DCHECK(sync_processor.get()); + DCHECK(error_handler.get()); + DCHECK_EQ(type, syncer::DEVICE_INFO); + + DCHECK(all_data_.empty()); + + sync_processor_ = sync_processor.Pass(); + error_handler_ = error_handler.Pass(); + + // Initialization should be completed before this type is enabled + // and local device info must be available. + const DeviceInfo* local_device_info = + local_device_info_provider_->GetLocalDeviceInfo(); + DCHECK(local_device_info != NULL); + + // Indicates whether a local device has been added or updated. + // |change_type| defaults to ADD and might be changed to + // UPDATE to INVALID down below if the initial data contains + // data matching the local device ID. + SyncChange::SyncChangeType change_type = SyncChange::ACTION_ADD; + size_t num_items_new = 0; + size_t num_items_updated = 0; + + // Iterate over all initial sync data and copy it to the cache. + for (SyncDataList::const_iterator iter = initial_sync_data.begin(); + iter != initial_sync_data.end(); + ++iter) { + DCHECK_EQ(syncer::DEVICE_INFO, iter->GetDataType()); + + const std::string& id = iter->GetSpecifics().device_info().cache_guid(); + + if (id == local_device_info->guid()) { + // |initial_sync_data| contains data matching the local device. + scoped_ptr<DeviceInfo> synced_local_device_info = + make_scoped_ptr(CreateDeviceInfo(*iter)); + + // Retrieve local device backup timestamp value from the sync data. + bool has_synced_backup_time = + iter->GetSpecifics().device_info().has_backup_timestamp(); + int64 synced_backup_time = + has_synced_backup_time + ? iter->GetSpecifics().device_info().backup_timestamp() + : -1; + + // Overwrite |local_device_backup_time_| with this value if it + // hasn't been set yet. + if (!has_local_device_backup_time() && has_synced_backup_time) { + set_local_device_backup_time(synced_backup_time); + } + + // Store the synced device info for the local device only + // it is the same as the local info. Otherwise store the local + // device info and issue a change further below after finishing + // processing the |initial_sync_data|. + if (synced_local_device_info->Equals(*local_device_info) && + synced_backup_time == local_device_backup_time()) { + change_type = SyncChange::ACTION_INVALID; + } else { + num_items_updated++; + change_type = SyncChange::ACTION_UPDATE; + continue; + } + } else { + // A new device that doesn't match the local device. + num_items_new++; + } + + StoreSyncData(id, *iter); + } + + syncer::SyncMergeResult result(type); + + // Add SyncData for the local device if it is new or different than + // the synced one, and also add it to the |change_list|. + if (change_type != SyncChange::ACTION_INVALID) { + SyncData local_data = CreateLocalData(local_device_info); + StoreSyncData(local_device_info->guid(), local_data); + + SyncChangeList change_list; + change_list.push_back(SyncChange(FROM_HERE, change_type, local_data)); + result.set_error( + sync_processor_->ProcessSyncChanges(FROM_HERE, change_list)); + } + + result.set_num_items_before_association(1); + result.set_num_items_after_association(all_data_.size()); + result.set_num_items_added(num_items_new); + result.set_num_items_modified(num_items_updated); + result.set_num_items_deleted(0); + + NotifyObservers(); + + return result; +} + +void DeviceInfoSyncService::StopSyncing(syncer::ModelType type) { + all_data_.clear(); + sync_processor_.reset(); + error_handler_.reset(); + clear_local_device_backup_time(); +} + +SyncDataList DeviceInfoSyncService::GetAllSyncData( + syncer::ModelType type) const { + SyncDataList list; + + for (SyncDataMap::const_iterator iter = all_data_.begin(); + iter != all_data_.end(); + ++iter) { + list.push_back(iter->second); + } + + return list; +} + +syncer::SyncError DeviceInfoSyncService::ProcessSyncChanges( + const tracked_objects::Location& from_here, + const SyncChangeList& change_list) { + syncer::SyncError error; + + DCHECK(local_device_info_provider_->GetLocalDeviceInfo()); + const std::string& local_device_id = + local_device_info_provider_->GetLocalDeviceInfo()->guid(); + + bool has_changes = false; + + // Iterate over all chanages and merge entries. + for (SyncChangeList::const_iterator iter = change_list.begin(); + iter != change_list.end(); + ++iter) { + const SyncData& sync_data = iter->sync_data(); + DCHECK_EQ(syncer::DEVICE_INFO, sync_data.GetDataType()); + + const std::string& client_id = + sync_data.GetSpecifics().device_info().cache_guid(); + // Ignore device info matching the local device. + if (local_device_id == client_id) { + DVLOG(1) << "Ignoring sync changes for the local DEVICE_INFO"; + continue; + } + + if (iter->change_type() == syncer::SyncChange::ACTION_DELETE) { + has_changes = true; + DeleteSyncData(client_id); + } else if (iter->change_type() == syncer::SyncChange::ACTION_UPDATE || + iter->change_type() == syncer::SyncChange::ACTION_ADD) { + has_changes = true; + StoreSyncData(client_id, sync_data); + } else { + error.Reset(FROM_HERE, "Invalid action received.", syncer::DEVICE_INFO); + } + } + + if (has_changes) { + NotifyObservers(); + } + + return error; +} + +scoped_ptr<DeviceInfo> DeviceInfoSyncService::GetDeviceInfo( + const std::string& client_id) const { + SyncDataMap::const_iterator iter = all_data_.find(client_id); + if (iter == all_data_.end()) { + return scoped_ptr<DeviceInfo>(); + } + + return make_scoped_ptr(CreateDeviceInfo(iter->second)); +} + +ScopedVector<DeviceInfo> DeviceInfoSyncService::GetAllDeviceInfo() const { + ScopedVector<DeviceInfo> list; + + for (SyncDataMap::const_iterator iter = all_data_.begin(); + iter != all_data_.end(); + ++iter) { + list.push_back(CreateDeviceInfo(iter->second)); + } + + return list.Pass(); +} + +void DeviceInfoSyncService::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void DeviceInfoSyncService::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +void DeviceInfoSyncService::NotifyObservers() { + FOR_EACH_OBSERVER(Observer, observers_, OnDeviceInfoChange()); +} + +void DeviceInfoSyncService::UpdateLocalDeviceBackupTime( + base::Time backup_time) { + set_local_device_backup_time(syncer::TimeToProtoTime(backup_time)); + + if (sync_processor_.get()) { + // Local device info must be available in advance + DCHECK(local_device_info_provider_->GetLocalDeviceInfo()); + const std::string& local_id = + local_device_info_provider_->GetLocalDeviceInfo()->guid(); + + SyncDataMap::iterator iter = all_data_.find(local_id); + DCHECK(iter != all_data_.end()); + + syncer::SyncData& data = iter->second; + if (UpdateBackupTime(&data)) { + // Local device backup time has changed. + // Push changes to the server via the |sync_processor_|. + SyncChangeList change_list; + change_list.push_back(SyncChange( + FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data)); + sync_processor_->ProcessSyncChanges(FROM_HERE, change_list); + } + } +} + +bool DeviceInfoSyncService::UpdateBackupTime(syncer::SyncData* sync_data) { + DCHECK(has_local_device_backup_time()); + DCHECK(sync_data->GetSpecifics().has_device_info()); + const sync_pb::DeviceInfoSpecifics& source_specifics = + sync_data->GetSpecifics().device_info(); + + if (!source_specifics.has_backup_timestamp() || + source_specifics.backup_timestamp() != local_device_backup_time()) { + sync_pb::EntitySpecifics entity(sync_data->GetSpecifics()); + entity.mutable_device_info()->set_backup_timestamp( + local_device_backup_time()); + *sync_data = CreateLocalData(entity); + + return true; + } + + return false; +} + +base::Time DeviceInfoSyncService::GetLocalDeviceBackupTime() const { + return has_local_device_backup_time() + ? syncer::ProtoTimeToTime(local_device_backup_time()) + : base::Time(); +} + +SyncData DeviceInfoSyncService::CreateLocalData(const DeviceInfo* info) { + sync_pb::EntitySpecifics entity; + sync_pb::DeviceInfoSpecifics& specifics = *entity.mutable_device_info(); + + 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()); + specifics.set_signin_scoped_device_id(info->signin_scoped_device_id()); + + if (has_local_device_backup_time()) { + specifics.set_backup_timestamp(local_device_backup_time()); + } + + return CreateLocalData(entity); +} + +SyncData DeviceInfoSyncService::CreateLocalData( + const sync_pb::EntitySpecifics& entity) { + const sync_pb::DeviceInfoSpecifics& specifics = entity.device_info(); + + std::string local_device_tag = + base::StringPrintf("DeviceInfo_%s", specifics.cache_guid().c_str()); + + return SyncData::CreateLocalData( + local_device_tag, specifics.client_name(), entity); +} + +DeviceInfo* DeviceInfoSyncService::CreateDeviceInfo( + const syncer::SyncData sync_data) { + const sync_pb::DeviceInfoSpecifics& specifics = + sync_data.GetSpecifics().device_info(); + + return new DeviceInfo(specifics.cache_guid(), + specifics.client_name(), + specifics.chrome_version(), + specifics.sync_user_agent(), + specifics.device_type(), + specifics.signin_scoped_device_id()); +} + +void DeviceInfoSyncService::StoreSyncData(const std::string& client_id, + const SyncData& sync_data) { + DVLOG(1) << "Storing DEVICE_INFO for " + << sync_data.GetSpecifics().device_info().client_name() + << " with ID " << client_id; + all_data_[client_id] = sync_data; +} + +void DeviceInfoSyncService::DeleteSyncData(const std::string& client_id) { + SyncDataMap::iterator iter = all_data_.find(client_id); + if (iter != all_data_.end()) { + DVLOG(1) << "Deleting DEVICE_INFO for " + << iter->second.GetSpecifics().device_info().client_name() + << " with ID " << client_id; + all_data_.erase(iter); + } +} + +} // namespace sync_driver diff --git a/components/sync_driver/device_info_sync_service.h b/components/sync_driver/device_info_sync_service.h new file mode 100644 index 0000000..26eb9a0 --- /dev/null +++ b/components/sync_driver/device_info_sync_service.h @@ -0,0 +1,108 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SYNC_DRIVER_DEVICE_INFO_SYNC_SERVICE_H_ +#define COMPONENTS_SYNC_DRIVER_DEVICE_INFO_SYNC_SERVICE_H_ + +#include "base/observer_list.h" +#include "components/sync_driver/device_info_tracker.h" +#include "sync/api/sync_change_processor.h" +#include "sync/api/sync_data.h" +#include "sync/api/sync_error_factory.h" +#include "sync/api/syncable_service.h" + +namespace sync_driver { + +class LocalDeviceInfoProvider; + +// SyncableService implementation for DEVICE_INFO model type. +class DeviceInfoSyncService : public syncer::SyncableService, + public DeviceInfoTracker { + public: + explicit DeviceInfoSyncService( + LocalDeviceInfoProvider* local_device_info_provider); + virtual ~DeviceInfoSyncService(); + + // syncer::SyncableService implementation. + virtual syncer::SyncMergeResult MergeDataAndStartSyncing( + syncer::ModelType type, + const syncer::SyncDataList& initial_sync_data, + scoped_ptr<syncer::SyncChangeProcessor> sync_processor, + scoped_ptr<syncer::SyncErrorFactory> error_handler) OVERRIDE; + virtual void StopSyncing(syncer::ModelType type) OVERRIDE; + virtual syncer::SyncDataList GetAllSyncData( + syncer::ModelType type) const OVERRIDE; + virtual syncer::SyncError ProcessSyncChanges( + const tracked_objects::Location& from_here, + const syncer::SyncChangeList& change_list) OVERRIDE; + + // DeviceInfoTracker implementation. + virtual scoped_ptr<DeviceInfo> GetDeviceInfo( + const std::string& client_id) const OVERRIDE; + virtual ScopedVector<DeviceInfo> GetAllDeviceInfo() const OVERRIDE; + virtual void AddObserver(Observer* observer) OVERRIDE; + virtual void RemoveObserver(Observer* observer) OVERRIDE; + + // Called to update local device backup time. + void UpdateLocalDeviceBackupTime(base::Time backup_time); + // Gets the most recently set local device backup time. + base::Time GetLocalDeviceBackupTime() const; + + private: + // Create SyncData from local DeviceInfo and |local_device_backup_time_|. + syncer::SyncData CreateLocalData(const DeviceInfo* info); + // Create SyncData from EntitySpecifics. + static syncer::SyncData CreateLocalData( + const sync_pb::EntitySpecifics& entity); + + // Allocate new DeviceInfo from SyncData. + static DeviceInfo* CreateDeviceInfo(const syncer::SyncData sync_data); + // Store SyncData in the cache. + void StoreSyncData(const std::string& client_id, + const syncer::SyncData& sync_data); + // Delete SyncData from the cache. + void DeleteSyncData(const std::string& client_id); + // Notify all registered observers. + void NotifyObservers(); + + // Updates backup time in place in |sync_data| if it is different than + // the one stored in |local_device_backup_time_|. + // Returns true if backup time was updated. + bool UpdateBackupTime(syncer::SyncData* sync_data); + + // |local_device_backup_time_| accessors. + int64 local_device_backup_time() const { return local_device_backup_time_; } + bool has_local_device_backup_time() const { + return local_device_backup_time_ >= 0; + } + void set_local_device_backup_time(int64 value) { + local_device_backup_time_ = value; + } + void clear_local_device_backup_time() { local_device_backup_time_ = -1; } + + // Local device last set backup time (in proto format). + // -1 if the value hasn't been specified + int64 local_device_backup_time_; + + // |local_device_info_provider_| isn't owned. + const LocalDeviceInfoProvider* const local_device_info_provider_; + + // Receives ownership of |sync_processor_| and |error_handler_| in + // MergeDataAndStartSyncing() and destroy them in StopSyncing(). + scoped_ptr<syncer::SyncChangeProcessor> sync_processor_; + scoped_ptr<syncer::SyncErrorFactory> error_handler_; + + // Cache of all syncable and local data. + typedef std::map<std::string, syncer::SyncData> SyncDataMap; + SyncDataMap all_data_; + + // Registered observers, not owned. + ObserverList<Observer, true> observers_; + + DISALLOW_COPY_AND_ASSIGN(DeviceInfoSyncService); +}; + +} // namespace sync_driver + +#endif // COMPONENTS_SYNC_DRIVER_DEVICE_INFO_SYNC_SERVICE_H_ diff --git a/components/sync_driver/device_info_tracker.h b/components/sync_driver/device_info_tracker.h new file mode 100644 index 0000000..cad6e87 --- /dev/null +++ b/components/sync_driver/device_info_tracker.h @@ -0,0 +1,40 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SYNC_DRIVER_DEVICE_INFO_TRACKER_H_ +#define COMPONENTS_SYNC_DRIVER_DEVICE_INFO_TRACKER_H_ + +#include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" +#include "components/sync_driver/device_info.h" + +namespace sync_driver { + +// Interface for tracking synced DeviceInfo. +class DeviceInfoTracker { + public: + virtual ~DeviceInfoTracker() {} + + // Observer class for listening to device info changes. + class Observer { + public: + virtual void OnDeviceInfoChange() = 0; + }; + + // Gets DeviceInfo the synced device with specified client ID. + // Returns an empty scoped_ptr if device with the given |client_id| hasn't + // been synced. + virtual scoped_ptr<DeviceInfo> GetDeviceInfo( + const std::string& client_id) const = 0; + // Gets DeviceInfo for all synced devices (including the local one). + virtual ScopedVector<DeviceInfo> GetAllDeviceInfo() const = 0; + // Registers an observer to be called on syncing any updated DeviceInfo. + virtual void AddObserver(Observer* observer) = 0; + // Unregisters an observer. + virtual void RemoveObserver(Observer* observer) = 0; +}; + +} // namespace sync_driver + +#endif // COMPONENTS_SYNC_DRIVER_DEVICE_INFO_TRACKER_H_ diff --git a/components/sync_driver/local_device_info_provider.h b/components/sync_driver/local_device_info_provider.h new file mode 100644 index 0000000..6036a7e --- /dev/null +++ b/components/sync_driver/local_device_info_provider.h @@ -0,0 +1,50 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SYNC_DRIVER_LOCAL_DEVICE_INFO_PROVIDER_H_ +#define COMPONENTS_SYNC_DRIVER_LOCAL_DEVICE_INFO_PROVIDER_H_ + +#include <string> +#include "base/callback_list.h" + +namespace sync_driver { + +class DeviceInfo; + +// Interface for providing sync specific informaiton about the +// local device. +class LocalDeviceInfoProvider { + public: + typedef base::CallbackList<void(void)>::Subscription Subscription; + + virtual ~LocalDeviceInfoProvider() {} + + // Returns sync's representation of the local device info; + // NULL if the device info is unavailable. + // The returned object is fully owned by LocalDeviceInfoProvider (must not + // be freed by the caller). It remains valid until LocalDeviceInfoProvider + // is destroyed. + virtual const DeviceInfo* GetLocalDeviceInfo() const = 0; + + // Returns a GUID string used for creation of the machine tag for + // this local session; an empty sting if LocalDeviceInfoProvider hasn't been + // initialized yet. + virtual std::string GetLocalSyncCacheGUID() const = 0; + + // Starts initializing local device info. + virtual void Initialize( + const std::string& cache_guid, + const std::string& signin_scoped_device_id) = 0; + + // Registers a callback to be called when local device info becomes available. + // The callback will remain registered until the + // returned Subscription is destroyed, which must occur before the + // CallbackList is destroyed. + virtual scoped_ptr<Subscription> RegisterOnInitializedCallback( + const base::Closure& callback) = 0; +}; + +} // namespace sync_driver + +#endif // COMPONENTS_SYNC_DRIVER_LOCAL_DEVICE_INFO_PROVIDER_H_ |