OLD | NEW |
| (Empty) |
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 base::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 base::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 base::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 base::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 std::string ExtensionPrefValueMap::GetExtensionControllingPref( | |
348 const std::string& pref_key) const { | |
349 ExtensionEntryMap::const_iterator winner = | |
350 GetEffectivePrefValueController(pref_key, false, NULL); | |
351 if (winner == entries_.end()) | |
352 return std::string(); | |
353 return winner->first; | |
354 } | |
355 | |
356 void ExtensionPrefValueMap::NotifyInitializationCompleted() { | |
357 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_, | |
358 OnInitializationCompleted()); | |
359 } | |
360 | |
361 void ExtensionPrefValueMap::NotifyPrefValueChanged( | |
362 const std::set<std::string>& keys) { | |
363 std::set<std::string>::const_iterator i; | |
364 for (i = keys.begin(); i != keys.end(); ++i) | |
365 NotifyPrefValueChanged(*i); | |
366 } | |
367 | |
368 void ExtensionPrefValueMap::NotifyPrefValueChanged(const std::string& key) { | |
369 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_, | |
370 OnPrefValueChanged(key)); | |
371 } | |
372 | |
373 void ExtensionPrefValueMap::NotifyOfDestruction() { | |
374 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_, | |
375 OnExtensionPrefValueMapDestruction()); | |
376 } | |
OLD | NEW |