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/exclusive_access/fullscreen_controller.h"
10 #include "chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.h"
11 #include "chrome/browser/ui/tabs/tab_strip_model.h"
12 #include "chrome/test/base/browser_with_test_window_test.h"
13 #include "content/public/browser/web_contents.h"
14 #include "content/public/common/url_constants.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 // The FullscreenControllerStateUnitTest unit test suite exhastively tests
18 // the FullscreenController through all permutations of events. The behavior
19 // of the BrowserWindow is mocked via FullscreenControllerTestWindow.
22 // FullscreenControllerTestWindow ----------------------------------------------
24 // A BrowserWindow used for testing FullscreenController. The behavior of this
25 // mock is verfied manually by running FullscreenControllerStateInteractiveTest.
26 class FullscreenControllerTestWindow
: public TestBrowserWindow
{
28 // Simulate the window state with an enumeration.
32 // No TO_ state for METRO_SNAP, the windows implementation is synchronous.
38 FullscreenControllerTestWindow();
39 ~FullscreenControllerTestWindow() override
{}
41 // BrowserWindow Interface:
42 void EnterFullscreen(const GURL
& url
,
43 ExclusiveAccessBubbleType type
,
44 bool with_toolbar
) override
;
45 void ExitFullscreen() override
;
46 bool ShouldHideUIForFullscreen() const override
;
47 bool IsFullscreen() const override
;
48 bool SupportsFullscreenWithToolbar() const override
;
49 void UpdateFullscreenWithToolbar(bool with_toolbar
) override
;
50 bool IsFullscreenWithToolbar() const override
;
52 virtual void SetMetroSnapMode(bool enable
) override
;
53 virtual bool IsInMetroSnapMode() const override
;
55 static const char* GetWindowStateString(WindowState state
);
56 WindowState
state() const { return state_
; }
57 void set_browser(Browser
* browser
) { browser_
= browser
; }
59 // Simulates the window changing state.
60 void ChangeWindowFullscreenState();
63 // Enters fullscreen with |new_mac_with_toolbar_mode|.
64 void EnterFullscreen(bool new_mac_with_toolbar_mode
);
66 // Returns true if ChangeWindowFullscreenState() should be called as a result
67 // of updating the current fullscreen state to the passed in state.
68 bool IsTransitionReentrant(bool new_fullscreen
,
69 bool new_mac_with_toolbar_mode
);
72 bool mac_with_toolbar_mode_
;
76 FullscreenControllerTestWindow::FullscreenControllerTestWindow()
78 mac_with_toolbar_mode_(false),
82 void FullscreenControllerTestWindow::EnterFullscreen(
84 ExclusiveAccessBubbleType type
,
86 EnterFullscreen(with_toolbar
);
89 void FullscreenControllerTestWindow::ExitFullscreen() {
92 mac_with_toolbar_mode_
= false;
94 if (IsTransitionReentrant(false, false))
95 ChangeWindowFullscreenState();
99 bool FullscreenControllerTestWindow::ShouldHideUIForFullscreen() const {
100 return IsFullscreen();
103 bool FullscreenControllerTestWindow::IsFullscreen() const {
104 #if defined(OS_MACOSX)
105 return state_
== FULLSCREEN
|| state_
== TO_FULLSCREEN
;
107 return state_
== FULLSCREEN
|| state_
== TO_NORMAL
;
111 bool FullscreenControllerTestWindow::SupportsFullscreenWithToolbar() const {
112 #if defined(OS_MACOSX)
119 void FullscreenControllerTestWindow::UpdateFullscreenWithToolbar(
121 EnterFullscreen(with_toolbar
);
124 bool FullscreenControllerTestWindow::IsFullscreenWithToolbar() const {
125 return IsFullscreen() && mac_with_toolbar_mode_
;
129 void FullscreenControllerTestWindow::SetMetroSnapMode(bool enable
) {
130 if (enable
!= IsInMetroSnapMode())
131 state_
= enable
? METRO_SNAP
: NORMAL
;
133 if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
134 ChangeWindowFullscreenState();
137 bool FullscreenControllerTestWindow::IsInMetroSnapMode() const {
138 return state_
== METRO_SNAP
;
143 const char* FullscreenControllerTestWindow::GetWindowStateString(
146 ENUM_TO_STRING(NORMAL
);
147 ENUM_TO_STRING(FULLSCREEN
);
148 ENUM_TO_STRING(METRO_SNAP
);
149 ENUM_TO_STRING(TO_FULLSCREEN
);
150 ENUM_TO_STRING(TO_NORMAL
);
152 NOTREACHED() << "No string for state " << state
;
153 return "WindowState-Unknown";
157 void FullscreenControllerTestWindow::ChangeWindowFullscreenState() {
158 // Most states result in "no operation" intentionally. The tests
159 // assume that all possible states and event pairs can be tested, even
160 // though window managers will not generate all of these.
161 if (state_
== TO_FULLSCREEN
)
163 else if (state_
== TO_NORMAL
)
166 // Emit a change event from every state to ensure the Fullscreen Controller
167 // handles it in all circumstances.
168 browser_
->WindowFullscreenStateChanged();
171 void FullscreenControllerTestWindow::EnterFullscreen(
172 bool new_mac_with_toolbar_mode
) {
173 bool reentrant
= IsTransitionReentrant(true, new_mac_with_toolbar_mode
);
175 mac_with_toolbar_mode_
= new_mac_with_toolbar_mode
;
177 state_
= TO_FULLSCREEN
;
180 ChangeWindowFullscreenState();
183 bool FullscreenControllerTestWindow::IsTransitionReentrant(
185 bool new_mac_with_toolbar_mode
) {
186 #if defined(OS_MACOSX)
187 bool mac_with_toolbar_mode_changed
=
188 new_mac_with_toolbar_mode
!= IsFullscreenWithToolbar();
190 bool mac_with_toolbar_mode_changed
= false;
192 bool fullscreen_changed
= (new_fullscreen
!= IsFullscreen());
194 if (!fullscreen_changed
&& !mac_with_toolbar_mode_changed
)
197 if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
200 // BrowserWindowCocoa::EnterFullscreen() and
201 // BrowserWindowCocoa::EnterFullscreenWithToolbar() are reentrant when
202 // switching between fullscreen with chrome and fullscreen without chrome.
203 return state_
== FULLSCREEN
&&
204 !fullscreen_changed
&&
205 mac_with_toolbar_mode_changed
;
209 // FullscreenControllerStateUnitTest -------------------------------------------
211 // Unit test fixture testing Fullscreen Controller through its states. Most of
212 // the test logic comes from FullscreenControllerStateTest.
213 class FullscreenControllerStateUnitTest
: public BrowserWithTestWindowTest
,
214 public FullscreenControllerStateTest
{
216 FullscreenControllerStateUnitTest();
218 // FullscreenControllerStateTest:
219 void SetUp() override
;
220 BrowserWindow
* CreateBrowserWindow() override
;
221 void ChangeWindowFullscreenState() override
;
222 const char* GetWindowStateString() override
;
223 void VerifyWindowState() override
;
226 // FullscreenControllerStateTest:
227 bool ShouldSkipStateAndEventPair(State state
, Event event
) override
;
228 Browser
* GetBrowser() override
;
229 FullscreenControllerTestWindow
* window_
;
232 FullscreenControllerStateUnitTest::FullscreenControllerStateUnitTest ()
236 void FullscreenControllerStateUnitTest::SetUp() {
237 BrowserWithTestWindowTest::SetUp();
238 window_
->set_browser(browser());
241 BrowserWindow
* FullscreenControllerStateUnitTest::CreateBrowserWindow() {
242 window_
= new FullscreenControllerTestWindow();
243 return window_
; // BrowserWithTestWindowTest takes ownership.
246 void FullscreenControllerStateUnitTest::ChangeWindowFullscreenState() {
247 window_
->ChangeWindowFullscreenState();
250 const char* FullscreenControllerStateUnitTest::GetWindowStateString() {
251 return FullscreenControllerTestWindow::GetWindowStateString(window_
->state());
254 void FullscreenControllerStateUnitTest::VerifyWindowState() {
257 EXPECT_EQ(FullscreenControllerTestWindow::NORMAL
,
258 window_
->state()) << GetAndClearDebugLog();
261 case STATE_BROWSER_FULLSCREEN_NO_CHROME
:
262 case STATE_BROWSER_FULLSCREEN_WITH_CHROME
:
263 case STATE_TAB_FULLSCREEN
:
264 case STATE_TAB_BROWSER_FULLSCREEN
:
265 case STATE_TAB_BROWSER_FULLSCREEN_CHROME
:
266 EXPECT_EQ(FullscreenControllerTestWindow::FULLSCREEN
,
267 window_
->state()) << GetAndClearDebugLog();
271 case STATE_METRO_SNAP
:
272 EXPECT_EQ(FullscreenControllerTestWindow::METRO_SNAP
,
273 window_
->state()) << GetAndClearDebugLog();
277 case STATE_TO_NORMAL
:
278 EXPECT_EQ(FullscreenControllerTestWindow::TO_NORMAL
,
279 window_
->state()) << GetAndClearDebugLog();
282 case STATE_TO_BROWSER_FULLSCREEN_NO_CHROME
:
283 case STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME
:
284 case STATE_TO_TAB_FULLSCREEN
:
285 EXPECT_EQ(FullscreenControllerTestWindow::TO_FULLSCREEN
,
286 window_
->state()) << GetAndClearDebugLog();
290 NOTREACHED() << GetAndClearDebugLog();
293 FullscreenControllerStateTest::VerifyWindowState();
296 bool FullscreenControllerStateUnitTest::ShouldSkipStateAndEventPair(
297 State state
, Event event
) {
298 #if defined(OS_MACOSX)
299 // TODO(scheib) Toggle, Window Event, Toggle, Toggle on Mac as exposed by
300 // test *.STATE_TO_NORMAL__TOGGLE_FULLSCREEN runs interactively and exits to
301 // Normal. This doesn't appear to be the desired result, and would add
302 // too much complexity to mimic in our simple FullscreenControllerTestWindow.
303 // http://crbug.com/156968
304 if ((state
== STATE_TO_NORMAL
||
305 state
== STATE_TO_BROWSER_FULLSCREEN_NO_CHROME
||
306 state
== STATE_TO_TAB_FULLSCREEN
) &&
307 event
== TOGGLE_FULLSCREEN
)
311 return FullscreenControllerStateTest::ShouldSkipStateAndEventPair(state
,
315 Browser
* FullscreenControllerStateUnitTest::GetBrowser() {
316 return BrowserWithTestWindowTest::browser();
320 // Soak tests ------------------------------------------------------------------
322 // Tests all states with all permutations of multiple events to detect lingering
323 // state issues that would bleed over to other states.
324 // I.E. for each state test all combinations of events E1, E2, E3.
326 // This produces coverage for event sequences that may happen normally but
327 // would not be exposed by traversing to each state via TransitionToState().
328 // TransitionToState() always takes the same path even when multiple paths
330 TEST_F(FullscreenControllerStateUnitTest
, TransitionsForEachState
) {
331 // A tab is needed for tab fullscreen.
332 AddTab(browser(), GURL(url::kAboutBlankURL
));
333 TestTransitionsForEachState();
334 // Progress of test can be examined via LOG(INFO) << GetAndClearDebugLog();
338 // Individual tests for each pair of state and event ---------------------------
340 #define TEST_EVENT(state, event) \
341 TEST_F(FullscreenControllerStateUnitTest, state##__##event) { \
342 AddTab(browser(), GURL(url::kAboutBlankURL)); \
343 ASSERT_NO_FATAL_FAILURE(TestStateAndEvent(state, event)) \
344 << GetAndClearDebugLog(); \
346 // Progress of tests can be examined by inserting the following line:
347 // LOG(INFO) << GetAndClearDebugLog(); }
349 #include "chrome/browser/ui/exclusive_access/fullscreen_controller_state_tests.h"
352 // Specific one-off tests for known issues -------------------------------------
354 // TODO(scheib) Toggling Tab fullscreen while pending Tab or
355 // Browser fullscreen is broken currently http://crbug.com/154196
356 TEST_F(FullscreenControllerStateUnitTest
,
357 DISABLED_ToggleTabWhenPendingBrowser
) {
358 // Only possible without reentrancy.
359 if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
361 AddTab(browser(), GURL(url::kAboutBlankURL
));
362 ASSERT_NO_FATAL_FAILURE(
363 TransitionToState(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME
))
364 << GetAndClearDebugLog();
366 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE
)) << GetAndClearDebugLog();
367 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE
)) << GetAndClearDebugLog();
368 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE
)) << GetAndClearDebugLog();
371 // TODO(scheib) Toggling Tab fullscreen while pending Tab or
372 // Browser fullscreen is broken currently http://crbug.com/154196
373 TEST_F(FullscreenControllerStateUnitTest
, DISABLED_ToggleTabWhenPendingTab
) {
374 // Only possible without reentrancy.
375 if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
377 AddTab(browser(), GURL(url::kAboutBlankURL
));
378 ASSERT_NO_FATAL_FAILURE(
379 TransitionToState(STATE_TO_TAB_FULLSCREEN
))
380 << GetAndClearDebugLog();
382 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE
)) << GetAndClearDebugLog();
383 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE
)) << GetAndClearDebugLog();
384 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE
)) << GetAndClearDebugLog();
387 // Debugging utility: Display the transition tables. Intentionally disabled
388 TEST_F(FullscreenControllerStateUnitTest
, DISABLED_DebugLogStateTables
) {
389 std::ostringstream output
;
390 output
<< "\n\nTransition Table:";
391 output
<< GetTransitionTableAsString();
393 output
<< "\n\nInitial transitions:";
394 output
<< GetStateTransitionsAsString();
396 // Calculate all transition pairs.
397 for (int state1_int
= 0; state1_int
< NUM_STATES
; ++state1_int
) {
398 State state1
= static_cast<State
>(state1_int
);
399 for (int state2_int
= 0; state2_int
< NUM_STATES
; ++state2_int
) {
400 State state2
= static_cast<State
>(state2_int
);
401 if (ShouldSkipStateAndEventPair(state1
, EVENT_INVALID
) ||
402 ShouldSkipStateAndEventPair(state2
, EVENT_INVALID
))
404 // Compute the transition
405 if (NextTransitionInShortestPath(state1
, state2
, NUM_STATES
).state
==
407 LOG(ERROR
) << "Should be skipping state transitions for: "
408 << GetStateString(state1
) << " " << GetStateString(state2
);
413 output
<< "\n\nAll transitions:";
414 output
<< GetStateTransitionsAsString();
415 LOG(INFO
) << output
.str();
418 // Test that the fullscreen exit bubble is closed by
419 // WindowFullscreenStateChanged() if fullscreen is exited via BrowserWindow.
420 // This currently occurs when an extension exits fullscreen via changing the
422 TEST_F(FullscreenControllerStateUnitTest
, ExitFullscreenViaBrowserWindow
) {
423 AddTab(browser(), GURL(url::kAboutBlankURL
));
424 ASSERT_TRUE(InvokeEvent(TOGGLE_FULLSCREEN
));
425 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE
));
426 ASSERT_TRUE(browser()->window()->IsFullscreen());
427 // Exit fullscreen without going through fullscreen controller.
428 browser()->window()->ExitFullscreen();
429 ChangeWindowFullscreenState();
430 EXPECT_EQ(EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE
,
432 ->exclusive_access_manager()
433 ->GetExclusiveAccessExitBubbleType());
436 // Test that switching tabs takes the browser out of tab fullscreen.
437 TEST_F(FullscreenControllerStateUnitTest
, ExitTabFullscreenViaSwitchingTab
) {
438 AddTab(browser(), GURL(url::kAboutBlankURL
));
439 AddTab(browser(), GURL(url::kAboutBlankURL
));
440 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE
));
441 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE
));
442 ASSERT_TRUE(browser()->window()->IsFullscreen());
444 browser()->tab_strip_model()->SelectNextTab();
445 ChangeWindowFullscreenState();
446 EXPECT_FALSE(browser()->window()->IsFullscreen());
449 // Test that switching tabs via detaching the active tab (which is in tab
450 // fullscreen) takes the browser out of tab fullscreen. This case can
451 // occur if the user is in both tab fullscreen and immersive browser fullscreen.
452 TEST_F(FullscreenControllerStateUnitTest
, ExitTabFullscreenViaDetachingTab
) {
453 AddTab(browser(), GURL(url::kAboutBlankURL
));
454 AddTab(browser(), GURL(url::kAboutBlankURL
));
455 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE
));
456 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE
));
457 ASSERT_TRUE(browser()->window()->IsFullscreen());
459 scoped_ptr
<content::WebContents
> web_contents(
460 browser()->tab_strip_model()->DetachWebContentsAt(0));
461 ChangeWindowFullscreenState();
462 EXPECT_FALSE(browser()->window()->IsFullscreen());
465 // Test that replacing the web contents for a tab which is in tab fullscreen
466 // takes the browser out of tab fullscreen. This can occur if the user
467 // navigates to a prerendered page from a page which is tab fullscreen.
468 TEST_F(FullscreenControllerStateUnitTest
, ExitTabFullscreenViaReplacingTab
) {
469 AddTab(browser(), GURL(url::kAboutBlankURL
));
470 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE
));
471 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE
));
472 ASSERT_TRUE(browser()->window()->IsFullscreen());
474 content::WebContents
* new_web_contents
= content::WebContents::Create(
475 content::WebContents::CreateParams(profile()));
476 scoped_ptr
<content::WebContents
> old_web_contents(
477 browser()->tab_strip_model()->ReplaceWebContentsAt(
478 0, new_web_contents
));
479 ChangeWindowFullscreenState();
480 EXPECT_FALSE(browser()->window()->IsFullscreen());
483 // Tests that, in a browser configured for Fullscreen-Within-Tab mode,
484 // fullscreening a screen-captured tab will NOT cause any fullscreen state
485 // change to the browser window. Furthermore, the test switches between tabs to
486 // confirm a captured tab will be resized by FullscreenController to the capture
487 // video resolution once the widget is detached from the UI.
489 // See 'FullscreenWithinTab Note' in fullscreen_controller.h.
490 TEST_F(FullscreenControllerStateUnitTest
, OneCapturedFullscreenedTab
) {
491 content::WebContentsDelegate
* const wc_delegate
=
492 static_cast<content::WebContentsDelegate
*>(browser());
493 ASSERT_TRUE(wc_delegate
->EmbedsFullscreenWidget());
495 AddTab(browser(), GURL(url::kAboutBlankURL
));
496 AddTab(browser(), GURL(url::kAboutBlankURL
));
497 content::WebContents
* const first_tab
=
498 browser()->tab_strip_model()->GetWebContentsAt(0);
499 content::WebContents
* const second_tab
=
500 browser()->tab_strip_model()->GetWebContentsAt(1);
502 // Activate the first tab and tell its WebContents it is being captured.
503 browser()->tab_strip_model()->ActivateTabAt(0, true);
504 const gfx::Size
kCaptureSize(1280, 720);
505 first_tab
->IncrementCapturerCount(kCaptureSize
);
506 ASSERT_FALSE(browser()->window()->IsFullscreen());
507 ASSERT_FALSE(wc_delegate
->IsFullscreenForTabOrPending(first_tab
));
508 ASSERT_FALSE(wc_delegate
->IsFullscreenForTabOrPending(second_tab
));
509 ASSERT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
511 // Enter tab fullscreen. Since the tab is being captured, the browser window
512 // should not expand to fill the screen.
513 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE
));
514 EXPECT_FALSE(browser()->window()->IsFullscreen());
515 EXPECT_TRUE(wc_delegate
->IsFullscreenForTabOrPending(first_tab
));
516 EXPECT_FALSE(wc_delegate
->IsFullscreenForTabOrPending(second_tab
));
517 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
519 // Switch to the other tab. Check that the first tab was resized to the
520 // WebContents' preferred size.
521 browser()->tab_strip_model()->ActivateTabAt(1, true);
522 EXPECT_FALSE(browser()->window()->IsFullscreen());
523 EXPECT_TRUE(wc_delegate
->IsFullscreenForTabOrPending(first_tab
));
524 EXPECT_FALSE(wc_delegate
->IsFullscreenForTabOrPending(second_tab
));
525 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
526 // TODO(miu): Need to make an adjustment to content::WebContentsViewMac for
527 // the following to work:
528 #if !defined(OS_MACOSX)
529 EXPECT_EQ(kCaptureSize
, first_tab
->GetViewBounds().size());
532 // Switch back to the first tab and exit fullscreen.
533 browser()->tab_strip_model()->ActivateTabAt(0, true);
534 EXPECT_FALSE(browser()->window()->IsFullscreen());
535 EXPECT_TRUE(wc_delegate
->IsFullscreenForTabOrPending(first_tab
));
536 EXPECT_FALSE(wc_delegate
->IsFullscreenForTabOrPending(second_tab
));
537 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
538 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE
));
539 EXPECT_FALSE(browser()->window()->IsFullscreen());
540 EXPECT_FALSE(wc_delegate
->IsFullscreenForTabOrPending(first_tab
));
541 EXPECT_FALSE(wc_delegate
->IsFullscreenForTabOrPending(second_tab
));
542 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
545 // Tests that, in a browser configured for Fullscreen-Within-Tab mode, more than
546 // one tab can be in fullscreen mode at the same time without interfering with
547 // each other. One tab is being screen-captured and is toggled into fullscreen
548 // mode, and then the user switches to another tab not being screen-captured and
549 // fullscreens it. The first tab's fullscreen toggle does not affect the
550 // browser window fullscreen, while the second one's does. Then, the order of
551 // operations is reversed.
553 // See 'FullscreenWithinTab Note' in fullscreen_controller.h.
554 TEST_F(FullscreenControllerStateUnitTest
, TwoFullscreenedTabsOneCaptured
) {
555 content::WebContentsDelegate
* const wc_delegate
=
556 static_cast<content::WebContentsDelegate
*>(browser());
557 ASSERT_TRUE(wc_delegate
->EmbedsFullscreenWidget());
559 AddTab(browser(), GURL(url::kAboutBlankURL
));
560 AddTab(browser(), GURL(url::kAboutBlankURL
));
561 content::WebContents
* const first_tab
=
562 browser()->tab_strip_model()->GetWebContentsAt(0);
563 content::WebContents
* const second_tab
=
564 browser()->tab_strip_model()->GetWebContentsAt(1);
566 // Start capturing the first tab, fullscreen it, then switch to the second tab
567 // and fullscreen that. The second tab will cause the browser window to
568 // expand to fill the screen.
569 browser()->tab_strip_model()->ActivateTabAt(0, true);
570 const gfx::Size
kCaptureSize(1280, 720);
571 first_tab
->IncrementCapturerCount(kCaptureSize
);
572 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE
));
573 EXPECT_FALSE(browser()->window()->IsFullscreen());
574 EXPECT_TRUE(wc_delegate
->IsFullscreenForTabOrPending(first_tab
));
575 EXPECT_FALSE(wc_delegate
->IsFullscreenForTabOrPending(second_tab
));
576 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
577 browser()->tab_strip_model()->ActivateTabAt(1, true);
578 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE
));
579 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE
));
580 EXPECT_TRUE(browser()->window()->IsFullscreen());
581 EXPECT_TRUE(wc_delegate
->IsFullscreenForTabOrPending(first_tab
));
582 EXPECT_TRUE(wc_delegate
->IsFullscreenForTabOrPending(second_tab
));
583 EXPECT_TRUE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
585 // Now exit fullscreen while still in the second tab. The browser window
586 // should no longer be fullscreened.
587 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE
));
588 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE
));
589 EXPECT_FALSE(browser()->window()->IsFullscreen());
590 EXPECT_TRUE(wc_delegate
->IsFullscreenForTabOrPending(first_tab
));
591 EXPECT_FALSE(wc_delegate
->IsFullscreenForTabOrPending(second_tab
));
592 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
594 // Finally, exit fullscreen on the captured tab.
595 browser()->tab_strip_model()->ActivateTabAt(0, true);
596 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE
));
597 EXPECT_FALSE(browser()->window()->IsFullscreen());
598 EXPECT_FALSE(wc_delegate
->IsFullscreenForTabOrPending(first_tab
));
599 EXPECT_FALSE(wc_delegate
->IsFullscreenForTabOrPending(second_tab
));
600 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
603 // Tests that, in a browser configured for Fullscreen-Within-Tab mode, more than
604 // one tab can be in fullscreen mode at the same time. This is like the
605 // TwoFullscreenedTabsOneCaptured test above, except that the screen-captured
606 // tab exits fullscreen mode while the second tab is still in the foreground.
607 // When the first tab exits fullscreen, the fullscreen state of the second tab
608 // and the browser window should remain unchanged.
610 // See 'FullscreenWithinTab Note' in fullscreen_controller.h.
611 TEST_F(FullscreenControllerStateUnitTest
,
612 BackgroundCapturedTabExitsFullscreen
) {
613 content::WebContentsDelegate
* const wc_delegate
=
614 static_cast<content::WebContentsDelegate
*>(browser());
615 ASSERT_TRUE(wc_delegate
->EmbedsFullscreenWidget());
617 AddTab(browser(), GURL(url::kAboutBlankURL
));
618 AddTab(browser(), GURL(url::kAboutBlankURL
));
619 content::WebContents
* const first_tab
=
620 browser()->tab_strip_model()->GetWebContentsAt(0);
621 content::WebContents
* const second_tab
=
622 browser()->tab_strip_model()->GetWebContentsAt(1);
624 // Start capturing the first tab, fullscreen it, then switch to the second tab
625 // and fullscreen that. The second tab will cause the browser window to
626 // expand to fill the screen.
627 browser()->tab_strip_model()->ActivateTabAt(0, true);
628 const gfx::Size
kCaptureSize(1280, 720);
629 first_tab
->IncrementCapturerCount(kCaptureSize
);
630 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE
));
631 EXPECT_FALSE(browser()->window()->IsFullscreen());
632 EXPECT_TRUE(wc_delegate
->IsFullscreenForTabOrPending(first_tab
));
633 EXPECT_FALSE(wc_delegate
->IsFullscreenForTabOrPending(second_tab
));
634 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
635 browser()->tab_strip_model()->ActivateTabAt(1, true);
636 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE
));
637 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE
));
638 EXPECT_TRUE(browser()->window()->IsFullscreen());
639 EXPECT_TRUE(wc_delegate
->IsFullscreenForTabOrPending(first_tab
));
640 EXPECT_TRUE(wc_delegate
->IsFullscreenForTabOrPending(second_tab
));
641 EXPECT_TRUE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
643 // Now, the first tab (backgrounded) exits fullscreen. This should not affect
644 // the second tab's fullscreen, nor the state of the browser window.
645 GetFullscreenController()->ExitFullscreenModeForTab(first_tab
);
646 EXPECT_TRUE(browser()->window()->IsFullscreen());
647 EXPECT_FALSE(wc_delegate
->IsFullscreenForTabOrPending(first_tab
));
648 EXPECT_TRUE(wc_delegate
->IsFullscreenForTabOrPending(second_tab
));
649 EXPECT_TRUE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
651 // Finally, exit fullscreen on the second tab.
652 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE
));
653 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE
));
654 EXPECT_FALSE(browser()->window()->IsFullscreen());
655 EXPECT_FALSE(wc_delegate
->IsFullscreenForTabOrPending(first_tab
));
656 EXPECT_FALSE(wc_delegate
->IsFullscreenForTabOrPending(second_tab
));
657 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
660 // Tests that, in a browser configured for Fullscreen-Within-Tab mode,
661 // fullscreening a screen-captured tab will NOT cause any fullscreen state
662 // change to the browser window. Then, toggling Browser Fullscreen mode should
663 // fullscreen the browser window, but this should behave fully independently of
664 // the tab's fullscreen state.
666 // See 'FullscreenWithinTab Note' in fullscreen_controller.h.
667 TEST_F(FullscreenControllerStateUnitTest
,
668 OneCapturedTabFullscreenedBeforeBrowserFullscreen
) {
669 content::WebContentsDelegate
* const wc_delegate
=
670 static_cast<content::WebContentsDelegate
*>(browser());
671 ASSERT_TRUE(wc_delegate
->EmbedsFullscreenWidget());
673 AddTab(browser(), GURL(url::kAboutBlankURL
));
674 content::WebContents
* const tab
=
675 browser()->tab_strip_model()->GetWebContentsAt(0);
677 // Start capturing the tab and fullscreen it. The state of the browser window
678 // should remain unchanged.
679 browser()->tab_strip_model()->ActivateTabAt(0, true);
680 const gfx::Size
kCaptureSize(1280, 720);
681 tab
->IncrementCapturerCount(kCaptureSize
);
682 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE
));
683 EXPECT_TRUE(wc_delegate
->IsFullscreenForTabOrPending(tab
));
684 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
685 EXPECT_FALSE(GetFullscreenController()->IsFullscreenForBrowser());
687 // Now, toggle into Browser Fullscreen mode. The browser window should now be
689 ASSERT_TRUE(InvokeEvent(TOGGLE_FULLSCREEN
));
690 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE
));
691 EXPECT_TRUE(wc_delegate
->IsFullscreenForTabOrPending(tab
));
692 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
693 EXPECT_TRUE(GetFullscreenController()->IsFullscreenForBrowser());
695 // Now, toggle back out of Browser Fullscreen mode. The browser window exits
696 // fullscreen mode, but the tab stays in fullscreen mode.
697 ASSERT_TRUE(InvokeEvent(TOGGLE_FULLSCREEN
));
698 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE
));
699 EXPECT_TRUE(wc_delegate
->IsFullscreenForTabOrPending(tab
));
700 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
701 EXPECT_FALSE(GetFullscreenController()->IsFullscreenForBrowser());
703 // Finally, toggle back into Browser Fullscreen mode and then toggle out of
704 // tab fullscreen mode. The browser window should stay fullscreened, while
705 // the tab exits fullscreen mode.
706 ASSERT_TRUE(InvokeEvent(TOGGLE_FULLSCREEN
));
707 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE
));
708 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE
));
709 EXPECT_FALSE(wc_delegate
->IsFullscreenForTabOrPending(tab
));
710 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
711 EXPECT_TRUE(GetFullscreenController()->IsFullscreenForBrowser());
714 // Tests that the state of a fullscreened, screen-captured tab is preserved if
715 // the tab is detached from one Browser window and attached to another.
717 // See 'FullscreenWithinTab Note' in fullscreen_controller.h.
718 TEST_F(FullscreenControllerStateUnitTest
,
719 CapturedFullscreenedTabTransferredBetweenBrowserWindows
) {
720 content::WebContentsDelegate
* const wc_delegate
=
721 static_cast<content::WebContentsDelegate
*>(browser());
722 ASSERT_TRUE(wc_delegate
->EmbedsFullscreenWidget());
724 AddTab(browser(), GURL(url::kAboutBlankURL
));
725 AddTab(browser(), GURL(url::kAboutBlankURL
));
726 content::WebContents
* const tab
=
727 browser()->tab_strip_model()->GetWebContentsAt(0);
729 // Activate the first tab and tell its WebContents it is being captured.
730 browser()->tab_strip_model()->ActivateTabAt(0, true);
731 const gfx::Size
kCaptureSize(1280, 720);
732 tab
->IncrementCapturerCount(kCaptureSize
);
733 ASSERT_FALSE(browser()->window()->IsFullscreen());
734 ASSERT_FALSE(wc_delegate
->IsFullscreenForTabOrPending(tab
));
735 ASSERT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
737 // Enter tab fullscreen. Since the tab is being captured, the browser window
738 // should not expand to fill the screen.
739 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE
));
740 EXPECT_FALSE(browser()->window()->IsFullscreen());
741 EXPECT_TRUE(wc_delegate
->IsFullscreenForTabOrPending(tab
));
742 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
744 // Create the second browser window.
745 const scoped_ptr
<BrowserWindow
> second_browser_window(CreateBrowserWindow());
746 const scoped_ptr
<Browser
> second_browser(CreateBrowser(
747 browser()->profile(),
750 browser()->host_desktop_type(),
751 second_browser_window
.get()));
752 AddTab(second_browser
.get(), GURL(url::kAboutBlankURL
));
753 content::WebContentsDelegate
* const second_wc_delegate
=
754 static_cast<content::WebContentsDelegate
*>(second_browser
.get());
756 // Detach the tab from the first browser window and attach it to the second.
757 // The tab should remain in fullscreen mode and neither browser window should
758 // have expanded. It is correct for both FullscreenControllers to agree the
759 // tab is in fullscreen mode.
760 browser()->tab_strip_model()->DetachWebContentsAt(0);
761 second_browser
->tab_strip_model()->
762 InsertWebContentsAt(0, tab
, TabStripModel::ADD_ACTIVE
);
763 EXPECT_FALSE(browser()->window()->IsFullscreen());
764 EXPECT_FALSE(second_browser
->window()->IsFullscreen());
765 EXPECT_TRUE(wc_delegate
->IsFullscreenForTabOrPending(tab
));
766 EXPECT_TRUE(second_wc_delegate
->IsFullscreenForTabOrPending(tab
));
767 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
768 EXPECT_FALSE(second_browser
->exclusive_access_manager()
769 ->fullscreen_controller()
770 ->IsWindowFullscreenForTabOrPending());
772 // Now, detach and reattach it back to the first browser window. Again, the
773 // tab should remain in fullscreen mode and neither browser window should have
775 second_browser
->tab_strip_model()->DetachWebContentsAt(0);
776 browser()->tab_strip_model()->
777 InsertWebContentsAt(0, tab
, TabStripModel::ADD_ACTIVE
);
778 EXPECT_FALSE(browser()->window()->IsFullscreen());
779 EXPECT_FALSE(second_browser
->window()->IsFullscreen());
780 EXPECT_TRUE(wc_delegate
->IsFullscreenForTabOrPending(tab
));
781 EXPECT_TRUE(second_wc_delegate
->IsFullscreenForTabOrPending(tab
));
782 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
783 EXPECT_FALSE(second_browser
->exclusive_access_manager()
784 ->fullscreen_controller()
785 ->IsWindowFullscreenForTabOrPending());
788 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE
));
789 EXPECT_FALSE(browser()->window()->IsFullscreen());
790 EXPECT_FALSE(wc_delegate
->IsFullscreenForTabOrPending(tab
));
791 EXPECT_FALSE(second_wc_delegate
->IsFullscreenForTabOrPending(tab
));
792 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
793 EXPECT_FALSE(second_browser
->exclusive_access_manager()
794 ->fullscreen_controller()
795 ->IsWindowFullscreenForTabOrPending());
797 // Required tear-down specific to this test.
798 second_browser
->tab_strip_model()->CloseAllTabs();