summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/ui/cocoa/browser_window_controller.mm4
-rw-r--r--chrome/browser/ui/fullscreen/fullscreen_controller.cc19
-rw-r--r--chrome/browser/ui/fullscreen/fullscreen_controller.h3
-rw-r--r--chrome/browser/ui/fullscreen/fullscreen_controller_browsertest.cc14
-rw-r--r--chrome/browser/ui/fullscreen/fullscreen_controller_interactive_browsertest.cc56
-rw-r--r--chrome/browser/ui/fullscreen/fullscreen_controller_state_interactive_browsertest.cc226
-rw-r--r--chrome/browser/ui/fullscreen/fullscreen_controller_state_test.cc570
-rw-r--r--chrome/browser/ui/fullscreen/fullscreen_controller_state_test.h143
-rw-r--r--chrome/browser/ui/fullscreen/fullscreen_controller_state_unittest.cc457
-rw-r--r--chrome/browser/ui/fullscreen/fullscreen_controller_test.cc10
-rw-r--r--chrome/browser/ui/fullscreen/fullscreen_controller_test.h2
-rw-r--r--chrome/browser/ui/fullscreen/fullscreen_controller_unittest.cc969
-rw-r--r--chrome/chrome_tests.gypi6
-rw-r--r--chrome/test/base/in_process_browser_test.cc6
14 files changed, 1458 insertions, 1027 deletions
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm
index 8d62a40..90bb372 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -2016,8 +2016,10 @@ willAnimateFromState:(bookmarks::VisualState)oldState
[self setPresentationModeInternal:YES forceDropdown:YES];
[self releaseBarVisibilityForOwner:self withAnimation:YES delay:YES];
// Since -windowDidEnterFullScreen: won't be called in the
- // fullscreen --> presentation mode case, manually show the exit bubble.
+ // fullscreen --> presentation mode case, manually show the exit bubble
+ // and notify the change happened with WindowFullscreenStateChanged().
[self showFullscreenExitBubbleIfNecessary];
+ browser_->WindowFullscreenStateChanged();
} else {
// If not in fullscreen mode, trigger the Lion fullscreen mode machinery.
// Presentation mode will automatically be enabled in
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller.cc b/chrome/browser/ui/fullscreen/fullscreen_controller.cc
index cf66456..289f6e2 100644
--- a/chrome/browser/ui/fullscreen/fullscreen_controller.cc
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller.cc
@@ -110,6 +110,10 @@ void FullscreenController::ToggleFullscreenModeForTab(WebContents* web_contents,
GetFullscreenSetting(url) == CONTENT_SETTING_ALLOW;
}
UpdateFullscreenExitBubbleContent();
+
+ // This is only a change between Browser and Tab fullscreen. We generate
+ // a fullscreen notification now because there is no window change.
+ PostFullscreenChangeNotification(true);
}
} else {
if (in_browser_or_tab_fullscreen_mode) {
@@ -126,6 +130,10 @@ void FullscreenController::ToggleFullscreenModeForTab(WebContents* web_contents,
// case, all we have to do is notifying the tab that it has exited "tab
// fullscreen" mode.
NotifyTabOfExitIfNecessary();
+
+ // This is only a change between Browser and Tab fullscreen. We generate
+ // a fullscreen notification now because there is no window change.
+ PostFullscreenChangeNotification(true);
}
}
}
@@ -258,9 +266,7 @@ void FullscreenController::WindowFullscreenStateChanged() {
#else
exiting_fullscreen = !window_->IsFullscreen();
#endif
- MessageLoop::current()->PostTask(FROM_HERE,
- base::Bind(&FullscreenController::NotifyFullscreenChange,
- ptr_factory_.GetWeakPtr(), !exiting_fullscreen));
+ PostFullscreenChangeNotification(!exiting_fullscreen);
if (exiting_fullscreen)
NotifyTabOfExitIfNecessary();
if (exiting_fullscreen)
@@ -441,6 +447,13 @@ void FullscreenController::UpdateNotificationRegistrations() {
}
}
+void FullscreenController::PostFullscreenChangeNotification(
+ bool is_fullscreen) {
+ MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(&FullscreenController::NotifyFullscreenChange,
+ ptr_factory_.GetWeakPtr(), is_fullscreen));
+}
+
void FullscreenController::NotifyFullscreenChange(bool is_fullscreen) {
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_FULLSCREEN_CHANGED,
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller.h b/chrome/browser/ui/fullscreen/fullscreen_controller.h
index 918568c..7638076 100644
--- a/chrome/browser/ui/fullscreen/fullscreen_controller.h
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller.h
@@ -130,6 +130,9 @@ class FullscreenController : public content::NotificationObserver {
void UpdateNotificationRegistrations();
+ // Posts a task to call NotifyFullscreenChange.
+ void PostFullscreenChangeNotification(bool is_fullscreen);
+ // Sends a NOTIFICATION_FULLSCREEN_CHANGED notification.
void NotifyFullscreenChange(bool is_fullscreen);
// Notifies the tab that it has been forced out of fullscreen and mouse lock
// mode if necessary.
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller_browsertest.cc b/chrome/browser/ui/fullscreen/fullscreen_controller_browsertest.cc
index a154431..c9da148 100644
--- a/chrome/browser/ui/fullscreen/fullscreen_controller_browsertest.cc
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller_browsertest.cc
@@ -19,17 +19,17 @@
#include "base/mac/mac_util.h"
#endif
+using chrome::kAboutBlankURL;
using content::WebContents;
+using content::PAGE_TRANSITION_TYPED;
class FullscreenControllerBrowserTest: public FullscreenControllerTest {
};
IN_PROC_BROWSER_TEST_F(FullscreenControllerTest,
PendingMouseLockExitsOnTabSwitch) {
- AddTabAtIndexAndWait(0, GURL(chrome::kAboutBlankURL),
- content::PAGE_TRANSITION_TYPED);
- AddTabAtIndexAndWait(0, GURL(chrome::kAboutBlankURL),
- content::PAGE_TRANSITION_TYPED);
+ AddTabAtIndex(0, GURL(kAboutBlankURL), PAGE_TRANSITION_TYPED);
+ AddTabAtIndex(0, GURL(kAboutBlankURL), PAGE_TRANSITION_TYPED);
WebContents* tab1 = chrome::GetActiveWebContents(browser());
// Request mouse lock. Bubble is displayed.
@@ -62,10 +62,8 @@ IN_PROC_BROWSER_TEST_F(FullscreenControllerTest,
IN_PROC_BROWSER_TEST_F(FullscreenControllerTest,
PendingMouseLockExitsOnTabClose) {
// Add more tabs.
- AddTabAtIndexAndWait(0, GURL(chrome::kAboutBlankURL),
- content::PAGE_TRANSITION_TYPED);
- AddTabAtIndexAndWait(0, GURL(chrome::kAboutBlankURL),
- content::PAGE_TRANSITION_TYPED);
+ AddTabAtIndex(0, GURL(kAboutBlankURL), PAGE_TRANSITION_TYPED);
+ AddTabAtIndex(0, GURL(kAboutBlankURL), PAGE_TRANSITION_TYPED);
// Request mouse lock. Bubble is displayed.
RequestToLockMouse(true, false);
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller_interactive_browsertest.cc b/chrome/browser/ui/fullscreen/fullscreen_controller_interactive_browsertest.cc
index 0dc9507..5882c69 100644
--- a/chrome/browser/ui/fullscreen/fullscreen_controller_interactive_browsertest.cc
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller_interactive_browsertest.cc
@@ -20,7 +20,9 @@
#include "base/mac/mac_util.h"
#endif
+using chrome::kAboutBlankURL;
using content::WebContents;
+using content::PAGE_TRANSITION_TYPED;
namespace {
@@ -94,7 +96,7 @@ void FullscreenControllerInteractiveTest::ToggleBrowserFullscreen(
void
FullscreenControllerInteractiveTest::TestFullscreenMouseLockContentSettings() {
GURL url = test_server()->GetURL("simple.html");
- AddTabAtIndexAndWait(0, url, content::PAGE_TRANSITION_TYPED);
+ AddTabAtIndex(0, url, PAGE_TRANSITION_TYPED);
// Validate that going fullscreen for a URL defaults to asking permision.
ASSERT_FALSE(IsFullscreenPermissionRequested());
@@ -154,23 +156,19 @@ FullscreenControllerInteractiveTest::TestFullscreenMouseLockContentSettings() {
void FullscreenControllerInteractiveTest::ToggleTabFullscreen_Internal(
bool enter_fullscreen, bool retry_until_success) {
WebContents* tab = chrome::GetActiveWebContents(browser());
- if (IsFullscreenForBrowser()) {
- // Changing tab fullscreen state will not actually change the window
- // when browser fullscreen is in effect.
+ do {
+ FullscreenNotificationObserver fullscreen_observer;
browser()->ToggleFullscreenModeForTab(tab, enter_fullscreen);
- } else { // Not in browser fullscreen, expect window to actually change.
- ASSERT_NE(browser()->window()->IsFullscreen(), enter_fullscreen);
- do {
- FullscreenNotificationObserver fullscreen_observer;
- browser()->ToggleFullscreenModeForTab(tab, enter_fullscreen);
- fullscreen_observer.Wait();
- // Repeat ToggleFullscreenModeForTab until the correct state is entered.
- // This addresses flakiness on test bots running many fullscreen
- // tests in parallel.
- } while (retry_until_success &&
- browser()->window()->IsFullscreen() != enter_fullscreen);
+ fullscreen_observer.Wait();
+ // Repeat ToggleFullscreenModeForTab until the correct state is entered.
+ // This addresses flakiness on test bots running many fullscreen
+ // tests in parallel.
+ } while (retry_until_success &&
+ !IsFullscreenForBrowser() &&
+ browser()->window()->IsFullscreen() != enter_fullscreen);
+ ASSERT_EQ(IsFullscreenForTabOrPending(), enter_fullscreen);
+ if (!IsFullscreenForBrowser())
ASSERT_EQ(browser()->window()->IsFullscreen(), enter_fullscreen);
- }
}
// Tests ///////////////////////////////////////////////////////////////////////
@@ -181,15 +179,13 @@ IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
DISABLED_TestNewTabExitsFullscreen) {
ASSERT_TRUE(test_server()->Start());
- AddTabAtIndexAndWait(
- 0, GURL(chrome::kAboutBlankURL), content::PAGE_TRANSITION_TYPED);
+ AddTabAtIndex(0, GURL(kAboutBlankURL), PAGE_TRANSITION_TYPED);
ASSERT_NO_FATAL_FAILURE(ToggleTabFullscreen(true));
{
FullscreenNotificationObserver fullscreen_observer;
- AddTabAtIndexAndWait(
- 1, GURL(chrome::kAboutBlankURL), content::PAGE_TRANSITION_TYPED);
+ AddTabAtIndex(1, GURL(kAboutBlankURL), PAGE_TRANSITION_TYPED);
fullscreen_observer.Wait();
ASSERT_FALSE(browser()->window()->IsFullscreen());
}
@@ -201,8 +197,7 @@ IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
DISABLED_TestTabExitsItselfFromFullscreen) {
ASSERT_TRUE(test_server()->Start());
- AddTabAtIndexAndWait(
- 0, GURL(chrome::kAboutBlankURL), content::PAGE_TRANSITION_TYPED);
+ AddTabAtIndex(0, GURL(kAboutBlankURL), PAGE_TRANSITION_TYPED);
ASSERT_NO_FATAL_FAILURE(ToggleTabFullscreen(true));
ASSERT_NO_FATAL_FAILURE(ToggleTabFullscreen(false));
@@ -215,10 +210,8 @@ IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
DISABLED_TestFullscreenBubbleMouseLockState) {
ASSERT_TRUE(test_server()->Start());
- AddTabAtIndexAndWait(0, GURL(chrome::kAboutBlankURL),
- content::PAGE_TRANSITION_TYPED);
- AddTabAtIndexAndWait(1, GURL(chrome::kAboutBlankURL),
- content::PAGE_TRANSITION_TYPED);
+ AddTabAtIndex(0, GURL(kAboutBlankURL), PAGE_TRANSITION_TYPED);
+ AddTabAtIndex(1, GURL(kAboutBlankURL), PAGE_TRANSITION_TYPED);
ASSERT_NO_FATAL_FAILURE(ToggleTabFullscreen(true));
@@ -257,8 +250,7 @@ IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
ASSERT_NO_FATAL_FAILURE(ToggleBrowserFullscreen(true));
// Enter tab fullscreen.
- AddTabAtIndexAndWait(0, GURL(chrome::kAboutBlankURL),
- content::PAGE_TRANSITION_TYPED);
+ AddTabAtIndex(0, GURL(kAboutBlankURL), PAGE_TRANSITION_TYPED);
ASSERT_NO_FATAL_FAILURE(ToggleTabFullscreen(true));
// Exit browser fullscreen.
@@ -274,8 +266,7 @@ IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
ASSERT_NO_FATAL_FAILURE(ToggleBrowserFullscreen(true));
// Enter and then exit tab fullscreen.
- AddTabAtIndexAndWait(0, GURL(chrome::kAboutBlankURL),
- content::PAGE_TRANSITION_TYPED);
+ AddTabAtIndex(0, GURL(kAboutBlankURL), PAGE_TRANSITION_TYPED);
ASSERT_NO_FATAL_FAILURE(ToggleTabFullscreen(true));
ASSERT_NO_FATAL_FAILURE(ToggleTabFullscreen(false));
@@ -369,8 +360,7 @@ IN_PROC_BROWSER_TEST_F(
FullscreenControllerTest, DISABLED_TabEntersPresentationModeFromWindowed) {
ASSERT_TRUE(test_server()->Start());
- AddTabAtIndexAndWait(
- 0, GURL(chrome::kAboutBlankURL), content::PAGE_TRANSITION_TYPED);
+ AddTabAtIndex(0, GURL(kAboutBlankURL), PAGE_TRANSITION_TYPED);
WebContents* tab = chrome::GetActiveWebContents(browser());
@@ -877,7 +867,7 @@ IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
// http://crbug.com/133831
GURL url = test_server()->GetURL("simple.html");
- AddTabAtIndexAndWait(0, url, content::PAGE_TRANSITION_TYPED);
+ AddTabAtIndex(0, url, PAGE_TRANSITION_TYPED);
// Validate that going fullscreen for a URL defaults to asking permision.
ASSERT_FALSE(IsFullscreenPermissionRequested());
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller_state_interactive_browsertest.cc b/chrome/browser/ui/fullscreen/fullscreen_controller_state_interactive_browsertest.cc
new file mode 100644
index 0000000..1cc5739
--- /dev/null
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller_state_interactive_browsertest.cc
@@ -0,0 +1,226 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "build/build_config.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
+#include "chrome/browser/ui/fullscreen/fullscreen_controller_state_test.h"
+#include "chrome/browser/ui/fullscreen/fullscreen_controller_test.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/url_constants.h"
+#include "content/public/test/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using chrome::kAboutBlankURL;
+using content::PAGE_TRANSITION_TYPED;
+
+// Interactive test fixture testing Fullscreen Controller through its states. --
+// See documentation at the top of fullscreen_controller_state_unittest.cc.
+class FullscreenControllerStateInteractiveTest
+ : public InProcessBrowserTest,
+ public FullscreenControllerStateTest {
+ public:
+ // FullscreenControllerStateTest:
+ virtual void ChangeWindowFullscreenState() OVERRIDE;
+ virtual bool InvokeEvent(Event event) OVERRIDE;
+
+ protected:
+ // FullscreenControllerStateTest:
+ virtual bool ShouldSkipTest(State state,
+ Event event,
+ bool reentrant) OVERRIDE;
+ virtual Browser* GetBrowser() OVERRIDE;
+
+ scoped_ptr<FullscreenNotificationObserver> fullscreen_observer_;
+};
+
+void FullscreenControllerStateInteractiveTest::ChangeWindowFullscreenState() {
+ if (fullscreen_observer_) {
+ // If tests are stuck here, use the following log command to see progress.
+ // LOG(INFO) << GetAndClearDebugLog();
+ fullscreen_observer_->Wait();
+ fullscreen_observer_.reset(NULL);
+ }
+}
+
+bool FullscreenControllerStateInteractiveTest::InvokeEvent(Event event) {
+ switch (event) {
+ case TOGGLE_FULLSCREEN:
+ case TAB_FULLSCREEN_TRUE:
+ case TAB_FULLSCREEN_FALSE:
+#if defined(OS_WIN)
+ case METRO_SNAP_TRUE:
+ case METRO_SNAP_FALSE:
+#endif
+ fullscreen_observer_.reset(new FullscreenNotificationObserver());
+ break;
+ case WINDOW_CHANGE:
+ // ChangeWindowFullscreenState() will be called and then wait on
+ // fullscreen_observer_ if needed.
+ break;
+ default:
+ NOTREACHED() << "InvokeEvent needs a handler for event "
+ << GetEventString(event) << GetAndClearDebugLog();
+ return false;
+ }
+
+ return FullscreenControllerStateTest::InvokeEvent(event);
+}
+
+bool FullscreenControllerStateInteractiveTest::ShouldSkipTest(State state,
+ Event event,
+ bool reentrant) {
+ // Interactive tests run reentrant or not based on the platform
+ // implementation, so limit our test runs to match.
+#if defined(OS_WIN)
+ if (!reentrant) {
+ debugging_log_ << "\nSkipping non-reentrant test on Windows.\n";
+ return true;
+ }
+#else
+ if (reentrant) {
+ debugging_log_ << "\nSkipping reentrant test on non-Windows.\n";
+ return true;
+ }
+#endif
+
+ return FullscreenControllerStateTest::ShouldSkipTest(state,
+ event,
+ reentrant);
+}
+
+Browser* FullscreenControllerStateInteractiveTest::GetBrowser() {
+ return InProcessBrowserTest::browser();
+}
+
+// Tests -----------------------------------------------------------------------
+
+#define TEST_EVENT_INNER(state, event, reentrant, reentrant_id) \
+ IN_PROC_BROWSER_TEST_F(FullscreenControllerStateInteractiveTest, \
+ DISABLED_##state##__##event##reentrant_id) { \
+ AddTabAtIndex(0, GURL(kAboutBlankURL), PAGE_TRANSITION_TYPED); \
+ ASSERT_NO_FATAL_FAILURE(TestStateAndEvent(state, event, reentrant)) \
+ << GetAndClearDebugLog(); \
+ }
+ // Progress of tests can be examined by inserting the following line:
+ // LOG(INFO) << GetAndClearDebugLog(); }
+
+#define TEST_EVENT(state, event) \
+ TEST_EVENT_INNER(state, event, false, ); \
+ TEST_EVENT_INNER(state, event, true, _Reentrant);
+
+// Individual tests for each pair of state and event:
+
+TEST_EVENT(STATE_NORMAL, TOGGLE_FULLSCREEN);
+TEST_EVENT(STATE_NORMAL, TAB_FULLSCREEN_TRUE);
+TEST_EVENT(STATE_NORMAL, TAB_FULLSCREEN_FALSE);
+#if defined(OS_WIN)
+TEST_EVENT(STATE_NORMAL, METRO_SNAP_TRUE);
+TEST_EVENT(STATE_NORMAL, METRO_SNAP_FALSE);
+#endif
+TEST_EVENT(STATE_NORMAL, WINDOW_CHANGE);
+
+TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, TOGGLE_FULLSCREEN);
+TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_TRUE);
+TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_FALSE);
+#if defined(OS_WIN)
+TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_TRUE);
+TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_FALSE);
+#endif
+TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, WINDOW_CHANGE);
+
+#if defined(OS_WIN)
+TEST_EVENT(STATE_METRO_SNAP, TOGGLE_FULLSCREEN);
+TEST_EVENT(STATE_METRO_SNAP, TAB_FULLSCREEN_TRUE);
+TEST_EVENT(STATE_METRO_SNAP, TAB_FULLSCREEN_FALSE);
+TEST_EVENT(STATE_METRO_SNAP, METRO_SNAP_TRUE);
+TEST_EVENT(STATE_METRO_SNAP, METRO_SNAP_FALSE);
+TEST_EVENT(STATE_METRO_SNAP, WINDOW_CHANGE);
+#endif
+
+TEST_EVENT(STATE_TAB_FULLSCREEN, TOGGLE_FULLSCREEN);
+TEST_EVENT(STATE_TAB_FULLSCREEN, TAB_FULLSCREEN_TRUE);
+TEST_EVENT(STATE_TAB_FULLSCREEN, TAB_FULLSCREEN_FALSE);
+#if defined(OS_WIN)
+TEST_EVENT(STATE_TAB_FULLSCREEN, METRO_SNAP_TRUE);
+TEST_EVENT(STATE_TAB_FULLSCREEN, METRO_SNAP_FALSE);
+#endif
+TEST_EVENT(STATE_TAB_FULLSCREEN, WINDOW_CHANGE);
+
+TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, TOGGLE_FULLSCREEN);
+TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, TAB_FULLSCREEN_TRUE);
+TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, TAB_FULLSCREEN_FALSE);
+#if defined(OS_WIN)
+TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, METRO_SNAP_TRUE);
+TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, METRO_SNAP_FALSE);
+#endif
+TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, WINDOW_CHANGE);
+
+TEST_EVENT(STATE_TO_NORMAL, TOGGLE_FULLSCREEN);
+TEST_EVENT(STATE_TO_NORMAL, TAB_FULLSCREEN_TRUE);
+TEST_EVENT(STATE_TO_NORMAL, TAB_FULLSCREEN_FALSE);
+#if defined(OS_WIN)
+TEST_EVENT(STATE_TO_NORMAL, METRO_SNAP_TRUE);
+TEST_EVENT(STATE_TO_NORMAL, METRO_SNAP_FALSE);
+#endif
+TEST_EVENT(STATE_TO_NORMAL, WINDOW_CHANGE);
+
+TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, TOGGLE_FULLSCREEN);
+TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_TRUE);
+TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_FALSE);
+#if defined(OS_WIN)
+TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_TRUE);
+TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_FALSE);
+#endif
+TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, WINDOW_CHANGE);
+
+TEST_EVENT(STATE_TO_TAB_FULLSCREEN, TOGGLE_FULLSCREEN);
+TEST_EVENT(STATE_TO_TAB_FULLSCREEN, TAB_FULLSCREEN_TRUE);
+TEST_EVENT(STATE_TO_TAB_FULLSCREEN, TAB_FULLSCREEN_FALSE);
+#if defined(OS_WIN)
+TEST_EVENT(STATE_TO_TAB_FULLSCREEN, METRO_SNAP_TRUE);
+TEST_EVENT(STATE_TO_TAB_FULLSCREEN, METRO_SNAP_FALSE);
+#endif
+TEST_EVENT(STATE_TO_TAB_FULLSCREEN, WINDOW_CHANGE);
+
+// Specific one-off tests for known issues:
+
+// Used manually to determine what happens on a platform.
+IN_PROC_BROWSER_TEST_F(FullscreenControllerStateInteractiveTest,
+ DISABLED_ManualTest) {
+ // A tab is needed for tab fullscreen.
+ AddTabAtIndex(0, GURL(kAboutBlankURL), PAGE_TRANSITION_TYPED);
+ ASSERT_TRUE(InvokeEvent(TOGGLE_FULLSCREEN)) << GetAndClearDebugLog();
+ ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE)) << GetAndClearDebugLog();
+ ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE)) << GetAndClearDebugLog();
+ ASSERT_TRUE(InvokeEvent(TOGGLE_FULLSCREEN)) << GetAndClearDebugLog();
+ ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE)) << GetAndClearDebugLog();
+
+ // Wait, allowing human operator to observe the result.
+ scoped_refptr<content::MessageLoopRunner> message_loop;
+ message_loop = new content::MessageLoopRunner();
+ message_loop->Run();
+}
+
+// Soak tests:
+
+// Tests all states with all permutations of multiple events to detect lingering
+// state issues that would bleed over to other states.
+// I.E. for each state test all combinations of events E1, E2, E3.
+//
+// This produces coverage for event sequences that may happen normally but
+// would not be exposed by traversing to each state via TransitionToState().
+// TransitionToState() always takes the same path even when multiple paths
+// exist.
+IN_PROC_BROWSER_TEST_F(FullscreenControllerStateInteractiveTest,
+ DISABLED_TransitionsForEachState) {
+ // A tab is needed for tab fullscreen.
+ AddTabAtIndex(0, GURL(kAboutBlankURL), PAGE_TRANSITION_TYPED);
+ TestTransitionsForEachState();
+ // Progress of test can be examined via LOG(INFO) << GetAndClearDebugLog();
+}
+
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller_state_test.cc b/chrome/browser/ui/fullscreen/fullscreen_controller_state_test.cc
new file mode 100644
index 0000000..09283b4
--- /dev/null
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller_state_test.cc
@@ -0,0 +1,570 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/fullscreen/fullscreen_controller_state_test.h"
+
+#include <memory.h>
+
+#include <iomanip>
+#include <iostream>
+
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
+#include "content/public/common/url_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+FullscreenControllerStateTest::FullscreenControllerStateTest()
+ : state_(STATE_NORMAL),
+ reentrant_(false) {
+ // Human specified state machine data.
+ // For each state, for each event, define the resulting state.
+ State transition_table_data[][NUM_EVENTS] = {
+ { // STATE_NORMAL:
+ STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, // Event TOGGLE_FULLSCREEN
+ STATE_TO_TAB_FULLSCREEN, // Event TAB_FULLSCREEN_TRUE
+ STATE_NORMAL, // Event TAB_FULLSCREEN_FALSE
+#if defined(OS_WIN)
+ STATE_METRO_SNAP, // Event METRO_SNAP_TRUE
+ STATE_NORMAL, // Event METRO_SNAP_FALSE
+#endif
+ STATE_NORMAL, // Event WINDOW_CHANGE
+ },
+ { // STATE_BROWSER_FULLSCREEN_NO_CHROME:
+ STATE_TO_NORMAL, // Event TOGGLE_FULLSCREEN
+ STATE_TAB_BROWSER_FULLSCREEN, // Event TAB_FULLSCREEN_TRUE
+ STATE_BROWSER_FULLSCREEN_NO_CHROME, // Event TAB_FULLSCREEN_FALSE
+#if defined(OS_WIN)
+ STATE_METRO_SNAP, // Event METRO_SNAP_TRUE
+ STATE_BROWSER_FULLSCREEN_NO_CHROME, // Event METRO_SNAP_FALSE
+#endif
+ STATE_BROWSER_FULLSCREEN_NO_CHROME, // Event WINDOW_CHANGE
+ },
+#if defined(OS_WIN)
+ { // STATE_METRO_SNAP:
+ STATE_METRO_SNAP, // Event TOGGLE_FULLSCREEN
+ STATE_METRO_SNAP, // Event TAB_FULLSCREEN_TRUE
+ STATE_METRO_SNAP, // Event TAB_FULLSCREEN_FALSE
+ STATE_METRO_SNAP, // Event METRO_SNAP_TRUE
+ STATE_NORMAL, // Event METRO_SNAP_FALSE
+ STATE_METRO_SNAP, // Event WINDOW_CHANGE
+ },
+#endif
+ { // STATE_TAB_FULLSCREEN:
+ STATE_TO_NORMAL, // Event TOGGLE_FULLSCREEN
+ STATE_TAB_FULLSCREEN, // Event TAB_FULLSCREEN_TRUE
+ STATE_TO_NORMAL, // Event TAB_FULLSCREEN_FALSE
+#if defined(OS_WIN)
+ STATE_METRO_SNAP, // Event METRO_SNAP_TRUE
+ STATE_TAB_FULLSCREEN, // Event METRO_SNAP_FALSE
+#endif
+ STATE_TAB_FULLSCREEN, // Event WINDOW_CHANGE
+ },
+ { // STATE_TAB_BROWSER_FULLSCREEN:
+ STATE_TO_NORMAL, // Event TOGGLE_FULLSCREEN
+ STATE_TAB_BROWSER_FULLSCREEN, // Event TAB_FULLSCREEN_TRUE
+#if defined(OS_MACOSX)
+ // TODO(scheib) Mac exits browser mode too http://crbug.com/155642
+ STATE_TO_NORMAL, // Event TAB_FULLSCREEN_FALSE
+#else
+ STATE_BROWSER_FULLSCREEN_NO_CHROME, // Event TAB_FULLSCREEN_FALSE
+#endif
+#if defined(OS_WIN)
+ STATE_METRO_SNAP, // Event METRO_SNAP_TRUE
+ STATE_TAB_BROWSER_FULLSCREEN, // Event METRO_SNAP_FALSE
+#endif
+ STATE_TAB_BROWSER_FULLSCREEN, // Event WINDOW_CHANGE
+ },
+ // STATE_TO_NORMAL:
+ { STATE_TO_NORMAL, // Event TOGGLE_FULLSCREEN
+ // TODO(scheib) Should be a route back to TAB. http://crbug.com/154196
+ STATE_TO_NORMAL, // Event TAB_FULLSCREEN_TRUE
+ STATE_TO_NORMAL, // Event TAB_FULLSCREEN_FALSE
+#if defined(OS_WIN)
+ STATE_METRO_SNAP, // Event METRO_SNAP_TRUE
+ STATE_TO_NORMAL, // Event METRO_SNAP_FALSE
+#endif
+ STATE_NORMAL, // Event WINDOW_CHANGE
+ },
+ // STATE_TO_BROWSER_FULLSCREEN_NO_CHROME:
+ { STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, // Event TOGGLE_FULLSCREEN
+ // TODO(scheib) Should be a route to TAB_BROWSER http://crbug.com/154196
+ STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, // Event TAB_FULLSCREEN_TRUE
+ STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, // Event TAB_FULLSCREEN_FALSE
+#if defined(OS_WIN)
+ STATE_METRO_SNAP, // Event METRO_SNAP_TRUE
+ STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, // Event METRO_SNAP_FALSE
+#endif
+ STATE_BROWSER_FULLSCREEN_NO_CHROME, // Event WINDOW_CHANGE
+ },
+ // STATE_TO_TAB_FULLSCREEN:
+ { // TODO(scheib) Should be a route to TAB_BROWSER http://crbug.com/154196
+ STATE_TO_TAB_FULLSCREEN, // Event TOGGLE_FULLSCREEN
+ STATE_TO_TAB_FULLSCREEN, // Event TAB_FULLSCREEN_TRUE
+ // TODO(scheib) Should be a route back to NORMAL. http://crbug.com/154196
+ STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, // Event TAB_FULLSCREEN_FALSE
+#if defined(OS_WIN)
+ STATE_METRO_SNAP, // Event METRO_SNAP_TRUE
+ STATE_TO_TAB_FULLSCREEN, // Event METRO_SNAP_FALSE
+#endif
+ STATE_TAB_FULLSCREEN, // Event WINDOW_CHANGE
+ },
+ };
+ CHECK_EQ(sizeof(transition_table_data), sizeof(transition_table_));
+ memcpy(transition_table_, transition_table_data,
+ sizeof(transition_table_data));
+
+ // Verify that transition_table_ has been completely defined.
+ for (int source = 0; source < NUM_STATES; source++) {
+ for (int event = 0; event < NUM_EVENTS; event++) {
+ CHECK_NE(STATE_INVALID, transition_table_[source][event]);
+ CHECK_LE(0, transition_table_[source][event]);
+ CHECK_GT(NUM_STATES, transition_table_[source][event]);
+ }
+ }
+
+ // Copy transition_table_ data into state_transitions_ table.
+ for (int source = 0; source < NUM_STATES; source++) {
+ for (int event = 0; event < NUM_EVENTS; event++) {
+ State destination = transition_table_[source][event];
+ state_transitions_[source][destination].event = static_cast<Event>(event);
+ state_transitions_[source][destination].state = destination;
+ state_transitions_[source][destination].distance = 1;
+ }
+ }
+}
+
+FullscreenControllerStateTest::~FullscreenControllerStateTest() {
+}
+
+// static
+const char* FullscreenControllerStateTest::GetStateString(State state) {
+ switch (state) {
+ case STATE_NORMAL:
+ return "STATE_NORMAL";
+ case STATE_BROWSER_FULLSCREEN_NO_CHROME:
+ return "STATE_BROWSER_FULLSCREEN_NO_CHROME";
+#if defined(OS_WIN)
+ case STATE_METRO_SNAP:
+ return "STATE_METRO_SNAP";
+#endif
+ case STATE_TAB_FULLSCREEN:
+ return "STATE_TAB_FULLSCREEN";
+ case STATE_TAB_BROWSER_FULLSCREEN:
+ return "STATE_TAB_BROWSER_FULLSCREEN";
+ case STATE_TO_NORMAL:
+ return "STATE_TO_NORMAL";
+ case STATE_TO_BROWSER_FULLSCREEN_NO_CHROME:
+ return "STATE_TO_BROWSER_FULLSCREEN_NO_CHROME";
+ case STATE_TO_TAB_FULLSCREEN:
+ return "STATE_TO_TAB_FULLSCREEN";
+ case STATE_INVALID:
+ return "STATE_INVALID";
+ default:
+ NOTREACHED() << "No string for state " << state;
+ return "State-Unknown";
+ }
+}
+
+// static
+const char* FullscreenControllerStateTest::GetEventString(Event event) {
+ switch (event) {
+ case TOGGLE_FULLSCREEN:
+ return "TOGGLE_FULLSCREEN";
+ case TAB_FULLSCREEN_TRUE:
+ return "TAB_FULLSCREEN_TRUE";
+ case TAB_FULLSCREEN_FALSE:
+ return "TAB_FULLSCREEN_FALSE";
+#if defined(OS_WIN)
+ case METRO_SNAP_TRUE:
+ return "METRO_SNAP_TRUE";
+ case METRO_SNAP_FALSE:
+ return "METRO_SNAP_FALSE";
+#endif
+ case WINDOW_CHANGE:
+ return "WINDOW_CHANGE";
+ case EVENT_INVALID:
+ return "EVENT_INVALID";
+ default:
+ NOTREACHED() << "No string for event " << event;
+ return "Event-Unknown";
+ }
+}
+
+void FullscreenControllerStateTest::TransitionToState(State final_state) {
+ int max_steps = NUM_STATES;
+ while (max_steps-- && TransitionAStepTowardState(final_state))
+ continue;
+ ASSERT_GE(max_steps, 0) << "TransitionToState was unable to achieve desired "
+ << "target state. TransitionAStepTowardState iterated too many times."
+ << GetAndClearDebugLog();
+ ASSERT_EQ(final_state, state_) << "TransitionToState was unable to achieve "
+ << "desired target state. TransitionAStepTowardState returned false."
+ << GetAndClearDebugLog();
+}
+
+bool FullscreenControllerStateTest::TransitionAStepTowardState(
+ State destination_state) {
+ State source_state = state_;
+ if (source_state == destination_state)
+ return false;
+
+ StateTransitionInfo next = NextTransitionInShortestPath(source_state,
+ destination_state,
+ NUM_STATES);
+ if (next.state == STATE_INVALID) {
+ NOTREACHED() << "TransitionAStepTowardState unable to transition. "
+ << "NextTransitionInShortestPath("
+ << GetStateString(source_state) << ", "
+ << GetStateString(destination_state) << ") returned STATE_INVALID."
+ << GetAndClearDebugLog();
+ return false;
+ }
+
+ return InvokeEvent(next.event);
+}
+
+const char* FullscreenControllerStateTest::GetWindowStateString() {
+ return NULL;
+}
+
+bool FullscreenControllerStateTest::InvokeEvent(Event event) {
+ State source_state = state_;
+ State next_state = transition_table_[source_state][event];
+
+ // When simulating reentrant window change calls, expect the next state
+ // automatically.
+ if (reentrant_)
+ next_state = transition_table_[next_state][WINDOW_CHANGE];
+
+ debugging_log_ << " InvokeEvent(" << std::left
+ << std::setw(MAX_EVENT_NAME_LENGTH) << GetEventString(event)
+ << ") to "
+ << std::setw(MAX_STATE_NAME_LENGTH) << GetStateString(next_state);
+
+ state_ = next_state;
+
+ switch (event) {
+ case TOGGLE_FULLSCREEN:
+ GetFullscreenController()->ToggleFullscreenMode();
+ break;
+ case TAB_FULLSCREEN_TRUE:
+ GetFullscreenController()->ToggleFullscreenModeForTab(
+ chrome::GetActiveWebContents(GetBrowser()), true);
+ break;
+ case TAB_FULLSCREEN_FALSE:
+ GetFullscreenController()->ToggleFullscreenModeForTab(
+ chrome::GetActiveWebContents(GetBrowser()), false);
+ break;
+#if defined(OS_WIN)
+ case METRO_SNAP_TRUE:
+ GetFullscreenController()->SetMetroSnapMode(true);
+ break;
+ case METRO_SNAP_FALSE:
+ GetFullscreenController()->SetMetroSnapMode(false);
+ break;
+#endif
+ case WINDOW_CHANGE:
+ ChangeWindowFullscreenState();
+ break;
+ default:
+ NOTREACHED() << "InvokeEvent needs a handler for event "
+ << GetEventString(event) << GetAndClearDebugLog();
+ return false;
+ }
+
+ if (GetWindowStateString())
+ debugging_log_ << " Window state now " << GetWindowStateString() << "\n";
+ else
+ debugging_log_ << "\n";
+
+ VerifyWindowState();
+
+ return true;
+}
+
+void FullscreenControllerStateTest::VerifyWindowState() {
+ switch (state_) {
+ case STATE_NORMAL:
+#if defined(OS_MACOSX)
+ EXPECT_FALSE(GetBrowser()->window()->InPresentationMode())
+ << GetAndClearDebugLog();
+#endif
+ EXPECT_FALSE(GetFullscreenController()->IsFullscreenForBrowser())
+ << GetAndClearDebugLog();
+ EXPECT_FALSE(GetFullscreenController()->IsFullscreenForTabOrPending())
+ << GetAndClearDebugLog();
+ EXPECT_FALSE(GetFullscreenController()->IsInMetroSnapMode())
+ << GetAndClearDebugLog();
+ break;
+ case STATE_BROWSER_FULLSCREEN_NO_CHROME:
+#if defined(OS_MACOSX)
+ EXPECT_FALSE(GetBrowser()->window()->InPresentationMode())
+ << GetAndClearDebugLog();
+#endif
+ EXPECT_TRUE(GetFullscreenController()->IsFullscreenForBrowser())
+ << GetAndClearDebugLog();
+ EXPECT_FALSE(GetFullscreenController()->IsFullscreenForTabOrPending())
+ << GetAndClearDebugLog();
+ EXPECT_FALSE(GetFullscreenController()->IsInMetroSnapMode())
+ << GetAndClearDebugLog();
+ break;
+#if defined(OS_WIN)
+ case STATE_METRO_SNAP:
+ // No expectation for InPresentationMode.
+
+ // TODO(scheib) IsFullscreenForBrowser and IsFullscreenForTabOrPending
+ // are returning true and false in interactive tests with real window.
+ // With only a single Metro Snap state in this test framework it isn't
+ // fair to try to have an expectation anyway.
+ //
+ // No expectation for IsFullscreenForBrowser.
+ // No expectation for IsFullscreenForTabOrPending.
+ EXPECT_TRUE(GetFullscreenController()->IsInMetroSnapMode())
+ << GetAndClearDebugLog();
+ break;
+#endif
+ case STATE_TAB_FULLSCREEN:
+#if defined(OS_MACOSX)
+ EXPECT_TRUE(GetBrowser()->window()->InPresentationMode())
+ << GetAndClearDebugLog();
+#endif
+ EXPECT_FALSE(GetFullscreenController()->IsFullscreenForBrowser())
+ << GetAndClearDebugLog();
+ EXPECT_TRUE(GetFullscreenController()->IsFullscreenForTabOrPending())
+ << GetAndClearDebugLog();
+ EXPECT_FALSE(GetFullscreenController()->IsInMetroSnapMode())
+ << GetAndClearDebugLog();
+ break;
+ case STATE_TAB_BROWSER_FULLSCREEN:
+#if defined(OS_MACOSX)
+ EXPECT_TRUE(GetBrowser()->window()->InPresentationMode())
+ << GetAndClearDebugLog();
+#endif
+#if defined(OS_MACOSX)
+ // TODO(scheib) Mac is reporting incorrect IsFullscreenForBrowser().
+ // e.g. in FullscreenControllerStateTest.
+ // STATE_BROWSER_FULLSCREEN_NO_CHROME__TAB_FULLSCREEN_TRUE
+ // At the end of ToggleFullscreenModeForTab
+ // tab_caused_fullscreen_ has incorrectly been set to true even
+ // though controller was already in browser fullscreen.
+ // http://crbug.com/155650
+ EXPECT_FALSE(GetFullscreenController()->IsFullscreenForBrowser())
+ << GetAndClearDebugLog();
+#else
+ EXPECT_TRUE(GetFullscreenController()->IsFullscreenForBrowser())
+ << GetAndClearDebugLog();
+#endif
+ EXPECT_TRUE(GetFullscreenController()->IsFullscreenForTabOrPending())
+ << GetAndClearDebugLog();
+ EXPECT_FALSE(GetFullscreenController()->IsInMetroSnapMode())
+ << GetAndClearDebugLog();
+ break;
+ case STATE_TO_NORMAL:
+#if defined(OS_MACOSX)
+ EXPECT_FALSE(GetBrowser()->window()->InPresentationMode())
+ << GetAndClearDebugLog();
+#endif
+ // No expectation for IsFullscreenForBrowser.
+ // No expectation for IsFullscreenForTabOrPending.
+ EXPECT_FALSE(GetFullscreenController()->IsInMetroSnapMode())
+ << GetAndClearDebugLog();
+ break;
+ case STATE_TO_BROWSER_FULLSCREEN_NO_CHROME:
+#if defined(OS_MACOSX)
+ EXPECT_FALSE(GetBrowser()->window()->InPresentationMode())
+ << GetAndClearDebugLog();
+ EXPECT_TRUE(GetFullscreenController()->IsFullscreenForBrowser())
+ << GetAndClearDebugLog();
+#else
+ EXPECT_FALSE(GetFullscreenController()->IsFullscreenForBrowser())
+ << GetAndClearDebugLog();
+#endif
+ // No expectation for IsFullscreenForTabOrPending.
+ EXPECT_FALSE(GetFullscreenController()->IsInMetroSnapMode())
+ << GetAndClearDebugLog();
+ break;
+ case STATE_TO_TAB_FULLSCREEN:
+#if defined(OS_MACOSX)
+ // TODO(scheib) InPresentationMode returns false when invoking events:
+ // TAB_FULLSCREEN_TRUE, TOGGLE_FULLSCREEN. http://crbug.com/156645
+ // It may be that a new testing state TO_TAB_BROWSER_FULLSCREEN
+ // would help work around this http://crbug.com/154196
+ // Test with: STATE_TO_TAB_FULLSCREEN__TOGGLE_FULLSCREEN
+ //
+ // EXPECT_TRUE(GetBrowser()->window()->InPresentationMode())
+ // << GetAndClearDebugLog();
+#endif
+ EXPECT_FALSE(GetFullscreenController()->IsFullscreenForBrowser())
+ << GetAndClearDebugLog();
+ EXPECT_TRUE(GetFullscreenController()->IsFullscreenForTabOrPending())
+ << GetAndClearDebugLog();
+ EXPECT_FALSE(GetFullscreenController()->IsInMetroSnapMode())
+ << GetAndClearDebugLog();
+ break;
+ default:
+ NOTREACHED() << GetAndClearDebugLog();
+ }
+}
+
+void FullscreenControllerStateTest::TestTransitionsForEachState() {
+ for (int reentrant = 0; reentrant <= 1; reentrant++) {
+ for (int source_int = 0; source_int < NUM_STATES; source_int++) {
+ for (int event1_int = 0; event1_int < NUM_EVENTS; event1_int++) {
+ State state = static_cast<State>(source_int);
+ Event event1 = static_cast<Event>(event1_int);
+
+ // Early out if skipping all tests for this state, reduces log noise.
+ if (ShouldSkipTest(state, event1, !!reentrant))
+ continue;
+
+ for (int event2_int = 0; event2_int < NUM_EVENTS; event2_int++) {
+ for (int event3_int = 0; event3_int < NUM_EVENTS; event3_int++) {
+ Event event2 = static_cast<Event>(event2_int);
+ Event event3 = static_cast<Event>(event3_int);
+
+ // Test each state and each event.
+ ASSERT_NO_FATAL_FAILURE(TestStateAndEvent(state,
+ event1,
+ !!reentrant))
+ << GetAndClearDebugLog();
+
+ // Then, add an additional event to the sequence.
+ if (ShouldSkipStateAndEventPair(state_, event2))
+ continue;
+ ASSERT_TRUE(InvokeEvent(event2)) << GetAndClearDebugLog();
+
+ // Then, add an additional event to the sequence.
+ if (ShouldSkipStateAndEventPair(state_, event3))
+ continue;
+ ASSERT_TRUE(InvokeEvent(event3)) << GetAndClearDebugLog();
+ }
+ }
+ }
+ }
+ }
+}
+
+FullscreenControllerStateTest::StateTransitionInfo
+ FullscreenControllerStateTest::NextTransitionInShortestPath(
+ State source, State destination, int search_limit) {
+ if (search_limit == 0)
+ return StateTransitionInfo(); // Return a default (invalid) state.
+
+ if (state_transitions_[source][destination].state == STATE_INVALID) {
+ // Don't know the next state yet, do a depth first search.
+ StateTransitionInfo result;
+
+ // Consider all states reachable via each event from the source state.
+ for (int event_int = 0; event_int < NUM_EVENTS; event_int++) {
+ Event event = static_cast<Event>(event_int);
+ State next_state_candidate = transition_table_[source][event];
+
+ if (ShouldSkipStateAndEventPair(source, event))
+ continue;
+
+ // Recurse.
+ StateTransitionInfo candidate = NextTransitionInShortestPath(
+ next_state_candidate, destination, search_limit - 1);
+
+ if (candidate.distance + 1 < result.distance) {
+ result.event = event;
+ result.state = next_state_candidate;
+ result.distance = candidate.distance + 1;
+ }
+ }
+
+ // Cache result so that a search is not required next time.
+ state_transitions_[source][destination] = result;
+ }
+
+ return state_transitions_[source][destination];
+}
+
+std::string FullscreenControllerStateTest::GetAndClearDebugLog() {
+ debugging_log_ << "(End of Debugging Log)\n";
+ std::string output_log = "\nDebugging Log:\n" + debugging_log_.str();
+ debugging_log_.str("");
+ return output_log;
+}
+
+bool FullscreenControllerStateTest::ShouldSkipStateAndEventPair(State state,
+ Event event) {
+ // TODO(scheib) Toggling Tab fullscreen while pending Tab or
+ // Browser fullscreen is broken currently http://crbug.com/154196
+ if ((state == STATE_TO_BROWSER_FULLSCREEN_NO_CHROME ||
+ state == STATE_TO_TAB_FULLSCREEN) &&
+ (event == TAB_FULLSCREEN_TRUE || event == TAB_FULLSCREEN_FALSE))
+ return true;
+ if (state == STATE_TO_NORMAL && event == TAB_FULLSCREEN_TRUE)
+ return true;
+
+ return false;
+}
+
+bool FullscreenControllerStateTest::ShouldSkipTest(State state,
+ Event event,
+ bool reentrant) {
+#if defined(OS_WIN)
+ // FullscreenController verifies that WindowFullscreenStateChanged is
+ // always reentrant on Windows. It will fail if we mock asynchronous calls.
+ if (!reentrant) {
+ debugging_log_ << "\nSkipping non-reentrant test on Windows.\n";
+ return true;
+ }
+#else
+ if (reentrant) {
+ debugging_log_ << "\nSkipping reentrant test on non-Windows.\n";
+ return true;
+ }
+#endif
+
+ // When testing reentrancy there are states the fullscreen controller
+ // will be unable to remain in, as they will progress due to the
+ // reentrant window change call. Skip states that will be instantly
+ // exited by the reentrant call.
+ if (reentrant && (transition_table_[state][WINDOW_CHANGE] != state)) {
+ debugging_log_ << "\nSkipping reentrant test for transitory source state "
+ << GetStateString(state) << ".\n";
+ return true;
+ }
+
+ if (ShouldSkipStateAndEventPair(state, event)) {
+ debugging_log_ << "\nSkipping test due to ShouldSkipStateAndEventPair("
+ << GetStateString(state) << ", "
+ << GetEventString(event) << ").\n";
+ LOG(INFO) << "Skipping test due to ShouldSkipStateAndEventPair("
+ << GetStateString(state) << ", "
+ << GetEventString(event) << ").";
+ return true;
+ }
+
+ return false;
+}
+
+void FullscreenControllerStateTest::TestStateAndEvent(State state,
+ Event event,
+ bool reentrant) {
+ if (ShouldSkipTest(state, event, reentrant))
+ return;
+
+ debugging_log_ << "\nTest transition from state "
+ << GetStateString(state)
+ << (reentrant ? " with reentrant calls.\n" : ".\n");
+ reentrant_ = reentrant;
+
+ debugging_log_ << " First, from "
+ << GetStateString(state_) << "\n";
+ ASSERT_NO_FATAL_FAILURE(TransitionToState(state))
+ << GetAndClearDebugLog();
+
+ debugging_log_ << " Then,\n";
+ ASSERT_TRUE(InvokeEvent(event)) << GetAndClearDebugLog();
+}
+
+FullscreenController* FullscreenControllerStateTest::GetFullscreenController() {
+ return GetBrowser()->fullscreen_controller();
+}
+
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller_state_test.h b/chrome/browser/ui/fullscreen/fullscreen_controller_state_test.h
new file mode 100644
index 0000000..14dc0de
--- /dev/null
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller_state_test.h
@@ -0,0 +1,143 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_STATE_TEST_H_
+#define CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_STATE_TEST_H_
+
+#include <sstream>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "build/build_config.h"
+
+class Browser;
+class FullscreenController;
+
+// Test fixture testing Fullscreen Controller through its states. --------------
+class FullscreenControllerStateTest {
+ public:
+ enum State {
+ // The window is not in fullscreen.
+ STATE_NORMAL,
+ // User-initiated fullscreen. On Mac, this is Lion-mode for 10.7+. On 10.6,
+ // this is synonymous with STATE_BROWSER_FULLSCREEN_WITH_CHROME.
+ STATE_BROWSER_FULLSCREEN_NO_CHROME,
+#if defined(OS_WIN)
+ // Windows 8 Metro Snap mode, which puts the window at 20% screen-width.
+ // No TO_ state for Metro, as the windows implementation is only reentrant.
+ STATE_METRO_SNAP,
+#endif
+ // HTML5 tab-initiated fullscreen.
+ STATE_TAB_FULLSCREEN,
+ // Both tab and browser fullscreen.
+ STATE_TAB_BROWSER_FULLSCREEN,
+ // TO_ states are asynchronous states waiting for window state change
+ // before transitioning to their named state.
+ STATE_TO_NORMAL,
+ STATE_TO_BROWSER_FULLSCREEN_NO_CHROME,
+ STATE_TO_TAB_FULLSCREEN,
+ NUM_STATES,
+ STATE_INVALID,
+ };
+
+ enum Event {
+ // FullscreenController::ToggleFullscreenMode()
+ TOGGLE_FULLSCREEN,
+ // FullscreenController::ToggleFullscreenModeForTab(, true)
+ TAB_FULLSCREEN_TRUE,
+ // FullscreenController::ToggleFullscreenModeForTab(, false)
+ TAB_FULLSCREEN_FALSE,
+#if defined(OS_WIN)
+ // FullscreenController::SetMetroSnapMode(true)
+ METRO_SNAP_TRUE,
+ // FullscreenController::SetMetroSnapMode(flase)
+ METRO_SNAP_FALSE,
+#endif
+ // FullscreenController::ChangeWindowFullscreenState()
+ WINDOW_CHANGE,
+ NUM_EVENTS,
+ EVENT_INVALID,
+ };
+
+ static const int MAX_STATE_NAME_LENGTH = 37;
+ static const int MAX_EVENT_NAME_LENGTH = 20;
+
+ FullscreenControllerStateTest();
+ virtual ~FullscreenControllerStateTest();
+
+ static const char* GetStateString(State state);
+ static const char* GetEventString(Event event);
+
+ // Causes Fullscreen Controller to transition to an arbitrary state.
+ void TransitionToState(State state);
+ // Makes one state change to approach |destination_state| via shortest path.
+ // Returns true if a state change is made.
+ // Repeated calls are needed to reach the destination.
+ bool TransitionAStepTowardState(State destination_state);
+
+ virtual void ChangeWindowFullscreenState() {}
+ virtual const char* GetWindowStateString();
+
+ // Causes the |event| to occur and return true on success.
+ virtual bool InvokeEvent(Event event);
+
+ // Checks that window state matches the expected controller state.
+ virtual void VerifyWindowState();
+
+ // Tests all states with all permutations of multiple events to detect
+ // lingering state issues that would bleed over to other states.
+ // I.E. for each state test all combinations of events E1, E2, E3.
+ //
+ // This produces coverage for event sequences that may happen normally but
+ // would not be exposed by traversing to each state via TransitionToState().
+ // TransitionToState() always takes the same path even when multiple paths
+ // exist.
+ void TestTransitionsForEachState();
+
+ protected:
+ // Generated information about the transitions between states.
+ struct StateTransitionInfo {
+ StateTransitionInfo()
+ : event(EVENT_INVALID),
+ state(STATE_INVALID),
+ distance(NUM_STATES) {}
+ Event event; // The |Event| that will cause the state transition.
+ State state; // The adjacent |State| transitioned to; not the final state.
+ int distance; // Steps to final state. NUM_STATES represents unknown.
+ };
+
+ // Returns next transition info for shortest path from source to destination.
+ StateTransitionInfo NextTransitionInShortestPath(State source,
+ State destination,
+ int search_limit);
+
+ std::string GetAndClearDebugLog();
+
+ // Avoids currently broken cases in the fullscreen controller.
+ virtual bool ShouldSkipStateAndEventPair(State state, Event event);
+ // Skips reentrant situations and calls ShouldSkipStateAndEventPair.
+ virtual bool ShouldSkipTest(State state, Event event, bool reentrant);
+
+ // Runs one test of transitioning to a state and invoking an event.
+ virtual void TestStateAndEvent(State state, Event event, bool reentrant);
+
+ virtual Browser* GetBrowser() = 0;
+ FullscreenController* GetFullscreenController();
+
+ State state_;
+ bool reentrant_;
+
+ // Human defined |State| that results given each [state][event] pair.
+ State transition_table_[NUM_STATES][NUM_EVENTS];
+
+ // Generated information about the transitions between states [from][to].
+ StateTransitionInfo state_transitions_[NUM_STATES][NUM_STATES];
+
+ // Log of operations reported on errors via GetAndClearDebugLog().
+ std::ostringstream debugging_log_;
+
+ DISALLOW_COPY_AND_ASSIGN(FullscreenControllerStateTest);
+};
+
+#endif // CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_STATE_TEST_H_
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller_state_unittest.cc b/chrome/browser/ui/fullscreen/fullscreen_controller_state_unittest.cc
new file mode 100644
index 0000000..160f3b3
--- /dev/null
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller_state_unittest.cc
@@ -0,0 +1,457 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "build/build_config.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
+#include "chrome/browser/ui/fullscreen/fullscreen_controller_state_test.h"
+#include "chrome/test/base/browser_with_test_window_test.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/url_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// The FullscreenControllerStateUnitTest unit test suite exhastively tests
+// the FullscreenController through all permutations of events. The behavior
+// of the BrowserWindow is mocked via FullscreenControllerTestWindow.
+//
+// FullscreenControllerStateInteractiveTest is an interactive test suite
+// used to verify that the FullscreenControllerTestWindow models the behavior
+// of actual windows accurately. The interactive tests are too flaky to run
+// on infrastructure, and so those tests are disabled. Run them with:
+// interactive_ui_tests
+// --gtest_filter="FullscreenControllerStateInteractiveTest.*"
+// --gtest_also_run_disabled_tests
+
+// A BrowserWindow used for testing FullscreenController. ----------------------
+class FullscreenControllerTestWindow : public TestBrowserWindow {
+ public:
+ // Simulate the window state with an enumeration.
+ enum WindowState {
+ NORMAL,
+ FULLSCREEN,
+ // No TO_ state for METRO_SNAP, the windows implementation is synchronous.
+ METRO_SNAP,
+ TO_NORMAL,
+ TO_FULLSCREEN,
+ };
+
+ FullscreenControllerTestWindow();
+ virtual ~FullscreenControllerTestWindow() {}
+
+ // BrowserWindow Interface:
+ virtual void EnterFullscreen(const GURL& url,
+ FullscreenExitBubbleType type) OVERRIDE;
+ virtual void EnterFullscreen();
+ virtual void ExitFullscreen() OVERRIDE;
+ virtual bool IsFullscreen() const OVERRIDE;
+#if defined(OS_WIN)
+ virtual void SetMetroSnapMode(bool enable) OVERRIDE;
+ virtual bool IsInMetroSnapMode() const OVERRIDE;
+#endif
+#if defined(OS_MACOSX)
+ virtual void EnterPresentationMode(
+ const GURL& url,
+ FullscreenExitBubbleType bubble_type) OVERRIDE;
+ virtual void ExitPresentationMode() OVERRIDE;
+ virtual bool InPresentationMode() OVERRIDE;
+#endif
+
+ static const char* GetWindowStateString(WindowState state);
+ WindowState state() const { return state_; }
+ void set_browser(Browser* browser) { browser_ = browser; }
+ void set_reentrant(bool value) { reentrant_ = value; }
+ bool reentrant() const { return reentrant_; }
+
+ // Simulates the window changing state.
+ void ChangeWindowFullscreenState();
+ // Calls ChangeWindowFullscreenState() if |reentrant_| is true.
+ void ChangeWindowFullscreenStateIfReentrant();
+
+ private:
+ WindowState state_;
+ bool mac_presentation_mode_;
+ Browser* browser_;
+
+ // Causes reentrant calls to be made by calling
+ // browser_->WindowFullscreenStateChanged() from the BrowserWindow
+ // interface methods.
+ bool reentrant_;
+};
+
+FullscreenControllerTestWindow::FullscreenControllerTestWindow()
+ : state_(NORMAL),
+ mac_presentation_mode_(false),
+ browser_(NULL),
+ reentrant_(false) {
+}
+
+void FullscreenControllerTestWindow::EnterFullscreen(
+ const GURL& url, FullscreenExitBubbleType type) {
+ EnterFullscreen();
+}
+
+void FullscreenControllerTestWindow::EnterFullscreen() {
+ if (!IsFullscreen()) {
+ state_ = TO_FULLSCREEN;
+ ChangeWindowFullscreenStateIfReentrant();
+ }
+}
+
+void FullscreenControllerTestWindow::ExitFullscreen() {
+ if (IsFullscreen()) {
+ state_ = TO_NORMAL;
+ mac_presentation_mode_ = false;
+ ChangeWindowFullscreenStateIfReentrant();
+ }
+}
+
+bool FullscreenControllerTestWindow::IsFullscreen() const {
+#if defined(OS_MACOSX)
+ return state_ == FULLSCREEN || state_ == TO_FULLSCREEN;
+#else
+ return state_ == FULLSCREEN || state_ == TO_NORMAL;
+#endif
+}
+
+#if defined(OS_WIN)
+void FullscreenControllerTestWindow::SetMetroSnapMode(bool enable) {
+ if (enable != IsInMetroSnapMode()) {
+ if (enable)
+ state_ = METRO_SNAP;
+ else
+ state_ = NORMAL;
+ }
+ ChangeWindowFullscreenStateIfReentrant();
+}
+
+bool FullscreenControllerTestWindow::IsInMetroSnapMode() const {
+ return state_ == METRO_SNAP;
+}
+#endif
+
+#if defined(OS_MACOSX)
+void FullscreenControllerTestWindow::EnterPresentationMode(
+ const GURL& url,
+ FullscreenExitBubbleType bubble_type) {
+ mac_presentation_mode_ = true;
+ EnterFullscreen();
+}
+
+void FullscreenControllerTestWindow::ExitPresentationMode() {
+ if (InPresentationMode()) {
+ mac_presentation_mode_ = false;
+ ExitFullscreen();
+ }
+}
+
+bool FullscreenControllerTestWindow::InPresentationMode() {
+ return mac_presentation_mode_;
+}
+#endif
+
+// static
+const char* FullscreenControllerTestWindow::GetWindowStateString(
+ WindowState state) {
+ switch (state) {
+ case NORMAL:
+ return "NORMAL";
+ case FULLSCREEN:
+ return "FULLSCREEN";
+ case METRO_SNAP:
+ return "METRO_SNAP";
+ case TO_FULLSCREEN:
+ return "TO_FULLSCREEN";
+ case TO_NORMAL:
+ return "TO_NORMAL";
+ default:
+ NOTREACHED() << "No string for state " << state;
+ return "WindowState-Unknown";
+ }
+}
+
+void FullscreenControllerTestWindow::ChangeWindowFullscreenState() {
+ // Several states result in "no operation" intentionally. The tests
+ // assume that all possible states and event pairs can be tested, even
+ // though window managers will not generate all of these.
+ switch (state_) {
+ case NORMAL:
+ break;
+ case FULLSCREEN:
+ break;
+ case METRO_SNAP:
+ break;
+ case TO_FULLSCREEN:
+ state_ = FULLSCREEN;
+ break;
+ case TO_NORMAL:
+ state_ = NORMAL;
+ break;
+ default:
+ NOTREACHED();
+ }
+ // Emit a change event from every state to ensure the Fullscreen Controller
+ // handles it in all circumstances.
+ browser_->WindowFullscreenStateChanged();
+}
+
+void FullscreenControllerTestWindow::ChangeWindowFullscreenStateIfReentrant() {
+ if (reentrant_)
+ ChangeWindowFullscreenState();
+}
+
+// Unit test fixture testing Fullscreen Controller through its states. ---------
+class FullscreenControllerStateUnitTest : public BrowserWithTestWindowTest,
+ public FullscreenControllerStateTest {
+ public:
+ FullscreenControllerStateUnitTest();
+
+ // FullscreenControllerStateTest:
+ virtual void SetUp() OVERRIDE;
+ virtual void ChangeWindowFullscreenState() OVERRIDE;
+ virtual const char* GetWindowStateString() OVERRIDE;
+ virtual void VerifyWindowState() OVERRIDE;
+
+ protected:
+ // FullscreenControllerStateTest:
+ virtual bool ShouldSkipStateAndEventPair(State state, Event event) OVERRIDE;
+ virtual void TestStateAndEvent(State state,
+ Event event,
+ bool reentrant) OVERRIDE;
+ virtual Browser* GetBrowser() OVERRIDE;
+ FullscreenControllerTestWindow* window_;
+};
+
+FullscreenControllerStateUnitTest::FullscreenControllerStateUnitTest ()
+ : window_(NULL) {
+}
+
+void FullscreenControllerStateUnitTest::SetUp() {
+ window_ = new FullscreenControllerTestWindow();
+ set_window(window_); // BrowserWithTestWindowTest takes ownership.
+ BrowserWithTestWindowTest::SetUp();
+ window_->set_browser(browser());
+}
+
+void FullscreenControllerStateUnitTest::ChangeWindowFullscreenState() {
+ window_->ChangeWindowFullscreenState();
+}
+
+const char* FullscreenControllerStateUnitTest::GetWindowStateString() {
+ return FullscreenControllerTestWindow::GetWindowStateString(window_->state());
+}
+
+void FullscreenControllerStateUnitTest::VerifyWindowState() {
+ switch (state_) {
+ case STATE_NORMAL:
+ EXPECT_EQ(FullscreenControllerTestWindow::NORMAL,
+ window_->state()) << GetAndClearDebugLog();
+ break;
+ case STATE_BROWSER_FULLSCREEN_NO_CHROME:
+ EXPECT_EQ(FullscreenControllerTestWindow::FULLSCREEN,
+ window_->state()) << GetAndClearDebugLog();
+ break;
+#if defined(OS_WIN)
+ case STATE_METRO_SNAP:
+ EXPECT_EQ(FullscreenControllerTestWindow::METRO_SNAP,
+ window_->state()) << GetAndClearDebugLog();
+ break;
+#endif
+ case STATE_TAB_FULLSCREEN:
+ EXPECT_EQ(FullscreenControllerTestWindow::FULLSCREEN,
+ window_->state()) << GetAndClearDebugLog();
+ break;
+ case STATE_TAB_BROWSER_FULLSCREEN:
+ EXPECT_EQ(FullscreenControllerTestWindow::FULLSCREEN,
+ window_->state()) << GetAndClearDebugLog();
+ break;
+ case STATE_TO_NORMAL:
+ EXPECT_EQ(FullscreenControllerTestWindow::TO_NORMAL,
+ window_->state()) << GetAndClearDebugLog();
+ break;
+ case STATE_TO_BROWSER_FULLSCREEN_NO_CHROME:
+ EXPECT_EQ(FullscreenControllerTestWindow::TO_FULLSCREEN,
+ window_->state()) << GetAndClearDebugLog();
+ break;
+ case STATE_TO_TAB_FULLSCREEN:
+ EXPECT_EQ(FullscreenControllerTestWindow::TO_FULLSCREEN,
+ window_->state()) << GetAndClearDebugLog();
+ break;
+ default:
+ NOTREACHED() << GetAndClearDebugLog();
+ }
+
+ FullscreenControllerStateTest::VerifyWindowState();
+}
+
+bool FullscreenControllerStateUnitTest::ShouldSkipStateAndEventPair(
+ State state, Event event) {
+#if defined(OS_MACOSX)
+ // TODO(scheib) Toggle, Window Event, Toggle, Toggle on Mac as exposed by
+ // test *.STATE_TO_NORMAL__TOGGLE_FULLSCREEN runs interactively and exits to
+ // Normal. This doesn't appear to be the desired result, and would add
+ // too much complexity to mimic in our simple FullscreenControllerTestWindow.
+ // http://crbug.com/156968
+ if ((state == STATE_TO_NORMAL ||
+ state == STATE_TO_BROWSER_FULLSCREEN_NO_CHROME ||
+ state == STATE_TO_TAB_FULLSCREEN) &&
+ event == TOGGLE_FULLSCREEN)
+ return true;
+#endif
+
+ return FullscreenControllerStateTest::ShouldSkipStateAndEventPair(state,
+ event);
+}
+
+void FullscreenControllerStateUnitTest::TestStateAndEvent(State state,
+ Event event,
+ bool reentrant) {
+ window_->set_reentrant(reentrant);
+ FullscreenControllerStateTest::TestStateAndEvent(state, event, reentrant);
+}
+
+Browser* FullscreenControllerStateUnitTest::GetBrowser() {
+ return BrowserWithTestWindowTest::browser();
+}
+
+// Tests -----------------------------------------------------------------------
+
+#define TEST_EVENT_INNER(state, event, reentrant, reentrant_id) \
+ TEST_F(FullscreenControllerStateUnitTest, \
+ state##__##event##reentrant_id) { \
+ AddTab(browser(), GURL(chrome::kAboutBlankURL)); \
+ ASSERT_NO_FATAL_FAILURE(TestStateAndEvent(state, event, reentrant)) \
+ << GetAndClearDebugLog(); \
+ }
+ // Progress of tests can be examined by inserting the following line:
+ // LOG(INFO) << GetAndClearDebugLog(); }
+
+#define TEST_EVENT(state, event) \
+ TEST_EVENT_INNER(state, event, false, ); \
+ TEST_EVENT_INNER(state, event, true, _Reentrant);
+
+// Individual tests for each pair of state and event:
+
+TEST_EVENT(STATE_NORMAL, TOGGLE_FULLSCREEN);
+TEST_EVENT(STATE_NORMAL, TAB_FULLSCREEN_TRUE);
+TEST_EVENT(STATE_NORMAL, TAB_FULLSCREEN_FALSE);
+#if defined(OS_WIN)
+TEST_EVENT(STATE_NORMAL, METRO_SNAP_TRUE);
+TEST_EVENT(STATE_NORMAL, METRO_SNAP_FALSE);
+#endif
+TEST_EVENT(STATE_NORMAL, WINDOW_CHANGE);
+
+TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, TOGGLE_FULLSCREEN);
+TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_TRUE);
+TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_FALSE);
+#if defined(OS_WIN)
+TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_TRUE);
+TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_FALSE);
+#endif
+TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, WINDOW_CHANGE);
+
+#if defined(OS_WIN)
+TEST_EVENT(STATE_METRO_SNAP, TOGGLE_FULLSCREEN);
+TEST_EVENT(STATE_METRO_SNAP, TAB_FULLSCREEN_TRUE);
+TEST_EVENT(STATE_METRO_SNAP, TAB_FULLSCREEN_FALSE);
+TEST_EVENT(STATE_METRO_SNAP, METRO_SNAP_TRUE);
+TEST_EVENT(STATE_METRO_SNAP, METRO_SNAP_FALSE);
+TEST_EVENT(STATE_METRO_SNAP, WINDOW_CHANGE);
+#endif
+
+TEST_EVENT(STATE_TAB_FULLSCREEN, TOGGLE_FULLSCREEN);
+TEST_EVENT(STATE_TAB_FULLSCREEN, TAB_FULLSCREEN_TRUE);
+TEST_EVENT(STATE_TAB_FULLSCREEN, TAB_FULLSCREEN_FALSE);
+#if defined(OS_WIN)
+TEST_EVENT(STATE_TAB_FULLSCREEN, METRO_SNAP_TRUE);
+TEST_EVENT(STATE_TAB_FULLSCREEN, METRO_SNAP_FALSE);
+#endif
+TEST_EVENT(STATE_TAB_FULLSCREEN, WINDOW_CHANGE);
+
+TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, TOGGLE_FULLSCREEN);
+TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, TAB_FULLSCREEN_TRUE);
+TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, TAB_FULLSCREEN_FALSE);
+#if defined(OS_WIN)
+TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, METRO_SNAP_TRUE);
+TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, METRO_SNAP_FALSE);
+#endif
+TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, WINDOW_CHANGE);
+
+TEST_EVENT(STATE_TO_NORMAL, TOGGLE_FULLSCREEN);
+TEST_EVENT(STATE_TO_NORMAL, TAB_FULLSCREEN_TRUE);
+TEST_EVENT(STATE_TO_NORMAL, TAB_FULLSCREEN_FALSE);
+#if defined(OS_WIN)
+TEST_EVENT(STATE_TO_NORMAL, METRO_SNAP_TRUE);
+TEST_EVENT(STATE_TO_NORMAL, METRO_SNAP_FALSE);
+#endif
+TEST_EVENT(STATE_TO_NORMAL, WINDOW_CHANGE);
+
+TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, TOGGLE_FULLSCREEN);
+TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_TRUE);
+TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_FALSE);
+#if defined(OS_WIN)
+TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_TRUE);
+TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_FALSE);
+#endif
+TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, WINDOW_CHANGE);
+
+TEST_EVENT(STATE_TO_TAB_FULLSCREEN, TOGGLE_FULLSCREEN);
+TEST_EVENT(STATE_TO_TAB_FULLSCREEN, TAB_FULLSCREEN_TRUE);
+TEST_EVENT(STATE_TO_TAB_FULLSCREEN, TAB_FULLSCREEN_FALSE);
+#if defined(OS_WIN)
+TEST_EVENT(STATE_TO_TAB_FULLSCREEN, METRO_SNAP_TRUE);
+TEST_EVENT(STATE_TO_TAB_FULLSCREEN, METRO_SNAP_FALSE);
+#endif
+TEST_EVENT(STATE_TO_TAB_FULLSCREEN, WINDOW_CHANGE);
+
+// Specific one-off tests for known issues:
+
+// TODO(scheib) Toggling Tab fullscreen while pending Tab or
+// Browser fullscreen is broken currently http://crbug.com/154196
+TEST_F(FullscreenControllerStateUnitTest,
+ DISABLED_ToggleTabWhenPendingBrowser) {
+#if !defined(OS_WIN) // Only possible without reentrancy
+ AddTab(browser(), GURL(chrome::kAboutBlankURL));
+ ASSERT_NO_FATAL_FAILURE(
+ TransitionToState(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME))
+ << GetAndClearDebugLog();
+
+ ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE)) << GetAndClearDebugLog();
+ ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE)) << GetAndClearDebugLog();
+ ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE)) << GetAndClearDebugLog();
+#endif
+}
+
+// TODO(scheib) Toggling Tab fullscreen while pending Tab or
+// Browser fullscreen is broken currently http://crbug.com/154196
+TEST_F(FullscreenControllerStateUnitTest, DISABLED_ToggleTabWhenPendingTab) {
+#if !defined(OS_WIN) // Only possible without reentrancy
+ AddTab(browser(), GURL(chrome::kAboutBlankURL));
+ ASSERT_NO_FATAL_FAILURE(
+ TransitionToState(STATE_TO_TAB_FULLSCREEN))
+ << GetAndClearDebugLog();
+
+ ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE)) << GetAndClearDebugLog();
+ ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE)) << GetAndClearDebugLog();
+ ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE)) << GetAndClearDebugLog();
+#endif
+}
+
+// Soak tests:
+
+// Tests all states with all permutations of multiple events to detect lingering
+// state issues that would bleed over to other states.
+// I.E. for each state test all combinations of events E1, E2, E3.
+//
+// This produces coverage for event sequences that may happen normally but
+// would not be exposed by traversing to each state via TransitionToState().
+// TransitionToState() always takes the same path even when multiple paths
+// exist.
+TEST_F(FullscreenControllerStateUnitTest, TransitionsForEachState) {
+ // A tab is needed for tab fullscreen.
+ AddTab(browser(), GURL(chrome::kAboutBlankURL));
+ TestTransitionsForEachState();
+ // Progress of test can be examined via LOG(INFO) << GetAndClearDebugLog();
+}
+
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller_test.cc b/chrome/browser/ui/fullscreen/fullscreen_controller_test.cc
index da86e2a..7be9a0b 100644
--- a/chrome/browser/ui/fullscreen/fullscreen_controller_test.cc
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller_test.cc
@@ -90,16 +90,6 @@ void FullscreenControllerTest::DenyCurrentFullscreenOrMouseLockRequest() {
browser()->fullscreen_controller()->OnDenyFullscreenPermission(type);
}
-void FullscreenControllerTest::AddTabAtIndexAndWait(int index, const GURL& url,
- content::PageTransition transition) {
- content::TestNavigationObserver observer(
- content::NotificationService::AllSources(), NULL, 1);
-
- AddTabAtIndex(index, url, transition);
-
- observer.Wait();
-}
-
void FullscreenControllerTest::GoBack() {
content::TestNavigationObserver observer(
content::NotificationService::AllSources(), NULL, 1);
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller_test.h b/chrome/browser/ui/fullscreen/fullscreen_controller_test.h
index eee66d9..cdc4730 100644
--- a/chrome/browser/ui/fullscreen/fullscreen_controller_test.h
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller_test.h
@@ -51,8 +51,6 @@ class FullscreenControllerTest : public InProcessBrowserTest {
bool IsFullscreenBubbleDisplayingButtons();
void AcceptCurrentFullscreenOrMouseLockRequest();
void DenyCurrentFullscreenOrMouseLockRequest();
- void AddTabAtIndexAndWait(int index, const GURL& url,
- content::PageTransition transition);
void GoBack();
void Reload();
static const char kFullscreenMouseLockHTML[];
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller_unittest.cc b/chrome/browser/ui/fullscreen/fullscreen_controller_unittest.cc
deleted file mode 100644
index b296122..0000000
--- a/chrome/browser/ui/fullscreen/fullscreen_controller_unittest.cc
+++ /dev/null
@@ -1,969 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <memory.h>
-
-#include <iomanip>
-#include <iostream>
-#include <sstream>
-
-#include "build/build_config.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_tabstrip.h"
-#include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
-#include "chrome/test/base/browser_with_test_window_test.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/url_constants.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-// A BrowserWindow used for testing FullscreenController. ----------------------
-class FullscreenControllerTestWindow : public TestBrowserWindow {
- public:
- // Simulate the window state with an enumeration.
- enum WindowState {
- NORMAL,
- FULLSCREEN,
- // No TO_ state for METRO_SNAP, the windows implementation is synchronous.
- METRO_SNAP,
- TO_NORMAL,
- TO_FULLSCREEN,
- };
-
- FullscreenControllerTestWindow();
- virtual ~FullscreenControllerTestWindow() {}
-
- // BrowserWindow Interface:
- virtual void EnterFullscreen(const GURL& url,
- FullscreenExitBubbleType type) OVERRIDE;
- virtual void EnterFullscreen();
- virtual void ExitFullscreen() OVERRIDE;
- virtual bool IsFullscreen() const OVERRIDE;
-#if defined(OS_WIN)
- virtual void SetMetroSnapMode(bool enable) OVERRIDE;
- virtual bool IsInMetroSnapMode() const OVERRIDE;
-#endif
-#if defined(OS_MACOSX)
- virtual void EnterPresentationMode(
- const GURL& url,
- FullscreenExitBubbleType bubble_type) OVERRIDE;
- virtual void ExitPresentationMode() OVERRIDE;
- virtual bool InPresentationMode() OVERRIDE;
-#endif
-
- static const char* GetWindowStateString(WindowState state);
- WindowState state() const { return state_; }
- void set_browser(Browser* browser) { browser_ = browser; }
- void set_reentrant(bool value) { reentrant_ = value; }
- bool reentrant() const { return reentrant_; }
-
- // Simulates the window changing state.
- void ChangeWindowFullscreenState();
- // Calls ChangeWindowFullscreenState() if |reentrant_| is true.
- void ChangeWindowFullscreenStateIfReentrant();
-
- private:
- WindowState state_;
- bool mac_presentation_mode_;
- Browser* browser_;
-
- // Causes reentrant calls to be made by calling
- // browser_->WindowFullscreenStateChanged() from the BrowserWindow
- // interface methods.
- bool reentrant_;
-};
-
-FullscreenControllerTestWindow::FullscreenControllerTestWindow()
- : state_(NORMAL),
- mac_presentation_mode_(false),
- browser_(NULL),
- reentrant_(false) {
-}
-
-void FullscreenControllerTestWindow::EnterFullscreen(
- const GURL& url, FullscreenExitBubbleType type) {
- EnterFullscreen();
-}
-
-void FullscreenControllerTestWindow::EnterFullscreen() {
- if (!IsFullscreen()) {
- state_ = TO_FULLSCREEN;
- ChangeWindowFullscreenStateIfReentrant();
- }
-}
-
-void FullscreenControllerTestWindow::ExitFullscreen() {
- if (IsFullscreen()) {
- state_ = TO_NORMAL;
- mac_presentation_mode_ = false;
- ChangeWindowFullscreenStateIfReentrant();
- }
-}
-
-bool FullscreenControllerTestWindow::IsFullscreen() const {
- return state_ == FULLSCREEN || state_ == TO_NORMAL;
-}
-
-#if defined(OS_WIN)
-void FullscreenControllerTestWindow::SetMetroSnapMode(bool enable) {
- if (enable != IsInMetroSnapMode()) {
- if (enable)
- state_ = METRO_SNAP;
- else
- state_ = NORMAL;
- }
- ChangeWindowFullscreenStateIfReentrant();
-}
-
-bool FullscreenControllerTestWindow::IsInMetroSnapMode() const {
- return state_ == METRO_SNAP;
-}
-#endif
-
-#if defined(OS_MACOSX)
-void FullscreenControllerTestWindow::EnterPresentationMode(
- const GURL& url,
- FullscreenExitBubbleType bubble_type) {
- mac_presentation_mode_ = true;
- EnterFullscreen();
-}
-
-void FullscreenControllerTestWindow::ExitPresentationMode() {
- if (InPresentationMode()) {
- mac_presentation_mode_ = false;
- ExitFullscreen();
- }
-}
-
-bool FullscreenControllerTestWindow::InPresentationMode() {
- return mac_presentation_mode_;
-}
-#endif
-
-// static
-const char* FullscreenControllerTestWindow::GetWindowStateString(
- WindowState state) {
- switch (state) {
- case NORMAL:
- return "NORMAL";
- case FULLSCREEN:
- return "FULLSCREEN";
- case METRO_SNAP:
- return "METRO_SNAP";
- case TO_FULLSCREEN:
- return "TO_FULLSCREEN";
- case TO_NORMAL:
- return "TO_NORMAL";
- default:
- NOTREACHED() << "No string for state " << state;
- return "WindowState-Unknown";
- }
-}
-
-void FullscreenControllerTestWindow::ChangeWindowFullscreenState() {
- // Several states result in "no operation" intentionally. The tests
- // assume that all possible states and event pairs can be tested, even
- // though window managers will not generate all of these.
- switch (state_) {
- case NORMAL:
- break;
- case FULLSCREEN:
- break;
- case METRO_SNAP:
- break;
- case TO_FULLSCREEN:
- state_ = FULLSCREEN;
- break;
- case TO_NORMAL:
- state_ = NORMAL;
- break;
- default:
- NOTREACHED();
- }
- // Emit a change event from every state to ensure the Fullscreen Controller
- // handles it in all circumstances.
- browser_->WindowFullscreenStateChanged();
-}
-
-void FullscreenControllerTestWindow::ChangeWindowFullscreenStateIfReentrant() {
- if (reentrant_)
- ChangeWindowFullscreenState();
-}
-
-// Unit test fixture for testing Fullscreen Controller. ------------------------
-class FullscreenControllerUnitTest : public BrowserWithTestWindowTest {
- public:
- enum State {
- // The window is not in fullscreen.
- STATE_NORMAL,
- // User-initiated fullscreen. On Mac, this is Lion-mode for 10.7+. On 10.6,
- // this is synonymous with STATE_BROWSER_FULLSCREEN_WITH_CHROME.
- STATE_BROWSER_FULLSCREEN_NO_CHROME,
-#if defined(OS_WIN)
- // Windows 8 Metro Snap mode, which puts the window at 20% screen-width.
- // No TO_ state for Metro, as the windows implementation is only reentrant.
- STATE_METRO_SNAP,
-#endif
- // HTML5 tab-initiated fullscreen.
- STATE_TAB_FULLSCREEN,
- // Both tab and browser fullscreen.
- STATE_TAB_BROWSER_FULLSCREEN,
- // TO_ states are asynchronous states waiting for window state change
- // before transitioning to their named state.
- STATE_TO_NORMAL,
- STATE_TO_BROWSER_FULLSCREEN_NO_CHROME,
- STATE_TO_TAB_FULLSCREEN,
- NUM_STATES,
- STATE_INVALID,
- };
-
- enum Event {
- // FullscreenController::ToggleFullscreenMode()
- TOGGLE_FULLSCREEN,
- // FullscreenController::ToggleFullscreenModeForTab(, true)
- TAB_FULLSCREEN_TRUE,
- // FullscreenController::ToggleFullscreenModeForTab(, false)
- TAB_FULLSCREEN_FALSE,
-#if defined(OS_WIN)
- // FullscreenController::SetMetroSnapMode(true)
- METRO_SNAP_TRUE,
- // FullscreenController::SetMetroSnapMode(flase)
- METRO_SNAP_FALSE,
-#endif
- // FullscreenController::ChangeWindowFullscreenState()
- WINDOW_CHANGE,
- NUM_EVENTS,
- EVENT_INVALID,
- };
-
- static const int MAX_STATE_NAME_LENGTH = 37;
- static const int MAX_EVENT_NAME_LENGTH = 20;
-
- virtual void SetUp() OVERRIDE;
-
- static const char* GetStateString(State state);
- static const char* GetEventString(Event event);
-
- // Causes Fullscreen Controller to transition to an arbitrary state.
- void TransitionToState(State state);
- // Makes one state change to approach |destination_state| via shortest path.
- // Returns true if a state change is made.
- // Repeated calls are needed to reach the destination.
- bool TransitionAStepTowardState(State destination_state);
-
- // Causes the |event| to occur and return true on success.
- bool InvokeEvent(Event event);
-
- // Checks that window state matches the expected controller state.
- void VerifyWindowState();
-
- protected:
- // Generated information about the transitions between states.
- struct StateTransitionInfo {
- StateTransitionInfo()
- : event(EVENT_INVALID),
- state(STATE_INVALID),
- distance(NUM_STATES) {}
- Event event; // The |Event| that will cause the state transition.
- State state; // The adjacent |State| transitioned to; not the final state.
- int distance; // Steps to final state. NUM_STATES represents unknown.
- };
-
- // Returns next transition info for shortest path from source to destination.
- StateTransitionInfo NextTransitionInShortestPath(State source,
- State destination,
- int search_limit);
-
- std::string GetAndClearDebugLog();
-
- // Avoids currently broken cases in the fullscreen controller.
- bool ShouldSkipStateAndEventPair(State state, Event event);
- // Skips reentrant situations and calls ShouldSkipStateAndEventPair.
- bool ShouldSkipTest(State state, Event event, bool reentrant);
-
- // Runs one test of transitioning to a state and invoking an event.
- void TestStateAndEvent(State state, Event event, bool reentrant);
-
- FullscreenControllerTestWindow* window_;
- FullscreenController* fullscreen_controller_;
- State state_;
-
- // Human defined |State| that results given each [state][event] pair.
- State transition_table_[NUM_STATES][NUM_EVENTS];
-
- // Generated information about the transitions between states [from][to].
- StateTransitionInfo state_transitions_[NUM_STATES][NUM_STATES];
-
- // Log of operations reported on errors via GetAndClearDebugLog().
- std::ostringstream debugging_log_;
-};
-
-void FullscreenControllerUnitTest::SetUp() {
- window_ = new FullscreenControllerTestWindow();
- set_window(window_); // BrowserWithTestWindowTest takes ownership.
- BrowserWithTestWindowTest::SetUp();
- window_->set_browser(browser());
- fullscreen_controller_ = browser()->fullscreen_controller();
- state_ = STATE_NORMAL;
-
- // Human specified state machine data.
- // For each state, for each event, define the resulting state.
- State transition_table_data[][NUM_EVENTS] = {
- { // STATE_NORMAL:
- STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, // Event TOGGLE_FULLSCREEN
- STATE_TO_TAB_FULLSCREEN, // Event TAB_FULLSCREEN_TRUE
- STATE_NORMAL, // Event TAB_FULLSCREEN_FALSE
-#if defined(OS_WIN)
- STATE_METRO_SNAP, // Event METRO_SNAP_TRUE
- STATE_NORMAL, // Event METRO_SNAP_FALSE
-#endif
- STATE_NORMAL, // Event WINDOW_CHANGE
- },
- { // STATE_BROWSER_FULLSCREEN_NO_CHROME:
- STATE_TO_NORMAL, // Event TOGGLE_FULLSCREEN
- STATE_TAB_BROWSER_FULLSCREEN, // Event TAB_FULLSCREEN_TRUE
- STATE_BROWSER_FULLSCREEN_NO_CHROME, // Event TAB_FULLSCREEN_FALSE
-#if defined(OS_WIN)
- STATE_METRO_SNAP, // Event METRO_SNAP_TRUE
- STATE_BROWSER_FULLSCREEN_NO_CHROME, // Event METRO_SNAP_FALSE
-#endif
- STATE_BROWSER_FULLSCREEN_NO_CHROME, // Event WINDOW_CHANGE
- },
-#if defined(OS_WIN)
- { // STATE_METRO_SNAP:
- STATE_METRO_SNAP, // Event TOGGLE_FULLSCREEN
- STATE_METRO_SNAP, // Event TAB_FULLSCREEN_TRUE
- STATE_METRO_SNAP, // Event TAB_FULLSCREEN_FALSE
- STATE_METRO_SNAP, // Event METRO_SNAP_TRUE
- STATE_NORMAL, // Event METRO_SNAP_FALSE
- STATE_METRO_SNAP, // Event WINDOW_CHANGE
- },
-#endif
- { // STATE_TAB_FULLSCREEN:
- STATE_TO_NORMAL, // Event TOGGLE_FULLSCREEN
- STATE_TAB_FULLSCREEN, // Event TAB_FULLSCREEN_TRUE
- STATE_TO_NORMAL, // Event TAB_FULLSCREEN_FALSE
-#if defined(OS_WIN)
- STATE_METRO_SNAP, // Event METRO_SNAP_TRUE
- STATE_TAB_FULLSCREEN, // Event METRO_SNAP_FALSE
-#endif
- STATE_TAB_FULLSCREEN, // Event WINDOW_CHANGE
- },
- { // STATE_TAB_BROWSER_FULLSCREEN:
- STATE_TO_NORMAL, // Event TOGGLE_FULLSCREEN
- STATE_TAB_BROWSER_FULLSCREEN, // Event TAB_FULLSCREEN_TRUE
-#if defined(OS_MACOSX)
- // TODO(scheib) Mac exits browser mode too http://crbug.com/155642
- STATE_TO_NORMAL, // Event TAB_FULLSCREEN_FALSE
-#else
- STATE_BROWSER_FULLSCREEN_NO_CHROME, // Event TAB_FULLSCREEN_FALSE
-#endif
-#if defined(OS_WIN)
- STATE_METRO_SNAP, // Event METRO_SNAP_TRUE
- STATE_TAB_BROWSER_FULLSCREEN, // Event METRO_SNAP_FALSE
-#endif
- STATE_TAB_BROWSER_FULLSCREEN, // Event WINDOW_CHANGE
- },
- // STATE_TO_NORMAL:
- { STATE_TO_NORMAL, // Event TOGGLE_FULLSCREEN
- // TODO(scheib) Should be a route back to TAB. http://crbug.com/154196
- STATE_TO_NORMAL, // Event TAB_FULLSCREEN_TRUE
- STATE_TO_NORMAL, // Event TAB_FULLSCREEN_FALSE
-#if defined(OS_WIN)
- STATE_METRO_SNAP, // Event METRO_SNAP_TRUE
- STATE_TO_NORMAL, // Event METRO_SNAP_FALSE
-#endif
- STATE_NORMAL, // Event WINDOW_CHANGE
- },
- // STATE_TO_BROWSER_FULLSCREEN_NO_CHROME:
- { STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, // Event TOGGLE_FULLSCREEN
- // TODO(scheib) Should be a route to TAB_BROWSER http://crbug.com/154196
- STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, // Event TAB_FULLSCREEN_TRUE
- STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, // Event TAB_FULLSCREEN_FALSE
-#if defined(OS_WIN)
- STATE_METRO_SNAP, // Event METRO_SNAP_TRUE
- STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, // Event METRO_SNAP_FALSE
-#endif
- STATE_BROWSER_FULLSCREEN_NO_CHROME, // Event WINDOW_CHANGE
- },
- // STATE_TO_TAB_FULLSCREEN:
- { // TODO(scheib) Should be a route to TAB_BROWSER http://crbug.com/154196
- STATE_TO_TAB_FULLSCREEN, // Event TOGGLE_FULLSCREEN
- STATE_TO_TAB_FULLSCREEN, // Event TAB_FULLSCREEN_TRUE
- // TODO(scheib) Should be a route back to NORMAL. http://crbug.com/154196
- STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, // Event TAB_FULLSCREEN_FALSE
-#if defined(OS_WIN)
- STATE_METRO_SNAP, // Event METRO_SNAP_TRUE
- STATE_TO_TAB_FULLSCREEN, // Event METRO_SNAP_FALSE
-#endif
- STATE_TAB_FULLSCREEN, // Event WINDOW_CHANGE
- },
- };
- ASSERT_EQ(sizeof(transition_table_data), sizeof(transition_table_));
- memcpy(transition_table_, transition_table_data,
- sizeof(transition_table_data));
-
- // Verify that transition_table_ has been completely defined.
- for (int source = 0; source < NUM_STATES; source++) {
- for (int event = 0; event < NUM_EVENTS; event++) {
- ASSERT_NE(STATE_INVALID, transition_table_[source][event]);
- ASSERT_LE(0, transition_table_[source][event]);
- ASSERT_GT(NUM_STATES, transition_table_[source][event]);
- }
- }
-
- // Copy transition_table_ data into state_transitions_ table.
- for (int source = 0; source < NUM_STATES; source++) {
- for (int event = 0; event < NUM_EVENTS; event++) {
- State destination = transition_table_[source][event];
- state_transitions_[source][destination].event = static_cast<Event>(event);
- state_transitions_[source][destination].state = destination;
- state_transitions_[source][destination].distance = 1;
- }
- }
-}
-
-// static
-const char* FullscreenControllerUnitTest::GetStateString(State state) {
- switch (state) {
- case STATE_NORMAL:
- return "STATE_NORMAL";
- case STATE_BROWSER_FULLSCREEN_NO_CHROME:
- return "STATE_BROWSER_FULLSCREEN_NO_CHROME";
-#if defined(OS_WIN)
- case STATE_METRO_SNAP:
- return "STATE_METRO_SNAP";
-#endif
- case STATE_TAB_FULLSCREEN:
- return "STATE_TAB_FULLSCREEN";
- case STATE_TAB_BROWSER_FULLSCREEN:
- return "STATE_TAB_BROWSER_FULLSCREEN";
- case STATE_TO_NORMAL:
- return "STATE_TO_NORMAL";
- case STATE_TO_BROWSER_FULLSCREEN_NO_CHROME:
- return "STATE_TO_BROWSER_FULLSCREEN_NO_CHROME";
- case STATE_TO_TAB_FULLSCREEN:
- return "STATE_TO_TAB_FULLSCREEN";
- case STATE_INVALID:
- return "STATE_INVALID";
- default:
- NOTREACHED() << "No string for state " << state;
- return "State-Unknown";
- }
-}
-
-// static
-const char* FullscreenControllerUnitTest::GetEventString(Event event) {
- switch (event) {
- case TOGGLE_FULLSCREEN:
- return "TOGGLE_FULLSCREEN";
- case TAB_FULLSCREEN_TRUE:
- return "TAB_FULLSCREEN_TRUE";
- case TAB_FULLSCREEN_FALSE:
- return "TAB_FULLSCREEN_FALSE";
-#if defined(OS_WIN)
- case METRO_SNAP_TRUE:
- return "METRO_SNAP_TRUE";
- case METRO_SNAP_FALSE:
- return "METRO_SNAP_FALSE";
-#endif
- case WINDOW_CHANGE:
- return "WINDOW_CHANGE";
- case EVENT_INVALID:
- return "EVENT_INVALID";
- default:
- NOTREACHED() << "No string for event " << event;
- return "Event-Unknown";
- }
-}
-
-void FullscreenControllerUnitTest::TransitionToState(State final_state) {
- int max_steps = NUM_STATES;
- while (max_steps-- && TransitionAStepTowardState(final_state))
- continue;
- ASSERT_GE(max_steps, 0) << "TransitionToState was unable to achieve desired "
- << "target state. TransitionAStepTowardState iterated too many times."
- << GetAndClearDebugLog();
- ASSERT_EQ(final_state, state_) << "TransitionToState was unable to achieve "
- << "desired target state. TransitionAStepTowardState returned false."
- << GetAndClearDebugLog();
-}
-
-bool FullscreenControllerUnitTest::TransitionAStepTowardState(
- State destination_state) {
- State source_state = state_;
- if (source_state == destination_state)
- return false;
-
- StateTransitionInfo next = NextTransitionInShortestPath(source_state,
- destination_state,
- NUM_STATES);
- if (next.state == STATE_INVALID) {
- NOTREACHED() << "TransitionAStepTowardState unable to transition. "
- << "NextTransitionInShortestPath("
- << GetStateString(source_state) << ", "
- << GetStateString(destination_state) << ") returned STATE_INVALID."
- << GetAndClearDebugLog();
- return false;
- }
-
- return InvokeEvent(next.event);
-}
-
-bool FullscreenControllerUnitTest::InvokeEvent(Event event) {
- State source_state = state_;
- State next_state = transition_table_[source_state][event];
-
- // When simulating reentrant window change calls, expect the next state
- // automatically.
- if (window_->reentrant())
- next_state = transition_table_[next_state][WINDOW_CHANGE];
-
- debugging_log_ << " InvokeEvent(" << std::left
- << std::setw(MAX_EVENT_NAME_LENGTH) << GetEventString(event)
- << ") to "
- << std::setw(MAX_STATE_NAME_LENGTH) << GetStateString(next_state)
- << " ";
-
- state_ = next_state;
-
- switch (event) {
- case TOGGLE_FULLSCREEN:
- fullscreen_controller_->ToggleFullscreenMode();
- break;
- case TAB_FULLSCREEN_TRUE:
- fullscreen_controller_->ToggleFullscreenModeForTab(
- chrome::GetActiveWebContents(browser()), true);
- break;
- case TAB_FULLSCREEN_FALSE:
- fullscreen_controller_->ToggleFullscreenModeForTab(
- chrome::GetActiveWebContents(browser()), false);
- break;
-#if defined(OS_WIN)
- case METRO_SNAP_TRUE:
- fullscreen_controller_->SetMetroSnapMode(true);
- break;
- case METRO_SNAP_FALSE:
- fullscreen_controller_->SetMetroSnapMode(false);
- break;
-#endif
- case WINDOW_CHANGE:
- window_->ChangeWindowFullscreenState();
- break;
- default:
- NOTREACHED() << "InvokeEvent needs a handler for event "
- << GetEventString(event) << GetAndClearDebugLog();
- return false;
- }
-
- debugging_log_ << "Window state now "
- << FullscreenControllerTestWindow::GetWindowStateString(window_->state())
- << std::endl;
-
- VerifyWindowState();
-
- return true;
-}
-
-void FullscreenControllerUnitTest::VerifyWindowState() {
- switch (state_) {
- case STATE_NORMAL:
- EXPECT_EQ(FullscreenControllerTestWindow::NORMAL,
- window_->state()) << GetAndClearDebugLog();
-#if defined(OS_MACOSX)
- EXPECT_FALSE(window_->InPresentationMode())
- << GetAndClearDebugLog();
-#endif
- EXPECT_FALSE(fullscreen_controller_->IsFullscreenForBrowser())
- << GetAndClearDebugLog();
- EXPECT_FALSE(fullscreen_controller_->IsFullscreenForTabOrPending())
- << GetAndClearDebugLog();
- EXPECT_FALSE(fullscreen_controller_->IsInMetroSnapMode())
- << GetAndClearDebugLog();
- break;
- case STATE_BROWSER_FULLSCREEN_NO_CHROME:
- EXPECT_EQ(FullscreenControllerTestWindow::FULLSCREEN,
- window_->state()) << GetAndClearDebugLog();
-#if defined(OS_MACOSX)
- EXPECT_FALSE(window_->InPresentationMode())
- << GetAndClearDebugLog();
-#endif
- EXPECT_TRUE(fullscreen_controller_->IsFullscreenForBrowser())
- << GetAndClearDebugLog();
- EXPECT_FALSE(fullscreen_controller_->IsFullscreenForTabOrPending())
- << GetAndClearDebugLog();
- EXPECT_FALSE(fullscreen_controller_->IsInMetroSnapMode())
- << GetAndClearDebugLog();
- break;
-#if defined(OS_WIN)
- case STATE_METRO_SNAP:
- EXPECT_EQ(FullscreenControllerTestWindow::METRO_SNAP,
- window_->state()) << GetAndClearDebugLog();
- // No expectation for InPresentationMode.
- EXPECT_FALSE(fullscreen_controller_->IsFullscreenForBrowser())
- << GetAndClearDebugLog();
- EXPECT_FALSE(fullscreen_controller_->IsFullscreenForTabOrPending())
- << GetAndClearDebugLog();
- EXPECT_TRUE(fullscreen_controller_->IsInMetroSnapMode())
- << GetAndClearDebugLog();
- break;
-#endif
- case STATE_TAB_FULLSCREEN:
- EXPECT_EQ(FullscreenControllerTestWindow::FULLSCREEN,
- window_->state()) << GetAndClearDebugLog();
-#if defined(OS_MACOSX)
- EXPECT_TRUE(window_->InPresentationMode())
- << GetAndClearDebugLog();
-#endif
- EXPECT_FALSE(fullscreen_controller_->IsFullscreenForBrowser())
- << GetAndClearDebugLog();
- EXPECT_TRUE(fullscreen_controller_->IsFullscreenForTabOrPending())
- << GetAndClearDebugLog();
- EXPECT_FALSE(fullscreen_controller_->IsInMetroSnapMode())
- << GetAndClearDebugLog();
- break;
- case STATE_TAB_BROWSER_FULLSCREEN:
- EXPECT_EQ(FullscreenControllerTestWindow::FULLSCREEN,
- window_->state()) << GetAndClearDebugLog();
-#if defined(OS_MACOSX)
- EXPECT_TRUE(window_->InPresentationMode())
- << GetAndClearDebugLog();
-#endif
-#if defined(OS_MACOSX)
- // TODO(scheib) Mac is reporting incorrect IsFullscreenForBrowser().
- // e.g. in FullscreenControllerUnitTest.
- // STATE_BROWSER_FULLSCREEN_NO_CHROME_TAB_FULLSCREEN_TRUE
- // At the end of ToggleFullscreenModeForTab
- // tab_caused_fullscreen_ has incorrectly been set to true even
- // though controller was already in browser fullscreen.
- // http://crbug.com/155650
- EXPECT_FALSE(fullscreen_controller_->IsFullscreenForBrowser())
- << GetAndClearDebugLog();
-#else
- EXPECT_TRUE(fullscreen_controller_->IsFullscreenForBrowser())
- << GetAndClearDebugLog();
-#endif
- EXPECT_TRUE(fullscreen_controller_->IsFullscreenForTabOrPending())
- << GetAndClearDebugLog();
- EXPECT_FALSE(fullscreen_controller_->IsInMetroSnapMode())
- << GetAndClearDebugLog();
- break;
- case STATE_TO_NORMAL:
- EXPECT_EQ(FullscreenControllerTestWindow::TO_NORMAL,
- window_->state()) << GetAndClearDebugLog();
-#if defined(OS_MACOSX)
- EXPECT_FALSE(window_->InPresentationMode())
- << GetAndClearDebugLog();
-#endif
- // No expectation for IsFullscreenForBrowser.
- // No expectation for IsFullscreenForTabOrPending.
- EXPECT_FALSE(fullscreen_controller_->IsInMetroSnapMode())
- << GetAndClearDebugLog();
- break;
- case STATE_TO_BROWSER_FULLSCREEN_NO_CHROME:
- EXPECT_EQ(FullscreenControllerTestWindow::TO_FULLSCREEN,
- window_->state()) << GetAndClearDebugLog();
-#if defined(OS_MACOSX)
- EXPECT_FALSE(window_->InPresentationMode())
- << GetAndClearDebugLog();
-#endif
- EXPECT_FALSE(fullscreen_controller_->IsFullscreenForBrowser())
- << GetAndClearDebugLog();
- // No expectation for IsFullscreenForTabOrPending.
- EXPECT_FALSE(fullscreen_controller_->IsInMetroSnapMode())
- << GetAndClearDebugLog();
- break;
- case STATE_TO_TAB_FULLSCREEN:
- EXPECT_EQ(FullscreenControllerTestWindow::TO_FULLSCREEN,
- window_->state()) << GetAndClearDebugLog();
-#if defined(OS_MACOSX)
- EXPECT_TRUE(window_->InPresentationMode())
- << GetAndClearDebugLog();
-#endif
- EXPECT_FALSE(fullscreen_controller_->IsFullscreenForBrowser())
- << GetAndClearDebugLog();
- EXPECT_TRUE(fullscreen_controller_->IsFullscreenForTabOrPending())
- << GetAndClearDebugLog();
- EXPECT_FALSE(fullscreen_controller_->IsInMetroSnapMode())
- << GetAndClearDebugLog();
- break;
- default:
- NOTREACHED() << GetAndClearDebugLog();
- }
-}
-
-FullscreenControllerUnitTest::StateTransitionInfo
- FullscreenControllerUnitTest::NextTransitionInShortestPath(
- State source, State destination, int search_limit) {
- if (search_limit == 0)
- return StateTransitionInfo(); // Return a default (invalid) state.
-
- if (state_transitions_[source][destination].state == STATE_INVALID) {
- // Don't know the next state yet, do a depth first search.
- StateTransitionInfo result;
-
- // Consider all states reachable via each event from the source state.
- for (int event_int = 0; event_int < NUM_EVENTS; event_int++) {
- Event event = static_cast<Event>(event_int);
- State next_state_candidate = transition_table_[source][event];
-
- if (ShouldSkipStateAndEventPair(source, event))
- continue;
-
- // Recurse.
- StateTransitionInfo candidate = NextTransitionInShortestPath(
- next_state_candidate, destination, search_limit - 1);
-
- if (candidate.distance + 1 < result.distance) {
- result.event = event;
- result.state = next_state_candidate;
- result.distance = candidate.distance + 1;
- }
- }
-
- // Cache result so that a search is not required next time.
- state_transitions_[source][destination] = result;
- }
-
- return state_transitions_[source][destination];
-}
-
-std::string FullscreenControllerUnitTest::GetAndClearDebugLog() {
- debugging_log_ << "(end of log)\n";
- std::string output_log = "\nDebugging Log:\n" + debugging_log_.str();
- debugging_log_.str("");
- return output_log;
-}
-
-bool FullscreenControllerUnitTest::ShouldSkipStateAndEventPair(State state,
- Event event) {
- // TODO(scheib) Toggling Tab fullscreen while pending Tab or
- // Browser fullscreen is broken currently http://crbug.com/154196
- if ((state == STATE_TO_BROWSER_FULLSCREEN_NO_CHROME ||
- state == STATE_TO_TAB_FULLSCREEN) &&
- (event == TAB_FULLSCREEN_TRUE || event == TAB_FULLSCREEN_FALSE))
- return true;
- if (state == STATE_TO_NORMAL && event == TAB_FULLSCREEN_TRUE)
- return true;
-
- return false;
-}
-
-bool FullscreenControllerUnitTest::ShouldSkipTest(State state,
- Event event,
- bool reentrant) {
-#if defined(OS_WIN)
- // FullscreenController verifies that WindowFullscreenStateChanged is
- // always reentrant on Windows. It will fail if we mock asynchronous calls.
- if (!reentrant) {
- debugging_log_ << "\nSkipping non-reentrant test on Windows.\n";
- return true;
- }
-#endif
-
- // When testing reentrancy there are states the fullscreen controller
- // will be unable to remain in, as they will progress due to the
- // reentrant window change call. Skip states that will be instantly
- // exited by the reentrant call.
- if (reentrant && (transition_table_[state][WINDOW_CHANGE] != state)) {
- debugging_log_ << "\nSkipping reentrant test for transitory source state "
- << GetStateString(state) << ".\n";
- return true;
- }
-
- return ShouldSkipStateAndEventPair(state, event);
-}
-
-void FullscreenControllerUnitTest::TestStateAndEvent(State state,
- Event event,
- bool reentrant) {
- if (ShouldSkipTest(state, event, reentrant))
- return;
-
- debugging_log_ << "\nTest transition from state "
- << GetStateString(state)
- << (reentrant ? " with reentrant calls.\n" : ".\n");
- window_->set_reentrant(reentrant);
-
- debugging_log_ << " First, from "
- << GetStateString(state_) << "\n";
- ASSERT_NO_FATAL_FAILURE(TransitionToState(state))
- << GetAndClearDebugLog();
-
- debugging_log_ << " Then,\n";
- ASSERT_TRUE(InvokeEvent(event)) << GetAndClearDebugLog();
-}
-
-
-// Tests -----------------------------------------------------------------------
-
-#define TEST_EVENT_INNER(state, event, reentrant, reentrant_id) \
- TEST_F(FullscreenControllerUnitTest, state##_##event##reentrant_id) { \
- AddTab(browser(), GURL(chrome::kAboutBlankURL)); \
- ASSERT_NO_FATAL_FAILURE(TestStateAndEvent(state, event, reentrant)) \
- << GetAndClearDebugLog(); \
- }
- // Progress of tests can be examined by inserting the following line:
- // LOG(INFO) << GetAndClearDebugLog(); }
-
-#define TEST_EVENT(state, event) \
- TEST_EVENT_INNER(state, event, false, ); \
- TEST_EVENT_INNER(state, event, true, _Reentrant);
-
-// Individual tests for each pair of state and event:
-
-TEST_EVENT(STATE_NORMAL, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_NORMAL, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_NORMAL, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_NORMAL, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_NORMAL, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_NORMAL, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_BROWSER_FULLSCREEN_NO_CHROME, WINDOW_CHANGE);
-
-#if defined(OS_WIN)
-TEST_EVENT(STATE_METRO_SNAP, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_METRO_SNAP, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_METRO_SNAP, TAB_FULLSCREEN_FALSE);
-TEST_EVENT(STATE_METRO_SNAP, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_METRO_SNAP, METRO_SNAP_FALSE);
-TEST_EVENT(STATE_METRO_SNAP, WINDOW_CHANGE);
-#endif
-
-TEST_EVENT(STATE_TAB_FULLSCREEN, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_TAB_FULLSCREEN, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_TAB_FULLSCREEN, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_TAB_FULLSCREEN, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_TAB_FULLSCREEN, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_TAB_FULLSCREEN, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_TAB_BROWSER_FULLSCREEN, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_TO_NORMAL, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_TO_NORMAL, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_TO_NORMAL, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_TO_NORMAL, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_TO_NORMAL, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_TO_NORMAL, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, WINDOW_CHANGE);
-
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, TOGGLE_FULLSCREEN);
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, TAB_FULLSCREEN_TRUE);
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, TAB_FULLSCREEN_FALSE);
-#if defined(OS_WIN)
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, METRO_SNAP_TRUE);
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, METRO_SNAP_FALSE);
-#endif
-TEST_EVENT(STATE_TO_TAB_FULLSCREEN, WINDOW_CHANGE);
-
-// Specific one-off tests for known issues:
-
-// TODO(scheib) Toggling Tab fullscreen while pending Tab or
-// Browser fullscreen is broken currently http://crbug.com/154196
-TEST_F(FullscreenControllerUnitTest, DISABLED_ToggleTabWhenPendingBrowser) {
-#if !defined(OS_WIN) // Only possible without reentrancy
- AddTab(browser(), GURL(chrome::kAboutBlankURL));
- ASSERT_NO_FATAL_FAILURE(
- TransitionToState(STATE_TO_BROWSER_FULLSCREEN_NO_CHROME))
- << GetAndClearDebugLog();
-
- ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE)) << GetAndClearDebugLog();
- ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE)) << GetAndClearDebugLog();
- ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE)) << GetAndClearDebugLog();
-#endif
-}
-
-// TODO(scheib) Toggling Tab fullscreen while pending Tab or
-// Browser fullscreen is broken currently http://crbug.com/154196
-TEST_F(FullscreenControllerUnitTest, DISABLED_ToggleTabWhenPendingTab) {
-#if !defined(OS_WIN) // Only possible without reentrancy
- AddTab(browser(), GURL(chrome::kAboutBlankURL));
- ASSERT_NO_FATAL_FAILURE(
- TransitionToState(STATE_TO_TAB_FULLSCREEN))
- << GetAndClearDebugLog();
-
- ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_TRUE)) << GetAndClearDebugLog();
- ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE)) << GetAndClearDebugLog();
- ASSERT_TRUE(InvokeEvent(WINDOW_CHANGE)) << GetAndClearDebugLog();
-#endif
-}
-
-// Soak tests:
-
-// Tests all states with all permutations of multiple events to detect lingering
-// state issues that would bleed over to other states.
-// I.E. for each state test all combinations of events E1, E2, E3.
-//
-// This produces coverage for event sequences that may happen normally but
-// would not be exposed by traversing to each state via TransitionToState().
-// TransitionToState() always takes the same path even when multiple paths
-// exist.
-TEST_F(FullscreenControllerUnitTest, TransitionsForEachState) {
- // A tab is needed for tab fullscreen.
- AddTab(browser(), GURL(chrome::kAboutBlankURL));
- for (int reentrant = 0; reentrant <= 1; reentrant++) {
- for (int source_int = 0; source_int < NUM_STATES; source_int++) {
- for (int event1_int = 0; event1_int < NUM_EVENTS; event1_int++) {
- State state = static_cast<State>(source_int);
- Event event1 = static_cast<Event>(event1_int);
-
- // Early out if skipping all tests for this state, reduces log noise.
- if (ShouldSkipTest(state, event1, !!reentrant))
- continue;
-
- for (int event2_int = 0; event2_int < NUM_EVENTS; event2_int++) {
- for (int event3_int = 0; event3_int < NUM_EVENTS; event3_int++) {
- Event event2 = static_cast<Event>(event2_int);
- Event event3 = static_cast<Event>(event3_int);
-
- // Test each state and each event.
- ASSERT_NO_FATAL_FAILURE(TestStateAndEvent(state,
- event1,
- !!reentrant))
- << GetAndClearDebugLog();
-
- // Then, add an additional event to the sequence.
- if (ShouldSkipStateAndEventPair(state_, event2))
- continue;
- ASSERT_TRUE(InvokeEvent(event2)) << GetAndClearDebugLog();
-
- // Then, add an additional event to the sequence.
- if (ShouldSkipStateAndEventPair(state_, event3))
- continue;
- ASSERT_TRUE(InvokeEvent(event3)) << GetAndClearDebugLog();
- }
- }
- }
- }
- }
- // Progress of test can be examined via LOG(INFO) << GetAndClearDebugLog();
-}
-
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 8d62ac5..b633f33 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -185,6 +185,8 @@
'browser/ui/cocoa/run_loop_testing.mm',
'browser/ui/cocoa/test/ui_test_utils_mac.mm',
'browser/ui/find_bar/find_bar_host_unittest_util.h',
+ 'browser/ui/fullscreen/fullscreen_controller_state_test.cc',
+ 'browser/ui/fullscreen/fullscreen_controller_state_test.h',
'browser/ui/fullscreen/fullscreen_controller_test.cc',
'browser/ui/fullscreen/fullscreen_controller_test.h',
'browser/ui/gtk/find_bar_host_unittest_util_gtk.cc',
@@ -511,6 +513,7 @@
'browser/task_manager/task_manager_browsertest_util.cc',
'browser/ui/browser_focus_uitest.cc',
'browser/ui/fullscreen/fullscreen_controller_interactive_browsertest.cc',
+ 'browser/ui/fullscreen/fullscreen_controller_state_interactive_browsertest.cc',
'browser/ui/gtk/bookmarks/bookmark_bar_gtk_interactive_uitest.cc',
'browser/ui/omnibox/action_box_browsertest.cc',
'browser/ui/omnibox/omnibox_view_browsertest.cc',
@@ -1982,7 +1985,7 @@
'browser/ui/content_settings/content_setting_bubble_model_unittest.cc',
'browser/ui/content_settings/content_setting_image_model_unittest.cc',
'browser/ui/find_bar/find_backend_unittest.cc',
- 'browser/ui/fullscreen/fullscreen_controller_unittest.cc',
+ 'browser/ui/fullscreen/fullscreen_controller_state_unittest.cc',
'browser/ui/global_error/global_error_service_unittest.cc',
'browser/ui/gtk/accelerators_gtk_unittest.cc',
'browser/ui/gtk/bookmarks/bookmark_bar_gtk_unittest.cc',
@@ -2680,6 +2683,7 @@
'browser/ui/bookmarks/bookmark_context_menu_controller_unittest.cc',
'browser/ui/bookmarks/bookmark_prompt_controller_unittest.cc',
'browser/ui/browser_command_controller_unittest.cc',
+ 'browser/ui/fullscreen/fullscreen_controller_state_unittest.cc',
'browser/ui/fullscreen/fullscreen_controller_unittest.cc',
'browser/ui/search/search_delegate_unittest.cc',
'browser/ui/tab_contents/tab_contents_iterator_unittest.cc',
diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc
index 6b842dd..e135331 100644
--- a/chrome/test/base/in_process_browser_test.cc
+++ b/chrome/test/base/in_process_browser_test.cc
@@ -39,6 +39,7 @@
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_browser_thread.h"
#include "content/public/test/test_launcher.h"
+#include "content/public/test/test_navigation_observer.h"
#include "net/base/mock_host_resolver.h"
#include "net/test/test_server.h"
#include "ui/compositor/compositor_switches.h"
@@ -212,10 +213,15 @@ void InProcessBrowserTest::AddTabAtIndexToBrowser(
int index,
const GURL& url,
content::PageTransition transition) {
+ content::TestNavigationObserver observer(
+ content::NotificationService::AllSources(), NULL, 1);
+
chrome::NavigateParams params(browser, url, transition);
params.tabstrip_index = index;
params.disposition = NEW_FOREGROUND_TAB;
chrome::Navigate(&params);
+
+ observer.Wait();
}
void InProcessBrowserTest::AddTabAtIndex(