| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/extension_pref_store.h" | 5 #include "chrome/browser/extensions/extension_pref_store.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/values.h" | 8 #include "base/values.h" |
| 9 #include "chrome/browser/browser_process.h" | 9 #include "chrome/browser/browser_process.h" |
| 10 #include "chrome/browser/prefs/pref_service.h" | 10 #include "chrome/browser/prefs/pref_service.h" |
| 11 #include "chrome/browser/profile.h" | 11 #include "chrome/browser/profile.h" |
| 12 #include "chrome/common/extensions/extension.h" | 12 #include "chrome/common/extensions/extension.h" |
| 13 #include "chrome/common/notification_service.h" | 13 #include "chrome/common/notification_service.h" |
| 14 | 14 |
| 15 ExtensionPrefStore::ExtensionPrefStore(Profile* profile, | 15 ExtensionPrefStore::ExtensionPrefStore(Profile* profile) |
| 16 PrefNotifier::PrefStoreType type) | |
| 17 : prefs_(new DictionaryValue()), | 16 : prefs_(new DictionaryValue()), |
| 18 profile_(profile), | 17 profile_(profile) { |
| 19 type_(type) { | |
| 20 RegisterObservers(); | 18 RegisterObservers(); |
| 21 } | 19 } |
| 22 | 20 |
| 23 ExtensionPrefStore::~ExtensionPrefStore() { | 21 ExtensionPrefStore::~ExtensionPrefStore() { |
| 24 STLDeleteElements(&extension_stack_); | 22 STLDeleteElements(&extension_stack_); |
| 25 notification_registrar_.RemoveAll(); | 23 notification_registrar_.RemoveAll(); |
| 26 } | 24 } |
| 27 | 25 |
| 28 void ExtensionPrefStore::InstallExtensionPref(const Extension* extension, | 26 void ExtensionPrefStore::InstallExtensionPref(const Extension* extension, |
| 29 const char* new_pref_path, | 27 const char* new_pref_path, |
| 30 Value* new_pref_value) { | 28 Value* new_pref_value) { |
| 31 ExtensionStack::iterator i; | 29 ExtensionStack::iterator i; |
| 32 for (i = extension_stack_.begin(); i != extension_stack_.end(); ++i) { | 30 for (i = extension_stack_.begin(); i != extension_stack_.end(); ++i) { |
| 33 if ((*i)->extension == extension) | 31 if ((*i)->extension == extension) |
| 34 break; | 32 break; |
| 35 } | 33 } |
| 36 | 34 |
| 37 // If this extension is not already in the stack, add it. Otherwise, update | 35 // If this extension is not already in the stack, add it. Otherwise, update |
| 38 // or add the value of this preference, but don't change the extension's | 36 // or add the value of this preference, but don't change the extension's |
| 39 // position in the stack. We store the extension even if this preference | 37 // position in the stack. |
| 40 // isn't registered with our PrefService, so that the ordering of extensions | |
| 41 // is consistent among all local-state and user ExtensionPrefStores. | |
| 42 PrefService* pref_service = GetPrefService(); | |
| 43 // The pref_service may be NULL in unit testing. | |
| 44 bool is_registered_pref = (pref_service == NULL || | |
| 45 pref_service->FindPreference(new_pref_path) != NULL); | |
| 46 PrefValueMap* pref_values; | 38 PrefValueMap* pref_values; |
| 47 if (i == extension_stack_.end()) { | 39 if (i == extension_stack_.end()) { |
| 48 pref_values = new PrefValueMap(); | 40 pref_values = new PrefValueMap(); |
| 49 if (is_registered_pref) | 41 (*pref_values)[new_pref_path] = new_pref_value; |
| 50 (*pref_values)[new_pref_path] = new_pref_value; | |
| 51 | 42 |
| 52 ExtensionPrefs* extension_prefs = new ExtensionPrefs(extension, | 43 ExtensionPrefs* extension_prefs = new ExtensionPrefs(extension, |
| 53 pref_values); | 44 pref_values); |
| 54 extension_stack_.push_front(extension_prefs); | 45 extension_stack_.push_front(extension_prefs); |
| 55 } else if (is_registered_pref) { | 46 } else { |
| 56 pref_values = (*i)->pref_values; | 47 pref_values = (*i)->pref_values; |
| 57 delete (*pref_values)[new_pref_path]; | 48 delete (*pref_values)[new_pref_path]; |
| 58 (*pref_values)[new_pref_path] = new_pref_value; | 49 (*pref_values)[new_pref_path] = new_pref_value; |
| 59 } | 50 } |
| 60 | 51 |
| 61 // Apply the preference to our local |prefs_| store. | 52 // Apply the preference to our local |prefs_| store. |
| 62 UpdateOnePref(new_pref_path); | 53 UpdateOnePref(new_pref_path); |
| 63 } | 54 } |
| 64 | 55 |
| 65 void ExtensionPrefStore::UninstallExtension(const Extension* extension) { | 56 void ExtensionPrefStore::UninstallExtension(const Extension* extension) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 80 i != extension_stack_.end(); ++i) { | 71 i != extension_stack_.end(); ++i) { |
| 81 (*result).push_back((*i)->extension->id()); | 72 (*result).push_back((*i)->extension->id()); |
| 82 } | 73 } |
| 83 } | 74 } |
| 84 | 75 |
| 85 // This could be sped up by keeping track of which extension currently controls | 76 // This could be sped up by keeping track of which extension currently controls |
| 86 // a given preference, among other optimizations. But probably fewer than 10 | 77 // a given preference, among other optimizations. But probably fewer than 10 |
| 87 // installed extensions will be trying to control any preferences, so stick | 78 // installed extensions will be trying to control any preferences, so stick |
| 88 // with this simpler algorithm until it causes a problem. | 79 // with this simpler algorithm until it causes a problem. |
| 89 void ExtensionPrefStore::UpdateOnePref(const char* path) { | 80 void ExtensionPrefStore::UpdateOnePref(const char* path) { |
| 90 PrefService* pref_service = GetPrefService(); | |
| 91 | |
| 92 // There are at least two PrefServices, one for local state and one for | |
| 93 // user prefs. (See browser_main.cc.) Different preferences are registered | |
| 94 // in each; if this one doesn't have the desired pref registered, we ignore | |
| 95 // it and let the other one handle it. | |
| 96 // The pref_service may be NULL in unit testing. | |
| 97 if (pref_service && !pref_service->FindPreference(path)) | |
| 98 return; | |
| 99 | |
| 100 // Save the old value before removing it from the local cache. | 81 // Save the old value before removing it from the local cache. |
| 101 Value* my_old_value_ptr = NULL; | 82 Value* my_old_value_ptr = NULL; |
| 102 prefs_->Get(path, &my_old_value_ptr); | 83 prefs_->Get(path, &my_old_value_ptr); |
| 103 scoped_ptr<Value> my_old_value; | 84 scoped_ptr<Value> my_old_value; |
| 104 if (my_old_value_ptr) | 85 if (my_old_value_ptr) |
| 105 my_old_value.reset(my_old_value_ptr->DeepCopy()); | 86 my_old_value.reset(my_old_value_ptr->DeepCopy()); |
| 106 | 87 |
| 107 // DictionaryValue::Set complains if a key is overwritten with the same | 88 // DictionaryValue::Set complains if a key is overwritten with the same |
| 108 // value, so remove it first. | 89 // value, so remove it first. |
| 109 prefs_->Remove(path, NULL); | 90 prefs_->Remove(path, NULL); |
| 110 | 91 |
| 111 // Find the first extension that wants to set this pref and use its value. | 92 // Find the first extension that wants to set this pref and use its value. |
| 112 Value* my_new_value = NULL; | 93 Value* my_new_value = NULL; |
| 113 for (ExtensionStack::iterator ext_iter = extension_stack_.begin(); | 94 for (ExtensionStack::iterator ext_iter = extension_stack_.begin(); |
| 114 ext_iter != extension_stack_.end(); ++ext_iter) { | 95 ext_iter != extension_stack_.end(); ++ext_iter) { |
| 115 PrefValueMap::iterator value_iter = (*ext_iter)->pref_values->find(path); | 96 PrefValueMap::iterator value_iter = (*ext_iter)->pref_values->find(path); |
| 116 if (value_iter != (*ext_iter)->pref_values->end()) { | 97 if (value_iter != (*ext_iter)->pref_values->end()) { |
| 117 prefs_->Set(path, (*value_iter).second->DeepCopy()); | 98 prefs_->Set(path, (*value_iter).second->DeepCopy()); |
| 118 my_new_value = (*value_iter).second; | 99 my_new_value = (*value_iter).second; |
| 119 break; | 100 break; |
| 120 } | 101 } |
| 121 } | 102 } |
| 122 | 103 |
| 123 if (pref_service) { | 104 bool value_changed = true; |
| 124 bool value_changed = true; | 105 if (!my_old_value.get() && !my_new_value) { |
| 125 if (!my_old_value.get() && !my_new_value) { | 106 value_changed = false; |
| 126 value_changed = false; | 107 } else if (my_old_value.get() && |
| 127 } else if (my_old_value.get() && | 108 my_new_value && |
| 128 my_new_value && | 109 my_old_value->Equals(my_new_value)) { |
| 129 my_old_value->Equals(my_new_value)) { | 110 value_changed = false; |
| 130 value_changed = false; | 111 } |
| 131 } | |
| 132 | 112 |
| 133 if (value_changed) | 113 if (value_changed) |
| 134 pref_service->pref_notifier()->OnPreferenceSet(path, type_); | 114 NotifyPrefValueChanged(path); |
| 135 } | |
| 136 } | 115 } |
| 137 | 116 |
| 138 void ExtensionPrefStore::UpdatePrefs(const PrefValueMap* pref_values) { | 117 void ExtensionPrefStore::UpdatePrefs(const PrefValueMap* pref_values) { |
| 139 if (!pref_values) | 118 if (!pref_values) |
| 140 return; | 119 return; |
| 141 | 120 |
| 142 for (PrefValueMap::const_iterator i = pref_values->begin(); | 121 for (PrefValueMap::const_iterator i = pref_values->begin(); |
| 143 i != pref_values->end(); ++i) { | 122 i != pref_values->end(); ++i) { |
| 144 UpdateOnePref(i->first); | 123 UpdateOnePref(i->first); |
| 145 } | 124 } |
| 146 } | 125 } |
| 147 | 126 |
| 148 PrefService* ExtensionPrefStore::GetPrefService() { | |
| 149 if (profile_) | |
| 150 return profile_->GetPrefs(); | |
| 151 return g_browser_process->local_state(); | |
| 152 } | |
| 153 | |
| 154 void ExtensionPrefStore::RegisterObservers() { | 127 void ExtensionPrefStore::RegisterObservers() { |
| 155 notification_registrar_.Add(this, | 128 notification_registrar_.Add(this, |
| 156 NotificationType::EXTENSION_PREF_CHANGED, | 129 NotificationType::EXTENSION_PREF_CHANGED, |
| 157 NotificationService::AllSources()); | 130 NotificationService::AllSources()); |
| 158 | 131 |
| 159 notification_registrar_.Add(this, | 132 notification_registrar_.Add(this, |
| 160 NotificationType::EXTENSION_UNLOADED, | 133 NotificationType::EXTENSION_UNLOADED, |
| 161 NotificationService::AllSources()); | 134 NotificationService::AllSources()); |
| 162 } | 135 } |
| 163 | 136 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 190 } | 163 } |
| 191 } | 164 } |
| 192 | 165 |
| 193 ExtensionPrefStore::ExtensionPrefs::ExtensionPrefs(const Extension* extension, | 166 ExtensionPrefStore::ExtensionPrefs::ExtensionPrefs(const Extension* extension, |
| 194 PrefValueMap* values) : extension(extension), pref_values(values) {} | 167 PrefValueMap* values) : extension(extension), pref_values(values) {} |
| 195 | 168 |
| 196 ExtensionPrefStore::ExtensionPrefs::~ExtensionPrefs() { | 169 ExtensionPrefStore::ExtensionPrefs::~ExtensionPrefs() { |
| 197 STLDeleteValues(pref_values); | 170 STLDeleteValues(pref_values); |
| 198 delete pref_values; | 171 delete pref_values; |
| 199 } | 172 } |
| OLD | NEW |