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 73e29ce6997a24592c803d141e0bc30737a5bb3c..edc33d2229b3cd87812c308316d2104c06af9363 100644 |
| --- a/chrome/browser/extensions/extension_preference_api.cc |
| +++ b/chrome/browser/extensions/extension_preference_api.cc |
| @@ -11,11 +11,14 @@ |
| #include "base/stl_util-inl.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_proxy_api.h" |
| #include "chrome/browser/extensions/extension_service.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/common/pref_names.h" |
| +#include "content/common/notification_type.h" |
| +#include "content/common/notification_service.h" |
| namespace { |
| @@ -35,6 +38,8 @@ const char kIncognitoSpecific[] = "incognitoSpecific"; |
| const char kLevelOfControl[] = "levelOfControl"; |
| const char kValue[] = "value"; |
| +const char kOnPrefChangeFormat[] = "experimental.preferences.%s.onChange"; |
| + |
| const char kIncognitoErrorMessage[] = |
| "You do not have permission to access incognito preferences."; |
| @@ -68,6 +73,32 @@ class IdentityPrefTransformer : public PrefTransformerInterface { |
| } |
| }; |
| +// 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) { |
| + 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(); |
| + |
| + if (!pref->IsExtensionModifiable()) |
| + return kNotControllable; |
| + |
| + if (ep->DoesExtensionControlPref(extension_id, browser_pref, incognito)) |
| + return kControlledByThisExtension; |
| + |
| + if (ep->CanExtensionControlPref(extension_id, browser_pref, incognito)) |
| + return kControllableByThisExtension; |
| + |
| + return kControlledByOtherExtensions; |
| +} |
| + |
| class PrefMapping { |
| public: |
| static PrefMapping* GetInstance() { |
| @@ -87,6 +118,19 @@ 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; |
| + } |
| + |
| PrefTransformerInterface* FindTransformerForBrowserPref( |
| const std::string& browser_pref) { |
| std::map<std::string, PrefTransformerInterface*>::iterator it = |
| @@ -106,8 +150,14 @@ class PrefMapping { |
| 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); |
| } |
| DCHECK_EQ(arraysize(kPrefMapping), mapping_.size()); |
| + DCHECK_EQ(arraysize(kPrefMapping), event_mapping_.size()); |
| RegisterPrefTransformer(prefs::kProxy, new ProxyPrefTransformer()); |
| } |
| @@ -126,40 +176,106 @@ class PrefMapping { |
| // Mapping from extension pref keys to browser pref keys. |
| std::map<std::string, std::pair<std::string, std::string> > mapping_; |
| + // 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
|
| + std::map<std::string, std::pair<std::string, std::string> > event_mapping_; |
| // Mapping from browser pref keys to transformers. |
| std::map<std::string, PrefTransformerInterface*> transformers_; |
| scoped_ptr<PrefTransformerInterface> identity_transformer_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(PrefMapping); |
| }; |
| } // namespace |
| -// TODO(battre): Factor out common parts once this is stable. |
| +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); |
| + } |
| +} |
| -GetPreferenceFunction::~GetPreferenceFunction() { } |
| +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); |
| + } else { |
| + NOTREACHED(); |
| + } |
| +} |
| -const char* GetPreferenceFunction::GetLevelOfControl( |
| - const std::string& browser_pref, |
| - bool incognito) const { |
| - PrefService* prefs = incognito ? profile_->GetOffTheRecordPrefs() |
| - : profile_->GetPrefs(); |
| +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 = |
| - prefs->FindPreference(browser_pref.c_str()); |
| + pref_service->FindPreference(browser_pref.c_str()); |
| CHECK(pref); |
| - ExtensionPrefs* ep = profile_->GetExtensionService()->extension_prefs(); |
| + ExtensionService* extension_service = profile_->GetExtensionService(); |
| + PrefTransformerInterface* transformer = |
| + PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref); |
| + dict->Set(kValue, transformer->BrowserToExtensionPref(pref->GetValue())); |
| + if (incognito) { |
| + ExtensionPrefs* ep = extension_service->extension_prefs(); |
| + dict->Set( |
| + kIncognitoSpecific, |
| + Value::CreateBooleanValue(ep->HasIncognitoPrefValue(browser_pref))); |
| + } |
| - if (!pref->IsExtensionModifiable()) |
| - return kNotControllable; |
| + 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); |
| + } |
| + } |
| +} |
| - if (ep->DoesExtensionControlPref(extension_id(), browser_pref, incognito)) |
| - return kControlledByThisExtension; |
| +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()); |
| +} |
| - if (ep->CanExtensionControlPref(extension_id(), browser_pref, incognito)) |
| - return kControllableByThisExtension; |
| +// TODO(battre): Factor out common parts once this is stable. |
| - return kControlledByOtherExtensions; |
| -} |
| +GetPreferenceFunction::~GetPreferenceFunction() { } |
| bool GetPreferenceFunction::RunImpl() { |
| std::string pref_key; |
| @@ -191,7 +307,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); |
| PrefTransformerInterface* transformer = |