build: enable JS semicolons (#22783)

This commit is contained in:
Samuel Attard 2020-03-20 13:28:31 -07:00 committed by GitHub
parent 24e21467b9
commit 5d657dece4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
354 changed files with 21512 additions and 21510 deletions

View file

@ -1,7 +1,7 @@
import { webFrame, IpcMessageEvent } from 'electron'
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal'
import { webFrame, IpcMessageEvent } from 'electron';
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
import { WebViewImpl } from '@electron/internal/renderer/web-view/web-view-impl'
import { WebViewImpl } from '@electron/internal/renderer/web-view/web-view-impl';
const WEB_VIEW_EVENTS: Record<string, Array<string>> = {
'load-commit': ['url', 'isMainFrame'],
@ -37,76 +37,76 @@ const WEB_VIEW_EVENTS: Record<string, Array<string>> = {
'found-in-page': ['result'],
'did-change-theme-color': ['themeColor'],
'update-target-url': ['url']
}
};
const DEPRECATED_EVENTS: Record<string, string> = {
'page-title-updated': 'page-title-set'
}
};
const dispatchEvent = function (
webView: WebViewImpl, eventName: string, eventKey: string, ...args: Array<any>
) {
if (DEPRECATED_EVENTS[eventName] != null) {
dispatchEvent(webView, DEPRECATED_EVENTS[eventName], eventKey, ...args)
dispatchEvent(webView, DEPRECATED_EVENTS[eventName], eventKey, ...args);
}
const domEvent = new Event(eventName) as ElectronInternal.WebViewEvent
const domEvent = new Event(eventName) as ElectronInternal.WebViewEvent;
WEB_VIEW_EVENTS[eventKey].forEach((prop, index) => {
(domEvent as any)[prop] = args[index]
})
(domEvent as any)[prop] = args[index];
});
webView.dispatchEvent(domEvent)
webView.dispatchEvent(domEvent);
if (eventName === 'load-commit') {
webView.onLoadCommit(domEvent)
webView.onLoadCommit(domEvent);
} else if (eventName === 'focus-change') {
webView.onFocusChange()
webView.onFocusChange();
}
}
};
export function registerEvents (webView: WebViewImpl, viewInstanceId: number) {
ipcRendererInternal.on(`ELECTRON_GUEST_VIEW_INTERNAL_DESTROY_GUEST-${viewInstanceId}`, function () {
webView.guestInstanceId = undefined
webView.reset()
const domEvent = new Event('destroyed')
webView.dispatchEvent(domEvent)
})
webView.guestInstanceId = undefined;
webView.reset();
const domEvent = new Event('destroyed');
webView.dispatchEvent(domEvent);
});
ipcRendererInternal.on(`ELECTRON_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-${viewInstanceId}`, function (event, eventName, ...args) {
dispatchEvent(webView, eventName, eventName, ...args)
})
dispatchEvent(webView, eventName, eventName, ...args);
});
ipcRendererInternal.on(`ELECTRON_GUEST_VIEW_INTERNAL_IPC_MESSAGE-${viewInstanceId}`, function (event, channel, ...args) {
const domEvent = new Event('ipc-message') as IpcMessageEvent
domEvent.channel = channel
domEvent.args = args
const domEvent = new Event('ipc-message') as IpcMessageEvent;
domEvent.channel = channel;
domEvent.args = args;
webView.dispatchEvent(domEvent)
})
webView.dispatchEvent(domEvent);
});
}
export function deregisterEvents (viewInstanceId: number) {
ipcRendererInternal.removeAllListeners(`ELECTRON_GUEST_VIEW_INTERNAL_DESTROY_GUEST-${viewInstanceId}`)
ipcRendererInternal.removeAllListeners(`ELECTRON_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-${viewInstanceId}`)
ipcRendererInternal.removeAllListeners(`ELECTRON_GUEST_VIEW_INTERNAL_IPC_MESSAGE-${viewInstanceId}`)
ipcRendererInternal.removeAllListeners(`ELECTRON_GUEST_VIEW_INTERNAL_DESTROY_GUEST-${viewInstanceId}`);
ipcRendererInternal.removeAllListeners(`ELECTRON_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-${viewInstanceId}`);
ipcRendererInternal.removeAllListeners(`ELECTRON_GUEST_VIEW_INTERNAL_IPC_MESSAGE-${viewInstanceId}`);
}
export function createGuest (params: Record<string, any>): Promise<number> {
return ipcRendererInternal.invoke('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST', params)
return ipcRendererInternal.invoke('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST', params);
}
export function attachGuest (
elementInstanceId: number, guestInstanceId: number, params: Record<string, any>, contentWindow: Window
) {
const embedderFrameId = (webFrame as ElectronInternal.WebFrameInternal).getWebFrameId(contentWindow)
const embedderFrameId = (webFrame as ElectronInternal.WebFrameInternal).getWebFrameId(contentWindow);
if (embedderFrameId < 0) { // this error should not happen.
throw new Error('Invalid embedder frame')
throw new Error('Invalid embedder frame');
}
ipcRendererInternal.invoke('ELECTRON_GUEST_VIEW_MANAGER_ATTACH_GUEST', embedderFrameId, elementInstanceId, guestInstanceId, params)
ipcRendererInternal.invoke('ELECTRON_GUEST_VIEW_MANAGER_ATTACH_GUEST', embedderFrameId, elementInstanceId, guestInstanceId, params);
}
export const guestViewInternalModule = {
deregisterEvents,
createGuest,
attachGuest
}
};

