Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / chrome / browser / ui / exclusive_access / fullscreen_controller_state_unittest.cc
blob5fd817af92e47d9d74dfc9ddec17e215ce8bbb9f
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/exclusive_access_context.h"
10 #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
11 #include "chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.h"
12 #include "chrome/browser/ui/tabs/tab_strip_model.h"
13 #include "chrome/test/base/browser_with_test_window_test.h"
14 #include "content/public/browser/web_contents.h"
15 #include "content/public/common/url_constants.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 // The FullscreenControllerStateUnitTest unit test suite exhastively tests
19 // the FullscreenController through all permutations of events. The behavior
20 // of the BrowserWindow is mocked via FullscreenControllerTestWindow.
23 // FullscreenControllerTestWindow ----------------------------------------------
25 // A BrowserWindow used for testing FullscreenController. The behavior of this
26 // mock is verfied manually by running FullscreenControllerStateInteractiveTest.
27 class FullscreenControllerTestWindow : public TestBrowserWindow,
28 ExclusiveAccessContext {
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,
40 FullscreenControllerTestWindow();
41 ~FullscreenControllerTestWindow() override {}
43 // BrowserWindow Interface:
44 void EnterFullscreen(const GURL& url,
45 ExclusiveAccessBubbleType type,
46 bool with_toolbar) override;
47 void ExitFullscreen() override;
48 bool ShouldHideUIForFullscreen() const override;
49 bool IsFullscreen() const override;
50 bool SupportsFullscreenWithToolbar() const override;
51 void UpdateFullscreenWithToolbar(bool with_toolbar) override;
52 bool IsFullscreenWithToolbar() const override;
53 #if defined(OS_WIN)
54 void SetMetroSnapMode(bool enable) override;
55 bool IsInMetroSnapMode() const override;
56 #endif
57 static const char* GetWindowStateString(WindowState state);
58 WindowState state() const { return state_; }
59 void set_browser(Browser* browser) { browser_ = browser; }
60 ExclusiveAccessContext* GetExclusiveAccessContext() override;
62 // ExclusiveAccessContext Interface:
63 Profile* GetProfile() override;
64 content::WebContents* GetActiveWebContents() override;
65 void HideDownloadShelf() override;
66 void UnhideDownloadShelf() override;
67 void UpdateExclusiveAccessExitBubbleContent(
68 const GURL& url,
69 ExclusiveAccessBubbleType bubble_type) override;
71 // Simulates the window changing state.
72 void ChangeWindowFullscreenState();
74 private:
75 // Enters fullscreen with |new_mac_with_toolbar_mode|.
76 void EnterFullscreen(bool new_mac_with_toolbar_mode);
78 // Returns true if ChangeWindowFullscreenState() should be called as a result
79 // of updating the current fullscreen state to the passed in state.
80 bool IsTransitionReentrant(bool new_fullscreen,
81 bool new_mac_with_toolbar_mode);
83 WindowState state_;
84 bool mac_with_toolbar_mode_;
85 Browser* browser_;
88 FullscreenControllerTestWindow::FullscreenControllerTestWindow()
89 : state_(NORMAL),
90 mac_with_toolbar_mode_(false),
91 browser_(NULL) {
94 void FullscreenControllerTestWindow::EnterFullscreen(
95 const GURL& url,
96 ExclusiveAccessBubbleType type,
97 bool with_toolbar) {
98 EnterFullscreen(with_toolbar);
101 void FullscreenControllerTestWindow::ExitFullscreen() {
102 if (IsFullscreen()) {
103 state_ = TO_NORMAL;
104 mac_with_toolbar_mode_ = false;
106 if (IsTransitionReentrant(false, false))
107 ChangeWindowFullscreenState();
111 bool FullscreenControllerTestWindow::ShouldHideUIForFullscreen() const {
112 return IsFullscreen();
115 bool FullscreenControllerTestWindow::IsFullscreen() const {
116 #if defined(OS_MACOSX)
117 return state_ == FULLSCREEN || state_ == TO_FULLSCREEN;
118 #else
119 return state_ == FULLSCREEN || state_ == TO_NORMAL;
120 #endif
123 bool FullscreenControllerTestWindow::SupportsFullscreenWithToolbar() const {
124 #if defined(OS_MACOSX)
125 return true;
126 #else
127 return false;
128 #endif
131 void FullscreenControllerTestWindow::UpdateFullscreenWithToolbar(
132 bool with_toolbar) {
133 EnterFullscreen(with_toolbar);
136 bool FullscreenControllerTestWindow::IsFullscreenWithToolbar() const {
137 return IsFullscreen() && mac_with_toolbar_mode_;
140 #if defined(OS_WIN)
141 void FullscreenControllerTestWindow::SetMetroSnapMode(bool enable) {
142 if (enable != IsInMetroSnapMode())
143 state_ = enable ? METRO_SNAP : NORMAL;
145 if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
146 ChangeWindowFullscreenState();
149 bool FullscreenControllerTestWindow::IsInMetroSnapMode() const {
150 return state_ == METRO_SNAP;
152 #endif
154 // static
155 const char* FullscreenControllerTestWindow::GetWindowStateString(
156 WindowState state) {
157 switch (state) {
158 ENUM_TO_STRING(NORMAL);
159 ENUM_TO_STRING(FULLSCREEN);
160 ENUM_TO_STRING(METRO_SNAP);
161 ENUM_TO_STRING(TO_FULLSCREEN);
162 ENUM_TO_STRING(TO_NORMAL);
163 default:
164 NOTREACHED() << "No string for state " << state;
165 return "WindowState-Unknown";
169 void FullscreenControllerTestWindow::ChangeWindowFullscreenState() {
170 // Most states result in "no operation" intentionally. The tests
171 // assume that all possible states and event pairs can be tested, even
172 // though window managers will not generate all of these.
173 if (state_ == TO_FULLSCREEN)
174 state_ = FULLSCREEN;
175 else if (state_ == TO_NORMAL)
176 state_ = NORMAL;
178 // Emit a change event from every state to ensure the Fullscreen Controller
179 // handles it in all circumstances.
180 browser_->WindowFullscreenStateChanged();
183 void FullscreenControllerTestWindow::EnterFullscreen(
184 bool new_mac_with_toolbar_mode) {
185 bool reentrant = IsTransitionReentrant(true, new_mac_with_toolbar_mode);
187 mac_with_toolbar_mode_ = new_mac_with_toolbar_mode;
188 if (!IsFullscreen())
189 state_ = TO_FULLSCREEN;
191 if (reentrant)
192 ChangeWindowFullscreenState();
195 bool FullscreenControllerTestWindow::IsTransitionReentrant(
196 bool new_fullscreen,
197 bool new_mac_with_toolbar_mode) {
198 #if defined(OS_MACOSX)
199 bool mac_with_toolbar_mode_changed =
200 new_mac_with_toolbar_mode != IsFullscreenWithToolbar();
201 #else
202 bool mac_with_toolbar_mode_changed = false;
203 #endif
204 bool fullscreen_changed = (new_fullscreen != IsFullscreen());
206 if (!fullscreen_changed && !mac_with_toolbar_mode_changed)
207 return false;
209 if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
210 return true;
212 // BrowserWindowCocoa::EnterFullscreen() and
213 // BrowserWindowCocoa::EnterFullscreenWithToolbar() are reentrant when
214 // switching between fullscreen with chrome and fullscreen without chrome.
215 return state_ == FULLSCREEN &&
216 !fullscreen_changed &&
217 mac_with_toolbar_mode_changed;
220 ExclusiveAccessContext*
221 FullscreenControllerTestWindow::GetExclusiveAccessContext() {
222 return this;
225 Profile* FullscreenControllerTestWindow::GetProfile() {
226 return browser_->profile();
229 content::WebContents* FullscreenControllerTestWindow::GetActiveWebContents() {
230 return browser_->tab_strip_model()->GetActiveWebContents();
233 void FullscreenControllerTestWindow::UnhideDownloadShelf() {
234 GetDownloadShelf()->Unhide();
237 void FullscreenControllerTestWindow::HideDownloadShelf() {
238 GetDownloadShelf()->Hide();
241 void FullscreenControllerTestWindow::UpdateExclusiveAccessExitBubbleContent(
242 const GURL& url,
243 ExclusiveAccessBubbleType bubble_type) {
244 TestBrowserWindow::UpdateExclusiveAccessExitBubbleContent(url, bubble_type);
247 // FullscreenControllerStateUnitTest -------------------------------------------
249 // Unit test fixture testing Fullscreen Controller through its states. Most of
250 // the test logic comes from FullscreenControllerStateTest.
251 class FullscreenControllerStateUnitTest : public BrowserWithTestWindowTest,
252 public FullscreenControllerStateTest {
253 public:
254 FullscreenControllerStateUnitTest();
256 // FullscreenControllerStateTest:
257 void SetUp() override;
258 BrowserWindow* CreateBrowserWindow() override;
259 void ChangeWindowFullscreenState() override;
260 const char* GetWindowStateString() override;
261 void VerifyWindowState() override;
263 protected:
264 // FullscreenControllerStateTest:
265 bool ShouldSkipStateAndEventPair(State state, Event event) override;
266 Browser* GetBrowser() override;
267 FullscreenControllerTestWindow* window_;
270 FullscreenControllerStateUnitTest::FullscreenControllerStateUnitTest()
271 : window_(NULL) {
274 void FullscreenControllerStateUnitTest::SetUp() {
275 BrowserWithTestWindowTest::SetUp();
276 window_->set_browser(browser());
279 BrowserWindow* FullscreenControllerStateUnitTest::CreateBrowserWindow() {
280 window_ = new FullscreenControllerTestWindow();
281 return window_; // BrowserWithTestWindowTest takes ownership.
284 void FullscreenControllerStateUnitTest::ChangeWindowFullscreenState() {
285 window_->ChangeWindowFullscreenState();
288 const char* FullscreenControllerStateUnitTest::GetWindowStateString() {
289 return FullscreenControllerTestWindow::GetWindowStateString(window_->state());
292 void FullscreenControllerStateUnitTest::VerifyWindowState() {
293 switch (state()) {
294 case STATE_NORMAL:
295 EXPECT_EQ(FullscreenControllerTestWindow::NORMAL,
296 window_->state()) << GetAndClearDebugLog();
297 break;
299 case STATE_BROWSER_FULLSCREEN_NO_CHROME:
300 case STATE_BROWSER_FULLSCREEN_WITH_CHROME:
301 case STATE_TAB_FULLSCREEN:
302 case STATE_TAB_BROWSER_FULLSCREEN:
303 case STATE_TAB_BROWSER_FULLSCREEN_CHROME:
304 EXPECT_EQ(FullscreenControllerTestWindow::FULLSCREEN,
305 window_->state()) << GetAndClearDebugLog();
306 break;
308 #if defined(OS_WIN)
309 case STATE_METRO_SNAP:
310 EXPECT_EQ(FullscreenControllerTestWindow::METRO_SNAP,
311 window_->state()) << GetAndClearDebugLog();
312 break;
313 #endif
315 case STATE_TO_NORMAL:
316 EXPECT_EQ(FullscreenControllerTestWindow::TO_NORMAL,
317 window_->state()) << GetAndClearDebugLog();
318 break;
320 case STATE_TO_BROWSER_FULLSCREEN_NO_CHROME:
321 case STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME:
322 case STATE_TO_TAB_FULLSCREEN:
323 EXPECT_EQ(FullscreenControllerTestWindow::TO_FULLSCREEN,
324 window_->state()) << GetAndClearDebugLog();
325 break;
327 default:
328 NOTREACHED() << GetAndClearDebugLog();
331 FullscreenControllerStateTest::VerifyWindowState();
334 bool FullscreenControllerStateUnitTest::ShouldSkipStateAndEventPair(
335 State state, Event event) {
336 #if defined(OS_MACOSX)
337 // TODO(scheib) Toggle, Window Event, Toggle, Toggle on Mac as exposed by
338 // test *.STATE_TO_NORMAL__TOGGLE_FULLSCREEN runs interactively and exits to
339 // Normal. This doesn't appear to be the desired result, and would add
340 // too much complexity to mimic in our simple FullscreenControllerTestWindow.
341 // http://crbug.com/156968
342 if ((state == STATE_TO_NORMAL ||
343 state == STATE_TO_BROWSER_FULLSCREEN_NO_CHROME ||
344 state == STATE_TO_TAB_FULLSCREEN) &&
345 event == TOGGLE_FULLSCREEN)
346 return true;
347 #endif
349 return FullscreenControllerStateTest::ShouldSkipStateAndEventPair(state,
350 event);
353 Browser* FullscreenControllerStateUnitTest::GetBrowser() {
354 return BrowserWithTestWindowTest::browser();
357 // Soak tests ------------------------------------------------------------------
359 // Tests all states with all permutations of multiple events to detect lingering
360 // state issues that would bleed over to other states.
361 // I.E. for each state test all combinations of events E1, E2, E3.
363 // This produces coverage for event sequences that may happen normally but
364 // would not be exposed by traversing to each state via TransitionToState().
365 // TransitionToState() always takes the same path even when multiple paths
366 // exist.
367 TEST_F(FullscreenControllerStateUnitTest, TransitionsForEachState) {
368 // A tab is needed for tab fullscreen.
369 AddTab(browser(), GURL(url::kAboutBlankURL));
370 TestTransitionsForEachState();
371 // Progress of test can be examined via LOG(INFO) << GetAndClearDebugLog();
375 // Individual tests for each pair of state and event ---------------------------
377 #define TEST_EVENT(state, event) \
378 TEST_F(FullscreenControllerStateUnitTest, state##__##event) { \
379 AddTab(browser(), GURL(url::kAboutBlankURL)); \
380 ASSERT_NO_FATAL_FAILURE(TestStateAndEvent(state, event)) \
381 << GetAndClearDebugLog(); \
383 // Progress of tests can be examined by inserting the following line:
384 // LOG(INFO) << GetAndClearDebugLog(); }
386 #include "chrome/browser/ui/exclusive_access/fullscreen_controller_state_tests.h"
389 // Specific one-off tests for known issues -------------------------------------
391 // TODO(scheib) Toggling Tab fullscreen while pending Tab or
392 // Browser fullscreen is broken currently http://crbug.com/154196
393 TEST_F(FullscreenControllerStateUnitTest,
394 DISABLED_ToggleTabWhenPendingBrowser) {
395 // Only possible without reentrancy.
396 if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
397 return;
398 AddTab(browser(), GURL(url::kAboutBlankURL));
399 ASSERT_NO_FATAL_FAILURE(
400 TransitionToState(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME))
401 << GetAndClearDebugLog();
403 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE)) << GetAndClearDebugLog();
404 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE)) << GetAndClearDebugLog();
405 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE)) << GetAndClearDebugLog();
408 // TODO(scheib) Toggling Tab fullscreen while pending Tab or
409 // Browser fullscreen is broken currently http://crbug.com/154196
410 TEST_F(FullscreenControllerStateUnitTest, DISABLED_ToggleTabWhenPendingTab) {
411 // Only possible without reentrancy.
412 if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
413 return;
414 AddTab(browser(), GURL(url::kAboutBlankURL));
415 ASSERT_NO_FATAL_FAILURE(
416 TransitionToState(STATE_TO_TAB_FULLSCREEN))
417 << GetAndClearDebugLog();
419 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE)) << GetAndClearDebugLog();
420 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE)) << GetAndClearDebugLog();
421 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE)) << GetAndClearDebugLog();
424 // Debugging utility: Display the transition tables. Intentionally disabled
425 TEST_F(FullscreenControllerStateUnitTest, DISABLED_DebugLogStateTables) {
426 std::ostringstream output;
427 output << "\n\nTransition Table:";
428 output << GetTransitionTableAsString();
430 output << "\n\nInitial transitions:";
431 output << GetStateTransitionsAsString();
433 // Calculate all transition pairs.
434 for (int state1_int = 0; state1_int < NUM_STATES; ++state1_int) {
435 State state1 = static_cast<State>(state1_int);
436 for (int state2_int = 0; state2_int < NUM_STATES; ++state2_int) {
437 State state2 = static_cast<State>(state2_int);
438 if (ShouldSkipStateAndEventPair(state1, EVENT_INVALID) ||
439 ShouldSkipStateAndEventPair(state2, EVENT_INVALID))
440 continue;
441 // Compute the transition
442 if (NextTransitionInShortestPath(state1, state2, NUM_STATES).state ==
443 STATE_INVALID) {
444 LOG(ERROR) << "Should be skipping state transitions for: "
445 << GetStateString(state1) << " " << GetStateString(state2);
450 output << "\n\nAll transitions:";
451 output << GetStateTransitionsAsString();
452 LOG(INFO) << output.str();
455 // Test that the fullscreen exit bubble is closed by
456 // WindowFullscreenStateChanged() if fullscreen is exited via BrowserWindow.
457 // This currently occurs when an extension exits fullscreen via changing the
458 // browser bounds.
459 TEST_F(FullscreenControllerStateUnitTest, ExitFullscreenViaBrowserWindow) {
460 AddTab(browser(), GURL(url::kAboutBlankURL));
461 ASSERT_TRUE(InvokeEvent(TOGGLE_FULLSCREEN));
462 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
463 ASSERT_TRUE(browser()->window()->IsFullscreen());
464 // Exit fullscreen without going through fullscreen controller.
465 browser()->window()->ExitFullscreen();
466 ChangeWindowFullscreenState();
467 EXPECT_EQ(EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE,
468 browser()
469 ->exclusive_access_manager()
470 ->GetExclusiveAccessExitBubbleType());
473 // Test that switching tabs takes the browser out of tab fullscreen.
474 TEST_F(FullscreenControllerStateUnitTest, ExitTabFullscreenViaSwitchingTab) {
475 AddTab(browser(), GURL(url::kAboutBlankURL));
476 AddTab(browser(), GURL(url::kAboutBlankURL));
477 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
478 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
479 ASSERT_TRUE(browser()->window()->IsFullscreen());
481 browser()->tab_strip_model()->SelectNextTab();
482 ChangeWindowFullscreenState();
483 EXPECT_FALSE(browser()->window()->IsFullscreen());
486 // Test that switching tabs via detaching the active tab (which is in tab
487 // fullscreen) takes the browser out of tab fullscreen. This case can
488 // occur if the user is in both tab fullscreen and immersive browser fullscreen.
489 TEST_F(FullscreenControllerStateUnitTest, ExitTabFullscreenViaDetachingTab) {
490 AddTab(browser(), GURL(url::kAboutBlankURL));
491 AddTab(browser(), GURL(url::kAboutBlankURL));
492 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
493 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
494 ASSERT_TRUE(browser()->window()->IsFullscreen());
496 scoped_ptr<content::WebContents> web_contents(
497 browser()->tab_strip_model()->DetachWebContentsAt(0));
498 ChangeWindowFullscreenState();
499 EXPECT_FALSE(browser()->window()->IsFullscreen());
502 // Test that replacing the web contents for a tab which is in tab fullscreen
503 // takes the browser out of tab fullscreen. This can occur if the user
504 // navigates to a prerendered page from a page which is tab fullscreen.
505 TEST_F(FullscreenControllerStateUnitTest, ExitTabFullscreenViaReplacingTab) {
506 AddTab(browser(), GURL(url::kAboutBlankURL));
507 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
508 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
509 ASSERT_TRUE(browser()->window()->IsFullscreen());
511 content::WebContents* new_web_contents = content::WebContents::Create(
512 content::WebContents::CreateParams(profile()));
513 scoped_ptr<content::WebContents> old_web_contents(
514 browser()->tab_strip_model()->ReplaceWebContentsAt(
515 0, new_web_contents));
516 ChangeWindowFullscreenState();
517 EXPECT_FALSE(browser()->window()->IsFullscreen());
520 // Tests that, in a browser configured for Fullscreen-Within-Tab mode,
521 // fullscreening a screen-captured tab will NOT cause any fullscreen state
522 // change to the browser window. Furthermore, the test switches between tabs to
523 // confirm a captured tab will be resized by FullscreenController to the capture
524 // video resolution once the widget is detached from the UI.
526 // See 'FullscreenWithinTab Note' in fullscreen_controller.h.
527 TEST_F(FullscreenControllerStateUnitTest, OneCapturedFullscreenedTab) {
528 content::WebContentsDelegate* const wc_delegate =
529 static_cast<content::WebContentsDelegate*>(browser());
530 ASSERT_TRUE(wc_delegate->EmbedsFullscreenWidget());
532 AddTab(browser(), GURL(url::kAboutBlankURL));
533 AddTab(browser(), GURL(url::kAboutBlankURL));
534 content::WebContents* const first_tab =
535 browser()->tab_strip_model()->GetWebContentsAt(0);
536 content::WebContents* const second_tab =
537 browser()->tab_strip_model()->GetWebContentsAt(1);
539 // Activate the first tab and tell its WebContents it is being captured.
540 browser()->tab_strip_model()->ActivateTabAt(0, true);
541 const gfx::Size kCaptureSize(1280, 720);
542 first_tab->IncrementCapturerCount(kCaptureSize);
543 ASSERT_FALSE(browser()->window()->IsFullscreen());
544 ASSERT_FALSE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
545 ASSERT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
546 ASSERT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
548 // Enter tab fullscreen. Since the tab is being captured, the browser window
549 // should not expand to fill the screen.
550 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
551 EXPECT_FALSE(browser()->window()->IsFullscreen());
552 EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
553 EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
554 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
556 // Switch to the other tab. Check that the first tab was resized to the
557 // WebContents' preferred size.
558 browser()->tab_strip_model()->ActivateTabAt(1, true);
559 EXPECT_FALSE(browser()->window()->IsFullscreen());
560 EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
561 EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
562 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
563 // TODO(miu): Need to make an adjustment to content::WebContentsViewMac for
564 // the following to work:
565 #if !defined(OS_MACOSX)
566 EXPECT_EQ(kCaptureSize, first_tab->GetViewBounds().size());
567 #endif
569 // Switch back to the first tab and exit fullscreen.
570 browser()->tab_strip_model()->ActivateTabAt(0, true);
571 EXPECT_FALSE(browser()->window()->IsFullscreen());
572 EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
573 EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
574 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
575 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE));
576 EXPECT_FALSE(browser()->window()->IsFullscreen());
577 EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
578 EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
579 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
582 // Tests that, in a browser configured for Fullscreen-Within-Tab mode, more than
583 // one tab can be in fullscreen mode at the same time without interfering with
584 // each other. One tab is being screen-captured and is toggled into fullscreen
585 // mode, and then the user switches to another tab not being screen-captured and
586 // fullscreens it. The first tab's fullscreen toggle does not affect the
587 // browser window fullscreen, while the second one's does. Then, the order of
588 // operations is reversed.
590 // See 'FullscreenWithinTab Note' in fullscreen_controller.h.
591 TEST_F(FullscreenControllerStateUnitTest, TwoFullscreenedTabsOneCaptured) {
592 content::WebContentsDelegate* const wc_delegate =
593 static_cast<content::WebContentsDelegate*>(browser());
594 ASSERT_TRUE(wc_delegate->EmbedsFullscreenWidget());
596 AddTab(browser(), GURL(url::kAboutBlankURL));
597 AddTab(browser(), GURL(url::kAboutBlankURL));
598 content::WebContents* const first_tab =
599 browser()->tab_strip_model()->GetWebContentsAt(0);
600 content::WebContents* const second_tab =
601 browser()->tab_strip_model()->GetWebContentsAt(1);
603 // Start capturing the first tab, fullscreen it, then switch to the second tab
604 // and fullscreen that. The second tab will cause the browser window to
605 // expand to fill the screen.
606 browser()->tab_strip_model()->ActivateTabAt(0, true);
607 const gfx::Size kCaptureSize(1280, 720);
608 first_tab->IncrementCapturerCount(kCaptureSize);
609 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
610 EXPECT_FALSE(browser()->window()->IsFullscreen());
611 EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
612 EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
613 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
614 browser()->tab_strip_model()->ActivateTabAt(1, true);
615 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
616 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
617 EXPECT_TRUE(browser()->window()->IsFullscreen());
618 EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
619 EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
620 EXPECT_TRUE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
622 // Now exit fullscreen while still in the second tab. The browser window
623 // should no longer be fullscreened.
624 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE));
625 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
626 EXPECT_FALSE(browser()->window()->IsFullscreen());
627 EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
628 EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
629 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
631 // Finally, exit fullscreen on the captured tab.
632 browser()->tab_strip_model()->ActivateTabAt(0, true);
633 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE));
634 EXPECT_FALSE(browser()->window()->IsFullscreen());
635 EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
636 EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
637 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
640 // Tests that, in a browser configured for Fullscreen-Within-Tab mode, more than
641 // one tab can be in fullscreen mode at the same time. This is like the
642 // TwoFullscreenedTabsOneCaptured test above, except that the screen-captured
643 // tab exits fullscreen mode while the second tab is still in the foreground.
644 // When the first tab exits fullscreen, the fullscreen state of the second tab
645 // and the browser window should remain unchanged.
647 // See 'FullscreenWithinTab Note' in fullscreen_controller.h.
648 TEST_F(FullscreenControllerStateUnitTest,
649 BackgroundCapturedTabExitsFullscreen) {
650 content::WebContentsDelegate* const wc_delegate =
651 static_cast<content::WebContentsDelegate*>(browser());
652 ASSERT_TRUE(wc_delegate->EmbedsFullscreenWidget());
654 AddTab(browser(), GURL(url::kAboutBlankURL));
655 AddTab(browser(), GURL(url::kAboutBlankURL));
656 content::WebContents* const first_tab =
657 browser()->tab_strip_model()->GetWebContentsAt(0);
658 content::WebContents* const second_tab =
659 browser()->tab_strip_model()->GetWebContentsAt(1);
661 // Start capturing the first tab, fullscreen it, then switch to the second tab
662 // and fullscreen that. The second tab will cause the browser window to
663 // expand to fill the screen.
664 browser()->tab_strip_model()->ActivateTabAt(0, true);
665 const gfx::Size kCaptureSize(1280, 720);
666 first_tab->IncrementCapturerCount(kCaptureSize);
667 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
668 EXPECT_FALSE(browser()->window()->IsFullscreen());
669 EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
670 EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
671 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
672 browser()->tab_strip_model()->ActivateTabAt(1, true);
673 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
674 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
675 EXPECT_TRUE(browser()->window()->IsFullscreen());
676 EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
677 EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
678 EXPECT_TRUE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
680 // Now, the first tab (backgrounded) exits fullscreen. This should not affect
681 // the second tab's fullscreen, nor the state of the browser window.
682 GetFullscreenController()->ExitFullscreenModeForTab(first_tab);
683 EXPECT_TRUE(browser()->window()->IsFullscreen());
684 EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
685 EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
686 EXPECT_TRUE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
688 // Finally, exit fullscreen on the second tab.
689 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE));
690 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
691 EXPECT_FALSE(browser()->window()->IsFullscreen());
692 EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(first_tab));
693 EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(second_tab));
694 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
697 // Tests that, in a browser configured for Fullscreen-Within-Tab mode,
698 // fullscreening a screen-captured tab will NOT cause any fullscreen state
699 // change to the browser window. Then, toggling Browser Fullscreen mode should
700 // fullscreen the browser window, but this should behave fully independently of
701 // the tab's fullscreen state.
703 // See 'FullscreenWithinTab Note' in fullscreen_controller.h.
704 TEST_F(FullscreenControllerStateUnitTest,
705 OneCapturedTabFullscreenedBeforeBrowserFullscreen) {
706 content::WebContentsDelegate* const wc_delegate =
707 static_cast<content::WebContentsDelegate*>(browser());
708 ASSERT_TRUE(wc_delegate->EmbedsFullscreenWidget());
710 AddTab(browser(), GURL(url::kAboutBlankURL));
711 content::WebContents* const tab =
712 browser()->tab_strip_model()->GetWebContentsAt(0);
714 // Start capturing the tab and fullscreen it. The state of the browser window
715 // should remain unchanged.
716 browser()->tab_strip_model()->ActivateTabAt(0, true);
717 const gfx::Size kCaptureSize(1280, 720);
718 tab->IncrementCapturerCount(kCaptureSize);
719 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
720 EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(tab));
721 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
722 EXPECT_FALSE(GetFullscreenController()->IsFullscreenForBrowser());
724 // Now, toggle into Browser Fullscreen mode. The browser window should now be
725 // fullscreened.
726 ASSERT_TRUE(InvokeEvent(TOGGLE_FULLSCREEN));
727 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
728 EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(tab));
729 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
730 EXPECT_TRUE(GetFullscreenController()->IsFullscreenForBrowser());
732 // Now, toggle back out of Browser Fullscreen mode. The browser window exits
733 // fullscreen mode, but the tab stays in fullscreen mode.
734 ASSERT_TRUE(InvokeEvent(TOGGLE_FULLSCREEN));
735 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
736 EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(tab));
737 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
738 EXPECT_FALSE(GetFullscreenController()->IsFullscreenForBrowser());
740 // Finally, toggle back into Browser Fullscreen mode and then toggle out of
741 // tab fullscreen mode. The browser window should stay fullscreened, while
742 // the tab exits fullscreen mode.
743 ASSERT_TRUE(InvokeEvent(TOGGLE_FULLSCREEN));
744 ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE));
745 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE));
746 EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(tab));
747 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
748 EXPECT_TRUE(GetFullscreenController()->IsFullscreenForBrowser());
751 // Tests that the state of a fullscreened, screen-captured tab is preserved if
752 // the tab is detached from one Browser window and attached to another.
754 // See 'FullscreenWithinTab Note' in fullscreen_controller.h.
755 TEST_F(FullscreenControllerStateUnitTest,
756 CapturedFullscreenedTabTransferredBetweenBrowserWindows) {
757 content::WebContentsDelegate* const wc_delegate =
758 static_cast<content::WebContentsDelegate*>(browser());
759 ASSERT_TRUE(wc_delegate->EmbedsFullscreenWidget());
761 AddTab(browser(), GURL(url::kAboutBlankURL));
762 AddTab(browser(), GURL(url::kAboutBlankURL));
763 content::WebContents* const tab =
764 browser()->tab_strip_model()->GetWebContentsAt(0);
766 // Activate the first tab and tell its WebContents it is being captured.
767 browser()->tab_strip_model()->ActivateTabAt(0, true);
768 const gfx::Size kCaptureSize(1280, 720);
769 tab->IncrementCapturerCount(kCaptureSize);
770 ASSERT_FALSE(browser()->window()->IsFullscreen());
771 ASSERT_FALSE(wc_delegate->IsFullscreenForTabOrPending(tab));
772 ASSERT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
774 // Enter tab fullscreen. Since the tab is being captured, the browser window
775 // should not expand to fill the screen.
776 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE));
777 EXPECT_FALSE(browser()->window()->IsFullscreen());
778 EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(tab));
779 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
781 // Create the second browser window.
782 const scoped_ptr<BrowserWindow> second_browser_window(CreateBrowserWindow());
783 const scoped_ptr<Browser> second_browser(CreateBrowser(
784 browser()->profile(),
785 browser()->type(),
786 false,
787 browser()->host_desktop_type(),
788 second_browser_window.get()));
789 AddTab(second_browser.get(), GURL(url::kAboutBlankURL));
790 content::WebContentsDelegate* const second_wc_delegate =
791 static_cast<content::WebContentsDelegate*>(second_browser.get());
793 // Detach the tab from the first browser window and attach it to the second.
794 // The tab should remain in fullscreen mode and neither browser window should
795 // have expanded. It is correct for both FullscreenControllers to agree the
796 // tab is in fullscreen mode.
797 browser()->tab_strip_model()->DetachWebContentsAt(0);
798 second_browser->tab_strip_model()->
799 InsertWebContentsAt(0, tab, TabStripModel::ADD_ACTIVE);
800 EXPECT_FALSE(browser()->window()->IsFullscreen());
801 EXPECT_FALSE(second_browser->window()->IsFullscreen());
802 EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(tab));
803 EXPECT_TRUE(second_wc_delegate->IsFullscreenForTabOrPending(tab));
804 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
805 EXPECT_FALSE(second_browser->exclusive_access_manager()
806 ->fullscreen_controller()
807 ->IsWindowFullscreenForTabOrPending());
809 // Now, detach and reattach it back to the first browser window. Again, the
810 // tab should remain in fullscreen mode and neither browser window should have
811 // expanded.
812 second_browser->tab_strip_model()->DetachWebContentsAt(0);
813 browser()->tab_strip_model()->
814 InsertWebContentsAt(0, tab, TabStripModel::ADD_ACTIVE);
815 EXPECT_FALSE(browser()->window()->IsFullscreen());
816 EXPECT_FALSE(second_browser->window()->IsFullscreen());
817 EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(tab));
818 EXPECT_TRUE(second_wc_delegate->IsFullscreenForTabOrPending(tab));
819 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
820 EXPECT_FALSE(second_browser->exclusive_access_manager()
821 ->fullscreen_controller()
822 ->IsWindowFullscreenForTabOrPending());
824 // Exit fullscreen.
825 ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE));
826 EXPECT_FALSE(browser()->window()->IsFullscreen());
827 EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(tab));
828 EXPECT_FALSE(second_wc_delegate->IsFullscreenForTabOrPending(tab));
829 EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending());
830 EXPECT_FALSE(second_browser->exclusive_access_manager()
831 ->fullscreen_controller()
832 ->IsWindowFullscreenForTabOrPending());
834 // Required tear-down specific to this test.
835 second_browser->tab_strip_model()->CloseAllTabs();