Durable Storage: Refactor browser test and test the basic "deny" flow.
[chromium-blink-merge.git] / extensions / browser / extension_pref_value_map.cc
blobfa188ce4a7fef2070d3eed181f32365bc08668de
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 "extensions/browser/extension_pref_value_map.h"
7 #include "base/prefs/pref_value_map.h"
8 #include "base/stl_util.h"
9 #include "base/values.h"
11 using extensions::ExtensionPrefsScope;
13 struct ExtensionPrefValueMap::ExtensionEntry {
14 // Installation time of the extension.
15 base::Time install_time;
16 // Whether extension is enabled in the profile.
17 bool enabled;
18 // Whether the extension has access to the incognito profile.
19 bool incognito_enabled;
20 // Extension controlled preferences for the regular profile.
21 PrefValueMap regular_profile_preferences;
22 // Extension controlled preferences that should *only* apply to the regular
23 // profile.
24 PrefValueMap regular_only_profile_preferences;
25 // Persistent extension controlled preferences for the incognito profile,
26 // empty for regular profile ExtensionPrefStore.
27 PrefValueMap incognito_profile_preferences_persistent;
28 // Session only extension controlled preferences for the incognito profile.
29 // These preferences are deleted when the incognito profile is destroyed.
30 PrefValueMap incognito_profile_preferences_session_only;
33 ExtensionPrefValueMap::ExtensionPrefValueMap() : destroyed_(false) {
36 ExtensionPrefValueMap::~ExtensionPrefValueMap() {
37 if (!destroyed_) {
38 NotifyOfDestruction();
39 destroyed_ = true;
41 STLDeleteValues(&entries_);
44 void ExtensionPrefValueMap::Shutdown() {
45 NotifyOfDestruction();
46 destroyed_ = true;
49 void ExtensionPrefValueMap::SetExtensionPref(const std::string& ext_id,
50 const std::string& key,
51 ExtensionPrefsScope scope,
52 base::Value* value) {
53 PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, scope);
55 if (prefs->SetValue(key, make_scoped_ptr(value)))
56 NotifyPrefValueChanged(key);
59 void ExtensionPrefValueMap::RemoveExtensionPref(
60 const std::string& ext_id,
61 const std::string& key,
62 ExtensionPrefsScope scope) {
63 PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, scope);
64 if (prefs->RemoveValue(key))
65 NotifyPrefValueChanged(key);
68 bool ExtensionPrefValueMap::CanExtensionControlPref(
69 const std::string& extension_id,
70 const std::string& pref_key,
71 bool incognito) const {
72 ExtensionEntryMap::const_iterator ext = entries_.find(extension_id);
73 if (ext == entries_.end()) {
74 NOTREACHED() << "Extension " << extension_id
75 << " is not registered but accesses pref " << pref_key
76 << " (incognito: " << incognito << ")."
77 << " http://crbug.com/454513";
78 return false;
81 if (incognito && !ext->second->incognito_enabled)
82 return false;
84 ExtensionEntryMap::const_iterator winner =
85 GetEffectivePrefValueController(pref_key, incognito, NULL);
86 if (winner == entries_.end())
87 return true;
89 return winner->second->install_time <= ext->second->install_time;
92 void ExtensionPrefValueMap::ClearAllIncognitoSessionOnlyPreferences() {
93 typedef std::set<std::string> KeySet;
94 KeySet deleted_keys;
96 ExtensionEntryMap::iterator i;
97 for (i = entries_.begin(); i != entries_.end(); ++i) {
98 PrefValueMap& inc_prefs =
99 i->second->incognito_profile_preferences_session_only;
100 PrefValueMap::iterator j;
101 for (j = inc_prefs.begin(); j != inc_prefs.end(); ++j)
102 deleted_keys.insert(j->first);
103 inc_prefs.Clear();
106 KeySet::iterator k;
107 for (k = deleted_keys.begin(); k != deleted_keys.end(); ++k)
108 NotifyPrefValueChanged(*k);
111 bool ExtensionPrefValueMap::DoesExtensionControlPref(
112 const std::string& extension_id,
113 const std::string& pref_key,
114 bool* from_incognito) const {
115 bool incognito = (from_incognito != NULL);
116 ExtensionEntryMap::const_iterator winner =
117 GetEffectivePrefValueController(pref_key, incognito, from_incognito);
118 if (winner == entries_.end())
119 return false;
120 return winner->first == extension_id;
123 void ExtensionPrefValueMap::RegisterExtension(const std::string& ext_id,
124 const base::Time& install_time,
125 bool is_enabled,
126 bool is_incognito_enabled) {
127 if (entries_.find(ext_id) == entries_.end()) {
128 entries_[ext_id] = new ExtensionEntry;
130 // Only update the install time if the extension is newly installed.
131 entries_[ext_id]->install_time = install_time;
134 entries_[ext_id]->enabled = is_enabled;
135 entries_[ext_id]->incognito_enabled = is_incognito_enabled;
138 void ExtensionPrefValueMap::UnregisterExtension(const std::string& ext_id) {
139 ExtensionEntryMap::iterator i = entries_.find(ext_id);
140 if (i == entries_.end())
141 return;
142 std::set<std::string> keys; // keys set by this extension
143 GetExtensionControlledKeys(*(i->second), &keys);
145 delete i->second;
146 entries_.erase(i);
148 NotifyPrefValueChanged(keys);
151 void ExtensionPrefValueMap::SetExtensionState(const std::string& ext_id,
152 bool is_enabled) {
153 ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
154 // This may happen when sync sets the extension state for an
155 // extension that is not installed.
156 if (i == entries_.end())
157 return;
158 if (i->second->enabled == is_enabled)
159 return;
160 std::set<std::string> keys; // keys set by this extension
161 GetExtensionControlledKeys(*(i->second), &keys);
162 i->second->enabled = is_enabled;
163 NotifyPrefValueChanged(keys);
166 void ExtensionPrefValueMap::SetExtensionIncognitoState(
167 const std::string& ext_id,
168 bool is_incognito_enabled) {
169 ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
170 // This may happen when sync sets the extension state for an
171 // extension that is not installed.
172 if (i == entries_.end())
173 return;
174 if (i->second->incognito_enabled == is_incognito_enabled)
175 return;
176 std::set<std::string> keys; // keys set by this extension
177 GetExtensionControlledKeys(*(i->second), &keys);
178 i->second->incognito_enabled = is_incognito_enabled;
179 NotifyPrefValueChanged(keys);
182 PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
183 const std::string& ext_id,
184 ExtensionPrefsScope scope) {
185 ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
186 CHECK(i != entries_.end());
187 switch (scope) {
188 case extensions::kExtensionPrefsScopeRegular:
189 return &(i->second->regular_profile_preferences);
190 case extensions::kExtensionPrefsScopeRegularOnly:
191 return &(i->second->regular_only_profile_preferences);
192 case extensions::kExtensionPrefsScopeIncognitoPersistent:
193 return &(i->second->incognito_profile_preferences_persistent);
194 case extensions::kExtensionPrefsScopeIncognitoSessionOnly:
195 return &(i->second->incognito_profile_preferences_session_only);
197 NOTREACHED();
198 return NULL;
201 const PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
202 const std::string& ext_id,
203 ExtensionPrefsScope scope) const {
204 ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
205 CHECK(i != entries_.end());
206 switch (scope) {
207 case extensions::kExtensionPrefsScopeRegular:
208 return &(i->second->regular_profile_preferences);
209 case extensions::kExtensionPrefsScopeRegularOnly:
210 return &(i->second->regular_only_profile_preferences);
211 case extensions::kExtensionPrefsScopeIncognitoPersistent:
212 return &(i->second->incognito_profile_preferences_persistent);
213 case extensions::kExtensionPrefsScopeIncognitoSessionOnly:
214 return &(i->second->incognito_profile_preferences_session_only);
216 NOTREACHED();
217 return NULL;
220 void ExtensionPrefValueMap::GetExtensionControlledKeys(
221 const ExtensionEntry& entry,
222 std::set<std::string>* out) const {
223 PrefValueMap::const_iterator i;
225 const PrefValueMap& regular_prefs = entry.regular_profile_preferences;
226 for (i = regular_prefs.begin(); i != regular_prefs.end(); ++i)
227 out->insert(i->first);
229 const PrefValueMap& regular_only_prefs =
230 entry.regular_only_profile_preferences;
231 for (i = regular_only_prefs.begin(); i != regular_only_prefs.end(); ++i)
232 out->insert(i->first);
234 const PrefValueMap& inc_prefs_pers =
235 entry.incognito_profile_preferences_persistent;
236 for (i = inc_prefs_pers.begin(); i != inc_prefs_pers.end(); ++i)
237 out->insert(i->first);
239 const PrefValueMap& inc_prefs_session =
240 entry.incognito_profile_preferences_session_only;
241 for (i = inc_prefs_session.begin(); i != inc_prefs_session.end(); ++i)
242 out->insert(i->first);
245 const base::Value* ExtensionPrefValueMap::GetEffectivePrefValue(
246 const std::string& key,
247 bool incognito,
248 bool* from_incognito) const {
249 ExtensionEntryMap::const_iterator winner =
250 GetEffectivePrefValueController(key, incognito, from_incognito);
251 if (winner == entries_.end())
252 return NULL;
254 const base::Value* value = NULL;
255 const std::string& ext_id = winner->first;
257 // First search for incognito session only preferences.
258 if (incognito) {
259 DCHECK(winner->second->incognito_enabled);
260 const PrefValueMap* prefs = GetExtensionPrefValueMap(
261 ext_id, extensions::kExtensionPrefsScopeIncognitoSessionOnly);
262 prefs->GetValue(key, &value);
263 if (value)
264 return value;
266 // If no incognito session only preference exists, fall back to persistent
267 // incognito preference.
268 prefs = GetExtensionPrefValueMap(
269 ext_id,
270 extensions::kExtensionPrefsScopeIncognitoPersistent);
271 prefs->GetValue(key, &value);
272 if (value)
273 return value;
274 } else {
275 // Regular-only preference.
276 const PrefValueMap* prefs = GetExtensionPrefValueMap(
277 ext_id, extensions::kExtensionPrefsScopeRegularOnly);
278 prefs->GetValue(key, &value);
279 if (value)
280 return value;
283 // Regular preference.
284 const PrefValueMap* prefs = GetExtensionPrefValueMap(
285 ext_id, extensions::kExtensionPrefsScopeRegular);
286 prefs->GetValue(key, &value);
287 return value;
290 ExtensionPrefValueMap::ExtensionEntryMap::const_iterator
291 ExtensionPrefValueMap::GetEffectivePrefValueController(
292 const std::string& key,
293 bool incognito,
294 bool* from_incognito) const {
295 ExtensionEntryMap::const_iterator winner = entries_.end();
296 base::Time winners_install_time;
298 ExtensionEntryMap::const_iterator i;
299 for (i = entries_.begin(); i != entries_.end(); ++i) {
300 const std::string& ext_id = i->first;
301 const base::Time& install_time = i->second->install_time;
302 const bool enabled = i->second->enabled;
303 const bool incognito_enabled = i->second->incognito_enabled;
305 if (!enabled)
306 continue;
307 if (install_time < winners_install_time)
308 continue;
309 if (incognito && !incognito_enabled)
310 continue;
312 const base::Value* value = NULL;
313 const PrefValueMap* prefs = GetExtensionPrefValueMap(
314 ext_id, extensions::kExtensionPrefsScopeRegular);
315 if (prefs->GetValue(key, &value)) {
316 winner = i;
317 winners_install_time = install_time;
318 if (from_incognito)
319 *from_incognito = false;
322 if (!incognito) {
323 const PrefValueMap* prefs = GetExtensionPrefValueMap(
324 ext_id, extensions::kExtensionPrefsScopeRegularOnly);
325 if (prefs->GetValue(key, &value)) {
326 winner = i;
327 winners_install_time = install_time;
328 if (from_incognito)
329 *from_incognito = false;
331 // Ignore the following prefs, because they're incognito-only.
332 continue;
335 prefs = GetExtensionPrefValueMap(
336 ext_id, extensions::kExtensionPrefsScopeIncognitoPersistent);
337 if (prefs->GetValue(key, &value)) {
338 winner = i;
339 winners_install_time = install_time;
340 if (from_incognito)
341 *from_incognito = true;
344 prefs = GetExtensionPrefValueMap(
345 ext_id, extensions::kExtensionPrefsScopeIncognitoSessionOnly);
346 if (prefs->GetValue(key, &value)) {
347 winner = i;
348 winners_install_time = install_time;
349 if (from_incognito)
350 *from_incognito = true;
353 return winner;
356 void ExtensionPrefValueMap::AddObserver(
357 ExtensionPrefValueMap::Observer* observer) {
358 observers_.AddObserver(observer);
360 // Collect all currently used keys and notify the new observer.
361 std::set<std::string> keys;
362 ExtensionEntryMap::const_iterator i;
363 for (i = entries_.begin(); i != entries_.end(); ++i)
364 GetExtensionControlledKeys(*(i->second), &keys);
366 std::set<std::string>::const_iterator j;
367 for (j = keys.begin(); j != keys.end(); ++j)
368 observer->OnPrefValueChanged(*j);
371 void ExtensionPrefValueMap::RemoveObserver(
372 ExtensionPrefValueMap::Observer* observer) {
373 observers_.RemoveObserver(observer);
376 std::string ExtensionPrefValueMap::GetExtensionControllingPref(
377 const std::string& pref_key) const {
378 ExtensionEntryMap::const_iterator winner =
379 GetEffectivePrefValueController(pref_key, false, NULL);
380 if (winner == entries_.end())
381 return std::string();
382 return winner->first;
385 void ExtensionPrefValueMap::NotifyInitializationCompleted() {
386 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
387 OnInitializationCompleted());
390 void ExtensionPrefValueMap::NotifyPrefValueChanged(
391 const std::set<std::string>& keys) {
392 std::set<std::string>::const_iterator i;
393 for (i = keys.begin(); i != keys.end(); ++i)
394 NotifyPrefValueChanged(*i);
397 void ExtensionPrefValueMap::NotifyPrefValueChanged(const std::string& key) {
398 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
399 OnPrefValueChanged(key));
402 void ExtensionPrefValueMap::NotifyOfDestruction() {
403 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
404 OnExtensionPrefValueMapDestruction());