Home | History | Annotate | Download | only in storage
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/extensions/api/storage/settings_sync_processor.h"
      6 #include "chrome/browser/extensions/api/storage/settings_sync_util.h"
      7 #include "content/public/browser/browser_thread.h"
      8 #include "extensions/browser/api/storage/settings_namespace.h"
      9 #include "sync/api/sync_change_processor.h"
     10 #include "sync/api/sync_data.h"
     11 #include "sync/protocol/extension_setting_specifics.pb.h"
     12 
     13 using content::BrowserThread;
     14 
     15 namespace extensions {
     16 
     17 SettingsSyncProcessor::SettingsSyncProcessor(
     18     const std::string& extension_id,
     19     syncer::ModelType type,
     20     syncer::SyncChangeProcessor* sync_processor)
     21     : extension_id_(extension_id),
     22       type_(type),
     23       sync_processor_(sync_processor),
     24       initialized_(false) {
     25   DCHECK_CURRENTLY_ON(BrowserThread::FILE);
     26   CHECK(type == syncer::EXTENSION_SETTINGS || type == syncer::APP_SETTINGS);
     27   CHECK(sync_processor);
     28 }
     29 
     30 SettingsSyncProcessor::~SettingsSyncProcessor() {
     31   DCHECK_CURRENTLY_ON(BrowserThread::FILE);
     32 }
     33 
     34 void SettingsSyncProcessor::Init(const base::DictionaryValue& initial_state) {
     35   DCHECK_CURRENTLY_ON(BrowserThread::FILE);
     36   CHECK(!initialized_) << "Init called multiple times";
     37 
     38   for (base::DictionaryValue::Iterator i(initial_state); !i.IsAtEnd();
     39        i.Advance())
     40     synced_keys_.insert(i.key());
     41 
     42   initialized_ = true;
     43 }
     44 
     45 syncer::SyncError SettingsSyncProcessor::SendChanges(
     46     const ValueStoreChangeList& changes) {
     47   DCHECK_CURRENTLY_ON(BrowserThread::FILE);
     48   CHECK(initialized_) << "Init not called";
     49 
     50   syncer::SyncChangeList sync_changes;
     51   std::set<std::string> added_keys;
     52   std::set<std::string> deleted_keys;
     53 
     54   for (ValueStoreChangeList::const_iterator i = changes.begin();
     55       i != changes.end(); ++i) {
     56     const std::string& key = i->key();
     57     const base::Value* value = i->new_value();
     58     if (value) {
     59       if (synced_keys_.count(key)) {
     60         // New value, key is synced; send ACTION_UPDATE.
     61         sync_changes.push_back(settings_sync_util::CreateUpdate(
     62             extension_id_, key, *value, type_));
     63       } else {
     64         // New value, key is not synced; send ACTION_ADD.
     65         sync_changes.push_back(settings_sync_util::CreateAdd(
     66             extension_id_, key, *value, type_));
     67         added_keys.insert(key);
     68       }
     69     } else {
     70       if (synced_keys_.count(key)) {
     71         // Clearing value, key is synced; send ACTION_DELETE.
     72         sync_changes.push_back(settings_sync_util::CreateDelete(
     73             extension_id_, key, type_));
     74         deleted_keys.insert(key);
     75       } else {
     76         LOG(WARNING) << "Deleted " << key << " but not in synced_keys_";
     77       }
     78     }
     79   }
     80 
     81   if (sync_changes.empty())
     82     return syncer::SyncError();
     83 
     84   syncer::SyncError error =
     85       sync_processor_->ProcessSyncChanges(FROM_HERE, sync_changes);
     86   if (error.IsSet())
     87     return error;
     88 
     89   synced_keys_.insert(added_keys.begin(), added_keys.end());
     90   for (std::set<std::string>::iterator i = deleted_keys.begin();
     91       i != deleted_keys.end(); ++i) {
     92     synced_keys_.erase(*i);
     93   }
     94 
     95   return syncer::SyncError();
     96 }
     97 
     98 void SettingsSyncProcessor::NotifyChanges(const ValueStoreChangeList& changes) {
     99   DCHECK_CURRENTLY_ON(BrowserThread::FILE);
    100   CHECK(initialized_) << "Init not called";
    101 
    102   for (ValueStoreChangeList::const_iterator i = changes.begin();
    103       i != changes.end(); ++i) {
    104     if (i->new_value())
    105       synced_keys_.insert(i->key());
    106     else
    107       synced_keys_.erase(i->key());
    108   }
    109 }
    110 
    111 }  // namespace extensions
    112