1 // Copyright 2014 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 #ifndef CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_SETTINGS_SERVICE_H_ 6 #define CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_SETTINGS_SERVICE_H_ 7 8 #include <memory> 9 #include <string> 10 #include <vector> 11 12 #include "base/callback.h" 13 #include "base/callback_list.h" 14 #include "base/macros.h" 15 #include "base/memory/ref_counted.h" 16 #include "base/values.h" 17 #include "chrome/browser/supervised_user/supervised_users.h" 18 #include "components/keyed_service/core/keyed_service.h" 19 #include "components/prefs/pref_store.h" 20 #include "components/sync/model/syncable_service.h" 21 22 class PersistentPrefStore; 23 24 namespace base { 25 class FilePath; 26 class SequencedTaskRunner; 27 } 28 29 // This class syncs supervised user settings from a server, which are mapped to 30 // preferences. The downloaded settings are persisted in a PrefStore (which is 31 // not directly hooked up to the PrefService; it's just used internally). 32 // Settings are key-value pairs, where the key uniquely identifies the setting. 33 // The value is a string containing a JSON serialization of an arbitrary value, 34 // which is the value of the setting. 35 // 36 // There are two kinds of settings handled by this class: Atomic and split 37 // settings. 38 // Atomic settings consist of a single key (which will be mapped to a pref key) 39 // and a single (arbitrary) value. 40 // Split settings encode a dictionary value and are stored as multiple Sync 41 // items, one for each dictionary entry. The key for each of these Sync items 42 // is the key of the split setting, followed by a separator (':') and the key 43 // for the dictionary entry. The value of the Sync item is the value of the 44 // dictionary entry. 45 // 46 // As an example, a split setting with key "Moose" and value 47 // { 48 // "foo": "bar", 49 // "baz": "blurp" 50 // } 51 // would be encoded as two sync items, one with key "Moose:foo" and value "bar", 52 // and one with key "Moose:baz" and value "blurp". 53 class SupervisedUserSettingsService : public KeyedService, 54 public syncer::SyncableService, 55 public PrefStore::Observer { 56 public: 57 // A callback whose first parameter is a dictionary containing all supervised 58 // user settings. If the dictionary is NULL, it means that the service is 59 // inactive, i.e. the user is not supervised. 60 using SettingsCallbackType = void(const base::DictionaryValue*); 61 using SettingsCallback = base::Callback<SettingsCallbackType>; 62 using SettingsCallbackList = base::CallbackList<SettingsCallbackType>; 63 64 using ShutdownCallbackType = void(); 65 using ShutdownCallback = base::Callback<ShutdownCallbackType>; 66 using ShutdownCallbackList = base::CallbackList<ShutdownCallbackType>; 67 68 SupervisedUserSettingsService(); 69 ~SupervisedUserSettingsService() override; 70 71 // Initializes the service by loading its settings from a file underneath the 72 // |profile_path|. File I/O will be serialized via the 73 // |sequenced_task_runner|. If |load_synchronously| is true, the settings will 74 // be loaded synchronously, otherwise asynchronously. 75 void Init(base::FilePath profile_path, 76 base::SequencedTaskRunner* sequenced_task_runner, 77 bool load_synchronously); 78 79 // Initializes the service by loading its settings from the |pref_store|. 80 // Use this method in tests to inject a different PrefStore than the 81 // default one. 82 void Init(scoped_refptr<PersistentPrefStore> pref_store); 83 84 // Adds a callback to be called when supervised user settings are initially 85 // available, or when they change. 86 std::unique_ptr<SettingsCallbackList::Subscription> 87 SubscribeForSettingsChange(const SettingsCallback& callback) 88 WARN_UNUSED_RESULT; 89 90 // Subscribe for a notification when the keyed service is shut down. The 91 // subscription object can be destroyed to unsubscribe. 92 std::unique_ptr<ShutdownCallbackList::Subscription> SubscribeForShutdown( 93 const ShutdownCallback& callback); 94 95 // Activates/deactivates the service. This is called by the 96 // SupervisedUserService when it is (de)activated. 97 void SetActive(bool active); 98 99 // Whether supervised user settings are available. 100 bool IsReady() const; 101 102 // Clears all supervised user settings and items. 103 void Clear(); 104 105 // Constructs a key for a split supervised user setting from a prefix and a 106 // variable key. 107 static std::string MakeSplitSettingKey(const std::string& prefix, 108 const std::string& key); 109 110 // Uploads an item to the Sync server. Items are the same data structure as 111 // supervised user settings (i.e. key-value pairs, as described at the top of 112 // the file), but they are only uploaded (whereas supervised user settings are 113 // only downloaded), and never passed to the preference system. 114 // An example of an uploaded item is an access request to a blocked URL. 115 void UploadItem(const std::string& key, std::unique_ptr<base::Value> value); 116 117 // Sets the setting with the given |key| to a copy of the given |value|. 118 void SetLocalSetting(const std::string& key, 119 std::unique_ptr<base::Value> value); 120 121 // Public for testing. 122 static syncer::SyncData CreateSyncDataForSetting(const std::string& name, 123 const base::Value& value); 124 125 // KeyedService implementation: 126 void Shutdown() override; 127 128 // SyncableService implementation: 129 void WaitUntilReadyToSync(base::OnceClosure done) override; 130 base::Optional<syncer::ModelError> MergeDataAndStartSyncing( 131 syncer::ModelType type, 132 const syncer::SyncDataList& initial_sync_data, 133 std::unique_ptr<syncer::SyncChangeProcessor> sync_processor, 134 std::unique_ptr<syncer::SyncErrorFactory> error_handler) override; 135 void StopSyncing(syncer::ModelType type) override; 136 syncer::SyncDataList GetAllSyncDataForTesting(syncer::ModelType type) const; 137 base::Optional<syncer::ModelError> ProcessSyncChanges( 138 const base::Location& from_here, 139 const syncer::SyncChangeList& change_list) override; 140 141 // PrefStore::Observer implementation: 142 void OnPrefValueChanged(const std::string& key) override; 143 void OnInitializationCompleted(bool success) override; 144 145 const base::DictionaryValue* LocalSettingsForTest() const; 146 147 // Returns the dictionary where a given Sync item should be stored, depending 148 // on whether the supervised user setting is atomic or split. In case of a 149 // split setting, the split setting prefix of |key| is removed, so that |key| 150 // can be used to update the returned dictionary. 151 base::DictionaryValue* GetDictionaryAndSplitKey(std::string* key) const; 152 153 private: 154 base::DictionaryValue* GetOrCreateDictionary(const std::string& key) const; 155 base::DictionaryValue* GetAtomicSettings() const; 156 base::DictionaryValue* GetSplitSettings() const; 157 base::DictionaryValue* GetQueuedItems() const; 158 159 // Returns a dictionary with all supervised user settings if the service is 160 // active, or NULL otherwise. 161 std::unique_ptr<base::DictionaryValue> GetSettings(); 162 163 // Sends the settings to all subscribers. This method should be called by the 164 // subclass whenever the settings change. 165 void InformSubscribers(); 166 167 void PushItemToSync(const std::string& key, 168 std::unique_ptr<base::Value> value); 169 170 // Used for persisting the settings. Unlike other PrefStores, this one is not 171 // directly hooked up to the PrefService. 172 scoped_refptr<PersistentPrefStore> store_; 173 174 bool active_; 175 176 bool initialization_failed_; 177 178 // Set when WaitUntilReadyToSync() is invoked before initialization completes. 179 base::OnceClosure wait_until_ready_to_sync_cb_; 180 181 // A set of local settings that are fixed and not configured remotely. 182 std::unique_ptr<base::DictionaryValue> local_settings_; 183 184 SettingsCallbackList settings_callback_list_; 185 186 ShutdownCallbackList shutdown_callback_list_; 187 188 std::unique_ptr<syncer::SyncChangeProcessor> sync_processor_; 189 std::unique_ptr<syncer::SyncErrorFactory> error_handler_; 190 191 DISALLOW_COPY_AND_ASSIGN(SupervisedUserSettingsService); 192 }; 193 194 #endif // CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_SETTINGS_SERVICE_H_ 195