| 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 <limits> | 7 #include <limits> | 
| 8 | 8 | 
| 9 #include "base/logging.h" | 9 #include "base/logging.h" | 
| 10 #include "base/values.h" | 10 #include "base/values.h" | 
| 11 #include "chrome/browser/browser_process.h" | 11 #include "chrome/browser/browser_process.h" | 
| 12 #include "chrome/browser/extensions/extensions_service.h" | 12 #include "chrome/browser/extensions/extensions_service.h" | 
| 13 #include "chrome/browser/extensions/extension_prefs.h" | 13 #include "chrome/browser/extensions/extension_prefs.h" | 
| 14 #include "chrome/browser/prefs/pref_service.h" | 14 #include "chrome/browser/prefs/pref_service.h" | 
| 15 #include "chrome/browser/profile.h" | 15 #include "chrome/browser/profile.h" | 
| 16 #include "chrome/common/extensions/extension.h" | 16 #include "chrome/common/extensions/extension.h" | 
| 17 #include "chrome/common/notification_service.h" | 17 #include "chrome/common/notification_details.h" | 
|  | 18 #include "chrome/common/notification_source.h" | 
|  | 19 #include "chrome/common/notification_type.h" | 
| 18 | 20 | 
| 19 ExtensionPrefStore::ExtensionPrefStore(Profile* profile, | 21 ExtensionPrefStore::ExtensionPrefStore(Profile* profile, | 
| 20                                        PrefNotifier::PrefStoreType type) | 22                                        PrefNotifier::PrefStoreType type) | 
| 21     : prefs_(new DictionaryValue()), | 23     : prefs_(new DictionaryValue()), | 
| 22       profile_(profile), | 24       profile_(profile), | 
| 23       type_(type) { | 25       type_(type) { | 
| 24   RegisterObservers(); | 26   RegisterObservers(); | 
| 25 } | 27 } | 
| 26 | 28 | 
| 27 ExtensionPrefStore::~ExtensionPrefStore() { | 29 ExtensionPrefStore::~ExtensionPrefStore() { | 
| 28   STLDeleteElements(&extension_stack_); | 30   STLDeleteElements(&extension_stack_); | 
| 29   notification_registrar_.RemoveAll(); | 31   notification_registrar_.RemoveAll(); | 
| 30 } | 32 } | 
| 31 | 33 | 
| 32 void ExtensionPrefStore::InstallExtensionPref(const Extension* extension, | 34 void ExtensionPrefStore::InstallExtensionPref(const Extension* extension, | 
| 33                                               const char* new_pref_path, | 35                                               const char* new_pref_path, | 
| 34                                               Value* new_pref_value) { | 36                                               Value* new_pref_value) { | 
| 35   if (extension_stack_.empty()) | 37   if (extension_stack_.empty()) | 
| 36     LazyInit(); | 38     LazyInit(); | 
| 37 | 39 | 
| 38   ExtensionStack::iterator i; | 40   ExtensionStack::iterator i; | 
| 39   for (i = extension_stack_.begin(); i != extension_stack_.end(); ++i) { | 41   for (i = extension_stack_.begin(); i != extension_stack_.end(); ++i) { | 
| 40     if ((*i)->extension_id == extension->id()) | 42     if ((*i)->extension_id == extension->id()) | 
| 41       break; | 43       break; | 
| 42   } | 44   } | 
| 43 | 45 | 
| 44   // If this extension is not already in the stack, add it. Otherwise, update | 46   // If this extension is not already in the stack, add it. Otherwise, update | 
| 45   // or add the value of this preference, but don't change the extension's | 47   // or add the value of this preference, but don't change the extension's | 
| 46   // position in the stack. We store the extension even if this preference | 48   // position in the stack. | 
| 47   // isn't registered with our PrefService, so that the ordering of extensions |  | 
| 48   // is consistent among all local-state and user ExtensionPrefStores. |  | 
| 49   PrefService* pref_service = GetPrefService(); |  | 
| 50   // The pref_service may be NULL in unit testing. |  | 
| 51   bool is_registered_pref = (pref_service == NULL || |  | 
| 52       pref_service->FindPreference(new_pref_path) != NULL); |  | 
| 53   PrefValueMap* pref_values; |  | 
| 54   if (i == extension_stack_.end()) { | 49   if (i == extension_stack_.end()) { | 
| 55     pref_values = new PrefValueMap(); | 50     PrefValueMap* pref_values = new PrefValueMap(); | 
| 56     if (is_registered_pref) | 51     (*pref_values)[new_pref_path] = new_pref_value; | 
| 57       (*pref_values)[new_pref_path] = new_pref_value; |  | 
| 58 | 52 | 
| 59     ExtensionPrefs* extension_prefs = new ExtensionPrefs(extension->id(), | 53     ExtensionPrefs* extension_prefs = new ExtensionPrefs(extension->id(), | 
| 60                                                          pref_values); | 54                                                          pref_values); | 
| 61     extension_stack_.push_front(extension_prefs); | 55     extension_stack_.push_front(extension_prefs); | 
| 62     AddPrecedence(extension->id()); | 56     AddPrecedence(extension->id()); | 
| 63 | 57 | 
| 64   } else if (is_registered_pref) { | 58   } else { | 
| 65     pref_values = (*i)->pref_values; | 59     PrefValueMap* pref_values = (*i)->pref_values; | 
| 66     delete (*pref_values)[new_pref_path]; | 60     delete (*pref_values)[new_pref_path]; | 
| 67     (*pref_values)[new_pref_path] = new_pref_value; | 61     (*pref_values)[new_pref_path] = new_pref_value; | 
| 68   } | 62   } | 
| 69 | 63 | 
| 70   // Apply the preference to our local |prefs_| store. | 64   // Apply the preference to our local |prefs_| store. | 
| 71   UpdateOnePref(new_pref_path); | 65   UpdateOnePref(new_pref_path); | 
| 72 } | 66 } | 
| 73 | 67 | 
| 74 void ExtensionPrefStore::UninstallExtension(const Extension* extension) { | 68 void ExtensionPrefStore::UninstallExtension(const Extension* extension) { | 
| 75   // Remove this extension from the stack. | 69   // Remove this extension from the stack. | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
| 90       i != extension_stack_.end(); ++i) { | 84       i != extension_stack_.end(); ++i) { | 
| 91     (*result).push_back((*i)->extension_id); | 85     (*result).push_back((*i)->extension_id); | 
| 92   } | 86   } | 
| 93 } | 87 } | 
| 94 | 88 | 
| 95 // This could be sped up by keeping track of which extension currently controls | 89 // This could be sped up by keeping track of which extension currently controls | 
| 96 // a given preference, among other optimizations. But probably fewer than 10 | 90 // a given preference, among other optimizations. But probably fewer than 10 | 
| 97 // installed extensions will be trying to control any preferences, so stick | 91 // installed extensions will be trying to control any preferences, so stick | 
| 98 // with this simpler algorithm until it causes a problem. | 92 // with this simpler algorithm until it causes a problem. | 
| 99 void ExtensionPrefStore::UpdateOnePref(const char* path) { | 93 void ExtensionPrefStore::UpdateOnePref(const char* path) { | 
| 100   PrefService* pref_service = GetPrefService(); |  | 
| 101 |  | 
| 102   // There are at least two PrefServices, one for local state and one for |  | 
| 103   // user prefs. (See browser_main.cc.) Different preferences are registered |  | 
| 104   // in each; if this one doesn't have the desired pref registered, we ignore |  | 
| 105   // it and let the other one handle it. |  | 
| 106   // The pref_service may be NULL in unit testing. |  | 
| 107   if (pref_service && !pref_service->FindPreference(path)) |  | 
| 108       return; |  | 
| 109 |  | 
| 110   // Save the old value before removing it from the local cache. | 94   // Save the old value before removing it from the local cache. | 
| 111   Value* my_old_value_ptr = NULL; | 95   Value* my_old_value_ptr = NULL; | 
| 112   prefs_->Get(path, &my_old_value_ptr); | 96   prefs_->Get(path, &my_old_value_ptr); | 
| 113   scoped_ptr<Value> my_old_value; | 97   scoped_ptr<Value> my_old_value; | 
| 114   if (my_old_value_ptr) | 98   if (my_old_value_ptr) | 
| 115     my_old_value.reset(my_old_value_ptr->DeepCopy()); | 99     my_old_value.reset(my_old_value_ptr->DeepCopy()); | 
| 116 | 100 | 
| 117   // DictionaryValue::Set complains if a key is overwritten with the same | 101   // DictionaryValue::Set complains if a key is overwritten with the same | 
| 118   // value, so remove it first. | 102   // value, so remove it first. | 
| 119   prefs_->Remove(path, NULL); | 103   prefs_->Remove(path, NULL); | 
| 120 | 104 | 
| 121   // Find the first extension that wants to set this pref and use its value. | 105   // Find the first extension that wants to set this pref and use its value. | 
| 122   Value* my_new_value = NULL; | 106   Value* my_new_value = NULL; | 
| 123   for (ExtensionStack::iterator ext_iter = extension_stack_.begin(); | 107   for (ExtensionStack::iterator ext_iter = extension_stack_.begin(); | 
| 124         ext_iter != extension_stack_.end(); ++ext_iter) { | 108         ext_iter != extension_stack_.end(); ++ext_iter) { | 
| 125     PrefValueMap::iterator value_iter = (*ext_iter)->pref_values->find(path); | 109     PrefValueMap::iterator value_iter = (*ext_iter)->pref_values->find(path); | 
| 126     if (value_iter != (*ext_iter)->pref_values->end()) { | 110     if (value_iter != (*ext_iter)->pref_values->end()) { | 
| 127       prefs_->Set(path, (*value_iter).second->DeepCopy()); | 111       prefs_->Set(path, (*value_iter).second->DeepCopy()); | 
| 128       my_new_value = (*value_iter).second; | 112       my_new_value = (*value_iter).second; | 
| 129       break; | 113       break; | 
| 130     } | 114     } | 
| 131   } | 115   } | 
| 132 | 116 | 
|  | 117   // May be null in unit tests. | 
|  | 118   PrefService* pref_service = GetPrefService(); | 
| 133   if (pref_service) { | 119   if (pref_service) { | 
| 134     bool value_changed = true; | 120     bool value_changed = true; | 
| 135     if (!my_old_value.get() && !my_new_value) { | 121     if (!my_old_value.get() && !my_new_value) { | 
| 136       value_changed = false; | 122       value_changed = false; | 
| 137     } else if (my_old_value.get() && | 123     } else if (my_old_value.get() && | 
| 138                my_new_value && | 124                my_new_value && | 
| 139                my_old_value->Equals(my_new_value)) { | 125                my_old_value->Equals(my_new_value)) { | 
| 140       value_changed = false; | 126       value_changed = false; | 
| 141     } | 127     } | 
| 142 | 128 | 
| 143     if (value_changed) | 129     if (value_changed) | 
| 144       pref_service->pref_notifier()->OnPreferenceSet(path, type_); | 130       pref_service->pref_notifier()->OnPreferenceSet(path, type_); | 
| 145   } | 131   } | 
| 146 } | 132 } | 
| 147 | 133 | 
| 148 void ExtensionPrefStore::UpdatePrefs(const PrefValueMap* pref_values) { | 134 void ExtensionPrefStore::UpdatePrefs(const PrefValueMap* pref_values) { | 
| 149   if (!pref_values) | 135   if (!pref_values) | 
| 150     return; | 136     return; | 
| 151 | 137 | 
| 152   for (PrefValueMap::const_iterator i = pref_values->begin(); | 138   for (PrefValueMap::const_iterator i = pref_values->begin(); | 
| 153         i != pref_values->end(); ++i) { | 139         i != pref_values->end(); ++i) { | 
| 154     UpdateOnePref(i->first); | 140     UpdateOnePref(i->first); | 
| 155   } | 141   } | 
| 156 } | 142 } | 
| 157 | 143 | 
| 158 PrefService* ExtensionPrefStore::GetPrefService() { | 144 PrefService* ExtensionPrefStore::GetPrefService() { | 
| 159   if (profile_) | 145   // May be null in unit tests. | 
| 160     return profile_->GetPrefs(); | 146   if (!profile_) | 
| 161   return g_browser_process->local_state(); | 147     return NULL; | 
|  | 148   return profile_->GetPrefs(); | 
| 162 } | 149 } | 
| 163 | 150 | 
| 164 void ExtensionPrefStore::RegisterObservers() { | 151 void ExtensionPrefStore::RegisterObservers() { | 
|  | 152   // If profile_==NULL, this ExtensionPrefStore is for local-state. | 
|  | 153   if (!profile_) | 
|  | 154     return; | 
|  | 155 | 
| 165   notification_registrar_.Add(this, | 156   notification_registrar_.Add(this, | 
| 166                               NotificationType::EXTENSION_PREF_CHANGED, | 157                               NotificationType::EXTENSION_PREF_CHANGED, | 
| 167                               NotificationService::AllSources()); | 158                               Source<Profile>(profile_)); | 
| 168 | 159 | 
| 169   notification_registrar_.Add(this, | 160   notification_registrar_.Add(this, | 
| 170                               NotificationType::EXTENSION_UNLOADED, | 161                               NotificationType::EXTENSION_UNLOADED, | 
| 171                               NotificationService::AllSources()); | 162                               Source<Profile>(profile_)); | 
| 172 } | 163 } | 
| 173 | 164 | 
| 174 void ExtensionPrefStore::Observe(NotificationType type, | 165 void ExtensionPrefStore::Observe(NotificationType type, | 
| 175                                  const NotificationSource& source, | 166                                  const NotificationSource& source, | 
| 176                                  const NotificationDetails& details) { | 167                                  const NotificationDetails& details) { | 
| 177   switch (type.value) { | 168   switch (type.value) { | 
| 178     case NotificationType::EXTENSION_PREF_CHANGED: { | 169     case NotificationType::EXTENSION_PREF_CHANGED: { | 
| 179       Profile* extension_profile = Source<Profile>(source).ptr(); | 170       ExtensionPrefStore::ExtensionPrefDetails* data = | 
| 180       // The ExtensionPrefStore for the local state watches all profiles. | 171           Details<ExtensionPrefStore::ExtensionPrefDetails>(details).ptr(); | 
| 181       if (!profile_ || profile_ == extension_profile) { | 172       InstallExtensionPref(data->first, data->second.first, | 
| 182         ExtensionPrefStore::ExtensionPrefDetails* data = | 173           data->second.second); | 
| 183             Details<ExtensionPrefStore::ExtensionPrefDetails>(details).ptr(); |  | 
| 184         InstallExtensionPref(data->first, data->second.first, |  | 
| 185             data->second.second); |  | 
| 186       } |  | 
| 187       break; | 174       break; | 
| 188     } | 175     } | 
| 189     case NotificationType::EXTENSION_UNLOADED: { | 176     case NotificationType::EXTENSION_UNLOADED: { | 
| 190       Profile* extension_profile = Source<Profile>(source).ptr(); |  | 
| 191       const Extension* extension = Details<const Extension>(details).ptr(); | 177       const Extension* extension = Details<const Extension>(details).ptr(); | 
| 192       // The ExtensionPrefStore for the local state watches all profiles. | 178       UninstallExtension(extension); | 
| 193       if (profile_ == NULL || profile_ == extension_profile) |  | 
| 194         UninstallExtension(extension); |  | 
| 195       break; | 179       break; | 
| 196     } | 180     } | 
| 197     default: { | 181     default: { | 
| 198       NOTREACHED(); | 182       NOTREACHED(); | 
| 199     } | 183     } | 
| 200   } | 184   } | 
| 201 } | 185 } | 
| 202 | 186 | 
| 203 void ExtensionPrefStore::AddPrecedence(const std::string& extension_id) { | 187 void ExtensionPrefStore::AddPrecedence(const std::string& extension_id) { | 
| 204   std::vector<std::string> precedence; | 188   std::vector<std::string> precedence; | 
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 259 } | 243 } | 
| 260 | 244 | 
| 261 ExtensionPrefStore::ExtensionPrefs::ExtensionPrefs( | 245 ExtensionPrefStore::ExtensionPrefs::ExtensionPrefs( | 
| 262     const std::string& extension_id, PrefValueMap* values) | 246     const std::string& extension_id, PrefValueMap* values) | 
| 263     : extension_id(extension_id), pref_values(values) {} | 247     : extension_id(extension_id), pref_values(values) {} | 
| 264 | 248 | 
| 265 ExtensionPrefStore::ExtensionPrefs::~ExtensionPrefs() { | 249 ExtensionPrefStore::ExtensionPrefs::~ExtensionPrefs() { | 
| 266   STLDeleteValues(pref_values); | 250   STLDeleteValues(pref_values); | 
| 267   delete pref_values; | 251   delete pref_values; | 
| 268 } | 252 } | 
| OLD | NEW | 
|---|