Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2736)

Unified Diff: chrome/browser/extensions/extension_preference_api.cc

Issue 6596044: Add onChange event to preference extension APIs. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: test Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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());

Powered by Google App Engine
This is Rietveld 408576698