Compare commits

...

1 Commits

Author SHA1 Message Date
Shelley Vohr
bb06bba2fd fix: webview visibilityState should track BrowserWindow webContents 2023-08-14 11:17:15 +02:00
5 changed files with 52 additions and 34 deletions

View File

@@ -37,22 +37,6 @@ BrowserWindow.prototype._init = function (this: BWT) {
app.emit('browser-window-focus', event, this);
});
// Subscribe to visibilityState changes and pass to renderer process.
let isVisible = this.isVisible() && !this.isMinimized();
const visibilityChanged = () => {
const newState = this.isVisible() && !this.isMinimized();
if (isVisible !== newState) {
isVisible = newState;
const visibilityState = isVisible ? 'visible' : 'hidden';
this.webContents.emit('-window-visibility-change', visibilityState);
}
};
const visibilityEvents = ['show', 'hide', 'minimize', 'maximize', 'restore'];
for (const event of visibilityEvents) {
this.on(event as any, visibilityChanged);
}
const warn = deprecate.warnOnceMessage('\'scroll-touch-{begin,end,edge}\' are deprecated and will be removed. Please use the WebContents \'input-event\' event instead.');
this.webContents.on('input-event', (_, e) => {
if (e.type === 'gestureScrollBegin') {

View File

@@ -176,7 +176,7 @@ const createGuest = function (embedder: Electron.WebContents, embedderFrameId: n
// FIXME Remove once https://github.com/electron/electron/issues/6828 is fixed
guest.on('dom-ready', function () {
const guestInstance = guestInstances.get(guestInstanceId);
if (guestInstance != null && guestInstance.visibilityState != null) {
if (guestInstance?.visibilityState != null) {
guest._sendInternal(IPC_MESSAGES.GUEST_INSTANCE_VISIBILITY_CHANGE, guestInstance.visibilityState);
}
});
@@ -229,7 +229,7 @@ const watchEmbedder = function (embedder: Electron.WebContents) {
watchedEmbedders.add(embedder);
// Forward embedder window visibility change events to guest
const onVisibilityChange = function (visibilityState: DocumentVisibilityState) {
const onVisibilityChange = (_: Event, visibilityState: DocumentVisibilityState) => {
for (const guestInstance of guestInstances.values()) {
guestInstance.visibilityState = visibilityState;
if (guestInstance.embedder === embedder) {
@@ -237,7 +237,7 @@ const watchEmbedder = function (embedder: Electron.WebContents) {
}
}
};
embedder.on('-window-visibility-change' as any, onVisibilityChange);
embedder.on('-visibility-change' as any, onVisibilityChange);
embedder.once('will-destroy' as any, () => {
// Usually the guestInstances is cleared when guest is destroyed, but it
@@ -248,8 +248,8 @@ const watchEmbedder = function (embedder: Electron.WebContents) {
detachGuest(embedder, guestInstanceId);
}
}
// Clear the listeners.
embedder.removeListener('-window-visibility-change' as any, onVisibilityChange);
embedder.removeListener('-visibility-change' as any, onVisibilityChange);
watchedEmbedders.delete(embedder);
});
};

View File

@@ -10,30 +10,27 @@ export const windowSetup = (isWebView: boolean, isHiddenPage: boolean) => {
window.close = function () {
ipcRendererInternal.send(IPC_MESSAGES.BROWSER_WINDOW_CLOSE);
};
if (contextIsolationEnabled) internalContextBridge.overrideGlobalValueFromIsolatedWorld(['close'], window.close);
if (contextIsolationEnabled) {
internalContextBridge.overrideGlobalValueFromIsolatedWorld(['close'], window.close);
}
}
// But we do not support prompt().
window.prompt = function () {
throw new Error('prompt() is and will not be supported.');
};
if (contextIsolationEnabled) internalContextBridge.overrideGlobalValueFromIsolatedWorld(['prompt'], window.prompt);
if (contextIsolationEnabled) {
internalContextBridge.overrideGlobalValueFromIsolatedWorld(['prompt'], window.prompt);
};
if (isWebView) {
// Webview `document.visibilityState` tracks window visibility (and ignores
// the actual <webview> element visibility) for backwards compatibility.
// See discussion in #9178.
//
// Note that this results in duplicate visibilitychange events (since
// Chromium also fires them) and potentially incorrect visibility change.
// We should reconsider this decision for Electron 2.0.
// Webview `document.visibilityState` tracks visibility of the containing webContents.
let cachedVisibilityState = isHiddenPage ? 'hidden' : 'visible';
// Subscribe to visibilityState changes.
ipcRendererInternal.on(IPC_MESSAGES.GUEST_INSTANCE_VISIBILITY_CHANGE, function (_event, visibilityState: DocumentVisibilityState) {
ipcRendererInternal.on(IPC_MESSAGES.GUEST_INSTANCE_VISIBILITY_CHANGE, (_: Event, visibilityState: DocumentVisibilityState) => {
if (cachedVisibilityState !== visibilityState) {
cachedVisibilityState = visibilityState;
document.dispatchEvent(new Event('visibilitychange'));
}
});
@@ -42,12 +39,22 @@ export const windowSetup = (isWebView: boolean, isHiddenPage: boolean) => {
Object.defineProperty(document, 'hidden', {
get: getDocumentHidden
});
if (contextIsolationEnabled) internalContextBridge.overrideGlobalPropertyFromIsolatedWorld(['document', 'hidden'], getDocumentHidden);
if (contextIsolationEnabled) {
internalContextBridge.overrideGlobalPropertyFromIsolatedWorld(
['document', 'hidden'],
getDocumentHidden
);
}
const getDocumentVisibilityState = () => cachedVisibilityState;
Object.defineProperty(document, 'visibilityState', {
get: getDocumentVisibilityState
});
if (contextIsolationEnabled) internalContextBridge.overrideGlobalPropertyFromIsolatedWorld(['document', 'visibilityState'], getDocumentVisibilityState);
if (contextIsolationEnabled) {
internalContextBridge.overrideGlobalPropertyFromIsolatedWorld(
['document', 'visibilityState'],
getDocumentVisibilityState
);
}
}
};

View File

@@ -336,6 +336,26 @@ struct Converter<scoped_refptr<content::DevToolsAgentHost>> {
}
};
template <>
struct Converter<content::Visibility> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
content::Visibility val) {
std::string visibility;
switch (val) {
case content::Visibility::VISIBLE:
visibility = "visible";
break;
case content::Visibility::OCCLUDED:
case content::Visibility::HIDDEN:
visibility = "hidden";
break;
default:
break;
}
return gin::ConvertToV8(isolate, visibility);
}
};
} // namespace gin
namespace electron::api {
@@ -1792,6 +1812,12 @@ void WebContents::OnWebContentsLostFocus(
Emit("blur");
}
void WebContents::OnVisibilityChanged(content::Visibility visibility) {
content::Visibility updated_visibility =
background_throttling_ ? visibility : content::Visibility::VISIBLE;
Emit("-visibility-change", updated_visibility);
}
void WebContents::DOMContentLoaded(
content::RenderFrameHost* render_frame_host) {
auto* web_frame = WebFrameMain::FromRenderFrameHost(render_frame_host);

View File

@@ -639,6 +639,7 @@ class WebContents : public ExclusiveAccessContext,
content::RenderWidgetHost* render_widget_host) override;
void OnWebContentsLostFocus(
content::RenderWidgetHost* render_widget_host) override;
void OnVisibilityChanged(content::Visibility visibility) override;
// InspectableWebContentsDelegate:
void DevToolsReloadPage() override;