2016-03-24 20:34:36 +00:00
'use strict'
2016-01-13 09:07:18 +00:00
2016-03-24 20:34:36 +00:00
const electron = require ( 'electron' )
2018-09-13 16:10:51 +00:00
const { EventEmitter } = require ( 'events' )
2018-05-21 12:56:05 +00:00
const fs = require ( 'fs' )
2019-03-28 10:38:51 +00:00
const path = require ( 'path' )
2019-03-08 10:21:41 +00:00
const util = require ( 'util' )
2019-03-16 00:32:04 +00:00
2019-03-18 19:37:06 +00:00
const v8Util = process . electronBinding ( 'v8_util' )
const eventBinding = process . electronBinding ( 'event' )
const clipboard = process . electronBinding ( 'clipboard' )
2017-01-24 23:05:34 +00:00
2018-10-06 11:48:00 +00:00
const { isPromise } = electron
2016-05-11 07:15:32 +00:00
2019-02-05 20:56:44 +00:00
const { crashReporterInit } = require ( '@electron/internal/browser/crash-reporter-init' )
2019-02-04 22:49:53 +00:00
const { ipcMainInternal } = require ( '@electron/internal/browser/ipc-main-internal' )
2019-02-05 20:56:44 +00:00
const ipcMainUtils = require ( '@electron/internal/browser/ipc-main-internal-utils' )
2018-09-20 03:43:26 +00:00
const objectsRegistry = require ( '@electron/internal/browser/objects-registry' )
2019-01-03 18:31:10 +00:00
const guestViewManager = require ( '@electron/internal/browser/guest-view-manager' )
2018-09-20 03:43:26 +00:00
const bufferUtils = require ( '@electron/internal/common/buffer-utils' )
2018-09-26 05:44:55 +00:00
const errorUtils = require ( '@electron/internal/common/error-utils' )
2019-03-16 00:32:04 +00:00
const clipboardUtils = require ( '@electron/internal/common/clipboard-utils' )
2019-03-28 10:38:51 +00:00
const { isParentDir } = require ( '@electron/internal/common/path-utils' )
2016-01-12 02:40:23 +00:00
2016-05-27 17:46:02 +00:00
const hasProp = { } . hasOwnProperty
2016-02-22 02:52:21 +00:00
// The internal properties of Function.
const FUNCTION _PROPERTIES = [
2016-03-24 20:34:36 +00:00
'length' , 'name' , 'arguments' , 'caller' , 'prototype'
]
2016-02-22 02:52:21 +00:00
2016-02-22 06:36:50 +00:00
// The remote functions in renderer processes.
2016-04-26 07:10:27 +00:00
// id => Function
2018-08-23 23:27:52 +00:00
const rendererFunctions = v8Util . createDoubleIDWeakMap ( )
2016-02-22 06:36:50 +00:00
2016-02-22 02:52:21 +00:00
// Return the description of object's members:
2018-08-23 23:27:52 +00:00
const getObjectMembers = function ( object ) {
2016-03-24 20:34:36 +00:00
let names = Object . getOwnPropertyNames ( object )
2016-02-22 02:52:21 +00:00
// For Function, we should not override following properties even though they
// are "own" properties.
if ( typeof object === 'function' ) {
names = names . filter ( ( name ) => {
2016-03-24 20:34:36 +00:00
return ! FUNCTION _PROPERTIES . includes ( name )
} )
2016-02-22 02:52:21 +00:00
}
// Map properties to descriptors.
return names . map ( ( name ) => {
2018-10-02 01:56:31 +00:00
const descriptor = Object . getOwnPropertyDescriptor ( object , name )
const member = { name , enumerable : descriptor . enumerable , writable : false }
2016-02-22 02:52:21 +00:00
if ( descriptor . get === undefined && typeof object [ name ] === 'function' ) {
2016-03-24 20:34:36 +00:00
member . type = 'method'
2016-02-22 02:52:21 +00:00
} else {
2016-03-24 20:34:36 +00:00
if ( descriptor . set || descriptor . writable ) member . writable = true
member . type = 'get'
2016-02-22 02:52:21 +00:00
}
2016-03-24 20:34:36 +00:00
return member
} )
}
2016-02-22 02:52:21 +00:00
// Return the description of object's prototype.
2018-08-23 23:27:52 +00:00
const getObjectPrototype = function ( object ) {
2018-10-02 01:56:31 +00:00
const proto = Object . getPrototypeOf ( object )
2016-03-24 20:34:36 +00:00
if ( proto === null || proto === Object . prototype ) return null
2016-02-22 02:52:21 +00:00
return {
2016-03-04 23:57:21 +00:00
members : getObjectMembers ( proto ) ,
2016-03-24 20:34:36 +00:00
proto : getObjectPrototype ( proto )
}
}
2016-02-22 02:52:21 +00:00
2016-01-14 18:35:29 +00:00
// Convert a real value into meta data.
2018-08-23 23:27:52 +00:00
const valueToMeta = function ( sender , contextId , value , optimizeSimpleObject = false ) {
2016-04-20 05:26:49 +00:00
// Determine the type of value.
2016-06-21 00:54:15 +00:00
const meta = { type : typeof value }
2016-04-20 05:32:32 +00:00
if ( meta . type === 'object' ) {
2016-04-20 05:26:49 +00:00
// Recognize certain types of objects.
2016-04-20 05:32:32 +00:00
if ( value === null ) {
meta . type = 'value'
2018-05-24 12:05:46 +00:00
} else if ( bufferUtils . isBuffer ( value ) ) {
2016-04-20 05:32:32 +00:00
meta . type = 'buffer'
} else if ( Array . isArray ( value ) ) {
meta . type = 'array'
} else if ( value instanceof Error ) {
meta . type = 'error'
} else if ( value instanceof Date ) {
meta . type = 'date'
2016-05-25 05:38:35 +00:00
} else if ( isPromise ( value ) ) {
2016-04-20 05:26:49 +00:00
meta . type = 'promise'
2016-05-27 17:46:02 +00:00
} else if ( hasProp . call ( value , 'callee' ) && value . length != null ) {
2016-04-20 05:26:49 +00:00
// Treat the arguments object as array.
meta . type = 'array'
} else if ( optimizeSimpleObject && v8Util . getHiddenValue ( value , 'simple' ) ) {
// Treat simple objects as value.
meta . type = 'value'
}
2016-01-12 02:40:23 +00:00
}
2016-04-20 05:26:49 +00:00
// Fill the meta object according to value's type.
2016-01-12 02:40:23 +00:00
if ( meta . type === 'array' ) {
2018-07-10 08:15:40 +00:00
meta . members = value . map ( ( el ) => valueToMeta ( sender , contextId , el , optimizeSimpleObject ) )
2016-01-12 02:40:23 +00:00
} else if ( meta . type === 'object' || meta . type === 'function' ) {
2016-04-20 05:26:49 +00:00
meta . name = value . constructor ? value . constructor . name : ''
2016-01-12 02:40:23 +00:00
2016-01-14 18:44:21 +00:00
// Reference the original value if it's an object, because when it's
// passed to renderer we would assume the renderer keeps a reference of
// it.
2018-07-10 08:15:40 +00:00
meta . id = objectsRegistry . add ( sender , contextId , value )
2016-03-24 20:34:36 +00:00
meta . members = getObjectMembers ( value )
meta . proto = getObjectPrototype ( value )
2016-01-12 02:40:23 +00:00
} else if ( meta . type === 'buffer' ) {
2018-05-24 12:05:46 +00:00
meta . value = bufferUtils . bufferToMeta ( value )
2016-01-12 02:40:23 +00:00
} else if ( meta . type === 'promise' ) {
2016-06-21 00:54:15 +00:00
// Add default handler to prevent unhandled rejections in main process
// Instead they should appear in the renderer process
value . then ( function ( ) { } , function ( ) { } )
2018-07-10 08:15:40 +00:00
meta . then = valueToMeta ( sender , contextId , function ( onFulfilled , onRejected ) {
2016-05-23 22:07:01 +00:00
value . then ( onFulfilled , onRejected )
} )
2016-01-12 02:40:23 +00:00
} else if ( meta . type === 'error' ) {
2016-03-24 20:34:36 +00:00
meta . members = plainObjectToMeta ( value )
2016-01-12 02:40:23 +00:00
2016-01-14 18:35:29 +00:00
// Error.name is not part of own properties.
2016-01-12 02:40:23 +00:00
meta . members . push ( {
name : 'name' ,
value : value . name
2016-03-24 20:34:36 +00:00
} )
2016-01-12 02:40:23 +00:00
} else if ( meta . type === 'date' ) {
2016-03-24 20:34:36 +00:00
meta . value = value . getTime ( )
2016-01-12 02:40:23 +00:00
} else {
2016-03-24 20:34:36 +00:00
meta . type = 'value'
meta . value = value
2016-01-12 02:40:23 +00:00
}
2016-03-24 20:34:36 +00:00
return meta
}
2016-01-12 02:40:23 +00:00
2016-01-14 18:35:29 +00:00
// Convert object to meta by value.
2016-06-21 00:54:15 +00:00
const plainObjectToMeta = function ( obj ) {
2016-03-24 20:34:36 +00:00
return Object . getOwnPropertyNames ( obj ) . map ( function ( name ) {
2016-01-12 02:40:23 +00:00
return {
name : name ,
value : obj [ name ]
2016-03-24 20:34:36 +00:00
}
} )
}
2016-01-12 02:40:23 +00:00
2016-01-14 18:35:29 +00:00
// Convert Error into meta data.
2018-12-12 21:31:16 +00:00
const exceptionToMeta = function ( error ) {
2016-01-12 02:40:23 +00:00
return {
type : 'exception' ,
2018-09-26 05:44:55 +00:00
value : errorUtils . serialize ( error )
2016-03-24 20:34:36 +00:00
}
}
2016-01-12 02:40:23 +00:00
2016-11-17 17:55:13 +00:00
const throwRPCError = function ( message ) {
const error = new Error ( message )
error . code = 'EBADRPC'
2016-11-17 18:22:29 +00:00
error . errno = - 72
2016-11-17 17:55:13 +00:00
throw error
}
2018-10-31 15:26:57 +00:00
const removeRemoteListenersAndLogWarning = ( sender , callIntoRenderer ) => {
const location = v8Util . getHiddenValue ( callIntoRenderer , 'location' )
2017-01-06 21:09:48 +00:00
let message = ` Attempting to call a function in a renderer window that has been closed or released. ` +
2018-10-31 15:26:57 +00:00
` \n Function provided here: ${ location } `
2017-01-06 21:09:48 +00:00
2018-05-21 01:00:56 +00:00
if ( sender instanceof EventEmitter ) {
2017-01-19 00:09:46 +00:00
const remoteEvents = sender . eventNames ( ) . filter ( ( eventName ) => {
return sender . listeners ( eventName ) . includes ( callIntoRenderer )
2017-01-13 20:28:11 +00:00
} )
2017-01-19 00:09:46 +00:00
if ( remoteEvents . length > 0 ) {
message += ` \n Remote event names: ${ remoteEvents . join ( ', ' ) } `
remoteEvents . forEach ( ( eventName ) => {
sender . removeListener ( eventName , callIntoRenderer )
} )
}
2017-01-06 21:09:48 +00:00
}
2017-01-19 00:09:46 +00:00
console . warn ( message )
2017-01-06 21:09:48 +00:00
}
2016-01-14 18:35:29 +00:00
// Convert array of meta data from renderer into array of real values.
2018-12-10 00:37:42 +00:00
const unwrapArgs = function ( sender , frameId , contextId , args ) {
2016-06-21 00:54:15 +00:00
const metaToValue = function ( meta ) {
2016-01-12 02:40:23 +00:00
switch ( meta . type ) {
case 'value' :
2016-03-24 20:34:36 +00:00
return meta . value
2016-01-12 02:40:23 +00:00
case 'remote-object' :
2016-03-24 20:34:36 +00:00
return objectsRegistry . get ( meta . id )
2016-01-12 02:40:23 +00:00
case 'array' :
2018-12-10 00:37:42 +00:00
return unwrapArgs ( sender , frameId , contextId , meta . value )
2016-01-12 02:40:23 +00:00
case 'buffer' :
2018-05-24 12:05:46 +00:00
return bufferUtils . metaToBuffer ( meta . value )
2016-01-12 02:40:23 +00:00
case 'date' :
2016-03-24 20:34:36 +00:00
return new Date ( meta . value )
2016-01-12 02:40:23 +00:00
case 'promise' :
return Promise . resolve ( {
then : metaToValue ( meta . then )
2016-03-24 20:34:36 +00:00
} )
2016-03-25 19:28:43 +00:00
case 'object' : {
2018-10-02 01:56:31 +00:00
const ret = { }
2016-03-24 20:34:36 +00:00
Object . defineProperty ( ret . constructor , 'name' , { value : meta . name } )
2016-02-22 03:51:41 +00:00
2018-09-13 16:10:51 +00:00
for ( const { name , value } of meta . members ) {
2018-06-27 01:00:05 +00:00
ret [ name ] = metaToValue ( value )
2016-03-24 20:34:36 +00:00
}
return ret
2016-03-25 19:28:43 +00:00
}
2016-01-12 02:40:23 +00:00
case 'function-with-return-value' :
2018-06-27 01:00:05 +00:00
const returnValue = metaToValue ( meta . value )
2016-03-24 20:34:36 +00:00
return function ( ) {
return returnValue
}
2016-03-25 19:28:43 +00:00
case 'function' : {
2018-07-10 08:15:40 +00:00
// Merge contextId and meta.id, since meta.id can be the same in
2016-04-26 07:10:27 +00:00
// different webContents.
2018-07-10 08:15:40 +00:00
const objectId = [ contextId , meta . id ]
2016-04-26 07:10:27 +00:00
2016-01-14 18:35:29 +00:00
// Cache the callbacks in renderer.
2016-04-26 07:10:27 +00:00
if ( rendererFunctions . has ( objectId ) ) {
return rendererFunctions . get ( objectId )
2016-01-12 02:40:23 +00:00
}
2016-01-13 09:07:18 +00:00
2018-10-02 01:56:31 +00:00
const callIntoRenderer = function ( ... args ) {
2018-12-10 00:37:42 +00:00
let succeed = false
2018-10-31 15:26:57 +00:00
if ( ! sender . isDestroyed ( ) ) {
2018-12-10 00:37:42 +00:00
succeed = sender . _sendToFrameInternal ( frameId , 'ELECTRON_RENDERER_CALLBACK' , contextId , meta . id , valueToMeta ( sender , contextId , args ) )
}
if ( ! succeed ) {
2018-10-31 15:26:57 +00:00
removeRemoteListenersAndLogWarning ( this , callIntoRenderer )
2016-03-24 20:34:36 +00:00
}
}
2018-10-31 15:26:57 +00:00
v8Util . setHiddenValue ( callIntoRenderer , 'location' , meta . location )
2016-11-09 13:05:46 +00:00
Object . defineProperty ( callIntoRenderer , 'length' , { value : meta . length } )
2016-04-26 07:10:27 +00:00
2018-07-10 08:15:40 +00:00
v8Util . setRemoteCallbackFreer ( callIntoRenderer , contextId , meta . id , sender )
2016-04-26 07:10:27 +00:00
rendererFunctions . set ( objectId , callIntoRenderer )
2016-03-24 20:34:36 +00:00
return callIntoRenderer
2016-03-25 19:28:43 +00:00
}
2016-01-12 02:40:23 +00:00
default :
2016-03-24 20:34:36 +00:00
throw new TypeError ( ` Unknown type: ${ meta . type } ` )
2016-01-12 02:40:23 +00:00
}
2016-03-24 20:34:36 +00:00
}
return args . map ( metaToValue )
}
2016-01-12 02:40:23 +00:00
2019-02-11 20:42:37 +00:00
const isRemoteModuleEnabledCache = new WeakMap ( )
const isRemoteModuleEnabled = function ( contents ) {
if ( ! isRemoteModuleEnabledCache . has ( contents ) ) {
isRemoteModuleEnabledCache . set ( contents , contents . _isRemoteModuleEnabled ( ) )
}
return isRemoteModuleEnabledCache . get ( contents )
}
2018-08-23 23:27:52 +00:00
const handleRemoteCommand = function ( channel , handler ) {
2019-02-04 22:49:53 +00:00
ipcMainInternal . on ( channel , ( event , contextId , ... args ) => {
2018-08-23 23:27:52 +00:00
let returnValue
2019-02-11 20:42:37 +00:00
if ( ! isRemoteModuleEnabled ( event . sender ) ) {
2018-10-13 17:50:07 +00:00
event . returnValue = null
return
}
2018-08-23 23:27:52 +00:00
try {
returnValue = handler ( event , contextId , ... args )
} catch ( error ) {
2018-12-12 21:31:16 +00:00
returnValue = exceptionToMeta ( error )
2018-08-23 23:27:52 +00:00
}
2018-10-13 17:50:07 +00:00
2018-08-23 23:27:52 +00:00
if ( returnValue !== undefined ) {
event . returnValue = returnValue
}
} )
}
2016-01-12 02:40:23 +00:00
2018-10-31 15:26:57 +00:00
handleRemoteCommand ( 'ELECTRON_BROWSER_WRONG_CONTEXT_ERROR' , function ( event , contextId , passedContextId , id ) {
const objectId = [ passedContextId , id ]
if ( ! rendererFunctions . has ( objectId ) ) {
// Do nothing if the error has already been reported before.
return
}
removeRemoteListenersAndLogWarning ( event . sender , rendererFunctions . get ( objectId ) )
} )
2018-10-18 03:36:45 +00:00
handleRemoteCommand ( 'ELECTRON_BROWSER_REQUIRE' , function ( event , contextId , moduleName ) {
const customEvent = eventBinding . createWithSender ( event . sender )
event . sender . emit ( 'remote-require' , customEvent , moduleName )
2019-01-08 22:27:56 +00:00
if ( customEvent . returnValue === undefined ) {
if ( customEvent . defaultPrevented ) {
throw new Error ( ` Blocked remote.require(' ${ moduleName } ') ` )
} else {
customEvent . returnValue = process . mainModule . require ( moduleName )
2018-10-18 03:36:45 +00:00
}
}
return valueToMeta ( event . sender , contextId , customEvent . returnValue )
2016-03-24 20:34:36 +00:00
} )
2016-01-12 02:40:23 +00:00
2019-01-08 22:27:56 +00:00
handleRemoteCommand ( 'ELECTRON_BROWSER_GET_BUILTIN' , function ( event , contextId , moduleName ) {
const customEvent = eventBinding . createWithSender ( event . sender )
event . sender . emit ( 'remote-get-builtin' , customEvent , moduleName )
if ( customEvent . returnValue === undefined ) {
if ( customEvent . defaultPrevented ) {
throw new Error ( ` Blocked remote.getBuiltin(' ${ moduleName } ') ` )
} else {
customEvent . returnValue = electron [ moduleName ]
}
}
return valueToMeta ( event . sender , contextId , customEvent . returnValue )
2016-03-24 20:34:36 +00:00
} )
2016-01-12 02:40:23 +00:00
2018-10-18 03:36:45 +00:00
handleRemoteCommand ( 'ELECTRON_BROWSER_GLOBAL' , function ( event , contextId , globalName ) {
const customEvent = eventBinding . createWithSender ( event . sender )
event . sender . emit ( 'remote-get-global' , customEvent , globalName )
2019-01-08 22:27:56 +00:00
if ( customEvent . returnValue === undefined ) {
if ( customEvent . defaultPrevented ) {
throw new Error ( ` Blocked remote.getGlobal(' ${ globalName } ') ` )
} else {
customEvent . returnValue = global [ globalName ]
2018-10-18 03:36:45 +00:00
}
}
return valueToMeta ( event . sender , contextId , customEvent . returnValue )
2016-03-24 20:34:36 +00:00
} )
2016-01-12 02:40:23 +00:00
2018-08-23 23:27:52 +00:00
handleRemoteCommand ( 'ELECTRON_BROWSER_CURRENT_WINDOW' , function ( event , contextId ) {
2019-01-08 22:27:56 +00:00
const customEvent = eventBinding . createWithSender ( event . sender )
event . sender . emit ( 'remote-get-current-window' , customEvent )
if ( customEvent . returnValue === undefined ) {
if ( customEvent . defaultPrevented ) {
throw new Error ( 'Blocked remote.getCurrentWindow()' )
} else {
customEvent . returnValue = event . sender . getOwnerBrowserWindow ( )
}
}
return valueToMeta ( event . sender , contextId , customEvent . returnValue )
2016-03-24 20:34:36 +00:00
} )
2016-01-12 02:40:23 +00:00
2018-08-23 23:27:52 +00:00
handleRemoteCommand ( 'ELECTRON_BROWSER_CURRENT_WEB_CONTENTS' , function ( event , contextId ) {
2019-01-08 22:27:56 +00:00
const customEvent = eventBinding . createWithSender ( event . sender )
event . sender . emit ( 'remote-get-current-web-contents' , customEvent )
if ( customEvent . returnValue === undefined ) {
if ( customEvent . defaultPrevented ) {
throw new Error ( 'Blocked remote.getCurrentWebContents()' )
} else {
customEvent . returnValue = event . sender
}
}
return valueToMeta ( event . sender , contextId , customEvent . returnValue )
2018-08-23 23:27:52 +00:00
} )
2016-01-12 02:40:23 +00:00
2018-08-23 23:27:52 +00:00
handleRemoteCommand ( 'ELECTRON_BROWSER_CONSTRUCTOR' , function ( event , contextId , id , args ) {
2018-12-10 00:37:42 +00:00
args = unwrapArgs ( event . sender , event . frameId , contextId , args )
2018-10-02 01:56:31 +00:00
const constructor = objectsRegistry . get ( id )
2016-11-17 17:55:13 +00:00
2018-08-23 23:27:52 +00:00
if ( constructor == null ) {
throwRPCError ( ` Cannot call constructor on missing remote object ${ id } ` )
2016-01-12 02:40:23 +00:00
}
2018-08-23 23:27:52 +00:00
return valueToMeta ( event . sender , contextId , new constructor ( ... args ) )
} )
2016-11-17 17:55:13 +00:00
2018-08-23 23:27:52 +00:00
handleRemoteCommand ( 'ELECTRON_BROWSER_FUNCTION_CALL' , function ( event , contextId , id , args ) {
2018-12-10 00:37:42 +00:00
args = unwrapArgs ( event . sender , event . frameId , contextId , args )
2018-10-02 01:56:31 +00:00
const func = objectsRegistry . get ( id )
2016-11-17 17:55:13 +00:00
2018-08-23 23:27:52 +00:00
if ( func == null ) {
throwRPCError ( ` Cannot call function on missing remote object ${ id } ` )
2016-01-12 02:40:23 +00:00
}
2019-03-19 18:59:33 +00:00
try {
return valueToMeta ( event . sender , contextId , func ( ... args ) , true )
} catch ( error ) {
const err = new Error ( ` Could not call remote function ' ${ func . name || 'anonymous' } '. Check that the function signature is correct. Underlying error: ${ error . message } ` )
err . cause = error
throw err
}
2018-08-23 23:27:52 +00:00
} )
2016-11-17 17:55:13 +00:00
2018-08-23 23:27:52 +00:00
handleRemoteCommand ( 'ELECTRON_BROWSER_MEMBER_CONSTRUCTOR' , function ( event , contextId , id , method , args ) {
2018-12-10 00:37:42 +00:00
args = unwrapArgs ( event . sender , event . frameId , contextId , args )
2018-10-02 01:56:31 +00:00
const object = objectsRegistry . get ( id )
2016-01-12 02:40:23 +00:00
2018-08-23 23:27:52 +00:00
if ( object == null ) {
throwRPCError ( ` Cannot call constructor ' ${ method } ' on missing remote object ${ id } ` )
2016-01-12 02:40:23 +00:00
}
2018-08-23 23:27:52 +00:00
return valueToMeta ( event . sender , contextId , new object [ method ] ( ... args ) )
} )
2016-11-17 17:55:13 +00:00
2018-08-23 23:27:52 +00:00
handleRemoteCommand ( 'ELECTRON_BROWSER_MEMBER_CALL' , function ( event , contextId , id , method , args ) {
2018-12-10 00:37:42 +00:00
args = unwrapArgs ( event . sender , event . frameId , contextId , args )
2019-03-19 18:59:33 +00:00
const object = objectsRegistry . get ( id )
2016-11-17 17:55:13 +00:00
2019-03-19 18:59:33 +00:00
if ( object == null ) {
throwRPCError ( ` Cannot call method ' ${ method } ' on missing remote object ${ id } ` )
2016-01-12 02:40:23 +00:00
}
2018-08-23 23:27:52 +00:00
2019-03-19 18:59:33 +00:00
try {
return valueToMeta ( event . sender , contextId , object [ method ] ( ... args ) , true )
} catch ( error ) {
const err = new Error ( ` Could not call remote method ' ${ method } '. Check that the method signature is correct. Underlying error: ${ error . message } ` )
err . cause = error
throw err
}
2016-03-24 20:34:36 +00:00
} )
2016-01-12 02:40:23 +00:00
2018-08-23 23:27:52 +00:00
handleRemoteCommand ( 'ELECTRON_BROWSER_MEMBER_SET' , function ( event , contextId , id , name , args ) {
2018-12-10 00:37:42 +00:00
args = unwrapArgs ( event . sender , event . frameId , contextId , args )
2018-10-02 01:56:31 +00:00
const obj = objectsRegistry . get ( id )
2016-11-17 17:55:13 +00:00
2018-08-23 23:27:52 +00:00
if ( obj == null ) {
throwRPCError ( ` Cannot set property ' ${ name } ' on missing remote object ${ id } ` )
2016-01-12 02:40:23 +00:00
}
2018-08-23 23:27:52 +00:00
obj [ name ] = args [ 0 ]
return null
} )
2016-11-17 20:23:00 +00:00
2018-08-23 23:27:52 +00:00
handleRemoteCommand ( 'ELECTRON_BROWSER_MEMBER_GET' , function ( event , contextId , id , name ) {
2018-10-02 01:56:31 +00:00
const obj = objectsRegistry . get ( id )
2016-11-17 20:23:00 +00:00
2018-08-23 23:27:52 +00:00
if ( obj == null ) {
throwRPCError ( ` Cannot get property ' ${ name } ' on missing remote object ${ id } ` )
2016-01-12 02:40:23 +00:00
}
2018-08-23 23:27:52 +00:00
return valueToMeta ( event . sender , contextId , obj [ name ] )
2016-03-24 20:34:36 +00:00
} )
2016-01-12 02:40:23 +00:00
2018-08-23 23:27:52 +00:00
handleRemoteCommand ( 'ELECTRON_BROWSER_DEREFERENCE' , function ( event , contextId , id ) {
2018-07-24 07:21:38 +00:00
objectsRegistry . remove ( event . sender , contextId , id )
2016-03-24 20:34:36 +00:00
} )
2016-01-12 02:40:23 +00:00
2018-08-23 23:27:52 +00:00
handleRemoteCommand ( 'ELECTRON_BROWSER_CONTEXT_RELEASE' , ( event , contextId ) => {
2018-07-24 07:21:38 +00:00
objectsRegistry . clear ( event . sender , contextId )
2018-08-23 23:27:52 +00:00
return null
2017-05-15 11:57:23 +00:00
} )
2018-08-23 23:27:52 +00:00
handleRemoteCommand ( 'ELECTRON_BROWSER_GUEST_WEB_CONTENTS' , function ( event , contextId , guestInstanceId ) {
2019-01-03 18:31:10 +00:00
const guest = guestViewManager . getGuestForWebContents ( guestInstanceId , event . sender )
2019-01-08 22:27:56 +00:00
const customEvent = eventBinding . createWithSender ( event . sender )
event . sender . emit ( 'remote-get-guest-web-contents' , customEvent , guest )
if ( customEvent . returnValue === undefined ) {
if ( customEvent . defaultPrevented ) {
throw new Error ( ` Blocked remote.getGuestForWebContents() ` )
} else {
customEvent . returnValue = guest
}
}
return valueToMeta ( event . sender , contextId , customEvent . returnValue )
2016-03-24 20:34:36 +00:00
} )
2016-01-12 02:40:23 +00:00
2016-12-02 01:34:14 +00:00
// Implements window.close()
2019-02-04 22:49:53 +00:00
ipcMainInternal . on ( 'ELECTRON_BROWSER_WINDOW_CLOSE' , function ( event ) {
2017-08-17 17:56:37 +00:00
const window = event . sender . getOwnerBrowserWindow ( )
if ( window ) {
window . close ( )
2017-08-15 21:59:48 +00:00
}
2017-08-17 17:56:37 +00:00
event . returnValue = null
2016-12-02 01:34:14 +00:00
} )
2018-05-21 12:56:05 +00:00
2019-02-26 23:48:26 +00:00
ipcMainUtils . handle ( 'ELECTRON_CRASH_REPORTER_INIT' , function ( event , options ) {
2019-02-05 20:56:44 +00:00
return crashReporterInit ( options )
2018-10-13 17:50:07 +00:00
} )
2019-02-26 23:48:26 +00:00
ipcMainUtils . handle ( 'ELECTRON_BROWSER_GET_LAST_WEB_PREFERENCES' , function ( event ) {
2019-02-06 17:53:29 +00:00
return event . sender . getLastWebPreferences ( )
2018-10-13 17:50:07 +00:00
} )
2019-03-16 00:32:04 +00:00
// Methods not listed in this set are called directly in the renderer process.
const allowedClipboardMethods = ( ( ) => {
switch ( process . platform ) {
case 'darwin' :
return new Set ( [ 'readFindText' , 'writeFindText' ] )
case 'linux' :
return new Set ( Object . keys ( clipboard ) )
default :
return new Set ( )
}
} ) ( )
ipcMainUtils . handle ( 'ELECTRON_BROWSER_CLIPBOARD' , function ( event , method , ... args ) {
if ( ! allowedClipboardMethods . has ( method ) ) {
throw new Error ( ` Invalid method: ${ method } ` )
}
2018-10-13 17:50:07 +00:00
2019-03-16 00:32:04 +00:00
return clipboardUtils . serialize ( electron . clipboard [ method ] ( ... clipboardUtils . deserialize ( args ) ) )
2018-09-26 05:43:34 +00:00
} )
2019-03-08 10:21:41 +00:00
const readFile = util . promisify ( fs . readFile )
2019-03-28 10:38:51 +00:00
const realpath = util . promisify ( fs . realpath )
let absoluteAppPath
const getAppPath = async function ( ) {
if ( absoluteAppPath === undefined ) {
absoluteAppPath = await realpath ( electron . app . getAppPath ( ) )
}
return absoluteAppPath
}
2019-03-08 10:21:41 +00:00
const getPreloadScript = async function ( preloadPath ) {
2018-05-21 12:56:05 +00:00
let preloadSrc = null
let preloadError = null
if ( preloadPath ) {
try {
2019-03-28 10:38:51 +00:00
if ( ! isParentDir ( await getAppPath ( ) , await realpath ( preloadPath ) ) ) {
throw new Error ( 'Preload scripts outside of app path are not allowed' )
}
2019-03-08 10:21:41 +00:00
preloadSrc = ( await readFile ( preloadPath ) ) . toString ( )
2018-05-21 12:56:05 +00:00
} catch ( err ) {
2019-01-18 11:03:43 +00:00
preloadError = errorUtils . serialize ( err )
2018-05-21 12:56:05 +00:00
}
}
2019-01-29 01:16:46 +00:00
return { preloadPath , preloadSrc , preloadError }
}
2019-03-08 10:21:41 +00:00
ipcMainUtils . handle ( 'ELECTRON_BROWSER_SANDBOX_LOAD' , async function ( event ) {
2019-01-29 01:16:46 +00:00
const preloadPaths = [
... ( event . sender . session ? event . sender . session . getPreloads ( ) : [ ] ) ,
event . sender . _getPreloadPath ( )
]
2019-03-08 10:21:41 +00:00
return {
preloadScripts : await Promise . all ( preloadPaths . map ( path => getPreloadScript ( path ) ) ) ,
2019-02-11 20:42:37 +00:00
isRemoteModuleEnabled : isRemoteModuleEnabled ( event . sender ) ,
2019-01-08 09:12:34 +00:00
isWebViewTagEnabled : guestViewManager . isWebViewTagEnabled ( event . sender ) ,
2018-08-21 18:05:45 +00:00
process : {
arch : process . arch ,
platform : process . platform ,
env : process . env ,
version : process . version ,
2018-11-15 20:59:01 +00:00
versions : process . versions ,
execPath : process . helperExecPath
2018-08-21 18:05:45 +00:00
}
2018-05-21 12:56:05 +00:00
}
} )
2019-01-18 11:03:43 +00:00
2019-02-04 22:49:53 +00:00
ipcMainInternal . on ( 'ELECTRON_BROWSER_PRELOAD_ERROR' , function ( event , preloadPath , error ) {
2019-01-18 11:03:43 +00:00
event . sender . emit ( 'preload-error' , event , preloadPath , errorUtils . deserialize ( error ) )
} )