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.
4
5#include "chrome/browser/ui/views/frame/browser_view.h"
6
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 "ui/views/controls/single_split_view.h"
18#include "ui/views/controls/webview/webview.h"
19
20namespace {
21
22// Tab strip bounds depend on the window frame sizes.
23gfx::Point ExpectedTabStripOrigin(BrowserView* browser_view) {
24  gfx::Rect tabstrip_bounds(
25      browser_view->frame()->GetBoundsForTabStrip(browser_view->tabstrip()));
26  gfx::Point tabstrip_origin(tabstrip_bounds.origin());
27  views::View::ConvertPointToTarget(browser_view->parent(),
28                                    browser_view,
29                                    &tabstrip_origin);
30  return tabstrip_origin;
31}
32
33}  // namespace
34
35typedef TestWithBrowserView BrowserViewTest;
36
37// Test basic construction and initialization.
38TEST_F(BrowserViewTest, BrowserView) {
39  // The window is owned by the native widget, not the test class.
40  EXPECT_FALSE(window());
41
42  EXPECT_TRUE(browser_view()->browser());
43
44  // Test initial state.
45  EXPECT_TRUE(browser_view()->IsTabStripVisible());
46  EXPECT_FALSE(browser_view()->IsOffTheRecord());
47  EXPECT_FALSE(browser_view()->IsGuestSession());
48  EXPECT_FALSE(browser_view()->ShouldShowAvatar());
49  EXPECT_TRUE(browser_view()->IsBrowserTypeNormal());
50  EXPECT_FALSE(browser_view()->IsFullscreen());
51  EXPECT_FALSE(browser_view()->IsBookmarkBarVisible());
52  EXPECT_FALSE(browser_view()->IsBookmarkBarAnimating());
53}
54
55// Test layout of the top-of-window UI.
56TEST_F(BrowserViewTest, BrowserViewLayout) {
57  BookmarkBarView::DisableAnimationsForTesting(true);
58
59  // |browser_view_| owns the Browser, not the test class.
60  Browser* browser = browser_view()->browser();
61  TopContainerView* top_container = browser_view()->top_container();
62  TabStrip* tabstrip = browser_view()->tabstrip();
63  ToolbarView* toolbar = browser_view()->toolbar();
64  views::View* contents_container =
65      browser_view()->GetContentsContainerForTest();
66  views::WebView* contents_web_view =
67      browser_view()->GetContentsWebViewForTest();
68  views::WebView* devtools_web_view =
69      browser_view()->GetDevToolsWebViewForTest();
70
71  // Start with a single tab open to a normal page.
72  AddTab(browser, GURL("about:blank"));
73
74  // Verify the view hierarchy.
75  EXPECT_EQ(top_container, browser_view()->tabstrip()->parent());
76  EXPECT_EQ(top_container, browser_view()->toolbar()->parent());
77  EXPECT_EQ(top_container, browser_view()->GetBookmarkBarView()->parent());
78  EXPECT_EQ(browser_view(), browser_view()->infobar_container()->parent());
79
80  // Find bar host is at the front of the view hierarchy, followed by the top
81  // container.
82  EXPECT_EQ(browser_view()->child_count() - 1,
83            browser_view()->GetIndexOf(browser_view()->find_bar_host_view()));
84  EXPECT_EQ(browser_view()->child_count() - 2,
85            browser_view()->GetIndexOf(top_container));
86
87  // Verify basic layout.
88  EXPECT_EQ(0, top_container->x());
89  EXPECT_EQ(0, top_container->y());
90  EXPECT_EQ(browser_view()->width(), top_container->width());
91  // Tabstrip layout varies based on window frame sizes.
92  gfx::Point expected_tabstrip_origin = ExpectedTabStripOrigin(browser_view());
93  EXPECT_EQ(expected_tabstrip_origin.x(), tabstrip->x());
94  EXPECT_EQ(expected_tabstrip_origin.y(), tabstrip->y());
95  EXPECT_EQ(0, toolbar->x());
96  EXPECT_EQ(
97      tabstrip->bounds().bottom() -
98          BrowserViewLayout::kToolbarTabStripVerticalOverlap,
99      toolbar->y());
100  EXPECT_EQ(0, contents_container->x());
101  EXPECT_EQ(toolbar->bounds().bottom(), contents_container->y());
102  EXPECT_EQ(top_container->bounds().bottom(), contents_container->y());
103  EXPECT_EQ(0, devtools_web_view->x());
104  EXPECT_EQ(0, devtools_web_view->y());
105  EXPECT_EQ(0, contents_web_view->x());
106  EXPECT_EQ(0, contents_web_view->y());
107
108  // Verify bookmark bar visibility.
109  BookmarkBarView* bookmark_bar = browser_view()->GetBookmarkBarView();
110  EXPECT_FALSE(bookmark_bar->visible());
111  EXPECT_FALSE(bookmark_bar->IsDetached());
112  chrome::ExecuteCommand(browser, IDC_SHOW_BOOKMARK_BAR);
113  EXPECT_TRUE(bookmark_bar->visible());
114  EXPECT_FALSE(bookmark_bar->IsDetached());
115  chrome::ExecuteCommand(browser, IDC_SHOW_BOOKMARK_BAR);
116  EXPECT_FALSE(bookmark_bar->visible());
117  EXPECT_FALSE(bookmark_bar->IsDetached());
118
119  // Bookmark bar is reparented to BrowserView on NTP.
120  NavigateAndCommitActiveTabWithTitle(browser,
121                                      GURL(chrome::kChromeUINewTabURL),
122                                      base::string16());
123  EXPECT_TRUE(bookmark_bar->visible());
124  EXPECT_TRUE(bookmark_bar->IsDetached());
125  EXPECT_EQ(browser_view(), bookmark_bar->parent());
126  // Find bar host is still at the front of the view hierarchy, followed by
127  // the top container.
128  EXPECT_EQ(browser_view()->child_count() - 1,
129            browser_view()->GetIndexOf(browser_view()->find_bar_host_view()));
130  EXPECT_EQ(browser_view()->child_count() - 2,
131            browser_view()->GetIndexOf(top_container));
132
133  // Bookmark bar layout on NTP.
134  EXPECT_EQ(0, bookmark_bar->x());
135  EXPECT_EQ(
136      tabstrip->bounds().bottom() +
137          toolbar->height() -
138          BrowserViewLayout::kToolbarTabStripVerticalOverlap -
139          views::NonClientFrameView::kClientEdgeThickness,
140      bookmark_bar->y());
141  EXPECT_EQ(toolbar->bounds().bottom(), contents_container->y());
142  // Contents view has a "top margin" pushing it below the bookmark bar.
143  EXPECT_EQ(bookmark_bar->height() -
144                views::NonClientFrameView::kClientEdgeThickness,
145            devtools_web_view->y());
146  EXPECT_EQ(bookmark_bar->height() -
147                views::NonClientFrameView::kClientEdgeThickness,
148            contents_web_view->y());
149
150  // Bookmark bar is parented back to top container on normal page.
151  NavigateAndCommitActiveTabWithTitle(browser,
152                                      GURL("about:blank"),
153                                      base::string16());
154  EXPECT_FALSE(bookmark_bar->visible());
155  EXPECT_FALSE(bookmark_bar->IsDetached());
156  EXPECT_EQ(top_container, bookmark_bar->parent());
157  // Top container is still second from front.
158  EXPECT_EQ(browser_view()->child_count() - 2,
159            browser_view()->GetIndexOf(top_container));
160
161  BookmarkBarView::DisableAnimationsForTesting(false);
162}
163
164class BrowserViewHostedAppTest : public TestWithBrowserView {
165 public:
166  BrowserViewHostedAppTest()
167      : TestWithBrowserView(Browser::TYPE_POPUP,
168                            chrome::HOST_DESKTOP_TYPE_NATIVE,
169                            true) {
170  }
171  virtual ~BrowserViewHostedAppTest() {
172  }
173
174 private:
175  DISALLOW_COPY_AND_ASSIGN(BrowserViewHostedAppTest);
176};
177
178// Test basic layout for hosted apps.
179TEST_F(BrowserViewHostedAppTest, Layout) {
180  // Add a tab because the browser starts out without any tabs at all.
181  AddTab(browser(), GURL("about:blank"));
182
183  views::View* contents_container =
184      browser_view()->GetContentsContainerForTest();
185
186  // The tabstrip, toolbar and bookmark bar should not be visible for hosted
187  // apps.
188  EXPECT_FALSE(browser_view()->tabstrip()->visible());
189  EXPECT_FALSE(browser_view()->toolbar()->visible());
190  EXPECT_FALSE(browser_view()->IsBookmarkBarVisible());
191
192  gfx::Point header_offset;
193  views::View::ConvertPointToTarget(
194      browser_view(),
195      browser_view()->frame()->non_client_view()->frame_view(),
196      &header_offset);
197
198  // The position of the bottom of the header (the bar with the window
199  // controls) in the coordinates of BrowserView.
200  int bottom_of_header = browser_view()->frame()->GetTopInset() -
201      header_offset.y();
202
203  // The web contents should be flush with the bottom of the header.
204  EXPECT_EQ(bottom_of_header, contents_container->y());
205
206  // The find bar should overlap the 1px header/web-contents separator at the
207  // bottom of the header.
208  EXPECT_EQ(browser_view()->frame()->GetTopInset() - 1,
209            browser_view()->GetFindBarBoundingBox().y());
210}
211