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