browser_view_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 "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" 22 23namespace { 24 25// Tab strip bounds depend on the window frame sizes. 26gfx::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(), 31 browser_view, 32 &tabstrip_origin); 33 return tabstrip_origin; 34} 35 36} // namespace 37 38typedef TestWithBrowserView BrowserViewTest; 39 40// Test basic construction and initialization. 41TEST_F(BrowserViewTest, BrowserView) { 42 // The window is owned by the native widget, not the test class. 43 EXPECT_FALSE(window()); 44 45 EXPECT_TRUE(browser_view()->browser()); 46 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()); 57} 58 59// Test layout of the top-of-window UI. 60TEST_F(BrowserViewTest, BrowserViewLayout) { 61 BookmarkBarView::DisableAnimationsForTesting(true); 62 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(); 74 75 // Start with a single tab open to a normal page. 76 AddTab(browser, GURL("about:blank")); 77 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()); 83 84 // Find bar host is at the front of the view hierarchy, followed by the top 85 // container. 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)); 90 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()); 100 EXPECT_EQ( 101 tabstrip->bounds().bottom() - 102 BrowserViewLayout::kToolbarTabStripVerticalOverlap, 103 toolbar->y()); 104 EXPECT_EQ(0, contents_container->x()); 105 EXPECT_EQ(toolbar->bounds().bottom(), contents_container->y()); 106 EXPECT_EQ(top_container->bounds().bottom(), contents_container->y()); 107 EXPECT_EQ(0, devtools_web_view->x()); 108 EXPECT_EQ(0, devtools_web_view->y()); 109 EXPECT_EQ(0, contents_web_view->x()); 110 EXPECT_EQ(0, contents_web_view->y()); 111 112 // Verify bookmark bar visibility. 113 BookmarkBarView* bookmark_bar = browser_view()->GetBookmarkBarView(); 114 EXPECT_FALSE(bookmark_bar->visible()); 115 EXPECT_FALSE(bookmark_bar->IsDetached()); 116 chrome::ExecuteCommand(browser, IDC_SHOW_BOOKMARK_BAR); 117 EXPECT_TRUE(bookmark_bar->visible()); 118 EXPECT_FALSE(bookmark_bar->IsDetached()); 119 chrome::ExecuteCommand(browser, IDC_SHOW_BOOKMARK_BAR); 120 EXPECT_FALSE(bookmark_bar->visible()); 121 EXPECT_FALSE(bookmark_bar->IsDetached()); 122 123 // Bookmark bar is reparented to BrowserView on NTP. 124 NavigateAndCommitActiveTabWithTitle(browser, 125 GURL(chrome::kChromeUINewTabURL), 126 base::string16()); 127 EXPECT_TRUE(bookmark_bar->visible()); 128 EXPECT_TRUE(bookmark_bar->IsDetached()); 129 EXPECT_EQ(browser_view(), bookmark_bar->parent()); 130 // Find bar host is still at the front of the view hierarchy, followed by 131 // the top container. 132 EXPECT_EQ(browser_view()->child_count() - 1, 133 browser_view()->GetIndexOf(browser_view()->find_bar_host_view())); 134 EXPECT_EQ(browser_view()->child_count() - 2, 135 browser_view()->GetIndexOf(top_container)); 136 137 // Bookmark bar layout on NTP. 138 EXPECT_EQ(0, bookmark_bar->x()); 139 EXPECT_EQ( 140 tabstrip->bounds().bottom() + 141 toolbar->height() - 142 BrowserViewLayout::kToolbarTabStripVerticalOverlap - 143 views::NonClientFrameView::kClientEdgeThickness, 144 bookmark_bar->y()); 145 EXPECT_EQ(toolbar->bounds().bottom(), contents_container->y()); 146 // Contents view has a "top margin" pushing it below the bookmark bar. 147 EXPECT_EQ(bookmark_bar->height() - 148 views::NonClientFrameView::kClientEdgeThickness, 149 devtools_web_view->y()); 150 EXPECT_EQ(bookmark_bar->height() - 151 views::NonClientFrameView::kClientEdgeThickness, 152 contents_web_view->y()); 153 154 // Bookmark bar is parented back to top container on normal page. 155 NavigateAndCommitActiveTabWithTitle(browser, 156 GURL("about:blank"), 157 base::string16()); 158 EXPECT_FALSE(bookmark_bar->visible()); 159 EXPECT_FALSE(bookmark_bar->IsDetached()); 160 EXPECT_EQ(top_container, bookmark_bar->parent()); 161 // Top container is still second from front. 162 EXPECT_EQ(browser_view()->child_count() - 2, 163 browser_view()->GetIndexOf(top_container)); 164 165 BookmarkBarView::DisableAnimationsForTesting(false); 166} 167 168class BrowserViewHostedAppTest : public TestWithBrowserView { 169 public: 170 BrowserViewHostedAppTest() 171 : TestWithBrowserView(Browser::TYPE_POPUP, 172 chrome::HOST_DESKTOP_TYPE_NATIVE, 173 true) { 174 } 175 virtual ~BrowserViewHostedAppTest() { 176 } 177 178 private: 179 DISALLOW_COPY_AND_ASSIGN(BrowserViewHostedAppTest); 180}; 181 182// Test basic layout for hosted apps. 183TEST_F(BrowserViewHostedAppTest, Layout) { 184 // Add a tab because the browser starts out without any tabs at all. 185 AddTab(browser(), GURL("about:blank")); 186 187 views::View* contents_container = 188 browser_view()->GetContentsContainerForTest(); 189 190 // The tabstrip, toolbar and bookmark bar should not be visible for hosted 191 // apps. 192 EXPECT_FALSE(browser_view()->tabstrip()->visible()); 193 EXPECT_FALSE(browser_view()->toolbar()->visible()); 194 EXPECT_FALSE(browser_view()->IsBookmarkBarVisible()); 195 196 gfx::Point header_offset; 197 views::View::ConvertPointToTarget( 198 browser_view(), 199 browser_view()->frame()->non_client_view()->frame_view(), 200 &header_offset); 201 202 // The position of the bottom of the header (the bar with the window 203 // controls) in the coordinates of BrowserView. 204 int bottom_of_header = browser_view()->frame()->GetTopInset() - 205 header_offset.y(); 206 207 // The web contents should be flush with the bottom of the header. 208 EXPECT_EQ(bottom_of_header, contents_container->y()); 209 210 // The find bar should overlap the 1px header/web-contents separator at the 211 // bottom of the header. 212 EXPECT_EQ(browser_view()->frame()->GetTopInset() - 1, 213 browser_view()->GetFindBarBoundingBox().y()); 214} 215 216#if defined(OS_WIN) 217 218// This class provides functionality to test the incognito window/normal window 219// switcher button which is added to Windows 8 metro Chrome. 220// We create the BrowserView ourselves in the 221// BrowserWithTestWindowTest::CreateBrowserWindow function override and add the 222// switcher button to the view. We also provide an incognito profile to ensure 223// that the switcher button is visible. 224class BrowserViewIncognitoSwitcherTest : public TestWithBrowserView { 225 public: 226 // Subclass of BrowserView, which overrides the GetRestoreBounds/IsMaximized 227 // functions to return dummy values. This is needed because we create the 228 // BrowserView instance ourselves and initialize it with the created Browser 229 // instance. These functions get called before the underlying Widget is 230 // initialized which causes a crash while dereferencing a null native_widget_ 231 // pointer in the Widget class. 232 class TestBrowserView : public BrowserView { 233 public: 234 virtual ~TestBrowserView() {} 235 236 virtual gfx::Rect GetRestoredBounds() const OVERRIDE { 237 return gfx::Rect(); 238 } 239 virtual bool IsMaximized() const OVERRIDE { 240 return false; 241 } 242 }; 243 244 BrowserViewIncognitoSwitcherTest() 245 : browser_view_(NULL) {} 246 247 virtual void SetUp() OVERRIDE { 248 TestWithBrowserView::SetUp(); 249 browser_view_->Init(browser()); 250 (new BrowserFrame(browser_view_))->InitBrowserFrame(); 251 browser_view_->SetBounds(gfx::Rect(10, 10, 500, 500)); 252 browser_view_->Show(); 253 } 254 255 virtual void TearDown() OVERRIDE { 256 // ok to release the window_ pointer because BrowserViewTest::TearDown 257 // deletes the BrowserView instance created. 258 release_browser_window(); 259 BrowserViewTest::TearDown(); 260 browser_view_ = NULL; 261 } 262 263 virtual BrowserWindow* CreateBrowserWindow() OVERRIDE { 264 // We need an incognito profile for the window switcher button to be 265 // visible. 266 // This profile instance is owned by the TestingProfile instance within the 267 // BrowserWithTestWindowTest class. 268 TestingProfile::Builder builder; 269 builder.SetIncognito(); 270 GetProfile()->SetOffTheRecordProfile(builder.Build()); 271 272 browser_view_ = new TestBrowserView(); 273 274 views::ImageButton* switcher_button = new views::ImageButton(NULL); 275 // The button in the incognito window has the hot-cold images inverted 276 // with respect to the regular browser window. 277 switcher_button->SetImage( 278 views::ImageButton::STATE_NORMAL, 279 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( 280 IDR_INCOGNITO_SWITCH_OFF)); 281 switcher_button->SetImage( 282 views::ImageButton::STATE_HOVERED, 283 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( 284 IDR_INCOGNITO_SWITCH_ON)); 285 switcher_button->SetImageAlignment(views::ImageButton::ALIGN_CENTER, 286 views::ImageButton::ALIGN_MIDDLE); 287 288 browser_view_->SetWindowSwitcherButton(switcher_button); 289 return browser_view_; 290 } 291 292 private: 293 BrowserView* browser_view_; 294 295 DISALLOW_COPY_AND_ASSIGN(BrowserViewIncognitoSwitcherTest); 296}; 297 298// Test whether the windows incognito/normal browser window switcher button 299// is the event handler for a point within its bounds. The event handler for 300// a point in the View class is dependent on the order in which children are 301// added to it. This test ensures that we don't regress in the window switcher 302// functionality when additional children are added to the BrowserView class. 303TEST_F(BrowserViewIncognitoSwitcherTest, 304 BrowserViewIncognitoSwitcherEventHandlerTest) { 305 // |browser_view_| owns the Browser, not the test class. 306 EXPECT_TRUE(browser_view()->browser()); 307 // Test initial state. 308 EXPECT_TRUE(browser_view()->IsTabStripVisible()); 309 // Validate whether the window switcher button is the target for the position 310 // passed in. 311 gfx::Point switcher_point(browser_view()->window_switcher_button()->x() + 2, 312 browser_view()->window_switcher_button()->y()); 313 EXPECT_EQ(browser_view()->GetEventHandlerForPoint(switcher_point), 314 browser_view()->window_switcher_button()); 315} 316#endif 317