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 UnregisterExtension(ext_id); 121 entries_[ext_id] = new ExtensionEntry; 122 entries_[ext_id]->install_time = install_time; 123 entries_[ext_id]->enabled = is_enabled; 124 } 125 126 void ExtensionPrefValueMap::UnregisterExtension(const std::string& ext_id) { 127 ExtensionEntryMap::iterator i = entries_.find(ext_id); 128 if (i == entries_.end()) 129 return; 130 std::set<std::string> keys; // keys set by this extension 131 GetExtensionControlledKeys(*(i->second), &keys); 132 133 delete i->second; 134 entries_.erase(i); 135 136 NotifyPrefValueChanged(keys); 137 } 138 139 void ExtensionPrefValueMap::SetExtensionState(const std::string& ext_id, 140 bool is_enabled) { 141 ExtensionEntryMap::const_iterator i = entries_.find(ext_id); 142 // This may happen when sync sets the extension state for an 143 // extension that is not installed. 144 if (i == entries_.end()) 145 return; 146 if (i->second->enabled == is_enabled) 147 return; 148 std::set<std::string> keys; // keys set by this extension 149 GetExtensionControlledKeys(*(i->second), &keys); 150 i->second->enabled = is_enabled; 151 NotifyPrefValueChanged(keys); 152 } 153 154 PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap( 155 const std::string& ext_id, 156 ExtensionPrefsScope scope) { 157 ExtensionEntryMap::const_iterator i = entries_.find(ext_id); 158 CHECK(i != entries_.end()); 159 switch (scope) { 160 case extensions::kExtensionPrefsScopeRegular: 161 return &(i->second->regular_profile_preferences); 162 case extensions::kExtensionPrefsScopeRegularOnly: 163 return &(i->second->regular_only_profile_preferences); 164 case extensions::kExtensionPrefsScopeIncognitoPersistent: 165 return &(i->second->incognito_profile_preferences_persistent); 166 case extensions::kExtensionPrefsScopeIncognitoSessionOnly: 167 return &(i->second->incognito_profile_preferences_session_only); 168 } 169 NOTREACHED(); 170 return NULL; 171 } 172 173 const PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap( 174 const std::string& ext_id, 175 ExtensionPrefsScope scope) const { 176 ExtensionEntryMap::const_iterator i = entries_.find(ext_id); 177 CHECK(i != entries_.end()); 178 switch (scope) { 179 case extensions::kExtensionPrefsScopeRegular: 180 return &(i->second->regular_profile_preferences); 181 case extensions::kExtensionPrefsScopeRegularOnly: 182 return &(i->second->regular_only_profile_preferences); 183 case extensions::kExtensionPrefsScopeIncognitoPersistent: 184 return &(i->second->incognito_profile_preferences_persistent); 185 case extensions::kExtensionPrefsScopeIncognitoSessionOnly: 186 return &(i->second->incognito_profile_preferences_session_only); 187 } 188 NOTREACHED(); 189 return NULL; 190 } 191 192 void ExtensionPrefValueMap::GetExtensionControlledKeys( 193 const ExtensionEntry& entry, 194 std::set<std::string>* out) const { 195 PrefValueMap::const_iterator i; 196 197 const PrefValueMap& regular_prefs = entry.regular_profile_preferences; 198 for (i = regular_prefs.begin(); i != regular_prefs.end(); ++i) 199 out->insert(i->first); 200 201 const PrefValueMap& regular_only_prefs = 202 entry.regular_only_profile_preferences; 203 for (i = regular_only_prefs.begin(); i != regular_only_prefs.end(); ++i) 204 out->insert(i->first); 205 206 const PrefValueMap& inc_prefs_pers = 207 entry.incognito_profile_preferences_persistent; 208 for (i = inc_prefs_pers.begin(); i != inc_prefs_pers.end(); ++i) 209 out->insert(i->first); 210 211 const PrefValueMap& inc_prefs_session = 212 entry.incognito_profile_preferences_session_only; 213 for (i = inc_prefs_session.begin(); i != inc_prefs_session.end(); ++i) 214 out->insert(i->first); 215 } 216 217 const Value* ExtensionPrefValueMap::GetEffectivePrefValue( 218 const std::string& key, 219 bool incognito, 220 bool* from_incognito) const { 221 ExtensionEntryMap::const_iterator winner = 222 GetEffectivePrefValueController(key, incognito, from_incognito); 223 if (winner == entries_.end()) 224 return NULL; 225 226 const Value* value = NULL; 227 const std::string& ext_id = winner->first; 228 229 // First search for incognito session only preferences. 230 if (incognito) { 231 const PrefValueMap* prefs = GetExtensionPrefValueMap( 232 ext_id, extensions::kExtensionPrefsScopeIncognitoSessionOnly); 233 prefs->GetValue(key, &value); 234 if (value) 235 return value; 236 237 // If no incognito session only preference exists, fall back to persistent 238 // incognito preference. 239 prefs = GetExtensionPrefValueMap( 240 ext_id, 241 extensions::kExtensionPrefsScopeIncognitoPersistent); 242 prefs->GetValue(key, &value); 243 if (value) 244 return value; 245 } else { 246 // Regular-only preference. 247 const PrefValueMap* prefs = GetExtensionPrefValueMap( 248 ext_id, extensions::kExtensionPrefsScopeRegularOnly); 249 prefs->GetValue(key, &value); 250 if (value) 251 return value; 252 } 253 254 // Regular preference. 255 const PrefValueMap* prefs = GetExtensionPrefValueMap( 256 ext_id, extensions::kExtensionPrefsScopeRegular); 257 prefs->GetValue(key, &value); 258 return value; 259 } 260 261 ExtensionPrefValueMap::ExtensionEntryMap::const_iterator 262 ExtensionPrefValueMap::GetEffectivePrefValueController( 263 const std::string& key, 264 bool incognito, 265 bool* from_incognito) const { 266 ExtensionEntryMap::const_iterator winner = entries_.end(); 267 base::Time winners_install_time; 268 269 ExtensionEntryMap::const_iterator i; 270 for (i = entries_.begin(); i != entries_.end(); ++i) { 271 const std::string& ext_id = i->first; 272 const base::Time& install_time = i->second->install_time; 273 const bool enabled = i->second->enabled; 274 275 if (!enabled) 276 continue; 277 if (install_time < winners_install_time) 278 continue; 279 280 const Value* value = NULL; 281 const PrefValueMap* prefs = GetExtensionPrefValueMap( 282 ext_id, extensions::kExtensionPrefsScopeRegular); 283 if (prefs->GetValue(key, &value)) { 284 winner = i; 285 winners_install_time = install_time; 286 if (from_incognito) 287 *from_incognito = false; 288 } 289 290 if (!incognito) { 291 const PrefValueMap* prefs = GetExtensionPrefValueMap( 292 ext_id, extensions::kExtensionPrefsScopeRegularOnly); 293 if (prefs->GetValue(key, &value)) { 294 winner = i; 295 winners_install_time = install_time; 296 if (from_incognito) 297 *from_incognito = false; 298 } 299 // Ignore the following prefs, because they're incognito-only. 300 continue; 301 } 302 303 prefs = GetExtensionPrefValueMap( 304 ext_id, extensions::kExtensionPrefsScopeIncognitoPersistent); 305 if (prefs->GetValue(key, &value)) { 306 winner = i; 307 winners_install_time = install_time; 308 if (from_incognito) 309 *from_incognito = true; 310 } 311 312 prefs = GetExtensionPrefValueMap( 313 ext_id, extensions::kExtensionPrefsScopeIncognitoSessionOnly); 314 if (prefs->GetValue(key, &value)) { 315 winner = i; 316 winners_install_time = install_time; 317 if (from_incognito) 318 *from_incognito = true; 319 } 320 } 321 return winner; 322 } 323 324 void ExtensionPrefValueMap::AddObserver( 325 ExtensionPrefValueMap::Observer* observer) { 326 observers_.AddObserver(observer); 327 328 // Collect all currently used keys and notify the new observer. 329 std::set<std::string> keys; 330 ExtensionEntryMap::const_iterator i; 331 for (i = entries_.begin(); i != entries_.end(); ++i) 332 GetExtensionControlledKeys(*(i->second), &keys); 333 334 std::set<std::string>::const_iterator j; 335 for (j = keys.begin(); j != keys.end(); ++j) 336 observer->OnPrefValueChanged(*j); 337 } 338 339 void ExtensionPrefValueMap::RemoveObserver( 340 ExtensionPrefValueMap::Observer* observer) { 341 observers_.RemoveObserver(observer); 342 } 343 344 void ExtensionPrefValueMap::NotifyInitializationCompleted() { 345 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_, 346 OnInitializationCompleted()); 347 } 348 349 void ExtensionPrefValueMap::NotifyPrefValueChanged( 350 const std::set<std::string>& keys) { 351 std::set<std::string>::const_iterator i; 352 for (i = keys.begin(); i != keys.end(); ++i) 353 NotifyPrefValueChanged(*i); 354 } 355 356 void ExtensionPrefValueMap::NotifyPrefValueChanged(const std::string& key) { 357 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_, 358 OnPrefValueChanged(key)); 359 } 360 361 void ExtensionPrefValueMap::NotifyOfDestruction() { 362 FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_, 363 OnExtensionPrefValueMapDestruction()); 364 } 365