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

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

Issue 9350024: Unrevert again r119770 - "Event pages: remember events that the page registered for,"" (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 10 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
« no previous file with comments | « chrome/browser/extensions/extension_event_router.h ('k') | chrome/browser/extensions/extension_host.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 0876aa018e2dc0a9138b4c0bbab59b2df5ad4ede..8d0a8dfb1a1d603441c9f7c229dd9e4eebf34e4a 100644
--- a/chrome/browser/extensions/extension_event_router.cc
+++ b/chrome/browser/extensions/extension_event_router.cc
@@ -23,7 +23,6 @@
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_messages.h"
#include "chrome/common/extensions/api/extension_api.h"
-#include "content/browser/child_process_security_policy.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_process_host.h"
@@ -62,21 +61,18 @@ struct ExtensionEventRouter::EventListener {
};
struct ExtensionEventRouter::ExtensionEvent {
- std::string extension_id;
std::string event_name;
std::string event_args;
GURL event_url;
Profile* restrict_to_profile;
std::string cross_incognito_args;
- ExtensionEvent(const std::string& extension_id,
- const std::string& event_name,
+ ExtensionEvent(const std::string& event_name,
const std::string& event_args,
const GURL& event_url,
Profile* restrict_to_profile,
const std::string& cross_incognito_args)
- : extension_id(extension_id),
- event_name(event_name),
+ : event_name(event_name),
event_args(event_args),
event_url(event_url),
restrict_to_profile(restrict_to_profile),
@@ -156,6 +152,21 @@ void ExtensionEventRouter::RemoveEventListener(
profile_, listener.extension_id, event_name));
}
+void ExtensionEventRouter::AddLazyEventListener(
+ const std::string& event_name,
+ const std::string& extension_id) {
+ EventListener lazy_listener(NULL, extension_id);
+ if (lazy_listeners_[event_name].count(lazy_listener) == 0)
+ lazy_listeners_[event_name].insert(lazy_listener);
+}
+
+void ExtensionEventRouter::RemoveLazyEventListener(
+ const std::string& event_name,
+ const std::string& extension_id) {
+ EventListener lazy_listener(NULL, extension_id);
+ lazy_listeners_[event_name].erase(lazy_listener);
+}
+
bool ExtensionEventRouter::HasEventListener(const std::string& event_name) {
return (listeners_.find(event_name) != listeners_.end() &&
!listeners_[event_name].empty());
@@ -182,9 +193,9 @@ void ExtensionEventRouter::DispatchEventToRenderers(
Profile* restrict_to_profile,
const GURL& event_url) {
linked_ptr<ExtensionEvent> event(
- new ExtensionEvent("", event_name, event_args, event_url,
+ new ExtensionEvent(event_name, event_args, event_url,
restrict_to_profile, ""));
- DispatchEventImpl(event, false);
+ DispatchEventImpl("", event, false);
}
void ExtensionEventRouter::DispatchEventToExtension(
@@ -195,9 +206,9 @@ void ExtensionEventRouter::DispatchEventToExtension(
const GURL& event_url) {
DCHECK(!extension_id.empty());
linked_ptr<ExtensionEvent> event(
- new ExtensionEvent(extension_id, event_name, event_args, event_url,
+ new ExtensionEvent(event_name, event_args, event_url,
restrict_to_profile, ""));
- DispatchEventImpl(event, false);
+ DispatchEventImpl(extension_id, event, false);
}
void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito(
@@ -207,24 +218,21 @@ void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito(
const std::string& cross_incognito_args,
const GURL& event_url) {
linked_ptr<ExtensionEvent> event(
- new ExtensionEvent("", event_name, event_args, event_url,
+ new ExtensionEvent(event_name, event_args, event_url,
restrict_to_profile, cross_incognito_args));
- DispatchEventImpl(event, false);
+ DispatchEventImpl("", event, false);
}
-bool ExtensionEventRouter::CanDispatchEventNow(
- const std::string& extension_id) {
- if (extension_id.empty())
- // TODO(mpcomplete): We need to test this per-extension, rather than
- // globally.
- return true;
-
- const Extension* extension = profile_->GetExtensionService()->
- GetExtensionById(extension_id, false);
- if (extension && extension->has_background_page() &&
+bool ExtensionEventRouter::CanDispatchEventNow(const Extension* extension) {
+ DCHECK(extension);
+ if (extension->has_background_page() &&
!extension->background_page_persists()) {
ExtensionProcessManager* pm = profile_->GetExtensionProcessManager();
- if (!pm->GetBackgroundHostForExtension(extension_id)) {
+
+ // TODO(mpcomplete): this is incorrect. We need to check whether the page
+ // has finished loading. If not, we can't dispatch the event (because the
+ // listener hasn't been set up yet).
+ if (!pm->GetBackgroundHostForExtension(extension->id())) {
pm->CreateBackgroundHost(extension, extension->GetBackgroundURL());
return false;
}
@@ -234,7 +242,13 @@ bool ExtensionEventRouter::CanDispatchEventNow(
}
void ExtensionEventRouter::DispatchEventImpl(
- const linked_ptr<ExtensionEvent>& event, bool was_pending) {
+ const std::string& extension_id,
+ const linked_ptr<ExtensionEvent>& event,
+ bool was_pending) {
+ // Ensure we are only dispatching pending events to a particular extension.
+ if (was_pending)
+ CHECK(!extension_id.empty());
+
if (!profile_)
return;
@@ -242,15 +256,8 @@ void ExtensionEventRouter::DispatchEventImpl(
DCHECK(!event->restrict_to_profile ||
profile_->IsSameProfile(event->restrict_to_profile));
- if (!CanDispatchEventNow(event->extension_id)) {
- // Events should not be made pending twice. This may happen if the
- // background page is shutdown before we finish dispatching pending events.
- CHECK(!was_pending);
- // TODO(tessamac): make sure Background Page notification doesn't
- // happen before the event is added to the pending list.
- AppendEvent(event);
- return;
- }
+ if (!was_pending)
+ LoadLazyBackgroundPagesForEvent(extension_id, event);
ListenerMap::iterator it = listeners_.find(event->event_name);
if (it == listeners_.end())
@@ -262,12 +269,11 @@ void ExtensionEventRouter::DispatchEventImpl(
// Send the event only to renderers that are listening for it.
for (std::set<EventListener>::iterator listener = listeners.begin();
listener != listeners.end(); ++listener) {
- if (!event->extension_id.empty() &&
- event->extension_id != listener->extension_id)
+ if (!extension_id.empty() && extension_id != listener->extension_id)
continue;
- const Extension* extension = service->GetExtensionById(
- listener->extension_id, false);
+ const Extension* extension = service->extensions()->GetByID(
+ listener->extension_id);
// The extension could have been removed, but we do not unregister it until
// the extension process is unloaded.
@@ -307,6 +313,32 @@ void ExtensionEventRouter::DispatchEventImpl(
}
}
+void ExtensionEventRouter::LoadLazyBackgroundPagesForEvent(
+ const std::string& extension_id,
+ const linked_ptr<ExtensionEvent>& event) {
+ ExtensionService* service = profile_->GetExtensionService();
+
+ ListenerMap::iterator it = lazy_listeners_.find(event->event_name);
+ if (it == lazy_listeners_.end())
+ return;
+
+ std::set<EventListener>& listeners = it->second;
+ for (std::set<EventListener>::iterator listener = listeners.begin();
+ listener != listeners.end(); ++listener) {
+ if (!extension_id.empty() && extension_id != listener->extension_id)
+ continue;
+
+ const Extension* extension = service->extensions()->GetByID(
+ listener->extension_id);
+
+ if (extension && !CanDispatchEventNow(extension)) {
+ // TODO(mpcomplete): make sure Background Page notification doesn't
+ // happen before the event is added to the pending list.
+ AppendEvent(extension->id(), event);
+ }
+ }
+}
+
void ExtensionEventRouter::IncrementInFlightEvents(const Extension* extension) {
if (!extension->background_page_persists())
in_flight_events_[extension->id()]++;
@@ -323,14 +355,13 @@ bool ExtensionEventRouter::HasInFlightEvents(const std::string& extension_id) {
}
void ExtensionEventRouter::AppendEvent(
+ const std::string& extension_id,
const linked_ptr<ExtensionEvent>& event) {
PendingEventsList* events_list = NULL;
- PendingEventsPerExtMap::iterator it =
- pending_events_.find(event->extension_id);
+ PendingEventsPerExtMap::iterator it = pending_events_.find(extension_id);
if (it == pending_events_.end()) {
events_list = new PendingEventsList();
- pending_events_[event->extension_id] =
- linked_ptr<PendingEventsList>(events_list);
+ pending_events_[extension_id] = linked_ptr<PendingEventsList>(events_list);
} else {
events_list = it->second.get();
}
@@ -339,8 +370,8 @@ void ExtensionEventRouter::AppendEvent(
}
void ExtensionEventRouter::DispatchPendingEvents(
- const std::string &extension_id) {
- // Find the list of pending events for this extension.
+ const std::string& extension_id) {
+ CHECK(!extension_id.empty());
PendingEventsPerExtMap::const_iterator map_it =
pending_events_.find(extension_id);
if (map_it == pending_events_.end())
@@ -349,11 +380,14 @@ void ExtensionEventRouter::DispatchPendingEvents(
PendingEventsList* events_list = map_it->second.get();
for (PendingEventsList::const_iterator it = events_list->begin();
it != events_list->end(); ++it)
- DispatchEventImpl(*it, true);
+ DispatchEventImpl(extension_id, *it, true);
- // Delete list.
events_list->clear();
pending_events_.erase(extension_id);
+
+ // Check if the extension is idle, which may be the case if no events were
+ // successfully dispatched.
+ profile_->GetExtensionProcessManager()->OnExtensionIdle(extension_id);
}
void ExtensionEventRouter::Observe(
@@ -382,9 +416,14 @@ void ExtensionEventRouter::Observe(
break;
}
case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: {
- // TODO: dispatch events in queue. ExtensionHost is in the details.
+ // If an on-demand background page finished loading, dispatch queued up
+ // events for it.
ExtensionHost* eh = content::Details<ExtensionHost>(details).ptr();
- DispatchPendingEvents(eh->extension_id());
+ if (eh->extension_host_type() ==
+ chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE &&
+ !eh->extension()->background_page_persists()) {
+ DispatchPendingEvents(eh->extension_id());
+ }
break;
}
// TODO(tessamac): if background page crashed/failed clear queue.
« no previous file with comments | « chrome/browser/extensions/extension_event_router.h ('k') | chrome/browser/extensions/extension_host.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698