15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file.
45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/sync_driver/device_info_sync_service.h"
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/stringprintf.h"
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/sync_driver/local_device_info_provider.h"
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "sync/api/sync_change.h"
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "sync/protocol/sync.pb.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "sync/util/time.h"
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace sync_driver {
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using syncer::ModelType;
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using syncer::SyncChange;
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using syncer::SyncChangeList;
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using syncer::SyncChangeProcessor;
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using syncer::SyncData;
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using syncer::SyncDataList;
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using syncer::SyncErrorFactory;
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using syncer::SyncMergeResult;
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)DeviceInfoSyncService::DeviceInfoSyncService(
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LocalDeviceInfoProvider* local_device_info_provider)
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : local_device_backup_time_(-1),
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      local_device_info_provider_(local_device_info_provider) {
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(local_device_info_provider);
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)DeviceInfoSyncService::~DeviceInfoSyncService() {
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SyncMergeResult DeviceInfoSyncService::MergeDataAndStartSyncing(
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ModelType type,
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const SyncDataList& initial_sync_data,
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scoped_ptr<SyncChangeProcessor> sync_processor,
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scoped_ptr<SyncErrorFactory> error_handler) {
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(sync_processor.get());
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(error_handler.get());
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_EQ(type, syncer::DEVICE_INFO);
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(all_data_.empty());
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  sync_processor_ = sync_processor.Pass();
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  error_handler_ = error_handler.Pass();
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Initialization should be completed before this type is enabled
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // and local device info must be available.
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const DeviceInfo* local_device_info =
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      local_device_info_provider_->GetLocalDeviceInfo();
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(local_device_info != NULL);
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Indicates whether a local device has been added or updated.
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // |change_type| defaults to ADD and might be changed to
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // UPDATE to INVALID down below if the initial data contains
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // data matching the local device ID.
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SyncChange::SyncChangeType change_type = SyncChange::ACTION_ADD;
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  size_t num_items_new = 0;
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  size_t num_items_updated = 0;
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Iterate over all initial sync data and copy it to the cache.
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (SyncDataList::const_iterator iter = initial_sync_data.begin();
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       iter != initial_sync_data.end();
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       ++iter) {
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DCHECK_EQ(syncer::DEVICE_INFO, iter->GetDataType());
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::string& id = iter->GetSpecifics().device_info().cache_guid();
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (id == local_device_info->guid()) {
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |initial_sync_data| contains data matching the local device.
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      scoped_ptr<DeviceInfo> synced_local_device_info =
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          make_scoped_ptr(CreateDeviceInfo(*iter));
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Retrieve local device backup timestamp value from the sync data.
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      bool has_synced_backup_time =
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          iter->GetSpecifics().device_info().has_backup_timestamp();
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      int64 synced_backup_time =
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          has_synced_backup_time
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              ? iter->GetSpecifics().device_info().backup_timestamp()
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              : -1;
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Overwrite |local_device_backup_time_| with this value if it
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // hasn't been set yet.
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (!has_local_device_backup_time() && has_synced_backup_time) {
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        set_local_device_backup_time(synced_backup_time);
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Store the synced device info for the local device only
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // it is the same as the local info. Otherwise store the local
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // device info and issue a change further below after finishing
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // processing the |initial_sync_data|.
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (synced_local_device_info->Equals(*local_device_info) &&
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          synced_backup_time == local_device_backup_time()) {
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        change_type = SyncChange::ACTION_INVALID;
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      } else {
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        num_items_updated++;
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        change_type = SyncChange::ACTION_UPDATE;
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        continue;
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    } else {
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // A new device that doesn't match the local device.
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      num_items_new++;
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    StoreSyncData(id, *iter);
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  syncer::SyncMergeResult result(type);
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Add SyncData for the local device if it is new or different than
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // the synced one, and also add it to the |change_list|.
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (change_type != SyncChange::ACTION_INVALID) {
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SyncData local_data = CreateLocalData(local_device_info);
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    StoreSyncData(local_device_info->guid(), local_data);
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SyncChangeList change_list;
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    change_list.push_back(SyncChange(FROM_HERE, change_type, local_data));
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    result.set_error(
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        sync_processor_->ProcessSyncChanges(FROM_HERE, change_list));
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  result.set_num_items_before_association(1);
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  result.set_num_items_after_association(all_data_.size());
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  result.set_num_items_added(num_items_new);
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  result.set_num_items_modified(num_items_updated);
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  result.set_num_items_deleted(0);
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  NotifyObservers();
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return result;
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void DeviceInfoSyncService::StopSyncing(syncer::ModelType type) {
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  all_data_.clear();
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  sync_processor_.reset();
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  error_handler_.reset();
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  clear_local_device_backup_time();
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SyncDataList DeviceInfoSyncService::GetAllSyncData(
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    syncer::ModelType type) const {
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SyncDataList list;
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (SyncDataMap::const_iterator iter = all_data_.begin();
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       iter != all_data_.end();
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       ++iter) {
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    list.push_back(iter->second);
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return list;
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)syncer::SyncError DeviceInfoSyncService::ProcessSyncChanges(
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const tracked_objects::Location& from_here,
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const SyncChangeList& change_list) {
1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  syncer::SyncError error;
1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(local_device_info_provider_->GetLocalDeviceInfo());
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const std::string& local_device_id =
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      local_device_info_provider_->GetLocalDeviceInfo()->guid();
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool has_changes = false;
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Iterate over all chanages and merge entries.
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (SyncChangeList::const_iterator iter = change_list.begin();
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       iter != change_list.end();
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       ++iter) {
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const SyncData& sync_data = iter->sync_data();
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DCHECK_EQ(syncer::DEVICE_INFO, sync_data.GetDataType());
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const std::string& client_id =
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        sync_data.GetSpecifics().device_info().cache_guid();
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Ignore device info matching the local device.
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (local_device_id == client_id) {
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      DVLOG(1) << "Ignoring sync changes for the local DEVICE_INFO";
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      continue;
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (iter->change_type() == syncer::SyncChange::ACTION_DELETE) {
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      has_changes = true;
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      DeleteSyncData(client_id);
1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } else if (iter->change_type() == syncer::SyncChange::ACTION_UPDATE ||
1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               iter->change_type() == syncer::SyncChange::ACTION_ADD) {
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      has_changes = true;
1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      StoreSyncData(client_id, sync_data);
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } else {
1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      error.Reset(FROM_HERE, "Invalid action received.", syncer::DEVICE_INFO);
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (has_changes) {
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    NotifyObservers();
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return error;
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)scoped_ptr<DeviceInfo> DeviceInfoSyncService::GetDeviceInfo(
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const std::string& client_id) const {
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SyncDataMap::const_iterator iter = all_data_.find(client_id);
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (iter == all_data_.end()) {
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return scoped_ptr<DeviceInfo>();
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return make_scoped_ptr(CreateDeviceInfo(iter->second));
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ScopedVector<DeviceInfo> DeviceInfoSyncService::GetAllDeviceInfo() const {
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ScopedVector<DeviceInfo> list;
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (SyncDataMap::const_iterator iter = all_data_.begin();
2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       iter != all_data_.end();
2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       ++iter) {
2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    list.push_back(CreateDeviceInfo(iter->second));
2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return list.Pass();
2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void DeviceInfoSyncService::AddObserver(Observer* observer) {
2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  observers_.AddObserver(observer);
2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void DeviceInfoSyncService::RemoveObserver(Observer* observer) {
2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  observers_.RemoveObserver(observer);
2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void DeviceInfoSyncService::NotifyObservers() {
2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observers_, OnDeviceInfoChange());
2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid DeviceInfoSyncService::UpdateLocalDeviceBackupTime(
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::Time backup_time) {
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  set_local_device_backup_time(syncer::TimeToProtoTime(backup_time));
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (sync_processor_.get()) {
2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Local device info must be available in advance
2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK(local_device_info_provider_->GetLocalDeviceInfo());
2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::string& local_id =
2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        local_device_info_provider_->GetLocalDeviceInfo()->guid();
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SyncDataMap::iterator iter = all_data_.find(local_id);
2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK(iter != all_data_.end());
2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    syncer::SyncData& data = iter->second;
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (UpdateBackupTime(&data)) {
2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Local device backup time has changed.
2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Push changes to the server via the |sync_processor_|.
2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      SyncChangeList change_list;
2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      change_list.push_back(SyncChange(
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data));
2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      sync_processor_->ProcessSyncChanges(FROM_HERE, change_list);
2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool DeviceInfoSyncService::UpdateBackupTime(syncer::SyncData* sync_data) {
2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(has_local_device_backup_time());
2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(sync_data->GetSpecifics().has_device_info());
2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const sync_pb::DeviceInfoSpecifics& source_specifics =
2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      sync_data->GetSpecifics().device_info();
2631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!source_specifics.has_backup_timestamp() ||
2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      source_specifics.backup_timestamp() != local_device_backup_time()) {
2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    sync_pb::EntitySpecifics entity(sync_data->GetSpecifics());
2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    entity.mutable_device_info()->set_backup_timestamp(
2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        local_device_backup_time());
2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    *sync_data = CreateLocalData(entity);
2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return true;
2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return false;
2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibase::Time DeviceInfoSyncService::GetLocalDeviceBackupTime() const {
2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return has_local_device_backup_time()
2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci             ? syncer::ProtoTimeToTime(local_device_backup_time())
2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci             : base::Time();
2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SyncData DeviceInfoSyncService::CreateLocalData(const DeviceInfo* info) {
2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  sync_pb::EntitySpecifics entity;
2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  sync_pb::DeviceInfoSpecifics& specifics = *entity.mutable_device_info();
2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  specifics.set_cache_guid(info->guid());
2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  specifics.set_client_name(info->client_name());
2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  specifics.set_chrome_version(info->chrome_version());
2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  specifics.set_sync_user_agent(info->sync_user_agent());
2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  specifics.set_device_type(info->device_type());
2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  specifics.set_signin_scoped_device_id(info->signin_scoped_device_id());
2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (has_local_device_backup_time()) {
2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    specifics.set_backup_timestamp(local_device_backup_time());
2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return CreateLocalData(entity);
2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciSyncData DeviceInfoSyncService::CreateLocalData(
3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const sync_pb::EntitySpecifics& entity) {
3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const sync_pb::DeviceInfoSpecifics& specifics = entity.device_info();
3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::string local_device_tag =
3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::StringPrintf("DeviceInfo_%s", specifics.cache_guid().c_str());
3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return SyncData::CreateLocalData(
3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      local_device_tag, specifics.client_name(), entity);
3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)DeviceInfo* DeviceInfoSyncService::CreateDeviceInfo(
3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const syncer::SyncData sync_data) {
3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const sync_pb::DeviceInfoSpecifics& specifics =
3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      sync_data.GetSpecifics().device_info();
3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return new DeviceInfo(specifics.cache_guid(),
3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        specifics.client_name(),
3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        specifics.chrome_version(),
3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        specifics.sync_user_agent(),
3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        specifics.device_type(),
3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        specifics.signin_scoped_device_id());
3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void DeviceInfoSyncService::StoreSyncData(const std::string& client_id,
3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          const SyncData& sync_data) {
3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DVLOG(1) << "Storing DEVICE_INFO for "
3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)           << sync_data.GetSpecifics().device_info().client_name()
3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)           << " with ID " << client_id;
3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  all_data_[client_id] = sync_data;
3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void DeviceInfoSyncService::DeleteSyncData(const std::string& client_id) {
3345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SyncDataMap::iterator iter = all_data_.find(client_id);
3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (iter != all_data_.end()) {
3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DVLOG(1) << "Deleting DEVICE_INFO for "
3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)             << iter->second.GetSpecifics().device_info().client_name()
3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)             << " with ID " << client_id;
3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    all_data_.erase(iter);
3405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace sync_driver
344