Use async randomBytes API to speedup Windows startup

This commit is contained in:
Rafael Oleza 2019-04-30 18:22:46 +02:00
parent 2a7ddf0d22
commit 3fcdcde74d
2 changed files with 46 additions and 27 deletions

View File

@ -751,7 +751,7 @@ describe('AtomApplication', function () {
options.version = version
const app = scenario.addApplication(options)
await app.listenForArgumentsFromNewProcess()
await app.listenForArgumentsFromNewProcess(options)
await app.launch(options)
return app
}
@ -759,7 +759,7 @@ describe('AtomApplication', function () {
it('creates a new application when no socket is present', async function () {
const app0 = await AtomApplication.open({createApplication, version})
app0.deleteSocketSecretFile()
await app0.deleteSocketSecretFile()
const app1 = await AtomApplication.open({createApplication, version})
assert.isNotNull(app1)

View File

@ -15,6 +15,7 @@ const path = require('path')
const os = require('os')
const net = require('net')
const url = require('url')
const {promisify} = require('util')
const {EventEmitter} = require('events')
const _ = require('underscore-plus')
let FindParentDir = null
@ -75,18 +76,21 @@ const getExistingSocketSecret = (atomVersion) => {
return fs.readFileSync(socketSecretPath, 'utf8')
}
const createSocketSecret = (atomVersion) => {
const socketSecret = crypto.randomBytes(16).toString('hex')
const getRandomBytes = promisify(crypto.randomBytes)
const writeFile = promisify(fs.writeFile)
fs.writeFileSync(getSocketSecretPath(atomVersion), socketSecret, {encoding: 'utf8', mode: 0o600})
const createSocketSecret = async (atomVersion) => {
const socketSecret = (await getRandomBytes(16)).toString('hex')
await writeFile(getSocketSecretPath(atomVersion), socketSecret, {encoding: 'utf8', mode: 0o600})
return socketSecret
}
const encryptOptions = (options, secret) => {
const encryptOptions = async (options, secret) => {
const message = JSON.stringify(options)
const initVector = crypto.randomBytes(16)
const initVector = await getRandomBytes(16)
const cipher = crypto.createCipheriv('aes-256-gcm', secret, initVector)
@ -144,10 +148,12 @@ class AtomApplication extends EventEmitter {
return new Promise(resolve => {
const client = net.connect({path: socketPath}, () => {
client.write(encryptOptions(options, socketSecret), () => {
client.end()
app.quit()
resolve(null)
encryptOptions(options, socketSecret).then((encryptedOptions) => {
client.write(encryptedOptions, () => {
client.end()
app.quit()
resolve(null)
})
})
})
@ -173,12 +179,6 @@ class AtomApplication extends EventEmitter {
this.logFile = options.logFile
this.userDataDir = options.userDataDir
this._killProcess = options.killProcess || process.kill.bind(process)
if (!options.test && !options.benchmark && !options.benchmarkTest) {
this.socketSecret = createSocketSecret(this.version)
this.socketPath = getSocketPath(this.socketSecret)
}
this.waitSessionsByWindow = new Map()
this.windowStack = new WindowStack()
@ -227,11 +227,16 @@ class AtomApplication extends EventEmitter {
this.applicationMenu = new ApplicationMenu(this.version, this.autoUpdateManager)
this.atomProtocolHandler = new AtomProtocolHandler(this.resourcePath, this.safeMode)
this.listenForArgumentsFromNewProcess()
// Don't await for the following method to avoid delaying the opening of a new window.
// (we await it just after opening it).
const socketServerPromise = this.listenForArgumentsFromNewProcess(options)
this.setupDockMenu()
const result = await this.launch(options)
this.autoUpdateManager.initialize()
await socketServerPromise
return result
}
@ -421,10 +426,15 @@ class AtomApplication extends EventEmitter {
// You can run the atom command multiple times, but after the first launch
// the other launches will just pass their information to this server and then
// close immediately.
listenForArgumentsFromNewProcess () {
if (!this.socketPath) return
async listenForArgumentsFromNewProcess (options) {
if (!options.test && !options.benchmark && !options.benchmarkTest) {
this.socketSecretPromise = createSocketSecret(this.version)
this.socketSecret = await this.socketSecretPromise
this.socketPath = getSocketPath(this.socketSecret)
}
await this.deleteSocketFile()
this.deleteSocketFile()
const server = net.createServer(connection => {
let data = ''
connection.on('data', chunk => { data += chunk })
@ -445,8 +455,13 @@ class AtomApplication extends EventEmitter {
})
}
deleteSocketFile () {
if (process.platform === 'win32' || !this.socketPath) return
async deleteSocketFile () {
if (process.platform === 'win32') return
if (!this.socketSecretPromise) {
return
}
await this.socketSecretPromise
if (fs.existsSync(this.socketPath)) {
try {
@ -460,10 +475,11 @@ class AtomApplication extends EventEmitter {
}
}
deleteSocketSecretFile () {
if (!this.socketSecret) {
async deleteSocketSecretFile () {
if (!this.socketSecretPromise) {
return
}
await this.socketSecretPromise
const socketSecretPath = getSocketSecretPath(this.version)
@ -595,8 +611,11 @@ class AtomApplication extends EventEmitter {
this.disposable.add(ipcHelpers.on(app, 'will-quit', () => {
this.killAllProcesses()
this.deleteSocketFile()
this.deleteSocketSecretFile()
return Promise.all([
this.deleteSocketFile(),
this.deleteSocketSecretFile()
])
}))
// Triggered by the 'open-file' event from Electron: