- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / extension_pref_value_map.cc
1 // Copyright (c) 2012 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 "chrome/browser/extensions/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   // Extension controlled preferences for the regular profile.
19   PrefValueMap regular_profile_preferences;
20   // Extension controlled preferences that should *only* apply to the regular
21   // profile.
22   PrefValueMap regular_only_profile_preferences;
23   // Persistent extension controlled preferences for the incognito profile,
24   // empty for regular profile ExtensionPrefStore.
25   PrefValueMap incognito_profile_preferences_persistent;
26   // Session only extension controlled preferences for the incognito profile.
27   // These preferences are deleted when the incognito profile is destroyed.
28   PrefValueMap incognito_profile_preferences_session_only;
29 };
30
31 ExtensionPrefValueMap::ExtensionPrefValueMap() : destroyed_(false) {
32 }
33
34 ExtensionPrefValueMap::~ExtensionPrefValueMap() {
35   if (!destroyed_) {
36     NotifyOfDestruction();
37     destroyed_ = true;
38   }
39   STLDeleteValues(&entries_);
40   entries_.clear();
41 }
42
43 void ExtensionPrefValueMap::Shutdown() {
44   NotifyOfDestruction();
45   destroyed_ = true;
46 }
47
48 void ExtensionPrefValueMap::SetExtensionPref(const std::string& ext_id,
49                                              const std::string& key,
50                                              ExtensionPrefsScope scope,
51                                              Value* value) {
52   PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, scope);
53
54   if (prefs->SetValue(key, value))
55     NotifyPrefValueChanged(key);
56 }
57
58 void ExtensionPrefValueMap::RemoveExtensionPref(
59     const std::string& ext_id,
60     const std::string& key,
61     ExtensionPrefsScope scope) {
62   PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, scope);
63   if (prefs->RemoveValue(key))
64     NotifyPrefValueChanged(key);
65 }
66
67 bool ExtensionPrefValueMap::CanExtensionControlPref(
68     const std::string& extension_id,
69     const std::string& pref_key,
70     bool incognito) const {
71   ExtensionEntryMap::const_iterator ext = entries_.find(extension_id);
72   if (ext == entries_.end()) {
73     NOTREACHED();
74     return false;
75   }
76
77   ExtensionEntryMap::const_iterator winner =
78       GetEffectivePrefValueController(pref_key, incognito, NULL);
79   if (winner == entries_.end())
80     return true;
81
82   return winner->second->install_time <= ext->second->install_time;
83 }
84
85 void ExtensionPrefValueMap::ClearAllIncognitoSessionOnlyPreferences() {
86   typedef std::set<std::string> KeySet;
87   KeySet deleted_keys;
88
89   ExtensionEntryMap::iterator i;
90   for (i = entries_.begin(); i != entries_.end(); ++i) {
91     PrefValueMap& inc_prefs =
92         i->second->incognito_profile_preferences_session_only;
93     PrefValueMap::iterator j;
94     for (j = inc_prefs.begin(); j != inc_prefs.end(); ++j)
95       deleted_keys.insert(j->first);
96     inc_prefs.Clear();
97   }
98
99   KeySet::iterator k;
100   for (k = deleted_keys.begin(); k != deleted_keys.end(); ++k)
101     NotifyPrefValueChanged(*k);
102 }
103
104 bool ExtensionPrefValueMap::DoesExtensionControlPref(
105     const std::string& extension_id,
106     const std::string& pref_key,
107     bool* from_incognito) const {
108   bool incognito = (from_incognito != NULL);
109   ExtensionEntryMap::const_iterator winner =
110       GetEffectivePrefValueController(pref_key, incognito, from_incognito);
111   if (winner == entries_.end())
112     return false;
113   return winner->first == extension_id;
114 }
115
116 void ExtensionPrefValueMap::RegisterExtension(const std::string& ext_id,
117                                               const base::Time& install_time,
118                                               bool is_enabled) {
119   if (entries_.find(ext_id) == entries_.end()) {
120     entries_[ext_id] = new ExtensionEntry;
121
122     // Only update the install time if the extension is newly installed.
123     entries_[ext_id]->install_time = install_time;
124   }
125
126   entries_[ext_id]->enabled = is_enabled;
127 }
128
129 void ExtensionPrefValueMap::UnregisterExtension(const std::string& ext_id) {
130   ExtensionEntryMap::iterator i = entries_.find(ext_id);
131   if (i == entries_.end())
132     return;
133   std::set<std::string> keys;  // keys set by this extension
134   GetExtensionControlledKeys(*(i->second), &keys);
135
136   delete i->second;
137   entries_.erase(i);
138
139   NotifyPrefValueChanged(keys);
140 }
141
142 void ExtensionPrefValueMap::SetExtensionState(const std::string& ext_id,
143                                               bool is_enabled) {
144   ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
145   // This may happen when sync sets the extension state for an
146   // extension that is not installed.
147   if (i == entries_.end())
148     return;
149   if (i->second->enabled == is_enabled)
150     return;
151   std::set<std::string> keys;  // keys set by this extension
152   GetExtensionControlledKeys(*(i->second), &keys);
153   i->second->enabled = is_enabled;
154   NotifyPrefValueChanged(keys);
155 }
156
157 PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
158     const std::string& ext_id,
159     ExtensionPrefsScope scope) {
160   ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
161   CHECK(i != entries_.end());
162   switch (scope) {
163     case extensions::kExtensionPrefsScopeRegular:
164       return &(i->second->regular_profile_preferences);
165     case extensions::kExtensionPrefsScopeRegularOnly:
166       return &(i->second->regular_only_profile_preferences);
167     case extensions::kExtensionPrefsScopeIncognitoPersistent:
168       return &(i->second->incognito_profile_preferences_persistent);
169     case extensions::kExtensionPrefsScopeIncognitoSessionOnly:
170       return &(i->second->incognito_profile_preferences_session_only);
171   }
172   NOTREACHED();
173   return NULL;
174 }
175
176 const PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
177     const std::string& ext_id,
178     ExtensionPrefsScope scope) const {
179   ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
180   CHECK(i != entries_.end());
181   switch (scope) {
182     case extensions::kExtensionPrefsScopeRegular:
183       return &(i->second->regular_profile_preferences);
184     case extensions::kExtensionPrefsScopeRegularOnly:
185       return &(i->second->regular_only_profile_preferences);
186     case extensions::kExtensionPrefsScopeIncognitoPersistent:
187       return &(i->second->incognito_profile_preferences_persistent);
188     case extensions::kExtensionPrefsScopeIncognitoSessionOnly:
189       return &(i->second->incognito_profile_preferences_session_only);
190   }
191   NOTREACHED();
192   return NULL;
193 }
194
195 void ExtensionPrefValueMap::GetExtensionControlledKeys(
196     const ExtensionEntry& entry,
197     std::set<std::string>* out) const {
198   PrefValueMap::const_iterator i;
199
200   const PrefValueMap& regular_prefs = entry.regular_profile_preferences;
201   for (i = regular_prefs.begin(); i != regular_prefs.end(); ++i)
202     out->insert(i->first);
203
204   const PrefValueMap& regular_only_prefs =
205       entry.regular_only_profile_preferences;
206   for (i = regular_only_prefs.begin(); i != regular_only_prefs.end(); ++i)
207     out->insert(i->first);
208
209   const PrefValueMap& inc_prefs_pers =
210       entry.incognito_profile_preferences_persistent;
211   for (i = inc_prefs_pers.begin(); i != inc_prefs_pers.end(); ++i)
212     out->insert(i->first);
213
214   const PrefValueMap& inc_prefs_session =
215       entry.incognito_profile_preferences_session_only;
216   for (i = inc_prefs_session.begin(); i != inc_prefs_session.end(); ++i)
217     out->insert(i->first);
218 }
219
220 const Value* ExtensionPrefValueMap::GetEffectivePrefValue(
221     const std::string& key,
222     bool incognito,
223     bool* from_incognito) const {
224   ExtensionEntryMap::const_iterator winner =
225       GetEffectivePrefValueController(key, incognito, from_incognito);
226   if (winner == entries_.end())
227     return NULL;
228
229   const Value* value = NULL;
230   const std::string& ext_id = winner->first;
231
232   // First search for incognito session only preferences.
233   if (incognito) {
234     const PrefValueMap* prefs = GetExtensionPrefValueMap(
235         ext_id, extensions::kExtensionPrefsScopeIncognitoSessionOnly);
236     prefs->GetValue(key, &value);
237     if (value)
238       return value;
239
240     // If no incognito session only preference exists, fall back to persistent
241     // incognito preference.
242     prefs = GetExtensionPrefValueMap(
243         ext_id,
244         extensions::kExtensionPrefsScopeIncognitoPersistent);
245     prefs->GetValue(key, &value);
246     if (value)
247       return value;
248   } else {
249     // Regular-only preference.
250     const PrefValueMap* prefs = GetExtensionPrefValueMap(
251         ext_id, extensions::kExtensionPrefsScopeRegularOnly);
252     prefs->GetValue(key, &value);
253     if (value)
254       return value;
255   }
256
257   // Regular preference.
258   const PrefValueMap* prefs = GetExtensionPrefValueMap(
259       ext_id, extensions::kExtensionPrefsScopeRegular);
260   prefs->GetValue(key, &value);
261   return value;
262 }
263
264 ExtensionPrefValueMap::ExtensionEntryMap::const_iterator
265 ExtensionPrefValueMap::GetEffectivePrefValueController(
266     const std::string& key,
267     bool incognito,
268     bool* from_incognito) const {
269   ExtensionEntryMap::const_iterator winner = entries_.end();
270   base::Time winners_install_time;
271
272   ExtensionEntryMap::const_iterator i;
273   for (i = entries_.begin(); i != entries_.end(); ++i) {
274     const std::string& ext_id = i->first;
275     const base::Time& install_time = i->second->install_time;
276     const bool enabled = i->second->enabled;
277
278     if (!enabled)
279       continue;
280     if (install_time < winners_install_time)
281       continue;
282
283     const Value* value = NULL;
284     const PrefValueMap* prefs = GetExtensionPrefValueMap(
285         ext_id, extensions::kExtensionPrefsScopeRegular);
286     if (prefs->GetValue(key, &value)) {
287       winner = i;
288       winners_install_time = install_time;
289       if (from_incognito)
290         *from_incognito = false;
291     }
292
293     if (!incognito) {
294       const PrefValueMap* prefs = GetExtensionPrefValueMap(
295           ext_id, extensions::kExtensionPrefsScopeRegularOnly);
296       if (prefs->GetValue(key, &value)) {
297         winner = i;
298         winners_install_time = install_time;
299         if (from_incognito)
300           *from_incognito = false;
301       }
302       // Ignore the following prefs, because they're incognito-only.
303       continue;
304     }
305
306     prefs = GetExtensionPrefValueMap(
307         ext_id, extensions::kExtensionPrefsScopeIncognitoPersistent);
308     if (prefs->GetValue(key, &value)) {
309       winner = i;
310       winners_install_time = install_time;
311       if (from_incognito)
312         *from_incognito = true;
313     }
314
315     prefs = GetExtensionPrefValueMap(
316         ext_id, extensions::kExtensionPrefsScopeIncognitoSessionOnly);
317     if (prefs->GetValue(key, &value)) {
318       winner = i;
319       winners_install_time = install_time;
320       if (from_incognito)
321         *from_incognito = true;
322     }
323   }
324   return winner;
325 }
326
327 void ExtensionPrefValueMap::AddObserver(
328     ExtensionPrefValueMap::Observer* observer) {
329   observers_.AddObserver(observer);
330
331   // Collect all currently used keys and notify the new observer.
332   std::set<std::string> keys;
333   ExtensionEntryMap::const_iterator i;
334   for (i = entries_.begin(); i != entries_.end(); ++i)
335     GetExtensionControlledKeys(*(i->second), &keys);
336
337   std::set<std::string>::const_iterator j;
338   for (j = keys.begin(); j != keys.end(); ++j)
339     observer->OnPrefValueChanged(*j);
340 }
341
342 void ExtensionPrefValueMap::RemoveObserver(
343     ExtensionPrefValueMap::Observer* observer) {
344   observers_.RemoveObserver(observer);
345 }
346
347 void ExtensionPrefValueMap::NotifyInitializationCompleted() {
348   FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
349                     OnInitializationCompleted());
350 }
351
352 void ExtensionPrefValueMap::NotifyPrefValueChanged(
353     const std::set<std::string>& keys) {
354   std::set<std::string>::const_iterator i;
355   for (i = keys.begin(); i != keys.end(); ++i)
356     NotifyPrefValueChanged(*i);
357 }
358
359 void ExtensionPrefValueMap::NotifyPrefValueChanged(const std::string& key) {
360   FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
361                     OnPrefValueChanged(key));
362 }
363
364 void ExtensionPrefValueMap::NotifyOfDestruction() {
365   FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
366                     OnExtensionPrefValueMapDestruction());
367 }