diff options
32 files changed, 273 insertions, 117 deletions
diff --git a/chrome/browser/chromeos/main_menu.h b/chrome/browser/chromeos/main_menu.h index 2d896fc..11e9942 100644 --- a/chrome/browser/chromeos/main_menu.h +++ b/chrome/browser/chromeos/main_menu.h @@ -18,6 +18,9 @@ class Browser; class RenderWidgetHostViewGtk; class SiteInstance; +namespace gfx { +class Size; +} namespace views { class WidgetGtk; } @@ -162,7 +165,7 @@ class MainMenu : public RenderViewHostDelegate, virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {} virtual void HandleMouseEvent() {} virtual void HandleMouseLeave() {} - virtual void UpdatePreferredWidth(int pref_width) {} + virtual void UpdatePreferredSize(const gfx::Size& pref_size) {} // The currently active browser. We use this to open urls. Browser* browser_; diff --git a/chrome/browser/cocoa/extension_view_mac.h b/chrome/browser/cocoa/extension_view_mac.h index 8abb481..4ce4c13 100644 --- a/chrome/browser/cocoa/extension_view_mac.h +++ b/chrome/browser/cocoa/extension_view_mac.h @@ -7,6 +7,7 @@ #include "app/gfx/native_widget_types.h" #include "base/basictypes.h" +#include "base/gfx/size.h" #include "third_party/skia/include/core/SkBitmap.h" class Browser; @@ -40,9 +41,9 @@ class ExtensionViewMac { // Sets the extensions's background image. void SetBackground(const SkBitmap& background); - // Method for the ExtensionHost to notify us about the correct width for + // Method for the ExtensionHost to notify us about the correct size for // extension contents. - void UpdatePreferredWidth(int pref_width); + void UpdatePreferredSize(const gfx::Size& new_size); // Method for the ExtensionHost to notify us when the RenderViewHost has a // connection. diff --git a/chrome/browser/cocoa/extension_view_mac.mm b/chrome/browser/cocoa/extension_view_mac.mm index c9844b3..171cc30 100644 --- a/chrome/browser/cocoa/extension_view_mac.mm +++ b/chrome/browser/cocoa/extension_view_mac.mm @@ -44,7 +44,7 @@ void ExtensionViewMac::SetBackground(const SkBitmap& background) { } } -void ExtensionViewMac::UpdatePreferredWidth(int pref_width) { +void ExtensionViewMac::UpdatePreferredSize(const gfx::Size& new_size) { // TODO(thakis, erikkay): Windows does some tricks to resize the extension // view not before it's visible. Do something similar here. @@ -52,7 +52,7 @@ void ExtensionViewMac::UpdatePreferredWidth(int pref_width) { // resizing. NSView* view = native_view(); NSRect frame = [view frame]; - frame.size.width = pref_width; + frame.size.width = new_size.width(); // RenderWidgetHostViewCocoa overrides setFrame but not setFrameSize. [view setFrame:frame]; diff --git a/chrome/browser/extensions/browser_action_apitest.cc b/chrome/browser/extensions/browser_action_apitest.cc index 692e74e..5a7c086 100644 --- a/chrome/browser/extensions/browser_action_apitest.cc +++ b/chrome/browser/extensions/browser_action_apitest.cc @@ -11,6 +11,7 @@ #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/views/browser_actions_container.h" +#include "chrome/browser/views/extensions/extension_popup.h" #include "chrome/browser/views/toolbar_view.h" #include "chrome/common/extensions/extension_action.h" #include "chrome/test/ui_test_utils.h" @@ -62,7 +63,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, BrowserAction) { ASSERT_TRUE(result); } - IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DynamicBrowserAction) { ASSERT_TRUE(RunExtensionTest("browser_action_no_icon")) << message_; @@ -84,3 +84,34 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DynamicBrowserAction) { ExtensionActionState* action_state = extension->browser_action_state(); ASSERT_TRUE(action_state->icon()); } + +IN_PROC_BROWSER_TEST_F(ExtensionApiTest, BrowserActionPopup) { + ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("popup"))); + + ResultCatcher catcher; + BrowserActionsContainer* browser_actions = + browser()->window()->GetBrowserWindowTesting()->GetToolbarView()-> + browser_actions(); + + // Simulate a click on the browser action and verify the size of the resulting + // popup. + browser_actions->TestExecuteBrowserAction(0); + EXPECT_TRUE(browser_actions->TestGetPopup() != NULL); + ASSERT_TRUE(catcher.GetNextResult()) << catcher.message(); + gfx::Rect bounds = browser_actions->TestGetPopup()->view()->bounds(); + EXPECT_EQ(100, bounds.width()); + EXPECT_EQ(100, bounds.height()); + browser_actions->HidePopup(); + EXPECT_TRUE(browser_actions->TestGetPopup() == NULL); + + // Do it again, and verify the new bigger size (the popup grows each time it's + // opened). + browser_actions->TestExecuteBrowserAction(0); + EXPECT_TRUE(browser_actions->TestGetPopup() != NULL); + ASSERT_TRUE(catcher.GetNextResult()) << catcher.message(); + bounds = browser_actions->TestGetPopup()->view()->bounds(); + EXPECT_EQ(200, bounds.width()); + EXPECT_EQ(200, bounds.height()); + browser_actions->HidePopup(); + EXPECT_TRUE(browser_actions->TestGetPopup() == NULL); +} diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc index 8b45d4c..5413cd7 100644 --- a/chrome/browser/extensions/extension_host.cc +++ b/chrome/browser/extensions/extension_host.cc @@ -213,9 +213,9 @@ void ExtensionHost::Observe(NotificationType type, } } -void ExtensionHost::UpdatePreferredWidth(int pref_width) { +void ExtensionHost::UpdatePreferredSize(const gfx::Size& new_size) { if (view_.get()) - view_->UpdatePreferredWidth(pref_width); + view_->UpdatePreferredSize(new_size); } void ExtensionHost::RenderViewGone(RenderViewHost* render_view_host) { @@ -503,7 +503,7 @@ void ExtensionHost::RenderViewCreated(RenderViewHost* render_view_host) { extension_function_dispatcher_.reset( new ExtensionFunctionDispatcher(render_view_host, this, url_)); - render_view_host->Send(new ViewMsg_EnableIntrinsicWidthChangedMode( + render_view_host->Send(new ViewMsg_EnablePreferredSizeChangedMode( render_view_host->routing_id())); } diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h index ba145b4..0c43067 100644 --- a/chrome/browser/extensions/extension_host.h +++ b/chrome/browser/extensions/extension_host.h @@ -134,7 +134,7 @@ class ExtensionHost : public RenderViewHostDelegate, virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event); virtual void HandleMouseEvent(); virtual void HandleMouseLeave(); - virtual void UpdatePreferredWidth(int pref_width); + virtual void UpdatePreferredSize(const gfx::Size& new_size); // NotificationObserver virtual void Observe(NotificationType type, diff --git a/chrome/browser/gtk/extension_view_gtk.cc b/chrome/browser/gtk/extension_view_gtk.cc index 55f7883..d7a4fca 100644 --- a/chrome/browser/gtk/extension_view_gtk.cc +++ b/chrome/browser/gtk/extension_view_gtk.cc @@ -36,8 +36,8 @@ void ExtensionViewGtk::SetBackground(const SkBitmap& background) { } } -void ExtensionViewGtk::UpdatePreferredWidth(int pref_width) { - gtk_widget_set_size_request(native_view(), pref_width, -1); +void ExtensionViewGtk::UpdatePreferredSize(const gfx::Size& new_size) { + gtk_widget_set_size_request(native_view(), new_size.width(), -1); } void ExtensionViewGtk::CreateWidgetHostView() { diff --git a/chrome/browser/gtk/extension_view_gtk.h b/chrome/browser/gtk/extension_view_gtk.h index 6f67f53..16b7892 100644 --- a/chrome/browser/gtk/extension_view_gtk.h +++ b/chrome/browser/gtk/extension_view_gtk.h @@ -7,6 +7,7 @@ #include "app/gfx/native_widget_types.h" #include "base/basictypes.h" +#include "base/gfx/size.h" #include "third_party/skia/include/core/SkBitmap.h" class Browser; @@ -29,9 +30,9 @@ class ExtensionViewGtk { void SetBackground(const SkBitmap& background); - // Method for the ExtensionHost to notify us about the correct width for + // Method for the ExtensionHost to notify us about the correct size for // extension contents. - void UpdatePreferredWidth(int pref_width); + void UpdatePreferredSize(const gfx::Size& new_size); // Method for the ExtensionHost to notify us when the RenderViewHost has a // connection. diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index 5ebe328..d8b86a7 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -764,8 +764,8 @@ void RenderViewHost::OnMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(ViewHostMsg_DidDownloadFavIcon, OnMsgDidDownloadFavIcon) IPC_MESSAGE_HANDLER(ViewHostMsg_ContextMenu, OnMsgContextMenu) IPC_MESSAGE_HANDLER(ViewHostMsg_OpenURL, OnMsgOpenURL) - IPC_MESSAGE_HANDLER(ViewHostMsg_DidContentsPreferredWidthChange, - OnMsgDidContentsPreferredWidthChange) + IPC_MESSAGE_HANDLER(ViewHostMsg_DidContentsPreferredSizeChange, + OnMsgDidContentsPreferredSizeChange) IPC_MESSAGE_HANDLER(ViewHostMsg_DomOperationResponse, OnMsgDomOperationResponse) IPC_MESSAGE_HANDLER(ViewHostMsg_DOMUISend, @@ -1189,11 +1189,12 @@ void RenderViewHost::OnMsgOpenURL(const GURL& url, delegate_->RequestOpenURL(validated_url, referrer, disposition); } -void RenderViewHost::OnMsgDidContentsPreferredWidthChange(int pref_width) { +void RenderViewHost::OnMsgDidContentsPreferredSizeChange( + const gfx::Size& new_size) { RenderViewHostDelegate::View* view = delegate_->GetViewDelegate(); if (!view) return; - view->UpdatePreferredWidth(pref_width); + view->UpdatePreferredSize(new_size); } void RenderViewHost::OnMsgDomOperationResponse( diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index acb1833..f6c1733 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -503,7 +503,7 @@ class RenderViewHost : public RenderWidgetHost, void OnMsgContextMenu(const ContextMenuParams& params); void OnMsgOpenURL(const GURL& url, const GURL& referrer, WindowOpenDisposition disposition); - void OnMsgDidContentsPreferredWidthChange(int pref_width); + void OnMsgDidContentsPreferredSizeChange(const gfx::Size& new_size); void OnMsgDomOperationResponse(const std::string& json_string, int automation_id); void OnMsgDOMUISend(const std::string& message, diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h index cb1d008..0e054d4 100644 --- a/chrome/browser/renderer_host/render_view_host_delegate.h +++ b/chrome/browser/renderer_host/render_view_host_delegate.h @@ -42,6 +42,7 @@ class WaitableEvent; namespace gfx { class Rect; +class Size; } namespace IPC { @@ -140,8 +141,8 @@ class RenderViewHostDelegate { virtual void HandleMouseEvent() = 0; virtual void HandleMouseLeave() = 0; - // The content's intrinsic width (prefWidth) changed. - virtual void UpdatePreferredWidth(int pref_width) = 0; + // The contents' preferred size changed. + virtual void UpdatePreferredSize(const gfx::Size& pref_size) = 0; }; // RendererManagerment ------------------------------------------------------- diff --git a/chrome/browser/tab_contents/interstitial_page.cc b/chrome/browser/tab_contents/interstitial_page.cc index 042801a..cb6648a 100644 --- a/chrome/browser/tab_contents/interstitial_page.cc +++ b/chrome/browser/tab_contents/interstitial_page.cc @@ -105,7 +105,7 @@ class InterstitialPage::InterstitialPageRVHViewDelegate const gfx::Rect& selection_rect, int active_match_ordinal, bool final_update); - virtual void UpdatePreferredWidth(int pref_width); + virtual void UpdatePreferredSize(const gfx::Size& pref_size); private: InterstitialPage* interstitial_page_; @@ -569,8 +569,8 @@ void InterstitialPage::InterstitialPageRVHViewDelegate::UpdateDragCursor( void InterstitialPage::InterstitialPageRVHViewDelegate::GotFocus() { } -void InterstitialPage::InterstitialPageRVHViewDelegate::UpdatePreferredWidth( - int pref_width) { +void InterstitialPage::InterstitialPageRVHViewDelegate::UpdatePreferredSize( + const gfx::Size& pref_size) { } void InterstitialPage::InterstitialPageRVHViewDelegate::TakeFocus( diff --git a/chrome/browser/tab_contents/tab_contents_view.cc b/chrome/browser/tab_contents/tab_contents_view.cc index 99a052a..2b8ae76 100644 --- a/chrome/browser/tab_contents/tab_contents_view.cc +++ b/chrome/browser/tab_contents/tab_contents_view.cc @@ -23,8 +23,8 @@ void TabContentsView::RenderViewCreated(RenderViewHost* host) { // Default implementation does nothing. Platforms may override. } -void TabContentsView::UpdatePreferredWidth(int pref_width) { - preferred_width_ = pref_width; +void TabContentsView::UpdatePreferredSize(const gfx::Size& pref_size) { + preferred_width_ = pref_size.width(); } void TabContentsView::CreateNewWindow(int route_id) { diff --git a/chrome/browser/tab_contents/tab_contents_view.h b/chrome/browser/tab_contents/tab_contents_view.h index fcef017..db5fff8 100644 --- a/chrome/browser/tab_contents/tab_contents_view.h +++ b/chrome/browser/tab_contents/tab_contents_view.h @@ -123,7 +123,7 @@ class TabContentsView : public RenderViewHostDelegate::View { virtual void HandleMouseLeave() {} // Set and return the content's intrinsic width. - virtual void UpdatePreferredWidth(int pref_width); + virtual void UpdatePreferredSize(const gfx::Size& pref_size); int preferred_width() const { return preferred_width_; } diff --git a/chrome/browser/tab_contents/tab_contents_view_mac.mm b/chrome/browser/tab_contents/tab_contents_view_mac.mm index c966ee8..3740a49 100644 --- a/chrome/browser/tab_contents/tab_contents_view_mac.mm +++ b/chrome/browser/tab_contents/tab_contents_view_mac.mm @@ -131,7 +131,7 @@ void TabContentsViewMac::RenderViewCreated(RenderViewHost* host) { // We want updates whenever the intrinsic width of the webpage // changes. Put the RenderView into that mode. int routing_id = host->routing_id(); - host->Send(new ViewMsg_EnableIntrinsicWidthChangedMode(routing_id)); + host->Send(new ViewMsg_EnablePreferredSizeChangedMode(routing_id)); } void TabContentsViewMac::SetPageTitle(const std::wstring& title) { diff --git a/chrome/browser/views/browser_actions_container.cc b/chrome/browser/views/browser_actions_container.cc index 4ce1197..aac8caf 100644 --- a/chrome/browser/views/browser_actions_container.cc +++ b/chrome/browser/views/browser_actions_container.cc @@ -271,6 +271,8 @@ class BrowserActionView : public views::View { BrowserActionView(ExtensionAction* browser_action, Extension* extension, BrowserActionsContainer* panel); + BrowserActionButton* button() { return button_; } + private: virtual void Layout(); @@ -445,15 +447,30 @@ void BrowserActionsContainer::OnBrowserActionVisibilityChanged() { void BrowserActionsContainer::HidePopup() { if (popup_) { - popup_->DetachFromBrowser(); - delete popup_; + // This sometimes gets called via a timer (See BubbleLostFocus), so clear + // the task factory. in case one is pending. + task_factory_.RevokeAll(); + + // Save these variables in local temporaries since destroying the popup + // calls BubbleLostFocus to be called, which will try to call HidePopup() + // again if popup_ is non-null. + ExtensionPopup* closing_popup = popup_; + BrowserActionButton* closing_button = popup_button_; popup_ = NULL; - popup_button_->PopupDidHide(); popup_button_ = NULL; + + closing_popup->DetachFromBrowser(); + delete closing_popup; + closing_button->PopupDidHide(); return; } } +void BrowserActionsContainer::TestExecuteBrowserAction(int index) { + BrowserActionButton* button = browser_action_views_[index]->button(); + OnBrowserActionExecuted(button); +} + void BrowserActionsContainer::OnBrowserActionExecuted( BrowserActionButton* button) { const ExtensionAction& browser_action = button->browser_action(); @@ -478,8 +495,7 @@ void BrowserActionsContainer::OnBrowserActionExecuted( rect.set_y(origin.y()); popup_ = ExtensionPopup::Show(browser_action.popup_url(), toolbar_->browser(), - rect, - browser_action.popup_height()); + rect); popup_->set_delegate(this); popup_button_ = button; popup_button_->PopupDidShow(); @@ -539,6 +555,9 @@ void BrowserActionsContainer::BubbleGotFocus(BrowserBubble* bubble) { } void BrowserActionsContainer::BubbleLostFocus(BrowserBubble* bubble) { + if (!popup_) + return; + // This is a bit annoying. If you click on the button that generated the // current popup, then we first get this lost focus message, and then // we get the click action. This results in the popup being immediately diff --git a/chrome/browser/views/browser_actions_container.h b/chrome/browser/views/browser_actions_container.h index f3b3863..c849d44 100644 --- a/chrome/browser/views/browser_actions_container.h +++ b/chrome/browser/views/browser_actions_container.h @@ -69,11 +69,17 @@ class BrowserActionsContainer : public views::View, // by default irrespective of the available space to draw them. int GetClippedPreferredWidth(int available_width); - private: - // Hide the current popup. void HidePopup(); + // Simulate a click on a browser action button. This should only be + // used by unit tests. + void TestExecuteBrowserAction(int index); + + // Retrieve the current popup. This should only be used by unit tests. + ExtensionPopup* TestGetPopup() { return popup_; } + + private: // The vector of browser actions (icons/image buttons for each action). std::vector<BrowserActionView*> browser_action_views_; diff --git a/chrome/browser/views/extensions/extension_popup.cc b/chrome/browser/views/extensions/extension_popup.cc index 0588664..53025e9 100644 --- a/chrome/browser/views/extensions/extension_popup.cc +++ b/chrome/browser/views/extensions/extension_popup.cc @@ -22,6 +22,7 @@ ExtensionPopup::ExtensionPopup(ExtensionHost* host, : BrowserBubble(host->view(), frame, gfx::Point()), relative_to_(relative_to), extension_host_(host) { + host->view()->SetContainer(this); registrar_.Add(this, NotificationType::EXTENSION_HOST_DID_STOP_LOADING, Source<Profile>(host->profile())); @@ -51,8 +52,19 @@ void ExtensionPopup::Hide() { } void ExtensionPopup::Show() { + if (visible()) + return; + ResizeToView(); + // Show the border first, then the popup overlaid on top. + border_widget_->Show(); + BrowserBubble::Show(true); +} + +void ExtensionPopup::ResizeToView() { + BrowserBubble::ResizeToView(); + // 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 @@ -73,10 +85,6 @@ void ExtensionPopup::Show() { origin.set_x(origin.x() + border_insets.left() + corner_inset); origin.set_y(origin.y() + border_insets.top() + corner_inset); MoveTo(origin.x(), origin.y()); - - // Show the border first, then the popup overlaid on top. - border_widget_->Show(); - BrowserBubble::Show(true); } void ExtensionPopup::Observe(NotificationType type, @@ -92,10 +100,14 @@ void ExtensionPopup::Observe(NotificationType type, } } +void ExtensionPopup::OnExtensionPreferredSizeChanged(ExtensionView* view) { + view->SizeToPreferredSize(); + ResizeToView(); +} + // static ExtensionPopup* ExtensionPopup::Show(const GURL& url, Browser* browser, - const gfx::Rect& relative_to, - int height) { + const gfx::Rect& relative_to) { ExtensionProcessManager* manager = browser->profile()->GetExtensionProcessManager(); DCHECK(manager); @@ -106,9 +118,6 @@ ExtensionPopup* ExtensionPopup::Show(const GURL& url, Browser* browser, views::Widget* frame = BrowserView::GetBrowserViewForNativeWindow( browser->window()->GetNativeHandle())->GetWidget(); ExtensionPopup* popup = new ExtensionPopup(host, frame, relative_to); - gfx::Size sz = host->view()->GetPreferredSize(); - sz.set_height(height); - host->view()->SetPreferredSize(sz); // 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 1e2ff73..5915f59 100644 --- a/chrome/browser/views/extensions/extension_popup.h +++ b/chrome/browser/views/extensions/extension_popup.h @@ -16,7 +16,8 @@ class Browser; class ExtensionHost; class ExtensionPopup : public BrowserBubble, - public NotificationObserver { + public NotificationObserver, + public ExtensionView::Container { public: virtual ~ExtensionPopup(); @@ -27,20 +28,25 @@ class ExtensionPopup : public BrowserBubble, // The actual display of the popup is delayed until the page contents // finish loading in order to minimize UI flashing and resizing. static ExtensionPopup* Show(const GURL& url, Browser* browser, - const gfx::Rect& relative_to, - int height); + const gfx::Rect& relative_to); ExtensionHost* host() const { return extension_host_.get(); } // BrowserBubble overrides. - virtual void Show(); virtual void Hide(); + virtual void Show(); + virtual void ResizeToView(); // NotificationObserver overrides. virtual void Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details); + // ExtensionView::Container overrides. + virtual void OnExtensionMouseEvent(ExtensionView* view) { }; + virtual void OnExtensionMouseLeave(ExtensionView* view) { }; + virtual void OnExtensionPreferredSizeChanged(ExtensionView* view); + private: ExtensionPopup(ExtensionHost* host, views::Widget* frame, diff --git a/chrome/browser/views/extensions/extension_shelf.h b/chrome/browser/views/extensions/extension_shelf.h index 08de605..3be5791 100644 --- a/chrome/browser/views/extensions/extension_shelf.h +++ b/chrome/browser/views/extensions/extension_shelf.h @@ -22,7 +22,7 @@ namespace views { // A shelf that contains Extension toolstrips. class ExtensionShelf : public DetachableToolbarView, - public ExtensionContainer, + public ExtensionView::Container, public ExtensionShelfModelObserver, public AnimationDelegate, public NotificationObserver { diff --git a/chrome/browser/views/extensions/extension_view.cc b/chrome/browser/views/extensions/extension_view.cc index f59d1a4..1d0cfc5 100644 --- a/chrome/browser/views/extensions/extension_view.cc +++ b/chrome/browser/views/extensions/extension_view.cc @@ -13,8 +13,10 @@ #include "views/widget/widget.h" ExtensionView::ExtensionView(ExtensionHost* host, Browser* browser) - : host_(host), browser_(browser), - initialized_(false), pending_preferred_width_(0), container_(NULL), + : host_(host), + browser_(browser), + initialized_(false), + container_(NULL), is_clipped_(false) { host_->set_view(this); } @@ -110,7 +112,8 @@ void ExtensionView::ShowIfCompletelyLoaded() { return; } SetVisible(true); - UpdatePreferredWidth(pending_preferred_width_); + + UpdatePreferredSize(pending_preferred_size_); } } @@ -131,17 +134,17 @@ void ExtensionView::SetBackground(const SkBitmap& background) { ShowIfCompletelyLoaded(); } -void ExtensionView::UpdatePreferredWidth(int pref_width) { +void ExtensionView::UpdatePreferredSize(const gfx::Size& new_size) { // Don't actually do anything with this information until we have been shown. // Size changes will not be honored by lower layers while we are hidden. - gfx::Size preferred_size = GetPreferredSize(); if (!IsVisible()) { - pending_preferred_width_ = pref_width; - } else if (pref_width > 0 && pref_width != preferred_size.width()) { - if (preferred_size.height() == 0) - preferred_size.set_height(height()); - SetPreferredSize(gfx::Size(pref_width, preferred_size.height())); + pending_preferred_size_ = new_size; + return; } + + gfx::Size preferred_size = GetPreferredSize(); + if (new_size != preferred_size) + SetPreferredSize(new_size); } void ExtensionView::ViewHierarchyChanged(bool is_add, @@ -168,3 +171,9 @@ void ExtensionView::RenderViewCreated() { pending_background_.reset(); } } + +void ExtensionView::SetPreferredSize(const gfx::Size& size) { + views::NativeViewHost::SetPreferredSize(size); + if (container_) + container_->OnExtensionPreferredSizeChanged(this); +} diff --git a/chrome/browser/views/extensions/extension_view.h b/chrome/browser/views/extensions/extension_view.h index 39b5851..8227771 100644 --- a/chrome/browser/views/extensions/extension_view.h +++ b/chrome/browser/views/extensions/extension_view.h @@ -17,21 +17,22 @@ class ExtensionHost; class ExtensionView; class RenderViewHost; -// A class that represents the container that this view is in. -// (bottom shelf, side bar, etc.) -class ExtensionContainer { - public: - // Mouse event notifications from the view. (useful for hover UI). - virtual void OnExtensionMouseEvent(ExtensionView* view) = 0; - virtual void OnExtensionMouseLeave(ExtensionView* view) = 0; -}; - // This handles the display portion of an ExtensionHost. class ExtensionView : public views::NativeViewHost { public: ExtensionView(ExtensionHost* host, Browser* browser); ~ExtensionView(); + // A class that represents the container that this view is in. + // (bottom shelf, side bar, etc.) + class Container { + public: + // Mouse event notifications from the view. (useful for hover UI). + virtual void OnExtensionMouseEvent(ExtensionView* view) = 0; + virtual void OnExtensionMouseLeave(ExtensionView* view) = 0; + virtual void OnExtensionPreferredSizeChanged(ExtensionView* view) {} + }; + ExtensionHost* host() const { return host_; } Browser* browser() const { return browser_; } Extension* extension() const; @@ -40,7 +41,7 @@ class ExtensionView : public views::NativeViewHost { void SetIsClipped(bool is_clipped); // Notification from ExtensionHost. - void UpdatePreferredWidth(int pref_width); + void UpdatePreferredSize(const gfx::Size& new_size); void HandleMouseEvent(); void HandleMouseLeave(); @@ -52,7 +53,7 @@ class ExtensionView : public views::NativeViewHost { void SetBackground(const SkBitmap& background); // Sets the container for this view. - void SetContainer(ExtensionContainer* container) { container_ = container; } + void SetContainer(Container* container) { container_ = container; } // Overridden from views::NativeViewHost: virtual void SetVisible(bool is_visible); @@ -60,6 +61,7 @@ class ExtensionView : public views::NativeViewHost { const gfx::Rect& current); virtual void ViewHierarchyChanged(bool is_add, views::View *parent, views::View *child); + virtual void SetPreferredSize(const gfx::Size& size); private: friend class ExtensionHost; @@ -90,11 +92,11 @@ class ExtensionView : public views::NativeViewHost { // What we should set the preferred width to once the ExtensionView has // loaded. - int pending_preferred_width_; + gfx::Size pending_preferred_size_; // The container this view is in (not necessarily its direct superview). // Note: the view does not own its container. - ExtensionContainer* container_; + Container* container_; // Whether this extension view is clipped. bool is_clipped_; diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc index 1d34c97d..664b44a 100644 --- a/chrome/common/extensions/extension.cc +++ b/chrome/common/extensions/extension.cc @@ -367,14 +367,6 @@ ExtensionAction* Extension::LoadExtensionActionHelper( return NULL; } result->set_popup_url(url); - - int height; - if (!popup->GetInteger(keys::kPageActionPopupHeight, &height)) { - *error = ExtensionErrorUtils::FormatErrorMessage( - errors::kInvalidPageActionPopupHeight, "<missing>"); - return NULL; - } - result->set_popup_height(height); } else if (!url_str.empty()) { GURL url = GetResourceURL(url_str); if (!url.is_valid()) { @@ -383,9 +375,6 @@ ExtensionAction* Extension::LoadExtensionActionHelper( return NULL; } result->set_popup_url(url); - // TODO(erikkay): Need dynamic sizing of popups. - // http://code.google.com/p/chromium/issues/detail?id=24471 - result->set_popup_height(100); } return result.release(); diff --git a/chrome/common/extensions/extension_action.h b/chrome/common/extensions/extension_action.h index 2e34bbb..31fe0e7 100644 --- a/chrome/common/extensions/extension_action.h +++ b/chrome/common/extensions/extension_action.h @@ -52,9 +52,6 @@ class ExtensionAction { const GURL& popup_url() const { return popup_url_; } void set_popup_url(const GURL& url) { popup_url_ = url; } - const int popup_height() const { return popup_height_; } - void set_popup_height(int height) { popup_height_ = height; } - bool is_popup() const { return !popup_url_.is_empty(); } private: @@ -77,7 +74,6 @@ class ExtensionAction { // If the action has a popup, it has a URL and a height. GURL popup_url_; - int popup_height_; }; typedef std::map<std::string, ExtensionAction*> ExtensionActionMap; diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 7408ab8..ebff2dc 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -694,9 +694,8 @@ IPC_BEGIN_MESSAGES(View) // the widget position while these asynchronous operations are in progress. IPC_MESSAGE_ROUTED0(ViewMsg_Move_ACK) - // Used to instruct the RenderView to send back updates to the intrinsic - // width. - IPC_MESSAGE_ROUTED0(ViewMsg_EnableIntrinsicWidthChangedMode) + // Used to instruct the RenderView to send back updates to the preferred size. + IPC_MESSAGE_ROUTED0(ViewMsg_EnablePreferredSizeChangedMode) // Used to inform the renderer that the browser has displayed its // requested notification. @@ -1135,8 +1134,9 @@ IPC_BEGIN_MESSAGES(ViewHost) GURL /* referrer */, WindowOpenDisposition /* disposition */) - IPC_MESSAGE_ROUTED1(ViewHostMsg_DidContentsPreferredWidthChange, - int /* pref_width */) + // Notify that the preferred size of the content changed. + IPC_MESSAGE_ROUTED1(ViewHostMsg_DidContentsPreferredSizeChange, + gfx::Size /* pref_size */) // Following message is used to communicate the values received by the // callback binding the JS to Cpp. diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index dce72c2..d2130c6 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -227,8 +227,7 @@ RenderView::RenderView(RenderThreadBase* render_thread, popup_notification_visible_(false), spelling_panel_visible_(false), delay_seconds_for_form_state_sync_(kDefaultDelaySecondsForFormStateSync), - preferred_width_(0), - send_preferred_width_changes_(false), + send_preferred_size_changes_(false), ALLOW_THIS_IN_INITIALIZER_LIST( notification_provider_(new NotificationProvider(this))), determine_page_text_after_loading_stops_(false), @@ -475,8 +474,8 @@ void RenderView::OnMessageReceived(const IPC::Message& message) { OnExtensionMessageInvoke) IPC_MESSAGE_HANDLER(ViewMsg_ClearFocusedNode, OnClearFocusedNode) IPC_MESSAGE_HANDLER(ViewMsg_SetBackground, OnSetBackground) - IPC_MESSAGE_HANDLER(ViewMsg_EnableIntrinsicWidthChangedMode, - OnEnableIntrinsicWidthChangedMode) + IPC_MESSAGE_HANDLER(ViewMsg_EnablePreferredSizeChangedMode, + OnEnablePreferredSizeChangedMode) IPC_MESSAGE_HANDLER(ViewMsg_SetRendererPrefs, OnSetRendererPrefs) IPC_MESSAGE_HANDLER(ViewMsg_UpdateBrowserWindowId, OnUpdateBrowserWindowId) @@ -2366,16 +2365,23 @@ void RenderView::didCreateIsolatedScriptContext(WebFrame* frame) { void RenderView::didChangeContentsSize(WebFrame* frame, const WebSize& size) { // We don't always want to send the change messages over IPC, only if we've - // be put in that mode by getting a |ViewMsg_EnableIntrinsicWidthChangedMode| + // be put in that mode by getting a |ViewMsg_EnablePreferredSizeChangedMode| // message. - if (send_preferred_width_changes_) { + if (send_preferred_size_changes_) { // WebCore likes to tell us things have changed even when they haven't, so - // cache the width and only send the IPC message when we're sure the - // width is different. + // cache the width and height and only send the IPC message when we're sure + // they're different. int width = webview()->mainFrame()->contentsPreferredWidth(); - if (width != preferred_width_) { - Send(new ViewHostMsg_DidContentsPreferredWidthChange(routing_id_, width)); - preferred_width_ = width; + if (width != preferred_size_.width() || + size.height != preferred_size_.height()) { + preferred_size_.set_width(width); + + // TODO(erikkay) the contents size is not really the same as the + // preferred size. It's just the current size. This means that for + // height, it will only ever grow, it will never shrink. + preferred_size_.set_height(size.height); + Send(new ViewHostMsg_DidContentsPreferredSizeChange(routing_id_, + preferred_size_)); } } } @@ -3027,8 +3033,8 @@ void RenderView::OnEnableViewSourceMode() { main_frame->enableViewSourceMode(true); } -void RenderView::OnEnableIntrinsicWidthChangedMode() { - send_preferred_width_changes_ = true; +void RenderView::OnEnablePreferredSizeChangedMode() { + send_preferred_size_changes_ = true; } void RenderView::OnSetRendererPrefs(const RendererPreferences& renderer_prefs) { diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index d0808e9..ca7d38e 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -601,7 +601,7 @@ class RenderView : public RenderWidget, void OnInstallMissingPlugin(); void OnFileChooserResponse(const std::vector<FilePath>& file_names); void OnEnableViewSourceMode(); - void OnEnableIntrinsicWidthChangedMode(); + void OnEnablePreferredSizeChangedMode(); void OnSetRendererPrefs(const RendererPreferences& renderer_prefs); void OnMediaPlayerActionAt(const gfx::Point& location, const WebKit::WebMediaPlayerAction& action); @@ -901,12 +901,12 @@ class RenderView : public RenderWidget, // it's for the selection clipboard. std::string selection_text_; - // Cache the preferred width of the page in order to prevent sending the IPC - // when layout() recomputes it but it doesn't actually change. - int preferred_width_; + // Cache the preferred size of the page in order to prevent sending the IPC + // when layout() recomputes but doesn't actually change sizes. + gfx::Size preferred_size_; - // If true, we send IPC messages when the preferred width changes. - bool send_preferred_width_changes_; + // If true, we send IPC messages when |preferred_size_| changes. + bool send_preferred_size_changes_; // The text selection the last time DidChangeSelection got called. std::string last_selection_; diff --git a/chrome/test/data/extensions/api_test/popup/chromium.png b/chrome/test/data/extensions/api_test/popup/chromium.png Binary files differnew file mode 100755 index 0000000..cc9fb60 --- /dev/null +++ b/chrome/test/data/extensions/api_test/popup/chromium.png diff --git a/chrome/test/data/extensions/api_test/popup/manifest.json b/chrome/test/data/extensions/api_test/popup/manifest.json new file mode 100755 index 0000000..f353316 --- /dev/null +++ b/chrome/test/data/extensions/api_test/popup/manifest.json @@ -0,0 +1,10 @@ +{
+ "name": "Popup tester",
+ "version": "0.1",
+ "description": "apitest for popups",
+ "browser_action": {
+ "name": "grow",
+ "icons": ["chromium.png"],
+ "popup": "popup.html"
+ }
+}
diff --git a/chrome/test/data/extensions/api_test/popup/popup.html b/chrome/test/data/extensions/api_test/popup/popup.html new file mode 100755 index 0000000..02d6342 --- /dev/null +++ b/chrome/test/data/extensions/api_test/popup/popup.html @@ -0,0 +1,44 @@ +<head>
+<script>
+function run_tests() {
+ // Compute the size of the popup.
+ var width = 100;
+ var height = 100;
+ if (localStorage.height) {
+ height = parseInt(localStorage.height);
+ }
+ if (localStorage.width) {
+ width = parseInt(localStorage.width);
+ }
+
+ // Set the div's size.
+ var test = document.getElementById("test");
+ test.style.width = width + "px";
+ test.style.height = height + "px";
+ chrome.test.log("height: " + test.offsetHeight);
+ chrome.test.log("width: " + test.offsetWidth);
+
+ // We should be done. Let the test harness know.
+ //window.setTimeout(chrome.test.notifyPass, 0);
+ chrome.test.notifyPass();
+
+ height += 100;
+ width += 100;
+ localStorage.height = JSON.stringify(height);
+ localStorage.width = JSON.stringify(width);
+}
+</script>
+<style>
+body {
+ padding: 0px;
+ margin: 0px;
+}
+div {
+ padding: 0px;
+ margin: 0px;
+}
+</style>
+</head>
+<body onload="window.setTimeout(run_tests, 0)">
+<div id="test">TEST</div>
+</body>
diff --git a/chrome/test/data/extensions/samples/buildbot/manifest.json b/chrome/test/data/extensions/samples/buildbot/manifest.json index ea764ef..39f6680 100644 --- a/chrome/test/data/extensions/samples/buildbot/manifest.json +++ b/chrome/test/data/extensions/samples/buildbot/manifest.json @@ -12,6 +12,6 @@ "browser_action": { "name": "Buildbot status", "icons": ["chromium.png"], - "popup": { "path": "popup.html", "height": 200 } + "popup": "popup.html" } } diff --git a/chrome/test/data/extensions/samples/buildbot/popup.html b/chrome/test/data/extensions/samples/buildbot/popup.html index 415c061..ca2314a 100755 --- a/chrome/test/data/extensions/samples/buildbot/popup.html +++ b/chrome/test/data/extensions/samples/buildbot/popup.html @@ -1,3 +1,4 @@ +<head>
<script>
var botRoot = "http://build.chromium.org/buildbot/waterfall";
//var botRoot = "http://chrome-buildbot.corp.google.com:8010";
@@ -82,24 +83,42 @@ function requestURL(url, callback) { }
window.onload = function() {
bots = document.getElementById("bots");
- bots.innerHTML = "onload";
- //window.setTimeout(requestUrl(waterfallURL, updateBotList), 10);
- requestURL(waterfallURL, updateBotList);
+
+ // XHR from onload winds up blocking the load, so we put it in a setTimeout.
+ window.setTimeout(requestURL, 0, waterfallURL, updateBotList);
}
+
+function toggle_size() {
+ if (document.body.className == "big") {
+ document.body.className = "small";
+ } else {
+ document.body.className = "big";
+ }
+}
+
</script>
<style>
body {
font: menu;
- width: 200px;
- background-color: #dddddd;
overflow: hidden;
}
+body.big .bot {
+ -webkit-transition: all .5s ease-out;
+ padding-right: 100px;
+}
+
+body.small .bot{
+ -webkit-transition: all .5s ease-out;
+ padding-right: 3px;
+}
+
.bot {
cursor: pointer;
-webkit-border-radius: 5px;
margin-top: 1px;
padding: 3px;
+ white-space: nowrap;
}
.bot:hover {
@@ -144,4 +163,7 @@ body { border: 1px solid rgb(172, 160, 179);
}
</style>
+</head>
+<body onClick="toggle_size()">
<div id="bots">Loading....</div>
+</body>
\ No newline at end of file |