/ src / main-process / start.js
start.js
  1  const { app } = require('electron');
  2  const nslog = require('nslog');
  3  const path = require('path');
  4  const temp = require('temp').track();
  5  const parseCommandLine = require('./parse-command-line');
  6  const startCrashReporter = require('../crash-reporter-start');
  7  const getReleaseChannel = require('../get-release-channel');
  8  const atomPaths = require('../atom-paths');
  9  const fs = require('fs');
 10  const CSON = require('season');
 11  const Config = require('../config');
 12  const StartupTime = require('../startup-time');
 13  
 14  StartupTime.setStartTime();
 15  
 16  module.exports = function start(resourcePath, devResourcePath, startTime) {
 17    global.shellStartTime = startTime;
 18    StartupTime.addMarker('main-process:start');
 19  
 20    process.on('uncaughtException', function(error = {}) {
 21      if (error.message != null) {
 22        console.log(error.message);
 23      }
 24  
 25      if (error.stack != null) {
 26        console.log(error.stack);
 27      }
 28    });
 29  
 30    process.on('unhandledRejection', function(error = {}) {
 31      if (error.message != null) {
 32        console.log(error.message);
 33      }
 34  
 35      if (error.stack != null) {
 36        console.log(error.stack);
 37      }
 38    });
 39  
 40    const previousConsoleLog = console.log;
 41    console.log = nslog;
 42  
 43    app.commandLine.appendSwitch('enable-experimental-web-platform-features');
 44  
 45    const args = parseCommandLine(process.argv.slice(1));
 46    args.resourcePath = normalizeDriveLetterName(resourcePath);
 47    args.devResourcePath = normalizeDriveLetterName(devResourcePath);
 48  
 49    atomPaths.setAtomHome(app.getPath('home'));
 50    atomPaths.setUserData(app);
 51  
 52    const config = getConfig();
 53    const colorProfile = config.get('core.colorProfile');
 54    if (colorProfile && colorProfile !== 'default') {
 55      app.commandLine.appendSwitch('force-color-profile', colorProfile);
 56    }
 57  
 58    if (handleStartupEventWithSquirrel()) {
 59      return;
 60    } else if (args.test && args.mainProcess) {
 61      app.setPath(
 62        'userData',
 63        temp.mkdirSync('atom-user-data-dir-for-main-process-tests')
 64      );
 65      console.log = previousConsoleLog;
 66      app.on('ready', function() {
 67        const testRunner = require(path.join(
 68          args.resourcePath,
 69          'spec/main-process/mocha-test-runner'
 70        ));
 71        testRunner(args.pathsToOpen);
 72      });
 73      return;
 74    }
 75  
 76    const releaseChannel = getReleaseChannel(app.getVersion());
 77    let appUserModelId = 'com.squirrel.atom.' + process.arch;
 78  
 79    // If the release channel is not stable, we append it to the app user model id.
 80    // This allows having the different release channels as separate items in the taskbar.
 81    if (releaseChannel !== 'stable') {
 82      appUserModelId += `-${releaseChannel}`;
 83    }
 84  
 85    // NB: This prevents Win10 from showing dupe items in the taskbar.
 86    app.setAppUserModelId(appUserModelId);
 87  
 88    function addPathToOpen(event, pathToOpen) {
 89      event.preventDefault();
 90      args.pathsToOpen.push(pathToOpen);
 91    }
 92  
 93    function addUrlToOpen(event, urlToOpen) {
 94      event.preventDefault();
 95      args.urlsToOpen.push(urlToOpen);
 96    }
 97  
 98    app.on('open-file', addPathToOpen);
 99    app.on('open-url', addUrlToOpen);
100    app.on('will-finish-launching', () =>
101      startCrashReporter({
102        uploadToServer: config.get('core.telemetryConsent') === 'limited',
103        releaseChannel
104      })
105    );
106  
107    if (args.userDataDir != null) {
108      app.setPath('userData', args.userDataDir);
109    } else if (args.test || args.benchmark || args.benchmarkTest) {
110      app.setPath('userData', temp.mkdirSync('atom-test-data'));
111    }
112  
113    StartupTime.addMarker('main-process:electron-onready:start');
114    app.on('ready', function() {
115      StartupTime.addMarker('main-process:electron-onready:end');
116      app.removeListener('open-file', addPathToOpen);
117      app.removeListener('open-url', addUrlToOpen);
118      const AtomApplication = require(path.join(
119        args.resourcePath,
120        'src',
121        'main-process',
122        'atom-application'
123      ));
124      AtomApplication.open(args);
125    });
126  };
127  
128  function handleStartupEventWithSquirrel() {
129    if (process.platform !== 'win32') {
130      return false;
131    }
132  
133    const SquirrelUpdate = require('./squirrel-update');
134    const squirrelCommand = process.argv[1];
135    return SquirrelUpdate.handleStartupEvent(squirrelCommand);
136  }
137  
138  function getConfig() {
139    const config = new Config();
140  
141    let configFilePath;
142    if (fs.existsSync(path.join(process.env.ATOM_HOME, 'config.json'))) {
143      configFilePath = path.join(process.env.ATOM_HOME, 'config.json');
144    } else if (fs.existsSync(path.join(process.env.ATOM_HOME, 'config.cson'))) {
145      configFilePath = path.join(process.env.ATOM_HOME, 'config.cson');
146    }
147  
148    if (configFilePath) {
149      const configFileData = CSON.readFileSync(configFilePath);
150      config.resetUserSettings(configFileData);
151    }
152  
153    return config;
154  }
155  
156  function normalizeDriveLetterName(filePath) {
157    if (process.platform === 'win32' && filePath) {
158      return filePath.replace(
159        /^([a-z]):/,
160        ([driveLetter]) => driveLetter.toUpperCase() + ':'
161      );
162    } else {
163      return filePath;
164    }
165  }