From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 4 Oct 2018 14:57:02 -0700 Subject: fix: also propagate fullscreen state for outer frame When entering fullscreen with Element.requestFullscreen in child frames, the parent frame should also enter fullscreen mode too. Chromium handles this for iframes, but not for webviews as they are essentially main frames instead of child frames. This patch makes webviews propagate the fullscreen state to embedder.It also handles a DCHECK preventing guest webcontents from becoming the focused webContents. Note that we also need to manually update embedder's `api::WebContents::IsFullscreenForTabOrPending` value. diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index c3d4f2dbf0131a80ce2e18c3f1f35f3b4aa5b6f7..3b88a74fe5ccbad4c691be18ad7b902b356f0a31 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc @@ -7999,6 +7999,17 @@ void RenderFrameHostImpl::EnterFullscreen( } } + // Entering fullscreen from webview should also notify its outer frame. + if (frame_tree_node()->render_manager()->IsMainFrameForInnerDelegate()) { + RenderFrameProxyHost* outer_proxy = + frame_tree_node()->render_manager()->GetProxyToOuterDelegate(); + DCHECK(outer_proxy); + if (outer_proxy->is_render_frame_proxy_live()) { + outer_proxy->GetAssociatedRemoteFrame()->WillEnterFullscreen( + options.Clone()); + } + } + // Focus the window if another frame may have delegated the capability. if (had_fullscreen_token && !GetView()->HasFocus()) GetView()->Focus(); diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index c0199d91e9abe6a7f2b747904a853422459caab4..639f34cac9f58c3e757ed9b10050e2c185fe6a0c 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc @@ -3874,21 +3874,25 @@ KeyboardEventProcessingResult WebContentsImpl::PreHandleKeyboardEvent( const input::NativeWebKeyboardEvent& event) { OPTIONAL_TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("content.verbose"), "WebContentsImpl::PreHandleKeyboardEvent"); - auto* outermost_contents = GetOutermostWebContents(); - // TODO(wjmaclean): Generalize this to forward all key events to the outermost - // delegate's handler. - if (outermost_contents != this && IsFullscreen() && - event.windows_key_code == ui::VKEY_ESCAPE) { - // When an inner WebContents has focus and is fullscreen, redirect - // key events to the outermost WebContents so it can be handled by that - // WebContents' delegate. - if (outermost_contents->PreHandleKeyboardEvent(event) == - KeyboardEventProcessingResult::HANDLED) { + + auto handled = delegate_ ? delegate_->PreHandleKeyboardEvent(this, event) + : KeyboardEventProcessingResult::NOT_HANDLED; + + if (IsFullscreen() && event.windows_key_code == ui::VKEY_ESCAPE) { + if (handled == KeyboardEventProcessingResult::HANDLED) return KeyboardEventProcessingResult::HANDLED; + + // When an inner WebContents has focus and is fullscreen, traverse through + // containing webcontents to any that may handle the escape key. + while (auto* outer_web_contents = GetOuterWebContents()) { + auto result = outer_web_contents->PreHandleKeyboardEvent(event); + if (result == KeyboardEventProcessingResult::HANDLED) { + return KeyboardEventProcessingResult::HANDLED; + } } } - return delegate_ ? delegate_->PreHandleKeyboardEvent(this, event) - : KeyboardEventProcessingResult::NOT_HANDLED; + + return handled; } bool WebContentsImpl::HandleMouseEvent(const blink::WebMouseEvent& event) { @@ -4046,7 +4050,7 @@ void WebContentsImpl::EnterFullscreenMode( OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::EnterFullscreenMode"); DCHECK(CanEnterFullscreenMode(requesting_frame)); DCHECK(requesting_frame->IsActive()); - DCHECK(ContainsOrIsFocusedWebContents()); + DCHECK(ContainsOrIsFocusedWebContents() || IsGuest()); if (base::FeatureList::IsEnabled( features::kAutomaticFullscreenContentSetting)) { // Ensure the window is made active to take input focus. The user may have diff --git a/third_party/blink/renderer/core/fullscreen/fullscreen.cc b/third_party/blink/renderer/core/fullscreen/fullscreen.cc index c38fb30f097334e46d491b59b28bb883a5e84433..5d2bc8b46ded48263678f48fb6d71a1b8720ace9 100644 --- a/third_party/blink/renderer/core/fullscreen/fullscreen.cc +++ b/third_party/blink/renderer/core/fullscreen/fullscreen.cc @@ -110,7 +110,7 @@ void FullscreenElementChanged(Document& document, // is the iframe element for the out-of-process frame that contains the // fullscreen element. Hence, it must match :-webkit-full-screen-ancestor. if (new_request_type & FullscreenRequestType::kForCrossProcessDescendant) { - DCHECK(IsA(new_element)); + // DCHECK(IsA(new_element)); new_element->SetContainsFullScreenElement(true); } new_element->SetContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(