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

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

Issue 2003016: Disallow display of multiple experimental.extension.popup(...) windows ... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years, 7 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.cc ('k') | chrome/browser/renderer_host/render_view_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
===================================================================
--- chrome/browser/extensions/extension_popup_api.cc (revision 47023)
+++ chrome/browser/extensions/extension_popup_api.cc (working copy)
@@ -12,6 +12,9 @@
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/profile.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_view_host_delegate.h"
+#include "chrome/browser/renderer_host/render_widget_host_view.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/notification_details.h"
@@ -22,9 +25,6 @@
#include "gfx/point.h"
#if defined(TOOLKIT_VIEWS)
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/renderer_host/render_view_host_delegate.h"
-#include "chrome/browser/renderer_host/render_widget_host_view.h"
#include "chrome/browser/views/extensions/extension_popup.h"
#include "views/view.h"
#include "views/focus/focus_manager.h"
@@ -42,6 +42,8 @@
const char kBadAnchorArgument[] = "Invalid anchor argument.";
const char kInvalidURLError[] = "Invalid URL.";
const char kNotAnExtension[] = "Not an extension view.";
+const char kPopupsDisallowed[] =
+ "Popups are only supported from toolstrip or tab-contents views.";
// Keys.
const wchar_t kUrlKey[] = L"url";
@@ -70,7 +72,8 @@
// containing view or any of *its* children.
class ExtensionPopupHost : public ExtensionPopup::Observer,
public views::WidgetFocusChangeListener,
- public base::RefCounted<ExtensionPopupHost> {
+ public base::RefCounted<ExtensionPopupHost>,
+ public NotificationObserver {
public:
explicit ExtensionPopupHost(ExtensionFunctionDispatcher* dispatcher)
: dispatcher_(dispatcher), popup_(NULL) {
@@ -85,9 +88,18 @@
void set_popup(ExtensionPopup* popup) {
popup_ = popup;
+
+ // Now that a popup has been assigned, listen for subsequent popups being
+ // created in the same extension - we want to disallow more than one
+ // concurrently displayed popup windows.
+ registrar_.Add(
+ this,
+ NotificationType::EXTENSION_HOST_CREATED,
+ Source<ExtensionProcessManager>(
+ dispatcher_->profile()->GetExtensionProcessManager()));
}
- // Overriden from ExtensionPopup::Observer
+ // Overridden from ExtensionPopup::Observer
virtual void ExtensionPopupClosed(ExtensionPopup* popup) {
// Unregister the automation resource routing registered upon host
// creation.
@@ -119,9 +131,13 @@
Release(); // Balanced in ctor.
}
- // Overriden from views::WidgetFocusChangeListener
+ // Overridden from views::WidgetFocusChangeListener
virtual void NativeFocusWillChange(gfx::NativeView focused_before,
gfx::NativeView focused_now) {
+ // If the popup doesn't exist, then do nothing.
+ if (!popup_)
+ return;
+
// If no view is to be focused, then Chrome was deactivated, so hide the
// popup.
if (focused_now) {
@@ -130,10 +146,13 @@
// 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;
+ ExtensionView* view = popup_->host()->view();
+ if (view) {
+ views::Widget* popup_root_widget = 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.
@@ -156,6 +175,23 @@
&ExtensionPopup::Close));
}
+ // Overridden from NotificationObserver
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(NotificationType::EXTENSION_HOST_CREATED == type);
+ if (NotificationType::EXTENSION_HOST_CREATED == type) {
+ Details<ExtensionHost> details_host(details);
+ // Disallow multiple pop-ups from the same extension, by closing
+ // the presently opened popup during construction of any new popups.
+ if (ViewType::EXTENSION_POPUP == details_host->GetRenderViewType() &&
+ popup_->host()->extension() == details_host->extension() &&
+ Details<ExtensionHost>(popup_->host()) != details) {
+ popup_->Close();
+ }
+ }
+ }
+
private:
// Returns the AutomationResourceRoutingDelegate interface for |dispatcher|.
static AutomationResourceRoutingDelegate*
@@ -177,6 +213,8 @@
// A pointer to the popup.
ExtensionPopup* popup_;
+ NotificationRegistrar registrar_;
+
DISALLOW_COPY_AND_ASSIGN(ExtensionPopupHost);
};
#endif // TOOLKIT_VIEWS
@@ -211,6 +249,16 @@
}
bool PopupShowFunction::RunImpl() {
+ // Popups may only be displayed from TAB_CONTENTS and EXTENSION_TOOLSTRIP
+ // views.
+ ViewType::Type view_type =
+ dispatcher()->render_view_host()->delegate()->GetRenderViewType();
+ if (ViewType::EXTENSION_TOOLSTRIP != view_type &&
+ ViewType::TAB_CONTENTS != view_type) {
+ error_ = kPopupsDisallowed;
+ return false;
+ }
+
EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
const ListValue* args = args_as_list();
@@ -272,7 +320,6 @@
return false;
}
-#if defined(TOOLKIT_VIEWS)
gfx::Point origin(dom_left, dom_top);
if (!dispatcher()->render_view_host()->view()) {
error_ = kNotAnExtension;
@@ -284,14 +331,6 @@
origin.Offset(content_bounds.x(), content_bounds.y());
gfx::Rect rect(origin.x(), origin.y(), dom_width, dom_height);
- // Pop-up from extension views (ExtensionShelf, etc.), and drop-down when
- // in a TabContents view.
- ViewType::Type view_type =
- dispatcher()->render_view_host()->delegate()->GetRenderViewType();
- BubbleBorder::ArrowLocation arrow_location =
- view_type == ViewType::TAB_CONTENTS ?
- BubbleBorder::TOP_LEFT : BubbleBorder::BOTTOM_LEFT;
-
// Get the correct native window to pass to ExtensionPopup.
// ExtensionFunctionDispatcher::Delegate may provide a custom implementation
// of this.
@@ -300,6 +339,13 @@
if (!window)
window = GetCurrentBrowser()->window()->GetNativeHandle();
+#if defined(TOOLKIT_VIEWS)
+ // Pop-up from extension views (ExtensionShelf, etc.), and drop-down when
+ // in a TabContents view.
+ BubbleBorder::ArrowLocation arrow_location =
+ view_type == ViewType::TAB_CONTENTS ?
+ BubbleBorder::TOP_LEFT : BubbleBorder::BOTTOM_LEFT;
+
// ExtensionPopupHost manages it's own lifetime.
ExtensionPopupHost* popup_host = new ExtensionPopupHost(dispatcher());
popup_ = ExtensionPopup::Show(url,
@@ -329,6 +375,8 @@
type == NotificationType::EXTENSION_HOST_DESTROYED);
DCHECK(popup_ != NULL);
+ // Wait for notification that the popup view is ready (and onload has been
+ // called), before completing the API call.
if (popup_ && type == NotificationType::EXTENSION_POPUP_VIEW_READY &&
Details<ExtensionHost>(popup_->host()) == details) {
SendResponse(true);
« no previous file with comments | « chrome/browser/extensions/extension_host.cc ('k') | chrome/browser/renderer_host/render_view_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698