blob: bb1fde5dd617302b3de4a27a04cd38f76df45686 [file] [log] [blame]
[email protected]489db0842014-01-22 18:20:031// Copyright 2014 The Chromium Authors. All rights reserved.
[email protected]9a8c4022011-01-25 14:25:332// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]489db0842014-01-22 18:20:035#include "extensions/browser/extension_pref_value_map.h"
[email protected]9a8c4022011-01-25 14:25:336
[email protected]9a8c4022011-01-25 14:25:337#include "base/values.h"
brettw066508682016-02-03 08:22:028#include "components/prefs/pref_value_map.h"
[email protected]9a8c4022011-01-25 14:25:339
[email protected]45759612012-07-10 17:21:2310using extensions::ExtensionPrefsScope;
11
[email protected]0865c1342011-01-28 20:29:3712struct ExtensionPrefValueMap::ExtensionEntry {
13 // Installation time of the extension.
14 base::Time install_time;
15 // Whether extension is enabled in the profile.
16 bool enabled;
[email protected]6c164752014-03-12 00:29:1517 // Whether the extension has access to the incognito profile.
18 bool incognito_enabled;
[email protected]9783c162011-05-25 21:45:5119 // Extension controlled preferences for the regular profile.
20 PrefValueMap regular_profile_preferences;
[email protected]7d3a0e32012-06-14 22:37:2921 // Extension controlled preferences that should *only* apply to the regular
22 // profile.
23 PrefValueMap regular_only_profile_preferences;
[email protected]9783c162011-05-25 21:45:5124 // Persistent extension controlled preferences for the incognito profile,
25 // empty for regular profile ExtensionPrefStore.
26 PrefValueMap incognito_profile_preferences_persistent;
[email protected]31685742011-05-25 23:01:5627 // Session only extension controlled preferences for the incognito profile.
28 // These preferences are deleted when the incognito profile is destroyed.
29 PrefValueMap incognito_profile_preferences_session_only;
[email protected]0865c1342011-01-28 20:29:3730};
31
[email protected]ef9bba12012-04-06 16:26:0932ExtensionPrefValueMap::ExtensionPrefValueMap() : destroyed_(false) {
[email protected]9a8c4022011-01-25 14:25:3333}
34
35ExtensionPrefValueMap::~ExtensionPrefValueMap() {
[email protected]ef9bba12012-04-06 16:26:0936 if (!destroyed_) {
37 NotifyOfDestruction();
38 destroyed_ = true;
39 }
[email protected]9a8c4022011-01-25 14:25:3340}
41
[email protected]ef9bba12012-04-06 16:26:0942void ExtensionPrefValueMap::Shutdown() {
43 NotifyOfDestruction();
44 destroyed_ = true;
45}
46
[email protected]9a8c4022011-01-25 14:25:3347void ExtensionPrefValueMap::SetExtensionPref(const std::string& ext_id,
48 const std::string& key,
[email protected]dece9a62011-06-07 17:38:5949 ExtensionPrefsScope scope,
[email protected]023b3d12013-12-23 18:46:4950 base::Value* value) {
[email protected]9783c162011-05-25 21:45:5151 PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, scope);
[email protected]9a8c4022011-01-25 14:25:3352
estade0bd407f2015-06-26 18:16:1853 if (prefs->SetValue(key, make_scoped_ptr(value)))
[email protected]9a8c4022011-01-25 14:25:3354 NotifyPrefValueChanged(key);
55}
56
[email protected]9783c162011-05-25 21:45:5157void ExtensionPrefValueMap::RemoveExtensionPref(
58 const std::string& ext_id,
59 const std::string& key,
[email protected]dece9a62011-06-07 17:38:5960 ExtensionPrefsScope scope) {
[email protected]9783c162011-05-25 21:45:5161 PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, scope);
[email protected]9a8c4022011-01-25 14:25:3362 if (prefs->RemoveValue(key))
63 NotifyPrefValueChanged(key);
64}
65
[email protected]9a28f132011-02-24 21:15:1666bool ExtensionPrefValueMap::CanExtensionControlPref(
67 const std::string& extension_id,
68 const std::string& pref_key,
69 bool incognito) const {
70 ExtensionEntryMap::const_iterator ext = entries_.find(extension_id);
71 if (ext == entries_.end()) {
battrec17c9742015-04-10 08:24:2572 NOTREACHED() << "Extension " << extension_id
73 << " is not registered but accesses pref " << pref_key
74 << " (incognito: " << incognito << ")."
75 << " http://crbug.com/454513";
[email protected]9a28f132011-02-24 21:15:1676 return false;
77 }
78
[email protected]6c164752014-03-12 00:29:1579 if (incognito && !ext->second->incognito_enabled)
80 return false;
81
[email protected]9a28f132011-02-24 21:15:1682 ExtensionEntryMap::const_iterator winner =
[email protected]c0793562011-03-09 15:31:0383 GetEffectivePrefValueController(pref_key, incognito, NULL);
[email protected]9a28f132011-02-24 21:15:1684 if (winner == entries_.end())
85 return true;
86
87 return winner->second->install_time <= ext->second->install_time;
88}
89
[email protected]31685742011-05-25 23:01:5690void ExtensionPrefValueMap::ClearAllIncognitoSessionOnlyPreferences() {
91 typedef std::set<std::string> KeySet;
92 KeySet deleted_keys;
93
limasdf39e712d72015-11-19 16:00:5094 for (const auto& entry : entries_) {
[email protected]31685742011-05-25 23:01:5695 PrefValueMap& inc_prefs =
limasdf39e712d72015-11-19 16:00:5096 entry.second->incognito_profile_preferences_session_only;
97 for (const auto& pref : inc_prefs)
98 deleted_keys.insert(pref.first);
[email protected]31685742011-05-25 23:01:5699 inc_prefs.Clear();
100 }
101
limasdf39e712d72015-11-19 16:00:50102 for (const auto& key : deleted_keys)
103 NotifyPrefValueChanged(key);
[email protected]31685742011-05-25 23:01:56104}
105
[email protected]9a28f132011-02-24 21:15:16106bool ExtensionPrefValueMap::DoesExtensionControlPref(
107 const std::string& extension_id,
108 const std::string& pref_key,
[email protected]42c037e2012-06-26 22:23:32109 bool* from_incognito) const {
110 bool incognito = (from_incognito != NULL);
[email protected]9a28f132011-02-24 21:15:16111 ExtensionEntryMap::const_iterator winner =
[email protected]42c037e2012-06-26 22:23:32112 GetEffectivePrefValueController(pref_key, incognito, from_incognito);
[email protected]9a28f132011-02-24 21:15:16113 if (winner == entries_.end())
114 return false;
115 return winner->first == extension_id;
116}
117
[email protected]9a8c4022011-01-25 14:25:33118void ExtensionPrefValueMap::RegisterExtension(const std::string& ext_id,
119 const base::Time& install_time,
[email protected]6c164752014-03-12 00:29:15120 bool is_enabled,
121 bool is_incognito_enabled) {
[email protected]ec5143b2013-09-17 12:03:53122 if (entries_.find(ext_id) == entries_.end()) {
limasdf39e712d72015-11-19 16:00:50123 entries_[ext_id] = make_scoped_ptr(new ExtensionEntry);
[email protected]ec5143b2013-09-17 12:03:53124
125 // Only update the install time if the extension is newly installed.
126 entries_[ext_id]->install_time = install_time;
127 }
128
[email protected]9a8c4022011-01-25 14:25:33129 entries_[ext_id]->enabled = is_enabled;
[email protected]6c164752014-03-12 00:29:15130 entries_[ext_id]->incognito_enabled = is_incognito_enabled;
[email protected]9a8c4022011-01-25 14:25:33131}
132
133void ExtensionPrefValueMap::UnregisterExtension(const std::string& ext_id) {
134 ExtensionEntryMap::iterator i = entries_.find(ext_id);
135 if (i == entries_.end())
136 return;
137 std::set<std::string> keys; // keys set by this extension
limasdf39e712d72015-11-19 16:00:50138 GetExtensionControlledKeys(*(i->second.get()), &keys);
[email protected]9a8c4022011-01-25 14:25:33139
[email protected]9a8c4022011-01-25 14:25:33140 entries_.erase(i);
141
142 NotifyPrefValueChanged(keys);
143}
144
145void ExtensionPrefValueMap::SetExtensionState(const std::string& ext_id,
146 bool is_enabled) {
147 ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
[email protected]06f92562011-04-29 19:27:31148 // This may happen when sync sets the extension state for an
149 // extension that is not installed.
150 if (i == entries_.end())
151 return;
[email protected]9a8c4022011-01-25 14:25:33152 if (i->second->enabled == is_enabled)
153 return;
154 std::set<std::string> keys; // keys set by this extension
155 GetExtensionControlledKeys(*(i->second), &keys);
156 i->second->enabled = is_enabled;
157 NotifyPrefValueChanged(keys);
158}
159
[email protected]6c164752014-03-12 00:29:15160void ExtensionPrefValueMap::SetExtensionIncognitoState(
161 const std::string& ext_id,
162 bool is_incognito_enabled) {
163 ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
164 // This may happen when sync sets the extension state for an
165 // extension that is not installed.
166 if (i == entries_.end())
167 return;
168 if (i->second->incognito_enabled == is_incognito_enabled)
169 return;
170 std::set<std::string> keys; // keys set by this extension
171 GetExtensionControlledKeys(*(i->second), &keys);
172 i->second->incognito_enabled = is_incognito_enabled;
173 NotifyPrefValueChanged(keys);
174}
175
[email protected]9a8c4022011-01-25 14:25:33176PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
177 const std::string& ext_id,
[email protected]dece9a62011-06-07 17:38:59178 ExtensionPrefsScope scope) {
[email protected]9a8c4022011-01-25 14:25:33179 ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
180 CHECK(i != entries_.end());
[email protected]9783c162011-05-25 21:45:51181 switch (scope) {
[email protected]45759612012-07-10 17:21:23182 case extensions::kExtensionPrefsScopeRegular:
[email protected]9783c162011-05-25 21:45:51183 return &(i->second->regular_profile_preferences);
[email protected]45759612012-07-10 17:21:23184 case extensions::kExtensionPrefsScopeRegularOnly:
[email protected]7d3a0e32012-06-14 22:37:29185 return &(i->second->regular_only_profile_preferences);
[email protected]45759612012-07-10 17:21:23186 case extensions::kExtensionPrefsScopeIncognitoPersistent:
[email protected]9783c162011-05-25 21:45:51187 return &(i->second->incognito_profile_preferences_persistent);
[email protected]45759612012-07-10 17:21:23188 case extensions::kExtensionPrefsScopeIncognitoSessionOnly:
[email protected]31685742011-05-25 23:01:56189 return &(i->second->incognito_profile_preferences_session_only);
[email protected]9783c162011-05-25 21:45:51190 }
191 NOTREACHED();
192 return NULL;
[email protected]9a8c4022011-01-25 14:25:33193}
194
195const PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
196 const std::string& ext_id,
[email protected]dece9a62011-06-07 17:38:59197 ExtensionPrefsScope scope) const {
[email protected]9a8c4022011-01-25 14:25:33198 ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
199 CHECK(i != entries_.end());
[email protected]9783c162011-05-25 21:45:51200 switch (scope) {
[email protected]45759612012-07-10 17:21:23201 case extensions::kExtensionPrefsScopeRegular:
[email protected]9783c162011-05-25 21:45:51202 return &(i->second->regular_profile_preferences);
[email protected]45759612012-07-10 17:21:23203 case extensions::kExtensionPrefsScopeRegularOnly:
[email protected]7d3a0e32012-06-14 22:37:29204 return &(i->second->regular_only_profile_preferences);
[email protected]45759612012-07-10 17:21:23205 case extensions::kExtensionPrefsScopeIncognitoPersistent:
[email protected]9783c162011-05-25 21:45:51206 return &(i->second->incognito_profile_preferences_persistent);
[email protected]45759612012-07-10 17:21:23207 case extensions::kExtensionPrefsScopeIncognitoSessionOnly:
[email protected]31685742011-05-25 23:01:56208 return &(i->second->incognito_profile_preferences_session_only);
[email protected]9783c162011-05-25 21:45:51209 }
210 NOTREACHED();
211 return NULL;
[email protected]9a8c4022011-01-25 14:25:33212}
213
214void ExtensionPrefValueMap::GetExtensionControlledKeys(
215 const ExtensionEntry& entry,
216 std::set<std::string>* out) const {
217 PrefValueMap::const_iterator i;
218
[email protected]7d3a0e32012-06-14 22:37:29219 const PrefValueMap& regular_prefs = entry.regular_profile_preferences;
220 for (i = regular_prefs.begin(); i != regular_prefs.end(); ++i)
221 out->insert(i->first);
222
223 const PrefValueMap& regular_only_prefs =
224 entry.regular_only_profile_preferences;
225 for (i = regular_only_prefs.begin(); i != regular_only_prefs.end(); ++i)
[email protected]9a8c4022011-01-25 14:25:33226 out->insert(i->first);
227
[email protected]9783c162011-05-25 21:45:51228 const PrefValueMap& inc_prefs_pers =
229 entry.incognito_profile_preferences_persistent;
230 for (i = inc_prefs_pers.begin(); i != inc_prefs_pers.end(); ++i)
[email protected]9a8c4022011-01-25 14:25:33231 out->insert(i->first);
[email protected]31685742011-05-25 23:01:56232
233 const PrefValueMap& inc_prefs_session =
234 entry.incognito_profile_preferences_session_only;
235 for (i = inc_prefs_session.begin(); i != inc_prefs_session.end(); ++i)
236 out->insert(i->first);
[email protected]9a8c4022011-01-25 14:25:33237}
238
[email protected]023b3d12013-12-23 18:46:49239const base::Value* ExtensionPrefValueMap::GetEffectivePrefValue(
[email protected]9a8c4022011-01-25 14:25:33240 const std::string& key,
[email protected]c0793562011-03-09 15:31:03241 bool incognito,
242 bool* from_incognito) const {
[email protected]9a28f132011-02-24 21:15:16243 ExtensionEntryMap::const_iterator winner =
[email protected]c0793562011-03-09 15:31:03244 GetEffectivePrefValueController(key, incognito, from_incognito);
[email protected]9a28f132011-02-24 21:15:16245 if (winner == entries_.end())
246 return NULL;
247
[email protected]023b3d12013-12-23 18:46:49248 const base::Value* value = NULL;
[email protected]9a28f132011-02-24 21:15:16249 const std::string& ext_id = winner->first;
[email protected]31685742011-05-25 23:01:56250
251 // First search for incognito session only preferences.
[email protected]9783c162011-05-25 21:45:51252 if (incognito) {
[email protected]6c164752014-03-12 00:29:15253 DCHECK(winner->second->incognito_enabled);
[email protected]9783c162011-05-25 21:45:51254 const PrefValueMap* prefs = GetExtensionPrefValueMap(
[email protected]45759612012-07-10 17:21:23255 ext_id, extensions::kExtensionPrefsScopeIncognitoSessionOnly);
[email protected]31685742011-05-25 23:01:56256 prefs->GetValue(key, &value);
[email protected]7d3a0e32012-06-14 22:37:29257 if (value)
258 return value;
259
260 // If no incognito session only preference exists, fall back to persistent
261 // incognito preference.
[email protected]45759612012-07-10 17:21:23262 prefs = GetExtensionPrefValueMap(
263 ext_id,
264 extensions::kExtensionPrefsScopeIncognitoPersistent);
[email protected]7d3a0e32012-06-14 22:37:29265 prefs->GetValue(key, &value);
266 if (value)
267 return value;
268 } else {
269 // Regular-only preference.
270 const PrefValueMap* prefs = GetExtensionPrefValueMap(
[email protected]45759612012-07-10 17:21:23271 ext_id, extensions::kExtensionPrefsScopeRegularOnly);
[email protected]7d3a0e32012-06-14 22:37:29272 prefs->GetValue(key, &value);
273 if (value)
274 return value;
[email protected]31685742011-05-25 23:01:56275 }
276
[email protected]7d3a0e32012-06-14 22:37:29277 // Regular preference.
278 const PrefValueMap* prefs = GetExtensionPrefValueMap(
[email protected]45759612012-07-10 17:21:23279 ext_id, extensions::kExtensionPrefsScopeRegular);
[email protected]7d3a0e32012-06-14 22:37:29280 prefs->GetValue(key, &value);
[email protected]9a28f132011-02-24 21:15:16281 return value;
282}
283
284ExtensionPrefValueMap::ExtensionEntryMap::const_iterator
285ExtensionPrefValueMap::GetEffectivePrefValueController(
286 const std::string& key,
[email protected]c0793562011-03-09 15:31:03287 bool incognito,
288 bool* from_incognito) const {
[email protected]9a28f132011-02-24 21:15:16289 ExtensionEntryMap::const_iterator winner = entries_.end();
[email protected]9a8c4022011-01-25 14:25:33290 base::Time winners_install_time;
291
292 ExtensionEntryMap::const_iterator i;
293 for (i = entries_.begin(); i != entries_.end(); ++i) {
294 const std::string& ext_id = i->first;
295 const base::Time& install_time = i->second->install_time;
296 const bool enabled = i->second->enabled;
[email protected]6c164752014-03-12 00:29:15297 const bool incognito_enabled = i->second->incognito_enabled;
[email protected]9a8c4022011-01-25 14:25:33298
299 if (!enabled)
300 continue;
301 if (install_time < winners_install_time)
302 continue;
[email protected]6c164752014-03-12 00:29:15303 if (incognito && !incognito_enabled)
304 continue;
[email protected]9a8c4022011-01-25 14:25:33305
[email protected]023b3d12013-12-23 18:46:49306 const base::Value* value = NULL;
[email protected]9783c162011-05-25 21:45:51307 const PrefValueMap* prefs = GetExtensionPrefValueMap(
[email protected]45759612012-07-10 17:21:23308 ext_id, extensions::kExtensionPrefsScopeRegular);
[email protected]9a8c4022011-01-25 14:25:33309 if (prefs->GetValue(key, &value)) {
[email protected]9a28f132011-02-24 21:15:16310 winner = i;
[email protected]9a8c4022011-01-25 14:25:33311 winners_install_time = install_time;
[email protected]c0793562011-03-09 15:31:03312 if (from_incognito)
313 *from_incognito = false;
[email protected]9a8c4022011-01-25 14:25:33314 }
315
[email protected]7d3a0e32012-06-14 22:37:29316 if (!incognito) {
317 const PrefValueMap* prefs = GetExtensionPrefValueMap(
[email protected]45759612012-07-10 17:21:23318 ext_id, extensions::kExtensionPrefsScopeRegularOnly);
[email protected]7d3a0e32012-06-14 22:37:29319 if (prefs->GetValue(key, &value)) {
320 winner = i;
321 winners_install_time = install_time;
322 if (from_incognito)
323 *from_incognito = false;
324 }
325 // Ignore the following prefs, because they're incognito-only.
[email protected]9a8c4022011-01-25 14:25:33326 continue;
[email protected]7d3a0e32012-06-14 22:37:29327 }
[email protected]9a8c4022011-01-25 14:25:33328
[email protected]9783c162011-05-25 21:45:51329 prefs = GetExtensionPrefValueMap(
[email protected]45759612012-07-10 17:21:23330 ext_id, extensions::kExtensionPrefsScopeIncognitoPersistent);
[email protected]9a8c4022011-01-25 14:25:33331 if (prefs->GetValue(key, &value)) {
[email protected]9a28f132011-02-24 21:15:16332 winner = i;
[email protected]9a8c4022011-01-25 14:25:33333 winners_install_time = install_time;
[email protected]c0793562011-03-09 15:31:03334 if (from_incognito)
335 *from_incognito = true;
[email protected]9a8c4022011-01-25 14:25:33336 }
[email protected]31685742011-05-25 23:01:56337
338 prefs = GetExtensionPrefValueMap(
[email protected]45759612012-07-10 17:21:23339 ext_id, extensions::kExtensionPrefsScopeIncognitoSessionOnly);
[email protected]31685742011-05-25 23:01:56340 if (prefs->GetValue(key, &value)) {
341 winner = i;
342 winners_install_time = install_time;
343 if (from_incognito)
344 *from_incognito = true;
345 }
[email protected]9a8c4022011-01-25 14:25:33346 }
347 return winner;
348}
349
350void ExtensionPrefValueMap::AddObserver(
351 ExtensionPrefValueMap::Observer* observer) {
352 observers_.AddObserver(observer);
353
354 // Collect all currently used keys and notify the new observer.
355 std::set<std::string> keys;
356 ExtensionEntryMap::const_iterator i;
357 for (i = entries_.begin(); i != entries_.end(); ++i)
358 GetExtensionControlledKeys(*(i->second), &keys);
359
360 std::set<std::string>::const_iterator j;
361 for (j = keys.begin(); j != keys.end(); ++j)
362 observer->OnPrefValueChanged(*j);
363}
364
365void ExtensionPrefValueMap::RemoveObserver(
366 ExtensionPrefValueMap::Observer* observer) {
367 observers_.RemoveObserver(observer);
368}
369
[email protected]b5a507b22013-11-08 20:41:57370std::string ExtensionPrefValueMap::GetExtensionControllingPref(
371 const std::string& pref_key) const {
372 ExtensionEntryMap::const_iterator winner =
373 GetEffectivePrefValueController(pref_key, false, NULL);
374 if (winner == entries_.end())
375 return std::string();
376 return winner->first;
377}
378
[email protected]9a8c4022011-01-25 14:25:33379void ExtensionPrefValueMap::NotifyInitializationCompleted() {
380 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
381 OnInitializationCompleted());
382}
383
384void ExtensionPrefValueMap::NotifyPrefValueChanged(
385 const std::set<std::string>& keys) {
limasdf39e712d72015-11-19 16:00:50386 for (const auto& key : keys)
387 NotifyPrefValueChanged(key);
[email protected]9a8c4022011-01-25 14:25:33388}
389
390void ExtensionPrefValueMap::NotifyPrefValueChanged(const std::string& key) {
391 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
392 OnPrefValueChanged(key));
393}
394
395void ExtensionPrefValueMap::NotifyOfDestruction() {
396 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
397 OnExtensionPrefValueMapDestruction());
398}