fix: webview should maximize on requestFullscreen (#29952)
This commit is contained in:
parent
95a9ff952c
commit
6eff9231b8
8 changed files with 127 additions and 4 deletions
|
@ -89,6 +89,7 @@ export_gin_v8platform_pageallocator_for_usage_outside_of_the_gin.patch
|
||||||
fix_export_zlib_symbols.patch
|
fix_export_zlib_symbols.patch
|
||||||
don_t_use_potentially_null_getwebframe_-_view_when_get_blink.patch
|
don_t_use_potentially_null_getwebframe_-_view_when_get_blink.patch
|
||||||
web_contents.patch
|
web_contents.patch
|
||||||
|
webview_fullscreen.patch
|
||||||
disable_unload_metrics.patch
|
disable_unload_metrics.patch
|
||||||
fix_add_check_for_sandbox_then_result.patch
|
fix_add_check_for_sandbox_then_result.patch
|
||||||
extend_apply_webpreferences.patch
|
extend_apply_webpreferences.patch
|
||||||
|
|
35
patches/chromium/webview_fullscreen.patch
Normal file
35
patches/chromium/webview_fullscreen.patch
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Cheng Zhao <zcbenz@gmail.com>
|
||||||
|
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.
|
||||||
|
|
||||||
|
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 5c16a9ee9bbf461c24456613ff709f4f608e3441..4e4d1fdf50e2d480e099c9af71a45fc864d2cf56 100644
|
||||||
|
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||||
|
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||||
|
@@ -5520,6 +5520,15 @@ void RenderFrameHostImpl::EnterFullscreen(
|
||||||
|
notified_instances.insert(parent_site_instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // 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);
|
||||||
|
+ outer_proxy->GetAssociatedRemoteFrame()->WillEnterFullscreen(
|
||||||
|
+ options.Clone());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
delegate_->EnterFullscreenMode(this, *options);
|
||||||
|
delegate_->FullscreenStateChanged(this, true /* is_fullscreen */,
|
||||||
|
std::move(options));
|
|
@ -99,6 +99,7 @@
|
||||||
#include "shell/browser/web_contents_zoom_controller.h"
|
#include "shell/browser/web_contents_zoom_controller.h"
|
||||||
#include "shell/browser/web_dialog_helper.h"
|
#include "shell/browser/web_dialog_helper.h"
|
||||||
#include "shell/browser/web_view_guest_delegate.h"
|
#include "shell/browser/web_view_guest_delegate.h"
|
||||||
|
#include "shell/browser/web_view_manager.h"
|
||||||
#include "shell/common/api/electron_api_native_image.h"
|
#include "shell/common/api/electron_api_native_image.h"
|
||||||
#include "shell/common/color_util.h"
|
#include "shell/common/color_util.h"
|
||||||
#include "shell/common/electron_constants.h"
|
#include "shell/common/electron_constants.h"
|
||||||
|
@ -3566,13 +3567,13 @@ void WebContents::SetHtmlApiFullscreen(bool enter_fullscreen) {
|
||||||
// Window is already in fullscreen mode, save the state.
|
// Window is already in fullscreen mode, save the state.
|
||||||
if (enter_fullscreen && owner_window_->IsFullscreen()) {
|
if (enter_fullscreen && owner_window_->IsFullscreen()) {
|
||||||
native_fullscreen_ = true;
|
native_fullscreen_ = true;
|
||||||
html_fullscreen_ = true;
|
UpdateHtmlApiFullscreen(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exit html fullscreen state but not window's fullscreen mode.
|
// Exit html fullscreen state but not window's fullscreen mode.
|
||||||
if (!enter_fullscreen && native_fullscreen_) {
|
if (!enter_fullscreen && native_fullscreen_) {
|
||||||
html_fullscreen_ = false;
|
UpdateHtmlApiFullscreen(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3587,10 +3588,41 @@ void WebContents::SetHtmlApiFullscreen(bool enter_fullscreen) {
|
||||||
owner_window_->SetFullScreen(enter_fullscreen);
|
owner_window_->SetFullScreen(enter_fullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
html_fullscreen_ = enter_fullscreen;
|
UpdateHtmlApiFullscreen(enter_fullscreen);
|
||||||
native_fullscreen_ = false;
|
native_fullscreen_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebContents::UpdateHtmlApiFullscreen(bool fullscreen) {
|
||||||
|
if (fullscreen == html_fullscreen_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
html_fullscreen_ = fullscreen;
|
||||||
|
|
||||||
|
// Notify renderer of the html fullscreen change.
|
||||||
|
web_contents()
|
||||||
|
->GetRenderViewHost()
|
||||||
|
->GetWidget()
|
||||||
|
->SynchronizeVisualProperties();
|
||||||
|
|
||||||
|
// The embedder WebContents is spearated from the frame tree of webview, so
|
||||||
|
// we must manually sync their fullscreen states.
|
||||||
|
if (embedder_)
|
||||||
|
embedder_->SetHtmlApiFullscreen(fullscreen);
|
||||||
|
|
||||||
|
// Make sure all child webviews quit html fullscreen.
|
||||||
|
if (!fullscreen && !IsGuest()) {
|
||||||
|
auto* manager = WebViewManager::GetWebViewManager(web_contents());
|
||||||
|
manager->ForEachGuest(
|
||||||
|
web_contents(), base::BindRepeating([](content::WebContents* guest) {
|
||||||
|
WebContents* api_web_contents = WebContents::From(guest);
|
||||||
|
// Use UpdateHtmlApiFullscreen instead of SetXXX becuase there is no
|
||||||
|
// need to interact with the owner window.
|
||||||
|
api_web_contents->UpdateHtmlApiFullscreen(false);
|
||||||
|
return false;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
v8::Local<v8::ObjectTemplate> WebContents::FillObjectTemplate(
|
v8::Local<v8::ObjectTemplate> WebContents::FillObjectTemplate(
|
||||||
v8::Isolate* isolate,
|
v8::Isolate* isolate,
|
||||||
|
|
|
@ -686,6 +686,8 @@ class WebContents : public gin::Wrappable<WebContents>,
|
||||||
|
|
||||||
// Set fullscreen mode triggered by html api.
|
// Set fullscreen mode triggered by html api.
|
||||||
void SetHtmlApiFullscreen(bool enter_fullscreen);
|
void SetHtmlApiFullscreen(bool enter_fullscreen);
|
||||||
|
// Update the html fullscreen flag in both browser and renderer.
|
||||||
|
void UpdateHtmlApiFullscreen(bool fullscreen);
|
||||||
|
|
||||||
v8::Global<v8::Value> session_;
|
v8::Global<v8::Value> session_;
|
||||||
v8::Global<v8::Value> devtools_web_contents_;
|
v8::Global<v8::Value> devtools_web_contents_;
|
||||||
|
|
|
@ -24,7 +24,6 @@ class WebViewManager : public content::BrowserPluginGuestManager {
|
||||||
|
|
||||||
static WebViewManager* GetWebViewManager(content::WebContents* web_contents);
|
static WebViewManager* GetWebViewManager(content::WebContents* web_contents);
|
||||||
|
|
||||||
protected:
|
|
||||||
// content::BrowserPluginGuestManager:
|
// content::BrowserPluginGuestManager:
|
||||||
bool ForEachGuest(content::WebContents* embedder,
|
bool ForEachGuest(content::WebContents* embedder,
|
||||||
const GuestCallback& callback) override;
|
const GuestCallback& callback) override;
|
||||||
|
|
12
spec-main/fixtures/webview/fullscreen/frame.html
Normal file
12
spec-main/fixtures/webview/fullscreen/frame.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<body>
|
||||||
|
<div id="div">
|
||||||
|
WebView
|
||||||
|
</div>
|
||||||
|
<script type="text/javascript" charset="utf-8">
|
||||||
|
const {ipcRenderer} = require('electron')
|
||||||
|
ipcRenderer.send('webview-ready')
|
||||||
|
document.addEventListener('fullscreenchange', () => {
|
||||||
|
ipcRenderer.send('webview-fullscreenchange')
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</body>
|
12
spec-main/fixtures/webview/fullscreen/main.html
Normal file
12
spec-main/fixtures/webview/fullscreen/main.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<body>
|
||||||
|
<webview id="webview" nodeintegration="on" webpreferences="contextIsolation=no" src="frame.html"/>
|
||||||
|
<script type="text/javascript" charset="utf-8">
|
||||||
|
document.addEventListener('fullscreenchange', () => {
|
||||||
|
require('electron').ipcRenderer.send('fullscreenchange')
|
||||||
|
})
|
||||||
|
|
||||||
|
function isIframeFullscreen() {
|
||||||
|
return document.getElementById('webview').shadowRoot.lastElementChild.matches(':fullscreen')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
|
@ -378,6 +378,36 @@ describe('<webview> tag', function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('requestFullscreen from webview', () => {
|
||||||
|
const loadWebViewWindow = async () => {
|
||||||
|
const w = new BrowserWindow({
|
||||||
|
webPreferences: {
|
||||||
|
webviewTag: true,
|
||||||
|
nodeIntegration: true,
|
||||||
|
contextIsolation: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const attachPromise = emittedOnce(w.webContents, 'did-attach-webview');
|
||||||
|
const readyPromise = emittedOnce(ipcMain, 'webview-ready');
|
||||||
|
w.loadFile(path.join(__dirname, 'fixtures', 'webview', 'fullscreen', 'main.html'));
|
||||||
|
const [, webview] = await attachPromise;
|
||||||
|
await readyPromise;
|
||||||
|
return [w, webview];
|
||||||
|
};
|
||||||
|
|
||||||
|
afterEach(closeAllWindows);
|
||||||
|
|
||||||
|
it('should make parent frame element fullscreen too', async () => {
|
||||||
|
const [w, webview] = await loadWebViewWindow();
|
||||||
|
expect(await w.webContents.executeJavaScript('isIframeFullscreen()')).to.be.false();
|
||||||
|
|
||||||
|
const parentFullscreen = emittedOnce(ipcMain, 'fullscreenchange');
|
||||||
|
await webview.executeJavaScript('document.getElementById("div").requestFullscreen()', true);
|
||||||
|
await parentFullscreen;
|
||||||
|
expect(await w.webContents.executeJavaScript('isIframeFullscreen()')).to.be.true();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('nativeWindowOpen option', () => {
|
describe('nativeWindowOpen option', () => {
|
||||||
let w: BrowserWindow;
|
let w: BrowserWindow;
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
|
Loading…
Reference in a new issue