[Metrics] Make MetricsStateManager take a callback param to check if UMA is enabled.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / browser_window_controller_browsertest.mm
blobe75d5dc60eca79c1d01769ec125c137c43fc5b18
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/run_loop.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/devtools/devtools_window.h"
12 #include "chrome/browser/infobars/infobar_service.h"
13 #include "chrome/browser/infobars/simple_alert_infobar_delegate.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/profiles/profile_manager.h"
16 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_commands.h"
19 #include "chrome/browser/ui/browser_list.h"
20 #include "chrome/browser/ui/browser_window.h"
21 #include "chrome/browser/ui/cocoa/browser_window_cocoa.h"
22 #import "chrome/browser/ui/cocoa/browser_window_controller_private.h"
23 #import "chrome/browser/ui/cocoa/fast_resize_view.h"
24 #import "chrome/browser/ui/cocoa/history_overlay_controller.h"
25 #import "chrome/browser/ui/cocoa/infobars/infobar_cocoa.h"
26 #import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
27 #import "chrome/browser/ui/cocoa/nsview_additions.h"
28 #import "chrome/browser/ui/cocoa/profiles/avatar_base_controller.h"
29 #import "chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller.h"
30 #include "chrome/browser/ui/extensions/application_launch.h"
31 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
32 #include "chrome/browser/ui/find_bar/find_bar.h"
33 #include "chrome/browser/ui/tabs/tab_strip_model.h"
34 #include "chrome/test/base/in_process_browser_test.h"
35 #include "chrome/test/base/testing_profile.h"
36 #include "content/public/browser/web_contents.h"
37 #import "testing/gtest_mac.h"
39 namespace {
41 #if !defined(MAC_OS_X_VERSION_10_7) || \
42     MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
43 enum {
44   NSWindowDocumentVersionsButton = 6,
45   NSWindowFullScreenButton
47 #endif  // MAC_OS_X_VERSION_10_7
49 void CreateProfileCallback(const base::Closure& quit_closure,
50                            Profile* profile,
51                            Profile::CreateStatus status) {
52   EXPECT_TRUE(profile);
53   EXPECT_NE(Profile::CREATE_STATUS_LOCAL_FAIL, status);
54   EXPECT_NE(Profile::CREATE_STATUS_REMOTE_FAIL, status);
55   // This will be called multiple times. Wait until the profile is initialized
56   // fully to quit the loop.
57   if (status == Profile::CREATE_STATUS_INITIALIZED)
58     quit_closure.Run();
61 enum ViewID {
62   VIEW_ID_TOOLBAR,
63   VIEW_ID_BOOKMARK_BAR,
64   VIEW_ID_INFO_BAR,
65   VIEW_ID_FIND_BAR,
66   VIEW_ID_DOWNLOAD_SHELF,
67   VIEW_ID_TAB_CONTENT_AREA,
68   VIEW_ID_FULLSCREEN_FLOATING_BAR,
69   VIEW_ID_COUNT,
72 }  // namespace
74 class BrowserWindowControllerTest : public InProcessBrowserTest {
75  public:
76   BrowserWindowControllerTest() : InProcessBrowserTest() {
77   }
79   virtual void SetUpOnMainThread() OVERRIDE {
80     [[controller() bookmarkBarController] setStateAnimationsEnabled:NO];
81     [[controller() bookmarkBarController] setInnerContentAnimationsEnabled:NO];
82   }
84   BrowserWindowController* controller() const {
85     return [BrowserWindowController browserWindowControllerForWindow:
86         browser()->window()->GetNativeWindow()];
87   }
89   static void ShowInfoBar(Browser* browser) {
90     SimpleAlertInfoBarDelegate::Create(
91         InfoBarService::FromWebContents(
92             browser->tab_strip_model()->GetActiveWebContents()),
93         0, base::string16(), false);
94   }
96   NSView* GetViewWithID(ViewID view_id) const {
97     switch (view_id) {
98       case VIEW_ID_FULLSCREEN_FLOATING_BAR:
99         return [controller() floatingBarBackingView];
100       case VIEW_ID_TOOLBAR:
101         return [[controller() toolbarController] view];
102       case VIEW_ID_BOOKMARK_BAR:
103         return [[controller() bookmarkBarController] view];
104       case VIEW_ID_INFO_BAR:
105         return [[controller() infoBarContainerController] view];
106       case VIEW_ID_FIND_BAR:
107         return [[controller() findBarCocoaController] view];
108       case VIEW_ID_DOWNLOAD_SHELF:
109         return [[controller() downloadShelf] view];
110       case VIEW_ID_TAB_CONTENT_AREA:
111         return [controller() tabContentArea];
112       default:
113         NOTREACHED();
114         return nil;
115     }
116   }
118   void VerifyZOrder(const std::vector<ViewID>& view_list) const {
119     for (size_t i = 0; i < view_list.size() - 1; ++i) {
120       NSView* bottom_view = GetViewWithID(view_list[i]);
121       NSView* top_view = GetViewWithID(view_list[i + 1]);
122       EXPECT_NSEQ([bottom_view superview], [top_view superview]);
123       EXPECT_TRUE([bottom_view cr_isBelowView:top_view]);
124     }
126     // Views not in |view_list| must either be nil or not parented.
127     for (size_t i = 0; i < VIEW_ID_COUNT; ++i) {
128       if (std::find(view_list.begin(), view_list.end(), i) == view_list.end()) {
129         NSView* view = GetViewWithID(static_cast<ViewID>(i));
130         EXPECT_TRUE(!view || ![view superview]);
131       }
132     }
133   }
135   CGFloat GetViewHeight(ViewID viewID) const {
136     CGFloat height = NSHeight([GetViewWithID(viewID) frame]);
137     if (viewID == VIEW_ID_INFO_BAR) {
138       height -= [[controller() infoBarContainerController]
139           overlappingTipHeight];
140     }
141     return height;
142   }
144   void SetDevToolsWindowContentsBounds(
145       DevToolsWindow* window, const gfx::Rect& bounds) {
146     window->SetInspectedPageBounds(bounds);
147   }
149  private:
150   DISALLOW_COPY_AND_ASSIGN(BrowserWindowControllerTest);
153 // Tests that adding the first profile moves the Lion fullscreen button over
154 // correctly.
155 // DISABLED_ because it regularly times out: http://crbug.com/159002.
156 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
157                        DISABLED_ProfileAvatarFullscreenButton) {
158   if (base::mac::IsOSSnowLeopard())
159     return;
161   // Initialize the locals.
162   ProfileManager* profile_manager = g_browser_process->profile_manager();
163   ASSERT_TRUE(profile_manager);
165   NSWindow* window = browser()->window()->GetNativeWindow();
166   ASSERT_TRUE(window);
168   // With only one profile, the fullscreen button should be visible, but the
169   // avatar button should not.
170   EXPECT_EQ(1u, profile_manager->GetNumberOfProfiles());
172   NSButton* fullscreen_button =
173       [window standardWindowButton:NSWindowFullScreenButton];
174   EXPECT_TRUE(fullscreen_button);
175   EXPECT_FALSE([fullscreen_button isHidden]);
177   AvatarBaseController* avatar_controller =
178       [controller() avatarButtonController];
179   NSView* avatar = [avatar_controller view];
180   EXPECT_TRUE(avatar);
181   EXPECT_TRUE([avatar isHidden]);
183   // Create a profile asynchronously and run the loop until its creation
184   // is complete.
185   base::RunLoop run_loop;
187   ProfileManager::CreateCallback create_callback =
188       base::Bind(&CreateProfileCallback, run_loop.QuitClosure());
189   profile_manager->CreateProfileAsync(
190       profile_manager->user_data_dir().Append("test"),
191       create_callback,
192       base::ASCIIToUTF16("avatar_test"),
193       base::string16(),
194       std::string());
196   run_loop.Run();
198   // There should now be two profiles, and the avatar button and fullscreen
199   // button are both visible.
200   EXPECT_EQ(2u, profile_manager->GetNumberOfProfiles());
201   EXPECT_FALSE([avatar isHidden]);
202   EXPECT_FALSE([fullscreen_button isHidden]);
203   EXPECT_EQ([avatar window], [fullscreen_button window]);
205   // Make sure the visual order of the buttons is correct and that they don't
206   // overlap.
207   NSRect avatar_frame = [avatar frame];
208   NSRect fullscreen_frame = [fullscreen_button frame];
210   EXPECT_LT(NSMinX(fullscreen_frame), NSMinX(avatar_frame));
211   EXPECT_LT(NSMaxX(fullscreen_frame), NSMinX(avatar_frame));
214 // Verify that in non-Instant normal mode that the find bar and download shelf
215 // are above the content area. Everything else should be below it.
216 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, ZOrderNormal) {
217   browser()->GetFindBarController();  // add find bar
219   std::vector<ViewID> view_list;
220   view_list.push_back(VIEW_ID_BOOKMARK_BAR);
221   view_list.push_back(VIEW_ID_TOOLBAR);
222   view_list.push_back(VIEW_ID_INFO_BAR);
223   view_list.push_back(VIEW_ID_TAB_CONTENT_AREA);
224   view_list.push_back(VIEW_ID_FIND_BAR);
225   view_list.push_back(VIEW_ID_DOWNLOAD_SHELF);
226   VerifyZOrder(view_list);
229 // Verify that in non-Instant presentation mode that the info bar is below the
230 // content are and everything else is above it.
231 // DISABLED due to flaky failures on trybots. http://crbug.com/178778
232 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
233                        DISABLED_ZOrderPresentationMode) {
234   chrome::ToggleFullscreenMode(browser());
235   browser()->GetFindBarController();  // add find bar
237   std::vector<ViewID> view_list;
238   view_list.push_back(VIEW_ID_INFO_BAR);
239   view_list.push_back(VIEW_ID_TAB_CONTENT_AREA);
240   view_list.push_back(VIEW_ID_FULLSCREEN_FLOATING_BAR);
241   view_list.push_back(VIEW_ID_BOOKMARK_BAR);
242   view_list.push_back(VIEW_ID_TOOLBAR);
243   view_list.push_back(VIEW_ID_FIND_BAR);
244   view_list.push_back(VIEW_ID_DOWNLOAD_SHELF);
245   VerifyZOrder(view_list);
248 // Verify that if the fullscreen floating bar view is below the tab content area
249 // then calling |updateSubviewZOrder:| will correctly move back above.
250 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
251                        DISABLED_FloatingBarBelowContentView) {
252   // TODO(kbr): re-enable: http://crbug.com/222296
253   if (base::mac::IsOSMountainLionOrLater())
254     return;
256   chrome::ToggleFullscreenMode(browser());
258   NSView* fullscreen_floating_bar =
259       GetViewWithID(VIEW_ID_FULLSCREEN_FLOATING_BAR);
260   [fullscreen_floating_bar removeFromSuperview];
261   [[[controller() window] contentView] addSubview:fullscreen_floating_bar
262                                        positioned:NSWindowBelow
263                                        relativeTo:nil];
264   [controller() updateSubviewZOrder:[controller() inPresentationMode]];
266   std::vector<ViewID> view_list;
267   view_list.push_back(VIEW_ID_INFO_BAR);
268   view_list.push_back(VIEW_ID_TAB_CONTENT_AREA);
269   view_list.push_back(VIEW_ID_FULLSCREEN_FLOATING_BAR);
270   view_list.push_back(VIEW_ID_BOOKMARK_BAR);
271   view_list.push_back(VIEW_ID_TOOLBAR);
272   view_list.push_back(VIEW_ID_DOWNLOAD_SHELF);
273   VerifyZOrder(view_list);
276 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, SheetPosition) {
277   ASSERT_TRUE([controller() isKindOfClass:[BrowserWindowController class]]);
278   EXPECT_TRUE([controller() isTabbedWindow]);
279   EXPECT_TRUE([controller() hasTabStrip]);
280   EXPECT_FALSE([controller() hasTitleBar]);
281   EXPECT_TRUE([controller() hasToolbar]);
282   EXPECT_FALSE([controller() isBookmarkBarVisible]);
284   NSRect defaultAlertFrame = NSMakeRect(0, 0, 300, 200);
285   NSWindow* window = browser()->window()->GetNativeWindow();
286   NSRect alertFrame = [controller() window:window
287                          willPositionSheet:nil
288                                  usingRect:defaultAlertFrame];
289   NSRect toolbarFrame = [[[controller() toolbarController] view] frame];
290   EXPECT_EQ(NSMinY(alertFrame), NSMinY(toolbarFrame));
292   // Open sheet with normal browser window, persistent bookmark bar.
293   chrome::ToggleBookmarkBarWhenVisible(browser()->profile());
294   EXPECT_TRUE([controller() isBookmarkBarVisible]);
295   alertFrame = [controller() window:window
296                   willPositionSheet:nil
297                           usingRect:defaultAlertFrame];
298   NSRect bookmarkBarFrame = [[[controller() bookmarkBarController] view] frame];
299   EXPECT_EQ(NSMinY(alertFrame), NSMinY(bookmarkBarFrame));
301   // Make sure the profile does not have the bookmark visible so that
302   // we'll create the shortcut window without the bookmark bar.
303   chrome::ToggleBookmarkBarWhenVisible(browser()->profile());
304   // Open application mode window.
305   OpenAppShortcutWindow(browser()->profile(), GURL("about:blank"));
306   Browser* popup_browser = BrowserList::GetInstance(
307       chrome::GetActiveDesktop())->GetLastActive();
308   NSWindow* popupWindow = popup_browser->window()->GetNativeWindow();
309   BrowserWindowController* popupController =
310       [BrowserWindowController browserWindowControllerForWindow:popupWindow];
311   ASSERT_TRUE([popupController isKindOfClass:[BrowserWindowController class]]);
312   EXPECT_FALSE([popupController isTabbedWindow]);
313   EXPECT_FALSE([popupController hasTabStrip]);
314   EXPECT_TRUE([popupController hasTitleBar]);
315   EXPECT_FALSE([popupController isBookmarkBarVisible]);
316   EXPECT_FALSE([popupController hasToolbar]);
318   // Open sheet in an application window.
319   [popupController showWindow:nil];
320   alertFrame = [popupController window:popupWindow
321                      willPositionSheet:nil
322                              usingRect:defaultAlertFrame];
323   EXPECT_EQ(NSMinY(alertFrame),
324             NSHeight([[popupWindow contentView] frame]) -
325             defaultAlertFrame.size.height);
327   // Close the application window.
328   popup_browser->tab_strip_model()->CloseSelectedTabs();
329   [popupController close];
332 // Verify that the info bar tip is hidden when the toolbar is not visible.
333 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
334                        InfoBarTipHiddenForWindowWithoutToolbar) {
335   ShowInfoBar(browser());
336   EXPECT_FALSE(
337       [[controller() infoBarContainerController] shouldSuppressTopInfoBarTip]);
339   OpenAppShortcutWindow(browser()->profile(), GURL("about:blank"));
340   Browser* popup_browser = BrowserList::GetInstance(
341       chrome::HOST_DESKTOP_TYPE_NATIVE)->GetLastActive();
342   NSWindow* popupWindow = popup_browser->window()->GetNativeWindow();
343   BrowserWindowController* popupController =
344       [BrowserWindowController browserWindowControllerForWindow:popupWindow];
345   EXPECT_FALSE([popupController hasToolbar]);
347   // Show infobar for controller.
348   ShowInfoBar(popup_browser);
349   EXPECT_TRUE(
350       [[popupController infoBarContainerController]
351           shouldSuppressTopInfoBarTip]);
354 // Verify that AllowOverlappingViews is set while the history overlay is
355 // visible.
356 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
357                        AllowOverlappingViewsHistoryOverlay) {
358   content::WebContents* web_contents =
359       browser()->tab_strip_model()->GetActiveWebContents();
360   EXPECT_TRUE(web_contents->GetAllowOverlappingViews());
362   base::scoped_nsobject<HistoryOverlayController> overlay(
363       [[HistoryOverlayController alloc] initForMode:kHistoryOverlayModeBack]);
364   [overlay showPanelForView:web_contents->GetNativeView()];
365   EXPECT_TRUE(web_contents->GetAllowOverlappingViews());
367   overlay.reset();
368   EXPECT_TRUE(web_contents->GetAllowOverlappingViews());
371 // Tests that status bubble's base frame does move when devTools are docked.
372 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
373                        StatusBubblePositioning) {
374   NSPoint origin = [controller() statusBubbleBaseFrame].origin;
376   DevToolsWindow* devtools_window = DevToolsWindow::OpenDevToolsWindowForTest(
377       browser(), true);
378   SetDevToolsWindowContentsBounds(devtools_window, gfx::Rect(10, 10, 100, 100));
380   NSPoint originWithDevTools = [controller() statusBubbleBaseFrame].origin;
381   EXPECT_FALSE(NSEqualPoints(origin, originWithDevTools));