diff options
author | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-27 23:27:29 +0000 |
---|---|---|
committer | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-27 23:27:29 +0000 |
commit | 017f19b5f1af1702252655b4b52bdcd9ab7a0de2 (patch) | |
tree | 72ac07978cf531eebdc071ca9645ed78c42f435a | |
parent | 1b66e47eba578f499c610a3b608a23a086254f48 (diff) | |
download | chromium_src-017f19b5f1af1702252655b4b52bdcd9ab7a0de2.zip chromium_src-017f19b5f1af1702252655b4b52bdcd9ab7a0de2.tar.gz chromium_src-017f19b5f1af1702252655b4b52bdcd9ab7a0de2.tar.bz2 |
Fix a crash in ExtensionGalleryInstallApiTest.InstallAndUninstall caused by
the ExtensionInstalledBubble.
The info bubble was closing after the extension was uninstalled. This wouldn't
always happen - sometimes the browser shut down first, so we didn't crash.
BUG=56558
TEST=covered by browser_test
Review URL: http://codereview.chromium.org/4112007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64177 0039d316-1c4b-4281-b951-d872f2087c98
4 files changed, 58 insertions, 27 deletions
diff --git a/chrome/browser/cocoa/extension_installed_bubble_controller.h b/chrome/browser/cocoa/extension_installed_bubble_controller.h index de2998a..bec656d 100644 --- a/chrome/browser/cocoa/extension_installed_bubble_controller.h +++ b/chrome/browser/cocoa/extension_installed_bubble_controller.h @@ -89,6 +89,10 @@ typedef enum { // the extensionObserver when the extension has completed loading. - (void)showWindow:(id)sender; +// Clears our weak pointer to the Extension. This callback is triggered by +// the extensionObserver when the extension is unloaded. +- (void)extensionUnloaded:(id)sender; + @end @interface ExtensionInstalledBubbleController(ExposedForTesting) diff --git a/chrome/browser/cocoa/extension_installed_bubble_controller.mm b/chrome/browser/cocoa/extension_installed_bubble_controller.mm index 00cd535..b83b303 100644 --- a/chrome/browser/cocoa/extension_installed_bubble_controller.mm +++ b/chrome/browser/cocoa/extension_installed_bubble_controller.mm @@ -31,10 +31,12 @@ class ExtensionLoadedNotificationObserver : public NotificationObserver { public: ExtensionLoadedNotificationObserver( - ExtensionInstalledBubbleController* controller) + ExtensionInstalledBubbleController* controller, Profile* profile) : controller_(controller) { registrar_.Add(this, NotificationType::EXTENSION_LOADED, - NotificationService::AllSources()); + Source<Profile>(profile)); + registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, + Source<Profile>(profile)); } private: @@ -50,6 +52,13 @@ class ExtensionLoadedNotificationObserver : public NotificationObserver { withObject:controller_ waitUntilDone:NO]; } + } else if (type == NotificationType::EXTENSION_UNLOADED) { + const Extension* extension = Details<const Extension>(details).ptr(); + if (extension == [controller_ extension]) { + [controller_ performSelectorOnMainThread:@selector(extensionUnloaded:) + withObject:controller_ + waitUntilDone:NO]; + } } else { NOTREACHED() << "Received unexpected notification."; } @@ -91,7 +100,8 @@ class ExtensionLoadedNotificationObserver : public NotificationObserver { } // Start showing window only after extension has fully loaded. - extensionObserver_.reset(new ExtensionLoadedNotificationObserver(self)); + extensionObserver_.reset(new ExtensionLoadedNotificationObserver( + self, browser->profile())); } return self; } @@ -140,8 +150,7 @@ class ExtensionLoadedNotificationObserver : public NotificationObserver { // Extracted to a function here so that it can be overwritten for unit // testing. - (void)removePageActionPreviewIfNecessary { - DCHECK(extension_); - if (!extension_->page_action() || pageActionRemoved_) + if (!extension_ || !extension_->page_action() || pageActionRemoved_) return; pageActionRemoved_ = YES; @@ -329,4 +338,8 @@ class ExtensionLoadedNotificationObserver : public NotificationObserver { return [extensionInstalledInfoMsg_ frame]; } +- (void)extensionUnloaded:(id)sender { + extension_ = NULL; +} + @end diff --git a/chrome/browser/gtk/extension_installed_bubble_gtk.cc b/chrome/browser/gtk/extension_installed_bubble_gtk.cc index c3ad8d6..0e54c14 100644 --- a/chrome/browser/gtk/extension_installed_bubble_gtk.cc +++ b/chrome/browser/gtk/extension_installed_bubble_gtk.cc @@ -72,7 +72,9 @@ ExtensionInstalledBubbleGtk::ExtensionInstalledBubbleGtk(Extension *extension, // be sure that a browser action or page action has had views created which we // can inspect for the purpose of pointing to them. registrar_.Add(this, NotificationType::EXTENSION_LOADED, - NotificationService::AllSources()); + Source<Profile>(browser->profile())); + registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, + Source<Profile>(browser->profile())); } ExtensionInstalledBubbleGtk::~ExtensionInstalledBubbleGtk() {} @@ -87,6 +89,10 @@ void ExtensionInstalledBubbleGtk::Observe(NotificationType type, MessageLoopForUI::current()->PostTask(FROM_HERE, NewRunnableMethod(this, &ExtensionInstalledBubbleGtk::ShowInternal)); } + } else if (type == NotificationType::EXTENSION_UNLOADED) { + const Extension* extension = Details<const Extension>(details).ptr(); + if (extension == extension_) + extension_ = NULL; } else { NOTREACHED() << L"Received unexpected notification"; } @@ -248,7 +254,7 @@ void ExtensionInstalledBubbleGtk::OnButtonClick(GtkWidget* button, // InfoBubbleDelegate void ExtensionInstalledBubbleGtk::InfoBubbleClosing(InfoBubbleGtk* info_bubble, bool closed_by_escape) { - if (extension_->page_action()) { + if (extension_ && type_ == PAGE_ACTION) { // Turn the page action preview off. BrowserWindowGtk* browser_window = BrowserWindowGtk::GetBrowserWindowForNativeWindow( diff --git a/chrome/browser/views/extensions/extension_installed_bubble.cc b/chrome/browser/views/extensions/extension_installed_bubble.cc index 4997ac6..27910e5 100644 --- a/chrome/browser/views/extensions/extension_installed_bubble.cc +++ b/chrome/browser/views/extensions/extension_installed_bubble.cc @@ -272,7 +272,9 @@ ExtensionInstalledBubble::ExtensionInstalledBubble(Extension *extension, // be sure that a BrowserAction or PageAction has had views created which we // can inspect for the purpose of previewing of pointing to them. registrar_.Add(this, NotificationType::EXTENSION_LOADED, - NotificationService::AllSources()); + Source<Profile>(browser->profile())); + registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, + Source<Profile>(browser->profile())); } void ExtensionInstalledBubble::Observe(NotificationType type, @@ -286,6 +288,10 @@ void ExtensionInstalledBubble::Observe(NotificationType type, MessageLoopForUI::current()->PostTask(FROM_HERE, NewRunnableMethod(this, &ExtensionInstalledBubble::ShowInternal)); } + } else if (type == NotificationType::EXTENSION_UNLOADED) { + const Extension* extension = Details<const Extension>(details).ptr(); + if (extension == extension_) + extension_ = NULL; } else { NOTREACHED() << L"Received unexpected notification"; } @@ -354,25 +360,27 @@ void ExtensionInstalledBubble::ShowInternal() { // InfoBubbleDelegate void ExtensionInstalledBubble::InfoBubbleClosing(InfoBubble* info_bubble, bool closed_by_escape) { - if (type_ == PAGE_ACTION) { - BrowserView* browser_view = BrowserView::GetBrowserViewForNativeWindow( - browser_->window()->GetNativeHandle()); - browser_view->GetLocationBarView()->SetPreviewEnabledPageAction( - extension_->page_action(), - false); // preview_enabled - } else if (type_ == EXTENSION_APP) { - if (bubble_content_->create_shortcut()) { - ShellIntegration::ShortcutInfo shortcut_info; - shortcut_info.url = extension_->GetFullLaunchURL(); - shortcut_info.extension_id = UTF8ToUTF16(extension_->id()); - shortcut_info.title = UTF8ToUTF16(extension_->name()); - shortcut_info.description = UTF8ToUTF16(extension_->description()); - shortcut_info.favicon = icon_; - shortcut_info.create_on_desktop = true; - shortcut_info.create_in_applications_menu = false; - shortcut_info.create_in_quick_launch_bar = false; - web_app::CreateShortcut(browser_->profile()->GetPath(), shortcut_info, - NULL); + if (extension_) { + if (type_ == PAGE_ACTION) { + BrowserView* browser_view = BrowserView::GetBrowserViewForNativeWindow( + browser_->window()->GetNativeHandle()); + browser_view->GetLocationBarView()->SetPreviewEnabledPageAction( + extension_->page_action(), + false); // preview_enabled + } else if (type_ == EXTENSION_APP) { + if (bubble_content_->create_shortcut()) { + ShellIntegration::ShortcutInfo shortcut_info; + shortcut_info.url = extension_->GetFullLaunchURL(); + shortcut_info.extension_id = UTF8ToUTF16(extension_->id()); + shortcut_info.title = UTF8ToUTF16(extension_->name()); + shortcut_info.description = UTF8ToUTF16(extension_->description()); + shortcut_info.favicon = icon_; + shortcut_info.create_on_desktop = true; + shortcut_info.create_in_applications_menu = false; + shortcut_info.create_in_quick_launch_bar = false; + web_app::CreateShortcut(browser_->profile()->GetPath(), shortcut_info, + NULL); + } } } |