summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/extension_popup_api.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/extensions/extension_popup_api.cc')
-rw-r--r--chrome/browser/extensions/extension_popup_api.cc71
1 files changed, 56 insertions, 15 deletions
diff --git a/chrome/browser/extensions/extension_popup_api.cc b/chrome/browser/extensions/extension_popup_api.cc
index a6f85f2..c8ef519 100644
--- a/chrome/browser/extensions/extension_popup_api.cc
+++ b/chrome/browser/extensions/extension_popup_api.cc
@@ -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 @@ namespace {
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 @@ const char kRectangleChrome[] = "rectangle";
// 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 @@ class ExtensionPopupHost : public ExtensionPopup::Observer,
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,7 +131,7 @@ class ExtensionPopupHost : public ExtensionPopup::Observer,
Release(); // Balanced in ctor.
}
- // Overriden from views::WidgetFocusChangeListener
+ // Overridden 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
@@ -156,6 +168,23 @@ class ExtensionPopupHost : public ExtensionPopup::Observer,
&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 +206,8 @@ class ExtensionPopupHost : public ExtensionPopup::Observer,
// A pointer to the popup.
ExtensionPopup* popup_;
+ NotificationRegistrar registrar_;
+
DISALLOW_COPY_AND_ASSIGN(ExtensionPopupHost);
};
#endif // TOOLKIT_VIEWS
@@ -211,6 +242,16 @@ void PopupShowFunction::Run() {
}
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 +313,6 @@ bool PopupShowFunction::RunImpl() {
return false;
}
-#if defined(TOOLKIT_VIEWS)
gfx::Point origin(dom_left, dom_top);
if (!dispatcher()->render_view_host()->view()) {
error_ = kNotAnExtension;
@@ -284,14 +324,6 @@ bool PopupShowFunction::RunImpl() {
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 +332,13 @@ bool PopupShowFunction::RunImpl() {
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 +368,8 @@ void PopupShowFunction::Observe(NotificationType type,
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);