refactor: use separate ipc-renderer-internal / ipc-main-internal APIs for Electron internals (#13940)
This commit is contained in:
parent
f7122610cc
commit
b50f86ef43
49 changed files with 322 additions and 133 deletions
|
@ -1,9 +1,10 @@
|
|||
'use strict'
|
||||
|
||||
const electron = require('electron')
|
||||
const { ipcMain, WebContentsView, TopLevelWindow } = electron
|
||||
const { WebContentsView, TopLevelWindow } = electron
|
||||
const { BrowserWindow } = process.atomBinding('window')
|
||||
const v8Util = process.atomBinding('v8_util')
|
||||
const ipcMain = require('@electron/internal/browser/ipc-main-internal')
|
||||
|
||||
Object.setPrototypeOf(BrowserWindow.prototype, TopLevelWindow.prototype)
|
||||
|
||||
|
|
14
lib/browser/api/crash-reporter.js
Normal file
14
lib/browser/api/crash-reporter.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
'use strict'
|
||||
|
||||
const CrashReporter = require('@electron/internal/common/crash-reporter')
|
||||
const ipcMain = require('@electron/internal/browser/ipc-main-internal')
|
||||
|
||||
class CrashReporterMain extends CrashReporter {
|
||||
sendSync (channel, ...args) {
|
||||
const event = {}
|
||||
ipcMain.emit(channel, event, ...args)
|
||||
return event.returnValue
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new CrashReporterMain()
|
|
@ -1,17 +1,9 @@
|
|||
'use strict'
|
||||
|
||||
const EventEmitter = require('events').EventEmitter
|
||||
const { EventEmitter } = require('events')
|
||||
|
||||
const emitter = new EventEmitter()
|
||||
|
||||
const removeAllListeners = emitter.removeAllListeners.bind(emitter)
|
||||
emitter.removeAllListeners = function (...args) {
|
||||
if (args.length === 0) {
|
||||
throw new Error('Removing all listeners from ipcMain will make Electron internals stop working. Please specify a event name')
|
||||
}
|
||||
removeAllListeners(...args)
|
||||
}
|
||||
|
||||
// Do not throw exception when channel name is "error".
|
||||
emitter.on('error', () => {})
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ module.exports = [
|
|||
{ name: 'BrowserView', file: 'browser-view' },
|
||||
{ name: 'BrowserWindow', file: 'browser-window' },
|
||||
{ name: 'contentTracing', file: 'content-tracing' },
|
||||
{ name: 'crashReporter', file: 'crash-reporter' },
|
||||
{ name: 'dialog', file: 'dialog' },
|
||||
{ name: 'globalShortcut', file: 'global-shortcut' },
|
||||
{ name: 'ipcMain', file: 'ipc-main' },
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use strict'
|
||||
|
||||
const { ipcMain } = require('electron')
|
||||
const ipcMain = require('@electron/internal/browser/ipc-main-internal')
|
||||
|
||||
// The history operation in renderer is redirected to browser.
|
||||
ipcMain.on('ELECTRON_NAVIGATION_CONTROLLER', function (event, method, ...args) {
|
||||
|
|
|
@ -6,6 +6,7 @@ const path = require('path')
|
|||
const url = require('url')
|
||||
const { app, ipcMain, session, NavigationController, deprecate } = electron
|
||||
|
||||
const ipcMainInternal = require('@electron/internal/browser/ipc-main-internal')
|
||||
const errorUtils = require('@electron/internal/common/error-utils')
|
||||
|
||||
// session is not used here, the purpose is to make sure session is initalized
|
||||
|
@ -98,12 +99,45 @@ Object.setPrototypeOf(WebContents.prototype, NavigationController.prototype)
|
|||
// WebContents::send(channel, args..)
|
||||
// WebContents::sendToAll(channel, args..)
|
||||
WebContents.prototype.send = function (channel, ...args) {
|
||||
if (channel == null) throw new Error('Missing required channel argument')
|
||||
return this._send(false, channel, args)
|
||||
if (typeof channel !== 'string') {
|
||||
throw new Error('Missing required channel argument')
|
||||
}
|
||||
|
||||
const internal = false
|
||||
const sendToAll = false
|
||||
|
||||
return this._send(internal, sendToAll, channel, args)
|
||||
}
|
||||
WebContents.prototype.sendToAll = function (channel, ...args) {
|
||||
if (channel == null) throw new Error('Missing required channel argument')
|
||||
return this._send(true, channel, args)
|
||||
if (typeof channel !== 'string') {
|
||||
throw new Error('Missing required channel argument')
|
||||
}
|
||||
|
||||
const internal = false
|
||||
const sendToAll = true
|
||||
|
||||
return this._send(internal, sendToAll, channel, args)
|
||||
}
|
||||
|
||||
WebContents.prototype._sendInternal = function (channel, ...args) {
|
||||
if (typeof channel !== 'string') {
|
||||
throw new Error('Missing required channel argument')
|
||||
}
|
||||
|
||||
const internal = true
|
||||
const sendToAll = false
|
||||
|
||||
return this._send(internal, sendToAll, channel, args)
|
||||
}
|
||||
WebContents.prototype._sendInternalToAll = function (channel, ...args) {
|
||||
if (typeof channel !== 'string') {
|
||||
throw new Error('Missing required channel argument')
|
||||
}
|
||||
|
||||
const internal = true
|
||||
const sendToAll = true
|
||||
|
||||
return this._send(internal, sendToAll, channel, args)
|
||||
}
|
||||
|
||||
// Following methods are mapped to webFrame.
|
||||
|
@ -116,8 +150,7 @@ const webFrameMethods = [
|
|||
|
||||
const asyncWebFrameMethods = function (requestId, method, callback, ...args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', requestId, method, args)
|
||||
ipcMain.once(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, function (event, error, result) {
|
||||
ipcMainInternal.once(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, function (event, error, result) {
|
||||
if (error == null) {
|
||||
if (typeof callback === 'function') callback(result)
|
||||
resolve(result)
|
||||
|
@ -125,12 +158,13 @@ const asyncWebFrameMethods = function (requestId, method, callback, ...args) {
|
|||
reject(errorUtils.deserialize(error))
|
||||
}
|
||||
})
|
||||
this._sendInternal('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', requestId, method, args)
|
||||
})
|
||||
}
|
||||
|
||||
for (const method of webFrameMethods) {
|
||||
WebContents.prototype[method] = function (...args) {
|
||||
this.send('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, args)
|
||||
this._sendInternal('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, args)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,6 +311,19 @@ WebContents.prototype._init = function () {
|
|||
ipcMain.emit(channel, event, ...args)
|
||||
})
|
||||
|
||||
this.on('ipc-internal-message', function (event, [channel, ...args]) {
|
||||
ipcMainInternal.emit(channel, event, ...args)
|
||||
})
|
||||
this.on('ipc-internal-message-sync', function (event, [channel, ...args]) {
|
||||
Object.defineProperty(event, 'returnValue', {
|
||||
set: function (value) {
|
||||
return event.sendReply([value])
|
||||
},
|
||||
get: function () {}
|
||||
})
|
||||
ipcMainInternal.emit(channel, event, ...args)
|
||||
})
|
||||
|
||||
// Handle context menu action request from pepper plugin.
|
||||
this.on('pepper-context-menu', function (event, params, callback) {
|
||||
// Access Menu via electron.Menu to prevent circular require.
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
'use strict'
|
||||
|
||||
const { app, ipcMain, webContents, BrowserWindow } = require('electron')
|
||||
const { app, webContents, BrowserWindow } = require('electron')
|
||||
const { getAllWebContents } = process.atomBinding('web_contents')
|
||||
const renderProcessPreferences = process.atomBinding('render_process_preferences').forAllWebContents()
|
||||
const ipcMain = require('@electron/internal/browser/ipc-main-internal')
|
||||
|
||||
const { Buffer } = require('buffer')
|
||||
const fs = require('fs')
|
||||
|
@ -108,7 +109,7 @@ const removeBackgroundPages = function (manifest) {
|
|||
|
||||
const sendToBackgroundPages = function (...args) {
|
||||
for (const page of Object.values(backgroundPages)) {
|
||||
page.webContents.sendToAll(...args)
|
||||
page.webContents._sendInternalToAll(...args)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,9 +161,9 @@ ipcMain.on('CHROME_RUNTIME_CONNECT', function (event, extensionId, connectInfo)
|
|||
|
||||
event.sender.once('render-view-deleted', () => {
|
||||
if (page.webContents.isDestroyed()) return
|
||||
page.webContents.sendToAll(`CHROME_PORT_DISCONNECT_${portId}`)
|
||||
page.webContents._sendInternalToAll(`CHROME_PORT_DISCONNECT_${portId}`)
|
||||
})
|
||||
page.webContents.sendToAll(`CHROME_RUNTIME_ONCONNECT_${extensionId}`, event.sender.id, portId, connectInfo)
|
||||
page.webContents._sendInternalToAll(`CHROME_RUNTIME_ONCONNECT_${extensionId}`, event.sender.id, portId, connectInfo)
|
||||
})
|
||||
|
||||
ipcMain.on('CHROME_I18N_MANIFEST', function (event, extensionId) {
|
||||
|
@ -177,9 +178,9 @@ ipcMain.on('CHROME_RUNTIME_SENDMESSAGE', function (event, extensionId, message,
|
|||
return
|
||||
}
|
||||
|
||||
page.webContents.sendToAll(`CHROME_RUNTIME_ONMESSAGE_${extensionId}`, event.sender.id, message, resultID)
|
||||
page.webContents._sendInternalToAll(`CHROME_RUNTIME_ONMESSAGE_${extensionId}`, event.sender.id, message, resultID)
|
||||
ipcMain.once(`CHROME_RUNTIME_ONMESSAGE_RESULT_${resultID}`, (event, result) => {
|
||||
event.sender.send(`CHROME_RUNTIME_SENDMESSAGE_RESULT_${originResultID}`, result)
|
||||
event.sender._sendInternal(`CHROME_RUNTIME_SENDMESSAGE_RESULT_${originResultID}`, result)
|
||||
})
|
||||
resultID++
|
||||
})
|
||||
|
@ -193,9 +194,9 @@ ipcMain.on('CHROME_TABS_SEND_MESSAGE', function (event, tabId, extensionId, isBa
|
|||
|
||||
const senderTabId = isBackgroundPage ? null : event.sender.id
|
||||
|
||||
contents.sendToAll(`CHROME_RUNTIME_ONMESSAGE_${extensionId}`, senderTabId, message, resultID)
|
||||
contents._sendInternalToAll(`CHROME_RUNTIME_ONMESSAGE_${extensionId}`, senderTabId, message, resultID)
|
||||
ipcMain.once(`CHROME_RUNTIME_ONMESSAGE_RESULT_${resultID}`, (event, result) => {
|
||||
event.sender.send(`CHROME_TABS_SEND_MESSAGE_RESULT_${originResultID}`, result)
|
||||
event.sender._sendInternal(`CHROME_TABS_SEND_MESSAGE_RESULT_${originResultID}`, result)
|
||||
})
|
||||
resultID++
|
||||
})
|
||||
|
@ -217,7 +218,7 @@ ipcMain.on('CHROME_TABS_EXECUTESCRIPT', function (event, requestId, tabId, exten
|
|||
url = `chrome-extension://${extensionId}/${String(Math.random()).substr(2, 8)}.js`
|
||||
}
|
||||
|
||||
contents.send('CHROME_TABS_EXECUTESCRIPT', event.sender.id, requestId, extensionId, url, code)
|
||||
contents._sendInternal('CHROME_TABS_EXECUTESCRIPT', event.sender.id, requestId, extensionId, url, code)
|
||||
})
|
||||
|
||||
// Transfer the content scripts to renderer.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use strict'
|
||||
|
||||
const { ipcMain } = require('electron')
|
||||
const ipcMain = require('@electron/internal/browser/ipc-main-internal')
|
||||
const { desktopCapturer } = process.atomBinding('desktop_capturer')
|
||||
|
||||
const deepEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b)
|
||||
|
@ -49,14 +49,16 @@ desktopCapturer.emit = (event, name, sources) => {
|
|||
})
|
||||
|
||||
if (handledWebContents) {
|
||||
handledWebContents.send(capturerResult(handledRequest.id), result)
|
||||
handledWebContents._sendInternal(capturerResult(handledRequest.id), result)
|
||||
}
|
||||
|
||||
// Check the queue to see whether there is another identical request & handle
|
||||
requestsQueue.forEach(request => {
|
||||
const webContents = request.webContents
|
||||
if (deepEqual(handledRequest.options, request.options)) {
|
||||
if (webContents) webContents.send(capturerResult(request.id), result)
|
||||
if (webContents) {
|
||||
webContents._sendInternal(capturerResult(request.id), result)
|
||||
}
|
||||
} else {
|
||||
unhandledRequestsQueue.push(request)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict'
|
||||
|
||||
const { ipcMain, webContents } = require('electron')
|
||||
const { webContents } = require('electron')
|
||||
const ipcMain = require('@electron/internal/browser/ipc-main-internal')
|
||||
const parseFeaturesString = require('@electron/internal/common/parse-features-string')
|
||||
|
||||
// Doesn't exist in early initialization.
|
||||
|
@ -118,7 +119,7 @@ const createGuest = function (embedder, params) {
|
|||
|
||||
const sendToEmbedder = (channel, ...args) => {
|
||||
if (!embedder.isDestroyed()) {
|
||||
embedder.send(`${channel}-${guest.viewInstanceId}`, ...args)
|
||||
embedder._sendInternal(`${channel}-${guest.viewInstanceId}`, ...args)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,7 +143,7 @@ const createGuest = function (embedder, params) {
|
|||
guest.on('dom-ready', function () {
|
||||
const guestInstance = guestInstances[guestInstanceId]
|
||||
if (guestInstance != null && guestInstance.visibilityState != null) {
|
||||
guest.send('ELECTRON_GUEST_INSTANCE_VISIBILITY_CHANGE', guestInstance.visibilityState)
|
||||
guest._sendInternal('ELECTRON_GUEST_INSTANCE_VISIBILITY_CHANGE', guestInstance.visibilityState)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -201,7 +202,7 @@ const attachGuest = function (event, embedderFrameId, elementInstanceId, guestIn
|
|||
// Remove guest from embedder if moving across web views
|
||||
if (guest.viewInstanceId !== params.instanceId) {
|
||||
webViewManager.removeGuest(guestInstance.embedder, guestInstanceId)
|
||||
guestInstance.embedder.send(`ELECTRON_GUEST_VIEW_INTERNAL_DESTROY_GUEST-${guest.viewInstanceId}`)
|
||||
guestInstance.embedder._sendInternal(`ELECTRON_GUEST_VIEW_INTERNAL_DESTROY_GUEST-${guest.viewInstanceId}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,7 +303,7 @@ const watchEmbedder = function (embedder) {
|
|||
const guestInstance = guestInstances[guestInstanceId]
|
||||
guestInstance.visibilityState = visibilityState
|
||||
if (guestInstance.embedder === embedder) {
|
||||
guestInstance.guest.send('ELECTRON_GUEST_INSTANCE_VISIBILITY_CHANGE', visibilityState)
|
||||
guestInstance.guest._sendInternal('ELECTRON_GUEST_INSTANCE_VISIBILITY_CHANGE', visibilityState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -325,7 +326,7 @@ const watchEmbedder = function (embedder) {
|
|||
}
|
||||
|
||||
ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST', function (event, params, requestId) {
|
||||
event.sender.send(`ELECTRON_RESPONSE_${requestId}`, createGuest(event.sender, params))
|
||||
event.sender._sendInternal(`ELECTRON_RESPONSE_${requestId}`, createGuest(event.sender, params))
|
||||
})
|
||||
|
||||
ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST_SYNC', function (event, params) {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
'use strict'
|
||||
|
||||
const { BrowserWindow, ipcMain, webContents } = require('electron')
|
||||
const { BrowserWindow, webContents } = require('electron')
|
||||
const { isSameOrigin } = process.atomBinding('v8_util')
|
||||
const ipcMain = require('@electron/internal/browser/ipc-main-internal')
|
||||
const parseFeaturesString = require('@electron/internal/common/parse-features-string')
|
||||
|
||||
const hasProp = {}.hasOwnProperty
|
||||
|
@ -87,7 +88,7 @@ const setupGuest = function (embedder, frameName, guest, options) {
|
|||
guest.destroy()
|
||||
}
|
||||
const closedByUser = function () {
|
||||
embedder.send('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_CLOSED_' + guestId)
|
||||
embedder._sendInternal('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_CLOSED_' + guestId)
|
||||
embedder.removeListener('render-view-deleted', closedByEmbedder)
|
||||
}
|
||||
embedder.once('render-view-deleted', closedByEmbedder)
|
||||
|
@ -320,7 +321,7 @@ ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', function (event,
|
|||
// postMessage across origins is useful and not harmful.
|
||||
if (targetOrigin === '*' || isSameOrigin(guestContents.getURL(), targetOrigin)) {
|
||||
const sourceId = event.sender.id
|
||||
guestContents.send('ELECTRON_GUEST_WINDOW_POSTMESSAGE', sourceId, message, sourceOrigin)
|
||||
guestContents._sendInternal('ELECTRON_GUEST_WINDOW_POSTMESSAGE', sourceId, message, sourceOrigin)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
10
lib/browser/ipc-main-internal.js
Normal file
10
lib/browser/ipc-main-internal.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
'use strict'
|
||||
|
||||
const { EventEmitter } = require('events')
|
||||
|
||||
const emitter = new EventEmitter()
|
||||
|
||||
// Do not throw exception when channel name is "error".
|
||||
emitter.on('error', () => {})
|
||||
|
||||
module.exports = emitter
|
|
@ -8,8 +8,9 @@ const os = require('os')
|
|||
const path = require('path')
|
||||
const v8Util = process.atomBinding('v8_util')
|
||||
|
||||
const { ipcMain, isPromise } = electron
|
||||
const { isPromise } = electron
|
||||
|
||||
const ipcMain = require('@electron/internal/browser/ipc-main-internal')
|
||||
const objectsRegistry = require('@electron/internal/browser/objects-registry')
|
||||
const bufferUtils = require('@electron/internal/common/buffer-utils')
|
||||
const errorUtils = require('@electron/internal/common/error-utils')
|
||||
|
@ -215,7 +216,7 @@ const unwrapArgs = function (sender, contextId, args) {
|
|||
const processId = sender.getProcessId()
|
||||
const callIntoRenderer = function (...args) {
|
||||
if (!sender.isDestroyed() && processId === sender.getProcessId()) {
|
||||
sender.send('ELECTRON_RENDERER_CALLBACK', contextId, meta.id, valueToMeta(sender, contextId, args))
|
||||
sender._sendInternal('ELECTRON_RENDERER_CALLBACK', contextId, meta.id, valueToMeta(sender, contextId, args))
|
||||
} else {
|
||||
removeRemoteListenersAndLogWarning(this, meta, callIntoRenderer)
|
||||
}
|
||||
|
@ -390,7 +391,7 @@ ipcMain.on('ELECTRON_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', function (event, request
|
|||
}, error => {
|
||||
return [errorUtils.serialize(error)]
|
||||
}).then(responseArgs => {
|
||||
event.sender.send(`ELECTRON_RENDERER_ASYNC_CALL_TO_GUEST_VIEW_RESPONSE_${requestId}`, ...responseArgs)
|
||||
event.sender._sendInternal(`ELECTRON_RENDERER_ASYNC_CALL_TO_GUEST_VIEW_RESPONSE_${requestId}`, ...responseArgs)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -424,7 +425,7 @@ const getTempDirectory = function () {
|
|||
}
|
||||
}
|
||||
|
||||
ipcMain.on('ELECTRON_CRASH_REPORTER_INIT', function (event, options) {
|
||||
const crashReporterInit = function (options) {
|
||||
const productName = options.productName || electron.app.getName()
|
||||
const crashesDirectory = path.join(getTempDirectory(), `${productName} Crashes`)
|
||||
|
||||
|
@ -445,11 +446,19 @@ ipcMain.on('ELECTRON_CRASH_REPORTER_INIT', function (event, options) {
|
|||
})
|
||||
}
|
||||
|
||||
event.returnValue = {
|
||||
return {
|
||||
productName,
|
||||
crashesDirectory,
|
||||
appVersion: electron.app.getVersion()
|
||||
}
|
||||
}
|
||||
|
||||
ipcMain.on('ELECTRON_CRASH_REPORTER_INIT', function (event, options) {
|
||||
try {
|
||||
event.returnValue = [null, crashReporterInit(options)]
|
||||
} catch (error) {
|
||||
event.returnValue = [errorUtils.serialize(error)]
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('ELECTRON_BROWSER_SANDBOX_LOAD', function (event) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue