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_
);
45 void ExtensionPrefValueMap::Shutdown() {
46 NotifyOfDestruction();
50 void ExtensionPrefValueMap::SetExtensionPref(const std::string
& ext_id
,
51 const std::string
& key
,
52 ExtensionPrefsScope scope
,
54 PrefValueMap
* prefs
= GetExtensionPrefValueMap(ext_id
, scope
);
56 if (prefs
->SetValue(key
, value
))
57 NotifyPrefValueChanged(key
);
60 void ExtensionPrefValueMap::RemoveExtensionPref(
61 const std::string
& ext_id
,
62 const std::string
& key
,
63 ExtensionPrefsScope scope
) {
64 PrefValueMap
* prefs
= GetExtensionPrefValueMap(ext_id
, scope
);
65 if (prefs
->RemoveValue(key
))
66 NotifyPrefValueChanged(key
);
69 bool ExtensionPrefValueMap::CanExtensionControlPref(
70 const std::string
& extension_id
,
71 const std::string
& pref_key
,
72 bool incognito
) const {
73 ExtensionEntryMap::const_iterator ext
= entries_
.find(extension_id
);
74 if (ext
== entries_
.end()) {
79 if (incognito
&& !ext
->second
->incognito_enabled
)
82 ExtensionEntryMap::const_iterator winner
=
83 GetEffectivePrefValueController(pref_key
, incognito
, NULL
);
84 if (winner
== entries_
.end())
87 return winner
->second
->install_time
<= ext
->second
->install_time
;
90 void ExtensionPrefValueMap::ClearAllIncognitoSessionOnlyPreferences() {
91 typedef std::set
<std::string
> KeySet
;
94 ExtensionEntryMap::iterator i
;
95 for (i
= entries_
.begin(); i
!= entries_
.end(); ++i
) {
96 PrefValueMap
& inc_prefs
=
97 i
->second
->incognito_profile_preferences_session_only
;
98 PrefValueMap::iterator j
;
99 for (j
= inc_prefs
.begin(); j
!= inc_prefs
.end(); ++j
)
100 deleted_keys
.insert(j
->first
);
105 for (k
= deleted_keys
.begin(); k
!= deleted_keys
.end(); ++k
)
106 NotifyPrefValueChanged(*k
);
109 bool ExtensionPrefValueMap::DoesExtensionControlPref(
110 const std::string
& extension_id
,
111 const std::string
& pref_key
,
112 bool* from_incognito
) const {
113 bool incognito
= (from_incognito
!= NULL
);
114 ExtensionEntryMap::const_iterator winner
=
115 GetEffectivePrefValueController(pref_key
, incognito
, from_incognito
);
116 if (winner
== entries_
.end())
118 return winner
->first
== extension_id
;
121 void ExtensionPrefValueMap::RegisterExtension(const std::string
& ext_id
,
122 const base::Time
& install_time
,
124 bool is_incognito_enabled
) {
125 if (entries_
.find(ext_id
) == entries_
.end()) {
126 entries_
[ext_id
] = new ExtensionEntry
;
128 // Only update the install time if the extension is newly installed.
129 entries_
[ext_id
]->install_time
= install_time
;
132 entries_
[ext_id
]->enabled
= is_enabled
;
133 entries_
[ext_id
]->incognito_enabled
= is_incognito_enabled
;
136 void ExtensionPrefValueMap::UnregisterExtension(const std::string
& ext_id
) {
137 ExtensionEntryMap::iterator i
= entries_
.find(ext_id
);
138 if (i
== entries_
.end())
140 std::set
<std::string
> keys
; // keys set by this extension
141 GetExtensionControlledKeys(*(i
->second
), &keys
);
146 NotifyPrefValueChanged(keys
);
149 void ExtensionPrefValueMap::SetExtensionState(const std::string
& ext_id
,
151 ExtensionEntryMap::const_iterator i
= entries_
.find(ext_id
);
152 // This may happen when sync sets the extension state for an
153 // extension that is not installed.
154 if (i
== entries_
.end())
156 if (i
->second
->enabled
== is_enabled
)
158 std::set
<std::string
> keys
; // keys set by this extension
159 GetExtensionControlledKeys(*(i
->second
), &keys
);
160 i
->second
->enabled
= is_enabled
;
161 NotifyPrefValueChanged(keys
);
164 void ExtensionPrefValueMap::SetExtensionIncognitoState(
165 const std::string
& ext_id
,
166 bool is_incognito_enabled
) {
167 ExtensionEntryMap::const_iterator i
= entries_
.find(ext_id
);
168 // This may happen when sync sets the extension state for an
169 // extension that is not installed.
170 if (i
== entries_
.end())
172 if (i
->second
->incognito_enabled
== is_incognito_enabled
)
174 std::set
<std::string
> keys
; // keys set by this extension
175 GetExtensionControlledKeys(*(i
->second
), &keys
);
176 i
->second
->incognito_enabled
= is_incognito_enabled
;
177 NotifyPrefValueChanged(keys
);
180 PrefValueMap
* ExtensionPrefValueMap::GetExtensionPrefValueMap(
181 const std::string
& ext_id
,
182 ExtensionPrefsScope scope
) {
183 ExtensionEntryMap::const_iterator i
= entries_
.find(ext_id
);
184 CHECK(i
!= entries_
.end());
186 case extensions::kExtensionPrefsScopeRegular
:
187 return &(i
->second
->regular_profile_preferences
);
188 case extensions::kExtensionPrefsScopeRegularOnly
:
189 return &(i
->second
->regular_only_profile_preferences
);
190 case extensions::kExtensionPrefsScopeIncognitoPersistent
:
191 return &(i
->second
->incognito_profile_preferences_persistent
);
192 case extensions::kExtensionPrefsScopeIncognitoSessionOnly
:
193 return &(i
->second
->incognito_profile_preferences_session_only
);
199 const PrefValueMap
* ExtensionPrefValueMap::GetExtensionPrefValueMap(
200 const std::string
& ext_id
,
201 ExtensionPrefsScope scope
) const {
202 ExtensionEntryMap::const_iterator i
= entries_
.find(ext_id
);
203 CHECK(i
!= entries_
.end());
205 case extensions::kExtensionPrefsScopeRegular
:
206 return &(i
->second
->regular_profile_preferences
);
207 case extensions::kExtensionPrefsScopeRegularOnly
:
208 return &(i
->second
->regular_only_profile_preferences
);
209 case extensions::kExtensionPrefsScopeIncognitoPersistent
:
210 return &(i
->second
->incognito_profile_preferences_persistent
);
211 case extensions::kExtensionPrefsScopeIncognitoSessionOnly
:
212 return &(i
->second
->incognito_profile_preferences_session_only
);
218 void ExtensionPrefValueMap::GetExtensionControlledKeys(
219 const ExtensionEntry
& entry
,
220 std::set
<std::string
>* out
) const {
221 PrefValueMap::const_iterator i
;
223 const PrefValueMap
& regular_prefs
= entry
.regular_profile_preferences
;
224 for (i
= regular_prefs
.begin(); i
!= regular_prefs
.end(); ++i
)
225 out
->insert(i
->first
);
227 const PrefValueMap
& regular_only_prefs
=
228 entry
.regular_only_profile_preferences
;
229 for (i
= regular_only_prefs
.begin(); i
!= regular_only_prefs
.end(); ++i
)
230 out
->insert(i
->first
);
232 const PrefValueMap
& inc_prefs_pers
=
233 entry
.incognito_profile_preferences_persistent
;
234 for (i
= inc_prefs_pers
.begin(); i
!= inc_prefs_pers
.end(); ++i
)
235 out
->insert(i
->first
);
237 const PrefValueMap
& inc_prefs_session
=
238 entry
.incognito_profile_preferences_session_only
;
239 for (i
= inc_prefs_session
.begin(); i
!= inc_prefs_session
.end(); ++i
)
240 out
->insert(i
->first
);
243 const base::Value
* ExtensionPrefValueMap::GetEffectivePrefValue(
244 const std::string
& key
,
246 bool* from_incognito
) const {
247 ExtensionEntryMap::const_iterator winner
=
248 GetEffectivePrefValueController(key
, incognito
, from_incognito
);
249 if (winner
== entries_
.end())
252 const base::Value
* value
= NULL
;
253 const std::string
& ext_id
= winner
->first
;
255 // First search for incognito session only preferences.
257 DCHECK(winner
->second
->incognito_enabled
);
258 const PrefValueMap
* prefs
= GetExtensionPrefValueMap(
259 ext_id
, extensions::kExtensionPrefsScopeIncognitoSessionOnly
);
260 prefs
->GetValue(key
, &value
);
264 // If no incognito session only preference exists, fall back to persistent
265 // incognito preference.
266 prefs
= GetExtensionPrefValueMap(
268 extensions::kExtensionPrefsScopeIncognitoPersistent
);
269 prefs
->GetValue(key
, &value
);
273 // Regular-only preference.
274 const PrefValueMap
* prefs
= GetExtensionPrefValueMap(
275 ext_id
, extensions::kExtensionPrefsScopeRegularOnly
);
276 prefs
->GetValue(key
, &value
);
281 // Regular preference.
282 const PrefValueMap
* prefs
= GetExtensionPrefValueMap(
283 ext_id
, extensions::kExtensionPrefsScopeRegular
);
284 prefs
->GetValue(key
, &value
);
288 ExtensionPrefValueMap::ExtensionEntryMap::const_iterator
289 ExtensionPrefValueMap::GetEffectivePrefValueController(
290 const std::string
& key
,
292 bool* from_incognito
) const {
293 ExtensionEntryMap::const_iterator winner
= entries_
.end();
294 base::Time winners_install_time
;
296 ExtensionEntryMap::const_iterator i
;
297 for (i
= entries_
.begin(); i
!= entries_
.end(); ++i
) {
298 const std::string
& ext_id
= i
->first
;
299 const base::Time
& install_time
= i
->second
->install_time
;
300 const bool enabled
= i
->second
->enabled
;
301 const bool incognito_enabled
= i
->second
->incognito_enabled
;
305 if (install_time
< winners_install_time
)
307 if (incognito
&& !incognito_enabled
)
310 const base::Value
* value
= NULL
;
311 const PrefValueMap
* prefs
= GetExtensionPrefValueMap(
312 ext_id
, extensions::kExtensionPrefsScopeRegular
);
313 if (prefs
->GetValue(key
, &value
)) {
315 winners_install_time
= install_time
;
317 *from_incognito
= false;
321 const PrefValueMap
* prefs
= GetExtensionPrefValueMap(
322 ext_id
, extensions::kExtensionPrefsScopeRegularOnly
);
323 if (prefs
->GetValue(key
, &value
)) {
325 winners_install_time
= install_time
;
327 *from_incognito
= false;
329 // Ignore the following prefs, because they're incognito-only.
333 prefs
= GetExtensionPrefValueMap(
334 ext_id
, extensions::kExtensionPrefsScopeIncognitoPersistent
);
335 if (prefs
->GetValue(key
, &value
)) {
337 winners_install_time
= install_time
;
339 *from_incognito
= true;
342 prefs
= GetExtensionPrefValueMap(
343 ext_id
, extensions::kExtensionPrefsScopeIncognitoSessionOnly
);
344 if (prefs
->GetValue(key
, &value
)) {
346 winners_install_time
= install_time
;
348 *from_incognito
= true;
354 void ExtensionPrefValueMap::AddObserver(
355 ExtensionPrefValueMap::Observer
* observer
) {
356 observers_
.AddObserver(observer
);
358 // Collect all currently used keys and notify the new observer.
359 std::set
<std::string
> keys
;
360 ExtensionEntryMap::const_iterator i
;
361 for (i
= entries_
.begin(); i
!= entries_
.end(); ++i
)
362 GetExtensionControlledKeys(*(i
->second
), &keys
);
364 std::set
<std::string
>::const_iterator j
;
365 for (j
= keys
.begin(); j
!= keys
.end(); ++j
)
366 observer
->OnPrefValueChanged(*j
);
369 void ExtensionPrefValueMap::RemoveObserver(
370 ExtensionPrefValueMap::Observer
* observer
) {
371 observers_
.RemoveObserver(observer
);
374 std::string
ExtensionPrefValueMap::GetExtensionControllingPref(
375 const std::string
& pref_key
) const {
376 ExtensionEntryMap::const_iterator winner
=
377 GetEffectivePrefValueController(pref_key
, false, NULL
);
378 if (winner
== entries_
.end())
379 return std::string();
380 return winner
->first
;
383 void ExtensionPrefValueMap::NotifyInitializationCompleted() {
384 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer
, observers_
,
385 OnInitializationCompleted());
388 void ExtensionPrefValueMap::NotifyPrefValueChanged(
389 const std::set
<std::string
>& keys
) {
390 std::set
<std::string
>::const_iterator i
;
391 for (i
= keys
.begin(); i
!= keys
.end(); ++i
)
392 NotifyPrefValueChanged(*i
);
395 void ExtensionPrefValueMap::NotifyPrefValueChanged(const std::string
& key
) {
396 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer
, observers_
,
397 OnPrefValueChanged(key
));
400 void ExtensionPrefValueMap::NotifyOfDestruction() {
401 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer
, observers_
,
402 OnExtensionPrefValueMapDestruction());