15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/supervised_user/supervised_user_shared_settings_service.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/json/json_reader.h" 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/json/json_writer.h" 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/prefs/pref_service.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/values.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/pref_names.h" 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "sync/api/sync_change.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "sync/api/sync_data.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "sync/api/sync_error.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "sync/api/sync_error_factory.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "sync/api/sync_merge_result.h" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "sync/protocol/sync.pb.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::DictionaryValue; 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::Value; 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using syncer::ModelType; 24116680a4aac90f2aa7413d9095a592090648e557Ben Murdochusing syncer::SUPERVISED_USER_SHARED_SETTINGS; 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using syncer::SyncChange; 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using syncer::SyncChangeList; 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using syncer::SyncChangeProcessor; 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using syncer::SyncData; 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using syncer::SyncDataList; 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using syncer::SyncError; 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using syncer::SyncErrorFactory; 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using syncer::SyncMergeResult; 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kAcknowledged[] = "acknowledged"; 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kValue[] = "value"; 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)DictionaryValue* FindOrCreateDictionary(DictionaryValue* parent, 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& key) { 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DictionaryValue* dict = NULL; 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!parent->GetDictionaryWithoutPathExpansion(key, &dict)) { 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dict = new DictionaryValue; 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) parent->SetWithoutPathExpansion(key, dict); 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return dict; 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class ScopedSupervisedUserSharedSettingsUpdate { 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedSupervisedUserSharedSettingsUpdate(PrefService* prefs, 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& su_id) 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : update_(prefs, prefs::kSupervisedUserSharedSettings), su_id_(su_id) { 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(!su_id.empty()); 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // A supervised user can only modify their own settings. 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string id = prefs->GetString(prefs::kSupervisedUserId); 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(id.empty() || id == su_id); 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DictionaryValue* Get() { 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return FindOrCreateDictionary(update_.Get(), su_id_); 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DictionaryPrefUpdate update_; 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string su_id_; 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SyncData CreateSyncDataForValue( 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& su_id, 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& key, 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const Value& dict_value) { 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const DictionaryValue* dict = NULL; 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!dict_value.GetAsDictionary(&dict)) 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return SyncData(); 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const Value* value = NULL; 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!dict->Get(kValue, &value)) 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return SyncData(); 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool acknowledged = false; 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dict->GetBoolean(kAcknowledged, &acknowledged); 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return SupervisedUserSharedSettingsService::CreateSyncDataForSetting( 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) su_id, key, *value, acknowledged); 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SupervisedUserSharedSettingsService::SupervisedUserSharedSettingsService( 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PrefService* prefs) 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : prefs_(prefs) {} 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SupervisedUserSharedSettingsService::~SupervisedUserSharedSettingsService() {} 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSharedSettingsService::SetValueInternal( 99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& su_id, 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& key, 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const Value& value, 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool acknowledged) { 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedSupervisedUserSharedSettingsUpdate update(prefs_, su_id); 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DictionaryValue* update_dict = update.Get(); 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DictionaryValue* dict = NULL; 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool has_key = update_dict->GetDictionaryWithoutPathExpansion(key, &dict); 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!has_key) { 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dict = new DictionaryValue; 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) update_dict->SetWithoutPathExpansion(key, dict); 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dict->SetWithoutPathExpansion(kValue, value.DeepCopy()); 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dict->SetBooleanWithoutPathExpansion(kAcknowledged, acknowledged); 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!sync_processor_) 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SyncData data = CreateSyncDataForSetting(su_id, key, value, acknowledged); 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncChange::SyncChangeType change_type = 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) has_key ? SyncChange::ACTION_UPDATE : SyncChange::ACTION_ADD; 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncChangeList changes; 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) changes.push_back(SyncChange(FROM_HERE, change_type, data)); 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, changes); 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!error.IsSet()) << error.ToString(); 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const Value* SupervisedUserSharedSettingsService::GetValue( 128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& su_id, 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& key) { 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const DictionaryValue* data = 131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) prefs_->GetDictionary(prefs::kSupervisedUserSharedSettings); 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const DictionaryValue* dict = NULL; 133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!data->GetDictionaryWithoutPathExpansion(su_id, &dict)) 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const DictionaryValue* settings = NULL; 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!dict->GetDictionaryWithoutPathExpansion(key, &settings)) 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const Value* value = NULL; 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!settings->GetWithoutPathExpansion(kValue, &value)) 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return value; 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSharedSettingsService::SetValue( 148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& su_id, 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& key, 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const Value& value) { 151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SetValueInternal(su_id, key, value, true); 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)scoped_ptr< 155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SupervisedUserSharedSettingsService::ChangeCallbackList::Subscription> 156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SupervisedUserSharedSettingsService::Subscribe( 157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const SupervisedUserSharedSettingsService::ChangeCallback& cb) { 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return callbacks_.Add(cb); 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSharedSettingsService::RegisterProfilePrefs( 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_prefs::PrefRegistrySyncable* registry) { 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) registry->RegisterDictionaryPref( 165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) prefs::kSupervisedUserSharedSettings, 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SyncData SupervisedUserSharedSettingsService::CreateSyncDataForSetting( 171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& su_id, 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& key, 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const Value& value, 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool acknowledged) { 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string json_value; 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::JSONWriter::Write(&value, &json_value); 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ::sync_pb::EntitySpecifics specifics; 178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) specifics.mutable_managed_user_shared_setting()->set_mu_id(su_id); 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) specifics.mutable_managed_user_shared_setting()->set_key(key); 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) specifics.mutable_managed_user_shared_setting()->set_value(json_value); 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) specifics.mutable_managed_user_shared_setting()->set_acknowledged( 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) acknowledged); 183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string title = su_id + ":" + key; 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return SyncData::CreateLocalData(title, title, specifics); 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSharedSettingsService::Shutdown() {} 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)syncer::SyncMergeResult 190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SupervisedUserSharedSettingsService::MergeDataAndStartSyncing( 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) syncer::ModelType type, 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const syncer::SyncDataList& initial_sync_data, 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<syncer::SyncChangeProcessor> sync_processor, 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<syncer::SyncErrorFactory> error_handler) { 195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_EQ(SUPERVISED_USER_SHARED_SETTINGS, type); 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_processor_ = sync_processor.Pass(); 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) error_handler_ = error_handler.Pass(); 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // We keep a map from MU ID to the set of keys that we have seen in the 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // initial sync data. 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::map<std::string, std::set<std::string> > seen_keys; 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Iterate over all initial sync data, and update it locally. This means that 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the value from the server always wins over a local value. 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (SyncDataList::const_iterator it = initial_sync_data.begin(); 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != initial_sync_data.end(); 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it) { 208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_EQ(SUPERVISED_USER_SHARED_SETTINGS, it->GetDataType()); 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ::sync_pb::ManagedUserSharedSettingSpecifics& 210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) supervised_user_shared_setting = 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it->GetSpecifics().managed_user_shared_setting(); 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<Value> value( 213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::JSONReader::Read(supervised_user_shared_setting.value())); 214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& su_id = supervised_user_shared_setting.mu_id(); 215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedSupervisedUserSharedSettingsUpdate update(prefs_, su_id); 216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& key = supervised_user_shared_setting.key(); 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DictionaryValue* dict = FindOrCreateDictionary(update.Get(), key); 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dict->SetWithoutPathExpansion(kValue, value.release()); 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Every setting we get from the server should have the acknowledged flag 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // set. 222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(supervised_user_shared_setting.acknowledged()); 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dict->SetBooleanWithoutPathExpansion( 224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) kAcknowledged, supervised_user_shared_setting.acknowledged()); 225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) callbacks_.Notify(su_id, key); 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) seen_keys[su_id].insert(key); 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Iterate over all settings that we have locally, which includes settings 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // that were just synced down. We filter those out using |seen_keys|. 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncChangeList change_list; 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const DictionaryValue* all_settings = 234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) prefs_->GetDictionary(prefs::kSupervisedUserSharedSettings); 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (DictionaryValue::Iterator it(*all_settings); !it.IsAtEnd(); 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it.Advance()) { 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const DictionaryValue* dict = NULL; 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool success = it.value().GetAsDictionary(&dict); 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(success); 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::set<std::string>& seen = seen_keys[it.key()]; 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (DictionaryValue::Iterator jt(*dict); !jt.IsAtEnd(); jt.Advance()) { 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // We only need to upload settings that we haven't seen in the initial 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // sync data (which means they were added locally). 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (seen.count(jt.key()) > 0) 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncData data = CreateSyncDataForValue(it.key(), jt.key(), jt.value()); 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(data.IsValid()); 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) change_list.push_back( 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncChange(FROM_HERE, SyncChange::ACTION_ADD, data)); 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SyncMergeResult result(SUPERVISED_USER_SHARED_SETTINGS); 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Process all the accumulated changes. 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (change_list.size() > 0) { 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result.set_error( 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_processor_->ProcessSyncChanges(FROM_HERE, change_list)); 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(bauerb): Statistics? 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return result; 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserSharedSettingsService::StopSyncing(syncer::ModelType type) { 267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_EQ(SUPERVISED_USER_SHARED_SETTINGS, type); 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_processor_.reset(); 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) error_handler_.reset(); 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)syncer::SyncDataList SupervisedUserSharedSettingsService::GetAllSyncData( 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) syncer::ModelType type) const { 274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_EQ(SUPERVISED_USER_SHARED_SETTINGS, type); 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncDataList data; 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const DictionaryValue* all_settings = 277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) prefs_->GetDictionary(prefs::kSupervisedUserSharedSettings); 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (DictionaryValue::Iterator it(*all_settings); !it.IsAtEnd(); 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it.Advance()) { 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const DictionaryValue* dict = NULL; 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool success = it.value().GetAsDictionary(&dict); 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(success); 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (DictionaryValue::Iterator jt(*dict); !jt.IsAtEnd(); jt.Advance()) { 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) data.push_back(CreateSyncDataForValue(it.key(), jt.key(), jt.value())); 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return data; 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)syncer::SyncError SupervisedUserSharedSettingsService::ProcessSyncChanges( 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const tracked_objects::Location& from_here, 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const syncer::SyncChangeList& change_list) { 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (SyncChangeList::const_iterator it = change_list.begin(); 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != change_list.end(); 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it) { 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncData data = it->sync_data(); 297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK_EQ(SUPERVISED_USER_SHARED_SETTINGS, data.GetDataType()); 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ::sync_pb::ManagedUserSharedSettingSpecifics& 299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) supervised_user_shared_setting = 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) data.GetSpecifics().managed_user_shared_setting(); 301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& key = supervised_user_shared_setting.key(); 302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& su_id = supervised_user_shared_setting.mu_id(); 303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedSupervisedUserSharedSettingsUpdate update(prefs_, su_id); 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DictionaryValue* update_dict = update.Get(); 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DictionaryValue* dict = NULL; 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool has_key = update_dict->GetDictionaryWithoutPathExpansion(key, &dict); 3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) switch (it->change_type()) { 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case SyncChange::ACTION_ADD: 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case SyncChange::ACTION_UPDATE: { 3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Every setting we get from the server should have the acknowledged 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // flag set. 312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(supervised_user_shared_setting.acknowledged()); 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (has_key) { 315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // If the supervised user already exists, it should be an update 316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // action. 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(SyncChange::ACTION_UPDATE, it->change_type()); 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Otherwise, it should be an add action. 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(SyncChange::ACTION_ADD, it->change_type()); 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dict = new DictionaryValue; 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) update_dict->SetWithoutPathExpansion(key, dict); 3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<Value> value( 325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::JSONReader::Read(supervised_user_shared_setting.value())); 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dict->SetWithoutPathExpansion(kValue, value.release()); 3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dict->SetBooleanWithoutPathExpansion( 328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) kAcknowledged, supervised_user_shared_setting.acknowledged()); 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case SyncChange::ACTION_DELETE: { 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (has_key) 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) update_dict->RemoveWithoutPathExpansion(key, NULL); 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED() << "Trying to delete nonexistent key " << key; 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case SyncChange::ACTION_INVALID: { 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) callbacks_.Notify(su_id, key); 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncError error; 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return error; 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 349