Initial Implementation of Node prelaunch
[platform/framework/web/crosswalk-tizen.git] / lib / browser / init.js
1 'use strict'
2
3 const {Buffer} = require('buffer')
4 const fs = require('fs')
5 const path = require('path')
6 const util = require('util')
7 const Module = require('module')
8 const v8 = require('v8')
9
10 // We modified the original process.argv to let node.js load the atom.js,
11 // we need to restore it here.
12 process.argv.splice(1, 1)
13
14 // Clear search paths.
15 require('../common/reset-search-paths')
16
17 // Import common settings.
18 require('../common/init')
19
20 var globalPaths = Module.globalPaths
21
22 // Expose public APIs.
23 globalPaths.push(path.join(__dirname, 'api', 'exports'))
24
25 if (process.platform === 'win32') {
26   // Redirect node's console to use our own implementations, since node can not
27   // handle console output when running as GUI program.
28   var consoleLog = function (...args) {
29     return process.log(util.format(...args) + '\n')
30   }
31   var streamWrite = function (chunk, encoding, callback) {
32     if (Buffer.isBuffer(chunk)) {
33       chunk = chunk.toString(encoding)
34     }
35     process.log(chunk)
36     if (callback) {
37       callback()
38     }
39     return true
40   }
41   console.log = console.error = console.warn = consoleLog
42   process.stdout.write = process.stderr.write = streamWrite
43 }
44
45 let {pwrt} = require('electron');
46 console.log = console.error = console.warn = function(...args) {
47   pwrt.log(util.format(...args));
48 };
49 process.stdout.write = process.stderr.write = function (chunk, encoding, callback) {
50   if (Buffer.isBuffer(chunk)) {
51     chunk = chunk.toString(encoding)
52   }
53   pwrt.log(chunk)
54   if (callback) {
55     callback()
56   }
57   return true
58 }
59
60 // Don't quit on fatal error.
61 process.on('uncaughtException', function (error) {
62   // Do nothing if the user has a custom uncaught exception handler.
63   var dialog, message, ref, stack
64   if (process.listeners('uncaughtException').length > 1) {
65     return
66   }
67
68   // Show error in GUI.
69   dialog = require('electron').dialog
70   stack = (ref = error.stack) != null ? ref : error.name + ': ' + error.message
71   message = 'Uncaught Exception:\n' + stack
72   dialog.showErrorBox('A JavaScript error occurred in the main process', message)
73 })
74
75 // Emit 'exit' event on quit.
76 const {app} = require('electron')
77
78 app.on('quit', function (event, exitCode) {
79   process.emit('exit', exitCode)
80 })
81
82 if (process.platform === 'win32') {
83   // If we are a Squirrel.Windows-installed app, set app user model ID
84   // so that users don't have to do this.
85   //
86   // Squirrel packages are always of the form:
87   //
88   // PACKAGE-NAME
89   // - Update.exe
90   // - app-VERSION
91   //   - OUREXE.exe
92   //
93   // Squirrel itself will always set the shortcut's App User Model ID to the
94   // form `com.squirrel.PACKAGE-NAME.OUREXE`. We need to call
95   // app.setAppUserModelId with a matching identifier so that renderer processes
96   // will inherit this value.
97   const updateDotExe = path.join(path.dirname(process.execPath), '..', 'update.exe')
98
99   if (fs.existsSync(updateDotExe)) {
100     const packageDir = path.dirname(path.resolve(updateDotExe))
101     const packageName = path.basename(packageDir).replace(/\s/g, '')
102     const exeName = path.basename(process.execPath).replace(/\.exe$/i, '').replace(/\s/g, '')
103
104     app.setAppUserModelId(`com.squirrel.${packageName}.${exeName}`)
105   }
106 }
107
108 // Map process.exit to app.exit, which quits gracefully.
109 process.exit = app.exit
110
111 // Load the RPC server.
112 require('./rpc-server')
113
114 // Load the guest view manager.
115 require('./guest-view-manager')
116 require('./guest-window-manager')
117
118 // Now we try to load app's package.json.
119 let packagePath = null
120 let packageJson = null
121 const searchPaths = ['app', 'app.asar', 'default_app.asar']
122 for (packagePath of searchPaths) {
123   try {
124     packagePath = path.join(process.resourcesPath, packagePath)
125     packageJson = require(path.join(packagePath, 'package.json'))
126     break
127   } catch (error) {
128     continue
129   }
130 }
131
132 if (packageJson == null) {
133   process.nextTick(function () {
134     return process.exit(1)
135   })
136   throw new Error('Unable to find a valid app')
137 }
138
139 // Set application's version.
140 if (packageJson.version != null) {
141   app.setVersion(packageJson.version)
142 }
143
144 // Set application's name.
145 if (packageJson.productName != null) {
146   app.setName(packageJson.productName)
147 } else if (packageJson.name != null) {
148   app.setName(packageJson.name)
149 }
150
151 // Set application's desktop name.
152 if (packageJson.desktopName != null) {
153   app.setDesktopName(packageJson.desktopName)
154 } else {
155   app.setDesktopName((app.getName()) + '.desktop')
156 }
157
158 // Set v8 flags
159 if (packageJson.v8Flags != null) {
160   v8.setFlagsFromString(packageJson.v8Flags)
161 }
162
163 // Set the user path according to application's name.
164 // FIXME: use app.getPath('cache') instead of app.getPath('appData').
165 //        This is for bringup.
166 // app.setPath('userData', path.join(app.getPath('appData'), app.getName()))
167 app.setPath('userData', path.join(app.getPath('cache'), app.getName()))
168 app.setPath('userCache', path.join(app.getPath('cache'), app.getName()))
169 app.setAppPath(packagePath)
170
171 // Load the chrome extension support.
172 // FIXME: When prelaunch, initializing electron modules
173 //        in chrome-extension cause segmentation fault.
174 //require('./chrome-extension')
175
176 // Load internal desktop-capturer module.
177 // FIXME: This is guard for bringup.
178 //require('./desktop-capturer')
179
180 // Load protocol module to ensure it is populated on app ready
181 require('./api/protocol')
182
183 // Set main startup script of the app.
184 const mainStartupScript = packageJson.main || 'index.js'
185
186 // Workaround for electron/electron#5050
187 if (process.platform === 'linux' && process.env.XDG_CURRENT_DESKTOP === 'Pantheon') {
188   process.env.XDG_CURRENT_DESKTOP = 'Unity'
189 }
190
191 // Finally load app's main.js and transfer control to C++.
192 Module._load(path.join(packagePath, mainStartupScript), Module, true)