Chromium Code Reviews| Index: chrome/browser/extensions/extension_preference_api.cc |
| diff --git a/chrome/browser/extensions/extension_preference_api.cc b/chrome/browser/extensions/extension_preference_api.cc |
| index 088c8cfc9392d09bf400b192d0ddd134c099707c..8fa0ac23f6d5a039f49d30edccf095530ff8da93 100644 |
| --- a/chrome/browser/extensions/extension_preference_api.cc |
| +++ b/chrome/browser/extensions/extension_preference_api.cc |
| @@ -4,22 +4,20 @@ |
| #include "chrome/browser/extensions/extension_preference_api.h" |
| +#include "base/json/json_writer.h" |
| #include "base/singleton.h" |
| #include "base/stringprintf.h" |
| #include "base/values.h" |
| +#include "chrome/browser/extensions/extension_event_router.h" |
| #include "chrome/browser/extensions/extension_prefs.h" |
| #include "chrome/browser/extensions/extension_service.h" |
| #include "chrome/browser/profiles/profile.h" |
| +#include "chrome/common/notification_type.h" |
| +#include "chrome/common/notification_service.h" |
| #include "chrome/common/pref_names.h" |
| namespace { |
| -struct PrefMappingEntry { |
| - const char* extension_pref; |
| - const char* browser_pref; |
| - const char* permission; |
| -}; |
| - |
| const char kNotControllable[] = "NotControllable"; |
| const char kControlledByOtherExtensions[] = "ControlledByOtherExtensions"; |
| const char kControllableByThisExtension[] = "ControllableByThisExtension"; |
| @@ -30,10 +28,22 @@ const char kIncognitoSpecific[] = "incognitoSpecific"; |
| const char kLevelOfControl[] = "levelOfControl"; |
| const char kValue[] = "value"; |
| +const char kOnPrefChangeFormat[] = "experimental.preferences.%s.onChange"; |
| + |
| +const char kPermissionErrorMessage[] = |
| + "You do not have permission to access the preference '%s'. " |
| + "Be sure to declare in your manifest what permissions you need."; |
| + |
| const char kIncognitoErrorMessage[] = |
| "You do not have permission to access incognito preferences."; |
| -PrefMappingEntry pref_mapping[] = { |
| +struct PrefMappingEntry { |
| + const char* extension_pref; |
| + const char* browser_pref; |
| + const char* permission; |
| +}; |
| + |
| +PrefMappingEntry kPrefMapping[] = { |
| { "blockThirdPartyCookies", |
| prefs::kBlockThirdPartyCookies, |
| Extension::kContentSettingsPermission |
| @@ -63,52 +73,156 @@ class PrefMapping { |
| return false; |
| } |
| + bool FindEventForBrowserPref(const std::string& browser_pref, |
| + std::string* event_name, |
| + std::string* permission) { |
| + std::map<std::string, std::pair<std::string, std::string> >::iterator it = |
| + event_mapping_.find(browser_pref); |
| + if (it != event_mapping_.end()) { |
| + *event_name = it->second.first; |
| + *permission = it->second.second; |
| + return true; |
| + } |
| + return false; |
| + } |
| + |
| private: |
| friend struct DefaultSingletonTraits<PrefMapping>; |
| + // Mapping from extension pref keys to browser pref keys. |
|
battre
2011/03/10 13:07:28
Thanks you :-)
|
| std::map<std::string, std::pair<std::string, std::string> > mapping_; |
| + // Mapping from browser pref keys to extension event names. |
| + std::map<std::string, std::pair<std::string, std::string> > event_mapping_; |
| + |
| PrefMapping() { |
| - for (size_t i = 0; i < arraysize(pref_mapping); ++i) { |
| - mapping_[pref_mapping[i].extension_pref] = |
| - std::make_pair(pref_mapping[i].browser_pref, |
| - pref_mapping[i].permission); |
| + for (size_t i = 0; i < arraysize(kPrefMapping); ++i) { |
| + mapping_[kPrefMapping[i].extension_pref] = |
| + std::make_pair(kPrefMapping[i].browser_pref, |
| + kPrefMapping[i].permission); |
| + std::string event_name = |
| + base::StringPrintf(kOnPrefChangeFormat, |
| + kPrefMapping[i].extension_pref); |
| + event_mapping_[kPrefMapping[i].browser_pref] = |
| + std::make_pair(event_name, kPrefMapping[i].permission); |
| } |
|
battre
2011/03/10 13:07:28
DCHECK(mapping_.size()==arraysize(kPrefMapping) &&
Bernhard Bauer
2011/03/10 14:51:15
Done.
|
| } |
| }; |
| -const char kPermissionErrorMessage[] = |
| - "You do not have permission to access the preference '%s'. " |
| - "Be sure to declare in your manifest what permissions you need."; |
| - |
| -} // namespace |
| - |
| -// TODO(battre): Factor out common parts once this is stable. |
| - |
| -GetPreferenceFunction::~GetPreferenceFunction() { } |
| - |
| -const char* GetPreferenceFunction::GetLevelOfControl( |
| +// Returns a string constant (defined in the API) indicating the level of |
| +// control this extension has over the specified preference. |
| +const char* GetLevelOfControl( |
| + Profile* profile, |
| + const std::string& extension_id, |
| const std::string& browser_pref, |
| - bool incognito) const { |
| - PrefService* prefs = incognito ? profile_->GetOffTheRecordPrefs() |
| - : profile_->GetPrefs(); |
| + bool incognito) { |
| + PrefService* prefs = incognito ? profile->GetOffTheRecordPrefs() |
| + : profile->GetPrefs(); |
| const PrefService::Preference* pref = |
| prefs->FindPreference(browser_pref.c_str()); |
| CHECK(pref); |
| - ExtensionPrefs* ep = profile_->GetExtensionService()->extension_prefs(); |
| + ExtensionPrefs* ep = profile->GetExtensionService()->extension_prefs(); |
| if (!pref->IsExtensionModifiable()) |
| return kNotControllable; |
| - if (ep->DoesExtensionControlPref(extension_id(), browser_pref, incognito)) |
| + if (ep->DoesExtensionControlPref(extension_id, browser_pref, incognito)) |
| return kControlledByThisExtension; |
| - if (ep->CanExtensionControlPref(extension_id(), browser_pref, incognito)) |
| + if (ep->CanExtensionControlPref(extension_id, browser_pref, incognito)) |
| return kControllableByThisExtension; |
| return kControlledByOtherExtensions; |
| } |
| +} // namespace |
| + |
| +ExtensionPreferenceEventRouter::ExtensionPreferenceEventRouter( |
| + Profile* profile) : profile_(profile) { |
| + registrar_.Init(profile_->GetPrefs()); |
| + incognito_registrar_.Init(profile_->GetOffTheRecordPrefs()); |
| + for (size_t i = 0; i < arraysize(kPrefMapping); ++i) { |
| + registrar_.Add(kPrefMapping[i].browser_pref, this); |
| + incognito_registrar_.Add(kPrefMapping[i].browser_pref, this); |
| + } |
| +} |
| + |
| +ExtensionPreferenceEventRouter::~ExtensionPreferenceEventRouter() { } |
| + |
| +void ExtensionPreferenceEventRouter::Observe( |
| + NotificationType type, |
| + const NotificationSource& source, |
| + const NotificationDetails& details) { |
| + if (type == NotificationType::PREF_CHANGED) { |
| + const std::string* pref_key = |
| + Details<const std::string>(details).ptr(); |
| + OnPrefChanged(Source<PrefService>(source).ptr(), *pref_key); |
|
battre
2011/03/10 13:07:28
PREF_CHANGED is only fired when the effective valu
Bernhard Bauer
2011/03/10 14:51:15
Oh, I was assuming it is also fired when the level
battre
2011/03/11 09:28:36
This is not implemented, yet.
|
| + } else { |
| + NOTREACHED(); |
| + } |
| +} |
| + |
| +void ExtensionPreferenceEventRouter::OnPrefChanged( |
| + PrefService* pref_service, |
| + const std::string& browser_pref) { |
| + bool incognito = (pref_service != profile_->GetPrefs()); |
| + |
| + std::string event_name; |
| + std::string permission; |
| + bool rv = PrefMapping::GetInstance()->FindEventForBrowserPref( |
| + browser_pref, &event_name, &permission); |
| + DCHECK(rv); |
| + |
| + ListValue args; |
| + DictionaryValue* dict = new DictionaryValue(); |
| + args.Append(dict); |
| + const PrefService::Preference* pref = |
| + pref_service->FindPreference(browser_pref.c_str()); |
| + CHECK(pref); |
| + ExtensionService* extension_service = profile_->GetExtensionService(); |
| + dict->Set(kValue, pref->GetValue()->DeepCopy()); |
|
battre
2011/03/10 13:07:28
The proxy settings API needs a hook to modify this
Bernhard Bauer
2011/03/10 14:51:15
Hm, I see. I guess we'll need a separate event rou
battre
2011/03/11 09:28:36
Yes, we could even extract the value transformatio
|
| + if (incognito) { |
| + ExtensionPrefs* ep = extension_service->extension_prefs(); |
| + dict->Set( |
| + kIncognitoSpecific, |
| + Value::CreateBooleanValue(ep->HasIncognitoPrefValue(browser_pref))); |
| + } |
| + |
| + ExtensionEventRouter* router = profile_->GetExtensionEventRouter(); |
| + if (!router || !router->HasEventListener(event_name)) |
| + return; |
| + const ExtensionList* extensions = extension_service->extensions(); |
| + for (ExtensionList::const_iterator it = extensions->begin(); |
| + it != extensions->end(); ++it) { |
| + std::string extension_id = (*it)->id(); |
| + // TODO(bauerb): Only iterate over registered event listeners. |
| + if (router->ExtensionHasEventListener(extension_id, event_name) && |
| + (*it)->HasApiPermission(permission) && |
| + (!incognito || extension_service->CanCrossIncognito(*it))) { |
| + std::string level_of_control = |
| + GetLevelOfControl(profile_, extension_id, browser_pref, incognito); |
| + dict->Set(kLevelOfControl, Value::CreateStringValue(level_of_control)); |
| + |
| + std::string json_args; |
| + base::JSONWriter::Write(&args, false, &json_args); |
| + |
| + DispatchEvent(extension_id, event_name, json_args); |
| + } |
| + } |
| +} |
| + |
| +void ExtensionPreferenceEventRouter::DispatchEvent( |
| + const std::string& extension_id, |
| + const std::string& event_name, |
| + const std::string& json_args) { |
| + profile_->GetExtensionEventRouter()->DispatchEventToExtension( |
| + extension_id, event_name, json_args, NULL, GURL()); |
| +} |
| + |
| +// TODO(battre): Factor out common parts once this is stable. |
| + |
| +GetPreferenceFunction::~GetPreferenceFunction() { } |
| + |
| bool GetPreferenceFunction::RunImpl() { |
| std::string pref_key; |
| EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key)); |
| @@ -139,7 +253,8 @@ bool GetPreferenceFunction::RunImpl() { |
| const PrefService::Preference* pref = |
| prefs->FindPreference(browser_pref.c_str()); |
| CHECK(pref); |
| - std::string level_of_control = GetLevelOfControl(browser_pref, incognito); |
| + std::string level_of_control = |
| + GetLevelOfControl(profile_, extension_id(), browser_pref, incognito); |
| scoped_ptr<DictionaryValue> result(new DictionaryValue); |
| result->Set(kValue, pref->GetValue()->DeepCopy()); |