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.
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
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() {
38 NotifyOfDestruction();
41 STLDeleteValues(&entries_
);
44 void ExtensionPrefValueMap::Shutdown() {
45 NotifyOfDestruction();
49 void ExtensionPrefValueMap::SetExtensionPref(const std::string
& ext_id
,
50 const std::string
& key
,
51 ExtensionPrefsScope scope
,
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";
81 if (incognito
&& !ext
->second
->incognito_enabled
)
84 ExtensionEntryMap::const_iterator winner
=
85 GetEffectivePrefValueController(pref_key
, incognito
, NULL
);
86 if (winner
== entries_
.end())
89 return winner
->second
->install_time
<= ext
->second
->install_time
;
92 void ExtensionPrefValueMap::ClearAllIncognitoSessionOnlyPreferences() {
93 typedef std::set
<std::string
> KeySet
;
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
);
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())
120 return winner
->first
== extension_id
;
123 void ExtensionPrefValueMap::RegisterExtension(const std::string
& ext_id
,
124 const base::Time
& install_time
,
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())
142 std::set
<std::string
> keys
; // keys set by this extension
143 GetExtensionControlledKeys(*(i
->second
), &keys
);
148 NotifyPrefValueChanged(keys
);
151 void ExtensionPrefValueMap::SetExtensionState(const std::string
& ext_id
,
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())
158 if (i
->second
->enabled
== is_enabled
)
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())
174 if (i
->second
->incognito_enabled
== is_incognito_enabled
)
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());
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
);
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());
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
);
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
,
248 bool* from_incognito
) const {
249 ExtensionEntryMap::const_iterator winner
=
250 GetEffectivePrefValueController(key
, incognito
, from_incognito
);
251 if (winner
== entries_
.end())
254 const base::Value
* value
= NULL
;
255 const std::string
& ext_id
= winner
->first
;
257 // First search for incognito session only preferences.
259 DCHECK(winner
->second
->incognito_enabled
);
260 const PrefValueMap
* prefs
= GetExtensionPrefValueMap(
261 ext_id
, extensions::kExtensionPrefsScopeIncognitoSessionOnly
);
262 prefs
->GetValue(key
, &value
);
266 // If no incognito session only preference exists, fall back to persistent
267 // incognito preference.
268 prefs
= GetExtensionPrefValueMap(
270 extensions::kExtensionPrefsScopeIncognitoPersistent
);
271 prefs
->GetValue(key
, &value
);
275 // Regular-only preference.
276 const PrefValueMap
* prefs
= GetExtensionPrefValueMap(
277 ext_id
, extensions::kExtensionPrefsScopeRegularOnly
);
278 prefs
->GetValue(key
, &value
);
283 // Regular preference.
284 const PrefValueMap
* prefs
= GetExtensionPrefValueMap(
285 ext_id
, extensions::kExtensionPrefsScopeRegular
);
286 prefs
->GetValue(key
, &value
);
290 ExtensionPrefValueMap::ExtensionEntryMap::const_iterator
291 ExtensionPrefValueMap::GetEffectivePrefValueController(
292 const std::string
& key
,
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
;
307 if (install_time
< winners_install_time
)
309 if (incognito
&& !incognito_enabled
)
312 const base::Value
* value
= NULL
;
313 const PrefValueMap
* prefs
= GetExtensionPrefValueMap(
314 ext_id
, extensions::kExtensionPrefsScopeRegular
);
315 if (prefs
->GetValue(key
, &value
)) {
317 winners_install_time
= install_time
;
319 *from_incognito
= false;
323 const PrefValueMap
* prefs
= GetExtensionPrefValueMap(
324 ext_id
, extensions::kExtensionPrefsScopeRegularOnly
);
325 if (prefs
->GetValue(key
, &value
)) {
327 winners_install_time
= install_time
;
329 *from_incognito
= false;
331 // Ignore the following prefs, because they're incognito-only.
335 prefs
= GetExtensionPrefValueMap(
336 ext_id
, extensions::kExtensionPrefsScopeIncognitoPersistent
);
337 if (prefs
->GetValue(key
, &value
)) {
339 winners_install_time
= install_time
;
341 *from_incognito
= true;
344 prefs
= GetExtensionPrefValueMap(
345 ext_id
, extensions::kExtensionPrefsScopeIncognitoSessionOnly
);
346 if (prefs
->GetValue(key
, &value
)) {
348 winners_install_time
= install_time
;
350 *from_incognito
= true;
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());