2019-02-06 18:27:20 +00:00
|
|
|
import { Buffer } from 'buffer'
|
2020-03-18 19:57:08 +00:00
|
|
|
import { EventEmitter } from 'events'
|
2019-02-06 18:27:20 +00:00
|
|
|
import * as fs from 'fs'
|
|
|
|
import * as path from 'path'
|
|
|
|
import * as util from 'util'
|
2016-03-18 18:51:02 +00:00
|
|
|
|
2016-03-24 20:15:04 +00:00
|
|
|
const Module = require('module')
|
2016-01-12 02:40:23 +00:00
|
|
|
|
2018-09-28 23:17:00 +00:00
|
|
|
// We modified the original process.argv to let node.js load the init.js,
|
2016-01-14 18:35:29 +00:00
|
|
|
// we need to restore it here.
|
2016-03-24 20:15:04 +00:00
|
|
|
process.argv.splice(1, 1)
|
2016-01-12 02:40:23 +00:00
|
|
|
|
2016-01-14 18:35:29 +00:00
|
|
|
// Clear search paths.
|
2016-03-24 20:15:04 +00:00
|
|
|
require('../common/reset-search-paths')
|
2016-01-12 02:40:23 +00:00
|
|
|
|
2016-01-14 18:35:29 +00:00
|
|
|
// Import common settings.
|
2018-09-20 03:43:26 +00:00
|
|
|
require('@electron/internal/common/init')
|
2016-01-12 02:40:23 +00:00
|
|
|
|
2020-03-18 19:57:08 +00:00
|
|
|
process.electronBinding('event_emitter').setEventEmitterPrototype(EventEmitter.prototype)
|
|
|
|
|
2016-01-12 02:40:23 +00:00
|
|
|
if (process.platform === 'win32') {
|
2016-01-14 18:44:21 +00:00
|
|
|
// Redirect node's console to use our own implementations, since node can not
|
|
|
|
// handle console output when running as GUI program.
|
2020-02-12 17:25:11 +00:00
|
|
|
const consoleLog = (...args: any[]) => {
|
|
|
|
// @ts-ignore this typing is incorrect; 'format' is an optional parameter
|
|
|
|
// See https://nodejs.org/api/util.html#util_util_format_format_args
|
|
|
|
return process.log(util.format(...args) + '\n')
|
2016-03-24 20:15:04 +00:00
|
|
|
}
|
2019-02-06 18:27:20 +00:00
|
|
|
const streamWrite: NodeJS.WritableStream['write'] = function (chunk: Buffer | string, encoding?: any, callback?: Function) {
|
2016-01-12 02:40:23 +00:00
|
|
|
if (Buffer.isBuffer(chunk)) {
|
2016-03-24 20:15:04 +00:00
|
|
|
chunk = chunk.toString(encoding)
|
2016-01-12 02:40:23 +00:00
|
|
|
}
|
2016-03-24 20:15:04 +00:00
|
|
|
process.log(chunk)
|
2016-01-12 02:40:23 +00:00
|
|
|
if (callback) {
|
2016-03-24 20:15:04 +00:00
|
|
|
callback()
|
2016-01-12 02:40:23 +00:00
|
|
|
}
|
2016-03-24 20:15:04 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
console.log = console.error = console.warn = consoleLog
|
|
|
|
process.stdout.write = process.stderr.write = streamWrite
|
2016-01-12 02:40:23 +00:00
|
|
|
}
|
|
|
|
|
2016-01-14 18:35:29 +00:00
|
|
|
// Don't quit on fatal error.
|
2016-03-24 20:15:04 +00:00
|
|
|
process.on('uncaughtException', function (error) {
|
2016-01-14 18:35:29 +00:00
|
|
|
// Do nothing if the user has a custom uncaught exception handler.
|
2019-05-01 13:07:57 +00:00
|
|
|
if (process.listenerCount('uncaughtException') > 1) {
|
2016-03-24 20:15:04 +00:00
|
|
|
return
|
2016-01-12 02:40:23 +00:00
|
|
|
}
|
|
|
|
|
2016-01-14 18:35:29 +00:00
|
|
|
// Show error in GUI.
|
2019-02-12 14:22:33 +00:00
|
|
|
// We can't import { dialog } at the top of this file as this file is
|
|
|
|
// responsible for setting up the require hook for the "electron" module
|
|
|
|
// so we import it inside the handler down here
|
|
|
|
import('electron')
|
|
|
|
.then(({ dialog }) => {
|
|
|
|
const stack = error.stack ? error.stack : `${error.name}: ${error.message}`
|
|
|
|
const message = 'Uncaught Exception:\n' + stack
|
|
|
|
dialog.showErrorBox('A JavaScript error occurred in the main process', message)
|
|
|
|
})
|
2016-03-24 20:15:04 +00:00
|
|
|
})
|
2016-01-12 02:40:23 +00:00
|
|
|
|
2016-01-14 18:35:29 +00:00
|
|
|
// Emit 'exit' event on quit.
|
2018-09-13 16:10:51 +00:00
|
|
|
const { app } = require('electron')
|
2016-01-12 02:40:23 +00:00
|
|
|
|
2016-03-24 20:15:04 +00:00
|
|
|
app.on('quit', function (event, exitCode) {
|
2016-05-19 22:28:08 +00:00
|
|
|
process.emit('exit', exitCode)
|
2016-03-24 20:15:04 +00:00
|
|
|
})
|
2016-01-12 02:40:23 +00:00
|
|
|
|
2016-03-15 03:36:48 +00:00
|
|
|
if (process.platform === 'win32') {
|
|
|
|
// If we are a Squirrel.Windows-installed app, set app user model ID
|
|
|
|
// so that users don't have to do this.
|
|
|
|
//
|
|
|
|
// Squirrel packages are always of the form:
|
|
|
|
//
|
|
|
|
// PACKAGE-NAME
|
|
|
|
// - Update.exe
|
|
|
|
// - app-VERSION
|
|
|
|
// - OUREXE.exe
|
|
|
|
//
|
|
|
|
// Squirrel itself will always set the shortcut's App User Model ID to the
|
|
|
|
// form `com.squirrel.PACKAGE-NAME.OUREXE`. We need to call
|
|
|
|
// app.setAppUserModelId with a matching identifier so that renderer processes
|
|
|
|
// will inherit this value.
|
2016-08-02 08:45:46 +00:00
|
|
|
const updateDotExe = path.join(path.dirname(process.execPath), '..', 'update.exe')
|
2016-03-15 03:36:48 +00:00
|
|
|
|
2016-08-02 08:45:46 +00:00
|
|
|
if (fs.existsSync(updateDotExe)) {
|
|
|
|
const packageDir = path.dirname(path.resolve(updateDotExe))
|
|
|
|
const packageName = path.basename(packageDir).replace(/\s/g, '')
|
|
|
|
const exeName = path.basename(process.execPath).replace(/\.exe$/i, '').replace(/\s/g, '')
|
2016-03-15 03:36:48 +00:00
|
|
|
|
2016-03-24 20:15:04 +00:00
|
|
|
app.setAppUserModelId(`com.squirrel.${packageName}.${exeName}`)
|
2016-03-15 03:36:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-14 18:35:29 +00:00
|
|
|
// Map process.exit to app.exit, which quits gracefully.
|
2019-02-06 18:27:20 +00:00
|
|
|
process.exit = app.exit as () => never
|
2016-01-12 02:40:23 +00:00
|
|
|
|
2016-01-14 18:35:29 +00:00
|
|
|
// Load the RPC server.
|
2018-09-20 03:43:26 +00:00
|
|
|
require('@electron/internal/browser/rpc-server')
|
2016-01-12 02:40:23 +00:00
|
|
|
|
2016-01-14 18:35:29 +00:00
|
|
|
// Load the guest view manager.
|
2018-09-20 03:43:26 +00:00
|
|
|
require('@electron/internal/browser/guest-view-manager')
|
|
|
|
require('@electron/internal/browser/guest-window-manager')
|
2016-01-12 02:40:23 +00:00
|
|
|
|
2016-01-14 18:35:29 +00:00
|
|
|
// Now we try to load app's package.json.
|
2016-08-02 08:45:46 +00:00
|
|
|
let packagePath = null
|
|
|
|
let packageJson = null
|
|
|
|
const searchPaths = ['app', 'app.asar', 'default_app.asar']
|
2019-02-21 09:26:07 +00:00
|
|
|
|
2019-02-06 18:27:20 +00:00
|
|
|
if (process.resourcesPath) {
|
|
|
|
for (packagePath of searchPaths) {
|
|
|
|
try {
|
|
|
|
packagePath = path.join(process.resourcesPath, packagePath)
|
2019-06-04 00:03:59 +00:00
|
|
|
packageJson = Module._load(path.join(packagePath, 'package.json'))
|
2019-02-06 18:27:20 +00:00
|
|
|
break
|
2019-02-21 09:26:07 +00:00
|
|
|
} catch {
|
2019-02-06 18:27:20 +00:00
|
|
|
continue
|
|
|
|
}
|
2016-01-12 02:40:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (packageJson == null) {
|
2016-03-24 20:15:04 +00:00
|
|
|
process.nextTick(function () {
|
|
|
|
return process.exit(1)
|
|
|
|
})
|
|
|
|
throw new Error('Unable to find a valid app')
|
2016-01-12 02:40:23 +00:00
|
|
|
}
|
|
|
|
|
2016-01-14 18:35:29 +00:00
|
|
|
// Set application's version.
|
2016-01-12 02:40:23 +00:00
|
|
|
if (packageJson.version != null) {
|
2016-03-24 20:15:04 +00:00
|
|
|
app.setVersion(packageJson.version)
|
2016-01-12 02:40:23 +00:00
|
|
|
}
|
|
|
|
|
2016-01-14 18:35:29 +00:00
|
|
|
// Set application's name.
|
2016-01-12 02:40:23 +00:00
|
|
|
if (packageJson.productName != null) {
|
2019-04-30 20:55:33 +00:00
|
|
|
app.name = `${packageJson.productName}`.trim()
|
2016-01-12 02:40:23 +00:00
|
|
|
} else if (packageJson.name != null) {
|
2019-04-30 20:55:33 +00:00
|
|
|
app.name = `${packageJson.name}`.trim()
|
2016-01-12 02:40:23 +00:00
|
|
|
}
|
|
|
|
|
2016-01-14 18:35:29 +00:00
|
|
|
// Set application's desktop name.
|
2016-01-12 02:40:23 +00:00
|
|
|
if (packageJson.desktopName != null) {
|
2016-03-24 20:15:04 +00:00
|
|
|
app.setDesktopName(packageJson.desktopName)
|
2016-01-12 02:40:23 +00:00
|
|
|
} else {
|
2019-04-30 20:55:33 +00:00
|
|
|
app.setDesktopName(`${app.name}.desktop`)
|
2016-01-12 02:40:23 +00:00
|
|
|
}
|
|
|
|
|
2019-06-03 08:03:33 +00:00
|
|
|
// Set v8 flags, delibrately lazy load so that apps that do not use this
|
|
|
|
// feature do not pay the price
|
2016-02-17 02:23:13 +00:00
|
|
|
if (packageJson.v8Flags != null) {
|
2019-06-03 08:03:33 +00:00
|
|
|
require('v8').setFlagsFromString(packageJson.v8Flags)
|
2016-02-17 02:23:13 +00:00
|
|
|
}
|
|
|
|
|
2019-04-16 18:22:51 +00:00
|
|
|
app._setDefaultAppPaths(packagePath)
|
2016-01-12 02:40:23 +00:00
|
|
|
|
2019-02-07 20:38:57 +00:00
|
|
|
// Load the chrome devtools support.
|
2019-05-17 22:37:09 +00:00
|
|
|
require('@electron/internal/browser/devtools')
|
2019-02-07 20:38:57 +00:00
|
|
|
|
2019-09-18 16:52:06 +00:00
|
|
|
const features = process.electronBinding('features')
|
|
|
|
|
2016-01-14 18:35:29 +00:00
|
|
|
// Load the chrome extension support.
|
2020-01-21 17:42:55 +00:00
|
|
|
if (features.isExtensionsEnabled()) {
|
|
|
|
require('@electron/internal/browser/chrome-extension-shim')
|
|
|
|
} else {
|
2019-07-31 21:25:41 +00:00
|
|
|
require('@electron/internal/browser/chrome-extension')
|
|
|
|
}
|
2016-01-12 02:40:23 +00:00
|
|
|
|
2019-09-18 16:52:06 +00:00
|
|
|
if (features.isRemoteModuleEnabled()) {
|
|
|
|
require('@electron/internal/browser/remote/server')
|
|
|
|
}
|
|
|
|
|
2016-06-23 01:51:39 +00:00
|
|
|
// Load protocol module to ensure it is populated on app ready
|
2018-09-20 03:43:26 +00:00
|
|
|
require('@electron/internal/browser/api/protocol')
|
2016-06-23 01:51:39 +00:00
|
|
|
|
2016-01-14 18:35:29 +00:00
|
|
|
// Set main startup script of the app.
|
2016-08-02 08:45:46 +00:00
|
|
|
const mainStartupScript = packageJson.main || 'index.js'
|
2016-01-12 02:40:23 +00:00
|
|
|
|
2018-05-14 09:00:41 +00:00
|
|
|
const KNOWN_XDG_DESKTOP_VALUES = ['Pantheon', 'Unity:Unity7', 'pop:GNOME']
|
|
|
|
|
2018-05-16 12:34:13 +00:00
|
|
|
function currentPlatformSupportsAppIndicator () {
|
2018-05-14 09:00:41 +00:00
|
|
|
if (process.platform !== 'linux') return false
|
|
|
|
const currentDesktop = process.env.XDG_CURRENT_DESKTOP
|
|
|
|
|
|
|
|
if (!currentDesktop) return false
|
|
|
|
if (KNOWN_XDG_DESKTOP_VALUES.includes(currentDesktop)) return true
|
|
|
|
// ubuntu based or derived session (default ubuntu one, communitheme…) supports
|
|
|
|
// indicator too.
|
|
|
|
if (/ubuntu/ig.test(currentDesktop)) return true
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2017-06-09 13:22:18 +00:00
|
|
|
// Workaround for electron/electron#5050 and electron/electron#9046
|
2018-05-14 09:00:41 +00:00
|
|
|
if (currentPlatformSupportsAppIndicator()) {
|
|
|
|
process.env.XDG_CURRENT_DESKTOP = 'Unity'
|
2016-09-27 11:19:52 +00:00
|
|
|
}
|
|
|
|
|
2019-01-15 20:35:53 +00:00
|
|
|
// Quit when all windows are closed and no other one is listening to this.
|
|
|
|
app.on('window-all-closed', () => {
|
|
|
|
if (app.listenerCount('window-all-closed') === 1) {
|
|
|
|
app.quit()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2019-12-09 19:17:36 +00:00
|
|
|
const { setDefaultApplicationMenu } = require('@electron/internal/browser/default-menu')
|
|
|
|
|
|
|
|
// Create default menu.
|
|
|
|
//
|
|
|
|
// Note that the task must be added before loading any app, so we can make sure
|
|
|
|
// the call is maded before any user window is created, otherwise the default
|
|
|
|
// menu may show even when user explicitly hides the menu.
|
2020-02-03 22:43:22 +00:00
|
|
|
app.whenReady().then(setDefaultApplicationMenu)
|
2019-01-15 20:35:53 +00:00
|
|
|
|
2019-02-06 18:27:20 +00:00
|
|
|
if (packagePath) {
|
|
|
|
// Finally load app's main.js and transfer control to C++.
|
2019-06-04 00:03:59 +00:00
|
|
|
process._firstFileName = Module._resolveFilename(path.join(packagePath, mainStartupScript), null, false)
|
2019-02-06 18:27:20 +00:00
|
|
|
Module._load(path.join(packagePath, mainStartupScript), Module, true)
|
|
|
|
} else {
|
|
|
|
console.error('Failed to locate a valid package to load (app, app.asar or default_app.asar)')
|
|
|
|
console.error('This normally means you\'ve damaged the Electron package somehow')
|
|
|
|
}
|