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
, 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()) {
78 if (incognito
&& !ext
->second
->incognito_enabled
)
81 ExtensionEntryMap::const_iterator winner
=
82 GetEffectivePrefValueController(pref_key
, incognito
, NULL
);
83 if (winner
== entries_
.end())
86 return winner
->second
->install_time
<= ext
->second
->install_time
;
89 void ExtensionPrefValueMap::ClearAllIncognitoSessionOnlyPreferences() {
90 typedef std::set
<std::string
> KeySet
;
93 ExtensionEntryMap::iterator i
;
94 for (i
= entries_
.begin(); i
!= entries_
.end(); ++i
) {
95 PrefValueMap
& inc_prefs
=
96 i
->second
->incognito_profile_preferences_session_only
;
97 PrefValueMap::iterator j
;
98 for (j
= inc_prefs
.begin(); j
!= inc_prefs
.end(); ++j
)
99 deleted_keys
.insert(j
->first
);
104 for (k
= deleted_keys
.begin(); k
!= deleted_keys
.end(); ++k
)
105 NotifyPrefValueChanged(*k
);
108 bool ExtensionPrefValueMap::DoesExtensionControlPref(
109 const std::string
& extension_id
,
110 const std::string
& pref_key
,
111 bool* from_incognito
) const {
112 bool incognito
= (from_incognito
!= NULL
);
113 ExtensionEntryMap::const_iterator winner
=
114 GetEffectivePrefValueController(pref_key
, incognito
, from_incognito
);
115 if (winner
== entries_
.end())
117 return winner
->first
== extension_id
;
120 void ExtensionPrefValueMap::RegisterExtension(const std::string
& ext_id
,
121 const base::Time
& install_time
,
123 bool is_incognito_enabled
) {
124 if (entries_
.find(ext_id
) == entries_
.end()) {
125 entries_
[ext_id
] = new ExtensionEntry
;
127 // Only update the install time if the extension is newly installed.
128 entries_
[ext_id
]->install_time
= install_time
;
131 entries_
[ext_id
]->enabled
= is_enabled
;
132 entries_
[ext_id
]->incognito_enabled
= is_incognito_enabled
;
135 void ExtensionPrefValueMap::UnregisterExtension(const std::string
& ext_id
) {
136 ExtensionEntryMap::iterator i
= entries_
.find(ext_id
);
137 if (i
== entries_
.end())
139 std::set
<std::string
> keys
; // keys set by this extension
140 GetExtensionControlledKeys(*(i
->second
), &keys
);
145 NotifyPrefValueChanged(keys
);
148 void ExtensionPrefValueMap::SetExtensionState(const std::string
& ext_id
,
150 ExtensionEntryMap::const_iterator i
= entries_
.find(ext_id
);
151 // This may happen when sync sets the extension state for an
152 // extension that is not installed.
153 if (i
== entries_
.end())
155 if (i
->second
->enabled
== is_enabled
)
157 std::set
<std::string
> keys
; // keys set by this extension
158 GetExtensionControlledKeys(*(i
->second
), &keys
);
159 i
->second
->enabled
= is_enabled
;
160 NotifyPrefValueChanged(keys
);
163 void ExtensionPrefValueMap::SetExtensionIncognitoState(
164 const std::string
& ext_id
,
165 bool is_incognito_enabled
) {
166 ExtensionEntryMap::const_iterator i
= entries_
.find(ext_id
);
167 // This may happen when sync sets the extension state for an
168 // extension that is not installed.
169 if (i
== entries_
.end())
171 if (i
->second
->incognito_enabled
== is_incognito_enabled
)
173 std::set
<std::string
> keys
; // keys set by this extension
174 GetExtensionControlledKeys(*(i
->second
), &keys
);
175 i
->second
->incognito_enabled
= is_incognito_enabled
;
176 NotifyPrefValueChanged(keys
);
179 PrefValueMap
* ExtensionPrefValueMap::GetExtensionPrefValueMap(
180 const std::string
& ext_id
,
181 ExtensionPrefsScope scope
) {
182 ExtensionEntryMap::const_iterator i
= entries_
.find(ext_id
);
183 CHECK(i
!= entries_
.end());
185 case extensions::kExtensionPrefsScopeRegular
:
186 return &(i
->second
->regular_profile_preferences
);
187 case extensions::kExtensionPrefsScopeRegularOnly
:
188 return &(i
->second
->regular_only_profile_preferences
);
189 case extensions::kExtensionPrefsScopeIncognitoPersistent
:
190 return &(i
->second
->incognito_profile_preferences_persistent
);
191 case extensions::kExtensionPrefsScopeIncognitoSessionOnly
:
192 return &(i
->second
->incognito_profile_preferences_session_only
);
198 const PrefValueMap
* ExtensionPrefValueMap::GetExtensionPrefValueMap(
199 const std::string
& ext_id
,
200 ExtensionPrefsScope scope
) const {
201 ExtensionEntryMap::const_iterator i
= entries_
.find(ext_id
);
202 CHECK(i
!= entries_
.end());
204 case extensions::kExtensionPrefsScopeRegular
:
205 return &(i
->second
->regular_profile_preferences
);
206 case extensions::kExtensionPrefsScopeRegularOnly
:
207 return &(i
->second
->regular_only_profile_preferences
);
208 case extensions::kExtensionPrefsScopeIncognitoPersistent
:
209 return &(i
->second
->incognito_profile_preferences_persistent
);
210 case extensions::kExtensionPrefsScopeIncognitoSessionOnly
:
211 return &(i
->second
->incognito_profile_preferences_session_only
);
217 void ExtensionPrefValueMap::GetExtensionControlledKeys(
218 const ExtensionEntry
& entry
,
219 std::set
<std::string
>* out
) const {
220 PrefValueMap::const_iterator i
;
222 const PrefValueMap
& regular_prefs
= entry
.regular_profile_preferences
;
223 for (i
= regular_prefs
.begin(); i
!= regular_prefs
.end(); ++i
)
224 out
->insert(i
->first
);
226 const PrefValueMap
& regular_only_prefs
=
227 entry
.regular_only_profile_preferences
;
228 for (i
= regular_only_prefs
.begin(); i
!= regular_only_prefs
.end(); ++i
)
229 out
->insert(i
->first
);
231 const PrefValueMap
& inc_prefs_pers
=
232 entry
.incognito_profile_preferences_persistent
;
233 for (i
= inc_prefs_pers
.begin(); i
!= inc_prefs_pers
.end(); ++i
)
234 out
->insert(i
->first
);
236 const PrefValueMap
& inc_prefs_session
=
237 entry
.incognito_profile_preferences_session_only
;
238 for (i
= inc_prefs_session
.begin(); i
!= inc_prefs_session
.end(); ++i
)
239 out
->insert(i
->first
);
242 const base::Value
* ExtensionPrefValueMap::GetEffectivePrefValue(
243 const std::string
& key
,
245 bool* from_incognito
) const {
246 ExtensionEntryMap::const_iterator winner
=
247 GetEffectivePrefValueController(key
, incognito
, from_incognito
);
248 if (winner
== entries_
.end())
251 const base::Value
* value
= NULL
;
252 const std::string
& ext_id
= winner
->first
;
254 // First search for incognito session only preferences.
256 DCHECK(winner
->second
->incognito_enabled
);
257 const PrefValueMap
* prefs
= GetExtensionPrefValueMap(
258 ext_id
, extensions::kExtensionPrefsScopeIncognitoSessionOnly
);
259 prefs
->GetValue(key
, &value
);
263 // If no incognito session only preference exists, fall back to persistent
264 // incognito preference.
265 prefs
= GetExtensionPrefValueMap(
267 extensions::kExtensionPrefsScopeIncognitoPersistent
);
268 prefs
->GetValue(key
, &value
);
272 // Regular-only preference.
273 const PrefValueMap
* prefs
= GetExtensionPrefValueMap(
274 ext_id
, extensions::kExtensionPrefsScopeRegularOnly
);
275 prefs
->GetValue(key
, &value
);
280 // Regular preference.
281 const PrefValueMap
* prefs
= GetExtensionPrefValueMap(
282 ext_id
, extensions::kExtensionPrefsScopeRegular
);
283 prefs
->GetValue(key
, &value
);
287 ExtensionPrefValueMap::ExtensionEntryMap::const_iterator
288 ExtensionPrefValueMap::GetEffectivePrefValueController(
289 const std::string
& key
,
291 bool* from_incognito
) const {
292 ExtensionEntryMap::const_iterator winner
= entries_
.end();
293 base::Time winners_install_time
;
295 ExtensionEntryMap::const_iterator i
;
296 for (i
= entries_
.begin(); i
!= entries_
.end(); ++i
) {
297 const std::string
& ext_id
= i
->first
;
298 const base::Time
& install_time
= i
->second
->install_time
;
299 const bool enabled
= i
->second
->enabled
;
300 const bool incognito_enabled
= i
->second
->incognito_enabled
;
304 if (install_time
< winners_install_time
)
306 if (incognito
&& !incognito_enabled
)
309 const base::Value
* value
= NULL
;
310 const PrefValueMap
* prefs
= GetExtensionPrefValueMap(
311 ext_id
, extensions::kExtensionPrefsScopeRegular
);
312 if (prefs
->GetValue(key
, &value
)) {
314 winners_install_time
= install_time
;
316 *from_incognito
= false;
320 const PrefValueMap
* prefs
= GetExtensionPrefValueMap(
321 ext_id
, extensions::kExtensionPrefsScopeRegularOnly
);
322 if (prefs
->GetValue(key
, &value
)) {
324 winners_install_time
= install_time
;
326 *from_incognito
= false;
328 // Ignore the following prefs, because they're incognito-only.
332 prefs
= GetExtensionPrefValueMap(
333 ext_id
, extensions::kExtensionPrefsScopeIncognitoPersistent
);
334 if (prefs
->GetValue(key
, &value
)) {
336 winners_install_time
= install_time
;
338 *from_incognito
= true;
341 prefs
= GetExtensionPrefValueMap(
342 ext_id
, extensions::kExtensionPrefsScopeIncognitoSessionOnly
);
343 if (prefs
->GetValue(key
, &value
)) {
345 winners_install_time
= install_time
;
347 *from_incognito
= true;
353 void ExtensionPrefValueMap::AddObserver(
354 ExtensionPrefValueMap::Observer
* observer
) {
355 observers_
.AddObserver(observer
);
357 // Collect all currently used keys and notify the new observer.
358 std::set
<std::string
> keys
;
359 ExtensionEntryMap::const_iterator i
;
360 for (i
= entries_
.begin(); i
!= entries_
.end(); ++i
)
361 GetExtensionControlledKeys(*(i
->second
), &keys
);
363 std::set
<std::string
>::const_iterator j
;
364 for (j
= keys
.begin(); j
!= keys
.end(); ++j
)
365 observer
->OnPrefValueChanged(*j
);
368 void ExtensionPrefValueMap::RemoveObserver(
369 ExtensionPrefValueMap::Observer
* observer
) {
370 observers_
.RemoveObserver(observer
);
373 std::string
ExtensionPrefValueMap::GetExtensionControllingPref(
374 const std::string
& pref_key
) const {
375 ExtensionEntryMap::const_iterator winner
=
376 GetEffectivePrefValueController(pref_key
, false, NULL
);
377 if (winner
== entries_
.end())
378 return std::string();
379 return winner
->first
;
382 void ExtensionPrefValueMap::NotifyInitializationCompleted() {
383 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer
, observers_
,
384 OnInitializationCompleted());
387 void ExtensionPrefValueMap::NotifyPrefValueChanged(
388 const std::set
<std::string
>& keys
) {
389 std::set
<std::string
>::const_iterator i
;
390 for (i
= keys
.begin(); i
!= keys
.end(); ++i
)
391 NotifyPrefValueChanged(*i
);
394 void ExtensionPrefValueMap::NotifyPrefValueChanged(const std::string
& key
) {
395 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer
, observers_
,
396 OnPrefValueChanged(key
));
399 void ExtensionPrefValueMap::NotifyOfDestruction() {
400 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer
, observers_
,
401 OnExtensionPrefValueMapDestruction());