1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #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"
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.
24 // FullscreenControllerTestWindow ----------------------------------------------
26 // A BrowserWindow used for testing FullscreenController. The behavior of this
27 // mock is verfied manually by running FullscreenControllerStateInteractiveTest.
28 class FullscreenControllerTestWindow : public TestBrowserWindow {
30 // Simulate the window state with an enumeration.
34 // No TO_ state for METRO_SNAP, the windows implementation is synchronous.
40 FullscreenControllerTestWindow();
41 virtual ~FullscreenControllerTestWindow() {}
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;
50 virtual void SetMetroSnapMode(bool enable) OVERRIDE;
51 virtual bool IsInMetroSnapMode() const OVERRIDE;
53 #if defined(OS_MACOSX)
54 virtual void EnterFullscreenWithChrome() OVERRIDE;
55 virtual bool IsFullscreenWithChrome() OVERRIDE;
56 virtual bool IsFullscreenWithoutChrome() OVERRIDE;
59 static const char* GetWindowStateString(WindowState state);
60 WindowState state() const { return state_; }
61 void set_browser(Browser* browser) { browser_ = browser; }
63 // Simulates the window changing state.
64 void ChangeWindowFullscreenState();
67 // Enters fullscreen with |new_mac_with_chrome_mode|.
68 void EnterFullscreen(bool new_mac_with_chrome_mode);
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);
76 bool mac_with_chrome_mode_;
80 FullscreenControllerTestWindow::FullscreenControllerTestWindow()
82 mac_with_chrome_mode_(false),
86 void FullscreenControllerTestWindow::EnterFullscreen(
87 const GURL& url, FullscreenExitBubbleType type) {
88 EnterFullscreen(false);
91 void FullscreenControllerTestWindow::ExitFullscreen() {
94 mac_with_chrome_mode_ = false;
96 if (IsTransitionReentrant(false, false))
97 ChangeWindowFullscreenState();
101 bool FullscreenControllerTestWindow::ShouldHideUIForFullscreen() const {
102 return IsFullscreen();
105 bool FullscreenControllerTestWindow::IsFullscreen() const {
106 #if defined(OS_MACOSX)
107 return state_ == FULLSCREEN || state_ == TO_FULLSCREEN;
109 return state_ == FULLSCREEN || state_ == TO_NORMAL;
114 void FullscreenControllerTestWindow::SetMetroSnapMode(bool enable) {
115 if (enable != IsInMetroSnapMode())
116 state_ = enable ? METRO_SNAP : NORMAL;
118 if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
119 ChangeWindowFullscreenState();
122 bool FullscreenControllerTestWindow::IsInMetroSnapMode() const {
123 return state_ == METRO_SNAP;
127 #if defined(OS_MACOSX)
128 void FullscreenControllerTestWindow::EnterFullscreenWithChrome() {
129 EnterFullscreen(true);
132 bool FullscreenControllerTestWindow::IsFullscreenWithChrome() {
133 return IsFullscreen() && mac_with_chrome_mode_;
136 bool FullscreenControllerTestWindow::IsFullscreenWithoutChrome() {
137 return IsFullscreen() && !mac_with_chrome_mode_;
142 const char* FullscreenControllerTestWindow::GetWindowStateString(
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);
151 NOTREACHED() << "No string for state " << state;
152 return "WindowState-Unknown";
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)
162 else if (state_ == TO_NORMAL)
165 // Emit a change event from every state to ensure the Fullscreen Controller
166 // handles it in all circumstances.
167 browser_->WindowFullscreenStateChanged();
170 void FullscreenControllerTestWindow::EnterFullscreen(
171 bool new_mac_with_chrome_mode) {
172 bool reentrant = IsTransitionReentrant(true, new_mac_with_chrome_mode);
174 mac_with_chrome_mode_ = new_mac_with_chrome_mode;
176 state_ = TO_FULLSCREEN;
179 ChangeWindowFullscreenState();
182 bool FullscreenControllerTestWindow::IsTransitionReentrant(
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();
189 bool mac_with_chrome_mode_changed = false;
191 bool fullscreen_changed = (new_fullscreen != IsFullscreen());
193 if (!fullscreen_changed && !mac_with_chrome_mode_changed)
196 if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
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;
208 // FullscreenControllerStateUnitTest -------------------------------------------
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 {
215 FullscreenControllerStateUnitTest();
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;
225 // FullscreenControllerStateTest:
226 virtual bool ShouldSkipStateAndEventPair(State state, Event event) OVERRIDE;
227 virtual Browser* GetBrowser() OVERRIDE;
228 FullscreenControllerTestWindow* window_;
231 FullscreenControllerStateUnitTest::FullscreenControllerStateUnitTest ()
235 void FullscreenControllerStateUnitTest::SetUp() {
236 BrowserWithTestWindowTest::SetUp();
237 window_->set_browser(browser());
240 BrowserWindow* FullscreenControllerStateUnitTest::CreateBrowserWindow() {
241 window_ = new FullscreenControllerTestWindow();
242 return window_; // BrowserWithTestWindowTest takes ownership.
245 void FullscreenControllerStateUnitTest::ChangeWindowFullscreenState() {
246 window_->ChangeWindowFullscreenState();
249 const char* FullscreenControllerStateUnitTest::GetWindowStateString() {
250 return FullscreenControllerTestWindow::GetWindowStateString(window_->state());
253 void FullscreenControllerStateUnitTest::VerifyWindowState() {
256 EXPECT_EQ(FullscreenControllerTestWindow::NORMAL,
257 window_->state()) << GetAndClearDebugLog();
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();
270 case STATE_METRO_SNAP:
271 EXPECT_EQ(FullscreenControllerTestWindow::METRO_SNAP,
272 window_->state()) << GetAndClearDebugLog();
276 case STATE_TO_NORMAL:
277 EXPECT_EQ(FullscreenControllerTestWindow::TO_NORMAL,
278 window_->state()) << GetAndClearDebugLog();
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();
289 NOTREACHED() << GetAndClearDebugLog();
292 FullscreenControllerStateTest::VerifyWindowState();
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)
310 return FullscreenControllerStateTest::ShouldSkipStateAndEventPair(state,
314 Browser* FullscreenControllerStateUnitTest::GetBrowser() {
315 return BrowserWithTestWindowTest::browser();
319 // Soak tests ------------------------------------------------------------------
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.
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
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();
337 // Individual tests for each pair of state and event ---------------------------
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(); \
345 // Progress of tests can be examined by inserting the following line:
346 // LOG(INFO) << GetAndClearDebugLog(); }
348 #include "chrome/browser/ui/fullscreen/fullscreen_controller_state_tests.h"
351 // Specific one-off tests for known issues -------------------------------------
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())
360 AddTab(browser(), GURL(content::kAboutBlankURL));
361 ASSERT_NO_FATAL_FAILURE(
362 TransitionToState(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME))
363 << GetAndClearDebugLog();
365 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE)) << GetAndClearDebugLog();
366 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE)) << GetAndClearDebugLog();
367 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE)) << GetAndClearDebugLog();
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())
376 AddTab(browser(), GURL(content::kAboutBlankURL));
377 ASSERT_NO_FATAL_FAILURE(
378 TransitionToState(STATE_TO_TAB_FULLSCREEN))
379 << GetAndClearDebugLog();
381 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE)) << GetAndClearDebugLog();
382 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE)) << GetAndClearDebugLog();
383 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE)) << GetAndClearDebugLog();
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();
392 output << "\n\nInitial transitions:";
393 output << GetStateTransitionsAsString();
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))
403 // Compute the transition
404 if (NextTransitionInShortestPath(state1, state2, NUM_STATES).state ==
406 LOG(ERROR) << "Should be skipping state transitions for: "
407 << GetStateString(state1) << " " << GetStateString(state2);
412 output << "\n\nAll transitions:";
413 output << GetStateTransitionsAsString();
414 LOG(INFO) << output.str();
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
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());
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());
441 browser()->tab_strip_model()->SelectNextTab();
442 ChangeWindowFullscreenState();
443 EXPECT_FALSE(browser()->window()->IsFullscreen());
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());
456 scoped_ptr<content::WebContents> web_contents(
457 browser()->tab_strip_model()->DetachWebContentsAt(0));
458 ChangeWindowFullscreenState();
459 EXPECT_FALSE(browser()->window()->IsFullscreen());
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());
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());
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.
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());
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);
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());
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());
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());
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());
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.
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());
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);
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());
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());
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());
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.
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());
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);
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());
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());
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());
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.
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());
678 AddTab(browser(), GURL(content::kAboutBlankURL));
679 content::WebContents* const tab =
680 browser()->tab_strip_model()->GetWebContentsAt(0);
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());
692 // Now, toggle into Browser Fullscreen mode. The browser window should now be
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());
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());
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());