Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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_preference_api.h" | 5 #include "chrome/browser/extensions/extension_preference_api.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 | 8 |
| 9 #include "base/json/json_writer.h" | 9 #include "base/json/json_writer.h" |
| 10 #include "base/singleton.h" | 10 #include "base/singleton.h" |
| 11 #include "base/stl_util-inl.h" | 11 #include "base/stl_util-inl.h" |
| 12 #include "base/stringprintf.h" | 12 #include "base/stringprintf.h" |
| 13 #include "base/values.h" | 13 #include "base/values.h" |
| 14 #include "chrome/browser/extensions/extension_event_router.h" | |
| 14 #include "chrome/browser/extensions/extension_prefs.h" | 15 #include "chrome/browser/extensions/extension_prefs.h" |
| 15 #include "chrome/browser/extensions/extension_proxy_api.h" | 16 #include "chrome/browser/extensions/extension_proxy_api.h" |
| 16 #include "chrome/browser/extensions/extension_service.h" | 17 #include "chrome/browser/extensions/extension_service.h" |
| 17 #include "chrome/browser/profiles/profile.h" | 18 #include "chrome/browser/profiles/profile.h" |
| 18 #include "chrome/common/pref_names.h" | 19 #include "chrome/common/pref_names.h" |
| 20 #include "content/common/notification_type.h" | |
| 21 #include "content/common/notification_service.h" | |
| 19 | 22 |
| 20 namespace { | 23 namespace { |
| 21 | 24 |
| 22 struct PrefMappingEntry { | 25 struct PrefMappingEntry { |
| 23 const char* extension_pref; | 26 const char* extension_pref; |
| 24 const char* browser_pref; | 27 const char* browser_pref; |
| 25 const char* permission; | 28 const char* permission; |
| 26 }; | 29 }; |
| 27 | 30 |
| 28 const char kNotControllable[] = "NotControllable"; | 31 const char kNotControllable[] = "NotControllable"; |
| 29 const char kControlledByOtherExtensions[] = "ControlledByOtherExtensions"; | 32 const char kControlledByOtherExtensions[] = "ControlledByOtherExtensions"; |
| 30 const char kControllableByThisExtension[] = "ControllableByThisExtension"; | 33 const char kControllableByThisExtension[] = "ControllableByThisExtension"; |
| 31 const char kControlledByThisExtension[] = "ControlledByThisExtension"; | 34 const char kControlledByThisExtension[] = "ControlledByThisExtension"; |
| 32 | 35 |
| 33 const char kIncognito[] = "incognito"; | 36 const char kIncognito[] = "incognito"; |
| 34 const char kIncognitoSpecific[] = "incognitoSpecific"; | 37 const char kIncognitoSpecific[] = "incognitoSpecific"; |
| 35 const char kLevelOfControl[] = "levelOfControl"; | 38 const char kLevelOfControl[] = "levelOfControl"; |
| 36 const char kValue[] = "value"; | 39 const char kValue[] = "value"; |
| 37 | 40 |
| 41 const char kOnPrefChangeFormat[] = "experimental.preferences.%s.onChange"; | |
| 42 | |
| 38 const char kIncognitoErrorMessage[] = | 43 const char kIncognitoErrorMessage[] = |
| 39 "You do not have permission to access incognito preferences."; | 44 "You do not have permission to access incognito preferences."; |
| 40 | 45 |
| 41 const char kPermissionErrorMessage[] = | 46 const char kPermissionErrorMessage[] = |
| 42 "You do not have permission to access the preference '%s'. " | 47 "You do not have permission to access the preference '%s'. " |
| 43 "Be sure to declare in your manifest what permissions you need."; | 48 "Be sure to declare in your manifest what permissions you need."; |
| 44 | 49 |
| 45 PrefMappingEntry kPrefMapping[] = { | 50 PrefMappingEntry kPrefMapping[] = { |
| 46 { "blockThirdPartyCookies", | 51 { "blockThirdPartyCookies", |
| 47 prefs::kBlockThirdPartyCookies, | 52 prefs::kBlockThirdPartyCookies, |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 61 virtual Value* ExtensionToBrowserPref(const Value* extension_pref, | 66 virtual Value* ExtensionToBrowserPref(const Value* extension_pref, |
| 62 std::string* error) { | 67 std::string* error) { |
| 63 return extension_pref->DeepCopy(); | 68 return extension_pref->DeepCopy(); |
| 64 } | 69 } |
| 65 | 70 |
| 66 virtual Value* BrowserToExtensionPref(const Value* browser_pref) { | 71 virtual Value* BrowserToExtensionPref(const Value* browser_pref) { |
| 67 return browser_pref->DeepCopy(); | 72 return browser_pref->DeepCopy(); |
| 68 } | 73 } |
| 69 }; | 74 }; |
| 70 | 75 |
| 76 // Returns a string constant (defined in the API) indicating the level of | |
| 77 // control this extension has over the specified preference. | |
| 78 const char* GetLevelOfControl( | |
| 79 Profile* profile, | |
| 80 const std::string& extension_id, | |
| 81 const std::string& browser_pref, | |
| 82 bool incognito) { | |
| 83 PrefService* prefs = incognito ? profile->GetOffTheRecordPrefs() | |
| 84 : profile->GetPrefs(); | |
| 85 const PrefService::Preference* pref = | |
| 86 prefs->FindPreference(browser_pref.c_str()); | |
| 87 CHECK(pref); | |
| 88 ExtensionPrefs* ep = profile->GetExtensionService()->extension_prefs(); | |
| 89 | |
| 90 if (!pref->IsExtensionModifiable()) | |
| 91 return kNotControllable; | |
| 92 | |
| 93 if (ep->DoesExtensionControlPref(extension_id, browser_pref, incognito)) | |
| 94 return kControlledByThisExtension; | |
| 95 | |
| 96 if (ep->CanExtensionControlPref(extension_id, browser_pref, incognito)) | |
| 97 return kControllableByThisExtension; | |
| 98 | |
| 99 return kControlledByOtherExtensions; | |
| 100 } | |
| 101 | |
| 71 class PrefMapping { | 102 class PrefMapping { |
| 72 public: | 103 public: |
| 73 static PrefMapping* GetInstance() { | 104 static PrefMapping* GetInstance() { |
| 74 return Singleton<PrefMapping>::get(); | 105 return Singleton<PrefMapping>::get(); |
| 75 } | 106 } |
| 76 | 107 |
| 77 bool FindBrowserPrefForExtensionPref(const std::string& extension_pref, | 108 bool FindBrowserPrefForExtensionPref(const std::string& extension_pref, |
| 78 std::string* browser_pref, | 109 std::string* browser_pref, |
| 79 std::string* permission) { | 110 std::string* permission) { |
| 80 std::map<std::string, std::pair<std::string, std::string> >::iterator it = | 111 std::map<std::string, std::pair<std::string, std::string> >::iterator it = |
| 81 mapping_.find(extension_pref); | 112 mapping_.find(extension_pref); |
| 82 if (it != mapping_.end()) { | 113 if (it != mapping_.end()) { |
| 83 *browser_pref = it->second.first; | 114 *browser_pref = it->second.first; |
| 84 *permission = it->second.second; | 115 *permission = it->second.second; |
| 85 return true; | 116 return true; |
| 86 } | 117 } |
| 87 return false; | 118 return false; |
| 88 } | 119 } |
| 89 | 120 |
| 121 bool FindEventForBrowserPref(const std::string& browser_pref, | |
| 122 std::string* event_name, | |
| 123 std::string* permission) { | |
| 124 std::map<std::string, std::pair<std::string, std::string> >::iterator it = | |
| 125 event_mapping_.find(browser_pref); | |
| 126 if (it != event_mapping_.end()) { | |
| 127 *event_name = it->second.first; | |
| 128 *permission = it->second.second; | |
| 129 return true; | |
| 130 } | |
| 131 return false; | |
| 132 } | |
| 133 | |
| 90 PrefTransformerInterface* FindTransformerForBrowserPref( | 134 PrefTransformerInterface* FindTransformerForBrowserPref( |
| 91 const std::string& browser_pref) { | 135 const std::string& browser_pref) { |
| 92 std::map<std::string, PrefTransformerInterface*>::iterator it = | 136 std::map<std::string, PrefTransformerInterface*>::iterator it = |
| 93 transformers_.find(browser_pref); | 137 transformers_.find(browser_pref); |
| 94 if (it != transformers_.end()) | 138 if (it != transformers_.end()) |
| 95 return it->second; | 139 return it->second; |
| 96 else | 140 else |
| 97 return identity_transformer_.get(); | 141 return identity_transformer_.get(); |
| 98 } | 142 } |
| 99 | 143 |
| 100 private: | 144 private: |
| 101 friend struct DefaultSingletonTraits<PrefMapping>; | 145 friend struct DefaultSingletonTraits<PrefMapping>; |
| 102 | 146 |
| 103 PrefMapping() { | 147 PrefMapping() { |
| 104 identity_transformer_.reset(new IdentityPrefTransformer()); | 148 identity_transformer_.reset(new IdentityPrefTransformer()); |
| 105 for (size_t i = 0; i < arraysize(kPrefMapping); ++i) { | 149 for (size_t i = 0; i < arraysize(kPrefMapping); ++i) { |
| 106 mapping_[kPrefMapping[i].extension_pref] = | 150 mapping_[kPrefMapping[i].extension_pref] = |
| 107 std::make_pair(kPrefMapping[i].browser_pref, | 151 std::make_pair(kPrefMapping[i].browser_pref, |
| 108 kPrefMapping[i].permission); | 152 kPrefMapping[i].permission); |
| 153 std::string event_name = | |
| 154 base::StringPrintf(kOnPrefChangeFormat, | |
| 155 kPrefMapping[i].extension_pref); | |
| 156 event_mapping_[kPrefMapping[i].browser_pref] = | |
| 157 std::make_pair(event_name, kPrefMapping[i].permission); | |
| 109 } | 158 } |
| 110 DCHECK_EQ(arraysize(kPrefMapping), mapping_.size()); | 159 DCHECK_EQ(arraysize(kPrefMapping), mapping_.size()); |
| 160 DCHECK_EQ(arraysize(kPrefMapping), event_mapping_.size()); | |
| 111 RegisterPrefTransformer(prefs::kProxy, new ProxyPrefTransformer()); | 161 RegisterPrefTransformer(prefs::kProxy, new ProxyPrefTransformer()); |
| 112 } | 162 } |
| 113 | 163 |
| 114 ~PrefMapping() { | 164 ~PrefMapping() { |
| 115 STLDeleteContainerPairSecondPointers(transformers_.begin(), | 165 STLDeleteContainerPairSecondPointers(transformers_.begin(), |
| 116 transformers_.end()); | 166 transformers_.end()); |
| 117 } | 167 } |
| 118 | 168 |
| 119 void RegisterPrefTransformer(const std::string& browser_pref, | 169 void RegisterPrefTransformer(const std::string& browser_pref, |
| 120 PrefTransformerInterface* transformer) { | 170 PrefTransformerInterface* transformer) { |
| 121 DCHECK_EQ(0u, transformers_.count(browser_pref)) << | 171 DCHECK_EQ(0u, transformers_.count(browser_pref)) << |
| 122 "Trying to register pref transformer for " << browser_pref << " twice"; | 172 "Trying to register pref transformer for " << browser_pref << " twice"; |
| 123 transformers_[browser_pref] = transformer; | 173 transformers_[browser_pref] = transformer; |
| 124 } | 174 } |
| 125 | 175 |
| 126 // Mapping from extension pref keys to browser pref keys. | 176 // Mapping from extension pref keys to browser pref keys. |
| 127 std::map<std::string, std::pair<std::string, std::string> > mapping_; | 177 std::map<std::string, std::pair<std::string, std::string> > mapping_; |
| 128 | 178 |
| 179 // Mapping from browser pref keys to extension event names. | |
|
battre
2011/03/16 13:07:35
"to extension event names" is not quite correct, i
| |
| 180 std::map<std::string, std::pair<std::string, std::string> > event_mapping_; | |
| 129 | 181 |
| 130 // Mapping from browser pref keys to transformers. | 182 // Mapping from browser pref keys to transformers. |
| 131 std::map<std::string, PrefTransformerInterface*> transformers_; | 183 std::map<std::string, PrefTransformerInterface*> transformers_; |
| 132 | 184 |
| 133 scoped_ptr<PrefTransformerInterface> identity_transformer_; | 185 scoped_ptr<PrefTransformerInterface> identity_transformer_; |
| 186 | |
| 187 DISALLOW_COPY_AND_ASSIGN(PrefMapping); | |
| 134 }; | 188 }; |
| 135 | 189 |
| 136 } // namespace | 190 } // namespace |
| 137 | 191 |
| 192 ExtensionPreferenceEventRouter::ExtensionPreferenceEventRouter( | |
| 193 Profile* profile) : profile_(profile) { | |
| 194 registrar_.Init(profile_->GetPrefs()); | |
| 195 incognito_registrar_.Init(profile_->GetOffTheRecordPrefs()); | |
| 196 for (size_t i = 0; i < arraysize(kPrefMapping); ++i) { | |
| 197 registrar_.Add(kPrefMapping[i].browser_pref, this); | |
| 198 incognito_registrar_.Add(kPrefMapping[i].browser_pref, this); | |
| 199 } | |
| 200 } | |
| 201 | |
| 202 ExtensionPreferenceEventRouter::~ExtensionPreferenceEventRouter() { } | |
| 203 | |
| 204 void ExtensionPreferenceEventRouter::Observe( | |
| 205 NotificationType type, | |
| 206 const NotificationSource& source, | |
| 207 const NotificationDetails& details) { | |
| 208 if (type == NotificationType::PREF_CHANGED) { | |
| 209 const std::string* pref_key = | |
| 210 Details<const std::string>(details).ptr(); | |
| 211 OnPrefChanged(Source<PrefService>(source).ptr(), *pref_key); | |
| 212 } else { | |
| 213 NOTREACHED(); | |
| 214 } | |
| 215 } | |
| 216 | |
| 217 void ExtensionPreferenceEventRouter::OnPrefChanged( | |
| 218 PrefService* pref_service, | |
| 219 const std::string& browser_pref) { | |
| 220 bool incognito = (pref_service != profile_->GetPrefs()); | |
| 221 | |
| 222 std::string event_name; | |
| 223 std::string permission; | |
| 224 bool rv = PrefMapping::GetInstance()->FindEventForBrowserPref( | |
| 225 browser_pref, &event_name, &permission); | |
| 226 DCHECK(rv); | |
| 227 | |
| 228 ListValue args; | |
| 229 DictionaryValue* dict = new DictionaryValue(); | |
| 230 args.Append(dict); | |
| 231 const PrefService::Preference* pref = | |
| 232 pref_service->FindPreference(browser_pref.c_str()); | |
| 233 CHECK(pref); | |
| 234 ExtensionService* extension_service = profile_->GetExtensionService(); | |
| 235 PrefTransformerInterface* transformer = | |
| 236 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref); | |
| 237 dict->Set(kValue, transformer->BrowserToExtensionPref(pref->GetValue())); | |
| 238 if (incognito) { | |
| 239 ExtensionPrefs* ep = extension_service->extension_prefs(); | |
| 240 dict->Set( | |
| 241 kIncognitoSpecific, | |
| 242 Value::CreateBooleanValue(ep->HasIncognitoPrefValue(browser_pref))); | |
| 243 } | |
| 244 | |
| 245 ExtensionEventRouter* router = profile_->GetExtensionEventRouter(); | |
| 246 if (!router || !router->HasEventListener(event_name)) | |
| 247 return; | |
| 248 const ExtensionList* extensions = extension_service->extensions(); | |
| 249 for (ExtensionList::const_iterator it = extensions->begin(); | |
| 250 it != extensions->end(); ++it) { | |
| 251 std::string extension_id = (*it)->id(); | |
| 252 // TODO(bauerb): Only iterate over registered event listeners. | |
| 253 if (router->ExtensionHasEventListener(extension_id, event_name) && | |
| 254 (*it)->HasApiPermission(permission) && | |
| 255 (!incognito || extension_service->CanCrossIncognito(*it))) { | |
| 256 std::string level_of_control = | |
| 257 GetLevelOfControl(profile_, extension_id, browser_pref, incognito); | |
| 258 dict->Set(kLevelOfControl, Value::CreateStringValue(level_of_control)); | |
| 259 | |
| 260 std::string json_args; | |
| 261 base::JSONWriter::Write(&args, false, &json_args); | |
| 262 | |
| 263 DispatchEvent(extension_id, event_name, json_args); | |
| 264 } | |
| 265 } | |
| 266 } | |
| 267 | |
| 268 void ExtensionPreferenceEventRouter::DispatchEvent( | |
| 269 const std::string& extension_id, | |
| 270 const std::string& event_name, | |
| 271 const std::string& json_args) { | |
| 272 profile_->GetExtensionEventRouter()->DispatchEventToExtension( | |
| 273 extension_id, event_name, json_args, NULL, GURL()); | |
| 274 } | |
| 275 | |
| 138 // TODO(battre): Factor out common parts once this is stable. | 276 // TODO(battre): Factor out common parts once this is stable. |
| 139 | 277 |
| 140 GetPreferenceFunction::~GetPreferenceFunction() { } | 278 GetPreferenceFunction::~GetPreferenceFunction() { } |
| 141 | 279 |
| 142 const char* GetPreferenceFunction::GetLevelOfControl( | |
| 143 const std::string& browser_pref, | |
| 144 bool incognito) const { | |
| 145 PrefService* prefs = incognito ? profile_->GetOffTheRecordPrefs() | |
| 146 : profile_->GetPrefs(); | |
| 147 const PrefService::Preference* pref = | |
| 148 prefs->FindPreference(browser_pref.c_str()); | |
| 149 CHECK(pref); | |
| 150 ExtensionPrefs* ep = profile_->GetExtensionService()->extension_prefs(); | |
| 151 | |
| 152 if (!pref->IsExtensionModifiable()) | |
| 153 return kNotControllable; | |
| 154 | |
| 155 if (ep->DoesExtensionControlPref(extension_id(), browser_pref, incognito)) | |
| 156 return kControlledByThisExtension; | |
| 157 | |
| 158 if (ep->CanExtensionControlPref(extension_id(), browser_pref, incognito)) | |
| 159 return kControllableByThisExtension; | |
| 160 | |
| 161 return kControlledByOtherExtensions; | |
| 162 } | |
| 163 | |
| 164 bool GetPreferenceFunction::RunImpl() { | 280 bool GetPreferenceFunction::RunImpl() { |
| 165 std::string pref_key; | 281 std::string pref_key; |
| 166 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key)); | 282 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key)); |
| 167 DictionaryValue* details = NULL; | 283 DictionaryValue* details = NULL; |
| 168 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details)); | 284 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details)); |
| 169 | 285 |
| 170 bool incognito = false; | 286 bool incognito = false; |
| 171 if (details->HasKey(kIncognito)) | 287 if (details->HasKey(kIncognito)) |
| 172 EXTENSION_FUNCTION_VALIDATE(details->GetBoolean(kIncognito, &incognito)); | 288 EXTENSION_FUNCTION_VALIDATE(details->GetBoolean(kIncognito, &incognito)); |
| 173 | 289 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 184 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( | 300 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( |
| 185 pref_key, &browser_pref, &permission)); | 301 pref_key, &browser_pref, &permission)); |
| 186 if (!GetExtension()->HasApiPermission(permission)) { | 302 if (!GetExtension()->HasApiPermission(permission)) { |
| 187 error_ = base::StringPrintf(kPermissionErrorMessage, pref_key.c_str()); | 303 error_ = base::StringPrintf(kPermissionErrorMessage, pref_key.c_str()); |
| 188 return false; | 304 return false; |
| 189 } | 305 } |
| 190 | 306 |
| 191 const PrefService::Preference* pref = | 307 const PrefService::Preference* pref = |
| 192 prefs->FindPreference(browser_pref.c_str()); | 308 prefs->FindPreference(browser_pref.c_str()); |
| 193 CHECK(pref); | 309 CHECK(pref); |
| 194 std::string level_of_control = GetLevelOfControl(browser_pref, incognito); | 310 std::string level_of_control = |
| 311 GetLevelOfControl(profile_, extension_id(), browser_pref, incognito); | |
| 195 | 312 |
| 196 scoped_ptr<DictionaryValue> result(new DictionaryValue); | 313 scoped_ptr<DictionaryValue> result(new DictionaryValue); |
| 197 PrefTransformerInterface* transformer = | 314 PrefTransformerInterface* transformer = |
| 198 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref); | 315 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref); |
| 199 result->Set(kValue, transformer->BrowserToExtensionPref(pref->GetValue())); | 316 result->Set(kValue, transformer->BrowserToExtensionPref(pref->GetValue())); |
| 200 result->Set(kLevelOfControl, Value::CreateStringValue(level_of_control)); | 317 result->Set(kLevelOfControl, Value::CreateStringValue(level_of_control)); |
| 201 if (incognito) { | 318 if (incognito) { |
| 202 ExtensionPrefs* ep = profile_->GetExtensionService()->extension_prefs(); | 319 ExtensionPrefs* ep = profile_->GetExtensionService()->extension_prefs(); |
| 203 result->Set( | 320 result->Set( |
| 204 kIncognitoSpecific, | 321 kIncognitoSpecific, |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 278 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( | 395 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( |
| 279 pref_key, &browser_pref, &permission)); | 396 pref_key, &browser_pref, &permission)); |
| 280 if (!GetExtension()->HasApiPermission(permission)) { | 397 if (!GetExtension()->HasApiPermission(permission)) { |
| 281 error_ = base::StringPrintf(kPermissionErrorMessage, pref_key.c_str()); | 398 error_ = base::StringPrintf(kPermissionErrorMessage, pref_key.c_str()); |
| 282 return false; | 399 return false; |
| 283 } | 400 } |
| 284 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); | 401 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); |
| 285 prefs->RemoveExtensionControlledPref(extension_id(), browser_pref, incognito); | 402 prefs->RemoveExtensionControlledPref(extension_id(), browser_pref, incognito); |
| 286 return true; | 403 return true; |
| 287 } | 404 } |
| OLD | NEW |