ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / chrome / browser / ui / exclusive_access / fullscreen_controller_state_unittest.cc
blob31ef25230b0fbaa2a3070651f3c1c6f741c8da47
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 {
27 public:
28 // Simulate the window state with an enumeration.
29 enum WindowState {
30 NORMAL,
31 FULLSCREEN,
32 // No TO_ state for METRO_SNAP, the windows implementation is synchronous.
33 METRO_SNAP,
34 TO_NORMAL,
35 TO_FULLSCREEN,
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;
51 #if defined(OS_WIN)
52 virtual void SetMetroSnapMode(bool enable) override;
53 virtual bool IsInMetroSnapMode() const override;
54 #endif
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();
62 private:
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);
71 WindowState state_;
72 bool mac_with_toolbar_mode_;
73 Browser* browser_;
76 FullscreenControllerTestWindow::FullscreenControllerTestWindow()
77 : state_(NORMAL),
78 mac_with_toolbar_mode_(false),
79 browser_(NULL) {
82 void FullscreenControllerTestWindow::EnterFullscreen(
83 const GURL& url,
84 ExclusiveAccessBubbleType type,
85 bool with_toolbar) {
86 EnterFullscreen(with_toolbar);
89 void FullscreenControllerTestWindow::ExitFullscreen() {
90 if (IsFullscreen()) {
91 state_ = TO_NORMAL;
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;
106 #else
107 return state_ == FULLSCREEN || state_ == TO_NORMAL;
108 #endif
111 bool FullscreenControllerTestWindow::SupportsFullscreenWithToolbar() const {
112 #if defined(OS_MACOSX)
113 return true;
114 #else
115 return false;
116 #endif
119 void FullscreenControllerTestWindow::UpdateFullscreenWithToolbar(
120 bool with_toolbar) {
121 EnterFullscreen(with_toolbar);
124 bool FullscreenControllerTestWindow::IsFullscreenWithToolbar() const {
125 return IsFullscreen() && mac_with_toolbar_mode_;
128 #if defined(OS_WIN)
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;
140 #endif
142 // static
143 const char* FullscreenControllerTestWindow::GetWindowStateString(
144 WindowState state) {
145 switch (state) {
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);
151 default:
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)
162 state_ = FULLSCREEN;
163 else if (state_ == TO_NORMAL)
164 state_ = 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;
176 if (!IsFullscreen())
177 state_ = TO_FULLSCREEN;
179 if (reentrant)
180 ChangeWindowFullscreenState();
183 bool FullscreenControllerTestWindow::IsTransitionReentrant(
184 bool new_fullscreen,
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();
189 #else
190 bool mac_with_toolbar_mode_changed = false;
191 #endif
192 bool fullscreen_changed = (new_fullscreen != IsFullscreen());
194 if (!fullscreen_changed && !mac_with_toolbar_mode_changed)
195 return false;
197 if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
198 return true;
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 {
215 public:
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;
225 protected:
226 // FullscreenControllerStateTest:
227 bool ShouldSkipStateAndEventPair(State state, Event event) override;
228 Browser* GetBrowser() override;
229 FullscreenControllerTestWindow* window_;
232 FullscreenControllerStateUnitTest::FullscreenControllerStateUnitTest ()
233 : window_(NULL) {
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() {
255 switch (state()) {
256 case STATE_NORMAL:
257 EXPECT_EQ(FullscreenControllerTestWindow::NORMAL,
258 window_->state()) << GetAndClearDebugLog();
259 break;
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();
268 break;
270 #if defined(OS_WIN)
271 case STATE_METRO_SNAP:
272 EXPECT_EQ(FullscreenControllerTestWindow::METRO_SNAP,
273 window_->state()) << GetAndClearDebugLog();
274 break;
275 #endif
277 case STATE_TO_NORMAL:
278 EXPECT_EQ(FullscreenControllerTestWindow::TO_NORMAL,
279 window_->state()) << GetAndClearDebugLog();
280 break;
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();
287 break;
289 default:
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)
308 return true;
309 #endif
311 return FullscreenControllerStateTest::ShouldSkipStateAndEventPair(state,
312 event);
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
329 // exist.
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())
360 return;
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())
376 return;
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))
403 continue;
404 // Compute the transition
405 if (NextTransitionInShortestPath(state1, state2, NUM_STATES).state ==
406 STATE_INVALID) {
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
421 // browser bounds.
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,
431 browser()
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());
530 #endif
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
688 // fullscreened.
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(),
748 browser()->type(),
749 false,
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
774 // expanded.
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());
787 // Exit fullscreen.
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();