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 7a9cb34065807cd76bf647eaab015609c542f117..a33e1c8fb04f9014ecb6e75e92323ba7d1ebf9e1 100644 |
--- a/chrome/browser/extensions/extension_event_router.cc |
+++ b/chrome/browser/extensions/extension_event_router.cc |
@@ -4,14 +4,17 @@ |
#include "chrome/browser/extensions/extension_event_router.h" |
+#include "base/command_line.h" |
#include "base/values.h" |
#include "chrome/browser/extensions/extension_devtools_manager.h" |
+#include "chrome/browser/extensions/extension_host.h" |
#include "chrome/browser/extensions/extension_processes_api.h" |
#include "chrome/browser/extensions/extension_processes_api_constants.h" |
#include "chrome/browser/extensions/extension_service.h" |
#include "chrome/browser/extensions/extension_tabs_module.h" |
#include "chrome/browser/extensions/extension_webrequest_api.h" |
#include "chrome/browser/profiles/profile.h" |
+#include "chrome/common/chrome_switches.h" |
#include "chrome/common/extensions/extension.h" |
#include "chrome/common/extensions/extension_messages.h" |
#include "content/browser/child_process_security_policy.h" |
@@ -48,6 +51,20 @@ struct ExtensionEventRouter::EventListener { |
} |
}; |
+struct ExtensionEventRouter::PendingEvent { |
+ std::string name; |
+ std::string args; |
+ Profile* restrict_to_profile; |
+ std::string cross_incognito_args; |
+ GURL url; |
+ |
+ PendingEvent(const std::string& name, const std::string& args, |
+ Profile* restrict_to_profile, |
+ const std::string& cross_incognito_args, const GURL& url) |
+ : name(name), args(args), restrict_to_profile(restrict_to_profile), |
+ cross_incognito_args(cross_incognito_args), url(url) {} |
+}; |
+ |
// static |
void ExtensionEventRouter::DispatchEvent(IPC::Message::Sender* ipc_sender, |
const std::string& extension_id, |
@@ -68,6 +85,9 @@ ExtensionEventRouter::ExtensionEventRouter(Profile* profile) |
NotificationService::AllSources()); |
registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
NotificationService::AllSources()); |
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, |
+ Source<Profile>(profile_)); |
+ // TODO(tessamac): also get notified for background page crash/failure. |
} |
ExtensionEventRouter::~ExtensionEventRouter() { |
@@ -142,8 +162,8 @@ void ExtensionEventRouter::DispatchEventToRenderers( |
const std::string& event_args, |
Profile* restrict_to_profile, |
const GURL& event_url) { |
- DispatchEventImpl("", event_name, event_args, restrict_to_profile, "", |
- event_url); |
+ MaybeDispatchEventImpl("", event_name, event_args, restrict_to_profile, "", |
+ event_url); |
} |
void ExtensionEventRouter::DispatchEventToExtension( |
@@ -153,8 +173,8 @@ void ExtensionEventRouter::DispatchEventToExtension( |
Profile* restrict_to_profile, |
const GURL& event_url) { |
DCHECK(!extension_id.empty()); |
- DispatchEventImpl(extension_id, event_name, event_args, restrict_to_profile, |
- "", event_url); |
+ MaybeDispatchEventImpl(extension_id, event_name, event_args, |
+ restrict_to_profile, "", event_url); |
} |
void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito( |
@@ -163,7 +183,40 @@ void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito( |
Profile* restrict_to_profile, |
const std::string& cross_incognito_args, |
const GURL& event_url) { |
- DispatchEventImpl("", event_name, event_args, restrict_to_profile, |
+ MaybeDispatchEventImpl("", event_name, event_args, restrict_to_profile, |
+ cross_incognito_args, event_url); |
+} |
+ |
+void ExtensionEventRouter::MaybeDispatchEventImpl( |
Aaron Boodman
2011/08/18 19:25:55
Another 'maybe' function. You could eliminate this
Tessa MacDuff
2011/08/23 18:18:42
Done.
|
+ const std::string& extension_id, |
+ const std::string& event_name, |
+ const std::string& event_args, |
+ Profile* restrict_to_profile, |
+ const std::string& cross_incognito_args, |
+ const GURL& event_url) { |
+ if (!profile_) |
+ return; |
+ |
+ if (CommandLine::ForCurrentProcess()->HasSwitch( |
+ switches::kEnableLazyBackgroundPages) && |
+ !extension_id.empty()) { |
+ // TODO(tessamac): Decide what to when there's no extension id. |
+ // Create all background pages? |
Aaron Boodman
2011/08/18 19:25:55
I think creating all background pages is the right
Tessa MacDuff
2011/08/23 18:18:42
I think I'll do this in a separate CL as since it
|
+ const Extension* extension = profile_->GetExtensionService()-> |
+ GetExtensionById(extension_id, false); // exclude disable extensions |
+ if (extension && extension->background_url().is_valid()) { |
+ ExtensionProcessManager* pm = profile_->GetExtensionProcessManager(); |
+ if (pm->GetBackgroundHostForExtension(extension) == NULL) { |
+ EnqueueEvent(extension_id, event_name, event_args, restrict_to_profile, |
+ cross_incognito_args, event_url); |
+ pm->CreateBackgroundHost(extension, extension->background_url()); |
+ return; |
+ } |
+ } |
+ |
+ } |
+ |
+ DispatchEventImpl(extension_id, event_name, event_args, restrict_to_profile, |
cross_incognito_args, event_url); |
} |
@@ -220,6 +273,35 @@ void ExtensionEventRouter::DispatchEventImpl( |
} |
} |
+void ExtensionEventRouter::EnqueueEvent(const std::string &extension_id, |
+ const std::string& event_name, |
+ const std::string& event_args, |
+ Profile* restrict_to_profile, |
+ const std::string& cross_incognito_args, |
+ const GURL& event_url) { |
+ PendingEvent event(event_name, event_args, restrict_to_profile, |
+ cross_incognito_args, event_url); |
+ // TODO: use insert instead of []. |
+ pending_events_[extension_id].push_back(event); |
Aaron Boodman
2011/08/18 19:25:55
I'm fine with this for now, but just so you know t
Tessa MacDuff
2011/08/23 18:18:42
Done.
|
+} |
+ |
+void ExtensionEventRouter::ClearPendingEvents(const std::string &extension_id) { |
+ pending_events_[extension_id].clear(); |
Aaron Boodman
2011/08/18 19:29:06
Little nit: If these one-liner methods aren't call
Tessa MacDuff
2011/08/23 18:18:42
Done.
I had to add an additional NewRunnableMetho
|
+} |
+ |
+void ExtensionEventRouter::DispatchPendingEvents( |
+ const std::string &extension_id) { |
+ const PendingEventsQueue& queue = pending_events_[extension_id]; |
+ for (PendingEventsQueue::const_iterator it = queue.begin(); |
+ it != queue.end(); ++it) { |
+ // Don't call MaybeDispatchEventImpl() to guard against these events |
+ // being re-enqueued if the Background Page still isn't all set. |
Aaron Boodman
2011/08/18 19:29:06
Oh, I see. I don't think it's a big deal if they g
Tessa MacDuff
2011/08/18 20:49:39
I was worried about what would happen if we were a
Aaron Boodman
2011/08/18 21:19:23
ok (to extra arg).
Tessa MacDuff
2011/08/23 18:18:42
Done.
|
+ DispatchEventImpl(extension_id, it->name, it->args, it->restrict_to_profile, |
+ it->cross_incognito_args, it->url); |
+ } |
+ ClearPendingEvents(extension_id); |
+} |
+ |
void ExtensionEventRouter::Observe(int type, |
const NotificationSource& source, |
const NotificationDetails& details) { |
@@ -243,6 +325,13 @@ void ExtensionEventRouter::Observe(int type, |
} |
break; |
} |
+ case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: { |
+ // TODO: dispatch events in queue. ExtensionHost is in the details. |
+ ExtensionHost* eh = Details<ExtensionHost>(details).ptr(); |
+ DispatchPendingEvents(eh->extension_id()); |
+ break; |
+ } |
+ // TODO(tessamac): if background page crashed/failed clear queue. |
default: |
NOTREACHED(); |
return; |