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 33 ExtensionPrefValueMap::ExtensionPrefValueMap() : destroyed_(false) { 34 } 35 36 ExtensionPrefValueMap::~ExtensionPrefValueMap() { 37 if (!destroyed_) { 38 NotifyOfDestruction(); 39 destroyed_ = true; 40 } 41 STLDeleteValues(&entries_); 42 entries_.clear(); 43 } 44 45 void ExtensionPrefValueMap::Shutdown() { 46 NotifyOfDestruction(); 47 destroyed_ = true; 48 } 49 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 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 69 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 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 109 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 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 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 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 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 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 199 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 218 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 243 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 289 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 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 369 void ExtensionPrefValueMap::RemoveObserver( 370 ExtensionPrefValueMap::Observer* observer) { 371 observers_.RemoveObserver(observer); 372 } 373 374 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 383 void ExtensionPrefValueMap::NotifyInitializationCompleted() { 384 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_, 385 OnInitializationCompleted()); 386 } 387 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 395 void ExtensionPrefValueMap::NotifyPrefValueChanged(const std::string& key) { 396 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_, 397 OnPrefValueChanged(key)); 398 } 399 400 void ExtensionPrefValueMap::NotifyOfDestruction() { 401 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_, 402 OnExtensionPrefValueMapDestruction()); 403 } 404