• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "extensions/browser/extension_pref_value_map.h"
6 
7 #include "base/prefs/pref_value_map.h"
8 #include "base/stl_util.h"
9 #include "base/values.h"
10 
11 using extensions::ExtensionPrefsScope;
12 
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;
31 };
32 
ExtensionPrefValueMap()33 ExtensionPrefValueMap::ExtensionPrefValueMap() : destroyed_(false) {
34 }
35 
~ExtensionPrefValueMap()36 ExtensionPrefValueMap::~ExtensionPrefValueMap() {
37   if (!destroyed_) {
38     NotifyOfDestruction();
39     destroyed_ = true;
40   }
41   STLDeleteValues(&entries_);
42   entries_.clear();
43 }
44 
Shutdown()45 void ExtensionPrefValueMap::Shutdown() {
46   NotifyOfDestruction();
47   destroyed_ = true;
48 }
49 
SetExtensionPref(const std::string & ext_id,const std::string & key,ExtensionPrefsScope scope,base::Value * value)50 void ExtensionPrefValueMap::SetExtensionPref(const std::string& ext_id,
51                                              const std::string& key,
52                                              ExtensionPrefsScope scope,
53                                              base::Value* value) {
54   PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, scope);
55 
56   if (prefs->SetValue(key, value))
57     NotifyPrefValueChanged(key);
58 }
59 
RemoveExtensionPref(const std::string & ext_id,const std::string & key,ExtensionPrefsScope scope)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);
67 }
68 
CanExtensionControlPref(const std::string & extension_id,const std::string & pref_key,bool incognito) const69 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()) {
75     NOTREACHED();
76     return false;
77   }
78 
79   if (incognito && !ext->second->incognito_enabled)
80     return false;
81 
82   ExtensionEntryMap::const_iterator winner =
83       GetEffectivePrefValueController(pref_key, incognito, NULL);
84   if (winner == entries_.end())
85     return true;
86 
87   return winner->second->install_time <= ext->second->install_time;
88 }
89 
ClearAllIncognitoSessionOnlyPreferences()90 void ExtensionPrefValueMap::ClearAllIncognitoSessionOnlyPreferences() {
91   typedef std::set<std::string> KeySet;
92   KeySet deleted_keys;
93 
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);
101     inc_prefs.Clear();
102   }
103 
104   KeySet::iterator k;
105   for (k = deleted_keys.begin(); k != deleted_keys.end(); ++k)
106     NotifyPrefValueChanged(*k);
107 }
108 
DoesExtensionControlPref(const std::string & extension_id,const std::string & pref_key,bool * from_incognito) const109 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())
117     return false;
118   return winner->first == extension_id;
119 }
120 
RegisterExtension(const std::string & ext_id,const base::Time & install_time,bool is_enabled,bool is_incognito_enabled)121 void ExtensionPrefValueMap::RegisterExtension(const std::string& ext_id,
122                                               const base::Time& install_time,
123                                               bool is_enabled,
124                                               bool is_incognito_enabled) {
125   if (entries_.find(ext_id) == entries_.end()) {
126     entries_[ext_id] = new ExtensionEntry;
127 
128     // Only update the install time if the extension is newly installed.
129     entries_[ext_id]->install_time = install_time;
130   }
131 
132   entries_[ext_id]->enabled = is_enabled;
133   entries_[ext_id]->incognito_enabled = is_incognito_enabled;
134 }
135 
UnregisterExtension(const std::string & ext_id)136 void ExtensionPrefValueMap::UnregisterExtension(const std::string& ext_id) {
137   ExtensionEntryMap::iterator i = entries_.find(ext_id);
138   if (i == entries_.end())
139     return;
140   std::set<std::string> keys;  // keys set by this extension
141   GetExtensionControlledKeys(*(i->second), &keys);
142 
143   delete i->second;
144   entries_.erase(i);
145 
146   NotifyPrefValueChanged(keys);
147 }
148 
SetExtensionState(const std::string & ext_id,bool is_enabled)149 void ExtensionPrefValueMap::SetExtensionState(const std::string& ext_id,
150                                               bool is_enabled) {
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())
155     return;
156   if (i->second->enabled == is_enabled)
157     return;
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);
162 }
163 
SetExtensionIncognitoState(const std::string & ext_id,bool is_incognito_enabled)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())
171     return;
172   if (i->second->incognito_enabled == is_incognito_enabled)
173     return;
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);
178 }
179 
GetExtensionPrefValueMap(const std::string & ext_id,ExtensionPrefsScope scope)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());
185   switch (scope) {
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);
194   }
195   NOTREACHED();
196   return NULL;
197 }
198 
GetExtensionPrefValueMap(const std::string & ext_id,ExtensionPrefsScope scope) const199 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());
204   switch (scope) {
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);
213   }
214   NOTREACHED();
215   return NULL;
216 }
217 
GetExtensionControlledKeys(const ExtensionEntry & entry,std::set<std::string> * out) const218 void ExtensionPrefValueMap::GetExtensionControlledKeys(
219     const ExtensionEntry& entry,
220     std::set<std::string>* out) const {
221   PrefValueMap::const_iterator i;
222 
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);
226 
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);
231 
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);
236 
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);
241 }
242 
GetEffectivePrefValue(const std::string & key,bool incognito,bool * from_incognito) const243 const base::Value* ExtensionPrefValueMap::GetEffectivePrefValue(
244     const std::string& key,
245     bool incognito,
246     bool* from_incognito) const {
247   ExtensionEntryMap::const_iterator winner =
248       GetEffectivePrefValueController(key, incognito, from_incognito);
249   if (winner == entries_.end())
250     return NULL;
251 
252   const base::Value* value = NULL;
253   const std::string& ext_id = winner->first;
254 
255   // First search for incognito session only preferences.
256   if (incognito) {
257     DCHECK(winner->second->incognito_enabled);
258     const PrefValueMap* prefs = GetExtensionPrefValueMap(
259         ext_id, extensions::kExtensionPrefsScopeIncognitoSessionOnly);
260     prefs->GetValue(key, &value);
261     if (value)
262       return value;
263 
264     // If no incognito session only preference exists, fall back to persistent
265     // incognito preference.
266     prefs = GetExtensionPrefValueMap(
267         ext_id,
268         extensions::kExtensionPrefsScopeIncognitoPersistent);
269     prefs->GetValue(key, &value);
270     if (value)
271       return value;
272   } else {
273     // Regular-only preference.
274     const PrefValueMap* prefs = GetExtensionPrefValueMap(
275         ext_id, extensions::kExtensionPrefsScopeRegularOnly);
276     prefs->GetValue(key, &value);
277     if (value)
278       return value;
279   }
280 
281   // Regular preference.
282   const PrefValueMap* prefs = GetExtensionPrefValueMap(
283       ext_id, extensions::kExtensionPrefsScopeRegular);
284   prefs->GetValue(key, &value);
285   return value;
286 }
287 
288 ExtensionPrefValueMap::ExtensionEntryMap::const_iterator
GetEffectivePrefValueController(const std::string & key,bool incognito,bool * from_incognito) const289 ExtensionPrefValueMap::GetEffectivePrefValueController(
290     const std::string& key,
291     bool incognito,
292     bool* from_incognito) const {
293   ExtensionEntryMap::const_iterator winner = entries_.end();
294   base::Time winners_install_time;
295 
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;
302 
303     if (!enabled)
304       continue;
305     if (install_time < winners_install_time)
306       continue;
307     if (incognito && !incognito_enabled)
308       continue;
309 
310     const base::Value* value = NULL;
311     const PrefValueMap* prefs = GetExtensionPrefValueMap(
312         ext_id, extensions::kExtensionPrefsScopeRegular);
313     if (prefs->GetValue(key, &value)) {
314       winner = i;
315       winners_install_time = install_time;
316       if (from_incognito)
317         *from_incognito = false;
318     }
319 
320     if (!incognito) {
321       const PrefValueMap* prefs = GetExtensionPrefValueMap(
322           ext_id, extensions::kExtensionPrefsScopeRegularOnly);
323       if (prefs->GetValue(key, &value)) {
324         winner = i;
325         winners_install_time = install_time;
326         if (from_incognito)
327           *from_incognito = false;
328       }
329       // Ignore the following prefs, because they're incognito-only.
330       continue;
331     }
332 
333     prefs = GetExtensionPrefValueMap(
334         ext_id, extensions::kExtensionPrefsScopeIncognitoPersistent);
335     if (prefs->GetValue(key, &value)) {
336       winner = i;
337       winners_install_time = install_time;
338       if (from_incognito)
339         *from_incognito = true;
340     }
341 
342     prefs = GetExtensionPrefValueMap(
343         ext_id, extensions::kExtensionPrefsScopeIncognitoSessionOnly);
344     if (prefs->GetValue(key, &value)) {
345       winner = i;
346       winners_install_time = install_time;
347       if (from_incognito)
348         *from_incognito = true;
349     }
350   }
351   return winner;
352 }
353 
AddObserver(ExtensionPrefValueMap::Observer * observer)354 void ExtensionPrefValueMap::AddObserver(
355     ExtensionPrefValueMap::Observer* observer) {
356   observers_.AddObserver(observer);
357 
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);
363 
364   std::set<std::string>::const_iterator j;
365   for (j = keys.begin(); j != keys.end(); ++j)
366     observer->OnPrefValueChanged(*j);
367 }
368 
RemoveObserver(ExtensionPrefValueMap::Observer * observer)369 void ExtensionPrefValueMap::RemoveObserver(
370     ExtensionPrefValueMap::Observer* observer) {
371   observers_.RemoveObserver(observer);
372 }
373 
GetExtensionControllingPref(const std::string & pref_key) const374 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;
381 }
382 
NotifyInitializationCompleted()383 void ExtensionPrefValueMap::NotifyInitializationCompleted() {
384   FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
385                     OnInitializationCompleted());
386 }
387 
NotifyPrefValueChanged(const std::set<std::string> & keys)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);
393 }
394 
NotifyPrefValueChanged(const std::string & key)395 void ExtensionPrefValueMap::NotifyPrefValueChanged(const std::string& key) {
396   FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
397                     OnPrefValueChanged(key));
398 }
399 
NotifyOfDestruction()400 void ExtensionPrefValueMap::NotifyOfDestruction() {
401   FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
402                     OnExtensionPrefValueMapDestruction());
403 }
404