[Smart Lock] Record a detailed UMA metric for each unlock attempt by Smart Lock users.
[chromium-blink-merge.git] / extensions / browser / extension_pref_value_map.cc
blobd21a96972fc05303bcd58a95ccd2fa0630a81fab
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.
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;
33 ExtensionPrefValueMap::ExtensionPrefValueMap() : destroyed_(false) {
36 ExtensionPrefValueMap::~ExtensionPrefValueMap() {
37 if (!destroyed_) {
38 NotifyOfDestruction();
39 destroyed_ = true;
41 STLDeleteValues(&entries_);
44 void ExtensionPrefValueMap::Shutdown() {
45 NotifyOfDestruction();
46 destroyed_ = true;
49 void ExtensionPrefValueMap::SetExtensionPref(const std::string& ext_id,
50 const std::string& key,
51 ExtensionPrefsScope scope,
52 base::Value* value) {
53 PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, scope);
55 if (prefs->SetValue(key, value))
56 NotifyPrefValueChanged(key);
59 void ExtensionPrefValueMap::RemoveExtensionPref(
60 const std::string& ext_id,
61 const std::string& key,
62 ExtensionPrefsScope scope) {
63 PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, scope);
64 if (prefs->RemoveValue(key))
65 NotifyPrefValueChanged(key);
68 bool ExtensionPrefValueMap::CanExtensionControlPref(
69 const std::string& extension_id,
70 const std::string& pref_key,
71 bool incognito) const {
72 ExtensionEntryMap::const_iterator ext = entries_.find(extension_id);
73 if (ext == entries_.end()) {
74 NOTREACHED();
75 return false;
78 if (incognito && !ext->second->incognito_enabled)
79 return false;
81 ExtensionEntryMap::const_iterator winner =
82 GetEffectivePrefValueController(pref_key, incognito, NULL);
83 if (winner == entries_.end())
84 return true;
86 return winner->second->install_time <= ext->second->install_time;
89 void ExtensionPrefValueMap::ClearAllIncognitoSessionOnlyPreferences() {
90 typedef std::set<std::string> KeySet;
91 KeySet deleted_keys;
93 ExtensionEntryMap::iterator i;
94 for (i = entries_.begin(); i != entries_.end(); ++i) {
95 PrefValueMap& inc_prefs =
96 i->second->incognito_profile_preferences_session_only;
97 PrefValueMap::iterator j;
98 for (j = inc_prefs.begin(); j != inc_prefs.end(); ++j)
99 deleted_keys.insert(j->first);
100 inc_prefs.Clear();
103 KeySet::iterator k;
104 for (k = deleted_keys.begin(); k != deleted_keys.end(); ++k)
105 NotifyPrefValueChanged(*k);
108 bool ExtensionPrefValueMap::DoesExtensionControlPref(
109 const std::string& extension_id,
110 const std::string& pref_key,
111 bool* from_incognito) const {
112 bool incognito = (from_incognito != NULL);
113 ExtensionEntryMap::const_iterator winner =
114 GetEffectivePrefValueController(pref_key, incognito, from_incognito);
115 if (winner == entries_.end())
116 return false;
117 return winner->first == extension_id;
120 void ExtensionPrefValueMap::RegisterExtension(const std::string& ext_id,
121 const base::Time& install_time,
122 bool is_enabled,
123 bool is_incognito_enabled) {
124 if (entries_.find(ext_id) == entries_.end()) {
125 entries_[ext_id] = new ExtensionEntry;
127 // Only update the install time if the extension is newly installed.
128 entries_[ext_id]->install_time = install_time;
131 entries_[ext_id]->enabled = is_enabled;
132 entries_[ext_id]->incognito_enabled = is_incognito_enabled;
135 void ExtensionPrefValueMap::UnregisterExtension(const std::string& ext_id) {
136 ExtensionEntryMap::iterator i = entries_.find(ext_id);
137 if (i == entries_.end())
138 return;
139 std::set<std::string> keys; // keys set by this extension
140 GetExtensionControlledKeys(*(i->second), &keys);
142 delete i->second;
143 entries_.erase(i);
145 NotifyPrefValueChanged(keys);
148 void ExtensionPrefValueMap::SetExtensionState(const std::string& ext_id,
149 bool is_enabled) {
150 ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
151 // This may happen when sync sets the extension state for an
152 // extension that is not installed.
153 if (i == entries_.end())
154 return;
155 if (i->second->enabled == is_enabled)
156 return;
157 std::set<std::string> keys; // keys set by this extension
158 GetExtensionControlledKeys(*(i->second), &keys);
159 i->second->enabled = is_enabled;
160 NotifyPrefValueChanged(keys);
163 void ExtensionPrefValueMap::SetExtensionIncognitoState(
164 const std::string& ext_id,
165 bool is_incognito_enabled) {
166 ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
167 // This may happen when sync sets the extension state for an
168 // extension that is not installed.
169 if (i == entries_.end())
170 return;
171 if (i->second->incognito_enabled == is_incognito_enabled)
172 return;
173 std::set<std::string> keys; // keys set by this extension
174 GetExtensionControlledKeys(*(i->second), &keys);
175 i->second->incognito_enabled = is_incognito_enabled;
176 NotifyPrefValueChanged(keys);
179 PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
180 const std::string& ext_id,
181 ExtensionPrefsScope scope) {
182 ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
183 CHECK(i != entries_.end());
184 switch (scope) {
185 case extensions::kExtensionPrefsScopeRegular:
186 return &(i->second->regular_profile_preferences);
187 case extensions::kExtensionPrefsScopeRegularOnly:
188 return &(i->second->regular_only_profile_preferences);
189 case extensions::kExtensionPrefsScopeIncognitoPersistent:
190 return &(i->second->incognito_profile_preferences_persistent);
191 case extensions::kExtensionPrefsScopeIncognitoSessionOnly:
192 return &(i->second->incognito_profile_preferences_session_only);
194 NOTREACHED();
195 return NULL;
198 const PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
199 const std::string& ext_id,
200 ExtensionPrefsScope scope) const {
201 ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
202 CHECK(i != entries_.end());
203 switch (scope) {
204 case extensions::kExtensionPrefsScopeRegular:
205 return &(i->second->regular_profile_preferences);
206 case extensions::kExtensionPrefsScopeRegularOnly:
207 return &(i->second->regular_only_profile_preferences);
208 case extensions::kExtensionPrefsScopeIncognitoPersistent:
209 return &(i->second->incognito_profile_preferences_persistent);
210 case extensions::kExtensionPrefsScopeIncognitoSessionOnly:
211 return &(i->second->incognito_profile_preferences_session_only);
213 NOTREACHED();
214 return NULL;
217 void ExtensionPrefValueMap::GetExtensionControlledKeys(
218 const ExtensionEntry& entry,
219 std::set<std::string>* out) const {
220 PrefValueMap::const_iterator i;
222 const PrefValueMap& regular_prefs = entry.regular_profile_preferences;
223 for (i = regular_prefs.begin(); i != regular_prefs.end(); ++i)
224 out->insert(i->first);
226 const PrefValueMap& regular_only_prefs =
227 entry.regular_only_profile_preferences;
228 for (i = regular_only_prefs.begin(); i != regular_only_prefs.end(); ++i)
229 out->insert(i->first);
231 const PrefValueMap& inc_prefs_pers =
232 entry.incognito_profile_preferences_persistent;
233 for (i = inc_prefs_pers.begin(); i != inc_prefs_pers.end(); ++i)
234 out->insert(i->first);
236 const PrefValueMap& inc_prefs_session =
237 entry.incognito_profile_preferences_session_only;
238 for (i = inc_prefs_session.begin(); i != inc_prefs_session.end(); ++i)
239 out->insert(i->first);
242 const base::Value* ExtensionPrefValueMap::GetEffectivePrefValue(
243 const std::string& key,
244 bool incognito,
245 bool* from_incognito) const {
246 ExtensionEntryMap::const_iterator winner =
247 GetEffectivePrefValueController(key, incognito, from_incognito);
248 if (winner == entries_.end())
249 return NULL;
251 const base::Value* value = NULL;
252 const std::string& ext_id = winner->first;
254 // First search for incognito session only preferences.
255 if (incognito) {
256 DCHECK(winner->second->incognito_enabled);
257 const PrefValueMap* prefs = GetExtensionPrefValueMap(
258 ext_id, extensions::kExtensionPrefsScopeIncognitoSessionOnly);
259 prefs->GetValue(key, &value);
260 if (value)
261 return value;
263 // If no incognito session only preference exists, fall back to persistent
264 // incognito preference.
265 prefs = GetExtensionPrefValueMap(
266 ext_id,
267 extensions::kExtensionPrefsScopeIncognitoPersistent);
268 prefs->GetValue(key, &value);
269 if (value)
270 return value;
271 } else {
272 // Regular-only preference.
273 const PrefValueMap* prefs = GetExtensionPrefValueMap(
274 ext_id, extensions::kExtensionPrefsScopeRegularOnly);
275 prefs->GetValue(key, &value);
276 if (value)
277 return value;
280 // Regular preference.
281 const PrefValueMap* prefs = GetExtensionPrefValueMap(
282 ext_id, extensions::kExtensionPrefsScopeRegular);
283 prefs->GetValue(key, &value);
284 return value;
287 ExtensionPrefValueMap::ExtensionEntryMap::const_iterator
288 ExtensionPrefValueMap::GetEffectivePrefValueController(
289 const std::string& key,
290 bool incognito,
291 bool* from_incognito) const {
292 ExtensionEntryMap::const_iterator winner = entries_.end();
293 base::Time winners_install_time;
295 ExtensionEntryMap::const_iterator i;
296 for (i = entries_.begin(); i != entries_.end(); ++i) {
297 const std::string& ext_id = i->first;
298 const base::Time& install_time = i->second->install_time;
299 const bool enabled = i->second->enabled;
300 const bool incognito_enabled = i->second->incognito_enabled;
302 if (!enabled)
303 continue;
304 if (install_time < winners_install_time)
305 continue;
306 if (incognito && !incognito_enabled)
307 continue;
309 const base::Value* value = NULL;
310 const PrefValueMap* prefs = GetExtensionPrefValueMap(
311 ext_id, extensions::kExtensionPrefsScopeRegular);
312 if (prefs->GetValue(key, &value)) {
313 winner = i;
314 winners_install_time = install_time;
315 if (from_incognito)
316 *from_incognito = false;
319 if (!incognito) {
320 const PrefValueMap* prefs = GetExtensionPrefValueMap(
321 ext_id, extensions::kExtensionPrefsScopeRegularOnly);
322 if (prefs->GetValue(key, &value)) {
323 winner = i;
324 winners_install_time = install_time;
325 if (from_incognito)
326 *from_incognito = false;
328 // Ignore the following prefs, because they're incognito-only.
329 continue;
332 prefs = GetExtensionPrefValueMap(
333 ext_id, extensions::kExtensionPrefsScopeIncognitoPersistent);
334 if (prefs->GetValue(key, &value)) {
335 winner = i;
336 winners_install_time = install_time;
337 if (from_incognito)
338 *from_incognito = true;
341 prefs = GetExtensionPrefValueMap(
342 ext_id, extensions::kExtensionPrefsScopeIncognitoSessionOnly);
343 if (prefs->GetValue(key, &value)) {
344 winner = i;
345 winners_install_time = install_time;
346 if (from_incognito)
347 *from_incognito = true;
350 return winner;
353 void ExtensionPrefValueMap::AddObserver(
354 ExtensionPrefValueMap::Observer* observer) {
355 observers_.AddObserver(observer);
357 // Collect all currently used keys and notify the new observer.
358 std::set<std::string> keys;
359 ExtensionEntryMap::const_iterator i;
360 for (i = entries_.begin(); i != entries_.end(); ++i)
361 GetExtensionControlledKeys(*(i->second), &keys);
363 std::set<std::string>::const_iterator j;
364 for (j = keys.begin(); j != keys.end(); ++j)
365 observer->OnPrefValueChanged(*j);
368 void ExtensionPrefValueMap::RemoveObserver(
369 ExtensionPrefValueMap::Observer* observer) {
370 observers_.RemoveObserver(observer);
373 std::string ExtensionPrefValueMap::GetExtensionControllingPref(
374 const std::string& pref_key) const {
375 ExtensionEntryMap::const_iterator winner =
376 GetEffectivePrefValueController(pref_key, false, NULL);
377 if (winner == entries_.end())
378 return std::string();
379 return winner->first;
382 void ExtensionPrefValueMap::NotifyInitializationCompleted() {
383 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
384 OnInitializationCompleted());
387 void ExtensionPrefValueMap::NotifyPrefValueChanged(
388 const std::set<std::string>& keys) {
389 std::set<std::string>::const_iterator i;
390 for (i = keys.begin(); i != keys.end(); ++i)
391 NotifyPrefValueChanged(*i);
394 void ExtensionPrefValueMap::NotifyPrefValueChanged(const std::string& key) {
395 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
396 OnPrefValueChanged(key));
399 void ExtensionPrefValueMap::NotifyOfDestruction() {
400 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
401 OnExtensionPrefValueMapDestruction());