Index: chrome/browser/extensions/extension_event_router.cc |
diff --git a/chrome/browser/extensions/extension_event_router.cc b/chrome/browser/extensions/extension_event_router.cc |
index 21c315c90242fdea08875992bd9f0962a1df4d93..5fb2dfd21e6e63b71b4afe37dcb9b75335bebd6f 100644 |
--- a/chrome/browser/extensions/extension_event_router.cc |
+++ b/chrome/browser/extensions/extension_event_router.cc |
@@ -119,10 +119,57 @@ ExtensionEventRouter::ExtensionEventRouter(Profile* profile) |
ExtensionEventRouter::~ExtensionEventRouter() {} |
+bool ExtensionEventRouter::IsEventAvailable( |
+ const std::string& event_name, |
+ const std::string& extension_id, |
+ content::RenderProcessHost* render_process, |
+ Feature::Context context_type) const { |
+ ExtensionService* extension_service = profile_->GetExtensionService(); |
+ const Extension* extension = |
+ extension_service->extensions()->GetByID(extension_id); |
+ if (!extension) |
+ return false; |
+ |
+ ExtensionAPI* api = ExtensionAPI::GetSharedInstance(); |
+ |
+ // If the API has been ported to the feature system, use that. |
+ if (api->GetFeature(event_name)) { |
+ if (!api->IsAvailable( |
+ event_name, |
+ extension, |
+ static_cast<Feature::Context>(context_type))) { |
+ LOG(ERROR) << "Access to extension API '" << event_name << "' denied."; |
+ return false; |
+ } |
+ } else { |
+ // Otherwise, fall back to the older system. |
+ // TODO(aa): Remove this when all APIs have been ported. |
+ if (!extension->HasAPIPermission(event_name)) { |
+ LOG(ERROR) << "Extension " << extension->id() << " does not have " |
+ << "permission to event: " << event_name; |
+ return false; |
+ } |
+ } |
+ |
+ // If the API requires a privileged process, ensure it is in one. |
+ if (api->IsPrivileged(event_name) && |
+ !extension_service->process_map()->Contains(extension->id(), |
+ render_process->GetID())) { |
+ LOG(ERROR) << "Extension API called from incorrect process"; |
+ return false; |
+ } |
+ |
+ return true; |
+} |
+ |
void ExtensionEventRouter::AddEventListener( |
const std::string& event_name, |
+ const std::string& extension_id, |
content::RenderProcessHost* process, |
- const std::string& extension_id) { |
+ Feature::Context context_type) { |
+ if (!IsEventAvailable(event_name, extension_id, process, context_type)) |
+ return; |
+ |
ListenerProcess listener(process, extension_id); |
DCHECK_EQ(listeners_[event_name].count(listener), 0u) << event_name; |
listeners_[event_name].insert(listener); |
@@ -167,6 +214,15 @@ void ExtensionEventRouter::RemoveEventListener( |
void ExtensionEventRouter::AddLazyEventListener( |
const std::string& event_name, |
+ const std::string& extension_id, |
+ content::RenderProcessHost* render_process, |
+ Feature::Context context_type) { |
+ if (!IsEventAvailable(event_name, extension_id, render_process, context_type)) |
+ AddLazyEventListener(event_name, extension_id); |
+} |
+ |
+void ExtensionEventRouter::AddLazyEventListener( |
+ const std::string& event_name, |
const std::string& extension_id) { |
ListenerProcess lazy_listener(NULL, extension_id); |
bool is_new = lazy_listeners_[event_name].insert(lazy_listener).second; |
@@ -312,15 +368,6 @@ void ExtensionEventRouter::DispatchEventToListener( |
Profile* listener_profile = Profile::FromBrowserContext( |
listener.process->GetBrowserContext()); |
- extensions::ProcessMap* process_map = |
- listener_profile->GetExtensionService()->process_map(); |
- // If the event is privileged, only send to extension processes. Otherwise, |
- // it's OK to send to normal renderers (e.g., for content scripts). |
- if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) && |
- !process_map->Contains(extension->id(), listener.process->GetID())) { |
- return; |
- } |
- |
const std::string* event_args; |
if (!CanDispatchEventToProfile(listener_profile, extension, |
event, &event_args)) |