Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7879)

Unified Diff: chrome/browser/ui/fullscreen/flash_fullscreen_interactive_browsertest.cc

Issue 670653005: Fix Flash fullscreen focus regressions, and add interactive_ui_tests. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove consts in ObjC code. Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | chrome/chrome_tests.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/ui/fullscreen/flash_fullscreen_interactive_browsertest.cc
diff --git a/chrome/browser/ui/fullscreen/flash_fullscreen_interactive_browsertest.cc b/chrome/browser/ui/fullscreen/flash_fullscreen_interactive_browsertest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..db7f86ba592d785216b3479275777c22446bf6fd
--- /dev/null
+++ b/chrome/browser/ui/fullscreen/flash_fullscreen_interactive_browsertest.cc
@@ -0,0 +1,348 @@
+// Copyright 2014 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 "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/macros.h"
+#include "base/message_loop/message_loop.h"
+#include "base/time/time.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/test/base/interactive_test_utils.h"
+#include "chrome/test/ppapi/ppapi_test.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/test_utils.h"
+#include "third_party/skia/include/core/SkColor.h"
+
+namespace {
+
+#if defined(OS_MACOSX)
+const bool kIsMacUI = true;
+#else
+const bool kIsMacUI = false;
+#endif
+
+// Runs the current MessageLoop until |condition| is true or timeout.
+bool RunLoopUntil(const base::Callback<bool()>& condition) {
+ const base::TimeTicks start_time = base::TimeTicks::Now();
+ while (!condition.Run()) {
+ const base::TimeTicks current_time = base::TimeTicks::Now();
+ if (current_time - start_time > base::TimeDelta::FromSeconds(10)) {
+ ADD_FAILURE() << "Condition not met within ten seconds.";
+ return false;
+ }
+
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::MessageLoop::QuitClosure(),
+ base::TimeDelta::FromMilliseconds(20));
+ content::RunMessageLoop();
+ }
+ return true;
+}
+
+} // namespace
+
+// A BrowserTest that opens a test page that launches a simulated fullscreen
+// Flash plugin. The plugin responds to mouse clicks and key presses by
+// changing color. Once launched, the browser UI can be tested to confirm the
+// desired interactive behaviors.
+class FlashFullscreenInteractiveBrowserTest : public OutOfProcessPPAPITest {
+ public:
+ FlashFullscreenInteractiveBrowserTest() {}
+ virtual ~FlashFullscreenInteractiveBrowserTest() {}
+
+ protected:
+ content::WebContents* GetActiveWebContents() const {
+ return browser()->tab_strip_model()->GetActiveWebContents();
+ }
+
+ // A simple way to convince libcontent and the browser UI that a tab is being
+ // screen captured. During tab capture, Flash fullscreen remains embedded
+ // within the tab content area of a non-fullscreened browser window.
+ void StartFakingTabCapture() {
+ GetActiveWebContents()->IncrementCapturerCount(gfx::Size(360, 240));
+ }
+
+ bool LaunchFlashFullscreen() {
+ // This navigates to a page that runs the simulated fullscreen Flash
+ // plugin. It will block until the plugin has completed an attempt to enter
+ // Flash fullscreen mode.
+ OutOfProcessPPAPITest::RunTest("FlashFullscreenForBrowserUI");
+
+ if (::testing::Test::HasFailure()) {
+ ADD_FAILURE() << ("Failed to launch simulated fullscreen Flash plugin. "
+ "Interactive UI testing cannot proceed.");
+ return false;
+ }
+
+ EXPECT_TRUE(ObserveTabIsInFullscreen(true));
+
+ return !::testing::Test::HasFailure();
+ }
+
+ void UseAcceleratorToOpenNewTab() {
+ content::WebContents* const old_tab_contents = GetActiveWebContents();
+ EXPECT_TRUE(ui_test_utils::SendKeyPressSync(
+ browser(), ui::VKEY_T, !kIsMacUI, false, false, kIsMacUI));
+ EXPECT_TRUE(RunLoopUntil(base::Bind(
+ &FlashFullscreenInteractiveBrowserTest::IsObservingActiveWebContents,
+ base::Unretained(this),
+ old_tab_contents,
+ false)));
+ }
+
+ void UseAcceleratorToSwitchToTab(int tab_index) {
+ content::WebContents* const old_tab_contents = GetActiveWebContents();
+ const ui::KeyboardCode key_code =
+ static_cast<ui::KeyboardCode>(ui::VKEY_1 + tab_index);
+ EXPECT_TRUE(ui_test_utils::SendKeyPressSync(
+ browser(), key_code, !kIsMacUI, false, false, kIsMacUI));
+ EXPECT_TRUE(RunLoopUntil(base::Bind(
+ &FlashFullscreenInteractiveBrowserTest::IsObservingActiveWebContents,
+ base::Unretained(this),
+ old_tab_contents,
+ false)));
+ }
+
+ void PressEscape() {
+ EXPECT_TRUE(ui_test_utils::SendKeyPressSync(
+ browser(), ui::VKEY_ESCAPE, false, false, false, false));
+ }
+
+ void PressSpacebar() {
+ EXPECT_TRUE(ui_test_utils::SendKeyPressSync(
+ browser(), ui::VKEY_SPACE, false, false, false, false));
+ }
+
+ void SpamSpacebar() {
+ for (int i = 0; i < 11; ++i)
+ PressSpacebar();
+ }
+
+ void ClickOnTabContainer() {
+ ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER);
+ }
+
+ void ClickOnOmnibox() {
+ ui_test_utils::ClickOnView(browser(), VIEW_ID_OMNIBOX);
+ }
+
+ bool ObserveTabIsInFullscreen(bool expected_in_fullscreen) const {
+ if (!RunLoopUntil(base::Bind(
+ &FlashFullscreenInteractiveBrowserTest::IsObservingTabInFullscreen,
+ base::Unretained(this),
+ GetActiveWebContents(),
+ expected_in_fullscreen)))
+ return false;
+
+ if (expected_in_fullscreen) {
+ if (!GetActiveWebContents()->GetFullscreenRenderWidgetHostView()) {
+ ADD_FAILURE()
+ << "WebContents should have a fullscreen RenderWidgetHostView.";
+ return false;
+ }
+ EXPECT_EQ(GetActiveWebContents()->GetCapturerCount() > 0,
+ !browser()->fullscreen_controller()->
+ IsWindowFullscreenForTabOrPending());
+ }
+
+ return true;
+ }
+
+ bool ObserveFlashHasFocus(content::WebContents* contents,
+ bool expected_to_have_focus) const {
+ if (!RunLoopUntil(base::Bind(
+ &FlashFullscreenInteractiveBrowserTest::IsObservingFlashHasFocus,
+ base::Unretained(this),
+ contents,
+ expected_to_have_focus)))
+ return false;
+
+ if (expected_to_have_focus) {
+ content::RenderWidgetHostView* const web_page_view =
+ contents->GetRenderWidgetHostView();
+ EXPECT_FALSE(web_page_view && web_page_view->HasFocus())
+ << "Both RenderWidgetHostViews cannot have focus at the same time.";
+
+ if (contents == GetActiveWebContents())
+ EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(),
+ VIEW_ID_TAB_CONTAINER));
+ }
+
+ return true;
+ }
+
+ bool ObserveFlashFillColor(SkColor expected_color) const {
+ return RunLoopUntil(base::Bind(
+ &FlashFullscreenInteractiveBrowserTest::IsObservingFlashFillColor,
+ base::Unretained(this),
+ expected_color));
+ }
+
+ private:
+ bool IsObservingTabInFullscreen(content::WebContents* contents,
+ bool expected_in_fullscreen) const {
+ return expected_in_fullscreen == browser()->fullscreen_controller()->
+ IsFullscreenForTabOrPending(contents);
+ }
+
+ bool IsObservingFlashHasFocus(content::WebContents* contents,
+ bool expected_to_have_focus) const {
+ content::RenderWidgetHostView* const flash_fs_view =
+ contents->GetFullscreenRenderWidgetHostView();
+ const bool flash_has_focus = flash_fs_view && flash_fs_view->HasFocus();
+ return flash_has_focus == expected_to_have_focus;
+ }
+
+ bool IsObservingActiveWebContents(content::WebContents* contents,
+ bool expected_active_contents) const {
+ return (contents == GetActiveWebContents()) == expected_active_contents;
+ }
+
+ bool IsObservingFlashFillColor(SkColor expected_color) const {
+ content::RenderWidgetHostView* const flash_fs_view =
+ GetActiveWebContents()->GetFullscreenRenderWidgetHostView();
+ content::RenderWidgetHost* const flash_fs_host =
+ flash_fs_view ? flash_fs_view->GetRenderWidgetHost() : nullptr;
+ if (!flash_fs_host) {
+ ADD_FAILURE() << "Flash fullscreen RenderWidgetHost is gone.";
+ return false;
+ }
+
+ // When a widget is first shown, it can take some time before it is ready
+ // for copying from its backing store. This is a transient condition, and
+ // so it is not being treated as a test failure.
+ if (!flash_fs_host->CanCopyFromBackingStore())
+ return false;
+
+ // Copy and examine the upper-left pixel of the widget and compare it to the
+ // |expected_color|.
+ bool is_expected_color = false;
+ flash_fs_host->CopyFromBackingStore(
+ gfx::Rect(0, 0, 1, 1),
+ gfx::Size(1, 1),
+ base::Bind(
+ &FlashFullscreenInteractiveBrowserTest::CheckBitmapForFillColor,
+ expected_color,
+ &is_expected_color,
+ base::MessageLoop::QuitClosure()),
+ kN32_SkColorType);
+ content::RunMessageLoop();
+
+ return is_expected_color;
+ }
+
+ static void CheckBitmapForFillColor(SkColor expected_color,
+ bool* is_expected_color,
+ const base::Closure& done_cb,
+ bool success,
+ const SkBitmap& bitmap) {
+ if (success) {
+ SkAutoLockPixels lock_pixels(bitmap);
+ if (bitmap.width() > 0 && bitmap.height() > 0)
+ *is_expected_color = (bitmap.getColor(0, 0) == expected_color);
+ }
+ done_cb.Run();
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(FlashFullscreenInteractiveBrowserTest);
+};
+
+// Tests that launching and exiting fullscreen-within-tab works.
+IN_PROC_BROWSER_TEST_F(FlashFullscreenInteractiveBrowserTest,
+ FullscreenWithinTab_EscapeKeyExitsFullscreen) {
+ ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+ StartFakingTabCapture();
+ ASSERT_TRUE(LaunchFlashFullscreen());
+ content::WebContents* const first_tab_contents = GetActiveWebContents();
+ EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, true));
+ PressEscape();
+ EXPECT_TRUE(ObserveTabIsInFullscreen(false));
+}
+
+// This tests that browser UI focus behavior is correct when switching between
+// tabs; particularly, that that focus between the omnibox and tab contents is
+// stored/restored correctly. Mouse and keyboard events are used to confirm
+// that the widget the UI thinks is focused is the one that responds to these
+// input events.
+IN_PROC_BROWSER_TEST_F(FlashFullscreenInteractiveBrowserTest,
+ FullscreenWithinTab_FocusWhenSwitchingTabs) {
+ ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+ StartFakingTabCapture();
+ ASSERT_TRUE(LaunchFlashFullscreen());
+
+ // Upon entering fullscreen, the Flash widget should have focus and be filled
+ // with green.
+ content::WebContents* const first_tab_contents = GetActiveWebContents();
+ EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, true));
+ ASSERT_TRUE(ObserveFlashFillColor(SK_ColorGREEN));
+
+ // Pressing the spacebar on the keyboard should change the fill color to red
+ // to indicate the plugin truly does have the keyboard focus. Clicking on the
+ // view should change the fill color to blue.
+ PressSpacebar();
+ ASSERT_TRUE(ObserveFlashFillColor(SK_ColorRED));
+ ClickOnTabContainer();
+ ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE));
+
+ // Launch a new tab. The Flash widget should have lost focus.
+ UseAcceleratorToOpenNewTab();
+ content::WebContents* const second_tab_contents = GetActiveWebContents();
+ ASSERT_NE(first_tab_contents, second_tab_contents);
+ EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, false));
+ ClickOnOmnibox();
+ EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, false));
+ SpamSpacebar();
+
+ // Switch back to first tab. The plugin should not have responded to the key
+ // presses above (while the omnibox was focused), and should regain focus only
+ // now. Poke it with key and mouse events to confirm.
+ UseAcceleratorToSwitchToTab(0);
+ EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, true));
+ ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE));
+ PressSpacebar();
+ ASSERT_TRUE(ObserveFlashFillColor(SK_ColorRED));
+ ClickOnTabContainer();
+ ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE));
+
+ // Click on the omnibox while still in the first tab, and the Flash widget
+ // should lose focus. Key presses should not affect the color of the Flash
+ // widget.
+ ClickOnOmnibox();
+ EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, false));
+ ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE));
+ SpamSpacebar();
+ ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE));
+
+ // Switch to the second tab, click on the web page content, and then go back
+ // to the first tab. Focus should have been restored to the omnibox when
+ // going back to the first tab, and so key presses should not change the color
+ // of the Flash widget.
+ UseAcceleratorToSwitchToTab(1);
+ EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, false));
+ ClickOnTabContainer();
+ EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, false));
+ UseAcceleratorToSwitchToTab(0);
+ EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, false));
+ ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE));
+ SpamSpacebar();
+ ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE));
+
+ // Clicking on the Flash widget should give it focus again.
+ ClickOnTabContainer();
+ EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, true));
+ ASSERT_TRUE(ObserveFlashFillColor(SK_ColorRED));
+ PressSpacebar();
+ ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE));
+
+ // Test that the Escape key is handled as an exit fullscreen command while the
+ // Flash widget has the focus.
+ EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, true));
+ PressEscape();
+ EXPECT_TRUE(ObserveTabIsInFullscreen(false));
+}
« no previous file with comments | « no previous file | chrome/chrome_tests.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698