Commit e118727d authored by W. James MacLean's avatar W. James MacLean Committed by Commit Bot

In fullscreen mode, pass <esc> to outmost WebContents.

When an inner WebContents is fullscreen, and has focus, pressing <esc>
causes the keyboard event to be handled by that webcontents. But it
should instead be handled by the outermost WebContents so that it can
get to the appropriate delegate.

Bug: 1013640
Change-Id: I4ff81bea8cd9fa43259dde39b3bc479f6fd06f07
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1896771Reviewed-by: default avatarIstiaque Ahmed <lazyboy@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarAlex Moshchuk <alexmos@chromium.org>
Commit-Queue: James MacLean <wjmaclean@chromium.org>
Cr-Commit-Position: refs/heads/master@{#714386}
parent f0e88c11
......@@ -234,6 +234,28 @@ var tests = [
() => document.body.webkitRequestFullscreen());
},
function testFullscreenEscape() {
checkStreamDetails('testFullscreenEscape.csv', false);
var calls = 0;
var windowId;
window.addEventListener('webkitfullscreenchange', async e => {
switch(calls) {
case 0: // On fullscreen entered.
chrome.test.assertTrue(document.webkitIsFullScreen);
chrome.test.assertEq(document.body, document.webkitFullscreenElement);
break;
case 1: // On fullscreen exited.
chrome.test.assertFalse(document.webkitIsFullScreen);
chrome.test.assertEq(null, document.webkitFullscreenElement);
chrome.test.succeed();
break;
}
calls++;
});
chrome.test.runWithUserGesture(
() => document.body.webkitRequestFullscreen());
},
function testBackgroundPage() {
checkStreamDetails('testBackgroundPage.csv', false);
chrome.runtime.getBackgroundPage(backgroundPage => {
......
......@@ -2288,6 +2288,19 @@ void WebContentsImpl::RenderWidgetWasResized(
KeyboardEventProcessingResult WebContentsImpl::PreHandleKeyboardEvent(
const NativeWebKeyboardEvent& event) {
auto* outermost_contents = GetOutermostWebContents();
// TODO(wjmaclean): Generalize this to forward all key events to the outermost
// delegate's handler.
if (outermost_contents != this && IsFullscreenForCurrentTab() &&
event.windows_key_code == ui::VKEY_ESCAPE) {
// When an inner WebContents has focus and is fullscreen, redirect <esc>
// key events to the outermost WebContents so it can be handled by that
// WebContents' delegate.
if (outermost_contents->PreHandleKeyboardEvent(event) ==
KeyboardEventProcessingResult::HANDLED) {
return KeyboardEventProcessingResult::HANDLED;
}
}
return delegate_ ? delegate_->PreHandleKeyboardEvent(this, event)
: KeyboardEventProcessingResult::NOT_HANDLED;
}
......
......@@ -2205,6 +2205,10 @@ RenderWidgetHost* GetFocusedRenderWidgetHost(WebContents* web_contents) {
web_contents_impl->GetMainFrame()->GetRenderWidgetHost());
}
bool IsRenderWidgetHostFocused(const RenderWidgetHost* host) {
return static_cast<const RenderWidgetHostImpl*>(host)->is_focused();
}
WebContents* GetFocusedWebContents(WebContents* web_contents) {
WebContentsImpl* web_contents_impl =
static_cast<WebContentsImpl*>(web_contents);
......
......@@ -982,6 +982,9 @@ std::vector<RenderWidgetHostView*> GetInputEventRouterRenderWidgetHostViews(
// Returns the focused RenderWidgetHost.
RenderWidgetHost* GetFocusedRenderWidgetHost(WebContents* web_contents);
// Returns whether or not the RenderWidgetHost thinks it is focused.
bool IsRenderWidgetHostFocused(const RenderWidgetHost*);
// Returns the focused WebContents.
WebContents* GetFocusedWebContents(WebContents* web_contents);
......
......@@ -43,4 +43,8 @@ specific_include_rules = {
"mime_handler_view_browsertest.cc": [
"+components/printing/common",
],
"mime_handler_view_interactive_uitest.cc": [
"+chrome/browser/ui/exclusive_access/fullscreen_controller_test.h",
"+chrome/test/base/interactive_test_utils.h",
],
}
......@@ -11,11 +11,15 @@
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_timeouts.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/ui/exclusive_access/fullscreen_controller_test.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/guest_view/browser/test_guest_view_manager.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
......@@ -26,6 +30,7 @@
#include "extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.h"
#include "extensions/test/result_catcher.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "third_party/blink/public/platform/web_pointer_properties.h"
using guest_view::GuestViewManager;
using guest_view::GuestViewManagerDelegate;
......@@ -143,4 +148,75 @@ IN_PROC_BROWSER_TEST_P(MimeHandlerViewTest, MAYBE_Fullscreen) {
RunTest("testFullscreen.csv");
}
namespace {
void WaitForFullscreenAnimation() {
#if defined(OS_MACOSX)
const int delay_in_ms = 1500;
#else
const int delay_in_ms = 100;
#endif
// Wait for Mac OS fullscreen animation.
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(),
base::TimeDelta::FromMilliseconds(delay_in_ms));
run_loop.Run();
}
} // namespace
IN_PROC_BROWSER_TEST_P(MimeHandlerViewTest, EscapeExitsFullscreen) {
// Only run this test in cross-process mode.
if (!GetParam())
return;
// Use the testing subclass of MimeHandlerViewGuest.
GetGuestViewManager()->RegisterTestGuestViewType<MimeHandlerViewGuest>(
base::BindRepeating(&TestMimeHandlerViewGuest::Create));
const Extension* extension = LoadTestExtension();
ASSERT_TRUE(extension);
ResultCatcher catcher;
// Set observer to watch for fullscreen.
FullscreenNotificationObserver fullscreen_waiter(browser());
ui_test_utils::NavigateToURL(
browser(), embedded_test_server()->GetURL("/testFullscreenEscape.csv"));
// Make sure we have a guestviewmanager.
auto* embedder_contents = browser()->tab_strip_model()->GetWebContentsAt(0);
auto* guest_contents = GetGuestViewManager()->WaitForSingleGuestCreated();
auto* guest_rwh =
guest_contents->GetRenderWidgetHostView()->GetRenderWidgetHost();
// Wait for fullscreen mode.
fullscreen_waiter.Wait();
WaitForFullscreenAnimation();
EXPECT_NE(guest_contents, content::GetFocusedWebContents(embedder_contents));
EXPECT_FALSE(IsRenderWidgetHostFocused(guest_rwh));
// Send a touch to focus the guest. We can't directly test that the correct
// RenderWidgetHost got focus, but the wait seems to work.
SimulateMouseClick(guest_contents, 0, blink::WebMouseEvent::Button::kLeft);
while (!IsRenderWidgetHostFocused(guest_rwh)) {
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
run_loop.Run();
}
EXPECT_EQ(guest_contents, content::GetFocusedWebContents(embedder_contents));
// Send <esc> to exit fullscreen.
ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_ESCAPE, false,
false, false, false));
WaitForFullscreenAnimation();
// Now wait for the test to succeed, or timeout.
if (!catcher.GetNextResult())
FAIL() << catcher.message();
}
} // namespace extensions
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment