Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / browser_window_controller_browsertest.mm
blob2e253f1ac580874d5dc00c03cde0f3453968b828
1 // Copyright (c) 2012 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 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
7 #import "base/mac/mac_util.h"
8 #include "base/mac/sdk_forward_declarations.h"
9 #include "base/run_loop.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/app/chrome_command_ids.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/devtools/devtools_window_testing.h"
14 #include "chrome/browser/infobars/infobar_service.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/profiles/profile_manager.h"
17 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_commands.h"
20 #include "chrome/browser/ui/browser_list.h"
21 #include "chrome/browser/ui/browser_window.h"
22 #include "chrome/browser/ui/cocoa/browser_window_cocoa.h"
23 #import "chrome/browser/ui/cocoa/browser_window_controller_private.h"
24 #import "chrome/browser/ui/cocoa/fast_resize_view.h"
25 #import "chrome/browser/ui/cocoa/history_overlay_controller.h"
26 #import "chrome/browser/ui/cocoa/infobars/infobar_cocoa.h"
27 #import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
28 #import "chrome/browser/ui/cocoa/infobars/infobar_controller.h"
29 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
30 #import "chrome/browser/ui/cocoa/profiles/avatar_base_controller.h"
31 #import "chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller.h"
32 #import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h"
33 #include "chrome/browser/ui/extensions/application_launch.h"
34 #include "chrome/browser/ui/find_bar/find_bar.h"
35 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
36 #include "chrome/browser/ui/infobar_container_delegate.h"
37 #include "chrome/browser/ui/tabs/tab_strip_model.h"
38 #include "chrome/test/base/in_process_browser_test.h"
39 #include "chrome/test/base/testing_profile.h"
40 #include "components/infobars/core/simple_alert_infobar_delegate.h"
41 #include "content/public/browser/web_contents.h"
42 #include "content/public/test/test_utils.h"
43 #import "testing/gtest_mac.h"
44 #import "third_party/ocmock/OCMock/OCMock.h"
45 #import "ui/base/cocoa/nsview_additions.h"
46 #include "ui/gfx/animation/slide_animation.h"
48 namespace {
50 // Creates a mock of an NSWindow that has the given |frame|.
51 id MockWindowWithFrame(NSRect frame) {
52   id window = [OCMockObject mockForClass:[NSWindow class]];
53   NSValue* window_frame =
54       [NSValue valueWithBytes:&frame objCType:@encode(NSRect)];
55   [[[window stub] andReturnValue:window_frame] frame];
56   return window;
59 void CreateProfileCallback(const base::Closure& quit_closure,
60                            Profile* profile,
61                            Profile::CreateStatus status) {
62   EXPECT_TRUE(profile);
63   EXPECT_NE(Profile::CREATE_STATUS_LOCAL_FAIL, status);
64   EXPECT_NE(Profile::CREATE_STATUS_REMOTE_FAIL, status);
65   // This will be called multiple times. Wait until the profile is initialized
66   // fully to quit the loop.
67   if (status == Profile::CREATE_STATUS_INITIALIZED)
68     quit_closure.Run();
71 enum ViewID {
72   VIEW_ID_TOOLBAR,
73   VIEW_ID_BOOKMARK_BAR,
74   VIEW_ID_INFO_BAR,
75   VIEW_ID_FIND_BAR,
76   VIEW_ID_DOWNLOAD_SHELF,
77   VIEW_ID_TAB_CONTENT_AREA,
78   VIEW_ID_FULLSCREEN_FLOATING_BAR,
79   VIEW_ID_COUNT,
82 // Checks that no views draw on top of the supposedly exposed view.
83 class ViewExposedChecker {
84  public:
85   ViewExposedChecker() : below_exposed_view_(YES) {}
86   ~ViewExposedChecker() {}
88   void SetExceptions(NSArray* exceptions) {
89     exceptions_.reset([exceptions retain]);
90   }
92   // Checks that no views draw in front of |view|, with the exception of
93   // |exceptions|.
94   void CheckViewExposed(NSView* view) {
95     below_exposed_view_ = YES;
96     exposed_view_.reset([view retain]);
97     CheckViewsDoNotObscure([[[view window] contentView] superview]);
98   }
100  private:
101   // Checks that |view| does not draw on top of |exposed_view_|.
102   void CheckViewDoesNotObscure(NSView* view) {
103     NSRect viewWindowFrame = [view convertRect:[view bounds] toView:nil];
104     NSRect viewBeingVerifiedWindowFrame =
105         [exposed_view_ convertRect:[exposed_view_ bounds] toView:nil];
107     // The views do not intersect.
108     if (!NSIntersectsRect(viewBeingVerifiedWindowFrame, viewWindowFrame))
109       return;
111     // No view can be above the view being checked.
112     EXPECT_TRUE(below_exposed_view_);
114     // If |view| is a parent of |exposed_view_|, then there's nothing else
115     // to check.
116     NSView* parent = exposed_view_;
117     while (parent != nil) {
118       parent = [parent superview];
119       if (parent == view)
120         return;
121     }
123     if ([exposed_view_ layer])
124       return;
126     // If the view being verified doesn't have a layer, then no views that
127     // intersect it can have a layer.
128     if ([exceptions_ containsObject:view]) {
129       EXPECT_FALSE([view isOpaque]);
130       return;
131     }
133     EXPECT_TRUE(![view layer]) << [[view description] UTF8String] << " " <<
134         [NSStringFromRect(viewWindowFrame) UTF8String];
135   }
137   // Recursively checks that |view| and its subviews do not draw on top of
138   // |exposed_view_|. The recursion passes through all views in order of
139   // back-most in Z-order to front-most in Z-order.
140   void CheckViewsDoNotObscure(NSView* view) {
141     // If this is the view being checked, don't recurse into its subviews. All
142     // future views encountered in the recursion are in front of the view being
143     // checked.
144     if (view == exposed_view_) {
145       below_exposed_view_ = NO;
146       return;
147     }
149     CheckViewDoesNotObscure(view);
151     // Perform the recursion.
152     for (NSView* subview in [view subviews])
153       CheckViewsDoNotObscure(subview);
154   }
156   // The method CheckViewExposed() recurses through the views in the view
157   // hierarchy and checks that none of the views obscure |exposed_view_|.
158   base::scoped_nsobject<NSView> exposed_view_;
160   // While this flag is true, the views being recursed through are below
161   // |exposed_view_| in Z-order. After the recursion passes |exposed_view_|,
162   // this flag is set to false.
163   BOOL below_exposed_view_;
165   // Exceptions are allowed to overlap |exposed_view_|. Exceptions must still
166   // be Z-order behind |exposed_view_|.
167   base::scoped_nsobject<NSArray> exceptions_;
169   DISALLOW_COPY_AND_ASSIGN(ViewExposedChecker);
172 }  // namespace
174 @interface InfoBarContainerController(TestingAPI)
175 - (BOOL)isTopInfoBarAnimationRunning;
176 @end
178 @implementation InfoBarContainerController(TestingAPI)
179 - (BOOL)isTopInfoBarAnimationRunning {
180   InfoBarController* infoBarController = [infobarControllers_ objectAtIndex:0];
181   if (infoBarController) {
182     const gfx::SlideAnimation& infobarAnimation =
183         static_cast<const InfoBarCocoa*>(
184             infoBarController.infobar)->animation();
185     return infobarAnimation.is_animating();
186   }
187   return NO;
189 @end
191 class BrowserWindowControllerTest : public InProcessBrowserTest {
192  public:
193   BrowserWindowControllerTest() : InProcessBrowserTest() {
194   }
196   void SetUpOnMainThread() override {
197     [[controller() bookmarkBarController] setStateAnimationsEnabled:NO];
198     [[controller() bookmarkBarController] setInnerContentAnimationsEnabled:NO];
199   }
201   BrowserWindowController* controller() const {
202     return [BrowserWindowController browserWindowControllerForWindow:
203         browser()->window()->GetNativeWindow()];
204   }
206   static void ShowInfoBar(Browser* browser) {
207     SimpleAlertInfoBarDelegate::Create(
208         InfoBarService::FromWebContents(
209             browser->tab_strip_model()->GetActiveWebContents()),
210         0, base::string16(), false);
211   }
213   NSView* GetViewWithID(ViewID view_id) const {
214     switch (view_id) {
215       case VIEW_ID_FULLSCREEN_FLOATING_BAR:
216         return [controller() floatingBarBackingView];
217       case VIEW_ID_TOOLBAR:
218         return [[controller() toolbarController] view];
219       case VIEW_ID_BOOKMARK_BAR:
220         return [[controller() bookmarkBarController] view];
221       case VIEW_ID_INFO_BAR:
222         return [[controller() infoBarContainerController] view];
223       case VIEW_ID_FIND_BAR:
224         return [[controller() findBarCocoaController] view];
225       case VIEW_ID_DOWNLOAD_SHELF:
226         return [[controller() downloadShelf] view];
227       case VIEW_ID_TAB_CONTENT_AREA:
228         return [controller() tabContentArea];
229       default:
230         NOTREACHED();
231         return nil;
232     }
233   }
235   void VerifyZOrder(const std::vector<ViewID>& view_list) const {
236     std::vector<NSView*> visible_views;
237     for (size_t i = 0; i < view_list.size(); ++i) {
238       NSView* view = GetViewWithID(view_list[i]);
239       if ([view superview])
240         visible_views.push_back(view);
241     }
243     for (size_t i = 0; i < visible_views.size() - 1; ++i) {
244       NSView* bottom_view = visible_views[i];
245       NSView* top_view = visible_views[i + 1];
247       EXPECT_NSEQ([bottom_view superview], [top_view superview]);
248       EXPECT_TRUE([bottom_view cr_isBelowView:top_view]);
249     }
251     // Views not in |view_list| must either be nil or not parented.
252     for (size_t i = 0; i < VIEW_ID_COUNT; ++i) {
253       if (std::find(view_list.begin(), view_list.end(), i) == view_list.end()) {
254         NSView* view = GetViewWithID(static_cast<ViewID>(i));
255         EXPECT_TRUE(!view || ![view superview]);
256       }
257     }
258   }
260   CGFloat GetViewHeight(ViewID viewID) const {
261     CGFloat height = NSHeight([GetViewWithID(viewID) frame]);
262     if (viewID == VIEW_ID_INFO_BAR) {
263       height -= [[controller() infoBarContainerController]
264           overlappingTipHeight];
265     }
266     return height;
267   }
269   static void CheckTopInfoBarAnimation(
270       InfoBarContainerController* info_bar_container_controller,
271       const base::Closure& quit_task) {
272     if (![info_bar_container_controller isTopInfoBarAnimationRunning])
273       quit_task.Run();
274   }
276   static void CheckBookmarkBarAnimation(
277       BookmarkBarController* bookmark_bar_controller,
278       const base::Closure& quit_task) {
279     if (![bookmark_bar_controller isAnimationRunning])
280       quit_task.Run();
281   }
283   void WaitForTopInfoBarAnimationToFinish() {
284     scoped_refptr<content::MessageLoopRunner> runner =
285         new content::MessageLoopRunner;
287     base::Timer timer(false, true);
288     timer.Start(
289         FROM_HERE,
290         base::TimeDelta::FromMilliseconds(15),
291         base::Bind(&CheckTopInfoBarAnimation,
292                    [controller() infoBarContainerController],
293                    runner->QuitClosure()));
294     runner->Run();
295   }
297   void WaitForBookmarkBarAnimationToFinish() {
298     scoped_refptr<content::MessageLoopRunner> runner =
299         new content::MessageLoopRunner;
301     base::Timer timer(false, true);
302     timer.Start(
303         FROM_HERE,
304         base::TimeDelta::FromMilliseconds(15),
305         base::Bind(&CheckBookmarkBarAnimation,
306                    [controller() bookmarkBarController],
307                    runner->QuitClosure()));
308     runner->Run();
309   }
311   NSInteger GetExpectedTopInfoBarTipHeight() {
312     InfoBarContainerController* info_bar_container_controller =
313         [controller() infoBarContainerController];
314     CGFloat overlapping_tip_height =
315         [info_bar_container_controller overlappingTipHeight];
316     LocationBarViewMac* location_bar_view = [controller() locationBarBridge];
317     NSPoint icon_bottom = location_bar_view->GetPageInfoBubblePoint();
319     NSPoint info_bar_top = NSMakePoint(0,
320         NSHeight([info_bar_container_controller view].frame) -
321         overlapping_tip_height);
322     info_bar_top = [[info_bar_container_controller view]
323         convertPoint:info_bar_top toView:nil];
324     return icon_bottom.y - info_bar_top.y;
325   }
327   // Nothing should draw on top of the window controls.
328   void VerifyWindowControlsZOrder() {
329     NSWindow* window = [controller() window];
330     ViewExposedChecker checker;
332     // The exceptions are the contentView, chromeContentView and tabStripView,
333     // which are layer backed but transparent.
334     NSArray* exceptions = @[
335       [window contentView],
336       controller().chromeContentView,
337       controller().tabStripView
338     ];
339     checker.SetExceptions(exceptions);
341     checker.CheckViewExposed([window standardWindowButton:NSWindowCloseButton]);
342     checker.CheckViewExposed(
343         [window standardWindowButton:NSWindowMiniaturizeButton]);
344     checker.CheckViewExposed([window standardWindowButton:NSWindowZoomButton]);
346     // There is no fullscreen button on OSX 10.6 or OSX 10.10+.
347     NSView* view = [window standardWindowButton:NSWindowFullScreenButton];
348     if (view)
349       checker.CheckViewExposed(view);
350   }
352  private:
353   DISALLOW_COPY_AND_ASSIGN(BrowserWindowControllerTest);
356 // Tests that adding the first profile moves the Lion fullscreen button over
357 // correctly.
358 // DISABLED_ because it regularly times out: http://crbug.com/159002.
359 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
360                        DISABLED_ProfileAvatarFullscreenButton) {
361   if (base::mac::IsOSSnowLeopard())
362     return;
364   // Initialize the locals.
365   ProfileManager* profile_manager = g_browser_process->profile_manager();
366   ASSERT_TRUE(profile_manager);
368   NSWindow* window = browser()->window()->GetNativeWindow();
369   ASSERT_TRUE(window);
371   // With only one profile, the fullscreen button should be visible, but the
372   // avatar button should not.
373   EXPECT_EQ(1u, profile_manager->GetNumberOfProfiles());
375   NSButton* fullscreen_button =
376       [window standardWindowButton:NSWindowFullScreenButton];
377   EXPECT_TRUE(fullscreen_button);
378   EXPECT_FALSE([fullscreen_button isHidden]);
380   AvatarBaseController* avatar_controller =
381       [controller() avatarButtonController];
382   NSView* avatar = [avatar_controller view];
383   EXPECT_TRUE(avatar);
384   EXPECT_TRUE([avatar isHidden]);
386   // Create a profile asynchronously and run the loop until its creation
387   // is complete.
388   base::RunLoop run_loop;
390   ProfileManager::CreateCallback create_callback =
391       base::Bind(&CreateProfileCallback, run_loop.QuitClosure());
392   profile_manager->CreateProfileAsync(
393       profile_manager->user_data_dir().Append("test"),
394       create_callback,
395       base::ASCIIToUTF16("avatar_test"),
396       base::string16(),
397       std::string());
399   run_loop.Run();
401   // There should now be two profiles, and the avatar button and fullscreen
402   // button are both visible.
403   EXPECT_EQ(2u, profile_manager->GetNumberOfProfiles());
404   EXPECT_FALSE([avatar isHidden]);
405   EXPECT_FALSE([fullscreen_button isHidden]);
406   EXPECT_EQ([avatar window], [fullscreen_button window]);
408   // Make sure the visual order of the buttons is correct and that they don't
409   // overlap.
410   NSRect avatar_frame = [avatar frame];
411   NSRect fullscreen_frame = [fullscreen_button frame];
413   EXPECT_LT(NSMinX(fullscreen_frame), NSMinX(avatar_frame));
414   EXPECT_LT(NSMaxX(fullscreen_frame), NSMinX(avatar_frame));
417 // Verify that in non-Instant normal mode that the find bar and download shelf
418 // are above the content area. Everything else should be below it.
419 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, ZOrderNormal) {
420   browser()->GetFindBarController();  // add find bar
422   std::vector<ViewID> view_list;
423   view_list.push_back(VIEW_ID_DOWNLOAD_SHELF);
424   view_list.push_back(VIEW_ID_BOOKMARK_BAR);
425   view_list.push_back(VIEW_ID_TOOLBAR);
426   view_list.push_back(VIEW_ID_INFO_BAR);
427   view_list.push_back(VIEW_ID_TAB_CONTENT_AREA);
428   view_list.push_back(VIEW_ID_FIND_BAR);
429   VerifyZOrder(view_list);
431   [controller() showOverlay];
432   [controller() removeOverlay];
433   VerifyZOrder(view_list);
435   [controller() enterImmersiveFullscreen];
436   [controller() exitImmersiveFullscreen];
437   VerifyZOrder(view_list);
440 // Verify that in non-Instant presentation mode that the info bar is below the
441 // content are and everything else is above it.
442 // DISABLED due to flaky failures on trybots. http://crbug.com/178778
443 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
444                        DISABLED_ZOrderPresentationMode) {
445   chrome::ToggleFullscreenMode(browser());
446   browser()->GetFindBarController();  // add find bar
448   std::vector<ViewID> view_list;
449   view_list.push_back(VIEW_ID_INFO_BAR);
450   view_list.push_back(VIEW_ID_TAB_CONTENT_AREA);
451   view_list.push_back(VIEW_ID_FULLSCREEN_FLOATING_BAR);
452   view_list.push_back(VIEW_ID_BOOKMARK_BAR);
453   view_list.push_back(VIEW_ID_TOOLBAR);
454   view_list.push_back(VIEW_ID_FIND_BAR);
455   view_list.push_back(VIEW_ID_DOWNLOAD_SHELF);
456   VerifyZOrder(view_list);
459 // Verify that if the fullscreen floating bar view is below the tab content area
460 // then calling |updateSubviewZOrder:| will correctly move back above.
461 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
462                        DISABLED_FloatingBarBelowContentView) {
463   // TODO(kbr): re-enable: http://crbug.com/222296
464   if (base::mac::IsOSMountainLionOrLater())
465     return;
467   chrome::ToggleFullscreenMode(browser());
469   NSView* fullscreen_floating_bar =
470       GetViewWithID(VIEW_ID_FULLSCREEN_FLOATING_BAR);
471   [fullscreen_floating_bar removeFromSuperview];
472   [[[controller() window] contentView] addSubview:fullscreen_floating_bar
473                                        positioned:NSWindowBelow
474                                        relativeTo:nil];
475   [controller() updateSubviewZOrder];
477   std::vector<ViewID> view_list;
478   view_list.push_back(VIEW_ID_INFO_BAR);
479   view_list.push_back(VIEW_ID_TAB_CONTENT_AREA);
480   view_list.push_back(VIEW_ID_FULLSCREEN_FLOATING_BAR);
481   view_list.push_back(VIEW_ID_BOOKMARK_BAR);
482   view_list.push_back(VIEW_ID_TOOLBAR);
483   view_list.push_back(VIEW_ID_DOWNLOAD_SHELF);
484   VerifyZOrder(view_list);
487 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, SheetPosition) {
488   ASSERT_TRUE([controller() isKindOfClass:[BrowserWindowController class]]);
489   EXPECT_TRUE([controller() isTabbedWindow]);
490   EXPECT_TRUE([controller() hasTabStrip]);
491   EXPECT_FALSE([controller() hasTitleBar]);
492   EXPECT_TRUE([controller() hasToolbar]);
493   EXPECT_FALSE([controller() isBookmarkBarVisible]);
495   id sheet = MockWindowWithFrame(NSMakeRect(0, 0, 300, 200));
496   NSWindow* window = browser()->window()->GetNativeWindow();
497   NSRect contentFrame = [[window contentView] frame];
498   NSRect defaultLocation =
499       NSMakeRect(0, NSMaxY(contentFrame), NSWidth(contentFrame), 0);
501   NSRect sheetLocation = [controller() window:window
502                             willPositionSheet:nil
503                                     usingRect:defaultLocation];
504   NSRect toolbarFrame = [[[controller() toolbarController] view] frame];
505   EXPECT_EQ(NSMinY(toolbarFrame), NSMinY(sheetLocation));
507   // Open sheet with normal browser window, persistent bookmark bar.
508   chrome::ToggleBookmarkBarWhenVisible(browser()->profile());
509   EXPECT_TRUE([controller() isBookmarkBarVisible]);
510   sheetLocation = [controller() window:window
511                      willPositionSheet:sheet
512                              usingRect:defaultLocation];
513   NSRect bookmarkBarFrame = [[[controller() bookmarkBarController] view] frame];
514   EXPECT_EQ(NSMinY(bookmarkBarFrame), NSMinY(sheetLocation));
516   // If the sheet is too large, it should be positioned at the top of the
517   // window.
518   sheet = MockWindowWithFrame(NSMakeRect(0, 0, 300, 2000));
519   sheetLocation = [controller() window:window
520                      willPositionSheet:sheet
521                              usingRect:defaultLocation];
522   EXPECT_EQ(NSHeight([window frame]), NSMinY(sheetLocation));
524   // Reset the sheet's size.
525   sheet = MockWindowWithFrame(NSMakeRect(0, 0, 300, 200));
527   // Make sure the profile does not have the bookmark visible so that
528   // we'll create the shortcut window without the bookmark bar.
529   chrome::ToggleBookmarkBarWhenVisible(browser()->profile());
530   // Open application mode window.
531   OpenAppShortcutWindow(browser()->profile(), GURL("about:blank"));
532   Browser* popup_browser = BrowserList::GetInstance(
533       chrome::GetActiveDesktop())->GetLastActive();
534   NSWindow* popupWindow = popup_browser->window()->GetNativeWindow();
535   BrowserWindowController* popupController =
536       [BrowserWindowController browserWindowControllerForWindow:popupWindow];
537   ASSERT_TRUE([popupController isKindOfClass:[BrowserWindowController class]]);
538   EXPECT_FALSE([popupController isTabbedWindow]);
539   EXPECT_FALSE([popupController hasTabStrip]);
540   EXPECT_TRUE([popupController hasTitleBar]);
541   EXPECT_FALSE([popupController isBookmarkBarVisible]);
542   EXPECT_FALSE([popupController hasToolbar]);
544   // Open sheet in an application window.
545   [popupController showWindow:nil];
546   sheetLocation = [popupController window:popupWindow
547                         willPositionSheet:sheet
548                                 usingRect:defaultLocation];
549   EXPECT_EQ(NSHeight([[popupWindow contentView] frame]), NSMinY(sheetLocation));
551   // Close the application window.
552   popup_browser->tab_strip_model()->CloseSelectedTabs();
553   [popupController close];
556 // Verify that the info bar tip is hidden when the toolbar is not visible.
557 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
558                        InfoBarTipHiddenForWindowWithoutToolbar) {
559   ShowInfoBar(browser());
560   EXPECT_FALSE(
561       [[controller() infoBarContainerController] shouldSuppressTopInfoBarTip]);
563   OpenAppShortcutWindow(browser()->profile(), GURL("about:blank"));
564   Browser* popup_browser = BrowserList::GetInstance(
565       chrome::HOST_DESKTOP_TYPE_NATIVE)->GetLastActive();
566   NSWindow* popupWindow = popup_browser->window()->GetNativeWindow();
567   BrowserWindowController* popupController =
568       [BrowserWindowController browserWindowControllerForWindow:popupWindow];
569   EXPECT_FALSE([popupController hasToolbar]);
571   // Show infobar for controller.
572   ShowInfoBar(popup_browser);
573   EXPECT_TRUE(
574       [[popupController infoBarContainerController]
575           shouldSuppressTopInfoBarTip]);
578 // Tests that status bubble's base frame does move when devTools are docked.
579 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
580                        StatusBubblePositioning) {
581   NSPoint origin = [controller() statusBubbleBaseFrame].origin;
583   DevToolsWindow* devtools_window =
584       DevToolsWindowTesting::OpenDevToolsWindowSync(browser(), true);
585   DevToolsWindowTesting::Get(devtools_window)->SetInspectedPageBounds(
586       gfx::Rect(10, 10, 100, 100));
588   NSPoint originWithDevTools = [controller() statusBubbleBaseFrame].origin;
589   EXPECT_NSNE(origin, originWithDevTools);
591   DevToolsWindowTesting::CloseDevToolsWindowSync(devtools_window);
594 // Tests that top infobar tip is streched when bookmark bar becomes SHOWN/HIDDEN
595 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
596                        InfoBarTipStretchedWhenBookmarkBarStatusChanged) {
597   EXPECT_FALSE([controller() isBookmarkBarVisible]);
598   ShowInfoBar(browser());
599   // The infobar tip is animated during the infobar is being added, wait until
600   // it completes.
601   WaitForTopInfoBarAnimationToFinish();
603   EXPECT_FALSE([[controller() infoBarContainerController]
604       shouldSuppressTopInfoBarTip]);
606   NSInteger max_tip_height =
607       InfoBarContainerDelegate::kMaximumArrowTargetHeight +
608           InfoBarContainerDelegate::kSeparatorLineHeight;
610   chrome::ExecuteCommand(browser(), IDC_SHOW_BOOKMARK_BAR);
611   WaitForBookmarkBarAnimationToFinish();
612   EXPECT_TRUE([controller() isBookmarkBarVisible]);
613   EXPECT_EQ(std::min(GetExpectedTopInfoBarTipHeight(), max_tip_height),
614             [[controller() infoBarContainerController] overlappingTipHeight]);
616   chrome::ExecuteCommand(browser(), IDC_SHOW_BOOKMARK_BAR);
617   WaitForBookmarkBarAnimationToFinish();
618   EXPECT_FALSE([controller() isBookmarkBarVisible]);
619   EXPECT_EQ(std::min(GetExpectedTopInfoBarTipHeight(), max_tip_height),
620             [[controller() infoBarContainerController] overlappingTipHeight]);
623 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, TrafficLightZOrder) {
624   // Verify z order immediately after creation.
625   VerifyWindowControlsZOrder();
627   // Verify z order in and out of overlay.
628   [controller() showOverlay];
629   VerifyWindowControlsZOrder();
630   [controller() removeOverlay];
631   VerifyWindowControlsZOrder();
633   // Toggle immersive fullscreen, then verify z order. In immersive fullscreen,
634   // there are no window controls.
635   [controller() enterImmersiveFullscreen];
636   [controller() exitImmersiveFullscreen];
637   VerifyWindowControlsZOrder();