summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/extension_host.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/extensions/extension_host.cc')
-rw-r--r--chrome/browser/extensions/extension_host.cc52
1 files changed, 39 insertions, 13 deletions
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc
index a600235..ef06bef 100644
--- a/chrome/browser/extensions/extension_host.cc
+++ b/chrome/browser/extensions/extension_host.cc
@@ -137,6 +137,10 @@ ExtensionHost::ExtensionHost(Extension* extension, SiteInstance* site_instance,
// to the task manager then.
registrar_.Add(this, NotificationType::RENDERER_PROCESS_CREATED,
Source<RenderProcessHost>(render_process_host()));
+ // Listen for when an extension is unloaded from the same profile, as it may
+ // be the same extension that this points to.
+ registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
+ Source<Profile>(profile_));
}
ExtensionHost::~ExtensionHost() {
@@ -226,19 +230,32 @@ void ExtensionHost::NavigateToURL(const GURL& url) {
void ExtensionHost::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
- if (type == NotificationType::EXTENSION_BACKGROUND_PAGE_READY) {
- DCHECK(extension_->GetBackgroundPageReady());
- NavigateToURL(url_);
- } else if (type == NotificationType::BROWSER_THEME_CHANGED) {
- InsertThemeCSS();
- } else if (type == NotificationType::RENDERER_PROCESS_CREATED) {
- LOG(INFO) << "Sending EXTENSION_PROCESS_CREATED";
- NotificationService::current()->Notify(
- NotificationType::EXTENSION_PROCESS_CREATED,
- Source<Profile>(profile_),
- Details<ExtensionHost>(this));
- } else {
- NOTREACHED();
+ switch (type.value) {
+ case NotificationType::EXTENSION_BACKGROUND_PAGE_READY:
+ DCHECK(extension_->GetBackgroundPageReady());
+ NavigateToURL(url_);
+ break;
+ case NotificationType::BROWSER_THEME_CHANGED:
+ InsertThemeCSS();
+ break;
+ case NotificationType::RENDERER_PROCESS_CREATED:
+ LOG(INFO) << "Sending EXTENSION_PROCESS_CREATED";
+ NotificationService::current()->Notify(
+ NotificationType::EXTENSION_PROCESS_CREATED,
+ Source<Profile>(profile_),
+ Details<ExtensionHost>(this));
+ break;
+ case NotificationType::EXTENSION_UNLOADED:
+ // The extension object will be deleted after this notification has been
+ // sent. NULL it out so that dirty pointer issues don't arise in cases
+ // when multiple ExtensionHost objects pointing to the same Extension are
+ // present.
+ if (extension_ == Details<Extension>(details).ptr())
+ extension_ = NULL;
+ break;
+ default:
+ NOTREACHED() << "Unexpected notification sent.";
+ break;
}
}
@@ -254,6 +271,15 @@ void ExtensionHost::RenderViewGone(RenderViewHost* render_view_host) {
if (browser_shutdown::GetShutdownType() != browser_shutdown::NOT_VALID)
return;
+ // In certain cases, multiple ExtensionHost objects may have pointed to
+ // the same Extension at some point (one with a background page and a
+ // popup, for example). When the first ExtensionHost goes away, the extension
+ // is unloaded, and any other host that pointed to that extension will have
+ // its pointer to it NULLed out so that any attempt to unload a dirty pointer
+ // will be averted.
+ if (!extension_)
+ return;
+
LOG(INFO) << "Sending EXTENSION_PROCESS_TERMINATED for " + extension_->name();
DCHECK_EQ(render_view_host_, render_view_host);
NotificationService::current()->Notify(