Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(562)

Unified Diff: chrome/browser/extensions/extension_popup_api.cc

Issue 1001002: Initial support for inspecting extension popups. (Closed)
Patch Set: pre submit Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/extensions/extension_host.h ('k') | chrome/browser/extensions/extension_popup_host.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/extensions/extension_popup_api.cc
diff --git a/chrome/browser/extensions/extension_popup_api.cc b/chrome/browser/extensions/extension_popup_api.cc
index c70747d47f20cf9524bc102db7d68ad8b99c5034..504a7a071be43d8a8cb2940c30b279533ff684da 100644
--- a/chrome/browser/extensions/extension_popup_api.cc
+++ b/chrome/browser/extensions/extension_popup_api.cc
@@ -21,9 +21,12 @@
#include "gfx/point.h"
#if defined(TOOLKIT_VIEWS)
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_widget_host_view.h"
#include "chrome/browser/views/extensions/extension_popup.h"
#include "views/view.h"
-#endif
+#include "views/focus/focus_manager.h"
+#endif // TOOLKIT_VIEWS
namespace extension_popup_module_events {
@@ -53,6 +56,97 @@ const char kRectangleChrome[] = "rectangle";
}; // namespace
+#if defined(TOOLKIT_VIEWS)
+// ExtensionPopupHost objects implement the environment necessary to host
+// an ExtensionPopup views for the popup api. Its main job is to handle
+// its lifetime and to fire the popup-closed event when the popup is closed.
+// Because the close-on-focus-lost behavior is different from page action
+// and browser action, it also manages its own focus change listening. The
+// difference in close-on-focus-lost is that in the page action and browser
+// action cases, the popup closes when the focus leaves the popup or any of its
+// children. In this case, the popup closes when the focus leaves the popups
+// containing view or any of *its* children.
+class ExtensionPopupHost : public ExtensionPopup::Observer,
+ public views::WidgetFocusChangeListener,
+ public base::RefCounted<ExtensionPopupHost> {
+ public:
+ explicit ExtensionPopupHost(ExtensionFunctionDispatcher* dispatcher)
+ : dispatcher_(dispatcher), popup_(NULL) {
+ AddRef(); // Balanced in ExtensionPopupClosed().
+ views::FocusManager::GetWidgetFocusManager()->AddFocusChangeListener(this);
+ }
+
+ ~ExtensionPopupHost() {
+ views::FocusManager::GetWidgetFocusManager()->
+ RemoveFocusChangeListener(this);
+ }
+
+ void set_popup(ExtensionPopup* popup) {
+ popup_ = popup;
+ }
+
+ // Overriden from ExtensionPopup::Observer
+ virtual void ExtensionPopupClosed(ExtensionPopup* popup) {
+ RenderViewHost* render_view_host = dispatcher_->GetExtensionHost() ?
+ dispatcher_->GetExtensionHost()->render_view_host() :
+ dispatcher_->GetExtensionDOMUI()->GetRenderViewHost();
+
+ PopupEventRouter::OnPopupClosed(dispatcher_->profile(),
+ render_view_host->routing_id());
+ dispatcher_ = NULL;
+ Release(); // Balanced in ctor.
+ }
+
+ // Overriden from views::WidgetFocusChangeListener
+ virtual void NativeFocusWillChange(gfx::NativeView focused_before,
+ gfx::NativeView focused_now) {
+ // If no view is to be focused, then Chrome was deactivated, so hide the
+ // popup.
+ if (focused_now) {
+ gfx::NativeView host_view = dispatcher_->GetExtensionHost() ?
+ dispatcher_->GetExtensionHost()->GetNativeViewOfHost() :
+ dispatcher_->GetExtensionDOMUI()->GetNativeViewOfHost();
+
+ // If the widget hosting the popup contains the newly focused view, then
+ // don't dismiss the pop-up.
+ views::Widget* popup_root_widget = popup_->host()->view()->GetWidget();
+ if (popup_root_widget &&
+ popup_root_widget->ContainsNativeView(focused_now))
+ return;
+
+ // If the widget or RenderWidgetHostView hosting the extension that
+ // launched the pop-up is receiving focus, then don't dismiss the popup.
+ views::Widget* host_widget =
+ views::Widget::GetWidgetFromNativeView(host_view);
+ if (host_widget && host_widget->ContainsNativeView(focused_now))
+ return;
+
+ RenderWidgetHostView* render_host_view =
+ RenderWidgetHostView::GetRenderWidgetHostViewFromNativeView(
+ host_view);
+ if (render_host_view &&
+ render_host_view->ContainsNativeView(focused_now))
+ return;
+ }
+
+ // We are careful here to let the current event loop unwind before
+ // causing the popup to be closed.
+ MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(popup_,
+ &ExtensionPopup::Close));
+ }
+
+ private:
+ // A pointer to the dispatcher that handled the request that opened this
+ // popup view.
+ ExtensionFunctionDispatcher* dispatcher_;
+
+ // A pointer to the popup.
+ ExtensionPopup* popup_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionPopupHost);
+};
+#endif // TOOLKIT_VIEWS
+
PopupShowFunction::PopupShowFunction()
#if defined (TOOLKIT_VIEWS)
: popup_(NULL)
@@ -157,19 +251,24 @@ bool PopupShowFunction::RunImpl() {
BubbleBorder::ArrowLocation arrow_location =
(NULL != dispatcher()->GetExtensionHost()) ? BubbleBorder::BOTTOM_LEFT :
BubbleBorder::TOP_LEFT;
- popup_ = ExtensionPopup::Show(url, GetBrowser(),
+
+ // ExtensionPopupHost manages it's own lifetime.
+ ExtensionPopupHost* popup_host = new ExtensionPopupHost(dispatcher());
+ popup_ = ExtensionPopup::Show(url,
+ GetBrowser(),
dispatcher()->profile(),
dispatcher()->GetFrameNativeWindow(),
rect,
arrow_location,
give_focus,
- chrome);
-
- ExtensionPopupHost* popup_host = dispatcher()->GetPopupHost();
- DCHECK(popup_host);
-
- popup_host->set_child_popup(popup_);
- popup_->set_delegate(popup_host);
+ false, // inspect_with_devtools
+ chrome,
+ popup_host); // ExtensionPopup::Observer
+
+ // popup_host will handle focus change listening and close the popup when
+ // focus leaves the containing views hierarchy.
+ popup_->set_close_on_lost_focus(false);
+ popup_host->set_popup(popup_);
#endif // defined(TOOLKIT_VIEWS)
return true;
}
« no previous file with comments | « chrome/browser/extensions/extension_host.h ('k') | chrome/browser/extensions/extension_popup_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698