fix: [webview] fix missing properties on events when contextIsolation: true (#26289)
This commit is contained in:
parent
c856b5fa53
commit
34156c424c
5 changed files with 51 additions and 24 deletions
|
@ -1,4 +1,4 @@
|
|||
import { webFrame, IpcMessageEvent } from 'electron';
|
||||
import { webFrame } from 'electron';
|
||||
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-internal-utils';
|
||||
import { webViewEvents } from '@electron/internal/common/web-view-events';
|
||||
|
@ -17,15 +17,15 @@ const dispatchEvent = function (
|
|||
dispatchEvent(webView, DEPRECATED_EVENTS[eventName], eventKey, ...args);
|
||||
}
|
||||
|
||||
const domEvent = new Event(eventName) as ElectronInternal.WebViewEvent;
|
||||
const props: Record<string, any> = {};
|
||||
webViewEvents[eventKey].forEach((prop, index) => {
|
||||
(domEvent as any)[prop] = args[index];
|
||||
props[prop] = args[index];
|
||||
});
|
||||
|
||||
webView.dispatchEvent(domEvent);
|
||||
webView.dispatchEvent(eventName, props);
|
||||
|
||||
if (eventName === 'load-commit') {
|
||||
webView.onLoadCommit(domEvent);
|
||||
webView.onLoadCommit(props);
|
||||
} else if (eventName === 'focus-change') {
|
||||
webView.onFocusChange();
|
||||
}
|
||||
|
@ -35,8 +35,7 @@ export function registerEvents (webView: WebViewImpl, viewInstanceId: number) {
|
|||
ipcRendererInternal.on(`${IPC_MESSAGES.GUEST_VIEW_INTERNAL_DESTROY_GUEST}-${viewInstanceId}`, function () {
|
||||
webView.guestInstanceId = undefined;
|
||||
webView.reset();
|
||||
const domEvent = new Event('destroyed');
|
||||
webView.dispatchEvent(domEvent);
|
||||
webView.dispatchEvent('destroyed');
|
||||
});
|
||||
|
||||
ipcRendererInternal.on(`${IPC_MESSAGES.GUEST_VIEW_INTERNAL_DISPATCH_EVENT}-${viewInstanceId}`, function (event, eventName, ...args) {
|
||||
|
@ -44,11 +43,7 @@ export function registerEvents (webView: WebViewImpl, viewInstanceId: number) {
|
|||
});
|
||||
|
||||
ipcRendererInternal.on(`${IPC_MESSAGES.GUEST_VIEW_INTERNAL_IPC_MESSAGE}-${viewInstanceId}`, function (event, channel, ...args) {
|
||||
const domEvent = new Event('ipc-message') as IpcMessageEvent;
|
||||
domEvent.channel = channel;
|
||||
domEvent.args = args;
|
||||
|
||||
webView.dispatchEvent(domEvent);
|
||||
webView.dispatchEvent('ipc-message', { channel, args });
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,13 @@ const defineWebViewElement = (v8Util: NodeJS.V8UtilBinding, webViewImpl: typeof
|
|||
|
||||
constructor () {
|
||||
super();
|
||||
v8Util.setHiddenValue(this, 'internal', new WebViewImpl(this));
|
||||
const internal = new WebViewImpl(this);
|
||||
internal.dispatchEventInMainWorld = (eventName, props) => {
|
||||
const event = new Event(eventName);
|
||||
Object.assign(event, props);
|
||||
return internal.webviewNode.dispatchEvent(event);
|
||||
};
|
||||
v8Util.setHiddenValue(this, 'internal', internal);
|
||||
}
|
||||
|
||||
connectedCallback () {
|
||||
|
|
|
@ -38,6 +38,8 @@ export class WebViewImpl {
|
|||
public attributes = new Map<string, WebViewAttribute>();
|
||||
public setupWebViewAttributes (): void {}
|
||||
|
||||
public dispatchEventInMainWorld?: (eventName: string, props: any) => boolean;
|
||||
|
||||
constructor (public webviewNode: HTMLElement) {
|
||||
// Create internal iframe element.
|
||||
this.internalElement = this.createInternalElement();
|
||||
|
@ -106,10 +108,11 @@ export class WebViewImpl {
|
|||
}
|
||||
|
||||
onElementResize () {
|
||||
const resizeEvent = new Event('resize') as ElectronInternal.WebFrameResizeEvent;
|
||||
resizeEvent.newWidth = this.webviewNode.clientWidth;
|
||||
resizeEvent.newHeight = this.webviewNode.clientHeight;
|
||||
this.dispatchEvent(resizeEvent);
|
||||
const props = {
|
||||
newWidth: this.webviewNode.clientWidth,
|
||||
newHeight: this.webviewNode.clientHeight
|
||||
};
|
||||
this.dispatchEvent('resize', props);
|
||||
}
|
||||
|
||||
createGuest () {
|
||||
|
@ -118,8 +121,8 @@ export class WebViewImpl {
|
|||
});
|
||||
}
|
||||
|
||||
dispatchEvent (webViewEvent: Electron.Event) {
|
||||
this.webviewNode.dispatchEvent(webViewEvent);
|
||||
dispatchEvent (eventName: string, props: Record<string, any> = {}) {
|
||||
this.dispatchEventInMainWorld!(eventName, props);
|
||||
}
|
||||
|
||||
// Adds an 'on<event>' property on the webview, which can be used to set/unset
|
||||
|
@ -144,10 +147,10 @@ export class WebViewImpl {
|
|||
}
|
||||
|
||||
// Updates state upon loadcommit.
|
||||
onLoadCommit (webViewEvent: ElectronInternal.WebViewEvent) {
|
||||
onLoadCommit (props: Record<string, any>) {
|
||||
const oldValue = this.webviewNode.getAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC);
|
||||
const newValue = webViewEvent.url;
|
||||
if (webViewEvent.isMainFrame && (oldValue !== newValue)) {
|
||||
const newValue = props.url;
|
||||
if (props.isMainFrame && (oldValue !== newValue)) {
|
||||
// Touching the src attribute triggers a navigation. To avoid
|
||||
// triggering a page reload on every guest-initiated navigation,
|
||||
// we do not handle this mutation.
|
||||
|
@ -160,7 +163,7 @@ export class WebViewImpl {
|
|||
const hasFocus = document.activeElement === this.webviewNode;
|
||||
if (hasFocus !== this.hasFocus) {
|
||||
this.hasFocus = hasFocus;
|
||||
this.dispatchEvent(new Event(hasFocus ? 'focus' : 'blur'));
|
||||
this.dispatchEvent(hasFocus ? 'focus' : 'blur');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -650,4 +650,27 @@ describe('<webview> tag', function () {
|
|||
generateSpecs('without sandbox', false);
|
||||
generateSpecs('with sandbox', true);
|
||||
});
|
||||
|
||||
describe('DOM events', () => {
|
||||
afterEach(closeAllWindows);
|
||||
it('receives extra properties on DOM events when contextIsolation is enabled', async () => {
|
||||
const w = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
webviewTag: true,
|
||||
contextIsolation: true
|
||||
}
|
||||
});
|
||||
await w.loadURL('about:blank');
|
||||
const message = await w.webContents.executeJavaScript(`new Promise((resolve, reject) => {
|
||||
const webview = new WebView()
|
||||
webview.setAttribute('src', 'data:text/html,<script>console.log("hi")</script>')
|
||||
webview.addEventListener('console-message', (e) => {
|
||||
resolve(e.message)
|
||||
})
|
||||
document.body.appendChild(webview)
|
||||
})`);
|
||||
expect(message).to.equal('hi');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
2
typings/internal-electron.d.ts
vendored
2
typings/internal-electron.d.ts
vendored
|
@ -254,7 +254,7 @@ declare namespace ElectronInternal {
|
|||
loader: ModuleLoader;
|
||||
}
|
||||
|
||||
interface WebFrameResizeEvent extends Electron.Event {
|
||||
interface WebFrameResizeEvent extends WebViewEvent {
|
||||
newWidth: number;
|
||||
newHeight: number;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue