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.h"
7 #include "chrome/app/chrome_command_ids.h"
8 #include "chrome/browser/ui/browser_commands.h"
9 #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
10 #include "chrome/browser/ui/views/frame/browser_view_layout.h"
11 #include "chrome/browser/ui/views/frame/test_with_browser_view.h"
12 #include "chrome/browser/ui/views/frame/top_container_view.h"
13 #include "chrome/browser/ui/views/infobars/infobar_container_view.h"
14 #include "chrome/browser/ui/views/tabs/tab_strip.h"
15 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
16 #include "chrome/common/url_constants.h"
17 #include "grit/generated_resources.h"
18 #include "grit/theme_resources.h"
19 #include "ui/base/resource/resource_bundle.h"
20 #include "ui/views/controls/single_split_view.h"
21 #include "ui/views/controls/webview/webview.h"
25 // Tab strip bounds depend on the window frame sizes.
26 gfx::Point ExpectedTabStripOrigin(BrowserView* browser_view) {
27 gfx::Rect tabstrip_bounds(
28 browser_view->frame()->GetBoundsForTabStrip(browser_view->tabstrip()));
29 gfx::Point tabstrip_origin(tabstrip_bounds.origin());
30 views::View::ConvertPointToTarget(browser_view->parent(),
33 return tabstrip_origin;
38 typedef TestWithBrowserView BrowserViewTest;
40 // Test basic construction and initialization.
41 TEST_F(BrowserViewTest, BrowserView) {
42 // The window is owned by the native widget, not the test class.
43 EXPECT_FALSE(window());
45 EXPECT_TRUE(browser_view()->browser());
47 // Test initial state.
48 EXPECT_TRUE(browser_view()->IsTabStripVisible());
49 EXPECT_FALSE(browser_view()->IsOffTheRecord());
50 EXPECT_EQ(IDR_OTR_ICON, browser_view()->GetOTRIconResourceID());
51 EXPECT_FALSE(browser_view()->IsGuestSession());
52 EXPECT_FALSE(browser_view()->ShouldShowAvatar());
53 EXPECT_TRUE(browser_view()->IsBrowserTypeNormal());
54 EXPECT_FALSE(browser_view()->IsFullscreen());
55 EXPECT_FALSE(browser_view()->IsBookmarkBarVisible());
56 EXPECT_FALSE(browser_view()->IsBookmarkBarAnimating());
59 // Test layout of the top-of-window UI.
60 TEST_F(BrowserViewTest, BrowserViewLayout) {
61 BookmarkBarView::DisableAnimationsForTesting(true);
63 // |browser_view_| owns the Browser, not the test class.
64 Browser* browser = browser_view()->browser();
65 TopContainerView* top_container = browser_view()->top_container();
66 TabStrip* tabstrip = browser_view()->tabstrip();
67 ToolbarView* toolbar = browser_view()->toolbar();
68 views::View* contents_container =
69 browser_view()->GetContentsContainerForTest();
70 views::WebView* contents_web_view =
71 browser_view()->GetContentsWebViewForTest();
72 views::WebView* devtools_web_view =
73 browser_view()->GetDevToolsWebViewForTest();
75 // Start with a single tab open to a normal page.
76 AddTab(browser, GURL("about:blank"));
78 // Verify the view hierarchy.
79 EXPECT_EQ(top_container, browser_view()->tabstrip()->parent());
80 EXPECT_EQ(top_container, browser_view()->toolbar()->parent());
81 EXPECT_EQ(top_container, browser_view()->GetBookmarkBarView()->parent());
82 EXPECT_EQ(browser_view(), browser_view()->infobar_container()->parent());
84 // Find bar host is at the front of the view hierarchy, followed by the top
86 EXPECT_EQ(browser_view()->child_count() - 1,
87 browser_view()->GetIndexOf(browser_view()->find_bar_host_view()));
88 EXPECT_EQ(browser_view()->child_count() - 2,
89 browser_view()->GetIndexOf(top_container));
91 // Verify basic layout.
92 EXPECT_EQ(0, top_container->x());
93 EXPECT_EQ(0, top_container->y());
94 EXPECT_EQ(browser_view()->width(), top_container->width());
95 // Tabstrip layout varies based on window frame sizes.
96 gfx::Point expected_tabstrip_origin = ExpectedTabStripOrigin(browser_view());
97 EXPECT_EQ(expected_tabstrip_origin.x(), tabstrip->x());
98 EXPECT_EQ(expected_tabstrip_origin.y(), tabstrip->y());
99 EXPECT_EQ(0, toolbar->x());
101 tabstrip->bounds().bottom() -
102 BrowserViewLayout::kToolbarTabStripVerticalOverlap,
104 EXPECT_EQ(0, contents_container->x());
105 EXPECT_EQ(toolbar->bounds().bottom(), contents_container->y());
106 EXPECT_EQ(0, devtools_web_view->x());
107 EXPECT_EQ(0, devtools_web_view->y());
108 EXPECT_EQ(0, contents_web_view->x());
109 EXPECT_EQ(0, contents_web_view->y());
111 // Verify bookmark bar visibility.
112 BookmarkBarView* bookmark_bar = browser_view()->GetBookmarkBarView();
113 EXPECT_FALSE(bookmark_bar->visible());
114 EXPECT_FALSE(bookmark_bar->IsDetached());
115 chrome::ExecuteCommand(browser, IDC_SHOW_BOOKMARK_BAR);
116 EXPECT_TRUE(bookmark_bar->visible());
117 EXPECT_FALSE(bookmark_bar->IsDetached());
118 chrome::ExecuteCommand(browser, IDC_SHOW_BOOKMARK_BAR);
119 EXPECT_FALSE(bookmark_bar->visible());
120 EXPECT_FALSE(bookmark_bar->IsDetached());
122 // Bookmark bar is reparented to BrowserView on NTP.
123 NavigateAndCommitActiveTabWithTitle(browser,
124 GURL(chrome::kChromeUINewTabURL),
126 EXPECT_TRUE(bookmark_bar->visible());
127 EXPECT_TRUE(bookmark_bar->IsDetached());
128 EXPECT_EQ(browser_view(), bookmark_bar->parent());
129 // Find bar host is still at the front of the view hierarchy, followed by
130 // the top container.
131 EXPECT_EQ(browser_view()->child_count() - 1,
132 browser_view()->GetIndexOf(browser_view()->find_bar_host_view()));
133 EXPECT_EQ(browser_view()->child_count() - 2,
134 browser_view()->GetIndexOf(top_container));
136 // Bookmark bar layout on NTP.
137 EXPECT_EQ(0, bookmark_bar->x());
139 tabstrip->bounds().bottom() +
141 BrowserViewLayout::kToolbarTabStripVerticalOverlap -
142 views::NonClientFrameView::kClientEdgeThickness,
144 EXPECT_EQ(toolbar->bounds().bottom(), contents_container->y());
145 // Contents view has a "top margin" pushing it below the bookmark bar.
146 EXPECT_EQ(bookmark_bar->height() -
147 views::NonClientFrameView::kClientEdgeThickness,
148 devtools_web_view->y());
149 EXPECT_EQ(bookmark_bar->height() -
150 views::NonClientFrameView::kClientEdgeThickness,
151 contents_web_view->y());
153 // Bookmark bar is parented back to top container on normal page.
154 NavigateAndCommitActiveTabWithTitle(browser,
157 EXPECT_FALSE(bookmark_bar->visible());
158 EXPECT_FALSE(bookmark_bar->IsDetached());
159 EXPECT_EQ(top_container, bookmark_bar->parent());
160 // Top container is still second from front.
161 EXPECT_EQ(browser_view()->child_count() - 2,
162 browser_view()->GetIndexOf(top_container));
164 BookmarkBarView::DisableAnimationsForTesting(false);
169 // This class provides functionality to test the incognito window/normal window
170 // switcher button which is added to Windows 8 metro Chrome.
171 // We create the BrowserView ourselves in the
172 // BrowserWithTestWindowTest::CreateBrowserWindow function override and add the
173 // switcher button to the view. We also provide an incognito profile to ensure
174 // that the switcher button is visible.
175 class BrowserViewIncognitoSwitcherTest : public TestWithBrowserView {
177 // Subclass of BrowserView, which overrides the GetRestoreBounds/IsMaximized
178 // functions to return dummy values. This is needed because we create the
179 // BrowserView instance ourselves and initialize it with the created Browser
180 // instance. These functions get called before the underlying Widget is
181 // initialized which causes a crash while dereferencing a null native_widget_
182 // pointer in the Widget class.
183 class TestBrowserView : public BrowserView {
185 virtual ~TestBrowserView() {}
187 virtual gfx::Rect GetRestoredBounds() const OVERRIDE {
190 virtual bool IsMaximized() const OVERRIDE {
195 BrowserViewIncognitoSwitcherTest()
196 : browser_view_(NULL) {}
198 virtual void SetUp() OVERRIDE {
199 TestWithBrowserView::SetUp();
200 browser_view_->Init(browser());
201 (new BrowserFrame(browser_view_))->InitBrowserFrame();
202 browser_view_->SetBounds(gfx::Rect(10, 10, 500, 500));
203 browser_view_->Show();
206 virtual void TearDown() OVERRIDE {
207 // ok to release the window_ pointer because BrowserViewTest::TearDown
208 // deletes the BrowserView instance created.
209 release_browser_window();
210 BrowserViewTest::TearDown();
211 browser_view_ = NULL;
214 virtual BrowserWindow* CreateBrowserWindow() OVERRIDE {
215 // We need an incognito profile for the window switcher button to be
217 // This profile instance is owned by the TestingProfile instance within the
218 // BrowserWithTestWindowTest class.
219 TestingProfile::Builder builder;
220 builder.SetIncognito();
221 GetProfile()->SetOffTheRecordProfile(builder.Build());
223 browser_view_ = new TestBrowserView();
225 views::ImageButton* switcher_button = new views::ImageButton(NULL);
226 // The button in the incognito window has the hot-cold images inverted
227 // with respect to the regular browser window.
228 switcher_button->SetImage(
229 views::ImageButton::STATE_NORMAL,
230 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
231 IDR_INCOGNITO_SWITCH_OFF));
232 switcher_button->SetImage(
233 views::ImageButton::STATE_HOVERED,
234 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
235 IDR_INCOGNITO_SWITCH_ON));
236 switcher_button->SetImageAlignment(views::ImageButton::ALIGN_CENTER,
237 views::ImageButton::ALIGN_MIDDLE);
239 browser_view_->SetWindowSwitcherButton(switcher_button);
240 return browser_view_;
244 BrowserView* browser_view_;
246 DISALLOW_COPY_AND_ASSIGN(BrowserViewIncognitoSwitcherTest);
249 // Test whether the windows incognito/normal browser window switcher button
250 // is the event handler for a point within its bounds. The event handler for
251 // a point in the View class is dependent on the order in which children are
252 // added to it. This test ensures that we don't regress in the window switcher
253 // functionality when additional children are added to the BrowserView class.
254 TEST_F(BrowserViewIncognitoSwitcherTest,
255 BrowserViewIncognitoSwitcherEventHandlerTest) {
256 // |browser_view_| owns the Browser, not the test class.
257 EXPECT_TRUE(browser_view()->browser());
258 // Test initial state.
259 EXPECT_TRUE(browser_view()->IsTabStripVisible());
260 // Validate whether the window switcher button is the target for the position
262 gfx::Point switcher_point(browser_view()->window_switcher_button()->x() + 2,
263 browser_view()->window_switcher_button()->y());
264 EXPECT_EQ(browser_view()->GetEventHandlerForPoint(switcher_point),
265 browser_view()->window_switcher_button());