View file

@ -1,15 +1,15 @@
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal'
import { WebViewImpl } from '@electron/internal/renderer/web-view/web-view-impl'
import { WEB_VIEW_CONSTANTS } from '@electron/internal/renderer/web-view/web-view-constants'
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
import { WebViewImpl } from '@electron/internal/renderer/web-view/web-view-impl';
import { WEB_VIEW_CONSTANTS } from '@electron/internal/renderer/web-view/web-view-constants';
// Helper function to resolve url set in attribute.
const a = document.createElement('a')
const a = document.createElement('a');
const resolveURL = function (url?: string | null) {
if (!url) return ''
a.href = url
return a.href
}
if (!url) return '';
a.href = url;
return a.href;
};
interface MutationHandler {
handleMutation (_oldValue: any, _newValue: any): any;
@ -22,40 +22,40 @@ class WebViewAttribute implements MutationHandler {
public ignoreMutation = false;
constructor (public name: string, public webViewImpl: WebViewImpl) {
this.name = name
this.value = (webViewImpl.webviewNode as Record<string, any>)[name] || ''
this.webViewImpl = webViewImpl
this.defineProperty()
this.name = name;
this.value = (webViewImpl.webviewNode as Record<string, any>)[name] || '';
this.webViewImpl = webViewImpl;
this.defineProperty();
}
// Retrieves and returns the attribute's value.
public getValue () {
return this.webViewImpl.webviewNode.getAttribute(this.name) || this.value
return this.webViewImpl.webviewNode.getAttribute(this.name) || this.value;
}
// Sets the attribute's value.
public setValue (value: any) {
this.webViewImpl.webviewNode.setAttribute(this.name, value || '')
this.webViewImpl.webviewNode.setAttribute(this.name, value || '');
}
// Changes the attribute's value without triggering its mutation handler.
public setValueIgnoreMutation (value: any) {
this.ignoreMutation = true
this.setValue(value)
this.ignoreMutation = false
this.ignoreMutation = true;
this.setValue(value);
this.ignoreMutation = false;
}
// Defines this attribute as a property on the webview node.
public defineProperty () {
return Object.defineProperty(this.webViewImpl.webviewNode, this.name, {
get: () => {
return this.getValue()
return this.getValue();
},
set: (value) => {
return this.setValue(value)
return this.setValue(value);
},
enumerable: true
})
});
}
// Called when the attribute's value changes.
@ -65,14 +65,14 @@ class WebViewAttribute implements MutationHandler {
// An attribute that is treated as a Boolean.
class BooleanAttribute extends WebViewAttribute {
getValue () {
return this.webViewImpl.webviewNode.hasAttribute(this.name)
return this.webViewImpl.webviewNode.hasAttribute(this.name);
}
setValue (value: boolean) {
if (value) {
this.webViewImpl.webviewNode.setAttribute(this.name, '')
this.webViewImpl.webviewNode.setAttribute(this.name, '');
} else {
this.webViewImpl.webviewNode.removeAttribute(this.name)
this.webViewImpl.webviewNode.removeAttribute(this.name);
}
}
}
@ -82,21 +82,21 @@ class PartitionAttribute extends WebViewAttribute {
public validPartitionId = true
constructor (public webViewImpl: WebViewImpl) {
super(WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION, webViewImpl)
super(WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION, webViewImpl);
}
public handleMutation = (oldValue: any, newValue: any) => {
newValue = newValue || ''
newValue = newValue || '';
// The partition cannot change if the webview has already navigated.
if (!this.webViewImpl.beforeFirstNavigation) {
console.error(WEB_VIEW_CONSTANTS.ERROR_MSG_ALREADY_NAVIGATED)
this.setValueIgnoreMutation(oldValue)
return
console.error(WEB_VIEW_CONSTANTS.ERROR_MSG_ALREADY_NAVIGATED);
this.setValueIgnoreMutation(oldValue);
return;
}
if (newValue === 'persist:') {
this.validPartitionId = false
console.error(WEB_VIEW_CONSTANTS.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE)
this.validPartitionId = false;
console.error(WEB_VIEW_CONSTANTS.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE);
}
}
}
@ -106,26 +106,26 @@ class SrcAttribute extends WebViewAttribute {
public observer!: MutationObserver;
constructor (public webViewImpl: WebViewImpl) {
super(WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC, webViewImpl)
this.setupMutationObserver()
super(WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC, webViewImpl);
this.setupMutationObserver();
}
public getValue () {
if (this.webViewImpl.webviewNode.hasAttribute(this.name)) {
return resolveURL(this.webViewImpl.webviewNode.getAttribute(this.name))
return resolveURL(this.webViewImpl.webviewNode.getAttribute(this.name));
} else {
return this.value
return this.value;
}
}
public setValueIgnoreMutation (value: any) {
super.setValueIgnoreMutation(value)
super.setValueIgnoreMutation(value);
// takeRecords() is needed to clear queued up src mutations. Without it, it
// is possible for this change to get picked up asyncronously by src's
// mutation observer |observer|, and then get handled even though we do not
// want to handle this mutation.
this.observer.takeRecords()
this.observer.takeRecords();
}
public handleMutation = (oldValue: any, newValue: any) => {
@ -136,10 +136,10 @@ class SrcAttribute extends WebViewAttribute {
// src attribute changes normally initiate a navigation. We suppress
// the next src attribute handler call to avoid reloading the page
// on every guest-initiated navigation.
this.setValueIgnoreMutation(oldValue)
return
this.setValueIgnoreMutation(oldValue);
return;
}
this.parse()
this.parse();
}
// The purpose of this mutation observer is to catch assignment to the src
@ -149,144 +149,144 @@ class SrcAttribute extends WebViewAttribute {
public setupMutationObserver () {
this.observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
const { oldValue } = mutation
const newValue = this.getValue()
const { oldValue } = mutation;
const newValue = this.getValue();
if (oldValue !== newValue) {
return
return;
}
this.handleMutation(oldValue, newValue)
this.handleMutation(oldValue, newValue);
}
})
});
const params = {
attributes: true,
attributeOldValue: true,
attributeFilter: [this.name]
}
};
this.observer.observe(this.webViewImpl.webviewNode, params)
this.observer.observe(this.webViewImpl.webviewNode, params);
}
public parse () {
if (!this.webViewImpl.elementAttached || !this.webViewImpl.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION].validPartitionId || !this.getValue()) {
return
return;
}
if (this.webViewImpl.guestInstanceId == null) {
if (this.webViewImpl.beforeFirstNavigation) {
this.webViewImpl.beforeFirstNavigation = false
this.webViewImpl.createGuest()
this.webViewImpl.beforeFirstNavigation = false;
this.webViewImpl.createGuest();
}
return
return;
}
// Navigate to |this.src|.
const opts: Record<string, string> = {}
const opts: Record<string, string> = {};
const httpreferrer = this.webViewImpl.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_HTTPREFERRER].getValue()
const httpreferrer = this.webViewImpl.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_HTTPREFERRER].getValue();
if (httpreferrer) {
opts.httpReferrer = httpreferrer
opts.httpReferrer = httpreferrer;
}
const useragent = this.webViewImpl.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_USERAGENT].getValue()
const useragent = this.webViewImpl.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_USERAGENT].getValue();
if (useragent) {
opts.userAgent = useragent
opts.userAgent = useragent;
}
const guestInstanceId = this.webViewImpl.guestInstanceId
const method = 'loadURL'
const args = [this.getValue(), opts]
const guestInstanceId = this.webViewImpl.guestInstanceId;
const method = 'loadURL';
const args = [this.getValue(), opts];
ipcRendererInternal.invoke('ELECTRON_GUEST_VIEW_MANAGER_CALL', guestInstanceId, method, args)
ipcRendererInternal.invoke('ELECTRON_GUEST_VIEW_MANAGER_CALL', guestInstanceId, method, args);
}
}
// Attribute specifies HTTP referrer.
class HttpReferrerAttribute extends WebViewAttribute {
constructor (webViewImpl: WebViewImpl) {
super(WEB_VIEW_CONSTANTS.ATTRIBUTE_HTTPREFERRER, webViewImpl)
super(WEB_VIEW_CONSTANTS.ATTRIBUTE_HTTPREFERRER, webViewImpl);
}
}
// Attribute specifies user agent
class UserAgentAttribute extends WebViewAttribute {
constructor (webViewImpl: WebViewImpl) {
super(WEB_VIEW_CONSTANTS.ATTRIBUTE_USERAGENT, webViewImpl)
super(WEB_VIEW_CONSTANTS.ATTRIBUTE_USERAGENT, webViewImpl);
}
}
// Attribute that set preload script.
class PreloadAttribute extends WebViewAttribute {
constructor (webViewImpl: WebViewImpl) {
super(WEB_VIEW_CONSTANTS.ATTRIBUTE_PRELOAD, webViewImpl)
super(WEB_VIEW_CONSTANTS.ATTRIBUTE_PRELOAD, webViewImpl);
}
public getValue () {
if (!this.webViewImpl.webviewNode.hasAttribute(this.name)) {
return this.value
return this.value;
}
let preload = resolveURL(this.webViewImpl.webviewNode.getAttribute(this.name))
const protocol = preload.substr(0, 5)
let preload = resolveURL(this.webViewImpl.webviewNode.getAttribute(this.name));
const protocol = preload.substr(0, 5);
if (protocol !== 'file:') {
console.error(WEB_VIEW_CONSTANTS.ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE)
preload = ''
console.error(WEB_VIEW_CONSTANTS.ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE);
preload = '';
}
return preload
return preload;
}
}
// Attribute that specifies the blink features to be enabled.
class BlinkFeaturesAttribute extends WebViewAttribute {
constructor (webViewImpl: WebViewImpl) {
super(WEB_VIEW_CONSTANTS.ATTRIBUTE_BLINKFEATURES, webViewImpl)
super(WEB_VIEW_CONSTANTS.ATTRIBUTE_BLINKFEATURES, webViewImpl);
}
}
// Attribute that specifies the blink features to be disabled.
class DisableBlinkFeaturesAttribute extends WebViewAttribute {
constructor (webViewImpl: WebViewImpl) {
super(WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEBLINKFEATURES, webViewImpl)
super(WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEBLINKFEATURES, webViewImpl);
}
}
// Attribute that specifies the web preferences to be enabled.
class WebPreferencesAttribute extends WebViewAttribute {
constructor (webViewImpl: WebViewImpl) {
super(WEB_VIEW_CONSTANTS.ATTRIBUTE_WEBPREFERENCES, webViewImpl)
super(WEB_VIEW_CONSTANTS.ATTRIBUTE_WEBPREFERENCES, webViewImpl);
}
}
class EnableRemoteModuleAttribute extends WebViewAttribute {
constructor (webViewImpl: WebViewImpl) {
super(WEB_VIEW_CONSTANTS.ATTRIBUTE_ENABLEREMOTEMODULE, webViewImpl)
super(WEB_VIEW_CONSTANTS.ATTRIBUTE_ENABLEREMOTEMODULE, webViewImpl);
}
public getValue () {
return this.webViewImpl.webviewNode.getAttribute(this.name) !== 'false'
return this.webViewImpl.webviewNode.getAttribute(this.name) !== 'false';
}
public setValue (value: any) {
this.webViewImpl.webviewNode.setAttribute(this.name, value ? 'true' : 'false')
this.webViewImpl.webviewNode.setAttribute(this.name, value ? 'true' : 'false');
}
}
// Sets up all of the webview attributes.
WebViewImpl.prototype.setupWebViewAttributes = function () {
this.attributes = {}
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION] = new PartitionAttribute(this)
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC] = new SrcAttribute(this)
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_HTTPREFERRER] = new HttpReferrerAttribute(this)
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_USERAGENT] = new UserAgentAttribute(this)
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATION] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATION, this)
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATIONINSUBFRAMES] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATIONINSUBFRAMES, this)
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PLUGINS] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_PLUGINS, this)
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEWEBSECURITY] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEWEBSECURITY, this)
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_ALLOWPOPUPS] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_ALLOWPOPUPS, this)
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_ENABLEREMOTEMODULE] = new EnableRemoteModuleAttribute(this)
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PRELOAD] = new PreloadAttribute(this)
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_BLINKFEATURES] = new BlinkFeaturesAttribute(this)
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEBLINKFEATURES] = new DisableBlinkFeaturesAttribute(this)
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_WEBPREFERENCES] = new WebPreferencesAttribute(this)
}
this.attributes = {};
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION] = new PartitionAttribute(this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC] = new SrcAttribute(this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_HTTPREFERRER] = new HttpReferrerAttribute(this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_USERAGENT] = new UserAgentAttribute(this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATION] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATION, this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATIONINSUBFRAMES] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATIONINSUBFRAMES, this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PLUGINS] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_PLUGINS, this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEWEBSECURITY] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEWEBSECURITY, this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_ALLOWPOPUPS] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_ALLOWPOPUPS, this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_ENABLEREMOTEMODULE] = new EnableRemoteModuleAttribute(this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PRELOAD] = new PreloadAttribute(this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_BLINKFEATURES] = new BlinkFeaturesAttribute(this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEBLINKFEATURES] = new DisableBlinkFeaturesAttribute(this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_WEBPREFERENCES] = new WebPreferencesAttribute(this);
};

