7d873e8c31071ad067074521f39d2b26671e0103
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / fullscreen / fullscreen_controller_state_unittest.cc
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 #include "base/command_line.h"
6 #include "build/build_config.h"
7 #include "chrome/browser/ui/browser.h"
8 #include "chrome/browser/ui/browser_tabstrip.h"
9 #include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
10 #include "chrome/browser/ui/fullscreen/fullscreen_controller_state_test.h"
11 #include "chrome/browser/ui/tabs/tab_strip_model.h"
12 #include "chrome/common/chrome_switches.h"
13 #include "chrome/test/base/browser_with_test_window_test.h"
14 #include "content/public/browser/web_contents.h"
15 #include "content/public/browser/web_contents_view.h"
16 #include "content/public/common/url_constants.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 // The FullscreenControllerStateUnitTest unit test suite exhastively tests
20 // the FullscreenController through all permutations of events. The behavior
21 // of the BrowserWindow is mocked via FullscreenControllerTestWindow.
22
23
24 // FullscreenControllerTestWindow ----------------------------------------------
25
26 // A BrowserWindow used for testing FullscreenController. The behavior of this
27 // mock is verfied manually by running FullscreenControllerStateInteractiveTest.
28 class FullscreenControllerTestWindow : public TestBrowserWindow {
29  public:
30   // Simulate the window state with an enumeration.
31   enum WindowState {
32     NORMAL,
33     FULLSCREEN,
34     // No TO_ state for METRO_SNAP, the windows implementation is synchronous.
35     METRO_SNAP,
36     TO_NORMAL,
37     TO_FULLSCREEN,
38   };
39
40   FullscreenControllerTestWindow();
41   virtual ~FullscreenControllerTestWindow() {}
42
43   // BrowserWindow Interface:
44   virtual void EnterFullscreen(const GURL& url,
45                                FullscreenExitBubbleType type) OVERRIDE;
46   virtual void ExitFullscreen() OVERRIDE;
47   virtual bool ShouldHideUIForFullscreen() const OVERRIDE;
48   virtual bool IsFullscreen() const OVERRIDE;
49 #if defined(OS_WIN)
50   virtual void SetMetroSnapMode(bool enable) OVERRIDE;
51   virtual bool IsInMetroSnapMode() const OVERRIDE;
52 #endif
53 #if defined(OS_MACOSX)
54   virtual void EnterFullscreenWithChrome() OVERRIDE;
55   virtual bool IsFullscreenWithChrome() OVERRIDE;
56   virtual bool IsFullscreenWithoutChrome() OVERRIDE;
57 #endif
58
59   static const char* GetWindowStateString(WindowState state);
60   WindowState state() const { return state_; }
61   void set_browser(Browser* browser) { browser_ = browser; }
62
63   // Simulates the window changing state.
64   void ChangeWindowFullscreenState();
65
66  private:
67   // Enters fullscreen with |new_mac_with_chrome_mode|.
68   void EnterFullscreen(bool new_mac_with_chrome_mode);
69
70   // Returns true if ChangeWindowFullscreenState() should be called as a result
71   // of updating the current fullscreen state to the passed in state.
72   bool IsTransitionReentrant(bool new_fullscreen,
73                              bool new_mac_with_chrome_mode);
74
75   WindowState state_;
76   bool mac_with_chrome_mode_;
77   Browser* browser_;
78 };
79
80 FullscreenControllerTestWindow::FullscreenControllerTestWindow()
81     : state_(NORMAL),
82       mac_with_chrome_mode_(false),
83       browser_(NULL) {
84 }
85
86 void FullscreenControllerTestWindow::EnterFullscreen(
87     const GURL& url, FullscreenExitBubbleType type) {
88   EnterFullscreen(false);
89 }
90
91 void FullscreenControllerTestWindow::ExitFullscreen() {
92   if (IsFullscreen()) {
93     state_ = TO_NORMAL;
94     mac_with_chrome_mode_ = false;
95
96     if (IsTransitionReentrant(false, false))
97       ChangeWindowFullscreenState();
98   }
99 }
100
101 bool FullscreenControllerTestWindow::ShouldHideUIForFullscreen() const {
102   return IsFullscreen();
103 }
104
105 bool FullscreenControllerTestWindow::IsFullscreen() const {
106 #if defined(OS_MACOSX)
107   return state_ == FULLSCREEN || state_ == TO_FULLSCREEN;
108 #else
109   return state_ == FULLSCREEN || state_ == TO_NORMAL;
110 #endif
111 }
112
113 #if defined(OS_WIN)
114 void FullscreenControllerTestWindow::SetMetroSnapMode(bool enable) {
115   if (enable != IsInMetroSnapMode())
116     state_ = enable ? METRO_SNAP : NORMAL;
117
118   if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
119     ChangeWindowFullscreenState();
120 }
121
122 bool FullscreenControllerTestWindow::IsInMetroSnapMode() const {
123   return state_ == METRO_SNAP;
124 }
125 #endif
126
127 #if defined(OS_MACOSX)
128 void FullscreenControllerTestWindow::EnterFullscreenWithChrome() {
129   EnterFullscreen(true);
130 }
131
132 bool FullscreenControllerTestWindow::IsFullscreenWithChrome() {
133   return IsFullscreen() && mac_with_chrome_mode_;
134 }
135
136 bool FullscreenControllerTestWindow::IsFullscreenWithoutChrome() {
137   return IsFullscreen() && !mac_with_chrome_mode_;
138 }
139 #endif
140
141 // static
142 const char* FullscreenControllerTestWindow::GetWindowStateString(
143     WindowState state) {
144   switch (state) {
145     ENUM_TO_STRING(NORMAL);
146     ENUM_TO_STRING(FULLSCREEN);
147     ENUM_TO_STRING(METRO_SNAP);
148     ENUM_TO_STRING(TO_FULLSCREEN);
149     ENUM_TO_STRING(TO_NORMAL);
150     default:
151       NOTREACHED() << "No string for state " << state;
152       return "WindowState-Unknown";
153   }
154 }
155
156 void FullscreenControllerTestWindow::ChangeWindowFullscreenState() {
157   // Most states result in "no operation" intentionally. The tests
158   // assume that all possible states and event pairs can be tested, even
159   // though window managers will not generate all of these.
160   if (state_ == TO_FULLSCREEN)
161       state_ = FULLSCREEN;
162   else if (state_ == TO_NORMAL)
163       state_ = NORMAL;
164
165   // Emit a change event from every state to ensure the Fullscreen Controller
166   // handles it in all circumstances.
167   browser_->WindowFullscreenStateChanged();
168 }
169
170 void FullscreenControllerTestWindow::EnterFullscreen(
171     bool new_mac_with_chrome_mode) {
172   bool reentrant = IsTransitionReentrant(true, new_mac_with_chrome_mode);
173
174   mac_with_chrome_mode_ = new_mac_with_chrome_mode;
175   if (!IsFullscreen())
176     state_ = TO_FULLSCREEN;
177
178   if (reentrant)
179     ChangeWindowFullscreenState();
180 }
181
182 bool FullscreenControllerTestWindow::IsTransitionReentrant(
183     bool new_fullscreen,
184     bool new_mac_with_chrome_mode) {
185 #if defined(OS_MACOSX)
186   bool mac_with_chrome_mode_changed = new_mac_with_chrome_mode ?
187       IsFullscreenWithoutChrome() : IsFullscreenWithChrome();
188 #else
189   bool mac_with_chrome_mode_changed = false;
190 #endif
191   bool fullscreen_changed = (new_fullscreen != IsFullscreen());
192
193   if (!fullscreen_changed && !mac_with_chrome_mode_changed)
194     return false;
195
196   if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
197     return true;
198
199   // BrowserWindowCocoa::EnterFullscreen() and
200   // BrowserWindowCocoa::EnterFullscreenWithChrome() are reentrant when
201   // switching between fullscreen with chrome and fullscreen without chrome.
202   return state_ == FULLSCREEN &&
203       !fullscreen_changed &&
204       mac_with_chrome_mode_changed;
205 }
206
207
208 // FullscreenControllerStateUnitTest -------------------------------------------
209
210 // Unit test fixture testing Fullscreen Controller through its states. Most of
211 // the test logic comes from FullscreenControllerStateTest.
212 class FullscreenControllerStateUnitTest : public BrowserWithTestWindowTest,
213                                           public FullscreenControllerStateTest {
214  public:
215   FullscreenControllerStateUnitTest();
216
217   // FullscreenControllerStateTest:
218   virtual void SetUp() OVERRIDE;
219   virtual BrowserWindow* CreateBrowserWindow() OVERRIDE;
220   virtual void ChangeWindowFullscreenState() OVERRIDE;
221   virtual const char* GetWindowStateString() OVERRIDE;
222   virtual void VerifyWindowState() OVERRIDE;
223
224  protected:
225   // FullscreenControllerStateTest:
226   virtual bool ShouldSkipStateAndEventPair(State state, Event event) OVERRIDE;
227   virtual Browser* GetBrowser() OVERRIDE;
228   FullscreenControllerTestWindow* window_;
229 };
230
231 FullscreenControllerStateUnitTest::FullscreenControllerStateUnitTest ()
232     : window_(NULL) {
233 }
234
235 void FullscreenControllerStateUnitTest::SetUp() {
236   BrowserWithTestWindowTest::SetUp();
237   window_->set_browser(browser());
238 }
239
240 BrowserWindow* FullscreenControllerStateUnitTest::CreateBrowserWindow() {
241   window_ = new FullscreenControllerTestWindow();
242   return window_;  // BrowserWithTestWindowTest takes ownership.
243 }
244
245 void FullscreenControllerStateUnitTest::ChangeWindowFullscreenState() {
246   window_->ChangeWindowFullscreenState();
247 }
248
249 const char* FullscreenControllerStateUnitTest::GetWindowStateString() {
250   return FullscreenControllerTestWindow::GetWindowStateString(window_->state());
251 }
252
253 void FullscreenControllerStateUnitTest::VerifyWindowState() {
254   switch (state()) {
255     case STATE_NORMAL:
256       EXPECT_EQ(FullscreenControllerTestWindow::NORMAL,
257                 window_->state()) << GetAndClearDebugLog();
258       break;
259
260     case STATE_BROWSER_FULLSCREEN_NO_CHROME:
261     case STATE_BROWSER_FULLSCREEN_WITH_CHROME:
262     case STATE_TAB_FULLSCREEN:
263     case STATE_TAB_BROWSER_FULLSCREEN:
264     case STATE_TAB_BROWSER_FULLSCREEN_CHROME:
265       EXPECT_EQ(FullscreenControllerTestWindow::FULLSCREEN,
266                 window_->state()) << GetAndClearDebugLog();
267       break;
268
269 #if defined(OS_WIN)
270     case STATE_METRO_SNAP:
271       EXPECT_EQ(FullscreenControllerTestWindow::METRO_SNAP,
272                 window_->state()) << GetAndClearDebugLog();
273       break;
274 #endif
275
276     case STATE_TO_NORMAL:
277       EXPECT_EQ(FullscreenControllerTestWindow::TO_NORMAL,
278                 window_->state()) << GetAndClearDebugLog();
279       break;
280
281     case STATE_TO_BROWSER_FULLSCREEN_NO_CHROME:
282     case STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME:
283     case STATE_TO_TAB_FULLSCREEN:
284       EXPECT_EQ(FullscreenControllerTestWindow::TO_FULLSCREEN,
285                 window_->state()) << GetAndClearDebugLog();
286       break;
287
288     default:
289       NOTREACHED() << GetAndClearDebugLog();
290   }
291
292   FullscreenControllerStateTest::VerifyWindowState();
293 }
294
295 bool FullscreenControllerStateUnitTest::ShouldSkipStateAndEventPair(
296     State state, Event event) {
297 #if defined(OS_MACOSX)
298   // TODO(scheib) Toggle, Window Event, Toggle, Toggle on Mac as exposed by
299   // test *.STATE_TO_NORMAL__TOGGLE_FULLSCREEN runs interactively and exits to
300   // Normal. This doesn't appear to be the desired result, and would add
301   // too much complexity to mimic in our simple FullscreenControllerTestWindow.
302   // http://crbug.com/156968
303   if ((state == STATE_TO_NORMAL ||
304        state == STATE_TO_BROWSER_FULLSCREEN_NO_CHROME ||
305        state == STATE_TO_TAB_FULLSCREEN) &&
306       event == TOGGLE_FULLSCREEN)
307     return true;
308 #endif
309
310   return FullscreenControllerStateTest::ShouldSkipStateAndEventPair(state,
311                                                                     event);
312 }
313
314 Browser* FullscreenControllerStateUnitTest::GetBrowser() {
315   return BrowserWithTestWindowTest::browser();
316 }
317
318
319 // Soak tests ------------------------------------------------------------------
320
321 // Tests all states with all permutations of multiple events to detect lingering
322 // state issues that would bleed over to other states.
323 // I.E. for each state test all combinations of events E1, E2, E3.
324 //
325 // This produces coverage for event sequences that may happen normally but
326 // would not be exposed by traversing to each state via TransitionToState().
327 // TransitionToState() always takes the same path even when multiple paths
328 // exist.
329 TEST_F(FullscreenControllerStateUnitTest, TransitionsForEachState) {
330   // A tab is needed for tab fullscreen.
331   AddTab(browser(), GURL(content::kAboutBlankURL));
332   TestTransitionsForEachState();
333   // Progress of test can be examined via LOG(INFO) << GetAndClearDebugLog();
334 }
335
336
337 // Individual tests for each pair of state and event ---------------------------
338
339 #define TEST_EVENT(state, event) \
340     TEST_F(FullscreenControllerStateUnitTest, state##__##event) { \
341       AddTab(browser(), GURL(content::kAboutBlankURL)); \
342       ASSERT_NO_FATAL_FAILURE(TestStateAndEvent(state, event)) \
343           << GetAndClearDebugLog(); \
344     }
345     // Progress of tests can be examined by inserting the following line:
346     // LOG(INFO) << GetAndClearDebugLog(); }
347
348 #include "chrome/browser/ui/fullscreen/fullscreen_controller_state_tests.h"
349
350
351 // Specific one-off tests for known issues -------------------------------------
352
353 // TODO(scheib) Toggling Tab fullscreen while pending Tab or
354 // Browser fullscreen is broken currently http://crbug.com/154196
355 TEST_F(FullscreenControllerStateUnitTest,
356        DISABLED_ToggleTabWhenPendingBrowser) {
357   // Only possible without reentrancy.
358   if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
359     return;
360   AddTab(browser(), GURL(content::kAboutBlankURL));
361   ASSERT_NO_FATAL_FAILURE(
362       TransitionToState(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME))
363       << GetAndClearDebugLog();
364
365   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE)) << GetAndClearDebugLog();
366   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE)) << GetAndClearDebugLog();
367   ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE)) << GetAndClearDebugLog();
368 }
369
370 // TODO(scheib) Toggling Tab fullscreen while pending Tab or
371 // Browser fullscreen is broken currently http://crbug.com/154196
372 TEST_F(FullscreenControllerStateUnitTest, DISABLED_ToggleTabWhenPendingTab) {
373   // Only possible without reentrancy.
374   if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
375     return;
376   AddTab(browser(), GURL(content::kAboutBlankURL));
377   ASSERT_NO_FATAL_FAILURE(
378       TransitionToState(STATE_TO_TAB_FULLSCREEN))
379       << GetAndClearDebugLog();
380
381   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE)) << GetAndClearDebugLog();
382   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE)) << GetAndClearDebugLog();
383   ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE)) << GetAndClearDebugLog();
384 }
385
386 // Debugging utility: Display the transition tables. Intentionally disabled
387 TEST_F(FullscreenControllerStateUnitTest, DISABLED_DebugLogStateTables) {
388   std::ostringstream output;
389   output << "\n\nTransition Table:";
390   output << GetTransitionTableAsString();
391
392   output << "\n\nInitial transitions:";
393   output << GetStateTransitionsAsString();
394
395   // Calculate all transition pairs.
396   for (int state1_int = 0; state1_int < NUM_STATES; ++state1_int) {
397     State state1 = static_cast<State>(state1_int);
398     for (int state2_int = 0; state2_int < NUM_STATES; ++state2_int) {
399       State state2 = static_cast<State>(state2_int);
400       if (ShouldSkipStateAndEventPair(state1, EVENT_INVALID) ||
401           ShouldSkipStateAndEventPair(state2, EVENT_INVALID))
402         continue;
403       // Compute the transition
404       if (NextTransitionInShortestPath(state1, state2, NUM_STATES).state ==
405           STATE_INVALID) {
406         LOG(ERROR) << "Should be skipping state transitions for: "
407             << GetStateString(state1) << " " << GetStateString(state2);
408       }
409     }
410   }
411
412   output << "\n\nAll transitions:";
413   output << GetStateTransitionsAsString();
414   LOG(INFO) << output.str();
415 }
416
417 // Test that the fullscreen exit bubble is closed by
418 // WindowFullscreenStateChanged() if fullscreen is exited via BrowserWindow.
419 // This currently occurs when an extension exits fullscreen via changing the
420 // browser bounds.
421 TEST_F(FullscreenControllerStateUnitTest, ExitFullscreenViaBrowserWindow) {
422   AddTab(browser(), GURL(content::kAboutBlankURL));
423   ASSERT_TRUE(InvokeEvent(TOGGLE_FULLSCREEN));
424   ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
425   ASSERT_TRUE(browser()->window()->IsFullscreen());
426   // Exit fullscreen without going through fullscreen controller.
427   browser()->window()->ExitFullscreen();
428   ChangeWindowFullscreenState();
429   EXPECT_EQ(FEB_TYPE_NONE,
430             browser()->fullscreen_controller()->GetFullscreenExitBubbleType());
431 }
432
433 // Test that switching tabs takes the browser out of tab fullscreen.
434 TEST_F(FullscreenControllerStateUnitTest, ExitTabFullscreenViaSwitchingTab) {
435   AddTab(browser(), GURL(content::kAboutBlankURL));
436   AddTab(browser(), GURL(content::kAboutBlankURL));
437   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
438   ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
439   ASSERT_TRUE(browser()->window()->IsFullscreen());
440
441   browser()->tab_strip_model()->SelectNextTab();
442   ChangeWindowFullscreenState();
443   EXPECT_FALSE(browser()->window()->IsFullscreen());
444 }
445
446 // Test that switching tabs via detaching the active tab (which is in tab
447 // fullscreen) takes the browser out of tab fullscreen. This case can
448 // occur if the user is in both tab fullscreen and immersive browser fullscreen.
449 TEST_F(FullscreenControllerStateUnitTest, ExitTabFullscreenViaDetachingTab) {
450   AddTab(browser(), GURL(content::kAboutBlankURL));
451   AddTab(browser(), GURL(content::kAboutBlankURL));
452   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
453   ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
454   ASSERT_TRUE(browser()->window()->IsFullscreen());
455
456   scoped_ptr<content::WebContents> web_contents(
457       browser()->tab_strip_model()->DetachWebContentsAt(0));
458   ChangeWindowFullscreenState();
459   EXPECT_FALSE(browser()->window()->IsFullscreen());
460 }
461
462 // Test that replacing the web contents for a tab which is in tab fullscreen
463 // takes the browser out of tab fullscreen. This can occur if the user
464 // navigates to a prerendered page from a page which is tab fullscreen.
465 TEST_F(FullscreenControllerStateUnitTest, ExitTabFullscreenViaReplacingTab) {
466   AddTab(browser(), GURL(content::kAboutBlankURL));
467   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
468   ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
469   ASSERT_TRUE(browser()->window()->IsFullscreen());
470
471   content::WebContents* new_web_contents = content::WebContents::Create(
472       content::WebContents::CreateParams(profile()));
473   scoped_ptr<content::WebContents> old_web_contents(
474       browser()->tab_strip_model()->ReplaceWebContentsAt(
475           0, new_web_contents));
476   ChangeWindowFullscreenState();
477   EXPECT_FALSE(browser()->window()->IsFullscreen());
478 }
479
480 // Tests that, in a browser configured for Fullscreen-Within-Tab mode,
481 // fullscreening a screen-captured tab will NOT cause any fullscreen state
482 // change to the browser window. Furthermore, the test switches between tabs to
483 // confirm a captured tab will be resized by FullscreenController to the capture
484 // video resolution once the widget is detached from the UI.
485 //
486 // See 'FullscreenWithinTab Note' in fullscreen_controller.h.
487 TEST_F(FullscreenControllerStateUnitTest, OneCapturedFullscreenedTab) {
488   CommandLine::ForCurrentProcess()->
489       AppendSwitch(switches::kEmbedFlashFullscreen);
490   content::WebContentsDelegate* const wc_delegate =
491       static_cast<content::WebContentsDelegate*>(browser());
492   ASSERT_TRUE(wc_delegate->EmbedsFullscreenWidget());
493
494   AddTab(browser(), GURL(content::kAboutBlankURL));
495   AddTab(browser(), GURL(content::kAboutBlankURL));
496   content::WebContents* const first_tab =
497       browser()->tab_strip_model()->GetWebContentsAt(0);
498   content::WebContents* const second_tab =
499       browser()->tab_strip_model()->GetWebContentsAt(1);
500
501   // Activate the first tab and tell its WebContents it is being captured.
502   browser()->tab_strip_model()->ActivateTabAt(0, true);
503   const gfx::Size kCaptureSize(1280, 720);
504   first_tab->IncrementCapturerCount(kCaptureSize);
505   ASSERT_FALSE(browser()->window()->IsFullscreen());
506   ASSERT_FALSE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
507   ASSERT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
508   ASSERT_FALSE(GetFullscreenController()->IsFullscreenForTabOrPending());
509
510   // Enter tab fullscreen.  Since the tab is being captured, the browser window
511   // should not expand to fill the screen.
512   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
513   EXPECT_FALSE(browser()->window()->IsFullscreen());
514   EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
515   EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
516   EXPECT_FALSE(GetFullscreenController()->IsFullscreenForTabOrPending());
517
518   // Switch to the other tab.  Check that the first tab was resized to the
519   // WebContents' preferred size.
520   browser()->tab_strip_model()->ActivateTabAt(1, true);
521   EXPECT_FALSE(browser()->window()->IsFullscreen());
522   EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
523   EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
524   EXPECT_FALSE(GetFullscreenController()->IsFullscreenForTabOrPending());
525   // TODO(miu): Need to make an adjustment to content::WebContentsViewMac for
526   // the following to work:
527 #if !defined(OS_MACOSX)
528   EXPECT_EQ(kCaptureSize, first_tab->GetView()->GetViewBounds().size());
529 #endif
530
531   // Switch back to the first tab and exit fullscreen.
532   browser()->tab_strip_model()->ActivateTabAt(0, true);
533   EXPECT_FALSE(browser()->window()->IsFullscreen());
534   EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
535   EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
536   EXPECT_FALSE(GetFullscreenController()->IsFullscreenForTabOrPending());
537   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE));
538   EXPECT_FALSE(browser()->window()->IsFullscreen());
539   EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
540   EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
541   EXPECT_FALSE(GetFullscreenController()->IsFullscreenForTabOrPending());
542 }
543
544 // Tests that, in a browser configured for Fullscreen-Within-Tab mode, more than
545 // one tab can be in fullscreen mode at the same time without interfering with
546 // each other.  One tab is being screen-captured and is toggled into fullscreen
547 // mode, and then the user switches to another tab not being screen-captured and
548 // fullscreens it.  The first tab's fullscreen toggle does not affect the
549 // browser window fullscreen, while the second one's does.  Then, the order of
550 // operations is reversed.
551 //
552 // See 'FullscreenWithinTab Note' in fullscreen_controller.h.
553 TEST_F(FullscreenControllerStateUnitTest, TwoFullscreenedTabsOneCaptured) {
554   CommandLine::ForCurrentProcess()->
555       AppendSwitch(switches::kEmbedFlashFullscreen);
556   content::WebContentsDelegate* const wc_delegate =
557       static_cast<content::WebContentsDelegate*>(browser());
558   ASSERT_TRUE(wc_delegate->EmbedsFullscreenWidget());
559
560   AddTab(browser(), GURL(content::kAboutBlankURL));
561   AddTab(browser(), GURL(content::kAboutBlankURL));
562   content::WebContents* const first_tab =
563       browser()->tab_strip_model()->GetWebContentsAt(0);
564   content::WebContents* const second_tab =
565       browser()->tab_strip_model()->GetWebContentsAt(1);
566
567   // Start capturing the first tab, fullscreen it, then switch to the second tab
568   // and fullscreen that.  The second tab will cause the browser window to
569   // expand to fill the screen.
570   browser()->tab_strip_model()->ActivateTabAt(0, true);
571   const gfx::Size kCaptureSize(1280, 720);
572   first_tab->IncrementCapturerCount(kCaptureSize);
573   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
574   EXPECT_FALSE(browser()->window()->IsFullscreen());
575   EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
576   EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
577   EXPECT_FALSE(GetFullscreenController()->IsFullscreenForTabOrPending());
578   browser()->tab_strip_model()->ActivateTabAt(1, true);
579   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
580   ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
581   EXPECT_TRUE(browser()->window()->IsFullscreen());
582   EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
583   EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
584   EXPECT_TRUE(GetFullscreenController()->IsFullscreenForTabOrPending());
585
586   // Now exit fullscreen while still in the second tab.  The browser window
587   // should no longer be fullscreened.
588   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE));
589   ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
590   EXPECT_FALSE(browser()->window()->IsFullscreen());
591   EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
592   EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
593   EXPECT_FALSE(GetFullscreenController()->IsFullscreenForTabOrPending());
594
595   // Finally, exit fullscreen on the captured tab.
596   browser()->tab_strip_model()->ActivateTabAt(0, true);
597   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE));
598   EXPECT_FALSE(browser()->window()->IsFullscreen());
599   EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
600   EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
601   EXPECT_FALSE(GetFullscreenController()->IsFullscreenForTabOrPending());
602 }
603
604 // Tests that, in a browser configured for Fullscreen-Within-Tab mode, more than
605 // one tab can be in fullscreen mode at the same time.  This is like the
606 // TwoFullscreenedTabsOneCaptured test above, except that the screen-captured
607 // tab exits fullscreen mode while the second tab is still in the foreground.
608 // When the first tab exits fullscreen, the fullscreen state of the second tab
609 // and the browser window should remain unchanged.
610 //
611 // See 'FullscreenWithinTab Note' in fullscreen_controller.h.
612 TEST_F(FullscreenControllerStateUnitTest,
613        BackgroundCapturedTabExitsFullscreen) {
614   CommandLine::ForCurrentProcess()->
615       AppendSwitch(switches::kEmbedFlashFullscreen);
616   content::WebContentsDelegate* const wc_delegate =
617       static_cast<content::WebContentsDelegate*>(browser());
618   ASSERT_TRUE(wc_delegate->EmbedsFullscreenWidget());
619
620   AddTab(browser(), GURL(content::kAboutBlankURL));
621   AddTab(browser(), GURL(content::kAboutBlankURL));
622   content::WebContents* const first_tab =
623       browser()->tab_strip_model()->GetWebContentsAt(0);
624   content::WebContents* const second_tab =
625       browser()->tab_strip_model()->GetWebContentsAt(1);
626
627   // Start capturing the first tab, fullscreen it, then switch to the second tab
628   // and fullscreen that.  The second tab will cause the browser window to
629   // expand to fill the screen.
630   browser()->tab_strip_model()->ActivateTabAt(0, true);
631   const gfx::Size kCaptureSize(1280, 720);
632   first_tab->IncrementCapturerCount(kCaptureSize);
633   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
634   EXPECT_FALSE(browser()->window()->IsFullscreen());
635   EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
636   EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
637   EXPECT_FALSE(GetFullscreenController()->IsFullscreenForTabOrPending());
638   browser()->tab_strip_model()->ActivateTabAt(1, true);
639   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
640   ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
641   EXPECT_TRUE(browser()->window()->IsFullscreen());
642   EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
643   EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
644   EXPECT_TRUE(GetFullscreenController()->IsFullscreenForTabOrPending());
645
646   // Now, the first tab (backgrounded) exits fullscreen.  This should not affect
647   // the second tab's fullscreen, nor the state of the browser window.
648   GetFullscreenController()->ToggleFullscreenModeForTab(first_tab, false);
649   EXPECT_TRUE(browser()->window()->IsFullscreen());
650   EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
651   EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
652   EXPECT_TRUE(GetFullscreenController()->IsFullscreenForTabOrPending());
653
654   // Finally, exit fullscreen on the second tab.
655   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE));
656   ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
657   EXPECT_FALSE(browser()->window()->IsFullscreen());
658   EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
659   EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
660   EXPECT_FALSE(GetFullscreenController()->IsFullscreenForTabOrPending());
661 }
662
663 // Tests that, in a browser configured for Fullscreen-Within-Tab mode,
664 // fullscreening a screen-captured tab will NOT cause any fullscreen state
665 // change to the browser window. Then, toggling Browser Fullscreen mode should
666 // fullscreen the browser window, but this should behave fully independently of
667 // the tab's fullscreen state.
668 //
669 // See 'FullscreenWithinTab Note' in fullscreen_controller.h.
670 TEST_F(FullscreenControllerStateUnitTest,
671        OneCapturedTabFullscreenedBeforeBrowserFullscreen) {
672   CommandLine::ForCurrentProcess()->
673       AppendSwitch(switches::kEmbedFlashFullscreen);
674   content::WebContentsDelegate* const wc_delegate =
675       static_cast<content::WebContentsDelegate*>(browser());
676   ASSERT_TRUE(wc_delegate->EmbedsFullscreenWidget());
677
678   AddTab(browser(), GURL(content::kAboutBlankURL));
679   content::WebContents* const tab =
680       browser()->tab_strip_model()->GetWebContentsAt(0);
681
682   // Start capturing the tab and fullscreen it.  The state of the browser window
683   // should remain unchanged.
684   browser()->tab_strip_model()->ActivateTabAt(0, true);
685   const gfx::Size kCaptureSize(1280, 720);
686   tab->IncrementCapturerCount(kCaptureSize);
687   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
688   EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(tab));
689   EXPECT_FALSE(GetFullscreenController()->IsFullscreenForTabOrPending());
690   EXPECT_FALSE(GetFullscreenController()->IsFullscreenForBrowser());
691
692   // Now, toggle into Browser Fullscreen mode.  The browser window should now be
693   // fullscreened.
694   ASSERT_TRUE(InvokeEvent(TOGGLE_FULLSCREEN));
695   ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
696   EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(tab));
697   EXPECT_FALSE(GetFullscreenController()->IsFullscreenForTabOrPending());
698   EXPECT_TRUE(GetFullscreenController()->IsFullscreenForBrowser());
699
700   // Now, toggle back out of Browser Fullscreen mode.  The browser window exits
701   // fullscreen mode, but the tab stays in fullscreen mode.
702   ASSERT_TRUE(InvokeEvent(TOGGLE_FULLSCREEN));
703   ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
704   EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(tab));
705   EXPECT_FALSE(GetFullscreenController()->IsFullscreenForTabOrPending());
706   EXPECT_FALSE(GetFullscreenController()->IsFullscreenForBrowser());
707
708   // Finally, toggle back into Browser Fullscreen mode and then toggle out of
709   // tab fullscreen mode.  The browser window should stay fullscreened, while
710   // the tab exits fullscreen mode.
711   ASSERT_TRUE(InvokeEvent(TOGGLE_FULLSCREEN));
712   ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
713   ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE));
714   EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(tab));
715   EXPECT_FALSE(GetFullscreenController()->IsFullscreenForTabOrPending());
716   EXPECT_TRUE(GetFullscreenController()->IsFullscreenForBrowser());
717 }