1// Copyright (c) 2011 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 "base/memory/scoped_nsobject.h" 6#include "base/memory/scoped_ptr.h" 7#include "chrome/app/chrome_command_ids.h" 8#include "chrome/browser/prefs/pref_service.h" 9#include "chrome/browser/sync/sync_ui_util.h" 10#include "chrome/browser/ui/browser_window.h" 11#include "chrome/browser/ui/cocoa/browser_test_helper.h" 12#include "chrome/browser/ui/cocoa/browser_window_controller.h" 13#include "chrome/browser/ui/cocoa/cocoa_test_helper.h" 14#include "chrome/browser/ui/cocoa/find_bar/find_bar_bridge.h" 15#include "chrome/common/pref_names.h" 16#include "chrome/test/testing_profile.h" 17#include "grit/generated_resources.h" 18#include "ui/base/l10n/l10n_util_mac.h" 19 20@interface BrowserWindowController (JustForTesting) 21// Already defined in BWC. 22- (void)saveWindowPositionToPrefs:(PrefService*)prefs; 23- (void)layoutSubviews; 24@end 25 26@interface BrowserWindowController (ExposedForTesting) 27// Implementations are below. 28- (NSView*)infoBarContainerView; 29- (NSView*)toolbarView; 30- (NSView*)bookmarkView; 31- (BOOL)bookmarkBarVisible; 32@end 33 34@implementation BrowserWindowController (ExposedForTesting) 35- (NSView*)infoBarContainerView { 36 return [infoBarContainerController_ view]; 37} 38 39- (NSView*)toolbarView { 40 return [toolbarController_ view]; 41} 42 43- (NSView*)bookmarkView { 44 return [bookmarkBarController_ view]; 45} 46 47- (NSView*)findBarView { 48 return [findBarCocoaController_ view]; 49} 50 51- (NSSplitView*)devToolsView { 52 return static_cast<NSSplitView*>([devToolsController_ view]); 53} 54 55- (NSView*)sidebarView { 56 return [sidebarController_ view]; 57} 58 59- (BOOL)bookmarkBarVisible { 60 return [bookmarkBarController_ isVisible]; 61} 62@end 63 64class BrowserWindowControllerTest : public CocoaTest { 65 public: 66 virtual void SetUp() { 67 CocoaTest::SetUp(); 68 Browser* browser = browser_helper_.browser(); 69 controller_ = [[BrowserWindowController alloc] initWithBrowser:browser 70 takeOwnership:NO]; 71 } 72 73 virtual void TearDown() { 74 [controller_ close]; 75 CocoaTest::TearDown(); 76 } 77 78 public: 79 BrowserTestHelper browser_helper_; 80 BrowserWindowController* controller_; 81}; 82 83TEST_F(BrowserWindowControllerTest, TestSaveWindowPosition) { 84 PrefService* prefs = browser_helper_.profile()->GetPrefs(); 85 ASSERT_TRUE(prefs != NULL); 86 87 // Check to make sure there is no existing pref for window placement. 88 const DictionaryValue* browser_window_placement = 89 prefs->GetDictionary(prefs::kBrowserWindowPlacement); 90 ASSERT_TRUE(browser_window_placement); 91 EXPECT_TRUE(browser_window_placement->empty()); 92 93 // Ask the window to save its position, then check that a preference 94 // exists. 95 [controller_ saveWindowPositionToPrefs:prefs]; 96 browser_window_placement = 97 prefs->GetDictionary(prefs::kBrowserWindowPlacement); 98 ASSERT_TRUE(browser_window_placement); 99 EXPECT_FALSE(browser_window_placement->empty()); 100} 101 102TEST_F(BrowserWindowControllerTest, TestFullScreenWindow) { 103 // Confirm that |-createFullscreenWindow| doesn't return nil. 104 // See BrowserWindowFullScreenControllerTest for more fullscreen tests. 105 EXPECT_TRUE([controller_ createFullscreenWindow]); 106} 107 108TEST_F(BrowserWindowControllerTest, TestNormal) { 109 // Force the bookmark bar to be shown. 110 browser_helper_.profile()->GetPrefs()-> 111 SetBoolean(prefs::kShowBookmarkBar, true); 112 [controller_ updateBookmarkBarVisibilityWithAnimation:NO]; 113 114 // Make sure a normal BrowserWindowController is, uh, normal. 115 EXPECT_TRUE([controller_ isNormalWindow]); 116 EXPECT_TRUE([controller_ hasTabStrip]); 117 EXPECT_FALSE([controller_ hasTitleBar]); 118 EXPECT_TRUE([controller_ isBookmarkBarVisible]); 119 120 // And make sure a controller for a pop-up window is not normal. 121 // popup_browser will be owned by its window. 122 Browser *popup_browser(Browser::CreateForType(Browser::TYPE_POPUP, 123 browser_helper_.profile())); 124 NSWindow *cocoaWindow = popup_browser->window()->GetNativeHandle(); 125 BrowserWindowController* controller = 126 static_cast<BrowserWindowController*>([cocoaWindow windowController]); 127 ASSERT_TRUE([controller isKindOfClass:[BrowserWindowController class]]); 128 EXPECT_FALSE([controller isNormalWindow]); 129 EXPECT_FALSE([controller hasTabStrip]); 130 EXPECT_TRUE([controller hasTitleBar]); 131 EXPECT_FALSE([controller isBookmarkBarVisible]); 132 [controller close]; 133} 134 135TEST_F(BrowserWindowControllerTest, TestTheme) { 136 [controller_ userChangedTheme]; 137} 138 139TEST_F(BrowserWindowControllerTest, BookmarkBarControllerIndirection) { 140 EXPECT_FALSE([controller_ isBookmarkBarVisible]); 141 142 // Explicitly show the bar. Can't use bookmark_utils::ToggleWhenVisible() 143 // because of the notification issues. 144 browser_helper_.profile()->GetPrefs()-> 145 SetBoolean(prefs::kShowBookmarkBar, true); 146 147 [controller_ updateBookmarkBarVisibilityWithAnimation:NO]; 148 EXPECT_TRUE([controller_ isBookmarkBarVisible]); 149} 150 151#if 0 152// TODO(jrg): This crashes trying to create the BookmarkBarController, adding 153// an observer to the BookmarkModel. 154TEST_F(BrowserWindowControllerTest, TestIncognitoWidthSpace) { 155 scoped_ptr<TestingProfile> incognito_profile(new TestingProfile()); 156 incognito_profile->set_off_the_record(true); 157 scoped_ptr<Browser> browser(new Browser(Browser::TYPE_NORMAL, 158 incognito_profile.get())); 159 controller_.reset([[BrowserWindowController alloc] 160 initWithBrowser:browser.get() 161 takeOwnership:NO]); 162 163 NSRect tabFrame = [[controller_ tabStripView] frame]; 164 [controller_ installIncognitoBadge]; 165 NSRect newTabFrame = [[controller_ tabStripView] frame]; 166 EXPECT_GT(tabFrame.size.width, newTabFrame.size.width); 167 168 controller_.release(); 169} 170#endif 171 172namespace { 173// Verifies that the toolbar, infobar, tab content area, and download shelf 174// completely fill the area under the tabstrip. 175void CheckViewPositions(BrowserWindowController* controller) { 176 NSRect contentView = [[[controller window] contentView] bounds]; 177 NSRect tabstrip = [[controller tabStripView] frame]; 178 NSRect toolbar = [[controller toolbarView] frame]; 179 NSRect infobar = [[controller infoBarContainerView] frame]; 180 NSRect contentArea = [[controller tabContentArea] frame]; 181 NSRect download = [[[controller downloadShelf] view] frame]; 182 183 EXPECT_EQ(NSMinY(contentView), NSMinY(download)); 184 EXPECT_EQ(NSMaxY(download), NSMinY(contentArea)); 185 EXPECT_EQ(NSMaxY(contentArea), NSMinY(infobar)); 186 187 // Bookmark bar frame is random memory when hidden. 188 if ([controller bookmarkBarVisible]) { 189 NSRect bookmark = [[controller bookmarkView] frame]; 190 EXPECT_EQ(NSMaxY(infobar), NSMinY(bookmark)); 191 EXPECT_EQ(NSMaxY(bookmark), NSMinY(toolbar)); 192 EXPECT_FALSE([[controller bookmarkView] isHidden]); 193 } else { 194 EXPECT_EQ(NSMaxY(infobar), NSMinY(toolbar)); 195 EXPECT_TRUE([[controller bookmarkView] isHidden]); 196 } 197 198 // Toolbar should start immediately under the tabstrip, but the tabstrip is 199 // not necessarily fixed with respect to the content view. 200 EXPECT_EQ(NSMinY(tabstrip), NSMaxY(toolbar)); 201} 202} // end namespace 203 204TEST_F(BrowserWindowControllerTest, TestAdjustWindowHeight) { 205 NSWindow* window = [controller_ window]; 206 NSRect workarea = [[window screen] visibleFrame]; 207 208 // Place the window well above the bottom of the screen and try to adjust its 209 // height. It should change appropriately (and only downwards). Then get it to 210 // shrink by the same amount; it should return to its original state. 211 NSRect initialFrame = NSMakeRect(workarea.origin.x, workarea.origin.y + 100, 212 200, 200); 213 [window setFrame:initialFrame display:YES]; 214 [controller_ resetWindowGrowthState]; 215 [controller_ adjustWindowHeightBy:40]; 216 NSRect finalFrame = [window frame]; 217 EXPECT_FALSE(NSEqualRects(finalFrame, initialFrame)); 218 EXPECT_FLOAT_EQ(NSMaxY(finalFrame), NSMaxY(initialFrame)); 219 EXPECT_FLOAT_EQ(NSHeight(finalFrame), NSHeight(initialFrame) + 40); 220 [controller_ adjustWindowHeightBy:-40]; 221 finalFrame = [window frame]; 222 EXPECT_FLOAT_EQ(NSMaxY(finalFrame), NSMaxY(initialFrame)); 223 EXPECT_FLOAT_EQ(NSHeight(finalFrame), NSHeight(initialFrame)); 224 225 // Place the window at the bottom of the screen and try again. Its height 226 // should still change, but it should not grow down below the work area; it 227 // should instead move upwards. Then shrink it and make sure it goes back to 228 // the way it was. 229 initialFrame = NSMakeRect(workarea.origin.x, workarea.origin.y, 200, 200); 230 [window setFrame:initialFrame display:YES]; 231 [controller_ resetWindowGrowthState]; 232 [controller_ adjustWindowHeightBy:40]; 233 finalFrame = [window frame]; 234 EXPECT_FALSE(NSEqualRects(finalFrame, initialFrame)); 235 EXPECT_FLOAT_EQ(NSMinY(finalFrame), NSMinY(initialFrame)); 236 EXPECT_FLOAT_EQ(NSHeight(finalFrame), NSHeight(initialFrame) + 40); 237 [controller_ adjustWindowHeightBy:-40]; 238 finalFrame = [window frame]; 239 EXPECT_FLOAT_EQ(NSMinY(finalFrame), NSMinY(initialFrame)); 240 EXPECT_FLOAT_EQ(NSHeight(finalFrame), NSHeight(initialFrame)); 241 242 // Put the window slightly offscreen and try again. The height should not 243 // change this time. 244 initialFrame = NSMakeRect(workarea.origin.x - 10, 0, 200, 200); 245 [window setFrame:initialFrame display:YES]; 246 [controller_ resetWindowGrowthState]; 247 [controller_ adjustWindowHeightBy:40]; 248 EXPECT_TRUE(NSEqualRects([window frame], initialFrame)); 249 [controller_ adjustWindowHeightBy:-40]; 250 EXPECT_TRUE(NSEqualRects([window frame], initialFrame)); 251 252 // Make the window the same size as the workarea. Resizing both larger and 253 // smaller should have no effect. 254 [window setFrame:workarea display:YES]; 255 [controller_ resetWindowGrowthState]; 256 [controller_ adjustWindowHeightBy:40]; 257 EXPECT_TRUE(NSEqualRects([window frame], workarea)); 258 [controller_ adjustWindowHeightBy:-40]; 259 EXPECT_TRUE(NSEqualRects([window frame], workarea)); 260 261 // Make the window smaller than the workarea and place it near the bottom of 262 // the workarea. The window should grow down until it hits the bottom and 263 // then continue to grow up. Then shrink it, and it should return to where it 264 // was. 265 initialFrame = NSMakeRect(workarea.origin.x, workarea.origin.y + 5, 266 200, 200); 267 [window setFrame:initialFrame display:YES]; 268 [controller_ resetWindowGrowthState]; 269 [controller_ adjustWindowHeightBy:40]; 270 finalFrame = [window frame]; 271 EXPECT_FLOAT_EQ(NSMinY(workarea), NSMinY(finalFrame)); 272 EXPECT_FLOAT_EQ(NSHeight(finalFrame), NSHeight(initialFrame) + 40); 273 [controller_ adjustWindowHeightBy:-40]; 274 finalFrame = [window frame]; 275 EXPECT_FLOAT_EQ(NSMinY(initialFrame), NSMinY(finalFrame)); 276 EXPECT_FLOAT_EQ(NSHeight(initialFrame), NSHeight(finalFrame)); 277 278 // Inset the window slightly from the workarea. It should not grow to be 279 // larger than the workarea. Shrink it; it should return to where it started. 280 initialFrame = NSInsetRect(workarea, 0, 5); 281 [window setFrame:initialFrame display:YES]; 282 [controller_ resetWindowGrowthState]; 283 [controller_ adjustWindowHeightBy:40]; 284 finalFrame = [window frame]; 285 EXPECT_FLOAT_EQ(NSMinY(workarea), NSMinY(finalFrame)); 286 EXPECT_FLOAT_EQ(NSHeight(workarea), NSHeight(finalFrame)); 287 [controller_ adjustWindowHeightBy:-40]; 288 finalFrame = [window frame]; 289 EXPECT_FLOAT_EQ(NSMinY(initialFrame), NSMinY(finalFrame)); 290 EXPECT_FLOAT_EQ(NSHeight(initialFrame), NSHeight(finalFrame)); 291 292 // Place the window at the bottom of the screen and grow; it should grow 293 // upwards. Move the window off the bottom, then shrink. It should then shrink 294 // from the bottom. 295 initialFrame = NSMakeRect(workarea.origin.x, workarea.origin.y, 200, 200); 296 [window setFrame:initialFrame display:YES]; 297 [controller_ resetWindowGrowthState]; 298 [controller_ adjustWindowHeightBy:40]; 299 finalFrame = [window frame]; 300 EXPECT_FALSE(NSEqualRects(finalFrame, initialFrame)); 301 EXPECT_FLOAT_EQ(NSMinY(finalFrame), NSMinY(initialFrame)); 302 EXPECT_FLOAT_EQ(NSHeight(finalFrame), NSHeight(initialFrame) + 40); 303 NSPoint oldOrigin = initialFrame.origin; 304 NSPoint newOrigin = NSMakePoint(oldOrigin.x, oldOrigin.y + 10); 305 [window setFrameOrigin:newOrigin]; 306 initialFrame = [window frame]; 307 EXPECT_FLOAT_EQ(NSMinY(initialFrame), oldOrigin.y + 10); 308 [controller_ adjustWindowHeightBy:-40]; 309 finalFrame = [window frame]; 310 EXPECT_FLOAT_EQ(NSMinY(finalFrame), NSMinY(initialFrame) + 40); 311 EXPECT_FLOAT_EQ(NSHeight(finalFrame), NSHeight(initialFrame) - 40); 312 313 // Do the "inset" test above, but using multiple calls to 314 // |-adjustWindowHeightBy|; the result should be the same. 315 initialFrame = NSInsetRect(workarea, 0, 5); 316 [window setFrame:initialFrame display:YES]; 317 [controller_ resetWindowGrowthState]; 318 for (int i = 0; i < 8; i++) 319 [controller_ adjustWindowHeightBy:5]; 320 finalFrame = [window frame]; 321 EXPECT_FLOAT_EQ(NSMinY(workarea), NSMinY(finalFrame)); 322 EXPECT_FLOAT_EQ(NSHeight(workarea), NSHeight(finalFrame)); 323 for (int i = 0; i < 8; i++) 324 [controller_ adjustWindowHeightBy:-5]; 325 finalFrame = [window frame]; 326 EXPECT_FLOAT_EQ(NSMinY(initialFrame), NSMinY(finalFrame)); 327 EXPECT_FLOAT_EQ(NSHeight(initialFrame), NSHeight(finalFrame)); 328} 329 330// Test to make sure resizing and relaying-out subviews works correctly. 331TEST_F(BrowserWindowControllerTest, TestResizeViews) { 332 TabStripView* tabstrip = [controller_ tabStripView]; 333 NSView* contentView = [[tabstrip window] contentView]; 334 NSView* toolbar = [controller_ toolbarView]; 335 NSView* infobar = [controller_ infoBarContainerView]; 336 337 // We need to muck with the views a bit to put us in a consistent state before 338 // we start resizing. In particular, we need to move the tab strip to be 339 // immediately above the content area, since we layout views to be directly 340 // under the tab strip. 341 NSRect tabstripFrame = [tabstrip frame]; 342 tabstripFrame.origin.y = NSMaxY([contentView frame]); 343 [tabstrip setFrame:tabstripFrame]; 344 345 // The download shelf is created lazily. Force-create it and set its initial 346 // height to 0. 347 NSView* download = [[controller_ downloadShelf] view]; 348 NSRect downloadFrame = [download frame]; 349 downloadFrame.size.height = 0; 350 [download setFrame:downloadFrame]; 351 352 // Force a layout and check each view's frame. 353 [controller_ layoutSubviews]; 354 CheckViewPositions(controller_); 355 356 // Expand the infobar to 60px and recheck 357 [controller_ resizeView:infobar newHeight:60]; 358 CheckViewPositions(controller_); 359 360 // Expand the toolbar to 64px and recheck 361 [controller_ resizeView:toolbar newHeight:64]; 362 CheckViewPositions(controller_); 363 364 // Add a 30px download shelf and recheck 365 [controller_ resizeView:download newHeight:30]; 366 CheckViewPositions(controller_); 367 368 // Shrink the infobar to 0px and toolbar to 39px and recheck 369 [controller_ resizeView:infobar newHeight:0]; 370 [controller_ resizeView:toolbar newHeight:39]; 371 CheckViewPositions(controller_); 372} 373 374TEST_F(BrowserWindowControllerTest, TestResizeViewsWithBookmarkBar) { 375 // Force a display of the bookmark bar. 376 browser_helper_.profile()->GetPrefs()-> 377 SetBoolean(prefs::kShowBookmarkBar, true); 378 [controller_ updateBookmarkBarVisibilityWithAnimation:NO]; 379 380 TabStripView* tabstrip = [controller_ tabStripView]; 381 NSView* contentView = [[tabstrip window] contentView]; 382 NSView* toolbar = [controller_ toolbarView]; 383 NSView* bookmark = [controller_ bookmarkView]; 384 NSView* infobar = [controller_ infoBarContainerView]; 385 386 // We need to muck with the views a bit to put us in a consistent state before 387 // we start resizing. In particular, we need to move the tab strip to be 388 // immediately above the content area, since we layout views to be directly 389 // under the tab strip. 390 NSRect tabstripFrame = [tabstrip frame]; 391 tabstripFrame.origin.y = NSMaxY([contentView frame]); 392 [tabstrip setFrame:tabstripFrame]; 393 394 // The download shelf is created lazily. Force-create it and set its initial 395 // height to 0. 396 NSView* download = [[controller_ downloadShelf] view]; 397 NSRect downloadFrame = [download frame]; 398 downloadFrame.size.height = 0; 399 [download setFrame:downloadFrame]; 400 401 // Force a layout and check each view's frame. 402 [controller_ layoutSubviews]; 403 CheckViewPositions(controller_); 404 405 // Add the bookmark bar and recheck. 406 [controller_ resizeView:bookmark newHeight:40]; 407 CheckViewPositions(controller_); 408 409 // Expand the infobar to 60px and recheck 410 [controller_ resizeView:infobar newHeight:60]; 411 CheckViewPositions(controller_); 412 413 // Expand the toolbar to 64px and recheck 414 [controller_ resizeView:toolbar newHeight:64]; 415 CheckViewPositions(controller_); 416 417 // Add a 30px download shelf and recheck 418 [controller_ resizeView:download newHeight:30]; 419 CheckViewPositions(controller_); 420 421 // Remove the bookmark bar and recheck 422 browser_helper_.profile()->GetPrefs()-> 423 SetBoolean(prefs::kShowBookmarkBar, false); 424 [controller_ resizeView:bookmark newHeight:0]; 425 CheckViewPositions(controller_); 426 427 // Shrink the infobar to 0px and toolbar to 39px and recheck 428 [controller_ resizeView:infobar newHeight:0]; 429 [controller_ resizeView:toolbar newHeight:39]; 430 CheckViewPositions(controller_); 431} 432 433// Make sure, by default, the bookmark bar and the toolbar are the same width. 434TEST_F(BrowserWindowControllerTest, BookmarkBarIsSameWidth) { 435 // Set the pref to the bookmark bar is visible when the toolbar is 436 // first created. 437 browser_helper_.profile()->GetPrefs()->SetBoolean( 438 prefs::kShowBookmarkBar, true); 439 440 // Make sure the bookmark bar is the same width as the toolbar 441 NSView* bookmarkBarView = [controller_ bookmarkView]; 442 NSView* toolbarView = [controller_ toolbarView]; 443 EXPECT_EQ([toolbarView frame].size.width, 444 [bookmarkBarView frame].size.width); 445} 446 447TEST_F(BrowserWindowControllerTest, TestTopRightForBubble) { 448 NSPoint p = [controller_ bookmarkBubblePoint]; 449 NSRect all = [[controller_ window] frame]; 450 451 // As a sanity check make sure the point is vaguely in the top right 452 // of the window. 453 EXPECT_GT(p.y, all.origin.y + (all.size.height/2)); 454 EXPECT_GT(p.x, all.origin.x + (all.size.width/2)); 455} 456 457// By the "zoom frame", we mean what Apple calls the "standard frame". 458TEST_F(BrowserWindowControllerTest, TestZoomFrame) { 459 NSWindow* window = [controller_ window]; 460 ASSERT_TRUE(window); 461 NSRect screenFrame = [[window screen] visibleFrame]; 462 ASSERT_FALSE(NSIsEmptyRect(screenFrame)); 463 464 // Minimum zoomed width is the larger of 60% of available horizontal space or 465 // 60% of available vertical space, subject to available horizontal space. 466 CGFloat minZoomWidth = 467 std::min(std::max((CGFloat)0.6 * screenFrame.size.width, 468 (CGFloat)0.6 * screenFrame.size.height), 469 screenFrame.size.width); 470 471 // |testFrame| is the size of the window we start out with, and |zoomFrame| is 472 // the one returned by |-windowWillUseStandardFrame:defaultFrame:|. 473 NSRect testFrame; 474 NSRect zoomFrame; 475 476 // 1. Test a case where it zooms the window both horizontally and vertically, 477 // and only moves it vertically. "+ 32", etc. are just arbitrary constants 478 // used to check that the window is moved properly and not just to the origin; 479 // they should be small enough to not shove windows off the screen. 480 testFrame.size.width = 0.5 * minZoomWidth; 481 testFrame.size.height = 0.5 * screenFrame.size.height; 482 testFrame.origin.x = screenFrame.origin.x + 32; // See above. 483 testFrame.origin.y = screenFrame.origin.y + 23; 484 [window setFrame:testFrame display:NO]; 485 zoomFrame = [controller_ windowWillUseStandardFrame:window 486 defaultFrame:screenFrame]; 487 EXPECT_LE(minZoomWidth, zoomFrame.size.width); 488 EXPECT_EQ(screenFrame.size.height, zoomFrame.size.height); 489 EXPECT_EQ(testFrame.origin.x, zoomFrame.origin.x); 490 EXPECT_EQ(screenFrame.origin.y, zoomFrame.origin.y); 491 492 // 2. Test a case where it zooms the window only horizontally, and only moves 493 // it horizontally. 494 testFrame.size.width = 0.5 * minZoomWidth; 495 testFrame.size.height = screenFrame.size.height; 496 testFrame.origin.x = screenFrame.origin.x + screenFrame.size.width - 497 testFrame.size.width; 498 testFrame.origin.y = screenFrame.origin.y; 499 [window setFrame:testFrame display:NO]; 500 zoomFrame = [controller_ windowWillUseStandardFrame:window 501 defaultFrame:screenFrame]; 502 EXPECT_LE(minZoomWidth, zoomFrame.size.width); 503 EXPECT_EQ(screenFrame.size.height, zoomFrame.size.height); 504 EXPECT_EQ(screenFrame.origin.x + screenFrame.size.width - 505 zoomFrame.size.width, zoomFrame.origin.x); 506 EXPECT_EQ(screenFrame.origin.y, zoomFrame.origin.y); 507 508 // 3. Test a case where it zooms the window only vertically, and only moves it 509 // vertically. 510 testFrame.size.width = std::min((CGFloat)1.1 * minZoomWidth, 511 screenFrame.size.width); 512 testFrame.size.height = 0.3 * screenFrame.size.height; 513 testFrame.origin.x = screenFrame.origin.x + 32; // See above (in 1.). 514 testFrame.origin.y = screenFrame.origin.y + 123; 515 [window setFrame:testFrame display:NO]; 516 zoomFrame = [controller_ windowWillUseStandardFrame:window 517 defaultFrame:screenFrame]; 518 // Use the actual width of the window frame, since it's subject to rounding. 519 EXPECT_EQ([window frame].size.width, zoomFrame.size.width); 520 EXPECT_EQ(screenFrame.size.height, zoomFrame.size.height); 521 EXPECT_EQ(testFrame.origin.x, zoomFrame.origin.x); 522 EXPECT_EQ(screenFrame.origin.y, zoomFrame.origin.y); 523 524 // 4. Test a case where zooming should do nothing (i.e., we're already at a 525 // zoomed frame). 526 testFrame.size.width = std::min((CGFloat)1.1 * minZoomWidth, 527 screenFrame.size.width); 528 testFrame.size.height = screenFrame.size.height; 529 testFrame.origin.x = screenFrame.origin.x + 32; // See above (in 1.). 530 testFrame.origin.y = screenFrame.origin.y; 531 [window setFrame:testFrame display:NO]; 532 zoomFrame = [controller_ windowWillUseStandardFrame:window 533 defaultFrame:screenFrame]; 534 // Use the actual width of the window frame, since it's subject to rounding. 535 EXPECT_EQ([window frame].size.width, zoomFrame.size.width); 536 EXPECT_EQ(screenFrame.size.height, zoomFrame.size.height); 537 EXPECT_EQ(testFrame.origin.x, zoomFrame.origin.x); 538 EXPECT_EQ(screenFrame.origin.y, zoomFrame.origin.y); 539} 540 541TEST_F(BrowserWindowControllerTest, TestFindBarOnTop) { 542 FindBarBridge bridge; 543 [controller_ addFindBar:bridge.find_bar_cocoa_controller()]; 544 545 // Test that the Z-order of the find bar is on top of everything. 546 NSArray* subviews = [[[controller_ window] contentView] subviews]; 547 NSUInteger findBar_index = 548 [subviews indexOfObject:[controller_ findBarView]]; 549 EXPECT_NE(NSNotFound, findBar_index); 550 NSUInteger toolbar_index = 551 [subviews indexOfObject:[controller_ toolbarView]]; 552 EXPECT_NE(NSNotFound, toolbar_index); 553 NSUInteger bookmark_index = 554 [subviews indexOfObject:[controller_ bookmarkView]]; 555 EXPECT_NE(NSNotFound, bookmark_index); 556 557 EXPECT_GT(findBar_index, toolbar_index); 558 EXPECT_GT(findBar_index, bookmark_index); 559} 560 561// Tests that the sidebar view and devtools view are both non-opaque. 562TEST_F(BrowserWindowControllerTest, TestSplitViewsAreNotOpaque) { 563 // Add a subview to the sidebar view to mimic what happens when a tab is added 564 // to the window. NSSplitView only marks itself as non-opaque when one of its 565 // subviews is non-opaque, so the test will not pass without this subview. 566 scoped_nsobject<NSView> view( 567 [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 10, 10)]); 568 [[controller_ sidebarView] addSubview:view]; 569 570 EXPECT_FALSE([[controller_ tabContentArea] isOpaque]); 571 EXPECT_FALSE([[controller_ devToolsView] isOpaque]); 572 EXPECT_FALSE([[controller_ sidebarView] isOpaque]); 573} 574 575// Tests that status bubble's base frame does move when devTools are docked. 576TEST_F(BrowserWindowControllerTest, TestStatusBubblePositioning) { 577 ASSERT_EQ(1U, [[[controller_ devToolsView] subviews] count]); 578 579 NSPoint bubbleOrigin = [controller_ statusBubbleBaseFrame].origin; 580 581 // Add a fake subview to devToolsView to emulate docked devTools. 582 scoped_nsobject<NSView> view( 583 [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 10, 10)]); 584 [[controller_ devToolsView] addSubview:view]; 585 [[controller_ devToolsView] adjustSubviews]; 586 587 NSPoint bubbleOriginWithDevTools = [controller_ statusBubbleBaseFrame].origin; 588 589 // Make sure that status bubble frame is moved. 590 EXPECT_FALSE(NSEqualPoints(bubbleOrigin, bubbleOriginWithDevTools)); 591} 592 593@interface BrowserWindowControllerFakeFullscreen : BrowserWindowController { 594 @private 595 // We release the window ourselves, so we don't have to rely on the unittest 596 // doing it for us. 597 scoped_nsobject<NSWindow> fullscreenWindow_; 598} 599@end 600 601class BrowserWindowFullScreenControllerTest : public CocoaTest { 602 public: 603 virtual void SetUp() { 604 CocoaTest::SetUp(); 605 Browser* browser = browser_helper_.browser(); 606 controller_ = 607 [[BrowserWindowControllerFakeFullscreen alloc] initWithBrowser:browser 608 takeOwnership:NO]; 609 } 610 611 virtual void TearDown() { 612 [controller_ close]; 613 CocoaTest::TearDown(); 614 } 615 616 public: 617 BrowserTestHelper browser_helper_; 618 BrowserWindowController* controller_; 619}; 620 621@interface BrowserWindowController (PrivateAPI) 622- (BOOL)supportsFullscreen; 623@end 624 625// Check if the window is front most or if one of its child windows (such 626// as a status bubble) is front most. 627static bool IsFrontWindow(NSWindow *window) { 628 NSWindow* frontmostWindow = [[NSApp orderedWindows] objectAtIndex:0]; 629 return [frontmostWindow isEqual:window] || 630 [[frontmostWindow parentWindow] isEqual:window]; 631} 632 633TEST_F(BrowserWindowFullScreenControllerTest, TestFullscreen) { 634 EXPECT_FALSE([controller_ isFullscreen]); 635 [controller_ setFullscreen:YES]; 636 EXPECT_TRUE([controller_ isFullscreen]); 637 [controller_ setFullscreen:NO]; 638 EXPECT_FALSE([controller_ isFullscreen]); 639} 640 641// If this test fails, it is usually a sign that the bots have some sort of 642// problem (such as a modal dialog up). This tests is a very useful canary, so 643// please do not mark it as flaky without first verifying that there are no bot 644// problems. 645TEST_F(BrowserWindowFullScreenControllerTest, TestActivate) { 646 EXPECT_FALSE([controller_ isFullscreen]); 647 648 [controller_ activate]; 649 EXPECT_TRUE(IsFrontWindow([controller_ window])); 650 651 [controller_ setFullscreen:YES]; 652 [controller_ activate]; 653 EXPECT_TRUE(IsFrontWindow([controller_ createFullscreenWindow])); 654 655 // We have to cleanup after ourselves by unfullscreening. 656 [controller_ setFullscreen:NO]; 657} 658 659@implementation BrowserWindowControllerFakeFullscreen 660// Override |-createFullscreenWindow| to return a dummy window. This isn't 661// needed to pass the test, but because the dummy window is only 100x100, it 662// prevents the real fullscreen window from flashing up and taking over the 663// whole screen. We have to return an actual window because |-layoutSubviews| 664// looks at the window's frame. 665- (NSWindow*)createFullscreenWindow { 666 if (fullscreenWindow_.get()) 667 return fullscreenWindow_.get(); 668 669 fullscreenWindow_.reset( 670 [[NSWindow alloc] initWithContentRect:NSMakeRect(0,0,400,400) 671 styleMask:NSBorderlessWindowMask 672 backing:NSBackingStoreBuffered 673 defer:NO]); 674 return fullscreenWindow_.get(); 675} 676@end 677 678/* TODO(???): test other methods of BrowserWindowController */ 679