android-webview: Remove legacy crash handler (### Version)
[chromium-blink-merge.git] / chrome / browser / supervised_user / supervised_user_whitelist_service.cc
blobc8fd10415ec05ff6279b1cfb36fe76cbe86b71fd
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.
5 #include "chrome/browser/supervised_user/supervised_user_whitelist_service.h"
7 #include <string>
9 #include "base/files/file_path.h"
10 #include "base/metrics/histogram.h"
11 #include "base/metrics/user_metrics.h"
12 #include "base/metrics/user_metrics_action.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/prefs/scoped_user_pref_update.h"
15 #include "base/values.h"
16 #include "chrome/browser/component_updater/supervised_user_whitelist_installer.h"
17 #include "chrome/browser/supervised_user/supervised_user_site_list.h"
18 #include "chrome/common/pref_names.h"
19 #include "components/pref_registry/pref_registry_syncable.h"
20 #include "sync/api/sync_change.h"
21 #include "sync/api/sync_data.h"
22 #include "sync/api/sync_error.h"
23 #include "sync/api/sync_error_factory.h"
24 #include "sync/api/sync_merge_result.h"
25 #include "sync/protocol/sync.pb.h"
27 const char kName[] = "name";
29 SupervisedUserWhitelistService::SupervisedUserWhitelistService(
30 PrefService* prefs,
31 component_updater::SupervisedUserWhitelistInstaller* installer,
32 const std::string& client_id)
33 : prefs_(prefs),
34 installer_(installer),
35 client_id_(client_id),
36 weak_ptr_factory_(this) {
37 DCHECK(prefs);
40 SupervisedUserWhitelistService::~SupervisedUserWhitelistService() {
43 // static
44 void SupervisedUserWhitelistService::RegisterProfilePrefs(
45 user_prefs::PrefRegistrySyncable* registry) {
46 registry->RegisterDictionaryPref(prefs::kSupervisedUserWhitelists);
49 void SupervisedUserWhitelistService::Init() {
50 const base::DictionaryValue* whitelists =
51 prefs_->GetDictionary(prefs::kSupervisedUserWhitelists);
52 for (base::DictionaryValue::Iterator it(*whitelists); !it.IsAtEnd();
53 it.Advance()) {
54 registered_whitelists_.insert(it.key());
56 UMA_HISTOGRAM_COUNTS_100("ManagedUsers.Whitelist.Count", whitelists->size());
58 // The installer can be null in some unit tests.
59 if (!installer_)
60 return;
62 installer_->Subscribe(
63 base::Bind(&SupervisedUserWhitelistService::OnWhitelistReady,
64 weak_ptr_factory_.GetWeakPtr()));
67 void SupervisedUserWhitelistService::AddSiteListsChangedCallback(
68 const SiteListsChangedCallback& callback) {
69 site_lists_changed_callbacks_.push_back(callback);
71 std::vector<scoped_refptr<SupervisedUserSiteList>> whitelists;
72 GetLoadedWhitelists(&whitelists);
73 callback.Run(whitelists);
76 void SupervisedUserWhitelistService::LoadWhitelistForTesting(
77 const std::string& id,
78 const base::FilePath& path) {
79 bool result = registered_whitelists_.insert(id).second;
80 DCHECK(result);
81 OnWhitelistReady(id, path);
84 void SupervisedUserWhitelistService::UnloadWhitelist(const std::string& id) {
85 bool result = registered_whitelists_.erase(id) > 0u;
86 DCHECK(result);
87 loaded_whitelists_.erase(id);
88 NotifyWhitelistsChanged();
91 // static
92 syncer::SyncData SupervisedUserWhitelistService::CreateWhitelistSyncData(
93 const std::string& id,
94 const std::string& name) {
95 sync_pb::EntitySpecifics specifics;
96 sync_pb::ManagedUserWhitelistSpecifics* whitelist =
97 specifics.mutable_managed_user_whitelist();
98 whitelist->set_id(id);
99 whitelist->set_name(name);
101 return syncer::SyncData::CreateLocalData(id, name, specifics);
104 syncer::SyncMergeResult
105 SupervisedUserWhitelistService::MergeDataAndStartSyncing(
106 syncer::ModelType type,
107 const syncer::SyncDataList& initial_sync_data,
108 scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
109 scoped_ptr<syncer::SyncErrorFactory> error_handler) {
110 DCHECK_EQ(syncer::SUPERVISED_USER_WHITELISTS, type);
112 syncer::SyncChangeList change_list;
113 syncer::SyncMergeResult result(syncer::SUPERVISED_USER_WHITELISTS);
115 DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUserWhitelists);
116 base::DictionaryValue* pref_dict = update.Get();
117 result.set_num_items_before_association(pref_dict->size());
118 std::set<std::string> seen_ids;
119 int num_items_added = 0;
120 int num_items_modified = 0;
122 for (const syncer::SyncData& sync_data : initial_sync_data) {
123 DCHECK_EQ(syncer::SUPERVISED_USER_WHITELISTS, sync_data.GetDataType());
124 const sync_pb::ManagedUserWhitelistSpecifics& whitelist =
125 sync_data.GetSpecifics().managed_user_whitelist();
126 std::string id = whitelist.id();
127 std::string name = whitelist.name();
128 seen_ids.insert(id);
129 base::DictionaryValue* dict = nullptr;
130 if (pref_dict->GetDictionary(id, &dict)) {
131 std::string old_name;
132 bool result = dict->GetString(kName, &old_name);
133 DCHECK(result);
134 if (name != old_name) {
135 SetWhitelistProperties(dict, whitelist);
136 num_items_modified++;
138 } else {
139 num_items_added++;
140 AddNewWhitelist(pref_dict, whitelist);
144 std::set<std::string> ids_to_remove;
145 for (base::DictionaryValue::Iterator it(*pref_dict); !it.IsAtEnd();
146 it.Advance()) {
147 if (seen_ids.find(it.key()) == seen_ids.end())
148 ids_to_remove.insert(it.key());
151 for (const std::string& id : ids_to_remove)
152 RemoveWhitelist(pref_dict, id);
154 // Notify if whitelists have been uninstalled. We will notify about newly
155 // added whitelists later, when they are actually available
156 // (in OnWhitelistLoaded).
157 if (!ids_to_remove.empty())
158 NotifyWhitelistsChanged();
160 result.set_num_items_added(num_items_added);
161 result.set_num_items_modified(num_items_modified);
162 result.set_num_items_deleted(ids_to_remove.size());
163 result.set_num_items_after_association(pref_dict->size());
164 return result;
167 void SupervisedUserWhitelistService::StopSyncing(syncer::ModelType type) {
168 DCHECK_EQ(syncer::SUPERVISED_USER_WHITELISTS, type);
171 syncer::SyncDataList SupervisedUserWhitelistService::GetAllSyncData(
172 syncer::ModelType type) const {
173 syncer::SyncDataList sync_data;
174 const base::DictionaryValue* whitelists =
175 prefs_->GetDictionary(prefs::kSupervisedUserWhitelists);
176 for (base::DictionaryValue::Iterator it(*whitelists); !it.IsAtEnd();
177 it.Advance()) {
178 const std::string& id = it.key();
179 const base::DictionaryValue* dict = nullptr;
180 it.value().GetAsDictionary(&dict);
181 std::string name;
182 bool result = dict->GetString(kName, &name);
183 DCHECK(result);
184 sync_pb::EntitySpecifics specifics;
185 sync_pb::ManagedUserWhitelistSpecifics* whitelist =
186 specifics.mutable_managed_user_whitelist();
187 whitelist->set_id(id);
188 whitelist->set_name(name);
189 sync_data.push_back(syncer::SyncData::CreateLocalData(id, name, specifics));
191 return sync_data;
194 syncer::SyncError SupervisedUserWhitelistService::ProcessSyncChanges(
195 const tracked_objects::Location& from_here,
196 const syncer::SyncChangeList& change_list) {
197 bool whitelists_removed = false;
198 syncer::SyncError error;
199 DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUserWhitelists);
200 base::DictionaryValue* pref_dict = update.Get();
201 for (const syncer::SyncChange& sync_change : change_list) {
202 syncer::SyncData data = sync_change.sync_data();
203 DCHECK_EQ(syncer::SUPERVISED_USER_WHITELISTS, data.GetDataType());
204 const sync_pb::ManagedUserWhitelistSpecifics& whitelist =
205 data.GetSpecifics().managed_user_whitelist();
206 std::string id = whitelist.id();
207 switch (sync_change.change_type()) {
208 case syncer::SyncChange::ACTION_ADD: {
209 DCHECK(!pref_dict->HasKey(id)) << id;
210 AddNewWhitelist(pref_dict, whitelist);
211 break;
213 case syncer::SyncChange::ACTION_UPDATE: {
214 base::DictionaryValue* dict = nullptr;
215 pref_dict->GetDictionaryWithoutPathExpansion(id, &dict);
216 SetWhitelistProperties(dict, whitelist);
217 break;
219 case syncer::SyncChange::ACTION_DELETE: {
220 DCHECK(pref_dict->HasKey(id)) << id;
221 RemoveWhitelist(pref_dict, id);
222 whitelists_removed = true;
223 break;
225 case syncer::SyncChange::ACTION_INVALID: {
226 NOTREACHED();
227 break;
232 if (whitelists_removed)
233 NotifyWhitelistsChanged();
235 return error;
238 void SupervisedUserWhitelistService::AddNewWhitelist(
239 base::DictionaryValue* pref_dict,
240 const sync_pb::ManagedUserWhitelistSpecifics& whitelist) {
241 base::RecordAction(base::UserMetricsAction("ManagedUsers_Whitelist_Added"));
243 bool new_installation = true;
244 RegisterWhitelist(whitelist.id(), whitelist.name(), new_installation);
245 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
246 SetWhitelistProperties(dict.get(), whitelist);
247 pref_dict->SetWithoutPathExpansion(whitelist.id(), dict.release());
250 void SupervisedUserWhitelistService::SetWhitelistProperties(
251 base::DictionaryValue* dict,
252 const sync_pb::ManagedUserWhitelistSpecifics& whitelist) {
253 dict->SetString(kName, whitelist.name());
256 void SupervisedUserWhitelistService::RemoveWhitelist(
257 base::DictionaryValue* pref_dict,
258 const std::string& id) {
259 base::RecordAction(base::UserMetricsAction("ManagedUsers_Whitelist_Removed"));
261 pref_dict->RemoveWithoutPathExpansion(id, NULL);
262 installer_->UnregisterWhitelist(client_id_, id);
263 UnloadWhitelist(id);
266 void SupervisedUserWhitelistService::RegisterWhitelist(const std::string& id,
267 const std::string& name,
268 bool new_installation) {
269 bool result = registered_whitelists_.insert(id).second;
270 DCHECK(result);
272 installer_->RegisterWhitelist(client_id_, id, name);
275 void SupervisedUserWhitelistService::GetLoadedWhitelists(
276 std::vector<scoped_refptr<SupervisedUserSiteList>>* whitelists) {
277 for (const auto& whitelist : loaded_whitelists_)
278 whitelists->push_back(whitelist.second);
281 void SupervisedUserWhitelistService::NotifyWhitelistsChanged() {
282 std::vector<scoped_refptr<SupervisedUserSiteList>> whitelists;
283 GetLoadedWhitelists(&whitelists);
285 for (const auto& callback : site_lists_changed_callbacks_)
286 callback.Run(whitelists);
289 void SupervisedUserWhitelistService::OnWhitelistReady(
290 const std::string& id,
291 const base::FilePath& whitelist_path) {
292 // If we did not register the whitelist or it has been unregistered in the
293 // mean time, ignore it.
294 if (registered_whitelists_.count(id) == 0u)
295 return;
297 SupervisedUserSiteList::Load(
298 whitelist_path,
299 base::Bind(&SupervisedUserWhitelistService::OnWhitelistLoaded,
300 weak_ptr_factory_.GetWeakPtr(), id, base::TimeTicks::Now()));
303 void SupervisedUserWhitelistService::OnWhitelistLoaded(
304 const std::string& id,
305 base::TimeTicks start_time,
306 const scoped_refptr<SupervisedUserSiteList>& whitelist) {
307 if (!whitelist) {
308 LOG(WARNING) << "Couldn't load whitelist " << id;
309 return;
312 UMA_HISTOGRAM_TIMES("ManagedUsers.Whitelist.TotalLoadDuration",
313 base::TimeTicks::Now() - start_time);
315 // If the whitelist has been unregistered in the mean time, ignore it.
316 if (registered_whitelists_.count(id) == 0u)
317 return;
319 loaded_whitelists_[id] = whitelist;
320 NotifyWhitelistsChanged();