- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / frame / immersive_mode_controller_ash_unittest.cc
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/immersive_mode_controller_ash.h"
6
7 #include "ash/display/display_manager.h"
8 #include "ash/root_window_controller.h"
9 #include "ash/shelf/shelf_layout_manager.h"
10 #include "ash/shelf/shelf_types.h"
11 #include "ash/shell.h"
12 #include "ash/test/ash_test_base.h"
13 #include "chrome/app/chrome_command_ids.h"
14 #include "chrome/browser/ui/browser_commands.h"
15 #include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
16 #include "chrome/browser/ui/fullscreen/fullscreen_controller_test.h"
17 #include "chrome/browser/ui/views/frame/browser_view.h"
18 #include "chrome/browser/ui/views/frame/test_with_browser_view.h"
19 #include "chrome/browser/ui/views/frame/top_container_view.h"
20 #include "chrome/browser/ui/views/tabs/tab_strip.h"
21 #include "chrome/browser/ui/views/toolbar_view.h"
22 #include "ui/aura/client/cursor_client.h"
23 #include "ui/aura/env.h"
24 #include "ui/aura/root_window.h"
25 #include "ui/aura/test/event_generator.h"
26 #include "ui/aura/window.h"
27 #include "ui/gfx/animation/slide_animation.h"
28 #include "ui/views/bubble/bubble_delegate.h"
29 #include "ui/views/controls/webview/webview.h"
30
31 // For now, immersive fullscreen is Chrome OS only.
32 #if defined(OS_CHROMEOS)
33
34 /////////////////////////////////////////////////////////////////////////////
35
36 class MockImmersiveModeControllerDelegate
37     : public ImmersiveModeController::Delegate {
38  public:
39   MockImmersiveModeControllerDelegate() : immersive_style_(false) {}
40   virtual ~MockImmersiveModeControllerDelegate() {}
41
42   bool immersive_style() const { return immersive_style_; }
43
44   // ImmersiveModeController::Delegate overrides:
45   virtual FullscreenController* GetFullscreenController() OVERRIDE {
46     return NULL;
47   }
48   virtual void FullscreenStateChanged() OVERRIDE {}
49   virtual void SetImmersiveStyle(bool immersive) OVERRIDE {
50     immersive_style_ = immersive;
51   }
52   virtual content::WebContents* GetWebContents() OVERRIDE {
53     return NULL;
54   }
55
56  private:
57   bool immersive_style_;
58
59   DISALLOW_COPY_AND_ASSIGN(MockImmersiveModeControllerDelegate);
60 };
61
62 /////////////////////////////////////////////////////////////////////////////
63
64 class ImmersiveModeControllerAshTest : public ash::test::AshTestBase {
65  public:
66   enum Modality {
67     MODALITY_MOUSE,
68     MODALITY_TOUCH,
69     MODALITY_GESTURE
70   };
71
72   ImmersiveModeControllerAshTest() : widget_(NULL), top_container_(NULL) {}
73   virtual ~ImmersiveModeControllerAshTest() {}
74
75   ImmersiveModeControllerAsh* controller() { return controller_.get(); }
76   views::View* top_container() { return top_container_; }
77   MockImmersiveModeControllerDelegate* delegate() { return delegate_.get(); }
78
79   // Access to private data from the controller.
80   bool top_edge_hover_timer_running() const {
81     return controller_->top_edge_hover_timer_.IsRunning();
82   }
83   int mouse_x_when_hit_top() const {
84     return controller_->mouse_x_when_hit_top_in_screen_;
85   }
86
87   // ash::test::AshTestBase overrides:
88   virtual void SetUp() OVERRIDE {
89     ash::test::AshTestBase::SetUp();
90
91     controller_.reset(new ImmersiveModeControllerAsh);
92     delegate_.reset(new MockImmersiveModeControllerDelegate);
93
94     widget_ = new views::Widget();
95     views::Widget::InitParams params;
96     params.context = CurrentContext();
97     params.bounds = gfx::Rect(0, 0, 500, 500);
98     widget_->Init(params);
99     widget_->Show();
100
101     top_container_ = new views::View();
102     top_container_->SetBounds(0, 0, 500, 100);
103     top_container_->set_focusable(true);
104
105     widget_->GetContentsView()->AddChildView(top_container_);
106
107     controller_->Init(delegate_.get(), widget_, top_container_);
108     SetAnimationsDisabled(true);
109
110     // The mouse is moved so that it is not over |top_container_| by
111     // AshTestBase.
112   }
113
114   // Enable or disable the immersive mode controller's animations. When the
115   // immersive mode controller's animations are disabled, some behavior is
116   // slightly different. In particular, the behavior is different when there
117   // is a transfer in which lock keeps the top-of-window views revealed (eg
118   // bubble keeps top-of-window views revealed -> mouse keeps top-of-window
119   // views revealed). It is necessary to temparily enable the immersive
120   // controller's animations to get the correct behavior in tests.
121   void SetAnimationsDisabled(bool disabled) {
122     controller_->animations_disabled_for_test_ = disabled;
123     // Force any in progress animations to finish.
124     if (disabled)
125       controller_->animation_->End();
126   }
127
128   // Attempt to reveal the top-of-window views via |modality|.
129   // The top-of-window views can only be revealed via mouse hover or a gesture.
130   void AttemptReveal(Modality modality) {
131     ASSERT_NE(modality, MODALITY_TOUCH);
132     AttemptRevealStateChange(true, modality);
133   }
134
135   // Attempt to unreveal the top-of-window views via |modality|. The
136   // top-of-window views can be unrevealed via any modality.
137   void AttemptUnreveal(Modality modality) {
138     AttemptRevealStateChange(false, modality);
139   }
140
141   // Sets whether the mouse is hovered above |top_container_|.
142   // SetHovered(true) moves the mouse over the |top_container_| but does not
143   // move it to the top of the screen so will not initiate a reveal.
144   void SetHovered(bool is_mouse_hovered) {
145     MoveMouse(0, is_mouse_hovered ? 10 : top_container_->height() + 100);
146   }
147
148   // Move the mouse to the given coordinates. The coordinates should be in
149   // |top_container_| coordinates.
150   void MoveMouse(int x, int y) {
151     gfx::Point screen_position(x, y);
152     views::View::ConvertPointToScreen(top_container_, &screen_position);
153     GetEventGenerator().MoveMouseTo(screen_position.x(), screen_position.y());
154
155     // If the top edge timer started running as a result of the mouse move, run
156     // the task which occurs after the timer delay. This reveals the
157     // top-of-window views synchronously if the mouse is hovered at the top of
158     // the screen.
159     if (controller()->top_edge_hover_timer_.IsRunning()) {
160       controller()->top_edge_hover_timer_.user_task().Run();
161       controller()->top_edge_hover_timer_.Stop();
162     }
163   }
164
165  private:
166   // Attempt to change the revealed state to |revealed| via |modality|.
167   void AttemptRevealStateChange(bool revealed, Modality modality) {
168     // Compute the event position in |top_container_| coordinates.
169     gfx::Point event_position(0, revealed ? 0 : top_container_->height() + 100);
170     switch (modality) {
171       case MODALITY_MOUSE: {
172         MoveMouse(event_position.x(), event_position.y());
173         break;
174       }
175       case MODALITY_TOUCH: {
176         gfx::Point screen_position = event_position;
177         views::View::ConvertPointToScreen(top_container_, &screen_position);
178
179         aura::test::EventGenerator& event_generator(GetEventGenerator());
180         event_generator.MoveTouch(event_position);
181         event_generator.PressTouch();
182         event_generator.ReleaseTouch();
183         break;
184       }
185       case MODALITY_GESTURE: {
186         aura::client::GetCursorClient(CurrentContext())->DisableMouseEvents();
187         ImmersiveModeControllerAsh::SwipeType swipe_type = revealed ?
188             ImmersiveModeControllerAsh::SWIPE_OPEN :
189             ImmersiveModeControllerAsh::SWIPE_CLOSE;
190         controller_->UpdateRevealedLocksForSwipe(swipe_type);
191         break;
192       }
193     }
194   }
195
196   scoped_ptr<ImmersiveModeControllerAsh> controller_;
197   scoped_ptr<MockImmersiveModeControllerDelegate> delegate_;
198   views::Widget* widget_;  // Owned by the native widget.
199   views::View* top_container_;  // Owned by |root_view_|.
200
201   DISALLOW_COPY_AND_ASSIGN(ImmersiveModeControllerAshTest);
202 };
203
204 // Test of initial state and basic functionality.
205 TEST_F(ImmersiveModeControllerAshTest, ImmersiveModeControllerAsh) {
206   // Initial state.
207   EXPECT_FALSE(controller()->IsEnabled());
208   EXPECT_FALSE(controller()->ShouldHideTopViews());
209   EXPECT_FALSE(controller()->IsRevealed());
210   EXPECT_FALSE(delegate()->immersive_style());
211
212   // Enabling hides the top views.
213   controller()->SetEnabled(true);
214   EXPECT_TRUE(controller()->IsEnabled());
215   EXPECT_FALSE(controller()->IsRevealed());
216   EXPECT_TRUE(controller()->ShouldHideTopViews());
217   EXPECT_FALSE(controller()->ShouldHideTabIndicators());
218   EXPECT_TRUE(delegate()->immersive_style());
219
220   // Revealing shows the top views.
221   AttemptReveal(MODALITY_MOUSE);
222   EXPECT_TRUE(controller()->IsRevealed());
223   EXPECT_FALSE(controller()->ShouldHideTopViews());
224   // Tabs are painting in the normal style during a reveal.
225   EXPECT_FALSE(delegate()->immersive_style());
226
227   // Disabling immersive fullscreen keeps the top views shown.
228   controller()->SetEnabled(false);
229   EXPECT_FALSE(controller()->IsEnabled());
230   EXPECT_FALSE(controller()->IsRevealed());
231   EXPECT_FALSE(controller()->ShouldHideTopViews());
232   EXPECT_FALSE(delegate()->immersive_style());
233
234   // Test disabling immersive fullscreen when the top views are hidden.
235   controller()->SetEnabled(true);
236   EXPECT_TRUE(controller()->IsEnabled());
237   EXPECT_FALSE(controller()->IsRevealed());
238   EXPECT_TRUE(controller()->ShouldHideTopViews());
239   EXPECT_TRUE(delegate()->immersive_style());
240
241   controller()->SetEnabled(false);
242   EXPECT_FALSE(controller()->IsEnabled());
243   EXPECT_FALSE(controller()->IsRevealed());
244   EXPECT_FALSE(controller()->ShouldHideTopViews());
245   EXPECT_FALSE(delegate()->immersive_style());
246 }
247
248 // GetRevealedLock() specific tests.
249 TEST_F(ImmersiveModeControllerAshTest, RevealedLock) {
250   scoped_ptr<ImmersiveRevealedLock> lock1;
251   scoped_ptr<ImmersiveRevealedLock> lock2;
252
253   // Immersive fullscreen is not on by default.
254   EXPECT_FALSE(controller()->IsEnabled());
255
256   // 1) Test acquiring and releasing a revealed state lock while immersive
257   // fullscreen is disabled. Acquiring or releasing the lock should have no
258   // effect till immersive fullscreen is enabled.
259   lock1.reset(controller()->GetRevealedLock(
260       ImmersiveModeControllerAsh::ANIMATE_REVEAL_NO));
261   EXPECT_FALSE(controller()->IsEnabled());
262   EXPECT_FALSE(controller()->IsRevealed());
263
264   // Immersive fullscreen should start in the revealed state due to the lock.
265   controller()->SetEnabled(true);
266   EXPECT_TRUE(controller()->IsEnabled());
267   EXPECT_TRUE(controller()->IsRevealed());
268
269   controller()->SetEnabled(false);
270   EXPECT_FALSE(controller()->IsEnabled());
271   EXPECT_FALSE(controller()->IsRevealed());
272
273   lock1.reset();
274   EXPECT_FALSE(controller()->IsEnabled());
275   EXPECT_FALSE(controller()->IsRevealed());
276
277   // Immersive fullscreen should start in the closed state because the lock is
278   // no longer held.
279   controller()->SetEnabled(true);
280   EXPECT_TRUE(controller()->IsEnabled());
281   EXPECT_FALSE(controller()->IsRevealed());
282
283   // 2) Test that acquiring a lock reveals the top-of-window views if they are
284   // hidden.
285   lock1.reset(controller()->GetRevealedLock(
286       ImmersiveModeControllerAsh::ANIMATE_REVEAL_NO));
287   EXPECT_TRUE(controller()->IsRevealed());
288
289   // 3) Test that the top-of-window views are only hidden when all of the locks
290   // are released.
291   lock2.reset(controller()->GetRevealedLock(
292       ImmersiveModeControllerAsh::ANIMATE_REVEAL_NO));
293   lock1.reset();
294   EXPECT_TRUE(controller()->IsRevealed());
295
296   lock2.reset();
297   EXPECT_FALSE(controller()->IsRevealed());
298 }
299
300 // Test mouse event processing for top-of-screen reveal triggering.
301 TEST_F(ImmersiveModeControllerAshTest, OnMouseEvent) {
302   // Set up initial state.
303   controller()->SetEnabled(true);
304   ASSERT_TRUE(controller()->IsEnabled());
305   ASSERT_FALSE(controller()->IsRevealed());
306
307   aura::test::EventGenerator& event_generator(GetEventGenerator());
308
309   gfx::Rect top_container_bounds_in_screen =
310       top_container()->GetBoundsInScreen();
311   // A position along the top edge of TopContainerView in screen coordinates.
312   gfx::Point top_edge_pos(top_container_bounds_in_screen.x() + 100,
313                           top_container_bounds_in_screen.y());
314
315   // Mouse wheel event does nothing.
316   ui::MouseEvent wheel(
317       ui::ET_MOUSEWHEEL, top_edge_pos, top_edge_pos, ui::EF_NONE);
318   event_generator.Dispatch(&wheel);
319   EXPECT_FALSE(top_edge_hover_timer_running());
320
321   // Move to top edge of screen starts hover timer running. We cannot use
322   // MoveMouse() because MoveMouse() stops the timer if it started running.
323   event_generator.MoveMouseTo(top_edge_pos);
324   EXPECT_TRUE(top_edge_hover_timer_running());
325   EXPECT_EQ(top_edge_pos.x(), mouse_x_when_hit_top());
326
327   // Moving |ImmersiveModeControllerAsh::kMouseRevealBoundsHeight| down from
328   // the top edge stops it.
329   event_generator.MoveMouseBy(0, 3);
330   EXPECT_FALSE(top_edge_hover_timer_running());
331
332   // Moving back to the top starts the timer again.
333   event_generator.MoveMouseTo(top_edge_pos);
334   EXPECT_TRUE(top_edge_hover_timer_running());
335   EXPECT_EQ(top_edge_pos.x(), mouse_x_when_hit_top());
336
337   // Slight move to the right keeps the timer running for the same hit point.
338   event_generator.MoveMouseBy(1, 0);
339   EXPECT_TRUE(top_edge_hover_timer_running());
340   EXPECT_EQ(top_edge_pos.x(), mouse_x_when_hit_top());
341
342   // Moving back to the left also keeps the timer running.
343   event_generator.MoveMouseBy(-1, 0);
344   EXPECT_TRUE(top_edge_hover_timer_running());
345   EXPECT_EQ(top_edge_pos.x(), mouse_x_when_hit_top());
346
347   // Large move right restarts the timer (so it is still running) and considers
348   // this a new hit at the top.
349   event_generator.MoveMouseTo(top_edge_pos.x() + 100, top_edge_pos.y());
350   EXPECT_TRUE(top_edge_hover_timer_running());
351   EXPECT_EQ(top_edge_pos.x() + 100, mouse_x_when_hit_top());
352
353   // Moving off the top edge horizontally stops the timer.
354   EXPECT_GT(CurrentContext()->bounds().width(), top_container()->width());
355   event_generator.MoveMouseTo(top_container_bounds_in_screen.right(),
356                               top_container_bounds_in_screen.y());
357   EXPECT_FALSE(top_edge_hover_timer_running());
358
359   // Once revealed, a move just a little below the top container doesn't end a
360   // reveal.
361   AttemptReveal(MODALITY_MOUSE);
362   event_generator.MoveMouseTo(top_container_bounds_in_screen.x(),
363                               top_container_bounds_in_screen.bottom() + 1);
364   EXPECT_TRUE(controller()->IsRevealed());
365
366   // Once revealed, clicking just below the top container ends the reveal.
367   event_generator.ClickLeftButton();
368   EXPECT_FALSE(controller()->IsRevealed());
369
370   // Moving a lot below the top container ends a reveal.
371   AttemptReveal(MODALITY_MOUSE);
372   EXPECT_TRUE(controller()->IsRevealed());
373   event_generator.MoveMouseTo(top_container_bounds_in_screen.x(),
374                               top_container_bounds_in_screen.bottom() + 50);
375   EXPECT_FALSE(controller()->IsRevealed());
376
377   // The mouse position cannot cause a reveal when TopContainerView's widget
378   // has capture.
379   views::Widget* widget = top_container()->GetWidget();
380   widget->SetCapture(top_container());
381   AttemptReveal(MODALITY_MOUSE);
382   EXPECT_FALSE(controller()->IsRevealed());
383   widget->ReleaseCapture();
384
385   // The mouse position cannot end the reveal while TopContainerView's widget
386   // has capture.
387   AttemptReveal(MODALITY_MOUSE);
388   EXPECT_TRUE(controller()->IsRevealed());
389   widget->SetCapture(top_container());
390   event_generator.MoveMouseTo(top_container_bounds_in_screen.x(),
391                               top_container_bounds_in_screen.bottom() + 51);
392   EXPECT_TRUE(controller()->IsRevealed());
393
394   // Releasing capture should end the reveal.
395   widget->ReleaseCapture();
396   EXPECT_FALSE(controller()->IsRevealed());
397 }
398
399 // Test mouse event processing for top-of-screen reveal triggering when the user
400 // has a vertical display layout (primary display above/below secondary display)
401 // and the immersive fullscreen window is on the bottom display.
402 TEST_F(ImmersiveModeControllerAshTest, MouseEventsVerticalDisplayLayout) {
403   if (!SupportsMultipleDisplays())
404     return;
405
406   // Set up initial state.
407   UpdateDisplay("800x600,800x600");
408   ash::DisplayLayout display_layout(ash::DisplayLayout::TOP, 0);
409   ash::Shell::GetInstance()->display_manager()->SetLayoutForCurrentDisplays(
410       display_layout);
411
412   controller()->SetEnabled(true);
413   ASSERT_TRUE(controller()->IsEnabled());
414   ASSERT_FALSE(controller()->IsRevealed());
415
416   ash::Shell::RootWindowList root_windows = ash::Shell::GetAllRootWindows();
417   ASSERT_EQ(root_windows[0],
418             top_container()->GetWidget()->GetNativeWindow()->GetRootWindow());
419
420   gfx::Rect primary_root_window_bounds_in_screen =
421       root_windows[0]->GetBoundsInScreen();
422   // Do not set |x| to the root window's x position because the display's
423   // corners have special behavior.
424   int x = primary_root_window_bounds_in_screen.x() + 10;
425   // The y position of the top edge of the primary display.
426   int y_top_edge = primary_root_window_bounds_in_screen.y();
427
428   aura::test::EventGenerator& event_generator(GetEventGenerator());
429
430   // Moving right below the top edge starts the hover timer running. We
431   // cannot use MoveMouse() because MoveMouse() stops the timer if it started
432   // running.
433   event_generator.MoveMouseTo(x, y_top_edge + 1);
434   EXPECT_TRUE(top_edge_hover_timer_running());
435   EXPECT_EQ(y_top_edge + 1,
436             aura::Env::GetInstance()->last_mouse_location().y());
437
438   // The timer should continue running if the user moves the mouse to the top
439   // edge even though the mouse is warped to the secondary display.
440   event_generator.MoveMouseTo(x, y_top_edge);
441   EXPECT_TRUE(top_edge_hover_timer_running());
442   EXPECT_NE(y_top_edge,
443             aura::Env::GetInstance()->last_mouse_location().y());
444
445   // The timer should continue running if the user overshoots the top edge
446   // a bit.
447   event_generator.MoveMouseTo(x, y_top_edge - 2);
448   EXPECT_TRUE(top_edge_hover_timer_running());
449
450   // The timer should stop running if the user overshoots the top edge by
451   // a lot.
452   event_generator.MoveMouseTo(x, y_top_edge - 20);
453   EXPECT_FALSE(top_edge_hover_timer_running());
454
455   // The timer should not start if the user moves the mouse to the bottom of the
456   // secondary display without crossing the top edge first.
457   event_generator.MoveMouseTo(x, y_top_edge - 2);
458
459   // Reveal the top-of-window views by overshooting the top edge slightly.
460   event_generator.MoveMouseTo(x, y_top_edge + 1);
461   // MoveMouse() runs the timer task.
462   MoveMouse(x, y_top_edge - 2);
463   EXPECT_TRUE(controller()->IsRevealed());
464
465   // The top-of-window views should stay revealed if the user moves the mouse
466   // around in the bottom region of the secondary display.
467   event_generator.MoveMouseTo(x + 10, y_top_edge - 3);
468   EXPECT_TRUE(controller()->IsRevealed());
469
470   // The top-of-window views should hide if the user moves the mouse away from
471   // the bottom region of the secondary display.
472   event_generator.MoveMouseTo(x, y_top_edge - 20);
473   EXPECT_FALSE(controller()->IsRevealed());
474 }
475
476 // Test that hovering the mouse over the find bar does not end a reveal.
477 TEST_F(ImmersiveModeControllerAshTest, FindBar) {
478   // Set up initial state.
479   controller()->SetEnabled(true);
480   ASSERT_TRUE(controller()->IsEnabled());
481   ASSERT_FALSE(controller()->IsRevealed());
482
483   // Compute the find bar bounds relative to TopContainerView. The find
484   // bar is aligned with the bottom right of the TopContainerView.
485   gfx::Rect find_bar_bounds(top_container()->bounds().right() - 100,
486                             top_container()->bounds().bottom(),
487                             100,
488                             50);
489
490   gfx::Point find_bar_position_in_screen = find_bar_bounds.origin();
491   views::View::ConvertPointToScreen(top_container(),
492       &find_bar_position_in_screen);
493   gfx::Rect find_bar_bounds_in_screen(find_bar_position_in_screen,
494       find_bar_bounds.size());
495   controller()->OnFindBarVisibleBoundsChanged(find_bar_bounds_in_screen);
496
497   // Moving the mouse over the find bar does not end the reveal.
498   gfx::Point over_find_bar(find_bar_bounds.x() + 25, find_bar_bounds.y() + 25);
499   AttemptReveal(MODALITY_MOUSE);
500   EXPECT_TRUE(controller()->IsRevealed());
501   MoveMouse(over_find_bar.x(), over_find_bar.y());
502   EXPECT_TRUE(controller()->IsRevealed());
503
504   // Moving the mouse off of the find bar horizontally ends the reveal.
505   MoveMouse(find_bar_bounds.x() - 25, find_bar_bounds.y() + 25);
506   EXPECT_FALSE(controller()->IsRevealed());
507
508   // Moving the mouse off of the find bar vertically ends the reveal.
509   AttemptReveal(MODALITY_MOUSE);
510   EXPECT_TRUE(controller()->IsRevealed());
511   MoveMouse(find_bar_bounds.x() + 25, find_bar_bounds.bottom() + 25);
512
513   // Similar to the TopContainerView, moving the mouse slightly off vertically
514   // of the find bar does not end the reveal.
515   AttemptReveal(MODALITY_MOUSE);
516   MoveMouse(find_bar_bounds.x() + 25, find_bar_bounds.bottom() + 1);
517   EXPECT_TRUE(controller()->IsRevealed());
518
519   // Similar to the TopContainerView, clicking the mouse even slightly off of
520   // the find bar ends the reveal.
521   GetEventGenerator().ClickLeftButton();
522   EXPECT_FALSE(controller()->IsRevealed());
523
524   // Set the find bar bounds to empty. Hovering over the position previously
525   // occupied by the find bar, |over_find_bar|, should end the reveal.
526   controller()->OnFindBarVisibleBoundsChanged(gfx::Rect());
527   AttemptReveal(MODALITY_MOUSE);
528   MoveMouse(over_find_bar.x(), over_find_bar.y());
529   EXPECT_FALSE(controller()->IsRevealed());
530 }
531
532 // Test behavior when the mouse becomes hovered without moving.
533 TEST_F(ImmersiveModeControllerAshTest, MouseHoveredWithoutMoving) {
534   controller()->SetEnabled(true);
535   scoped_ptr<ImmersiveRevealedLock> lock;
536
537   // 1) Test that if the mouse becomes hovered without the mouse moving due to a
538   // lock causing the top-of-window views to be revealed (and the mouse
539   // happening to be near the top of the screen), the top-of-window views do not
540   // hide till the mouse moves off of the top-of-window views.
541   SetHovered(true);
542   EXPECT_FALSE(controller()->IsRevealed());
543   lock.reset(controller()->GetRevealedLock(
544       ImmersiveModeControllerAsh::ANIMATE_REVEAL_NO));
545   EXPECT_TRUE(controller()->IsRevealed());
546   lock.reset();
547   EXPECT_TRUE(controller()->IsRevealed());
548   SetHovered(false);
549   EXPECT_FALSE(controller()->IsRevealed());
550
551   // 2) Test that if the mouse becomes hovered without moving because of a
552   // reveal in ImmersiveModeControllerAshTest::controller()->SetEnabled(true)
553   // and there are no locks keeping the top-of-window views revealed, that mouse
554   // hover does not prevent the top-of-window views from closing.
555   controller()->SetEnabled(false);
556   SetHovered(true);
557   EXPECT_FALSE(controller()->IsRevealed());
558   controller()->SetEnabled(true);
559   EXPECT_FALSE(controller()->IsRevealed());
560
561   // 3) Test that if the mouse becomes hovered without moving because of a
562   // reveal in ImmersiveModeControllerAshTest::controller()->SetEnabled(true)
563   // and there is a lock keeping the top-of-window views revealed, that the
564   // top-of-window views do not hide till the mouse moves off of the
565   // top-of-window views.
566   controller()->SetEnabled(false);
567   SetHovered(true);
568   lock.reset(controller()->GetRevealedLock(
569       ImmersiveModeControllerAsh::ANIMATE_REVEAL_NO));
570   EXPECT_FALSE(controller()->IsRevealed());
571   controller()->SetEnabled(true);
572   EXPECT_TRUE(controller()->IsRevealed());
573   lock.reset();
574   EXPECT_TRUE(controller()->IsRevealed());
575   SetHovered(false);
576   EXPECT_FALSE(controller()->IsRevealed());
577 }
578
579 // Test revealing the top-of-window views using one modality and ending
580 // the reveal via another. For instance, initiating the reveal via a SWIPE_OPEN
581 // edge gesture, switching to using the mouse and ending the reveal by moving
582 // the mouse off of the top-of-window views.
583 TEST_F(ImmersiveModeControllerAshTest, DifferentModalityEnterExit) {
584   controller()->SetEnabled(true);
585   EXPECT_TRUE(controller()->IsEnabled());
586   EXPECT_FALSE(controller()->IsRevealed());
587
588   // Initiate reveal via gesture, end reveal via mouse.
589   AttemptReveal(MODALITY_GESTURE);
590   EXPECT_TRUE(controller()->IsRevealed());
591   MoveMouse(1, 1);
592   EXPECT_TRUE(controller()->IsRevealed());
593   AttemptUnreveal(MODALITY_MOUSE);
594   EXPECT_FALSE(controller()->IsRevealed());
595
596   // Initiate reveal via gesture, end reveal via touch.
597   AttemptReveal(MODALITY_GESTURE);
598   EXPECT_TRUE(controller()->IsRevealed());
599   AttemptUnreveal(MODALITY_TOUCH);
600   EXPECT_FALSE(controller()->IsRevealed());
601
602   // Initiate reveal via mouse, end reveal via gesture.
603   AttemptReveal(MODALITY_MOUSE);
604   EXPECT_TRUE(controller()->IsRevealed());
605   AttemptUnreveal(MODALITY_GESTURE);
606   EXPECT_FALSE(controller()->IsRevealed());
607
608   // Initiate reveal via mouse, end reveal via touch.
609   AttemptReveal(MODALITY_MOUSE);
610   EXPECT_TRUE(controller()->IsRevealed());
611   AttemptUnreveal(MODALITY_TOUCH);
612   EXPECT_FALSE(controller()->IsRevealed());
613 }
614
615 // Test when the SWIPE_CLOSE edge gesture closes the top-of-window views.
616 TEST_F(ImmersiveModeControllerAshTest, EndRevealViaGesture) {
617   controller()->SetEnabled(true);
618   EXPECT_TRUE(controller()->IsEnabled());
619   EXPECT_FALSE(controller()->IsRevealed());
620
621   // A gesture should be able to close the top-of-window views when
622   // top-of-window views have focus.
623   AttemptReveal(MODALITY_MOUSE);
624   top_container()->RequestFocus();
625   EXPECT_TRUE(controller()->IsRevealed());
626   AttemptUnreveal(MODALITY_GESTURE);
627   EXPECT_FALSE(controller()->IsRevealed());
628   top_container()->GetFocusManager()->ClearFocus();
629
630   // If some other code is holding onto a lock, a gesture should not be able to
631   // end the reveal.
632   AttemptReveal(MODALITY_MOUSE);
633   scoped_ptr<ImmersiveRevealedLock> lock(controller()->GetRevealedLock(
634       ImmersiveModeController::ANIMATE_REVEAL_NO));
635   EXPECT_TRUE(controller()->IsRevealed());
636   AttemptUnreveal(MODALITY_GESTURE);
637   EXPECT_TRUE(controller()->IsRevealed());
638   lock.reset();
639   EXPECT_FALSE(controller()->IsRevealed());
640 }
641
642 // Do not test under windows because focus testing is not reliable on
643 // Windows. (crbug.com/79493)
644 #if !defined(OS_WIN)
645
646 // Test how focus and activation affects whether the top-of-window views are
647 // revealed.
648 TEST_F(ImmersiveModeControllerAshTest, Focus) {
649   // Add views to the view hierarchy which we will focus and unfocus during the
650   // test.
651   views::View* child_view = new views::View();
652   child_view->SetBounds(0, 0, 10, 10);
653   child_view->set_focusable(true);
654   top_container()->AddChildView(child_view);
655   views::View* unrelated_view = new views::View();
656   unrelated_view->SetBounds(0, 100, 10, 10);
657   unrelated_view->set_focusable(true);
658   top_container()->parent()->AddChildView(unrelated_view);
659   views::FocusManager* focus_manager =
660       top_container()->GetWidget()->GetFocusManager();
661
662   controller()->SetEnabled(true);
663
664   // 1) Test that the top-of-window views stay revealed as long as either a
665   // |child_view| has focus or the mouse is hovered above the top-of-window
666   // views.
667   AttemptReveal(MODALITY_MOUSE);
668   child_view->RequestFocus();
669   focus_manager->ClearFocus();
670   EXPECT_TRUE(controller()->IsRevealed());
671   child_view->RequestFocus();
672   SetHovered(false);
673   EXPECT_TRUE(controller()->IsRevealed());
674   focus_manager->ClearFocus();
675   EXPECT_FALSE(controller()->IsRevealed());
676
677   // 2) Test that focusing |unrelated_view| hides the top-of-window views.
678   // Note: In this test we can cheat and trigger a reveal via focus because
679   // the top container does not hide when the top-of-window views are not
680   // revealed.
681   child_view->RequestFocus();
682   EXPECT_TRUE(controller()->IsRevealed());
683   unrelated_view->RequestFocus();
684   EXPECT_FALSE(controller()->IsRevealed());
685
686   // 3) Test that a loss of focus of |child_view| to |unrelated_view|
687   // while immersive mode is disabled is properly registered.
688   child_view->RequestFocus();
689   EXPECT_TRUE(controller()->IsRevealed());
690   controller()->SetEnabled(false);
691   EXPECT_FALSE(controller()->IsRevealed());
692   unrelated_view->RequestFocus();
693   controller()->SetEnabled(true);
694   EXPECT_FALSE(controller()->IsRevealed());
695
696   // Repeat test but with a revealed lock acquired when immersive mode is
697   // disabled because the code path is different.
698   child_view->RequestFocus();
699   EXPECT_TRUE(controller()->IsRevealed());
700   controller()->SetEnabled(false);
701   scoped_ptr<ImmersiveRevealedLock> lock(controller()->GetRevealedLock(
702       ImmersiveModeController::ANIMATE_REVEAL_NO));
703   EXPECT_FALSE(controller()->IsRevealed());
704   unrelated_view->RequestFocus();
705   controller()->SetEnabled(true);
706   EXPECT_TRUE(controller()->IsRevealed());
707   lock.reset();
708   EXPECT_FALSE(controller()->IsRevealed());
709 }
710
711 // Test how activation affects whether the top-of-window views are revealed.
712 // The behavior when a bubble is activated is tested in
713 // ImmersiveModeControllerAshTest.Bubbles.
714 TEST_F(ImmersiveModeControllerAshTest, Activation) {
715   views::Widget* top_container_widget = top_container()->GetWidget();
716
717   controller()->SetEnabled(true);
718   ASSERT_FALSE(controller()->IsRevealed());
719
720   // 1) Test that a transient window which is not a bubble does not trigger a
721   // reveal but does keep the top-of-window views revealed if they are already
722   // revealed.
723   views::Widget::InitParams transient_params;
724   transient_params.ownership =
725       views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
726   transient_params.parent = top_container_widget->GetNativeView();
727   transient_params.bounds = gfx::Rect(0, 0, 100, 100);
728   scoped_ptr<views::Widget> transient_widget(new views::Widget());
729   transient_widget->Init(transient_params);
730   transient_widget->Show();
731
732   EXPECT_FALSE(controller()->IsRevealed());
733   top_container_widget->Activate();
734   AttemptReveal(MODALITY_MOUSE);
735   EXPECT_TRUE(controller()->IsRevealed());
736   transient_widget->Activate();
737   SetHovered(false);
738   EXPECT_TRUE(controller()->IsRevealed());
739   transient_widget.reset();
740   EXPECT_FALSE(controller()->IsRevealed());
741
742   // 2) Test that activating a non-transient window ends the reveal if any.
743   views::Widget::InitParams non_transient_params;
744   non_transient_params.ownership =
745       views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
746   non_transient_params.context = top_container_widget->GetNativeView();
747   non_transient_params.bounds = gfx::Rect(0, 0, 100, 100);
748   scoped_ptr<views::Widget> non_transient_widget(new views::Widget());
749   non_transient_widget->Init(non_transient_params);
750   non_transient_widget->Show();
751
752   EXPECT_FALSE(controller()->IsRevealed());
753   top_container_widget->Activate();
754   AttemptReveal(MODALITY_MOUSE);
755   EXPECT_TRUE(controller()->IsRevealed());
756   non_transient_widget->Activate();
757   EXPECT_FALSE(controller()->IsRevealed());
758 }
759
760 // Test how bubbles affect whether the top-of-window views are revealed.
761 TEST_F(ImmersiveModeControllerAshTest, Bubbles) {
762   scoped_ptr<ImmersiveRevealedLock> revealed_lock;
763   views::Widget* top_container_widget = top_container()->GetWidget();
764
765   // Add views to the view hierarchy to which we will anchor bubbles.
766   views::View* child_view = new views::View();
767   child_view->SetBounds(0, 0, 10, 10);
768   top_container()->AddChildView(child_view);
769   views::View* unrelated_view = new views::View();
770   unrelated_view->SetBounds(0, 100, 10, 10);
771   top_container()->parent()->AddChildView(unrelated_view);
772
773   controller()->SetEnabled(true);
774   ASSERT_FALSE(controller()->IsRevealed());
775
776   // 1) Test that a bubble anchored to a child of the top container triggers
777   // a reveal and keeps the top-of-window views revealed for the duration of
778   // its visibility.
779   views::Widget* bubble_widget1(views::BubbleDelegateView::CreateBubble(
780       new views::BubbleDelegateView(child_view, views::BubbleBorder::NONE)));
781   bubble_widget1->Show();
782   EXPECT_TRUE(controller()->IsRevealed());
783
784   // Activating |top_container_widget| will close |bubble_widget1|.
785   top_container_widget->Activate();
786   AttemptReveal(MODALITY_MOUSE);
787   revealed_lock.reset(controller()->GetRevealedLock(
788       ImmersiveModeController::ANIMATE_REVEAL_NO));
789   EXPECT_TRUE(controller()->IsRevealed());
790
791   views::Widget* bubble_widget2 = views::BubbleDelegateView::CreateBubble(
792       new views::BubbleDelegateView(child_view, views::BubbleBorder::NONE));
793   bubble_widget2->Show();
794   EXPECT_TRUE(controller()->IsRevealed());
795   revealed_lock.reset();
796   SetHovered(false);
797   EXPECT_TRUE(controller()->IsRevealed());
798   bubble_widget2->Close();
799   EXPECT_FALSE(controller()->IsRevealed());
800
801   // 2) Test that transitioning from keeping the top-of-window views revealed
802   // because of a bubble to keeping the top-of-window views revealed because of
803   // mouse hover by activating |top_container_widget| works.
804   views::Widget* bubble_widget3 = views::BubbleDelegateView::CreateBubble(
805       new views::BubbleDelegateView(child_view, views::BubbleBorder::NONE));
806   bubble_widget3->Show();
807   SetHovered(true);
808   EXPECT_TRUE(controller()->IsRevealed());
809
810   SetAnimationsDisabled(false);
811   // Activating |top_container_widget| will close |bubble_widget3|.
812   top_container_widget->Activate();
813   SetAnimationsDisabled(true);
814   EXPECT_TRUE(controller()->IsRevealed());
815
816   // 3) Test that the top-of-window views stay revealed as long as at least one
817   // bubble anchored to a child of the top container is visible.
818   SetHovered(false);
819   EXPECT_FALSE(controller()->IsRevealed());
820
821   views::BubbleDelegateView* bubble_delegate4(new views::BubbleDelegateView(
822       child_view, views::BubbleBorder::NONE));
823   bubble_delegate4->set_use_focusless(true);
824   views::Widget* bubble_widget4(views::BubbleDelegateView::CreateBubble(
825       bubble_delegate4));
826   bubble_widget4->Show();
827
828   views::BubbleDelegateView* bubble_delegate5(new views::BubbleDelegateView(
829       child_view, views::BubbleBorder::NONE));
830   bubble_delegate5->set_use_focusless(true);
831   views::Widget* bubble_widget5(views::BubbleDelegateView::CreateBubble(
832       bubble_delegate5));
833   bubble_widget5->Show();
834
835   EXPECT_TRUE(controller()->IsRevealed());
836   bubble_widget4->Hide();
837   EXPECT_TRUE(controller()->IsRevealed());
838   bubble_widget5->Hide();
839   EXPECT_FALSE(controller()->IsRevealed());
840   bubble_widget5->Show();
841   EXPECT_TRUE(controller()->IsRevealed());
842
843   // 4) Test that visibility changes which occur while immersive fullscreen is
844   // disabled are handled upon reenabling immersive fullscreen.
845   controller()->SetEnabled(false);
846   bubble_widget5->Hide();
847   controller()->SetEnabled(true);
848   EXPECT_FALSE(controller()->IsRevealed());
849
850   // We do not need |bubble_widget4| or |bubble_widget5| anymore, close them.
851   bubble_widget4->Close();
852   bubble_widget5->Close();
853
854   // 5) Test that a bubble added while immersive fullscreen is disabled is
855   // handled upon reenabling immersive fullscreen.
856   controller()->SetEnabled(false);
857
858   views::Widget* bubble_widget6 = views::BubbleDelegateView::CreateBubble(
859       new views::BubbleDelegateView(child_view, views::BubbleBorder::NONE));
860   bubble_widget6->Show();
861
862   controller()->SetEnabled(true);
863   EXPECT_TRUE(controller()->IsRevealed());
864
865   bubble_widget6->Close();
866
867   // 6) Test that a bubble which is not anchored to a child of the
868   // TopContainerView does not trigger a reveal or keep the
869   // top-of-window views revealed if they are already revealed.
870   views::Widget* bubble_widget7 = views::BubbleDelegateView::CreateBubble(
871       new views::BubbleDelegateView(unrelated_view, views::BubbleBorder::NONE));
872   bubble_widget7->Show();
873   EXPECT_FALSE(controller()->IsRevealed());
874
875   // Activating |top_container_widget| will close |bubble_widget6|.
876   top_container_widget->Activate();
877   AttemptReveal(MODALITY_MOUSE);
878   EXPECT_TRUE(controller()->IsRevealed());
879
880   views::Widget* bubble_widget8 = views::BubbleDelegateView::CreateBubble(
881       new views::BubbleDelegateView(unrelated_view, views::BubbleBorder::NONE));
882   bubble_widget8->Show();
883   SetHovered(false);
884   EXPECT_FALSE(controller()->IsRevealed());
885   bubble_widget8->Close();
886 }
887
888 #endif  // defined(OS_WIN)
889
890 class ImmersiveModeControllerAshTestWithBrowserView
891     : public TestWithBrowserView {
892  public:
893   ImmersiveModeControllerAshTestWithBrowserView() {}
894   virtual ~ImmersiveModeControllerAshTestWithBrowserView() {}
895
896   // TestWithBrowserView override:
897   virtual void SetUp() OVERRIDE {
898     TestWithBrowserView::SetUp();
899
900     browser()->window()->Show();
901
902     controller_ = browser_view()->immersive_mode_controller();
903     controller_->SetupForTest();
904   }
905
906   // Returns the bounds of |view| in widget coordinates.
907   gfx::Rect GetBoundsInWidget(views::View* view) {
908     return view->ConvertRectToWidget(view->GetLocalBounds());
909   }
910
911   // Toggle the browser's fullscreen state.
912   void ToggleFullscreen() {
913     // NOTIFICATION_FULLSCREEN_CHANGED is sent asynchronously. The notification
914     // is used to trigger changes in whether the shelf is auto hidden and
915     // whether a "light bar" version of the tab strip is used when the
916     // top-of-window views are hidden.
917     scoped_ptr<FullscreenNotificationObserver> waiter(
918         new FullscreenNotificationObserver());
919     chrome::ToggleFullscreenMode(browser());
920     waiter->Wait();
921   }
922
923   // Set whether the browser is in tab fullscreen.
924   void SetTabFullscreen(bool tab_fullscreen) {
925     content::WebContents* web_contents =
926         browser_view()->GetContentsWebViewForTest()->GetWebContents();
927     scoped_ptr<FullscreenNotificationObserver> waiter(
928         new FullscreenNotificationObserver());
929     browser()->fullscreen_controller()->ToggleFullscreenModeForTab(
930         web_contents, tab_fullscreen);
931     waiter->Wait();
932   }
933
934   // Attempt revealing the top-of-window views.
935   void AttemptReveal() {
936     if (!revealed_lock_.get()) {
937       revealed_lock_.reset(controller_->GetRevealedLock(
938           ImmersiveModeControllerAsh::ANIMATE_REVEAL_NO));
939     }
940   }
941
942   // Attempt unrevealing the top-of-window views.
943   void AttemptUnreveal() {
944     revealed_lock_.reset();
945   }
946
947   ImmersiveModeController* controller() { return controller_; }
948
949  private:
950   // Not owned.
951   ImmersiveModeController* controller_;
952
953   scoped_ptr<ImmersiveRevealedLock> revealed_lock_;
954
955   DISALLOW_COPY_AND_ASSIGN(ImmersiveModeControllerAshTestWithBrowserView);
956 };
957
958 // Test the layout and visibility of the tabstrip, toolbar and TopContainerView
959 // in immersive fullscreen.
960 TEST_F(ImmersiveModeControllerAshTestWithBrowserView, Layout) {
961   AddTab(browser(), GURL("about:blank"));
962
963   TabStrip* tabstrip = browser_view()->tabstrip();
964   ToolbarView* toolbar = browser_view()->toolbar();
965   views::WebView* contents_web_view =
966       browser_view()->GetContentsWebViewForTest();
967
968   // Immersive fullscreen starts out disabled.
969   ASSERT_FALSE(browser_view()->GetWidget()->IsFullscreen());
970   ASSERT_FALSE(controller()->IsEnabled());
971
972   // By default, the tabstrip and toolbar should be visible.
973   EXPECT_TRUE(tabstrip->visible());
974   EXPECT_TRUE(toolbar->visible());
975
976   ToggleFullscreen();
977   EXPECT_TRUE(browser_view()->GetWidget()->IsFullscreen());
978   EXPECT_TRUE(controller()->IsEnabled());
979   EXPECT_FALSE(controller()->IsRevealed());
980
981   // Entering immersive fullscreen should make the tab strip use the immersive
982   // style and hide the toolbar.
983   EXPECT_TRUE(tabstrip->visible());
984   EXPECT_TRUE(tabstrip->IsImmersiveStyle());
985   EXPECT_FALSE(toolbar->visible());
986
987   // The tab indicators should be flush with the top of the widget.
988   EXPECT_EQ(0, GetBoundsInWidget(tabstrip).y());
989
990   // The web contents should be immediately below the tab indicators.
991   EXPECT_EQ(Tab::GetImmersiveHeight(),
992             GetBoundsInWidget(contents_web_view).y());
993
994   // Revealing the top-of-window views should set the tab strip back to the
995   // normal style and show the toolbar.
996   AttemptReveal();
997   EXPECT_TRUE(controller()->IsRevealed());
998   EXPECT_TRUE(tabstrip->visible());
999   EXPECT_FALSE(tabstrip->IsImmersiveStyle());
1000   EXPECT_TRUE(toolbar->visible());
1001
1002   // The TopContainerView should be flush with the top edge of the widget. If
1003   // it is not flush with the top edge the immersive reveal animation looks
1004   // wonky.
1005   EXPECT_EQ(0, GetBoundsInWidget(browser_view()->top_container()).y());
1006
1007   // The web contents should be at the same y position as they were when the
1008   // top-of-window views were hidden.
1009   EXPECT_EQ(Tab::GetImmersiveHeight(),
1010             GetBoundsInWidget(contents_web_view).y());
1011
1012   // Repeat the test for when in both immersive fullscreen and tab fullscreen.
1013   SetTabFullscreen(true);
1014   // Hide and reveal the top-of-window views so that they get relain out.
1015   AttemptUnreveal();
1016   AttemptReveal();
1017
1018   // The tab strip and toolbar should still be visible and the TopContainerView
1019   // should still be flush with the top edge of the widget.
1020   EXPECT_TRUE(controller()->IsRevealed());
1021   EXPECT_TRUE(tabstrip->visible());
1022   EXPECT_FALSE(tabstrip->IsImmersiveStyle());
1023   EXPECT_TRUE(toolbar->visible());
1024   EXPECT_EQ(0, GetBoundsInWidget(browser_view()->top_container()).y());
1025
1026   // The web contents should be flush with the top edge of the widget when in
1027   // both immersive and tab fullscreen.
1028   EXPECT_EQ(0, GetBoundsInWidget(contents_web_view).y());
1029
1030   // Hide the top-of-window views. Both the tab strip and the toolbar should
1031   // hide when in both immersive and tab fullscreen.
1032   AttemptUnreveal();
1033   EXPECT_FALSE(controller()->IsRevealed());
1034   EXPECT_FALSE(tabstrip->visible());
1035   EXPECT_FALSE(toolbar->visible());
1036
1037   // The web contents should still be flush with the edge of the widget.
1038   EXPECT_EQ(0, GetBoundsInWidget(contents_web_view).y());
1039
1040   // Exiting both immersive and tab fullscreen should show the tab strip and
1041   // toolbar.
1042   ToggleFullscreen();
1043   EXPECT_FALSE(browser_view()->GetWidget()->IsFullscreen());
1044   EXPECT_FALSE(controller()->IsEnabled());
1045   EXPECT_FALSE(controller()->IsRevealed());
1046   EXPECT_TRUE(tabstrip->visible());
1047   EXPECT_FALSE(tabstrip->IsImmersiveStyle());
1048   EXPECT_TRUE(toolbar->visible());
1049 }
1050
1051 // Test that the browser commands which are usually disabled in fullscreen are
1052 // are enabled in immersive fullscreen.
1053 TEST_F(ImmersiveModeControllerAshTestWithBrowserView, EnabledCommands) {
1054   ASSERT_FALSE(controller()->IsEnabled());
1055   EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPEN_CURRENT_URL));
1056   EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_ABOUT));
1057   EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_LOCATION));
1058
1059   ToggleFullscreen();
1060   EXPECT_TRUE(controller()->IsEnabled());
1061   EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPEN_CURRENT_URL));
1062   EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_ABOUT));
1063   EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_LOCATION));
1064 }
1065
1066 // Test that restoring a window properly exits immersive fullscreen.
1067 TEST_F(ImmersiveModeControllerAshTestWithBrowserView, ExitUponRestore) {
1068   ASSERT_FALSE(controller()->IsEnabled());
1069   ToggleFullscreen();
1070   AttemptReveal();
1071   ASSERT_TRUE(controller()->IsEnabled());
1072   ASSERT_TRUE(controller()->IsRevealed());
1073   ASSERT_TRUE(browser_view()->GetWidget()->IsFullscreen());
1074
1075   browser_view()->GetWidget()->Restore();
1076   EXPECT_FALSE(controller()->IsEnabled());
1077 }
1078
1079 // Test that the shelf is set to auto hide as long as the window is in
1080 // immersive fullscreen and that the shelf's state before entering immersive
1081 // fullscreen is restored upon exiting immersive fullscreen.
1082 TEST_F(ImmersiveModeControllerAshTestWithBrowserView, Shelf) {
1083   // Shelf is visible when the test starts.
1084   ash::internal::ShelfLayoutManager* shelf =
1085       ash::Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
1086   ASSERT_EQ(ash::SHELF_VISIBLE, shelf->visibility_state());
1087
1088   // Entering immersive fullscreen sets the shelf to auto hide.
1089   ToggleFullscreen();
1090   ASSERT_TRUE(browser_view()->IsFullscreen());
1091   ASSERT_TRUE(controller()->IsEnabled());
1092   EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state());
1093
1094   // Disabling immersive fullscreen puts it back.
1095   ToggleFullscreen();
1096   ASSERT_FALSE(browser_view()->IsFullscreen());
1097   ASSERT_FALSE(controller()->IsEnabled());
1098   EXPECT_EQ(ash::SHELF_VISIBLE, shelf->visibility_state());
1099
1100   // The user could toggle the shelf auto-hide behavior.
1101   shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1102   EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state());
1103
1104   // Entering immersive fullscreen keeps auto-hide.
1105   ToggleFullscreen();
1106   ASSERT_TRUE(browser_view()->IsFullscreen());
1107   ASSERT_TRUE(controller()->IsEnabled());
1108   EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state());
1109
1110   // Disabling immersive fullscreen maintains the user's auto-hide selection.
1111   ToggleFullscreen();
1112   ASSERT_FALSE(browser_view()->IsFullscreen());
1113   ASSERT_FALSE(controller()->IsEnabled());
1114   EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state());
1115 }
1116
1117 // Test how being simultaneously in tab fullscreen and immersive fullscreen
1118 // affects the shelf visibility and whether the tab indicators are hidden.
1119 TEST_F(ImmersiveModeControllerAshTestWithBrowserView, TabAndBrowserFullscreen) {
1120   AddTab(browser(), GURL("about:blank"));
1121
1122   // The shelf should start out as visible.
1123   ash::internal::ShelfLayoutManager* shelf =
1124       ash::Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
1125   ASSERT_EQ(ash::SHELF_VISIBLE, shelf->visibility_state());
1126
1127   // 1) Test that entering tab fullscreen from immersive fullscreen hides the
1128   // tab indicators and the shelf.
1129   ToggleFullscreen();
1130   ASSERT_TRUE(controller()->IsEnabled());
1131   EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state());
1132   EXPECT_FALSE(controller()->ShouldHideTabIndicators());
1133
1134   SetTabFullscreen(true);
1135   ASSERT_TRUE(controller()->IsEnabled());
1136   EXPECT_EQ(ash::SHELF_HIDDEN, shelf->visibility_state());
1137   EXPECT_TRUE(controller()->ShouldHideTabIndicators());
1138
1139   // 2) Test that exiting tab fullscreen shows the tab indicators and autohides
1140   // the shelf.
1141   SetTabFullscreen(false);
1142   ASSERT_TRUE(controller()->IsEnabled());
1143   EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state());
1144   EXPECT_FALSE(controller()->ShouldHideTabIndicators());
1145
1146   // 3) Test that exiting tab fullscreen and immersive fullscreen
1147   // simultaneously correctly updates the shelf visibility and whether the tab
1148   // indicators should be hidden.
1149   SetTabFullscreen(true);
1150   ToggleFullscreen();
1151   ASSERT_FALSE(controller()->IsEnabled());
1152   EXPECT_EQ(ash::SHELF_VISIBLE, shelf->visibility_state());
1153   EXPECT_TRUE(controller()->ShouldHideTabIndicators());
1154 }
1155
1156 #endif  // defined(OS_CHROMEOS)