diff options
-rw-r--r-- | chrome/browser/ui/fullscreen/flash_fullscreen_interactive_browsertest.cc | 348 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | chrome/interactive_ui_tests.isolate | 5 | ||||
-rw-r--r-- | content/browser/renderer_host/render_widget_host_delegate.h | 3 | ||||
-rw-r--r-- | content/browser/renderer_host/render_widget_host_impl.cc | 2 | ||||
-rw-r--r-- | content/browser/web_contents/web_contents_impl.cc | 33 | ||||
-rw-r--r-- | content/browser/web_contents/web_contents_impl.h | 1 | ||||
-rw-r--r-- | content/browser/web_contents/web_contents_view_aura.cc | 5 | ||||
-rw-r--r-- | content/browser/web_contents/web_contents_view_mac.h | 5 | ||||
-rw-r--r-- | content/browser/web_contents/web_contents_view_mac.mm | 21 | ||||
-rw-r--r-- | ppapi/ppapi_sources.gypi | 2 | ||||
-rw-r--r-- | ppapi/tests/test_flash_fullscreen_for_browser_ui.cc | 91 | ||||
-rw-r--r-- | ppapi/tests/test_flash_fullscreen_for_browser_ui.h | 56 |
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_ |