summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortwiz@chromium.org <twiz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-12 20:27:10 +0000
committertwiz@chromium.org <twiz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-12 20:27:10 +0000
commitc7bf140b32a1a6504e48716b90c6a13fd5c421d3 (patch)
tree876ada1f8ca6320060aab4db3790522989829d31
parent1be7eadb032256687abda35ae4b2ba4770757c70 (diff)
downloadchromium_src-c7bf140b32a1a6504e48716b90c6a13fd5c421d3.zip
chromium_src-c7bf140b32a1a6504e48716b90c6a13fd5c421d3.tar.gz
chromium_src-c7bf140b32a1a6504e48716b90c6a13fd5c421d3.tar.bz2
Clone of issue 577015.
See http://codereview.chromium.org/577015 for the review status of this CL. BUG=None TEST=ExtensionApiTest.Popup Review URL: http://codereview.chromium.org/600101 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@38927 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--app/win/window_impl.h2
-rw-r--r--chrome/browser/extensions/extension_popup_api.cc19
-rw-r--r--chrome/browser/views/browser_actions_container.cc16
-rw-r--r--chrome/browser/views/browser_bubble.cc5
-rw-r--r--chrome/browser/views/browser_bubble.h8
-rw-r--r--chrome/browser/views/browser_bubble_gtk.cc4
-rw-r--r--chrome/browser/views/browser_bubble_win.cc5
-rw-r--r--chrome/browser/views/extensions/extension_popup.cc157
-rw-r--r--chrome/browser/views/extensions/extension_popup.h31
-rw-r--r--chrome/browser/views/extensions/extension_shelf.cc3
-rw-r--r--chrome/browser/views/location_bar_view.cc16
-rwxr-xr-xchrome/common/extensions/api/extension_api.json6
-rw-r--r--chrome/renderer/resources/extension_process_bindings.js8
-rw-r--r--chrome/test/data/extensions/api_test/popup/toolband.html14
-rw-r--r--views/controls/native/native_view_host.cc11
15 files changed, 231 insertions, 74 deletions
diff --git a/app/win/window_impl.h b/app/win/window_impl.h
index fb5d512..2f6a2ab 100644
--- a/app/win/window_impl.h
+++ b/app/win/window_impl.h
@@ -68,7 +68,7 @@ class WindowImpl : public MessageMapInterface {
DCHECK_EQ((class_style & CS_GLOBALCLASS), 0);
class_style_ = class_style;
}
- UINT initial_class_style() { return class_style_; }
+ UINT initial_class_style() const { return class_style_; }
protected:
// Handles the WndProc callback for this object.
diff --git a/chrome/browser/extensions/extension_popup_api.cc b/chrome/browser/extensions/extension_popup_api.cc
index f68553c..48e414c 100644
--- a/chrome/browser/extensions/extension_popup_api.cc
+++ b/chrome/browser/extensions/extension_popup_api.cc
@@ -44,6 +44,10 @@ const wchar_t kTopKey[] = L"top";
const wchar_t kLeftKey[] = L"left";
const wchar_t kGiveFocusKey[] = L"giveFocus";
const wchar_t kDomAnchorKey[] = L"domAnchor";
+const wchar_t kBorderStyleKey[] = L"borderStyle";
+
+// chrome enumeration values
+const char kRectangleChrome[] = "rectangle";
}; // namespace
@@ -111,6 +115,18 @@ bool PopupShowFunction::RunImpl() {
&give_focus));
}
+#if defined(TOOLKIT_VIEWS)
+ // The default behaviour is to provide the bubble-chrome to the popup.
+ ExtensionPopup::PopupChrome chrome = ExtensionPopup::BUBBLE_CHROME;
+ if (show_details->HasKey(kBorderStyleKey)) {
+ std::string chrome_string;
+ EXTENSION_FUNCTION_VALIDATE(show_details->GetString(kBorderStyleKey,
+ &chrome_string));
+ if (chrome_string == kRectangleChrome)
+ chrome = ExtensionPopup::RECTANGLE_CHROME;
+ }
+#endif
+
GURL url = dispatcher()->url().Resolve(url_string);
if (!url.is_valid()) {
error_ = kInvalidURLError;
@@ -144,7 +160,8 @@ bool PopupShowFunction::RunImpl() {
dispatcher()->GetFrameNativeWindow(),
rect,
arrow_location,
- give_focus);
+ give_focus,
+ chrome);
ExtensionPopupHost* popup_host = dispatcher()->GetPopupHost();
DCHECK(popup_host);
diff --git a/chrome/browser/views/browser_actions_container.cc b/chrome/browser/views/browser_actions_container.cc
index 5a1ae90..be8cf1b 100644
--- a/chrome/browser/views/browser_actions_container.cc
+++ b/chrome/browser/views/browser_actions_container.cc
@@ -534,13 +534,15 @@ void BrowserActionsContainer::OnBrowserActionExecuted(
BubbleBorder::ArrowLocation arrow_location = UILayoutIsRightToLeft() ?
BubbleBorder::TOP_LEFT : BubbleBorder::TOP_RIGHT;
- popup_ = ExtensionPopup::Show(button->GetPopupUrl(),
- browser_,
- browser_->profile(),
- frame_window,
- rect,
- arrow_location,
- true); // Activate the popup window.
+ popup_ = ExtensionPopup::Show(
+ button->GetPopupUrl(),
+ browser_,
+ browser_->profile(),
+ frame_window,
+ rect,
+ arrow_location,
+ true, // Activate the popup window.
+ ExtensionPopup::BUBBLE_CHROME);
popup_->set_delegate(this);
popup_button_ = button;
popup_button_->SetButtonPushed();
diff --git a/chrome/browser/views/browser_bubble.cc b/chrome/browser/views/browser_bubble.cc
index 26dff82..1b690db 100644
--- a/chrome/browser/views/browser_bubble.cc
+++ b/chrome/browser/views/browser_bubble.cc
@@ -25,12 +25,13 @@ BrowserView* GetBrowserViewFromFrame(views::Widget* frame) {
} // namespace
BrowserBubble::BrowserBubble(views::View* view, views::Widget* frame,
- const gfx::Point& origin)
+ const gfx::Point& origin, bool drop_shadow)
: frame_(frame),
view_(view),
visible_(false),
delegate_(NULL),
- attached_(false) {
+ attached_(false),
+ drop_shadow_enabled_(drop_shadow) {
gfx::Size size = view->GetPreferredSize();
bounds_.SetRect(origin.x(), origin.y(), size.width(), size.height());
InitPopup();
diff --git a/chrome/browser/views/browser_bubble.h b/chrome/browser/views/browser_bubble.h
index 25b91e9..012c552 100644
--- a/chrome/browser/views/browser_bubble.h
+++ b/chrome/browser/views/browser_bubble.h
@@ -38,9 +38,10 @@ class BrowserBubble {
// Note that the bubble will size itself to the preferred size of |view|.
// |view| is the embedded view, |frame| is widget that the bubble is being
// positioned relative to, |origin| is the location that the bubble will
- // be positioned relative to |frame|.
+ // be positioned relative to |frame|. Pass true through |drop_shadow| to
+ // surround the bubble widget with a drop-shadow.
BrowserBubble(views::View* view, views::Widget* frame,
- const gfx::Point& origin);
+ const gfx::Point& origin, bool drop_shadow);
virtual ~BrowserBubble();
// Call manually if you need to detach the bubble from tracking the browser's
@@ -116,6 +117,9 @@ class BrowserBubble {
// Is the bubble attached to a Browser window.
bool attached_;
+ // Does the bubble have a drop-shadow.
+ bool drop_shadow_enabled_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserBubble);
};
diff --git a/chrome/browser/views/browser_bubble_gtk.cc b/chrome/browser/views/browser_bubble_gtk.cc
index ebc343a..66b07c1 100644
--- a/chrome/browser/views/browser_bubble_gtk.cc
+++ b/chrome/browser/views/browser_bubble_gtk.cc
@@ -76,6 +76,10 @@ class BubbleWidget : public views::WidgetGtk {
} // namespace
void BrowserBubble::InitPopup() {
+ // TODO(port)
+ DCHECK(!drop_shadow_enabled_) <<
+ "Drop shadows not supported on GTK browser bubbles.";
+
views::WidgetGtk* pop = new BubbleWidget(this);
pop->SetOpacity(0xFF);
pop->make_transient_to_parent();
diff --git a/chrome/browser/views/browser_bubble_win.cc b/chrome/browser/views/browser_bubble_win.cc
index 2a2a4c2..a74b84a 100644
--- a/chrome/browser/views/browser_bubble_win.cc
+++ b/chrome/browser/views/browser_bubble_win.cc
@@ -79,6 +79,11 @@ void BrowserBubble::InitPopup() {
// popup_ is a Widget, but we need to do some WidgetWin stuff first, then
// we'll assign it into popup_.
views::WidgetWin* pop = new BubbleWidget(this);
+
+ // Enable the drop-shadow through the native windows drop-shadow support.
+ if (drop_shadow_enabled_)
+ pop->set_initial_class_style(CS_DROPSHADOW | pop->initial_class_style());
+
pop->Init(frame_->GetNativeView(), bounds_);
pop->SetContentsView(view_);
diff --git a/chrome/browser/views/extensions/extension_popup.cc b/chrome/browser/views/extensions/extension_popup.cc
index 9fc5ae7..70c9222 100644
--- a/chrome/browser/views/extensions/extension_popup.cc
+++ b/chrome/browser/views/extensions/extension_popup.cc
@@ -14,6 +14,7 @@
#include "chrome/common/notification_details.h"
#include "chrome/common/notification_source.h"
#include "chrome/common/notification_type.h"
+#include "third_party/skia/include/core/SkColor.h"
#include "views/widget/root_view.h"
#include "views/window/window.h"
@@ -32,17 +33,32 @@ const int ExtensionPopup::kMinHeight = 25;
const int ExtensionPopup::kMaxWidth = 800;
const int ExtensionPopup::kMaxHeight = 600;
+// The width, in pixels, of the black-border on a popup.
+const int kPopupBorderWidth = 1;
+
+const int kPopupBubbleCornerRadius = BubbleBorder::GetCornerRadius() / 2;
+
ExtensionPopup::ExtensionPopup(ExtensionHost* host,
views::Widget* frame,
const gfx::Rect& relative_to,
BubbleBorder::ArrowLocation arrow_location,
- bool activate_on_show)
+ bool activate_on_show,
+ PopupChrome chrome)
: BrowserBubble(host->view(),
frame,
- gfx::Point()),
+ gfx::Point(),
+ RECTANGLE_CHROME == chrome), // If no bubble chrome is to
+ // be displayed, then enable a
+ // drop-shadow on the bubble
+ // widget.
relative_to_(relative_to),
extension_host_(host),
- activate_on_show_(activate_on_show) {
+ activate_on_show_(activate_on_show),
+ border_widget_(NULL),
+ border_(NULL),
+ border_view_(NULL),
+ popup_chrome_(chrome),
+ anchor_position_(arrow_location) {
host->view()->SetContainer(this);
registrar_.Add(this,
NotificationType::EXTENSION_HOST_DID_STOP_LOADING,
@@ -51,45 +67,56 @@ ExtensionPopup::ExtensionPopup(ExtensionHost* host,
// TODO(erikkay) Some of this border code is derived from InfoBubble.
// We should see if we can unify these classes.
- gfx::NativeView native_window = frame->GetNativeView();
+ // The bubble chrome requires a separate window, so construct it here.
+ if (BUBBLE_CHROME == popup_chrome_) {
+ gfx::NativeView native_window = frame->GetNativeView();
#if defined(OS_LINUX)
- border_widget_ = new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW);
- static_cast<views::WidgetGtk*>(border_widget_)->MakeTransparent();
- static_cast<views::WidgetGtk*>(border_widget_)->make_transient_to_parent();
+ border_widget_ = new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW);
+ static_cast<views::WidgetGtk*>(border_widget_)->MakeTransparent();
+ static_cast<views::WidgetGtk*>(border_widget_)->make_transient_to_parent();
#else
- border_widget_ = Widget::CreatePopupWidget(Widget::Transparent,
- Widget::NotAcceptEvents,
- Widget::DeleteOnDestroy);
+ border_widget_ = Widget::CreatePopupWidget(Widget::Transparent,
+ Widget::NotAcceptEvents,
+ Widget::DeleteOnDestroy);
#endif
- border_widget_->Init(native_window, bounds());
+ border_widget_->Init(native_window, bounds());
#if defined(OS_LINUX)
- TabOverviewTypes::instance()->SetWindowType(
- border_widget_->GetNativeView(),
- TabOverviewTypes::WINDOW_TYPE_CHROME_INFO_BUBBLE,
- NULL);
+ TabOverviewTypes::instance()->SetWindowType(
+ border_widget_->GetNativeView(),
+ TabOverviewTypes::WINDOW_TYPE_CHROME_INFO_BUBBLE,
+ NULL);
#endif
- border_ = new BubbleBorder;
- border_->set_arrow_location(arrow_location);
+ border_ = new BubbleBorder;
+ border_->set_arrow_location(arrow_location);
- border_view_ = new views::View;
- border_view_->set_background(new BubbleBackground(border_));
- border_view_->set_border(border_);
- border_widget_->SetContentsView(border_view_);
+ border_view_ = new views::View;
+ border_view_->set_background(new BubbleBackground(border_));
- // Ensure that the popup contents are always displayed ontop of the border
- // widget.
- border_widget_->MoveAbove(popup_);
+ border_view_->set_border(border_);
+ border_widget_->SetContentsView(border_view_);
+ // Ensure that the popup contents are always displayed ontop of the border
+ // widget.
+ border_widget_->MoveAbove(popup_);
+ } else {
+ // Otherwise simply set a black-border on the view containing the popup
+ // extension view.
+ views::Border* border = views::Border::CreateSolidBorder(kPopupBorderWidth,
+ SK_ColorBLACK);
+ view()->set_border(border);
+ }
}
ExtensionPopup::~ExtensionPopup() {
// The widget is set to delete on destroy, so no leak here.
- border_widget_->Close();
+ if (border_widget_)
+ border_widget_->Close();
}
void ExtensionPopup::Hide() {
BrowserBubble::Hide();
- border_widget_->Hide();
+ if (border_widget_)
+ border_widget_->Hide();
}
void ExtensionPopup::Show(bool activate) {
@@ -104,7 +131,8 @@ void ExtensionPopup::Show(bool activate) {
ResizeToView();
// Show the border first, then the popup overlaid on top.
- border_widget_->Show();
+ if (border_widget_)
+ border_widget_->Show();
BrowserBubble::Show(activate);
}
@@ -113,27 +141,27 @@ void ExtensionPopup::ResizeToView() {
// know our position to do it.
gfx::Size new_size = view()->size();
- // The rounded corners cut off more of the view than the border insets claim.
- // Since we can't clip the ExtensionView's corners, we need to increase the
- // inset by half the corner radius as well as lying about the size of the
- // contents size to compensate.
- int corner_inset = BubbleBorder::GetCornerRadius() / 2;
- gfx::Size adjusted_size = new_size;
- adjusted_size.Enlarge(2 * corner_inset, 2 * corner_inset);
- gfx::Rect rect = border_->GetBounds(relative_to_, adjusted_size);
- border_widget_->SetBounds(rect);
-
- // Now calculate the inner bounds. This is a bit more convoluted than
- // it should be because BrowserBubble coordinates are in Browser coordinates
- // while |rect| is in screen coordinates.
- gfx::Insets border_insets;
- border_->GetInsets(&border_insets);
+ gfx::Rect rect = GetOuterBounds(relative_to_, new_size);
gfx::Point origin = rect.origin();
views::View::ConvertPointToView(NULL, frame_->GetRootView(), &origin);
- origin.set_x(origin.x() + border_insets.left() + corner_inset);
- origin.set_y(origin.y() + border_insets.top() + corner_inset);
+ if (border_widget_) {
+ // Set the bubble-chrome widget according to the outer bounds of the entire
+ // popup.
+ border_widget_->SetBounds(rect);
- SetBounds(origin.x(), origin.y(), new_size.width(), new_size.height());
+ // Now calculate the inner bounds. This is a bit more convoluted than
+ // it should be because BrowserBubble coordinates are in Browser coordinates
+ // while |rect| is in screen coordinates.
+ gfx::Insets border_insets;
+ border_->GetInsets(&border_insets);
+
+ origin.set_x(origin.x() + border_insets.left() + kPopupBubbleCornerRadius);
+ origin.set_y(origin.y() + border_insets.top() + kPopupBubbleCornerRadius);
+
+ SetBounds(origin.x(), origin.y(), new_size.width(), new_size.height());
+ } else {
+ SetBounds(origin.x(), origin.y(), rect.width(), rect.height());
+ }
}
void ExtensionPopup::Observe(NotificationType type,
@@ -159,6 +187,39 @@ void ExtensionPopup::OnExtensionPreferredSizeChanged(ExtensionView* view) {
ResizeToView();
}
+gfx::Rect ExtensionPopup::GetOuterBounds(const gfx::Rect& position_relative_to,
+ const gfx::Size& contents_size) const {
+ gfx::Size adjusted_size = contents_size;
+ // If the popup has a bubble-chrome, then let the BubbleBorder compute
+ // the bounds.
+ if (BUBBLE_CHROME == popup_chrome_) {
+ // The rounded corners cut off more of the view than the border insets
+ // claim. Since we can't clip the ExtensionView's corners, we need to
+ // increase the inset by half the corner radius as well as lying about the
+ // size of the contents size to compensate.
+ adjusted_size.Enlarge(2 * kPopupBubbleCornerRadius,
+ 2 * kPopupBubbleCornerRadius);
+ return border_->GetBounds(position_relative_to, adjusted_size);
+ }
+
+ // Otherwise, enlarge the bounds by the size of the local border.
+ gfx::Insets border_insets;
+ view()->border()->GetInsets(&border_insets);
+ adjusted_size.Enlarge(border_insets.width(), border_insets.height());
+
+ // Position the bounds according to the location of the |anchor_position_|.
+ int y;
+ if ((anchor_position_ == BubbleBorder::TOP_LEFT) ||
+ (anchor_position_ == BubbleBorder::TOP_RIGHT)) {
+ y = position_relative_to.bottom();
+ } else {
+ y = position_relative_to.y() - adjusted_size.height();
+ }
+
+ return gfx::Rect(position_relative_to.x(), y, adjusted_size.width(),
+ adjusted_size.height());
+}
+
// static
ExtensionPopup* ExtensionPopup::Show(
const GURL& url,
@@ -167,7 +228,8 @@ ExtensionPopup* ExtensionPopup::Show(
gfx::NativeWindow frame_window,
const gfx::Rect& relative_to,
BubbleBorder::ArrowLocation arrow_location,
- bool activate_on_show) {
+ bool activate_on_show,
+ PopupChrome chrome) {
DCHECK(profile);
DCHECK(frame_window);
ExtensionProcessManager* manager = profile->GetExtensionProcessManager();
@@ -187,7 +249,8 @@ ExtensionPopup* ExtensionPopup::Show(
ExtensionHost* host = manager->CreatePopup(url, browser);
ExtensionPopup* popup = new ExtensionPopup(host, frame_widget, relative_to,
- arrow_location, activate_on_show);
+ arrow_location, activate_on_show,
+ chrome);
// If the host had somehow finished loading, then we'd miss the notification
// and not show. This seems to happen in single-process mode.
diff --git a/chrome/browser/views/extensions/extension_popup.h b/chrome/browser/views/extensions/extension_popup.h
index 92eab93..72df7b2 100644
--- a/chrome/browser/views/extensions/extension_popup.h
+++ b/chrome/browser/views/extensions/extension_popup.h
@@ -26,6 +26,11 @@ class ExtensionPopup : public BrowserBubble,
public NotificationObserver,
public ExtensionView::Container {
public:
+ enum PopupChrome {
+ BUBBLE_CHROME,
+ RECTANGLE_CHROME
+ };
+
virtual ~ExtensionPopup();
// Create and show a popup with |url| positioned adjacent to |relative_to| in
@@ -42,6 +47,12 @@ class ExtensionPopup : public BrowserBubble,
// If |arrow_location| is BOTTOM_*, then the popup 'pops up', otherwise
// the popup 'drops down'.
// Pass |activate_on_show| as true to activate the popup window.
+ // The |chrome| argument controls the chrome that surrounds the pop-up.
+ // Passing BUBBLE_CHROME will give the pop-up a bubble-like appearance,
+ // including the arrow mentioned above. Passing RECTANGLE_CHROME will give
+ // the popup a rectangular, black border with a drop-shadow with no arrow.
+ // The positioning of the popup is still governed by the arrow-location
+ // parameter.
//
// The actual display of the popup is delayed until the page contents
// finish loading in order to minimize UI flashing and resizing.
@@ -50,7 +61,8 @@ class ExtensionPopup : public BrowserBubble,
gfx::NativeWindow frame_window,
const gfx::Rect& relative_to,
BubbleBorder::ArrowLocation arrow_location,
- bool activate_on_show);
+ bool activate_on_show,
+ PopupChrome chrome);
ExtensionHost* host() const { return extension_host_.get(); }
@@ -80,7 +92,14 @@ class ExtensionPopup : public BrowserBubble,
views::Widget* frame,
const gfx::Rect& relative_to,
BubbleBorder::ArrowLocation arrow_location,
- bool activate_on_show);
+ bool activate_on_show,
+ PopupChrome chrome);
+
+ // Gives the desired bounds (in screen coordinates) given the rect to point
+ // to and the size of the contained contents. Includes all of the
+ // border-chrome surrounding the pop-up as well.
+ gfx::Rect GetOuterBounds(const gfx::Rect& position_relative_to,
+ const gfx::Size& contents_size) const;
// The area on the screen that the popup should be positioned relative to.
gfx::Rect relative_to_;
@@ -101,6 +120,14 @@ class ExtensionPopup : public BrowserBubble,
BubbleBorder* border_;
views::View* border_view_;
+ // The type of chrome associated with the popup window.
+ PopupChrome popup_chrome_;
+
+ // A cached copy of the arrow-position for the bubble chrome.
+ // If a black-border was requested, we still need this value to determine
+ // the position of the pop-up in relation to |relative_to_|.
+ BubbleBorder::ArrowLocation anchor_position_;
+
DISALLOW_COPY_AND_ASSIGN(ExtensionPopup);
};
diff --git a/chrome/browser/views/extensions/extension_shelf.cc b/chrome/browser/views/extensions/extension_shelf.cc
index 69b6dc1..640dfed 100644
--- a/chrome/browser/views/extensions/extension_shelf.cc
+++ b/chrome/browser/views/extensions/extension_shelf.cc
@@ -428,7 +428,8 @@ void ExtensionShelf::Toolstrip::LayoutWindow() {
if (!window_.get()) {
window_.reset(new BrowserBubble(this, shelf_->GetWidget(),
- gfx::Point(0, 0)));
+ gfx::Point(0, 0),
+ false)); // Do not add a drop-shadow.
window_->set_delegate(this);
}
diff --git a/chrome/browser/views/location_bar_view.cc b/chrome/browser/views/location_bar_view.cc
index fef451d..18d0f1a 100644
--- a/chrome/browser/views/location_bar_view.cc
+++ b/chrome/browser/views/location_bar_view.cc
@@ -1501,13 +1501,15 @@ void LocationBarView::PageActionImageView::ExecuteAction(int button) {
rect.set_x(origin.x());
rect.set_y(origin.y());
- popup_ = ExtensionPopup::Show(page_action_->GetPopupUrl(current_tab_id_),
- browser,
- browser->profile(),
- browser->window()->GetNativeHandle(),
- rect,
- BubbleBorder::TOP_RIGHT,
- true); // Activate the popup window.
+ popup_ = ExtensionPopup::Show(
+ page_action_->GetPopupUrl(current_tab_id_),
+ browser,
+ browser->profile(),
+ browser->window()->GetNativeHandle(),
+ rect,
+ BubbleBorder::TOP_RIGHT,
+ true, // Activate the popup window.
+ ExtensionPopup::BUBBLE_CHROME);
popup_->set_delegate(this);
} else {
ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted(
diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json
index 69805df..562ada0 100755
--- a/chrome/common/extensions/api/extension_api.json
+++ b/chrome/common/extensions/api/extension_api.json
@@ -1912,6 +1912,12 @@
"type": "boolean",
"description": "Pass true to give the focus to the popup window. The default behaviour is true.",
"optional": true
+ },
+ "borderStyle": {
+ "type": "string",
+ "description": "Pass 'bubble' to give the pop-up window a bubble-chrome border, including an arrow pointing at the relative-to point. Pass 'rectangle' to give the pop-up a rectangular black border with drop-shadow. Default behaviour is to pass 'bubble'.",
+ "optional": true,
+ "enum": ["bubble", "rectangle"]
}
}
},
diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js
index 4b50d36..f543366 100644
--- a/chrome/renderer/resources/extension_process_bindings.js
+++ b/chrome/renderer/resources/extension_process_bindings.js
@@ -447,6 +447,11 @@ var chrome = chrome || {};
giveFocus: {
type: "boolean",
optional: true
+ },
+ borderStyle: {
+ type: "string",
+ optional: true,
+ enum: ["bubble", "rectangle"]
}
}
},
@@ -456,7 +461,8 @@ var chrome = chrome || {};
[url,
{
domAnchor: getAbsoluteRect(showDetails.relativeTo),
- giveFocus: showDetails.giveFocus
+ giveFocus: showDetails.giveFocus,
+ borderStyle: showDetails.borderStyle
},
callback],
internalSchema);
diff --git a/chrome/test/data/extensions/api_test/popup/toolband.html b/chrome/test/data/extensions/api_test/popup/toolband.html
index 77467ee..f0dd50b2 100644
--- a/chrome/test/data/extensions/api_test/popup/toolband.html
+++ b/chrome/test/data/extensions/api_test/popup/toolband.html
@@ -92,6 +92,20 @@ window.onload = function() {
// chrome.experimental.extension.getPopupView() == undefined);
});
chrome.experimental.extension.getPopupView().close();
+ },
+ function popupBlackBorder() {
+ // Validate that displaying a pop-up with a black border still invokes
+ // the callback successfully. Note that this test does not validate
+ // the actual style of the border displayed.
+ var showDetails = {
+ "relativeTo": document.getElementById("anchorHere"),
+ "borderStyle": "rectangle"
+ };
+ chrome.experimental.popup.show("toolband_popup.html",
+ showDetails,
+ chrome.test.callbackPass(function() {
+ chrome.experimental.extension.getPopupView().close();
+ }));
}
]);
}
diff --git a/views/controls/native/native_view_host.cc b/views/controls/native/native_view_host.cc
index 79abc1d..463f149 100644
--- a/views/controls/native/native_view_host.cc
+++ b/views/controls/native/native_view_host.cc
@@ -98,10 +98,15 @@ void NativeViewHost::Layout() {
// Since widgets know nothing about the View hierarchy (they are direct
// children of the Widget that hosts our View hierarchy) they need to be
// positioned in the coordinate system of the Widget, not the current
- // view.
- gfx::Point top_left;
+ // view. Also, they should be positioned respecting the border insets
+ // of the native view.
+ gfx::Insets insets = GetInsets();
+ gfx::Point top_left(insets.left(), insets.top());
ConvertPointToWidget(this, &top_left);
- native_wrapper_->ShowWidget(top_left.x(), top_left.y(), width(), height());
+ gfx::Rect local_bounds = GetLocalBounds(false);
+ native_wrapper_->ShowWidget(top_left.x(), top_left.y(),
+ local_bounds.width(),
+ local_bounds.height());
} else {
native_wrapper_->HideWidget();
}