// 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 "chrome/browser/extensions/api/storage/settings_sync_processor.h" #include "chrome/browser/extensions/api/storage/settings_sync_util.h" #include "content/public/browser/browser_thread.h" #include "extensions/browser/api/storage/settings_namespace.h" #include "sync/api/sync_change_processor.h" #include "sync/api/sync_data.h" #include "sync/protocol/extension_setting_specifics.pb.h" using content::BrowserThread; namespace extensions { SettingsSyncProcessor::SettingsSyncProcessor( const std::string& extension_id, syncer::ModelType type, syncer::SyncChangeProcessor* sync_processor) : extension_id_(extension_id), type_(type), sync_processor_(sync_processor), initialized_(false) { DCHECK_CURRENTLY_ON(BrowserThread::FILE); CHECK(type == syncer::EXTENSION_SETTINGS || type == syncer::APP_SETTINGS); CHECK(sync_processor); } SettingsSyncProcessor::~SettingsSyncProcessor() { DCHECK_CURRENTLY_ON(BrowserThread::FILE); } void SettingsSyncProcessor::Init(const base::DictionaryValue& initial_state) { DCHECK_CURRENTLY_ON(BrowserThread::FILE); CHECK(!initialized_) << "Init called multiple times"; for (base::DictionaryValue::Iterator i(initial_state); !i.IsAtEnd(); i.Advance()) synced_keys_.insert(i.key()); initialized_ = true; } syncer::SyncError SettingsSyncProcessor::SendChanges( const ValueStoreChangeList& changes) { DCHECK_CURRENTLY_ON(BrowserThread::FILE); CHECK(initialized_) << "Init not called"; syncer::SyncChangeList sync_changes; std::set<std::string> added_keys; std::set<std::string> deleted_keys; for (ValueStoreChangeList::const_iterator i = changes.begin(); i != changes.end(); ++i) { const std::string& key = i->key(); const base::Value* value = i->new_value(); if (value) { if (synced_keys_.count(key)) { // New value, key is synced; send ACTION_UPDATE. sync_changes.push_back(settings_sync_util::CreateUpdate( extension_id_, key, *value, type_)); } else { // New value, key is not synced; send ACTION_ADD. sync_changes.push_back(settings_sync_util::CreateAdd( extension_id_, key, *value, type_)); added_keys.insert(key); } } else { if (synced_keys_.count(key)) { // Clearing value, key is synced; send ACTION_DELETE. sync_changes.push_back(settings_sync_util::CreateDelete( extension_id_, key, type_)); deleted_keys.insert(key); } else { LOG(WARNING) << "Deleted " << key << " but not in synced_keys_"; } } } if (sync_changes.empty()) return syncer::SyncError(); syncer::SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, sync_changes); if (error.IsSet()) return error; synced_keys_.insert(added_keys.begin(), added_keys.end()); for (std::set<std::string>::iterator i = deleted_keys.begin(); i != deleted_keys.end(); ++i) { synced_keys_.erase(*i); } return syncer::SyncError(); } void SettingsSyncProcessor::NotifyChanges(const ValueStoreChangeList& changes) { DCHECK_CURRENTLY_ON(BrowserThread::FILE); CHECK(initialized_) << "Init not called"; for (ValueStoreChangeList::const_iterator i = changes.begin(); i != changes.end(); ++i) { if (i->new_value()) synced_keys_.insert(i->key()); else synced_keys_.erase(i->key()); } } } // namespace extensions