View file

@ -8,12 +8,12 @@
// which runs in browserify environment instead of Node environment, all native
// modules must be passed from outside, all included files must be plain JS.
import { WEB_VIEW_CONSTANTS } from '@electron/internal/renderer/web-view/web-view-constants'
import { WebViewImpl as IWebViewImpl, webViewImplModule } from '@electron/internal/renderer/web-view/web-view-impl'
import { WEB_VIEW_CONSTANTS } from '@electron/internal/renderer/web-view/web-view-constants';
import { WebViewImpl as IWebViewImpl, webViewImplModule } from '@electron/internal/renderer/web-view/web-view-impl';
// Return a WebViewElement class that is defined in this context.
const defineWebViewElement = (v8Util: NodeJS.V8UtilBinding, webViewImpl: typeof webViewImplModule) => {
const { guestViewInternal, WebViewImpl } = webViewImpl
const { guestViewInternal, WebViewImpl } = webViewImpl;
return class WebViewElement extends HTMLElement {
public internalInstanceId?: number;
@ -33,45 +33,45 @@ const defineWebViewElement = (v8Util: NodeJS.V8UtilBinding, webViewImpl: typeof
WEB_VIEW_CONSTANTS.ATTRIBUTE_BLINKFEATURES,
WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEBLINKFEATURES,
WEB_VIEW_CONSTANTS.ATTRIBUTE_WEBPREFERENCES
]
];
}
constructor () {
super()
v8Util.setHiddenValue(this, 'internal', new WebViewImpl(this))
super();
v8Util.setHiddenValue(this, 'internal', new WebViewImpl(this));
}
connectedCallback () {
const internal = v8Util.getHiddenValue<IWebViewImpl>(this, 'internal')
const internal = v8Util.getHiddenValue<IWebViewImpl>(this, 'internal');
if (!internal) {
return
return;
}
if (!internal.elementAttached) {
guestViewInternal.registerEvents(internal, internal.viewInstanceId)
internal.elementAttached = true
internal.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC].parse()
guestViewInternal.registerEvents(internal, internal.viewInstanceId);
internal.elementAttached = true;
internal.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC].parse();
}
}
attributeChangedCallback (name: string, oldValue: any, newValue: any) {
const internal = v8Util.getHiddenValue<IWebViewImpl>(this, 'internal')
const internal = v8Util.getHiddenValue<IWebViewImpl>(this, 'internal');
if (internal) {
internal.handleWebviewAttributeMutation(name, oldValue, newValue)
internal.handleWebviewAttributeMutation(name, oldValue, newValue);
}
}
disconnectedCallback () {
const internal = v8Util.getHiddenValue<IWebViewImpl>(this, 'internal')
const internal = v8Util.getHiddenValue<IWebViewImpl>(this, 'internal');
if (!internal) {
return
return;
}
guestViewInternal.deregisterEvents(internal.viewInstanceId)
internal.elementAttached = false
this.internalInstanceId = 0
internal.reset()
guestViewInternal.deregisterEvents(internal.viewInstanceId);
internal.elementAttached = false;
this.internalInstanceId = 0;
internal.reset();
}
}
}
};
};
// Register <webview> custom element.
const registerWebViewElement = (v8Util: NodeJS.V8UtilBinding, webViewImpl: typeof webViewImplModule) => {
@ -79,40 +79,40 @@ const registerWebViewElement = (v8Util: NodeJS.V8UtilBinding, webViewImpl: typeo
// eslint-disable-next-line
const WebViewElement = defineWebViewElement(v8Util, webViewImpl) as unknown as typeof ElectronInternal.WebViewElement
webViewImpl.setupMethods(WebViewElement)
webViewImpl.setupMethods(WebViewElement);
// The customElements.define has to be called in a special scope.
const webFrame = webViewImpl.webFrame as ElectronInternal.WebFrameInternal
const webFrame = webViewImpl.webFrame as ElectronInternal.WebFrameInternal;
webFrame.allowGuestViewElementDefinition(window, () => {
window.customElements.define('webview', WebViewElement);
(window as any).WebView = WebViewElement
(window as any).WebView = WebViewElement;
// Delete the callbacks so developers cannot call them and produce unexpected
// behavior.
delete WebViewElement.prototype.connectedCallback
delete WebViewElement.prototype.disconnectedCallback
delete WebViewElement.prototype.attributeChangedCallback
delete WebViewElement.prototype.connectedCallback;
delete WebViewElement.prototype.disconnectedCallback;
delete WebViewElement.prototype.attributeChangedCallback;
// Now that |observedAttributes| has been retrieved, we can hide it from
// user code as well.
// TypeScript is concerned that we're deleting a read-only attribute
delete (WebViewElement as any).observedAttributes
})
}
delete (WebViewElement as any).observedAttributes;
});
};
// Prepare to register the <webview> element.
export const setupWebView = (v8Util: NodeJS.V8UtilBinding, webViewImpl: typeof webViewImplModule) => {
const useCapture = true
const useCapture = true;
const listener = (event: Event) => {
if (document.readyState === 'loading') {
return
return;
}
webViewImpl.setupAttributes()
registerWebViewElement(v8Util, webViewImpl)
webViewImpl.setupAttributes();
registerWebViewElement(v8Util, webViewImpl);
window.removeEventListener(event.type, listener, useCapture)
}
window.removeEventListener(event.type, listener, useCapture);
};
window.addEventListener('readystatechange', listener, useCapture)
}
window.addEventListener('readystatechange', listener, useCapture);
};

