summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/ui/fullscreen/flash_fullscreen_interactive_browsertest.cc348
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/interactive_ui_tests.isolate5
-rw-r--r--content/browser/renderer_host/render_widget_host_delegate.h3
-rw-r--r--content/browser/renderer_host/render_widget_host_impl.cc2
-rw-r--r--content/browser/web_contents/web_contents_impl.cc33
-rw-r--r--content/browser/web_contents/web_contents_impl.h1
-rw-r--r--content/browser/web_contents/web_contents_view_aura.cc5
-rw-r--r--content/browser/web_contents/web_contents_view_mac.h5
-rw-r--r--content/browser/web_contents/web_contents_view_mac.mm21
-rw-r--r--ppapi/ppapi_sources.gypi2
-rw-r--r--ppapi/tests/test_flash_fullscreen_for_browser_ui.cc91
-rw-r--r--ppapi/tests/test_flash_fullscreen_for_browser_ui.h56
13 files changed, 547 insertions, 26 deletions
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 0000000..db7f86b
--- /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));
+}
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index fd4e170..445ee5c 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -864,6 +864,7 @@
'browser/ui/cocoa/apps/quit_with_apps_controller_mac_interactive_uitest.cc',
'browser/ui/cocoa/panels/panel_cocoa_browsertest.mm',
'browser/ui/find_bar/find_bar_host_interactive_uitest.cc',
+ 'browser/ui/fullscreen/flash_fullscreen_interactive_browsertest.cc',
'browser/ui/fullscreen/fullscreen_controller_interactive_browsertest.cc',
'browser/ui/fullscreen/fullscreen_controller_state_interactive_browsertest.cc',
'browser/ui/omnibox/omnibox_view_browsertest.cc',
diff --git a/chrome/interactive_ui_tests.isolate b/chrome/interactive_ui_tests.isolate
index 9f2717d..df3893d 100644
--- a/chrome/interactive_ui_tests.isolate
+++ b/chrome/interactive_ui_tests.isolate
@@ -17,6 +17,7 @@
'../testing/xvfb.py',
'<(PRODUCT_DIR)/libffmpegsumo.so',
'<(PRODUCT_DIR)/libosmesa.so',
+ '<(PRODUCT_DIR)/libppapi_tests.so',
'<(PRODUCT_DIR)/pyproto/',
],
},
@@ -33,6 +34,8 @@
'files': [
'../net/data/ssl/certificates/',
'../net/tools/testserver/',
+ '../ppapi/tests/test_case.html',
+ '../ppapi/tests/test_page.css',
'../testing/test_env.py',
'../third_party/pyftpdlib/',
'../third_party/pywebsocket/',
@@ -61,6 +64,7 @@
'<(PRODUCT_DIR)/<(mac_product_name).app/',
'<(PRODUCT_DIR)/ffmpegsumo.so',
'<(PRODUCT_DIR)/osmesa.so',
+ '<(PRODUCT_DIR)/ppapi_tests.plugin/Contents/MacOS/ppapi_tests',
],
},
}],
@@ -85,6 +89,7 @@
'<(PRODUCT_DIR)/libGLESv2.dll',
'<(PRODUCT_DIR)/osmesa.dll',
'<(PRODUCT_DIR)/plugins/npapi_test_plugin.dll',
+ '<(PRODUCT_DIR)/ppapi_tests.dll',
],
},
}],
diff --git a/content/browser/renderer_host/render_widget_host_delegate.h b/content/browser/renderer_host/render_widget_host_delegate.h
index d3bd78d..669dc25 100644
--- a/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/content/browser/renderer_host/render_widget_host_delegate.h
@@ -31,6 +31,9 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// The RenderWidgetHost is going to be deleted.
virtual void RenderWidgetDeleted(RenderWidgetHostImpl* render_widget_host) {}
+ // The RenderWidgetHost got the focus.
+ virtual void RenderWidgetGotFocus(RenderWidgetHostImpl* render_widget_host) {}
+
// Callback to give the browser a chance to handle the specified keyboard
// event before sending it to the renderer.
// Returns true if the |event| was handled. Otherwise, if the |event| would
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 8d0d24c..06c1163 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -628,6 +628,8 @@ void RenderWidgetHostImpl::ResizeRectChanged(const gfx::Rect& new_rect) {
void RenderWidgetHostImpl::GotFocus() {
Focus();
+ if (delegate_)
+ delegate_->RenderWidgetGotFocus(this);
}
void RenderWidgetHostImpl::Focus() {
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 4ce4f972..e6ee4cf 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1286,6 +1286,15 @@ void WebContentsImpl::RenderWidgetDeleted(
}
}
+void WebContentsImpl::RenderWidgetGotFocus(
+ RenderWidgetHostImpl* render_widget_host) {
+ // Notify the delegate if an embedded fullscreen widget was focused.
+ if (delegate_ && render_widget_host &&
+ delegate_->EmbedsFullscreenWidget() &&
+ render_widget_host->GetView() == GetFullscreenRenderWidgetHostView())
+ delegate_->WebContentsFocused(this);
+}
+
bool WebContentsImpl::PreHandleKeyboardEvent(
const NativeWebKeyboardEvent& event,
bool* is_keyboard_shortcut) {
@@ -2100,35 +2109,19 @@ DropData* WebContentsImpl::GetDropData() {
}
void WebContentsImpl::Focus() {
- RenderWidgetHostView* const fullscreen_view =
- GetFullscreenRenderWidgetHostView();
- if (fullscreen_view)
- fullscreen_view->Focus();
- else
- view_->Focus();
+ view_->Focus();
}
void WebContentsImpl::SetInitialFocus() {
- RenderWidgetHostView* const fullscreen_view =
- GetFullscreenRenderWidgetHostView();
- if (fullscreen_view)
- fullscreen_view->Focus();
- else
- view_->SetInitialFocus();
+ view_->SetInitialFocus();
}
void WebContentsImpl::StoreFocus() {
- if (!GetFullscreenRenderWidgetHostView())
- view_->StoreFocus();
+ view_->StoreFocus();
}
void WebContentsImpl::RestoreFocus() {
- RenderWidgetHostView* const fullscreen_view =
- GetFullscreenRenderWidgetHostView();
- if (fullscreen_view)
- fullscreen_view->Focus();
- else
- view_->RestoreFocus();
+ view_->RestoreFocus();
}
void WebContentsImpl::FocusThroughTabTraversal(bool reverse) {
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 60fdc72..c437796 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -515,6 +515,7 @@ class CONTENT_EXPORT WebContentsImpl
// RenderWidgetHostDelegate --------------------------------------------------
void RenderWidgetDeleted(RenderWidgetHostImpl* render_widget_host) override;
+ void RenderWidgetGotFocus(RenderWidgetHostImpl* render_widget_host) override;
bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
bool* is_keyboard_shortcut) override;
void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) override;
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
index 3ba80e7..3a9e7ab 100644
--- a/content/browser/web_contents/web_contents_view_aura.cc
+++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -1033,7 +1033,10 @@ void WebContentsViewAura::Focus() {
if (delegate_.get() && delegate_->Focus())
return;
- RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
+ RenderWidgetHostView* rwhv =
+ web_contents_->GetFullscreenRenderWidgetHostView();
+ if (!rwhv)
+ rwhv = web_contents_->GetRenderWidgetHostView();
if (rwhv)
rwhv->Focus();
}
diff --git a/content/browser/web_contents/web_contents_view_mac.h b/content/browser/web_contents/web_contents_view_mac.h
index 80292af..93c1eaf 100644
--- a/content/browser/web_contents/web_contents_view_mac.h
+++ b/content/browser/web_contents/web_contents_view_mac.h
@@ -122,6 +122,11 @@ class WebContentsViewMac : public WebContentsView,
WebContentsViewDelegate* delegate() { return delegate_.get(); }
private:
+ // Returns the fullscreen view, if one exists; otherwise, returns the content
+ // native view. This ensures that the view currently attached to a NSWindow is
+ // being used to query or set first responder state.
+ gfx::NativeView GetNativeViewForFocus() const;
+
// The WebContentsImpl whose contents we display.
WebContentsImpl* web_contents_;
diff --git a/content/browser/web_contents/web_contents_view_mac.mm b/content/browser/web_contents/web_contents_view_mac.mm
index 6e883b6..42348a9 100644
--- a/content/browser/web_contents/web_contents_view_mac.mm
+++ b/content/browser/web_contents/web_contents_view_mac.mm
@@ -158,9 +158,18 @@ void WebContentsViewMac::SizeContents(const gfx::Size& size) {
// previous implementation.
}
+gfx::NativeView WebContentsViewMac::GetNativeViewForFocus() const {
+ RenderWidgetHostView* rwhv =
+ web_contents_->GetFullscreenRenderWidgetHostView();
+ if (!rwhv)
+ rwhv = web_contents_->GetRenderWidgetHostView();
+ return rwhv ? rwhv->GetNativeView() : nil;
+}
+
void WebContentsViewMac::Focus() {
- NSWindow* window = [cocoa_view_.get() window];
- [window makeFirstResponder:GetContentNativeView()];
+ gfx::NativeView native_view = GetNativeViewForFocus();
+ NSWindow* window = [native_view window];
+ [window makeFirstResponder:native_view];
if (![window isVisible])
return;
[window makeKeyAndOrderFront:nil];
@@ -170,21 +179,23 @@ void WebContentsViewMac::SetInitialFocus() {
if (web_contents_->FocusLocationBarByDefault())
web_contents_->SetFocusToLocationBar(false);
else
- [[cocoa_view_.get() window] makeFirstResponder:GetContentNativeView()];
+ Focus();
}
void WebContentsViewMac::StoreFocus() {
+ gfx::NativeView native_view = GetNativeViewForFocus();
// We're explicitly being asked to store focus, so don't worry if there's
// already a view saved.
focus_tracker_.reset(
- [[FocusTracker alloc] initWithWindow:[cocoa_view_ window]]);
+ [[FocusTracker alloc] initWithWindow:[native_view window]]);
}
void WebContentsViewMac::RestoreFocus() {
+ gfx::NativeView native_view = GetNativeViewForFocus();
// TODO(avi): Could we be restoring a view that's no longer in the key view
// chain?
if (!(focus_tracker_.get() &&
- [focus_tracker_ restoreFocusInWindow:[cocoa_view_ window]])) {
+ [focus_tracker_ restoreFocusInWindow:[native_view window]])) {
// Fall back to the default focus behavior if we could not restore focus.
// TODO(shess): If location-bar gets focus by default, this will
// select-all in the field. If there was a specific selection in
diff --git a/ppapi/ppapi_sources.gypi b/ppapi/ppapi_sources.gypi
index 105ae4f..4407da7 100644
--- a/ppapi/ppapi_sources.gypi
+++ b/ppapi/ppapi_sources.gypi
@@ -554,6 +554,8 @@
'tests/test_flash_file.h',
'tests/test_flash_fullscreen.cc',
'tests/test_flash_fullscreen.h',
+ 'tests/test_flash_fullscreen_for_browser_ui.cc',
+ 'tests/test_flash_fullscreen_for_browser_ui.h',
'tests/test_flash_message_loop.cc',
'tests/test_flash_message_loop.h',
'tests/test_net_address_private.cc',
diff --git a/ppapi/tests/test_flash_fullscreen_for_browser_ui.cc b/ppapi/tests/test_flash_fullscreen_for_browser_ui.cc
new file mode 100644
index 0000000..0e37339
--- /dev/null
+++ b/ppapi/tests/test_flash_fullscreen_for_browser_ui.cc
@@ -0,0 +1,91 @@
+// 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 "ppapi/tests/test_flash_fullscreen_for_browser_ui.h"
+
+#include "ppapi/cpp/input_event.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/rect.h"
+#include "ppapi/tests/testing_instance.h"
+
+REGISTER_TEST_CASE(FlashFullscreenForBrowserUI);
+
+TestFlashFullscreenForBrowserUI::
+ TestFlashFullscreenForBrowserUI(TestingInstance* instance)
+ : TestCase(instance),
+ screen_mode_(instance),
+ view_change_event_(instance->pp_instance()),
+ num_trigger_events_(0),
+ callback_factory_(this) {
+ // This plugin should not be removed after this TestCase passes because
+ // browser UI testing requires it to remain and to be interactive.
+ instance_->set_remove_plugin(false);
+}
+
+TestFlashFullscreenForBrowserUI::~TestFlashFullscreenForBrowserUI() {
+}
+
+bool TestFlashFullscreenForBrowserUI::Init() {
+ return CheckTestingInterface();
+}
+
+void TestFlashFullscreenForBrowserUI::RunTests(const std::string& filter) {
+ RUN_TEST(EnterFullscreen, filter);
+}
+
+std::string TestFlashFullscreenForBrowserUI::TestEnterFullscreen() {
+ if (screen_mode_.IsFullscreen())
+ return ReportError("IsFullscreen() at start", true);
+
+ view_change_event_.Reset();
+ if (!screen_mode_.SetFullscreen(true))
+ return ReportError("SetFullscreen(true) in normal", false);
+ // DidChangeView() will call the callback once in fullscreen mode.
+ view_change_event_.Wait();
+
+ if (!screen_mode_.IsFullscreen())
+ return ReportError("IsFullscreen() in fullscreen", false);
+
+ const int32_t result =
+ instance_->RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_MOUSE |
+ PP_INPUTEVENT_CLASS_KEYBOARD);
+ if (result != PP_OK)
+ return ReportError("RequestFilteringInputEvents() failed", result);
+
+ PASS();
+}
+
+void TestFlashFullscreenForBrowserUI::DidChangeView(const pp::View& view) {
+ compositor_ = pp::Compositor(instance_);
+ instance_->BindGraphics(compositor_);
+ layer_size_ = view.GetRect().size();
+ color_layer_ = compositor_.AddLayer();
+ Paint(PP_OK);
+
+ view_change_event_.Signal();
+}
+
+bool TestFlashFullscreenForBrowserUI::HandleInputEvent(
+ const pp::InputEvent& event) {
+ if (event.GetType() != PP_INPUTEVENT_TYPE_MOUSEDOWN &&
+ event.GetType() != PP_INPUTEVENT_TYPE_CHAR) {
+ return false;
+ }
+
+ ++num_trigger_events_;
+
+ return true;
+}
+
+void TestFlashFullscreenForBrowserUI::Paint(int32_t last_compositor_result) {
+ if (num_trigger_events_ == 0)
+ color_layer_.SetColor(0.0f, 1.0f, 0.0f, 1.0f, layer_size_);
+ else if (num_trigger_events_ % 2)
+ color_layer_.SetColor(1.0f, 0.0f, 0.0f, 1.0f, layer_size_);
+ else
+ color_layer_.SetColor(0.0f, 0.0f, 1.0f, 1.0f, layer_size_);
+
+ compositor_.CommitLayers(
+ callback_factory_.NewCallback(&TestFlashFullscreenForBrowserUI::Paint));
+}
diff --git a/ppapi/tests/test_flash_fullscreen_for_browser_ui.h b/ppapi/tests/test_flash_fullscreen_for_browser_ui.h
new file mode 100644
index 0000000..4e253f3
--- /dev/null
+++ b/ppapi/tests/test_flash_fullscreen_for_browser_ui.h
@@ -0,0 +1,56 @@
+// 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.
+
+#ifndef PPAPI_TESTS_TEST_FLASH_FULLSCREEN_FOR_BROWSER_UI_H_
+#define PPAPI_TESTS_TEST_FLASH_FULLSCREEN_FOR_BROWSER_UI_H_
+
+#include <string>
+
+#include "ppapi/cpp/compositor.h"
+#include "ppapi/cpp/compositor_layer.h"
+#include "ppapi/cpp/private/flash_fullscreen.h"
+#include "ppapi/cpp/size.h"
+#include "ppapi/tests/test_case.h"
+#include "ppapi/tests/test_utils.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+// This is a special TestCase whose purpose is *not* to test the correctness of
+// the Pepper APIs. Instead, this is a simulated Flash plugin, used to place
+// the browser window and other UI elements into Flash Fullscreen mode for
+// layout, event, focus, etc. testing. See
+// chrome/browser/ui/fullscreen/flash_fullscreen_interactive_browsertest.cc.
+//
+// At start, this simulated Flash plugin will enter fullscreen and paint a green
+// color fill. From there, it will respond to mouse clicks or key presses by
+// toggling its fill color between red and blue. The browser test reads these
+// color changes to detect the desired behavior.
+class TestFlashFullscreenForBrowserUI : public TestCase {
+ public:
+ explicit TestFlashFullscreenForBrowserUI(TestingInstance* instance);
+ virtual ~TestFlashFullscreenForBrowserUI();
+
+ // TestCase implementation.
+ virtual bool Init() override;
+ virtual void RunTests(const std::string& filter) override;
+ virtual void DidChangeView(const pp::View& view) override;
+ virtual bool HandleInputEvent(const pp::InputEvent& event) override;
+
+ private:
+ std::string TestEnterFullscreen();
+ void Paint(int32_t last_compositor_result);
+
+ pp::FlashFullscreen screen_mode_;
+ NestedEvent view_change_event_;
+
+ pp::Compositor compositor_;
+ pp::Size layer_size_;
+ pp::CompositorLayer color_layer_;
+
+ int num_trigger_events_;
+
+ pp::CompletionCallbackFactory<TestFlashFullscreenForBrowserUI>
+ callback_factory_;
+};
+
+#endif // PPAPI_TESTS_TEST_FLASH_FULLSCREEN_FOR_BROWSER_UI_H_