Index: chrome/browser/ui/extensions/extension_action_view_controller.cc |
diff --git a/chrome/browser/ui/extensions/extension_action_view_controller.cc b/chrome/browser/ui/extensions/extension_action_view_controller.cc |
index 63905e5786c73a2302305887cd424753b23867f8..0b55989869a919faae12294155ed9ed64fd9838d 100644 |
--- a/chrome/browser/ui/extensions/extension_action_view_controller.cc |
+++ b/chrome/browser/ui/extensions/extension_action_view_controller.cc |
@@ -9,6 +9,7 @@ |
#include "chrome/browser/extensions/api/commands/command_service.h" |
#include "chrome/browser/extensions/api/extension_action/extension_action_api.h" |
#include "chrome/browser/extensions/extension_action.h" |
+#include "chrome/browser/extensions/extension_view_host.h" |
#include "chrome/browser/profiles/profile.h" |
#include "chrome/browser/sessions/session_tab_helper.h" |
#include "chrome/browser/ui/browser.h" |
@@ -16,7 +17,11 @@ |
#include "chrome/browser/ui/extensions/extension_action_platform_delegate.h" |
#include "chrome/browser/ui/toolbar/toolbar_action_view_delegate.h" |
#include "chrome/common/extensions/api/extension_action/action_info.h" |
+#include "content/public/browser/notification_details.h" |
+#include "content/public/browser/notification_source.h" |
+#include "extensions/browser/extension_host.h" |
#include "extensions/browser/extension_registry.h" |
+#include "extensions/browser/notification_types.h" |
#include "extensions/common/extension.h" |
#include "extensions/common/manifest_constants.h" |
#include "ui/gfx/image/image_skia.h" |
@@ -32,6 +37,7 @@ ExtensionActionViewController::ExtensionActionViewController( |
: extension_(extension), |
browser_(browser), |
extension_action_(extension_action), |
+ popup_host_(nullptr), |
view_delegate_(nullptr), |
platform_delegate_(ExtensionActionPlatformDelegate::Create(this)), |
icon_factory_(browser->profile(), extension, extension_action, this), |
@@ -58,6 +64,8 @@ void ExtensionActionViewController::SetDelegate( |
view_delegate_ = delegate; |
platform_delegate_->OnDelegateSet(); |
} else { |
+ if (is_showing_popup()) |
+ HidePopup(); |
platform_delegate_.reset(); |
view_delegate_ = nullptr; |
} |
@@ -133,8 +141,14 @@ bool ExtensionActionViewController::HasPopup( |
} |
void ExtensionActionViewController::HidePopup() { |
- if (platform_delegate_->IsShowingPopup()) |
+ if (is_showing_popup()) { |
platform_delegate_->CloseOwnPopup(); |
+ // We need to do these actions synchronously (instead of closing and then |
+ // performing the rest of the cleanup in Observe()) because the extension |
+ // host can close asynchronously, and we need to keep the view delegate |
+ // up-to-date. |
+ OnPopupClosed(); |
+ } |
} |
gfx::NativeView ExtensionActionViewController::GetPopupNativeView() { |
@@ -218,6 +232,19 @@ void ExtensionActionViewController::OnIconUpdated() { |
view_delegate_->UpdateState(); |
} |
+void ExtensionActionViewController::Observe( |
+ int type, |
+ const content::NotificationSource& source, |
+ const content::NotificationDetails& details) { |
+ // TODO(devlin): Ew. Notifications. Extract out an observer interface for |
+ // ExtensionHost and convert this. |
+ DCHECK_EQ(extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, type); |
+ extensions::ExtensionHost* host = |
+ content::Details<extensions::ExtensionHost>(details).ptr(); |
+ if (host == popup_host_) |
+ OnPopupClosed(); |
+} |
+ |
bool ExtensionActionViewController::ExtensionIsValid() const { |
return extension_registry_->enabled_extensions().Contains(extension_->id()); |
} |
@@ -244,7 +271,7 @@ bool ExtensionActionViewController::ShowPopupWithUrl( |
if (!ExtensionIsValid()) |
return false; |
- bool already_showing = platform_delegate_->IsShowingPopup(); |
+ bool already_showing = is_showing_popup(); |
// Always hide the current popup, even if it's not owned by this extension. |
// Only one popup should be visible at a time. |
@@ -256,6 +283,21 @@ bool ExtensionActionViewController::ShowPopupWithUrl( |
if (already_showing) |
return false; |
- return platform_delegate_->ShowPopupWithUrl( |
+ popup_host_ = platform_delegate_->ShowPopupWithUrl( |
show_action, popup_url, grant_tab_permissions); |
+ if (popup_host_) { |
+ // Lazily register for notifications about extension host destructions. |
+ static const int kType = extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED; |
+ content::Source<content::BrowserContext> source(browser_->profile()); |
+ if (!registrar_.IsRegistered(this, kType, source)) |
+ registrar_.Add(this, kType, source); |
+ |
+ view_delegate_->OnPopupShown(grant_tab_permissions); |
+ } |
+ return is_showing_popup(); |
+} |
+ |
+void ExtensionActionViewController::OnPopupClosed() { |
+ popup_host_ = nullptr; |
+ view_delegate_->OnPopupClosed(); |
} |