View file

@ -1,21 +1,21 @@
import * as electron from 'electron'
import * as electron from 'electron';
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal'
import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-internal-utils'
import * as guestViewInternal from '@electron/internal/renderer/web-view/guest-view-internal'
import { WEB_VIEW_CONSTANTS } from '@electron/internal/renderer/web-view/web-view-constants'
import { syncMethods, asyncMethods, properties } from '@electron/internal/common/web-view-methods'
import { deserialize } from '@electron/internal/common/type-utils'
const { webFrame } = electron
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-internal-utils';
import * as guestViewInternal from '@electron/internal/renderer/web-view/guest-view-internal';
import { WEB_VIEW_CONSTANTS } from '@electron/internal/renderer/web-view/web-view-constants';
import { syncMethods, asyncMethods, properties } from '@electron/internal/common/web-view-methods';
import { deserialize } from '@electron/internal/common/type-utils';
const { webFrame } = electron;
const v8Util = process.electronBinding('v8_util')
const v8Util = process.electronBinding('v8_util');
// ID generator.
let nextId = 0
let nextId = 0;
const getNextId = function () {
return ++nextId
}
return ++nextId;
};
// Represents the internal state of the WebView node.
export class WebViewImpl {
@ -38,29 +38,29 @@ export class WebViewImpl {
constructor (public webviewNode: HTMLElement) {
// Create internal iframe element.
this.internalElement = this.createInternalElement()
const shadowRoot = this.webviewNode.attachShadow({ mode: 'open' })
shadowRoot.innerHTML = '<!DOCTYPE html><style type="text/css">:host { display: flex; }</style>'
this.setupWebViewAttributes()
this.viewInstanceId = getNextId()
shadowRoot.appendChild(this.internalElement)
this.internalElement = this.createInternalElement();
const shadowRoot = this.webviewNode.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = '<!DOCTYPE html><style type="text/css">:host { display: flex; }</style>';
this.setupWebViewAttributes();
this.viewInstanceId = getNextId();
shadowRoot.appendChild(this.internalElement);
// Provide access to contentWindow.
Object.defineProperty(this.webviewNode, 'contentWindow', {
get: () => {
return this.internalElement.contentWindow
return this.internalElement.contentWindow;
},
enumerable: true
})
});
}
createInternalElement () {
const iframeElement = document.createElement('iframe')
iframeElement.style.flex = '1 1 auto'
iframeElement.style.width = '100%'
iframeElement.style.border = '0'
v8Util.setHiddenValue(iframeElement, 'internal', this)
return iframeElement
const iframeElement = document.createElement('iframe');
iframeElement.style.flex = '1 1 auto';
iframeElement.style.width = '100%';
iframeElement.style.border = '0';
v8Util.setHiddenValue(iframeElement, 'internal', this);
return iframeElement;
}
// Resets some state upon reattaching <webview> element to the DOM.
@ -72,20 +72,20 @@ export class WebViewImpl {
// heard back from createGuest yet. We will not reset the flag in this case so
// that we don't end up allocating a second guest.
if (this.guestInstanceId) {
this.guestInstanceId = undefined
this.guestInstanceId = undefined;
}
this.beforeFirstNavigation = true
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION].validPartitionId = true
this.beforeFirstNavigation = true;
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION].validPartitionId = true;
// Since attachment swaps a local frame for a remote frame, we need our
// internal iframe element to be local again before we can reattach.
const newFrame = this.createInternalElement()
const oldFrame = this.internalElement
this.internalElement = newFrame
const newFrame = this.createInternalElement();
const oldFrame = this.internalElement;
this.internalElement = newFrame;
if (oldFrame && oldFrame.parentNode) {
oldFrame.parentNode.replaceChild(newFrame, oldFrame)
oldFrame.parentNode.replaceChild(newFrame, oldFrame);
}
}
@ -96,179 +96,179 @@ export class WebViewImpl {
// details.
handleWebviewAttributeMutation (attributeName: string, oldValue: any, newValue: any) {
if (!this.attributes[attributeName] || this.attributes[attributeName].ignoreMutation) {
return
return;
}
// Let the changed attribute handle its own mutation
this.attributes[attributeName].handleMutation(oldValue, newValue)
this.attributes[attributeName].handleMutation(oldValue, newValue);
}
onElementResize () {
const resizeEvent = new Event('resize') as ElectronInternal.WebFrameResizeEvent
resizeEvent.newWidth = this.webviewNode.clientWidth
resizeEvent.newHeight = this.webviewNode.clientHeight
this.dispatchEvent(resizeEvent)
const resizeEvent = new Event('resize') as ElectronInternal.WebFrameResizeEvent;
resizeEvent.newWidth = this.webviewNode.clientWidth;
resizeEvent.newHeight = this.webviewNode.clientHeight;
this.dispatchEvent(resizeEvent);
}
createGuest () {
guestViewInternal.createGuest(this.buildParams()).then(guestInstanceId => {
this.attachGuestInstance(guestInstanceId)
})
this.attachGuestInstance(guestInstanceId);
});
}
dispatchEvent (webViewEvent: Electron.Event) {
this.webviewNode.dispatchEvent(webViewEvent)
this.webviewNode.dispatchEvent(webViewEvent);
}
// Adds an 'on<event>' property on the webview, which can be used to set/unset
// an event handler.
setupEventProperty (eventName: string) {
const propertyName = `on${eventName.toLowerCase()}`
const propertyName = `on${eventName.toLowerCase()}`;
return Object.defineProperty(this.webviewNode, propertyName, {
get: () => {
return this.on[propertyName]
return this.on[propertyName];
},
set: (value) => {
if (this.on[propertyName]) {
this.webviewNode.removeEventListener(eventName, this.on[propertyName])
this.webviewNode.removeEventListener(eventName, this.on[propertyName]);
}
this.on[propertyName] = value
this.on[propertyName] = value;
if (value) {
return this.webviewNode.addEventListener(eventName, value)
return this.webviewNode.addEventListener(eventName, value);
}
},
enumerable: true
})
});
}
// Updates state upon loadcommit.
onLoadCommit (webViewEvent: ElectronInternal.WebViewEvent) {
const oldValue = this.webviewNode.getAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC)
const newValue = webViewEvent.url
const oldValue = this.webviewNode.getAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC);
const newValue = webViewEvent.url;
if (webViewEvent.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.
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC].setValueIgnoreMutation(newValue)
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC].setValueIgnoreMutation(newValue);
}
}
// Emits focus/blur events.
onFocusChange () {
const hasFocus = document.activeElement === this.webviewNode
const hasFocus = document.activeElement === this.webviewNode;
if (hasFocus !== this.hasFocus) {
this.hasFocus = hasFocus
this.dispatchEvent(new Event(hasFocus ? 'focus' : 'blur'))
this.hasFocus = hasFocus;
this.dispatchEvent(new Event(hasFocus ? 'focus' : 'blur'));
}
}
onAttach (storagePartitionId: number) {
return this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION].setValue(storagePartitionId)
return this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION].setValue(storagePartitionId);
}
buildParams () {
const params: Record<string, any> = {
instanceId: this.viewInstanceId,
userAgentOverride: this.userAgentOverride
}
};
for (const attributeName in this.attributes) {
if (Object.prototype.hasOwnProperty.call(this.attributes, attributeName)) {
params[attributeName] = this.attributes[attributeName].getValue()
params[attributeName] = this.attributes[attributeName].getValue();
}
}
return params
return params;
}
attachGuestInstance (guestInstanceId: number) {
if (!this.elementAttached) {
// The element could be detached before we got response from browser.
return
return;
}
this.internalInstanceId = getNextId()
this.guestInstanceId = guestInstanceId
this.internalInstanceId = getNextId();
this.guestInstanceId = guestInstanceId;
guestViewInternal.attachGuest(
this.internalInstanceId,
this.guestInstanceId,
this.buildParams(),
this.internalElement.contentWindow!
)
);
// ResizeObserver is a browser global not recognized by "standard".
/* globals ResizeObserver */
// TODO(zcbenz): Should we deprecate the "resize" event? Wait, it is not
// even documented.
this.resizeObserver = new ResizeObserver(this.onElementResize.bind(this))
this.resizeObserver.observe(this.internalElement)
this.resizeObserver = new ResizeObserver(this.onElementResize.bind(this));
this.resizeObserver.observe(this.internalElement);
}
}
export const setupAttributes = () => {
require('@electron/internal/renderer/web-view/web-view-attributes')
}
require('@electron/internal/renderer/web-view/web-view-attributes');
};
// I wish eslint wasn't so stupid, but it is
// eslint-disable-next-line
export const setupMethods = (WebViewElement: typeof ElectronInternal.WebViewElement) => {
WebViewElement.prototype.getWebContentsId = function () {
const internal = v8Util.getHiddenValue<WebViewImpl>(this, 'internal')
const internal = v8Util.getHiddenValue<WebViewImpl>(this, 'internal');
if (!internal.guestInstanceId) {
throw new Error('The WebView must be attached to the DOM and the dom-ready event emitted before this method can be called.')
throw new Error('The WebView must be attached to the DOM and the dom-ready event emitted before this method can be called.');
}
return internal.guestInstanceId
}
return internal.guestInstanceId;
};
// Focusing the webview should move page focus to the underlying iframe.
WebViewElement.prototype.focus = function () {
this.contentWindow.focus()
}
this.contentWindow.focus();
};
// Forward proto.foo* method calls to WebViewImpl.foo*.
const createBlockHandler = function (method: string) {
return function (this: ElectronInternal.WebViewElement, ...args: Array<any>) {
return ipcRendererUtils.invokeSync('ELECTRON_GUEST_VIEW_MANAGER_CALL', this.getWebContentsId(), method, args)
}
}
return ipcRendererUtils.invokeSync('ELECTRON_GUEST_VIEW_MANAGER_CALL', this.getWebContentsId(), method, args);
};
};
for (const method of syncMethods) {
(WebViewElement.prototype as Record<string, any>)[method] = createBlockHandler(method)
(WebViewElement.prototype as Record<string, any>)[method] = createBlockHandler(method);
}
const createNonBlockHandler = function (method: string) {
return function (this: ElectronInternal.WebViewElement, ...args: Array<any>) {
return ipcRendererInternal.invoke('ELECTRON_GUEST_VIEW_MANAGER_CALL', this.getWebContentsId(), method, args)
}
}
return ipcRendererInternal.invoke('ELECTRON_GUEST_VIEW_MANAGER_CALL', this.getWebContentsId(), method, args);
};
};
for (const method of asyncMethods) {
(WebViewElement.prototype as Record<string, any>)[method] = createNonBlockHandler(method)
(WebViewElement.prototype as Record<string, any>)[method] = createNonBlockHandler(method);
}
WebViewElement.prototype.capturePage = async function (...args) {
return deserialize(await ipcRendererInternal.invoke('ELECTRON_GUEST_VIEW_MANAGER_CAPTURE_PAGE', this.getWebContentsId(), args))
}
return deserialize(await ipcRendererInternal.invoke('ELECTRON_GUEST_VIEW_MANAGER_CAPTURE_PAGE', this.getWebContentsId(), args));
};
const createPropertyGetter = function (property: string) {
return function (this: ElectronInternal.WebViewElement) {
return ipcRendererUtils.invokeSync('ELECTRON_GUEST_VIEW_MANAGER_PROPERTY_GET', this.getWebContentsId(), property)
}
}
return ipcRendererUtils.invokeSync('ELECTRON_GUEST_VIEW_MANAGER_PROPERTY_GET', this.getWebContentsId(), property);
};
};
const createPropertySetter = function (property: string) {
return function (this: ElectronInternal.WebViewElement, arg: any) {
return ipcRendererUtils.invokeSync('ELECTRON_GUEST_VIEW_MANAGER_PROPERTY_SET', this.getWebContentsId(), property, arg)
}
}
return ipcRendererUtils.invokeSync('ELECTRON_GUEST_VIEW_MANAGER_PROPERTY_SET', this.getWebContentsId(), property, arg);
};
};
for (const property of properties) {
Object.defineProperty(WebViewElement.prototype, property, {
get: createPropertyGetter(property) as any,
set: createPropertySetter(property)
})
});
}
}
};
export const webViewImplModule = {
setupAttributes,
@ -276,4 +276,4 @@ export const webViewImplModule = {
guestViewInternal,
webFrame,
WebViewImpl
}
};

