1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/views/frame/browser_view_layout.h"
7 #include "chrome/browser/ui/views/frame/browser_view.h"
8 #include "chrome/browser/ui/views/frame/browser_view_layout_delegate.h"
9 #include "chrome/browser/ui/views/frame/contents_container.h"
10 #include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
11 #include "chrome/browser/ui/views/infobars/infobar_container_view.h"
12 #include "chrome/browser/ui/views/tabs/tab_strip.h"
13 #include "chrome/test/base/browser_with_test_window_test.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 class MockBrowserViewLayoutDelegate : public BrowserViewLayoutDelegate {
18 MockBrowserViewLayoutDelegate()
19 : tab_strip_visible_(true),
20 toolbar_visible_(true),
21 bookmark_bar_visible_(true),
22 download_shelf_needs_layout_(false) {
24 virtual ~MockBrowserViewLayoutDelegate() {}
26 void set_download_shelf_needs_layout(bool layout) {
27 download_shelf_needs_layout_ = layout;
29 void set_tab_strip_visible(bool visible) {
30 tab_strip_visible_ = visible;
32 void set_toolbar_visible(bool visible) {
33 toolbar_visible_ = visible;
35 void set_bookmark_bar_visible(bool visible) {
36 bookmark_bar_visible_ = visible;
39 // BrowserViewLayout::Delegate overrides:
40 virtual views::View* GetWindowSwitcherButton() const OVERRIDE {
41 // TODO(jamescook): Add a test for Windows that exercises the layout for
45 virtual bool IsTabStripVisible() const OVERRIDE {
46 return tab_strip_visible_;
48 virtual gfx::Rect GetBoundsForTabStrip(views::View* tab_strip) const
52 virtual bool IsToolbarVisible() const OVERRIDE {
53 return toolbar_visible_;
55 virtual bool IsBookmarkBarVisible() const OVERRIDE {
56 return bookmark_bar_visible_;
58 virtual bool DownloadShelfNeedsLayout() const OVERRIDE {
59 return download_shelf_needs_layout_;
62 virtual FullscreenExitBubbleViews* GetFullscreenExitBubble() const OVERRIDE {
67 bool tab_strip_visible_;
68 bool toolbar_visible_;
69 bool bookmark_bar_visible_;
70 bool download_shelf_needs_layout_;
72 DISALLOW_COPY_AND_ASSIGN(MockBrowserViewLayoutDelegate);
75 ///////////////////////////////////////////////////////////////////////////////
77 // A simple view that prefers an initial size.
78 class MockView : public views::View {
80 explicit MockView(gfx::Size initial_size)
81 : size_(initial_size) {
82 SetBoundsRect(gfx::Rect(gfx::Point(), size_));
84 virtual ~MockView() {}
86 // views::View overrides:
87 virtual gfx::Size GetPreferredSize() OVERRIDE {
94 DISALLOW_COPY_AND_ASSIGN(MockView);
97 ///////////////////////////////////////////////////////////////////////////////
99 class MockImmersiveModeController : public ImmersiveModeController {
101 MockImmersiveModeController() {}
102 virtual ~MockImmersiveModeController() {}
104 // ImmersiveModeController overrides:
105 virtual void Init(Delegate* delegate,
106 views::Widget* widget,
107 views::View* top_container) OVERRIDE {}
108 virtual void SetEnabled(bool enabled) OVERRIDE {}
109 virtual bool IsEnabled() const OVERRIDE { return false; }
110 virtual bool ShouldHideTabIndicators() const OVERRIDE { return false; }
111 virtual bool ShouldHideTopViews() const OVERRIDE { return false; }
112 virtual bool IsRevealed() const OVERRIDE { return false; }
113 virtual int GetTopContainerVerticalOffset(
114 const gfx::Size& top_container_size) const OVERRIDE { return 0; }
115 virtual ImmersiveRevealedLock* GetRevealedLock(
116 AnimateReveal animate_reveal) OVERRIDE WARN_UNUSED_RESULT { return NULL; }
117 virtual void OnFindBarVisibleBoundsChanged(
118 const gfx::Rect& new_visible_bounds) OVERRIDE {}
119 virtual void SetupForTest() OVERRIDE {}
122 DISALLOW_COPY_AND_ASSIGN(MockImmersiveModeController);
125 ///////////////////////////////////////////////////////////////////////////////
126 // Tests of BrowserViewLayout. Runs tests without constructing a BrowserView.
127 class BrowserViewLayoutTest : public BrowserWithTestWindowTest {
129 BrowserViewLayoutTest()
131 top_container_(NULL),
134 infobar_container_(NULL),
135 contents_split_(NULL),
136 contents_container_(NULL),
137 active_web_view_(NULL) {}
138 virtual ~BrowserViewLayoutTest() {}
140 BrowserViewLayout* layout() { return layout_.get(); }
141 MockBrowserViewLayoutDelegate* delegate() { return delegate_; }
142 MockView* root_view() { return root_view_.get(); }
143 MockView* top_container() { return top_container_; }
144 TabStrip* tab_strip() { return tab_strip_; }
145 MockView* toolbar() { return toolbar_; }
146 InfoBarContainerView* infobar_container() { return infobar_container_; }
147 MockView* contents_split() { return contents_split_; }
148 ContentsContainer* contents_container() { return contents_container_; }
150 // BrowserWithTestWindowTest overrides:
151 virtual void SetUp() OVERRIDE {
152 BrowserWithTestWindowTest::SetUp();
154 root_view_.reset(new MockView(gfx::Size(800, 600)));
156 immersive_mode_controller_.reset(new MockImmersiveModeController);
158 top_container_ = new MockView(gfx::Size(800, 60));
159 tab_strip_ = new TabStrip(NULL);
160 top_container_->AddChildView(tab_strip_);
161 toolbar_ = new MockView(gfx::Size(800, 30));
162 top_container_->AddChildView(toolbar_);
163 root_view_->AddChildView(top_container_);
165 infobar_container_ = new InfoBarContainerView(NULL);
166 root_view_->AddChildView(infobar_container_);
168 contents_split_ = new MockView(gfx::Size(800, 600));
169 active_web_view_ = new MockView(gfx::Size(800, 600));
170 contents_container_ = new ContentsContainer(active_web_view_);
171 contents_split_->AddChildView(contents_container_);
172 root_view_->AddChildView(contents_split_);
174 // TODO(jamescook): Attach |layout_| to |root_view_|?
175 layout_.reset(new BrowserViewLayout);
176 delegate_ = new MockBrowserViewLayoutDelegate;
177 layout_->Init(delegate_,
179 NULL, // BrowserView.
186 immersive_mode_controller_.get());
190 scoped_ptr<BrowserViewLayout> layout_;
191 MockBrowserViewLayoutDelegate* delegate_; // Owned by |layout_|.
192 scoped_ptr<MockView> root_view_;
194 // Views owned by |root_view_|.
195 MockView* top_container_;
196 TabStrip* tab_strip_;
198 InfoBarContainerView* infobar_container_;
199 MockView* contents_split_;
200 ContentsContainer* contents_container_;
201 MockView* active_web_view_;
203 scoped_ptr<MockImmersiveModeController> immersive_mode_controller_;
205 DISALLOW_COPY_AND_ASSIGN(BrowserViewLayoutTest);
208 // Test basic construction and initialization.
209 TEST_F(BrowserViewLayoutTest, BrowserViewLayout) {
210 EXPECT_TRUE(layout()->browser());
211 EXPECT_TRUE(layout()->GetWebContentsModalDialogHost());
212 EXPECT_FALSE(layout()->InfobarVisible());
215 // Test the core layout functions.
216 TEST_F(BrowserViewLayoutTest, Layout) {
217 // Simulate a window with no interesting UI.
218 delegate()->set_tab_strip_visible(false);
219 delegate()->set_toolbar_visible(false);
220 delegate()->set_bookmark_bar_visible(false);
221 layout()->Layout(root_view());
223 // Top views are zero-height.
224 EXPECT_EQ("0,0 0x0", tab_strip()->bounds().ToString());
225 EXPECT_EQ("0,0 800x0", toolbar()->bounds().ToString());
226 EXPECT_EQ("0,0 800x0", infobar_container()->bounds().ToString());
227 // Contents split fills the window.
228 EXPECT_EQ("0,0 800x600", contents_split()->bounds().ToString());
230 // Turn on the toolbar, like in a pop-up window.
231 delegate()->set_toolbar_visible(true);
232 layout()->Layout(root_view());
234 // Now the toolbar has bounds and other views shift down.
235 EXPECT_EQ("0,0 0x0", tab_strip()->bounds().ToString());
236 EXPECT_EQ("0,0 800x30", toolbar()->bounds().ToString());
237 EXPECT_EQ("0,30 800x0", infobar_container()->bounds().ToString());
238 EXPECT_EQ("0,30 800x570", contents_split()->bounds().ToString());
240 // TODO(jamescook): Tab strip and bookmark bar.
243 TEST_F(BrowserViewLayoutTest, LayoutDownloadShelf) {
244 scoped_ptr<MockView> download_shelf(new MockView(gfx::Size(800, 50)));
245 layout()->set_download_shelf(download_shelf.get());
247 // If download shelf doesn't need layout, it doesn't move the bottom edge.
248 delegate()->set_download_shelf_needs_layout(false);
249 const int kBottom = 500;
250 EXPECT_EQ(kBottom, layout()->LayoutDownloadShelf(kBottom));
252 // Download shelf layout moves up the bottom edge and sets visibility.
253 delegate()->set_download_shelf_needs_layout(true);
254 download_shelf->SetVisible(false);
255 EXPECT_EQ(450, layout()->LayoutDownloadShelf(kBottom));
256 EXPECT_TRUE(download_shelf->visible());
257 EXPECT_EQ("0,450 0x50", download_shelf->bounds().ToString());