diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/extensions/extension_host.cc | 52 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service.cc | 12 |
2 files changed, 43 insertions, 21 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( diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index c1a0a3b..de75aba 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -845,15 +845,11 @@ void ExtensionsService::Observe(NotificationType type, std::string extension_id(host->extension()->id()); CHECK(extension_id.length() == 32U); Extension* extension = GetExtensionById(extension_id, true); - // It is possible that the extension is already unloaded. If it is not - // found, then bail. This seems to be Mac-specific caused by the race - // conditions introduced by Core Animation and Browser Action popups. - // TODO(andybons): Find out why this is fired twice. http://crbug/32653 - if (!extension) - return; - - // http://crbug.com/30405 CHECK(extension == host->extension()); + if (!extension) { + NOTREACHED(); + return; + } // Unload the entire extension. We want it to be in a consistent state: // either fully working or not loaded at all, but never half-crashed. |