View file

@ -1,18 +1,18 @@
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal'
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
const v8Util = process.electronBinding('v8_util')
const v8Util = process.electronBinding('v8_util');
function handleFocusBlur (guestInstanceId: number) {
// Note that while Chromium content APIs have observer for focus/blur, they
// unfortunately do not work for webview.
window.addEventListener('focus', () => {
ipcRendererInternal.send('ELECTRON_GUEST_VIEW_MANAGER_FOCUS_CHANGE', true, guestInstanceId)
})
ipcRendererInternal.send('ELECTRON_GUEST_VIEW_MANAGER_FOCUS_CHANGE', true, guestInstanceId);
});
window.addEventListener('blur', () => {
ipcRendererInternal.send('ELECTRON_GUEST_VIEW_MANAGER_FOCUS_CHANGE', false, guestInstanceId)
})
ipcRendererInternal.send('ELECTRON_GUEST_VIEW_MANAGER_FOCUS_CHANGE', false, guestInstanceId);
});
}
export function webViewInit (
@ -20,17 +20,17 @@ export function webViewInit (
) {
// Don't allow recursive `<webview>`.
if (webviewTag && guestInstanceId == null) {
const { webViewImplModule } = require('@electron/internal/renderer/web-view/web-view-impl')
const { webViewImplModule } = require('@electron/internal/renderer/web-view/web-view-impl');
if (contextIsolation) {
v8Util.setHiddenValue(window, 'web-view-impl', webViewImplModule)
v8Util.setHiddenValue(window, 'web-view-impl', webViewImplModule);
} else {
const { setupWebView } = require('@electron/internal/renderer/web-view/web-view-element')
setupWebView(v8Util, webViewImplModule)
const { setupWebView } = require('@electron/internal/renderer/web-view/web-view-element');
setupWebView(v8Util, webViewImplModule);
}
}
if (guestInstanceId) {
// Report focus/blur events of webview to browser.
handleFocusBlur(guestInstanceId)
handleFocusBlur(guestInstanceId);
}
}