summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-27 23:27:29 +0000
committermpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-27 23:27:29 +0000
commit017f19b5f1af1702252655b4b52bdcd9ab7a0de2 (patch)
tree72ac07978cf531eebdc071ca9645ed78c42f435a
parent1b66e47eba578f499c610a3b608a23a086254f48 (diff)
downloadchromium_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
-rw-r--r--chrome/browser/cocoa/extension_installed_bubble_controller.h4
-rw-r--r--chrome/browser/cocoa/extension_installed_bubble_controller.mm23
-rw-r--r--chrome/browser/gtk/extension_installed_bubble_gtk.cc10
-rw-r--r--chrome/browser/views/extensions/extension_installed_bubble.cc48
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);
+ }
}
}