Merge pull request #4909 from atom/standard

Use `standard` JavaScript Style
This commit is contained in:
Cheng Zhao 2016-04-01 11:13:56 +09:00
commit 7023528042
115 changed files with 7877 additions and 7952 deletions

View file

@ -28,7 +28,7 @@ possible with your report. If you can, please include:
## Submitting Pull Requests ## Submitting Pull Requests
* Include screenshots and animated GIFs in your pull request whenever possible. * Include screenshots and animated GIFs in your pull request whenever possible.
* Follow the CoffeeScript, JavaScript, C++ and Python [coding style defined in docs](/docs/development/coding-style.md). * Follow the JavaScript, C++, and Python [coding style defined in docs](/docs/development/coding-style.md).
* Write documentation in [Markdown](https://daringfireball.net/projects/markdown). * Write documentation in [Markdown](https://daringfireball.net/projects/markdown).
See the [Documentation Styleguide](/docs/styleguide.md). See the [Documentation Styleguide](/docs/styleguide.md).
* Use short, present tense commit messages. See [Commit Message Styleguide](#git-commit-messages). * Use short, present tense commit messages. See [Commit Message Styleguide](#git-commit-messages).

View file

@ -1,23 +1,23 @@
const electron = require('electron'); const electron = require('electron')
const app = electron.app; const app = electron.app
const BrowserWindow = electron.BrowserWindow; const BrowserWindow = electron.BrowserWindow
var mainWindow = null; var mainWindow = null
// Quit when all windows are closed. // Quit when all windows are closed.
app.on('window-all-closed', function() { app.on('window-all-closed', function () {
app.quit(); app.quit()
}); })
exports.load = function(appUrl) { exports.load = function (appUrl) {
app.on('ready', function() { app.on('ready', function () {
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 800, width: 800,
height: 600, height: 600,
autoHideMenuBar: true, autoHideMenuBar: true,
useContentSize: true, useContentSize: true
}); })
mainWindow.loadURL(appUrl); mainWindow.loadURL(appUrl)
mainWindow.focus(); mainWindow.focus()
}); })
}; }

View file

@ -1,52 +1,52 @@
const electron = require('electron'); const electron = require('electron')
const app = electron.app; const app = electron.app
const dialog = electron.dialog; const dialog = electron.dialog
const shell = electron.shell; const shell = electron.shell
const Menu = electron.Menu; const Menu = electron.Menu
const fs = require('fs'); const fs = require('fs')
const path = require('path'); const path = require('path')
const repl = require('repl'); const repl = require('repl')
const url = require('url'); const url = require('url')
// Parse command line options. // Parse command line options.
var argv = process.argv.slice(1); var argv = process.argv.slice(1)
var option = { file: null, help: null, version: null, webdriver: null, modules: [] }; var option = { file: null, help: null, version: null, webdriver: null, modules: [] }
for (var i = 0; i < argv.length; i++) { for (var i = 0; i < argv.length; i++) {
if (argv[i] == '--version' || argv[i] == '-v') { if (argv[i] === '--version' || argv[i] === '-v') {
option.version = true; option.version = true
break; break
} else if (argv[i].match(/^--app=/)) { } else if (argv[i].match(/^--app=/)) {
option.file = argv[i].split('=')[1]; option.file = argv[i].split('=')[1]
break; break
} else if (argv[i] == '--help' || argv[i] == '-h') { } else if (argv[i] === '--help' || argv[i] === '-h') {
option.help = true; option.help = true
break; break
} else if (argv[i] == '--interactive' || argv[i] == '-i') { } else if (argv[i] === '--interactive' || argv[i] === '-i') {
option.interactive = true; option.interactive = true
} else if (argv[i] == '--test-type=webdriver') { } else if (argv[i] === '--test-type=webdriver') {
option.webdriver = true; option.webdriver = true
} else if (argv[i] == '--require' || argv[i] == '-r') { } else if (argv[i] === '--require' || argv[i] === '-r') {
option.modules.push(argv[++i]); option.modules.push(argv[++i])
continue; continue
} else if (argv[i][0] == '-') { } else if (argv[i][0] === '-') {
continue; continue
} else { } else {
option.file = argv[i]; option.file = argv[i]
break; break
} }
} }
// Quit when all windows are closed and no other one is listening to this. // Quit when all windows are closed and no other one is listening to this.
app.on('window-all-closed', function() { app.on('window-all-closed', function () {
if (app.listeners('window-all-closed').length == 1 && !option.interactive) if (app.listeners('window-all-closed').length === 1 && !option.interactive) {
app.quit(); app.quit()
}); }
})
// Create default menu. // Create default menu.
app.once('ready', function() { app.once('ready', function () {
if (Menu.getApplicationMenu()) if (Menu.getApplicationMenu()) return
return;
var template = [ var template = [
{ {
@ -84,7 +84,7 @@ app.once('ready', function() {
label: 'Select All', label: 'Select All',
accelerator: 'CmdOrCtrl+A', accelerator: 'CmdOrCtrl+A',
role: 'selectall' role: 'selectall'
}, }
] ]
}, },
{ {
@ -93,37 +93,28 @@ app.once('ready', function() {
{ {
label: 'Reload', label: 'Reload',
accelerator: 'CmdOrCtrl+R', accelerator: 'CmdOrCtrl+R',
click: function(item, focusedWindow) { click: function (item, focusedWindow) {
if (focusedWindow) if (focusedWindow) focusedWindow.reload()
focusedWindow.reload();
} }
}, },
{ {
label: 'Toggle Full Screen', label: 'Toggle Full Screen',
accelerator: (function() { accelerator: (function () {
if (process.platform == 'darwin') return (process.platform === 'darwin') ? 'Ctrl+Command+F' : 'F11'
return 'Ctrl+Command+F';
else
return 'F11';
})(), })(),
click: function(item, focusedWindow) { click: function (item, focusedWindow) {
if (focusedWindow) if (focusedWindow) focusedWindow.setFullScreen(!focusedWindow.isFullScreen())
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
} }
}, },
{ {
label: 'Toggle Developer Tools', label: 'Toggle Developer Tools',
accelerator: (function() { accelerator: (function () {
if (process.platform == 'darwin') return (process.platform === 'darwin') ? 'Alt+Command+I' : 'Ctrl+Shift+I'
return 'Alt+Command+I';
else
return 'Ctrl+Shift+I';
})(), })(),
click: function(item, focusedWindow) { click: function (item, focusedWindow) {
if (focusedWindow) if (focusedWindow) focusedWindow.toggleDevTools()
focusedWindow.toggleDevTools();
} }
}, }
] ]
}, },
{ {
@ -139,7 +130,7 @@ app.once('ready', function() {
label: 'Close', label: 'Close',
accelerator: 'CmdOrCtrl+W', accelerator: 'CmdOrCtrl+W',
role: 'close' role: 'close'
}, }
] ]
}, },
{ {
@ -148,35 +139,35 @@ app.once('ready', function() {
submenu: [ submenu: [
{ {
label: 'Learn More', label: 'Learn More',
click: function() { click: function () {
shell.openExternal('http://electron.atom.io'); shell.openExternal('http://electron.atom.io')
} }
}, },
{ {
label: 'Documentation', label: 'Documentation',
click: function() { click: function () {
shell.openExternal( shell.openExternal(
`https://github.com/atom/electron/tree/v${process.versions.electron}/docs#readme` `https://github.com/atom/electron/tree/v${process.versions.electron}/docs#readme`
); )
} }
}, },
{ {
label: 'Community Discussions', label: 'Community Discussions',
click: function() { click: function () {
shell.openExternal('https://discuss.atom.io/c/electron'); shell.openExternal('https://discuss.atom.io/c/electron')
} }
}, },
{ {
label: 'Search Issues', label: 'Search Issues',
click: function() { click: function () {
shell.openExternal('https://github.com/atom/electron/issues'); shell.openExternal('https://github.com/atom/electron/issues')
} }
} }
] ]
}, }
]; ]
if (process.platform == 'darwin') { if (process.platform === 'darwin') {
template.unshift({ template.unshift({
label: 'Electron', label: 'Electron',
submenu: [ submenu: [
@ -215,10 +206,10 @@ app.once('ready', function() {
{ {
label: 'Quit', label: 'Quit',
accelerator: 'Command+Q', accelerator: 'Command+Q',
click: function() { app.quit(); } click: function () { app.quit() }
}, }
] ]
}); })
template[3].submenu.push( template[3].submenu.push(
{ {
type: 'separator' type: 'separator'
@ -227,98 +218,107 @@ app.once('ready', function() {
label: 'Bring All to Front', label: 'Bring All to Front',
role: 'front' role: 'front'
} }
); )
} }
var menu = Menu.buildFromTemplate(template); var menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu); Menu.setApplicationMenu(menu)
}); })
if (option.modules.length > 0) { if (option.modules.length > 0) {
require('module')._preloadModules(option.modules); require('module')._preloadModules(option.modules)
} }
function loadApplicationPackage(packagePath) { function loadApplicationPackage (packagePath) {
try { try {
// Override app name and version. // Override app name and version.
packagePath = path.resolve(packagePath); packagePath = path.resolve(packagePath)
var packageJsonPath = path.join(packagePath, 'package.json'); var packageJsonPath = path.join(packagePath, 'package.json')
if (fs.existsSync(packageJsonPath)) { if (fs.existsSync(packageJsonPath)) {
var packageJson = JSON.parse(fs.readFileSync(packageJsonPath)); var packageJson = JSON.parse(fs.readFileSync(packageJsonPath))
if (packageJson.version) if (packageJson.version) app.setVersion(packageJson.version)
app.setVersion(packageJson.version);
if (packageJson.productName) if (packageJson.productName) {
app.setName(packageJson.productName); app.setName(packageJson.productName)
else if (packageJson.name) } else if (packageJson.name) {
app.setName(packageJson.name); app.setName(packageJson.name)
app.setPath('userData', path.join(app.getPath('appData'), app.getName())); }
app.setPath('userCache', path.join(app.getPath('cache'), app.getName()));
app.setAppPath(packagePath); app.setPath('userData', path.join(app.getPath('appData'), app.getName()))
app.setPath('userCache', path.join(app.getPath('cache'), app.getName()))
app.setAppPath(packagePath)
} }
// Run the app. // Run the app.
require('module')._load(packagePath, module, true); require('module')._load(packagePath, module, true)
} catch(e) { } catch (e) {
if (e.code == 'MODULE_NOT_FOUND') { if (e.code === 'MODULE_NOT_FOUND') {
app.focus(); app.focus()
dialog.showErrorBox( dialog.showErrorBox(
'Error opening app', 'Error opening app',
'The app provided is not a valid Electron app, please read the docs on how to write one:\n' + 'The app provided is not a valid Electron app, please read the docs on how to write one:\n' +
`https://github.com/atom/electron/tree/v${process.versions.electron}/docs\n\n${e.toString()}` `https://github.com/atom/electron/tree/v${process.versions.electron}/docs
);
process.exit(1); ${e.toString()}`
)
process.exit(1)
} else { } else {
console.error('App threw an error when running', e); console.error('App threw an error when running', e)
throw e; throw e
} }
} }
} }
function loadApplicationByUrl(appUrl) { function loadApplicationByUrl (appUrl) {
require('./default_app').load(appUrl); require('./default_app').load(appUrl)
} }
function startRepl() { function startRepl () {
repl.start('> ').on('exit', function() { repl.start('> ').on('exit', function () {
process.exit(0); process.exit(0)
}); })
} }
// Start the specified app if there is one specified in command line, otherwise // Start the specified app if there is one specified in command line, otherwise
// start the default app. // start the default app.
if (option.file && !option.webdriver) { if (option.file && !option.webdriver) {
var file = option.file; var file = option.file
var protocol = url.parse(file).protocol; var protocol = url.parse(file).protocol
var extension = path.extname(file); var extension = path.extname(file)
if (protocol === 'http:' || protocol === 'https:' || protocol === 'file:') { if (protocol === 'http:' || protocol === 'https:' || protocol === 'file:') {
loadApplicationByUrl(file); loadApplicationByUrl(file)
} else if (extension === '.html' || extension === '.htm') { } else if (extension === '.html' || extension === '.htm') {
loadApplicationByUrl('file://' + path.resolve(file)); loadApplicationByUrl('file://' + path.resolve(file))
} else { } else {
loadApplicationPackage(file); loadApplicationPackage(file)
} }
} else if (option.version) { } else if (option.version) {
console.log('v' + process.versions.electron); console.log('v' + process.versions.electron)
process.exit(0); process.exit(0)
} else if (option.help) { } else if (option.help) {
var helpMessage = "Electron v" + process.versions.electron + " - Cross Platform Desktop Application Shell\n\n"; var helpMessage = `Electron v${process.versions.electron} - Cross Platform Desktop Application Shell
helpMessage += "Usage: electron [options] [path]\n\n";
helpMessage += "A path to an Electron application may be specified.\n"; Usage: electron [options] [path]
helpMessage += "The path must be one of the following:\n\n";
helpMessage += " - index.js file.\n"; A path to an Electron application may be specified.
helpMessage += " - Folder containing a package.json file.\n"; The path must be one of the following:
helpMessage += " - Folder containing an index.js file.\n";
helpMessage += " - .html/.htm file.\n"; - index.js file.
helpMessage += " - http://, https://, or file:// URL.\n"; - Folder containing a package.json file.
helpMessage += "\nOptions:\n"; - Folder containing an index.js file.
helpMessage += " -h, --help Print this usage message.\n"; - .html/.htm file.
helpMessage += " -i, --interactive Open a REPL to the main process.\n"; - http://, https://, or file:// URL.
helpMessage += " -r, --require Module to preload (option can be repeated)\n";
helpMessage += " -v, --version Print the version."; Options:
console.log(helpMessage); -h, --help Print this usage message.
process.exit(0); -i, --interactive Open a REPL to the main process.
-r, --require Module to preload (option can be repeated)
-v, --version Print the version.`
console.log(helpMessage)
process.exit(0)
} else if (option.interactive) { } else if (option.interactive) {
startRepl(); startRepl()
} else { } else {
loadApplicationByUrl('file://' + __dirname + '/index.html'); var indexPath = path.join(__dirname, '/index.html')
loadApplicationByUrl(`file://${indexPath}`)
} }

View file

@ -22,8 +22,7 @@ etc.
## JavaScript ## JavaScript
* Use a two space indent, no hard tabs. * Write [standard](http://npm.im/standard) JavaScript style.
* End lines with a `;`
* Files should **NOT** end with new line, because we want to match Google's * Files should **NOT** end with new line, because we want to match Google's
styles. styles.
* File names should be concatenated with `-` instead of `_`, e.g. * File names should be concatenated with `-` instead of `_`, e.g.

View file

@ -1,36 +1,36 @@
'use strict'; 'use strict'
const deprecate = require('electron').deprecate; const deprecate = require('electron').deprecate
const session = require('electron').session; const session = require('electron').session
const Menu = require('electron').Menu; const Menu = require('electron').Menu
const EventEmitter = require('events').EventEmitter; const EventEmitter = require('events').EventEmitter
const bindings = process.atomBinding('app'); const bindings = process.atomBinding('app')
const downloadItemBindings = process.atomBinding('download_item'); const downloadItemBindings = process.atomBinding('download_item')
const app = bindings.app; const app = bindings.app
app.__proto__ = EventEmitter.prototype; Object.setPrototypeOf(app, EventEmitter.prototype)
app.setApplicationMenu = function(menu) { app.setApplicationMenu = function (menu) {
return Menu.setApplicationMenu(menu); return Menu.setApplicationMenu(menu)
}; }
app.getApplicationMenu = function() { app.getApplicationMenu = function () {
return Menu.getApplicationMenu(); return Menu.getApplicationMenu()
}; }
app.commandLine = { app.commandLine = {
appendSwitch: bindings.appendSwitch, appendSwitch: bindings.appendSwitch,
appendArgument: bindings.appendArgument appendArgument: bindings.appendArgument
}; }
if (process.platform === 'darwin') { if (process.platform === 'darwin') {
app.dock = { app.dock = {
bounce: function(type) { bounce: function (type) {
if (type == null) { if (type == null) {
type = 'informational'; type = 'informational'
} }
return bindings.dockBounce(type); return bindings.dockBounce(type)
}, },
cancelBounce: bindings.dockCancelBounce, cancelBounce: bindings.dockCancelBounce,
setBadge: bindings.dockSetBadgeText, setBadge: bindings.dockSetBadgeText,
@ -39,81 +39,79 @@ if (process.platform === 'darwin') {
show: bindings.dockShow, show: bindings.dockShow,
setMenu: bindings.dockSetMenu, setMenu: bindings.dockSetMenu,
setIcon: bindings.dockSetIcon setIcon: bindings.dockSetIcon
}; }
} }
var appPath = null; var appPath = null
app.setAppPath = function(path) { app.setAppPath = function (path) {
return appPath = path; appPath = path
}; }
app.getAppPath = function() { app.getAppPath = function () {
return appPath; return appPath
}; }
// Routes the events to webContents. // Routes the events to webContents.
var ref1 = ['login', 'certificate-error', 'select-client-certificate']; var ref1 = ['login', 'certificate-error', 'select-client-certificate']
var fn = function(name) { var fn = function (name) {
return app.on(name, function(event, webContents, ...args) { return app.on(name, function (event, webContents, ...args) {
return webContents.emit.apply(webContents, [name, event].concat(args)); return webContents.emit.apply(webContents, [name, event].concat(args))
}); })
}; }
var i, len; var i, len
for (i = 0, len = ref1.length; i < len; i++) { for (i = 0, len = ref1.length; i < len; i++) {
fn(ref1[i]); fn(ref1[i])
} }
// Deprecated. // Deprecated.
app.getHomeDir = deprecate('app.getHomeDir', 'app.getPath', function() { app.getHomeDir = deprecate('app.getHomeDir', 'app.getPath', function () {
return this.getPath('home'); return this.getPath('home')
}); })
app.getDataPath = deprecate('app.getDataPath', 'app.getPath', function() { app.getDataPath = deprecate('app.getDataPath', 'app.getPath', function () {
return this.getPath('userData'); return this.getPath('userData')
}); })
app.setDataPath = deprecate('app.setDataPath', 'app.setPath', function(path) { app.setDataPath = deprecate('app.setDataPath', 'app.setPath', function (path) {
return this.setPath('userData', path); return this.setPath('userData', path)
}); })
app.resolveProxy = deprecate('app.resolveProxy', 'session.defaultSession.resolveProxy', function(url, callback) { app.resolveProxy = deprecate('app.resolveProxy', 'session.defaultSession.resolveProxy', function (url, callback) {
return session.defaultSession.resolveProxy(url, callback); return session.defaultSession.resolveProxy(url, callback)
}); })
deprecate.rename(app, 'terminate', 'quit'); deprecate.rename(app, 'terminate', 'quit')
deprecate.event(app, 'finish-launching', 'ready', function() {
deprecate.event(app, 'finish-launching', 'ready', function () {
// give default app a chance to setup default menu. // give default app a chance to setup default menu.
setImmediate(() => { setImmediate(() => {
this.emit('finish-launching'); this.emit('finish-launching')
}); })
}); })
deprecate.event(app, 'activate-with-no-open-windows', 'activate', function(event, hasVisibleWindows) { deprecate.event(app, 'activate-with-no-open-windows', 'activate', function (event, hasVisibleWindows) {
if (!hasVisibleWindows) { if (!hasVisibleWindows) {
return this.emit('activate-with-no-open-windows', event); return this.emit('activate-with-no-open-windows', event)
} }
}); })
deprecate.event(app, 'select-certificate', 'select-client-certificate'); deprecate.event(app, 'select-certificate', 'select-client-certificate')
// Wrappers for native classes. // Wrappers for native classes.
var wrapDownloadItem = function(downloadItem) { var wrapDownloadItem = function (downloadItem) {
// downloadItem is an EventEmitter. // downloadItem is an EventEmitter.
downloadItem.__proto__ = EventEmitter.prototype; Object.setPrototypeOf(downloadItem, EventEmitter.prototype)
// Deprecated. // Deprecated.
deprecate.property(downloadItem, 'url', 'getURL'); deprecate.property(downloadItem, 'url', 'getURL')
deprecate.property(downloadItem, 'filename', 'getFilename'); deprecate.property(downloadItem, 'filename', 'getFilename')
deprecate.property(downloadItem, 'mimeType', 'getMimeType'); deprecate.property(downloadItem, 'mimeType', 'getMimeType')
return deprecate.rename(downloadItem, 'getUrl', 'getURL'); return deprecate.rename(downloadItem, 'getUrl', 'getURL')
}; }
downloadItemBindings._setWrapDownloadItem(wrapDownloadItem); downloadItemBindings._setWrapDownloadItem(wrapDownloadItem)
// Only one App object pemitted. // Only one App object pemitted.
module.exports = app; module.exports = app

View file

@ -1,7 +1,7 @@
const deprecate = require('electron').deprecate; const deprecate = require('electron').deprecate
const autoUpdater = process.platform === 'win32' ? require('./auto-updater/auto-updater-win') : require('./auto-updater/auto-updater-native'); const autoUpdater = process.platform === 'win32' ? require('./auto-updater/auto-updater-win') : require('./auto-updater/auto-updater-native')
// Deprecated. // Deprecated.
deprecate.rename(autoUpdater, 'setFeedUrl', 'setFeedURL'); deprecate.rename(autoUpdater, 'setFeedUrl', 'setFeedURL')
module.exports = autoUpdater; module.exports = autoUpdater

View file

@ -1,6 +1,6 @@
const EventEmitter = require('events').EventEmitter; const EventEmitter = require('events').EventEmitter
const autoUpdater = process.atomBinding('auto_updater').autoUpdater; const autoUpdater = process.atomBinding('auto_updater').autoUpdater
autoUpdater.__proto__ = EventEmitter.prototype; Object.setPrototypeOf(autoUpdater, EventEmitter.prototype)
module.exports = autoUpdater; module.exports = autoUpdater

View file

@ -1,61 +1,62 @@
'use strict'; 'use strict'
const app = require('electron').app; const app = require('electron').app
const EventEmitter = require('events').EventEmitter; const EventEmitter = require('events').EventEmitter
const squirrelUpdate = require('./squirrel-update-win'); const squirrelUpdate = require('./squirrel-update-win')
const util = require('util'); const util = require('util')
function AutoUpdater() { function AutoUpdater () {
EventEmitter.call(this); EventEmitter.call(this)
} }
util.inherits(AutoUpdater, EventEmitter); util.inherits(AutoUpdater, EventEmitter)
AutoUpdater.prototype.quitAndInstall = function() { AutoUpdater.prototype.quitAndInstall = function () {
squirrelUpdate.processStart(); squirrelUpdate.processStart()
return app.quit(); return app.quit()
}; }
AutoUpdater.prototype.setFeedURL = function(updateURL) { AutoUpdater.prototype.setFeedURL = function (updateURL) {
return this.updateURL = updateURL; this.updateURL = updateURL
}; }
AutoUpdater.prototype.checkForUpdates = function() { AutoUpdater.prototype.checkForUpdates = function () {
if (!this.updateURL) { if (!this.updateURL) {
return this.emitError('Update URL is not set'); return this.emitError('Update URL is not set')
} }
if (!squirrelUpdate.supported()) { if (!squirrelUpdate.supported()) {
return this.emitError('Can not find Squirrel'); return this.emitError('Can not find Squirrel')
} }
this.emit('checking-for-update'); this.emit('checking-for-update')
squirrelUpdate.download(this.updateURL, (error, update) => { squirrelUpdate.download(this.updateURL, (error, update) => {
if (error != null) { if (error != null) {
return this.emitError(error); return this.emitError(error)
} }
if (update == null) { if (update == null) {
return this.emit('update-not-available'); return this.emit('update-not-available')
} }
this.emit('update-available'); this.emit('update-available')
squirrelUpdate.update(this.updateURL, (error) => { squirrelUpdate.update(this.updateURL, (error) => {
var date, releaseNotes, version; var date, releaseNotes, version
if (error != null) { if (error != null) {
return this.emitError(error); return this.emitError(error)
} }
releaseNotes = update.releaseNotes, version = update.version; releaseNotes = update.releaseNotes
version = update.version
// Following information is not available on Windows, so fake them. // Following information is not available on Windows, so fake them.
date = new Date; date = new Date()
this.emit('update-downloaded', {}, releaseNotes, version, date, this.updateURL, () => { this.emit('update-downloaded', {}, releaseNotes, version, date, this.updateURL, () => {
this.quitAndInstall(); this.quitAndInstall()
}); })
}); })
}); })
}; }
// Private: Emit both error object and message, this is to keep compatibility // Private: Emit both error object and message, this is to keep compatibility
// with Old APIs. // with Old APIs.
AutoUpdater.prototype.emitError = function(message) { AutoUpdater.prototype.emitError = function (message) {
return this.emit('error', new Error(message), message); return this.emit('error', new Error(message), message)
}; }
module.exports = new AutoUpdater; module.exports = new AutoUpdater()

View file

@ -1,98 +1,95 @@
const fs = require('fs'); const fs = require('fs')
const path = require('path'); const path = require('path')
const spawn = require('child_process').spawn; const spawn = require('child_process').spawn
// i.e. my-app/app-0.1.13/ // i.e. my-app/app-0.1.13/
const appFolder = path.dirname(process.execPath); const appFolder = path.dirname(process.execPath)
// i.e. my-app/Update.exe // i.e. my-app/Update.exe
const updateExe = path.resolve(appFolder, '..', 'Update.exe'); const updateExe = path.resolve(appFolder, '..', 'Update.exe')
const exeName = path.basename(process.execPath); const exeName = path.basename(process.execPath)
// Spawn a command and invoke the callback when it completes with an error // Spawn a command and invoke the callback when it completes with an error
// and the output from standard out. // and the output from standard out.
var spawnUpdate = function(args, detached, callback) { var spawnUpdate = function (args, detached, callback) {
var error, errorEmitted, spawnedProcess, stderr, stdout; var error, errorEmitted, spawnedProcess, stderr, stdout
try { try {
spawnedProcess = spawn(updateExe, args, { spawnedProcess = spawn(updateExe, args, {
detached: detached detached: detached
}); })
} catch (error1) { } catch (error1) {
error = error1; error = error1
// Shouldn't happen, but still guard it. // Shouldn't happen, but still guard it.
process.nextTick(function() { process.nextTick(function () {
return callback(error); return callback(error)
}); })
return; return
} }
stdout = ''; stdout = ''
stderr = ''; stderr = ''
spawnedProcess.stdout.on('data', function(data) { spawnedProcess.stdout.on('data', function (data) {
return stdout += data; stdout += data
}); })
spawnedProcess.stderr.on('data', function(data) { spawnedProcess.stderr.on('data', function (data) {
return stderr += data; stderr += data
}); })
errorEmitted = false; errorEmitted = false
spawnedProcess.on('error', function(error) { spawnedProcess.on('error', function (error) {
errorEmitted = true; errorEmitted = true
return callback(error); return callback(error)
}); })
return spawnedProcess.on('exit', function(code, signal) { return spawnedProcess.on('exit', function (code, signal) {
// We may have already emitted an error. // We may have already emitted an error.
if (errorEmitted) { if (errorEmitted) {
return; return
} }
// Process terminated with error. // Process terminated with error.
if (code !== 0) { if (code !== 0) {
return callback("Command failed: " + (signal != null ? signal : code) + "\n" + stderr); return callback('Command failed: ' + (signal != null ? signal : code) + '\n' + stderr)
} }
// Success. // Success.
return callback(null, stdout); return callback(null, stdout)
}); })
}; }
// Start an instance of the installed app. // Start an instance of the installed app.
exports.processStart = function() { exports.processStart = function () {
return spawnUpdate(['--processStart', exeName], true, function() {}); return spawnUpdate(['--processStart', exeName], true, function () {})
}; }
// Download the releases specified by the URL and write new results to stdout. // Download the releases specified by the URL and write new results to stdout.
exports.download = function(updateURL, callback) { exports.download = function (updateURL, callback) {
return spawnUpdate(['--download', updateURL], false, function(error, stdout) { return spawnUpdate(['--download', updateURL], false, function (error, stdout) {
var json, ref, ref1, update; var json, ref, ref1, update
if (error != null) { if (error != null) {
return callback(error); return callback(error)
} }
try { try {
// Last line of output is the JSON details about the releases // Last line of output is the JSON details about the releases
json = stdout.trim().split('\n').pop(); json = stdout.trim().split('\n').pop()
update = (ref = JSON.parse(json)) != null ? (ref1 = ref.releasesToApply) != null ? typeof ref1.pop === "function" ? ref1.pop() : void 0 : void 0 : void 0; update = (ref = JSON.parse(json)) != null ? (ref1 = ref.releasesToApply) != null ? typeof ref1.pop === 'function' ? ref1.pop() : void 0 : void 0 : void 0
} catch (jsonError) { } catch (jsonError) {
return callback("Invalid result:\n" + stdout); return callback('Invalid result:\n' + stdout)
} }
return callback(null, update); return callback(null, update)
}); })
}; }
// Update the application to the latest remote version specified by URL. // Update the application to the latest remote version specified by URL.
exports.update = function(updateURL, callback) { exports.update = function (updateURL, callback) {
return spawnUpdate(['--update', updateURL], false, callback); return spawnUpdate(['--update', updateURL], false, callback)
}; }
// Is the Update.exe installed with the current application? // Is the Update.exe installed with the current application?
exports.supported = function() { exports.supported = function () {
try { try {
fs.accessSync(updateExe, fs.R_OK); fs.accessSync(updateExe, fs.R_OK)
return true; return true
} catch (error) { } catch (error) {
return false; return false
} }
}; }

View file

@ -1,65 +1,64 @@
'use strict'; 'use strict'
const ipcMain = require('electron').ipcMain; const ipcMain = require('electron').ipcMain
const deprecate = require('electron').deprecate; const deprecate = require('electron').deprecate
const EventEmitter = require('events').EventEmitter; const EventEmitter = require('events').EventEmitter
const {BrowserWindow, _setDeprecatedOptionsCheck} = process.atomBinding('window'); const {BrowserWindow, _setDeprecatedOptionsCheck} = process.atomBinding('window')
BrowserWindow.prototype.__proto__ = EventEmitter.prototype; Object.setPrototypeOf(BrowserWindow.prototype, EventEmitter.prototype)
BrowserWindow.prototype._init = function() { BrowserWindow.prototype._init = function () {
// avoid recursive require. // avoid recursive require.
var app, menu; var app, menu
app = require('electron').app; app = require('electron').app
// Simulate the application menu on platforms other than OS X. // Simulate the application menu on platforms other than OS X.
if (process.platform !== 'darwin') { if (process.platform !== 'darwin') {
menu = app.getApplicationMenu(); menu = app.getApplicationMenu()
if (menu != null) { if (menu != null) {
this.setMenu(menu); this.setMenu(menu)
} }
} }
// Make new windows requested by links behave like "window.open" // Make new windows requested by links behave like "window.open"
this.webContents.on('-new-window', (event, url, frameName) => { this.webContents.on('-new-window', (event, url, frameName) => {
var options; var options
options = { options = {
show: true, show: true,
width: 800, width: 800,
height: 600 height: 600
}; }
return ipcMain.emit('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', event, url, frameName, options); return ipcMain.emit('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', event, url, frameName, options)
}); })
// window.resizeTo(...) // window.resizeTo(...)
// window.moveTo(...) // window.moveTo(...)
this.webContents.on('move', (event, size) => { this.webContents.on('move', (event, size) => {
this.setBounds(size); this.setBounds(size)
}); })
// Hide the auto-hide menu when webContents is focused. // Hide the auto-hide menu when webContents is focused.
this.webContents.on('activate', () => { this.webContents.on('activate', () => {
if (process.platform !== 'darwin' && this.isMenuBarAutoHide() && this.isMenuBarVisible()) { if (process.platform !== 'darwin' && this.isMenuBarAutoHide() && this.isMenuBarVisible()) {
this.setMenuBarVisibility(false); this.setMenuBarVisibility(false)
} }
}); })
// Forward the crashed event. // Forward the crashed event.
this.webContents.on('crashed', () => { this.webContents.on('crashed', () => {
this.emit('crashed'); this.emit('crashed')
}); })
// Change window title to page title. // Change window title to page title.
this.webContents.on('page-title-updated', (event, title) => { this.webContents.on('page-title-updated', (event, title) => {
// The page-title-updated event is not emitted immediately (see #3645), so // The page-title-updated event is not emitted immediately (see #3645), so
// when the callback is called the BrowserWindow might have been closed. // when the callback is called the BrowserWindow might have been closed.
if (this.isDestroyed()) if (this.isDestroyed()) return
return;
// Route the event to BrowserWindow. // Route the event to BrowserWindow.
this.emit('page-title-updated', event, title); this.emit('page-title-updated', event, title)
if (!event.defaultPrevented) if (!event.defaultPrevented) this.setTitle(title)
this.setTitle(title); })
});
// Sometimes the webContents doesn't get focus when window is shown, so we have // Sometimes the webContents doesn't get focus when window is shown, so we have
// to force focusing on webContents in this case. The safest way is to focus it // to force focusing on webContents in this case. The safest way is to focus it
@ -67,228 +66,228 @@ BrowserWindow.prototype._init = function() {
// if we do it later we might move focus in the page. // if we do it later we might move focus in the page.
// Though this hack is only needed on OS X when the app is launched from // Though this hack is only needed on OS X when the app is launched from
// Finder, we still do it on all platforms in case of other bugs we don't know. // Finder, we still do it on all platforms in case of other bugs we don't know.
this.webContents.once('load-url', function() { this.webContents.once('load-url', function () {
this.focus(); this.focus()
}); })
// Redirect focus/blur event to app instance too. // Redirect focus/blur event to app instance too.
this.on('blur', (event) => { this.on('blur', (event) => {
app.emit('browser-window-blur', event, this); app.emit('browser-window-blur', event, this)
}); })
this.on('focus', (event) => { this.on('focus', (event) => {
app.emit('browser-window-focus', event, this); app.emit('browser-window-focus', event, this)
}); })
// Evented visibilityState changes // Evented visibilityState changes
this.on('show', () => { this.on('show', () => {
this.webContents.send('ATOM_RENDERER_WINDOW_VISIBILITY_CHANGE', this.isVisible(), this.isMinimized()); this.webContents.send('ATOM_RENDERER_WINDOW_VISIBILITY_CHANGE', this.isVisible(), this.isMinimized())
}); })
this.on('hide', () => { this.on('hide', () => {
this.webContents.send('ATOM_RENDERER_WINDOW_VISIBILITY_CHANGE', this.isVisible(), this.isMinimized()); this.webContents.send('ATOM_RENDERER_WINDOW_VISIBILITY_CHANGE', this.isVisible(), this.isMinimized())
}); })
this.on('minimize', () => { this.on('minimize', () => {
this.webContents.send('ATOM_RENDERER_WINDOW_VISIBILITY_CHANGE', this.isVisible(), this.isMinimized()); this.webContents.send('ATOM_RENDERER_WINDOW_VISIBILITY_CHANGE', this.isVisible(), this.isMinimized())
}); })
this.on('restore', () => { this.on('restore', () => {
this.webContents.send('ATOM_RENDERER_WINDOW_VISIBILITY_CHANGE', this.isVisible(), this.isMinimized()); this.webContents.send('ATOM_RENDERER_WINDOW_VISIBILITY_CHANGE', this.isVisible(), this.isMinimized())
}); })
// Notify the creation of the window. // Notify the creation of the window.
app.emit('browser-window-created', {}, this); app.emit('browser-window-created', {}, this)
// Be compatible with old APIs. // Be compatible with old APIs.
this.webContents.on('devtools-focused', () => { this.webContents.on('devtools-focused', () => {
this.emit('devtools-focused'); this.emit('devtools-focused')
}); })
this.webContents.on('devtools-opened', () => { this.webContents.on('devtools-opened', () => {
this.emit('devtools-opened'); this.emit('devtools-opened')
}); })
this.webContents.on('devtools-closed', () => { this.webContents.on('devtools-closed', () => {
this.emit('devtools-closed'); this.emit('devtools-closed')
}); })
Object.defineProperty(this, 'devToolsWebContents', { Object.defineProperty(this, 'devToolsWebContents', {
enumerable: true, enumerable: true,
configurable: false, configurable: false,
get: function() { get: function () {
return this.webContents.devToolsWebContents; return this.webContents.devToolsWebContents
} }
}); })
}; }
BrowserWindow.getFocusedWindow = function() { BrowserWindow.getFocusedWindow = function () {
var i, len, window, windows; var i, len, window, windows
windows = BrowserWindow.getAllWindows(); windows = BrowserWindow.getAllWindows()
for (i = 0, len = windows.length; i < len; i++) { for (i = 0, len = windows.length; i < len; i++) {
window = windows[i]; window = windows[i]
if (window.isFocused()) { if (window.isFocused()) {
return window; return window
} }
} }
return null; return null
}; }
BrowserWindow.fromWebContents = function(webContents) { BrowserWindow.fromWebContents = function (webContents) {
var i, len, ref1, window, windows; var i, len, ref1, window, windows
windows = BrowserWindow.getAllWindows(); windows = BrowserWindow.getAllWindows()
for (i = 0, len = windows.length; i < len; i++) { for (i = 0, len = windows.length; i < len; i++) {
window = windows[i]; window = windows[i]
if ((ref1 = window.webContents) != null ? ref1.equal(webContents) : void 0) { if ((ref1 = window.webContents) != null ? ref1.equal(webContents) : void 0) {
return window; return window
} }
} }
}; }
BrowserWindow.fromDevToolsWebContents = function(webContents) { BrowserWindow.fromDevToolsWebContents = function (webContents) {
var i, len, ref1, window, windows; var i, len, ref1, window, windows
windows = BrowserWindow.getAllWindows(); windows = BrowserWindow.getAllWindows()
for (i = 0, len = windows.length; i < len; i++) { for (i = 0, len = windows.length; i < len; i++) {
window = windows[i]; window = windows[i]
if ((ref1 = window.devToolsWebContents) != null ? ref1.equal(webContents) : void 0) { if ((ref1 = window.devToolsWebContents) != null ? ref1.equal(webContents) : void 0) {
return window; return window
} }
} }
}; }
// Helpers. // Helpers.
BrowserWindow.prototype.loadURL = function() { BrowserWindow.prototype.loadURL = function () {
return this.webContents.loadURL.apply(this.webContents, arguments); return this.webContents.loadURL.apply(this.webContents, arguments)
}; }
BrowserWindow.prototype.getURL = function() { BrowserWindow.prototype.getURL = function () {
return this.webContents.getURL(); return this.webContents.getURL()
}; }
BrowserWindow.prototype.reload = function() { BrowserWindow.prototype.reload = function () {
return this.webContents.reload.apply(this.webContents, arguments); return this.webContents.reload.apply(this.webContents, arguments)
}; }
BrowserWindow.prototype.send = function() { BrowserWindow.prototype.send = function () {
return this.webContents.send.apply(this.webContents, arguments); return this.webContents.send.apply(this.webContents, arguments)
}; }
BrowserWindow.prototype.openDevTools = function() { BrowserWindow.prototype.openDevTools = function () {
return this.webContents.openDevTools.apply(this.webContents, arguments); return this.webContents.openDevTools.apply(this.webContents, arguments)
}; }
BrowserWindow.prototype.closeDevTools = function() { BrowserWindow.prototype.closeDevTools = function () {
return this.webContents.closeDevTools(); return this.webContents.closeDevTools()
}; }
BrowserWindow.prototype.isDevToolsOpened = function() { BrowserWindow.prototype.isDevToolsOpened = function () {
return this.webContents.isDevToolsOpened(); return this.webContents.isDevToolsOpened()
}; }
BrowserWindow.prototype.isDevToolsFocused = function() { BrowserWindow.prototype.isDevToolsFocused = function () {
return this.webContents.isDevToolsFocused(); return this.webContents.isDevToolsFocused()
}; }
BrowserWindow.prototype.toggleDevTools = function() { BrowserWindow.prototype.toggleDevTools = function () {
return this.webContents.toggleDevTools(); return this.webContents.toggleDevTools()
}; }
BrowserWindow.prototype.inspectElement = function() { BrowserWindow.prototype.inspectElement = function () {
return this.webContents.inspectElement.apply(this.webContents, arguments); return this.webContents.inspectElement.apply(this.webContents, arguments)
}; }
BrowserWindow.prototype.inspectServiceWorker = function() { BrowserWindow.prototype.inspectServiceWorker = function () {
return this.webContents.inspectServiceWorker(); return this.webContents.inspectServiceWorker()
}; }
// Deprecated. // Deprecated.
deprecate.member(BrowserWindow, 'undo', 'webContents'); deprecate.member(BrowserWindow, 'undo', 'webContents')
deprecate.member(BrowserWindow, 'redo', 'webContents'); deprecate.member(BrowserWindow, 'redo', 'webContents')
deprecate.member(BrowserWindow, 'cut', 'webContents'); deprecate.member(BrowserWindow, 'cut', 'webContents')
deprecate.member(BrowserWindow, 'copy', 'webContents'); deprecate.member(BrowserWindow, 'copy', 'webContents')
deprecate.member(BrowserWindow, 'paste', 'webContents'); deprecate.member(BrowserWindow, 'paste', 'webContents')
deprecate.member(BrowserWindow, 'selectAll', 'webContents'); deprecate.member(BrowserWindow, 'selectAll', 'webContents')
deprecate.member(BrowserWindow, 'reloadIgnoringCache', 'webContents'); deprecate.member(BrowserWindow, 'reloadIgnoringCache', 'webContents')
deprecate.member(BrowserWindow, 'isLoading', 'webContents'); deprecate.member(BrowserWindow, 'isLoading', 'webContents')
deprecate.member(BrowserWindow, 'isWaitingForResponse', 'webContents'); deprecate.member(BrowserWindow, 'isWaitingForResponse', 'webContents')
deprecate.member(BrowserWindow, 'stop', 'webContents'); deprecate.member(BrowserWindow, 'stop', 'webContents')
deprecate.member(BrowserWindow, 'isCrashed', 'webContents'); deprecate.member(BrowserWindow, 'isCrashed', 'webContents')
deprecate.member(BrowserWindow, 'print', 'webContents'); deprecate.member(BrowserWindow, 'print', 'webContents')
deprecate.member(BrowserWindow, 'printToPDF', 'webContents'); deprecate.member(BrowserWindow, 'printToPDF', 'webContents')
deprecate.rename(BrowserWindow, 'restart', 'reload'); deprecate.rename(BrowserWindow, 'restart', 'reload')
deprecate.rename(BrowserWindow, 'loadUrl', 'loadURL'); deprecate.rename(BrowserWindow, 'loadUrl', 'loadURL')
deprecate.rename(BrowserWindow, 'getUrl', 'getURL'); deprecate.rename(BrowserWindow, 'getUrl', 'getURL')
BrowserWindow.prototype.executeJavaScriptInDevTools = deprecate('executeJavaScriptInDevTools', 'devToolsWebContents.executeJavaScript', function(code) { BrowserWindow.prototype.executeJavaScriptInDevTools = deprecate('executeJavaScriptInDevTools', 'devToolsWebContents.executeJavaScript', function (code) {
var ref1; var ref1
return (ref1 = this.devToolsWebContents) != null ? ref1.executeJavaScript(code) : void 0; return (ref1 = this.devToolsWebContents) != null ? ref1.executeJavaScript(code) : void 0
}); })
BrowserWindow.prototype.getPageTitle = deprecate('getPageTitle', 'webContents.getTitle', function() { BrowserWindow.prototype.getPageTitle = deprecate('getPageTitle', 'webContents.getTitle', function () {
var ref1; var ref1
return (ref1 = this.webContents) != null ? ref1.getTitle() : void 0; return (ref1 = this.webContents) != null ? ref1.getTitle() : void 0
}); })
const isDeprecatedKey = function(key) { const isDeprecatedKey = function (key) {
return key.indexOf('-') >= 0; return key.indexOf('-') >= 0
}; }
// Map deprecated key with hyphens to camel case key // Map deprecated key with hyphens to camel case key
const getNonDeprecatedKey = function(deprecatedKey) { const getNonDeprecatedKey = function (deprecatedKey) {
return deprecatedKey.replace(/-./g, function(match) { return deprecatedKey.replace(/-./g, function (match) {
return match[1].toUpperCase(); return match[1].toUpperCase()
}); })
}; }
// TODO Remove for 1.0 // TODO Remove for 1.0
const checkForDeprecatedOptions = function(options) { const checkForDeprecatedOptions = function (options) {
if (!options) return ''; if (!options) return ''
let keysToCheck = Object.keys(options); let keysToCheck = Object.keys(options)
if (options.webPreferences) { if (options.webPreferences) {
keysToCheck = keysToCheck.concat(Object.keys(options.webPreferences)); keysToCheck = keysToCheck.concat(Object.keys(options.webPreferences))
} }
// Check options for keys with hyphens in them // Check options for keys with hyphens in them
let deprecatedKey = keysToCheck.filter(isDeprecatedKey)[0]; let deprecatedKey = keysToCheck.filter(isDeprecatedKey)[0]
if (deprecatedKey) { if (deprecatedKey) {
try { try {
deprecate.warn(deprecatedKey, getNonDeprecatedKey(deprecatedKey)); deprecate.warn(deprecatedKey, getNonDeprecatedKey(deprecatedKey))
} catch (error) { } catch (error) {
// Return error message so it can be rethrown via C++ // Return error message so it can be rethrown via C++
return error.message; return error.message
} }
} }
let webPreferenceOption; let webPreferenceOption
if (options.hasOwnProperty('nodeIntegration')) { if (options.hasOwnProperty('nodeIntegration')) {
webPreferenceOption = 'nodeIntegration'; webPreferenceOption = 'nodeIntegration'
} else if (options.hasOwnProperty('preload')) { } else if (options.hasOwnProperty('preload')) {
webPreferenceOption = 'preload'; webPreferenceOption = 'preload'
} else if (options.hasOwnProperty('zoomFactor')) { } else if (options.hasOwnProperty('zoomFactor')) {
webPreferenceOption = 'zoomFactor'; webPreferenceOption = 'zoomFactor'
} }
if (webPreferenceOption) { if (webPreferenceOption) {
try { try {
deprecate.warn(`options.${webPreferenceOption}`, `options.webPreferences.${webPreferenceOption}`); deprecate.warn(`options.${webPreferenceOption}`, `options.webPreferences.${webPreferenceOption}`)
} catch (error) { } catch (error) {
// Return error message so it can be rethrown via C++ // Return error message so it can be rethrown via C++
return error.message; return error.message
} }
} }
return ''; return ''
}; }
_setDeprecatedOptionsCheck(checkForDeprecatedOptions); _setDeprecatedOptionsCheck(checkForDeprecatedOptions)
module.exports = BrowserWindow; module.exports = BrowserWindow

View file

@ -1 +1 @@
module.exports = process.atomBinding('content_tracing'); module.exports = process.atomBinding('content_tracing')

View file

@ -1,183 +1,183 @@
'use strict'; 'use strict'
const app = require('electron').app; const app = require('electron').app
const BrowserWindow = require('electron').BrowserWindow; const BrowserWindow = require('electron').BrowserWindow
const binding = process.atomBinding('dialog'); const binding = process.atomBinding('dialog')
const v8Util = process.atomBinding('v8_util'); const v8Util = process.atomBinding('v8_util')
var includes = [].includes; var includes = [].includes
var fileDialogProperties = { var fileDialogProperties = {
openFile: 1 << 0, openFile: 1 << 0,
openDirectory: 1 << 1, openDirectory: 1 << 1,
multiSelections: 1 << 2, multiSelections: 1 << 2,
createDirectory: 1 << 3 createDirectory: 1 << 3
}; }
var messageBoxTypes = ['none', 'info', 'warning', 'error', 'question']; var messageBoxTypes = ['none', 'info', 'warning', 'error', 'question']
var messageBoxOptions = { var messageBoxOptions = {
noLink: 1 << 0 noLink: 1 << 0
}; }
var parseArgs = function(window, options, callback) { var parseArgs = function (window, options, callback) {
if (!(window === null || (window != null ? window.constructor : void 0) === BrowserWindow)) { if (!(window === null || (window != null ? window.constructor : void 0) === BrowserWindow)) {
// Shift. // Shift.
callback = options; callback = options
options = window; options = window
window = null; window = null
} }
if ((callback == null) && typeof options === 'function') { if ((callback == null) && typeof options === 'function') {
// Shift. // Shift.
callback = options; callback = options
options = null; options = null
} }
return [window, options, callback]; return [window, options, callback]
}; }
var checkAppInitialized = function() { var checkAppInitialized = function () {
if (!app.isReady()) { if (!app.isReady()) {
throw new Error('dialog module can only be used after app is ready'); throw new Error('dialog module can only be used after app is ready')
} }
}; }
module.exports = { module.exports = {
showOpenDialog: function(...args) { showOpenDialog: function (...args) {
var prop, properties, value, wrappedCallback; var prop, properties, value, wrappedCallback
checkAppInitialized(); checkAppInitialized()
let [window, options, callback] = parseArgs.apply(null, args); let [window, options, callback] = parseArgs.apply(null, args)
if (options == null) { if (options == null) {
options = { options = {
title: 'Open', title: 'Open',
properties: ['openFile'] properties: ['openFile']
}; }
} }
if (options.properties == null) { if (options.properties == null) {
options.properties = ['openFile']; options.properties = ['openFile']
} }
if (!Array.isArray(options.properties)) { if (!Array.isArray(options.properties)) {
throw new TypeError('Properties must be an array'); throw new TypeError('Properties must be an array')
} }
properties = 0; properties = 0
for (prop in fileDialogProperties) { for (prop in fileDialogProperties) {
value = fileDialogProperties[prop]; value = fileDialogProperties[prop]
if (includes.call(options.properties, prop)) { if (includes.call(options.properties, prop)) {
properties |= value; properties |= value
} }
} }
if (options.title == null) { if (options.title == null) {
options.title = ''; options.title = ''
} else if (typeof options.title !== 'string') { } else if (typeof options.title !== 'string') {
throw new TypeError('Title must be a string'); throw new TypeError('Title must be a string')
} }
if (options.defaultPath == null) { if (options.defaultPath == null) {
options.defaultPath = ''; options.defaultPath = ''
} else if (typeof options.defaultPath !== 'string') { } else if (typeof options.defaultPath !== 'string') {
throw new TypeError('Default path must be a string'); throw new TypeError('Default path must be a string')
} }
if (options.filters == null) { if (options.filters == null) {
options.filters = []; options.filters = []
} }
wrappedCallback = typeof callback === 'function' ? function(success, result) { wrappedCallback = typeof callback === 'function' ? function (success, result) {
return callback(success ? result : void 0); return callback(success ? result : void 0)
} : null; } : null
return binding.showOpenDialog(String(options.title), String(options.defaultPath), options.filters, properties, window, wrappedCallback); return binding.showOpenDialog(String(options.title), String(options.defaultPath), options.filters, properties, window, wrappedCallback)
}, },
showSaveDialog: function(...args) { showSaveDialog: function (...args) {
var wrappedCallback; var wrappedCallback
checkAppInitialized(); checkAppInitialized()
let [window, options, callback] = parseArgs.apply(null, args); let [window, options, callback] = parseArgs.apply(null, args)
if (options == null) { if (options == null) {
options = { options = {
title: 'Save' title: 'Save'
}; }
} }
if (options.title == null) { if (options.title == null) {
options.title = ''; options.title = ''
} else if (typeof options.title !== 'string') { } else if (typeof options.title !== 'string') {
throw new TypeError('Title must be a string'); throw new TypeError('Title must be a string')
} }
if (options.defaultPath == null) { if (options.defaultPath == null) {
options.defaultPath = ''; options.defaultPath = ''
} else if (typeof options.defaultPath !== 'string') { } else if (typeof options.defaultPath !== 'string') {
throw new TypeError('Default path must be a string'); throw new TypeError('Default path must be a string')
} }
if (options.filters == null) { if (options.filters == null) {
options.filters = []; options.filters = []
} }
wrappedCallback = typeof callback === 'function' ? function(success, result) { wrappedCallback = typeof callback === 'function' ? function (success, result) {
return callback(success ? result : void 0); return callback(success ? result : void 0)
} : null; } : null
return binding.showSaveDialog(String(options.title), String(options.defaultPath), options.filters, window, wrappedCallback); return binding.showSaveDialog(String(options.title), String(options.defaultPath), options.filters, window, wrappedCallback)
}, },
showMessageBox: function(...args) { showMessageBox: function (...args) {
var flags, i, j, len, messageBoxType, ref2, ref3, text; var flags, i, j, len, messageBoxType, ref2, ref3, text
checkAppInitialized(); checkAppInitialized()
let [window, options, callback] = parseArgs.apply(null, args); let [window, options, callback] = parseArgs.apply(null, args)
if (options == null) { if (options == null) {
options = { options = {
type: 'none' type: 'none'
}; }
} }
if (options.type == null) { if (options.type == null) {
options.type = 'none'; options.type = 'none'
} }
messageBoxType = messageBoxTypes.indexOf(options.type); messageBoxType = messageBoxTypes.indexOf(options.type)
if (!(messageBoxType > -1)) { if (!(messageBoxType > -1)) {
throw new TypeError('Invalid message box type'); throw new TypeError('Invalid message box type')
} }
if (!Array.isArray(options.buttons)) { if (!Array.isArray(options.buttons)) {
throw new TypeError('Buttons must be an array'); throw new TypeError('Buttons must be an array')
} }
if (options.title == null) { if (options.title == null) {
options.title = ''; options.title = ''
} else if (typeof options.title !== 'string') { } else if (typeof options.title !== 'string') {
throw new TypeError('Title must be a string'); throw new TypeError('Title must be a string')
} }
if (options.message == null) { if (options.message == null) {
options.message = ''; options.message = ''
} else if (typeof options.message !== 'string') { } else if (typeof options.message !== 'string') {
throw new TypeError('Message must be a string'); throw new TypeError('Message must be a string')
} }
if (options.detail == null) { if (options.detail == null) {
options.detail = ''; options.detail = ''
} else if (typeof options.detail !== 'string') { } else if (typeof options.detail !== 'string') {
throw new TypeError('Detail must be a string'); throw new TypeError('Detail must be a string')
} }
if (options.icon == null) { if (options.icon == null) {
options.icon = null; options.icon = null
} }
if (options.defaultId == null) { if (options.defaultId == null) {
options.defaultId = -1; options.defaultId = -1
} }
// Choose a default button to get selected when dialog is cancelled. // Choose a default button to get selected when dialog is cancelled.
if (options.cancelId == null) { if (options.cancelId == null) {
options.cancelId = 0; options.cancelId = 0
ref2 = options.buttons; ref2 = options.buttons
for (i = j = 0, len = ref2.length; j < len; i = ++j) { for (i = j = 0, len = ref2.length; j < len; i = ++j) {
text = ref2[i]; text = ref2[i]
if ((ref3 = text.toLowerCase()) === 'cancel' || ref3 === 'no') { if ((ref3 = text.toLowerCase()) === 'cancel' || ref3 === 'no') {
options.cancelId = i; options.cancelId = i
break; break
} }
} }
} }
flags = options.noLink ? messageBoxOptions.noLink : 0; flags = options.noLink ? messageBoxOptions.noLink : 0
return binding.showMessageBox(messageBoxType, options.buttons, options.defaultId, options.cancelId, flags, options.title, options.message, options.detail, options.icon, window, callback); return binding.showMessageBox(messageBoxType, options.buttons, options.defaultId, options.cancelId, flags, options.title, options.message, options.detail, options.icon, window, callback)
}, },
showErrorBox: function(...args) { showErrorBox: function (...args) {
return binding.showErrorBox.apply(binding, args); return binding.showErrorBox.apply(binding, args)
} }
}; }
// Mark standard asynchronous functions. // Mark standard asynchronous functions.
var ref1 = ['showMessageBox', 'showOpenDialog', 'showSaveDialog']; var ref1 = ['showMessageBox', 'showOpenDialog', 'showSaveDialog']
var j, len, api; var j, len, api
for (j = 0, len = ref1.length; j < len; j++) { for (j = 0, len = ref1.length; j < len; j++) {
api = ref1[j]; api = ref1[j]
v8Util.setHiddenValue(module.exports[api], 'asynchronous', true); v8Util.setHiddenValue(module.exports[api], 'asynchronous', true)
} }

View file

@ -1,112 +1,110 @@
const common = require('../../../common/api/exports/electron'); const common = require('../../../common/api/exports/electron')
// Import common modules. // Import common modules.
common.defineProperties(exports); common.defineProperties(exports)
Object.defineProperties(exports, { Object.defineProperties(exports, {
// Browser side modules, please sort with alphabet order. // Browser side modules, please sort with alphabet order.
app: { app: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../app'); return require('../app')
} }
}, },
autoUpdater: { autoUpdater: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../auto-updater'); return require('../auto-updater')
} }
}, },
BrowserWindow: { BrowserWindow: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../browser-window'); return require('../browser-window')
} }
}, },
contentTracing: { contentTracing: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../content-tracing'); return require('../content-tracing')
} }
}, },
dialog: { dialog: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../dialog'); return require('../dialog')
} }
}, },
ipcMain: { ipcMain: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../ipc-main'); return require('../ipc-main')
} }
}, },
globalShortcut: { globalShortcut: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../global-shortcut'); return require('../global-shortcut')
} }
}, },
Menu: { Menu: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../menu'); return require('../menu')
} }
}, },
MenuItem: { MenuItem: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../menu-item'); return require('../menu-item')
} }
}, },
powerMonitor: { powerMonitor: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../power-monitor'); return require('../power-monitor')
} }
}, },
powerSaveBlocker: { powerSaveBlocker: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../power-save-blocker'); return require('../power-save-blocker')
} }
}, },
protocol: { protocol: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../protocol'); return require('../protocol')
} }
}, },
screen: { screen: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../screen'); return require('../screen')
} }
}, },
session: { session: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../session'); return require('../session')
} }
}, },
Tray: { Tray: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../tray'); return require('../tray')
} }
}, },
// The internal modules, invisible unless you know their names. // The internal modules, invisible unless you know their names.
NavigationController: { NavigationController: {
get: function() { get: function () {
return require('../navigation-controller'); return require('../navigation-controller')
} }
}, },
webContents: { webContents: {
get: function() { get: function () {
return require('../web-contents'); return require('../web-contents')
} }
} }
}); })

View file

@ -1,5 +1,5 @@
var globalShortcut; var globalShortcut
globalShortcut = process.atomBinding('global_shortcut').globalShortcut; globalShortcut = process.atomBinding('global_shortcut').globalShortcut
module.exports = globalShortcut; module.exports = globalShortcut

View file

@ -1,3 +1,3 @@
const EventEmitter = require('events').EventEmitter; const EventEmitter = require('events').EventEmitter
module.exports = new EventEmitter; module.exports = new EventEmitter()

View file

@ -1,7 +1,7 @@
const deprecate = require('electron').deprecate; const deprecate = require('electron').deprecate
const ipcMain = require('electron').ipcMain; const ipcMain = require('electron').ipcMain
// This module is deprecated, we mirror everything from ipcMain. // This module is deprecated, we mirror everything from ipcMain.
deprecate.warn('ipc module', 'require("electron").ipcMain'); deprecate.warn('ipc module', 'require("electron").ipcMain')
module.exports = ipcMain; module.exports = ipcMain

View file

@ -1,8 +1,8 @@
'use strict'; 'use strict'
var MenuItem, methodInBrowserWindow, nextCommandId, rolesMap; var MenuItem, methodInBrowserWindow, nextCommandId, rolesMap
nextCommandId = 0; nextCommandId = 0
// Maps role to methods of webContents // Maps role to methods of webContents
rolesMap = { rolesMap = {
@ -15,88 +15,98 @@ rolesMap = {
minimize: 'minimize', minimize: 'minimize',
close: 'close', close: 'close',
delete: 'delete' delete: 'delete'
}; }
// Maps methods that should be called directly on the BrowserWindow instance // Maps methods that should be called directly on the BrowserWindow instance
methodInBrowserWindow = { methodInBrowserWindow = {
minimize: true, minimize: true,
close: true close: true
}; }
MenuItem = (function() { MenuItem = (function () {
MenuItem.types = ['normal', 'separator', 'submenu', 'checkbox', 'radio']; MenuItem.types = ['normal', 'separator', 'submenu', 'checkbox', 'radio']
function MenuItem(options) { function MenuItem (options) {
var click, ref; var click, ref
const Menu = require('electron').Menu; const Menu = require('electron').Menu
click = options.click, this.selector = options.selector, this.type = options.type, this.role = options.role, this.label = options.label, this.sublabel = options.sublabel, this.accelerator = options.accelerator, this.icon = options.icon, this.enabled = options.enabled, this.visible = options.visible, this.checked = options.checked, this.submenu = options.submenu; click = options.click
this.selector = options.selector
this.type = options.type
this.role = options.role
this.label = options.label
this.sublabel = options.sublabel
this.accelerator = options.accelerator
this.icon = options.icon
this.enabled = options.enabled
this.visible = options.visible
this.checked = options.checked
this.submenu = options.submenu
if ((this.submenu != null) && this.submenu.constructor !== Menu) { if ((this.submenu != null) && this.submenu.constructor !== Menu) {
this.submenu = Menu.buildFromTemplate(this.submenu); this.submenu = Menu.buildFromTemplate(this.submenu)
} }
if ((this.type == null) && (this.submenu != null)) { if ((this.type == null) && (this.submenu != null)) {
this.type = 'submenu'; this.type = 'submenu'
} }
if (this.type === 'submenu' && ((ref = this.submenu) != null ? ref.constructor : void 0) !== Menu) { if (this.type === 'submenu' && ((ref = this.submenu) != null ? ref.constructor : void 0) !== Menu) {
throw new Error('Invalid submenu'); throw new Error('Invalid submenu')
} }
this.overrideReadOnlyProperty('type', 'normal'); this.overrideReadOnlyProperty('type', 'normal')
this.overrideReadOnlyProperty('role'); this.overrideReadOnlyProperty('role')
this.overrideReadOnlyProperty('accelerator'); this.overrideReadOnlyProperty('accelerator')
this.overrideReadOnlyProperty('icon'); this.overrideReadOnlyProperty('icon')
this.overrideReadOnlyProperty('submenu'); this.overrideReadOnlyProperty('submenu')
this.overrideProperty('label', ''); this.overrideProperty('label', '')
this.overrideProperty('sublabel', ''); this.overrideProperty('sublabel', '')
this.overrideProperty('enabled', true); this.overrideProperty('enabled', true)
this.overrideProperty('visible', true); this.overrideProperty('visible', true)
this.overrideProperty('checked', false); this.overrideProperty('checked', false)
if (MenuItem.types.indexOf(this.type) === -1) { if (MenuItem.types.indexOf(this.type) === -1) {
throw new Error("Unknown menu type " + this.type); throw new Error('Unknown menu type ' + this.type)
} }
this.commandId = ++nextCommandId; this.commandId = ++nextCommandId
this.click = (focusedWindow) => { this.click = (focusedWindow) => {
// Manually flip the checked flags when clicked. // Manually flip the checked flags when clicked.
var methodName, ref1, ref2; var methodName, ref1, ref2
if ((ref1 = this.type) === 'checkbox' || ref1 === 'radio') { if ((ref1 = this.type) === 'checkbox' || ref1 === 'radio') {
this.checked = !this.checked; this.checked = !this.checked
} }
if (this.role && rolesMap[this.role] && process.platform !== 'darwin' && (focusedWindow != null)) { if (this.role && rolesMap[this.role] && process.platform !== 'darwin' && (focusedWindow != null)) {
methodName = rolesMap[this.role]; methodName = rolesMap[this.role]
if (methodInBrowserWindow[methodName]) { if (methodInBrowserWindow[methodName]) {
return focusedWindow[methodName](); return focusedWindow[methodName]()
} else { } else {
return (ref2 = focusedWindow.webContents) != null ? ref2[methodName]() : void 0; return (ref2 = focusedWindow.webContents) != null ? ref2[methodName]() : void 0
} }
} else if (typeof click === 'function') { } else if (typeof click === 'function') {
return click(this, focusedWindow); return click(this, focusedWindow)
} else if (typeof this.selector === 'string' && process.platform === 'darwin') { } else if (typeof this.selector === 'string' && process.platform === 'darwin') {
return Menu.sendActionToFirstResponder(this.selector); return Menu.sendActionToFirstResponder(this.selector)
} }
}; }
} }
MenuItem.prototype.overrideProperty = function(name, defaultValue) { MenuItem.prototype.overrideProperty = function (name, defaultValue) {
if (defaultValue == null) { if (defaultValue == null) {
defaultValue = null; defaultValue = null
} }
return this[name] != null ? this[name] : this[name] = defaultValue; return this[name] != null ? this[name] : this[name] = defaultValue
}; }
MenuItem.prototype.overrideReadOnlyProperty = function(name, defaultValue) { MenuItem.prototype.overrideReadOnlyProperty = function (name, defaultValue) {
if (defaultValue == null) { if (defaultValue == null) {
defaultValue = null; defaultValue = null
} }
if (this[name] == null) { if (this[name] == null) {
this[name] = defaultValue; this[name] = defaultValue
} }
return Object.defineProperty(this, name, { return Object.defineProperty(this, name, {
enumerable: true, enumerable: true,
writable: false, writable: false,
value: this[name] value: this[name]
}); })
}; }
return MenuItem; return MenuItem
})()
})(); module.exports = MenuItem
module.exports = MenuItem;

View file

@ -1,70 +1,70 @@
'use strict'; 'use strict'
const BrowserWindow = require('electron').BrowserWindow; const BrowserWindow = require('electron').BrowserWindow
const MenuItem = require('electron').MenuItem; const MenuItem = require('electron').MenuItem
const EventEmitter = require('events').EventEmitter; const EventEmitter = require('events').EventEmitter
const v8Util = process.atomBinding('v8_util'); const v8Util = process.atomBinding('v8_util')
const bindings = process.atomBinding('menu'); const bindings = process.atomBinding('menu')
// Automatically generated radio menu item's group id. // Automatically generated radio menu item's group id.
var nextGroupId = 0; var nextGroupId = 0
// Search between separators to find a radio menu item and return its group id, // Search between separators to find a radio menu item and return its group id,
// otherwise generate a group id. // otherwise generate a group id.
var generateGroupId = function(items, pos) { var generateGroupId = function (items, pos) {
var i, item, j, k, ref1, ref2, ref3; var i, item, j, k, ref1, ref2, ref3
if (pos > 0) { if (pos > 0) {
for (i = j = ref1 = pos - 1; ref1 <= 0 ? j <= 0 : j >= 0; i = ref1 <= 0 ? ++j : --j) { for (i = j = ref1 = pos - 1; ref1 <= 0 ? j <= 0 : j >= 0; i = ref1 <= 0 ? ++j : --j) {
item = items[i]; item = items[i]
if (item.type === 'radio') { if (item.type === 'radio') {
return item.groupId; return item.groupId
} }
if (item.type === 'separator') { if (item.type === 'separator') {
break; break
} }
} }
} else if (pos < items.length) { } else if (pos < items.length) {
for (i = k = ref2 = pos, ref3 = items.length - 1; ref2 <= ref3 ? k <= ref3 : k >= ref3; i = ref2 <= ref3 ? ++k : --k) { for (i = k = ref2 = pos, ref3 = items.length - 1; ref2 <= ref3 ? k <= ref3 : k >= ref3; i = ref2 <= ref3 ? ++k : --k) {
item = items[i]; item = items[i]
if (item.type === 'radio') { if (item.type === 'radio') {
return item.groupId; return item.groupId
} }
if (item.type === 'separator') { if (item.type === 'separator') {
break; break
} }
} }
} }
return ++nextGroupId; return ++nextGroupId
}; }
// Returns the index of item according to |id|. // Returns the index of item according to |id|.
var indexOfItemById = function(items, id) { var indexOfItemById = function (items, id) {
var i, item, j, len; var i, item, j, len
for (i = j = 0, len = items.length; j < len; i = ++j) { for (i = j = 0, len = items.length; j < len; i = ++j) {
item = items[i]; item = items[i]
if (item.id === id) { if (item.id === id) {
return i; return i
} }
} }
return -1; return -1
}; }
// Returns the index of where to insert the item according to |position|. // Returns the index of where to insert the item according to |position|.
var indexToInsertByPosition = function(items, position) { var indexToInsertByPosition = function (items, position) {
var insertIndex; var insertIndex
if (!position) { if (!position) {
return items.length; return items.length
} }
const [query, id] = position.split('='); const [query, id] = position.split('=')
insertIndex = indexOfItemById(items, id); insertIndex = indexOfItemById(items, id)
if (insertIndex === -1 && query !== 'endof') { if (insertIndex === -1 && query !== 'endof') {
console.warn("Item with id '" + id + "' is not found"); console.warn("Item with id '" + id + "' is not found")
return items.length; return items.length
} }
switch (query) { switch (query) {
case 'after': case 'after':
insertIndex++; insertIndex++
break; break
case 'endof': case 'endof':
// If the |id| doesn't exist, then create a new group with the |id|. // If the |id| doesn't exist, then create a new group with the |id|.
@ -72,235 +72,234 @@ var indexToInsertByPosition = function(items, position) {
items.push({ items.push({
id: id, id: id,
type: 'separator' type: 'separator'
}); })
insertIndex = items.length - 1; insertIndex = items.length - 1
} }
// Find the end of the group. // Find the end of the group.
insertIndex++; insertIndex++
while (insertIndex < items.length && items[insertIndex].type !== 'separator') { while (insertIndex < items.length && items[insertIndex].type !== 'separator') {
insertIndex++; insertIndex++
} }
} }
return insertIndex; return insertIndex
}; }
const Menu = bindings.Menu; const Menu = bindings.Menu
Menu.prototype.__proto__ = EventEmitter.prototype; Object.setPrototypeOf(Menu.prototype, EventEmitter.prototype)
Menu.prototype._init = function() { Menu.prototype._init = function () {
this.commandsMap = {}; this.commandsMap = {}
this.groupsMap = {}; this.groupsMap = {}
this.items = []; this.items = []
return this.delegate = { this.delegate = {
isCommandIdChecked: (commandId) => { isCommandIdChecked: (commandId) => {
var command = this.commandsMap[commandId]; var command = this.commandsMap[commandId]
return command != null ? command.checked : undefined; return command != null ? command.checked : undefined
}, },
isCommandIdEnabled: (commandId) => { isCommandIdEnabled: (commandId) => {
var command = this.commandsMap[commandId]; var command = this.commandsMap[commandId]
return command != null ? command.enabled : undefined; return command != null ? command.enabled : undefined
}, },
isCommandIdVisible: (commandId) => { isCommandIdVisible: (commandId) => {
var command = this.commandsMap[commandId]; var command = this.commandsMap[commandId]
return command != null ? command.visible : undefined; return command != null ? command.visible : undefined
}, },
getAcceleratorForCommandId: (commandId) => { getAcceleratorForCommandId: (commandId) => {
var command = this.commandsMap[commandId]; var command = this.commandsMap[commandId]
return command != null ? command.accelerator : undefined; return command != null ? command.accelerator : undefined
}, },
getIconForCommandId: (commandId) => { getIconForCommandId: (commandId) => {
var command = this.commandsMap[commandId]; var command = this.commandsMap[commandId]
return command != null ? command.icon : undefined; return command != null ? command.icon : undefined
}, },
executeCommand: (commandId) => { executeCommand: (commandId) => {
var command = this.commandsMap[commandId]; var command = this.commandsMap[commandId]
return command != null ? command.click(BrowserWindow.getFocusedWindow()) : undefined; return command != null ? command.click(BrowserWindow.getFocusedWindow()) : undefined
}, },
menuWillShow: () => { menuWillShow: () => {
// Make sure radio groups have at least one menu item seleted. // Make sure radio groups have at least one menu item seleted.
var checked, group, id, j, len, radioItem, ref1; var checked, group, id, j, len, radioItem, ref1
ref1 = this.groupsMap; ref1 = this.groupsMap
for (id in ref1) { for (id in ref1) {
group = ref1[id]; group = ref1[id]
checked = false; checked = false
for (j = 0, len = group.length; j < len; j++) { for (j = 0, len = group.length; j < len; j++) {
radioItem = group[j]; radioItem = group[j]
if (!radioItem.checked) { if (!radioItem.checked) {
continue; continue
} }
checked = true; checked = true
break; break
} }
if (!checked) { if (!checked) {
v8Util.setHiddenValue(group[0], 'checked', true); v8Util.setHiddenValue(group[0], 'checked', true)
} }
} }
} }
}; }
}; }
Menu.prototype.popup = function(window, x, y, positioningItem) { Menu.prototype.popup = function (window, x, y, positioningItem) {
if (typeof window != 'object' || window.constructor !== BrowserWindow) { if (typeof window !== 'object' || window.constructor !== BrowserWindow) {
// Shift. // Shift.
positioningItem = y; positioningItem = y
y = x; y = x
x = window; x = window
window = BrowserWindow.getFocusedWindow(); window = BrowserWindow.getFocusedWindow()
} }
// Default parameters. // Default parameters.
if (typeof x !== 'number') x = -1; if (typeof x !== 'number') x = -1
if (typeof y !== 'number') y = -1; if (typeof y !== 'number') y = -1
if (typeof positioningItem !== 'number') positioningItem = 0; if (typeof positioningItem !== 'number') positioningItem = 0
this.popupAt(window, x, y, positioningItem); this.popupAt(window, x, y, positioningItem)
}; }
Menu.prototype.append = function(item) { Menu.prototype.append = function (item) {
return this.insert(this.getItemCount(), item); return this.insert(this.getItemCount(), item)
}; }
Menu.prototype.insert = function(pos, item) { Menu.prototype.insert = function (pos, item) {
var base, name; var base, name
if ((item != null ? item.constructor : void 0) !== MenuItem) { if ((item != null ? item.constructor : void 0) !== MenuItem) {
throw new TypeError('Invalid item'); throw new TypeError('Invalid item')
} }
switch (item.type) { switch (item.type) {
case 'normal': case 'normal':
this.insertItem(pos, item.commandId, item.label); this.insertItem(pos, item.commandId, item.label)
break; break
case 'checkbox': case 'checkbox':
this.insertCheckItem(pos, item.commandId, item.label); this.insertCheckItem(pos, item.commandId, item.label)
break; break
case 'separator': case 'separator':
this.insertSeparator(pos); this.insertSeparator(pos)
break; break
case 'submenu': case 'submenu':
this.insertSubMenu(pos, item.commandId, item.label, item.submenu); this.insertSubMenu(pos, item.commandId, item.label, item.submenu)
break; break
case 'radio': case 'radio':
// Grouping radio menu items. // Grouping radio menu items.
item.overrideReadOnlyProperty('groupId', generateGroupId(this.items, pos)); item.overrideReadOnlyProperty('groupId', generateGroupId(this.items, pos))
if ((base = this.groupsMap)[name = item.groupId] == null) { if ((base = this.groupsMap)[name = item.groupId] == null) {
base[name] = []; base[name] = []
} }
this.groupsMap[item.groupId].push(item); this.groupsMap[item.groupId].push(item)
// Setting a radio menu item should flip other items in the group. // Setting a radio menu item should flip other items in the group.
v8Util.setHiddenValue(item, 'checked', item.checked); v8Util.setHiddenValue(item, 'checked', item.checked)
Object.defineProperty(item, 'checked', { Object.defineProperty(item, 'checked', {
enumerable: true, enumerable: true,
get: function() { get: function () {
return v8Util.getHiddenValue(item, 'checked'); return v8Util.getHiddenValue(item, 'checked')
}, },
set: () => { set: () => {
var j, len, otherItem, ref1; var j, len, otherItem, ref1
ref1 = this.groupsMap[item.groupId]; ref1 = this.groupsMap[item.groupId]
for (j = 0, len = ref1.length; j < len; j++) { for (j = 0, len = ref1.length; j < len; j++) {
otherItem = ref1[j]; otherItem = ref1[j]
if (otherItem !== item) { if (otherItem !== item) {
v8Util.setHiddenValue(otherItem, 'checked', false); v8Util.setHiddenValue(otherItem, 'checked', false)
} }
} }
return v8Util.setHiddenValue(item, 'checked', true); return v8Util.setHiddenValue(item, 'checked', true)
} }
}); })
this.insertRadioItem(pos, item.commandId, item.label, item.groupId); this.insertRadioItem(pos, item.commandId, item.label, item.groupId)
} }
if (item.sublabel != null) { if (item.sublabel != null) {
this.setSublabel(pos, item.sublabel); this.setSublabel(pos, item.sublabel)
} }
if (item.icon != null) { if (item.icon != null) {
this.setIcon(pos, item.icon); this.setIcon(pos, item.icon)
} }
if (item.role != null) { if (item.role != null) {
this.setRole(pos, item.role); this.setRole(pos, item.role)
} }
// Make menu accessable to items. // Make menu accessable to items.
item.overrideReadOnlyProperty('menu', this); item.overrideReadOnlyProperty('menu', this)
// Remember the items. // Remember the items.
this.items.splice(pos, 0, item); this.items.splice(pos, 0, item)
return this.commandsMap[item.commandId] = item; this.commandsMap[item.commandId] = item
}; }
// Force menuWillShow to be called // Force menuWillShow to be called
Menu.prototype._callMenuWillShow = function() { Menu.prototype._callMenuWillShow = function () {
if (this.delegate != null) { if (this.delegate != null) {
this.delegate.menuWillShow(); this.delegate.menuWillShow()
} }
this.items.forEach(function(item) { this.items.forEach(function (item) {
if (item.submenu != null) { if (item.submenu != null) {
item.submenu._callMenuWillShow(); item.submenu._callMenuWillShow()
} }
}); })
}; }
var applicationMenu = null; var applicationMenu = null
Menu.setApplicationMenu = function(menu) { Menu.setApplicationMenu = function (menu) {
if (!(menu === null || menu.constructor === Menu)) { if (!(menu === null || menu.constructor === Menu)) {
throw new TypeError('Invalid menu'); throw new TypeError('Invalid menu')
} }
// Keep a reference. // Keep a reference.
applicationMenu = menu; applicationMenu = menu
if (process.platform === 'darwin') { if (process.platform === 'darwin') {
if (menu === null) { if (menu === null) {
return; return
} }
menu._callMenuWillShow(); menu._callMenuWillShow()
bindings.setApplicationMenu(menu); bindings.setApplicationMenu(menu)
} else { } else {
BrowserWindow.getAllWindows().forEach(function(window) { BrowserWindow.getAllWindows().forEach(function (window) {
window.setMenu(menu); window.setMenu(menu)
}); })
} }
}; }
Menu.getApplicationMenu = function() { Menu.getApplicationMenu = function () {
return applicationMenu; return applicationMenu
}; }
Menu.sendActionToFirstResponder = bindings.sendActionToFirstResponder; Menu.sendActionToFirstResponder = bindings.sendActionToFirstResponder
Menu.buildFromTemplate = function(template) { Menu.buildFromTemplate = function (template) {
var insertIndex, item, j, k, key, len, len1, menu, menuItem, positionedTemplate; var insertIndex, item, j, k, key, len, len1, menu, menuItem, positionedTemplate
if (!Array.isArray(template)) { if (!Array.isArray(template)) {
throw new TypeError('Invalid template for Menu'); throw new TypeError('Invalid template for Menu')
} }
positionedTemplate = []; positionedTemplate = []
insertIndex = 0; insertIndex = 0
for (j = 0, len = template.length; j < len; j++) { for (j = 0, len = template.length; j < len; j++) {
item = template[j]; item = template[j]
if (item.position) { if (item.position) {
insertIndex = indexToInsertByPosition(positionedTemplate, item.position); insertIndex = indexToInsertByPosition(positionedTemplate, item.position)
} else { } else {
// If no |position| is specified, insert after last item. // If no |position| is specified, insert after last item.
insertIndex++; insertIndex++
} }
positionedTemplate.splice(insertIndex, 0, item); positionedTemplate.splice(insertIndex, 0, item)
} }
menu = new Menu; menu = new Menu()
for (k = 0, len1 = positionedTemplate.length; k < len1; k++) { for (k = 0, len1 = positionedTemplate.length; k < len1; k++) {
item = positionedTemplate[k]; item = positionedTemplate[k]
if (typeof item !== 'object') { if (typeof item !== 'object') {
throw new TypeError('Invalid template for MenuItem'); throw new TypeError('Invalid template for MenuItem')
} }
menuItem = new MenuItem(item); menuItem = new MenuItem(item)
for (key in item) { for (key in item) {
// Preserve extra fields specified by user // Preserve extra fields specified by user
if (!menuItem.hasOwnProperty(key)) { if (!menuItem.hasOwnProperty(key)) {
menuItem[key] = item[key]; menuItem[key] = item[key]
} }
} }
menu.append(menuItem); menu.append(menuItem)
} }
return menu; return menu
}; }
module.exports = Menu; module.exports = Menu

View file

@ -1,179 +1,178 @@
'use strict'; 'use strict'
const ipcMain = require('electron').ipcMain; const ipcMain = require('electron').ipcMain
// The history operation in renderer is redirected to browser. // The history operation in renderer is redirected to browser.
ipcMain.on('ATOM_SHELL_NAVIGATION_CONTROLLER', function(event, method, ...args) { ipcMain.on('ATOM_SHELL_NAVIGATION_CONTROLLER', function (event, method, ...args) {
var ref; var ref
return (ref = event.sender)[method].apply(ref, args); (ref = event.sender)[method].apply(ref, args)
}); })
ipcMain.on('ATOM_SHELL_SYNC_NAVIGATION_CONTROLLER', function(event, method, ...args) { ipcMain.on('ATOM_SHELL_SYNC_NAVIGATION_CONTROLLER', function (event, method, ...args) {
var ref; var ref
return event.returnValue = (ref = event.sender)[method].apply(ref, args); event.returnValue = (ref = event.sender)[method].apply(ref, args)
}); })
// JavaScript implementation of Chromium's NavigationController. // JavaScript implementation of Chromium's NavigationController.
// Instead of relying on Chromium for history control, we compeletely do history // Instead of relying on Chromium for history control, we compeletely do history
// control on user land, and only rely on WebContents.loadURL for navigation. // control on user land, and only rely on WebContents.loadURL for navigation.
// This helps us avoid Chromium's various optimizations so we can ensure renderer // This helps us avoid Chromium's various optimizations so we can ensure renderer
// process is restarted everytime. // process is restarted everytime.
var NavigationController = (function() { var NavigationController = (function () {
function NavigationController(webContents) { function NavigationController (webContents) {
this.webContents = webContents; this.webContents = webContents
this.clearHistory(); this.clearHistory()
// webContents may have already navigated to a page. // webContents may have already navigated to a page.
if (this.webContents._getURL()) { if (this.webContents._getURL()) {
this.currentIndex++; this.currentIndex++
this.history.push(this.webContents._getURL()); this.history.push(this.webContents._getURL())
} }
this.webContents.on('navigation-entry-commited', (event, url, inPage, replaceEntry) => { this.webContents.on('navigation-entry-commited', (event, url, inPage, replaceEntry) => {
var currentEntry; var currentEntry
if (this.inPageIndex > -1 && !inPage) { if (this.inPageIndex > -1 && !inPage) {
// Navigated to a new page, clear in-page mark. // Navigated to a new page, clear in-page mark.
this.inPageIndex = -1; this.inPageIndex = -1
} else if (this.inPageIndex === -1 && inPage) { } else if (this.inPageIndex === -1 && inPage) {
// Started in-page navigations. // Started in-page navigations.
this.inPageIndex = this.currentIndex; this.inPageIndex = this.currentIndex
} }
if (this.pendingIndex >= 0) { if (this.pendingIndex >= 0) {
// Go to index. // Go to index.
this.currentIndex = this.pendingIndex; this.currentIndex = this.pendingIndex
this.pendingIndex = -1; this.pendingIndex = -1
return this.history[this.currentIndex] = url; this.history[this.currentIndex] = url
} else if (replaceEntry) { } else if (replaceEntry) {
// Non-user initialized navigation. // Non-user initialized navigation.
return this.history[this.currentIndex] = url; this.history[this.currentIndex] = url
} else { } else {
// Normal navigation. Clear history. // Normal navigation. Clear history.
this.history = this.history.slice(0, this.currentIndex + 1); this.history = this.history.slice(0, this.currentIndex + 1)
currentEntry = this.history[this.currentIndex]; currentEntry = this.history[this.currentIndex]
if ((currentEntry != null ? currentEntry.url : void 0) !== url) { if ((currentEntry != null ? currentEntry.url : void 0) !== url) {
this.currentIndex++; this.currentIndex++
return this.history.push(url); return this.history.push(url)
} }
} }
}); })
} }
NavigationController.prototype.loadURL = function(url, options) { NavigationController.prototype.loadURL = function (url, options) {
if (options == null) { if (options == null) {
options = {}; options = {}
} }
this.pendingIndex = -1; this.pendingIndex = -1
this.webContents._loadURL(url, options); this.webContents._loadURL(url, options)
return this.webContents.emit('load-url', url, options); return this.webContents.emit('load-url', url, options)
}; }
NavigationController.prototype.getURL = function() { NavigationController.prototype.getURL = function () {
if (this.currentIndex === -1) { if (this.currentIndex === -1) {
return ''; return ''
} else { } else {
return this.history[this.currentIndex]; return this.history[this.currentIndex]
} }
}; }
NavigationController.prototype.stop = function() { NavigationController.prototype.stop = function () {
this.pendingIndex = -1; this.pendingIndex = -1
return this.webContents._stop(); return this.webContents._stop()
}; }
NavigationController.prototype.reload = function() { NavigationController.prototype.reload = function () {
this.pendingIndex = this.currentIndex; this.pendingIndex = this.currentIndex
return this.webContents._loadURL(this.getURL(), {}); return this.webContents._loadURL(this.getURL(), {})
}; }
NavigationController.prototype.reloadIgnoringCache = function() { NavigationController.prototype.reloadIgnoringCache = function () {
this.pendingIndex = this.currentIndex; this.pendingIndex = this.currentIndex
return this.webContents._loadURL(this.getURL(), { return this.webContents._loadURL(this.getURL(), {
extraHeaders: "pragma: no-cache\n" extraHeaders: 'pragma: no-cache\n'
}); })
}; }
NavigationController.prototype.canGoBack = function() { NavigationController.prototype.canGoBack = function () {
return this.getActiveIndex() > 0; return this.getActiveIndex() > 0
}; }
NavigationController.prototype.canGoForward = function() { NavigationController.prototype.canGoForward = function () {
return this.getActiveIndex() < this.history.length - 1; return this.getActiveIndex() < this.history.length - 1
}; }
NavigationController.prototype.canGoToIndex = function(index) { NavigationController.prototype.canGoToIndex = function (index) {
return index >= 0 && index < this.history.length; return index >= 0 && index < this.history.length
}; }
NavigationController.prototype.canGoToOffset = function(offset) { NavigationController.prototype.canGoToOffset = function (offset) {
return this.canGoToIndex(this.currentIndex + offset); return this.canGoToIndex(this.currentIndex + offset)
}; }
NavigationController.prototype.clearHistory = function() { NavigationController.prototype.clearHistory = function () {
this.history = []; this.history = []
this.currentIndex = -1; this.currentIndex = -1
this.pendingIndex = -1; this.pendingIndex = -1
return this.inPageIndex = -1; this.inPageIndex = -1
}; }
NavigationController.prototype.goBack = function() { NavigationController.prototype.goBack = function () {
if (!this.canGoBack()) { if (!this.canGoBack()) {
return; return
} }
this.pendingIndex = this.getActiveIndex() - 1; this.pendingIndex = this.getActiveIndex() - 1
if (this.inPageIndex > -1 && this.pendingIndex >= this.inPageIndex) { if (this.inPageIndex > -1 && this.pendingIndex >= this.inPageIndex) {
return this.webContents._goBack(); return this.webContents._goBack()
} else { } else {
return this.webContents._loadURL(this.history[this.pendingIndex], {}); return this.webContents._loadURL(this.history[this.pendingIndex], {})
} }
}; }
NavigationController.prototype.goForward = function() { NavigationController.prototype.goForward = function () {
if (!this.canGoForward()) { if (!this.canGoForward()) {
return; return
} }
this.pendingIndex = this.getActiveIndex() + 1; this.pendingIndex = this.getActiveIndex() + 1
if (this.inPageIndex > -1 && this.pendingIndex >= this.inPageIndex) { if (this.inPageIndex > -1 && this.pendingIndex >= this.inPageIndex) {
return this.webContents._goForward(); return this.webContents._goForward()
} else { } else {
return this.webContents._loadURL(this.history[this.pendingIndex], {}); return this.webContents._loadURL(this.history[this.pendingIndex], {})
} }
}; }
NavigationController.prototype.goToIndex = function(index) { NavigationController.prototype.goToIndex = function (index) {
if (!this.canGoToIndex(index)) { if (!this.canGoToIndex(index)) {
return; return
} }
this.pendingIndex = index; this.pendingIndex = index
return this.webContents._loadURL(this.history[this.pendingIndex], {}); return this.webContents._loadURL(this.history[this.pendingIndex], {})
}; }
NavigationController.prototype.goToOffset = function(offset) { NavigationController.prototype.goToOffset = function (offset) {
var pendingIndex; var pendingIndex
if (!this.canGoToOffset(offset)) { if (!this.canGoToOffset(offset)) {
return; return
} }
pendingIndex = this.currentIndex + offset; pendingIndex = this.currentIndex + offset
if (this.inPageIndex > -1 && pendingIndex >= this.inPageIndex) { if (this.inPageIndex > -1 && pendingIndex >= this.inPageIndex) {
this.pendingIndex = pendingIndex; this.pendingIndex = pendingIndex
return this.webContents._goToOffset(offset); return this.webContents._goToOffset(offset)
} else { } else {
return this.goToIndex(pendingIndex); return this.goToIndex(pendingIndex)
} }
}; }
NavigationController.prototype.getActiveIndex = function() { NavigationController.prototype.getActiveIndex = function () {
if (this.pendingIndex === -1) { if (this.pendingIndex === -1) {
return this.currentIndex; return this.currentIndex
} else { } else {
return this.pendingIndex; return this.pendingIndex
} }
}; }
NavigationController.prototype.length = function() { NavigationController.prototype.length = function () {
return this.history.length; return this.history.length
}; }
return NavigationController; return NavigationController
})()
})(); module.exports = NavigationController
module.exports = NavigationController;

View file

@ -1,6 +1,6 @@
const EventEmitter = require('events').EventEmitter; const EventEmitter = require('events').EventEmitter
const powerMonitor = process.atomBinding('power_monitor').powerMonitor; const powerMonitor = process.atomBinding('power_monitor').powerMonitor
powerMonitor.__proto__ = EventEmitter.prototype; Object.setPrototypeOf(powerMonitor, EventEmitter.prototype)
module.exports = powerMonitor; module.exports = powerMonitor

View file

@ -1,5 +1,5 @@
var powerSaveBlocker; var powerSaveBlocker
powerSaveBlocker = process.atomBinding('power_save_blocker').powerSaveBlocker; powerSaveBlocker = process.atomBinding('power_save_blocker').powerSaveBlocker
module.exports = powerSaveBlocker; module.exports = powerSaveBlocker

View file

@ -1,31 +1,31 @@
const app = require('electron').app; const app = require('electron').app
if (!app.isReady()) { if (!app.isReady()) {
throw new Error('Can not initialize protocol module before app is ready'); throw new Error('Can not initialize protocol module before app is ready')
} }
const protocol = process.atomBinding('protocol').protocol; const protocol = process.atomBinding('protocol').protocol
// Warn about removed APIs. // Warn about removed APIs.
var logAndThrow = function(callback, message) { var logAndThrow = function (callback, message) {
console.error(message); console.error(message)
if (callback) { if (callback) {
return callback(new Error(message)); return callback(new Error(message))
} else { } else {
throw new Error(message); throw new Error(message)
} }
}; }
protocol.registerProtocol = function(scheme, handler, callback) { protocol.registerProtocol = function (scheme, handler, callback) {
return logAndThrow(callback, 'registerProtocol API has been replaced by the register[File/Http/Buffer/String]Protocol API family, please switch to the new APIs.'); return logAndThrow(callback, 'registerProtocol API has been replaced by the register[File/Http/Buffer/String]Protocol API family, please switch to the new APIs.')
}; }
protocol.isHandledProtocol = function(scheme, callback) { protocol.isHandledProtocol = function (scheme, callback) {
return logAndThrow(callback, 'isHandledProtocol API has been replaced by isProtocolHandled.'); return logAndThrow(callback, 'isHandledProtocol API has been replaced by isProtocolHandled.')
}; }
protocol.interceptProtocol = function(scheme, handler, callback) { protocol.interceptProtocol = function (scheme, handler, callback) {
return logAndThrow(callback, 'interceptProtocol API has been replaced by the intercept[File/Http/Buffer/String]Protocol API family, please switch to the new APIs.'); return logAndThrow(callback, 'interceptProtocol API has been replaced by the intercept[File/Http/Buffer/String]Protocol API family, please switch to the new APIs.')
}; }
module.exports = protocol; module.exports = protocol

View file

@ -1,6 +1,6 @@
const EventEmitter = require('events').EventEmitter; const EventEmitter = require('events').EventEmitter
const screen = process.atomBinding('screen').screen; const screen = process.atomBinding('screen').screen
screen.__proto__ = EventEmitter.prototype; Object.setPrototypeOf(screen, EventEmitter.prototype)
module.exports = screen; module.exports = screen

View file

@ -1,33 +1,33 @@
const EventEmitter = require('events').EventEmitter; const EventEmitter = require('events').EventEmitter
const bindings = process.atomBinding('session'); const bindings = process.atomBinding('session')
const PERSIST_PREFIX = 'persist:'; const PERSIST_PREFIX = 'persist:'
// Returns the Session from |partition| string. // Returns the Session from |partition| string.
exports.fromPartition = function(partition) { exports.fromPartition = function (partition) {
if (partition == null) { if (partition == null) {
partition = ''; partition = ''
} }
if (partition === '') { if (partition === '') {
return exports.defaultSession; return exports.defaultSession
} }
if (partition.startsWith(PERSIST_PREFIX)) { if (partition.startsWith(PERSIST_PREFIX)) {
return bindings.fromPartition(partition.substr(PERSIST_PREFIX.length), false); return bindings.fromPartition(partition.substr(PERSIST_PREFIX.length), false)
} else { } else {
return bindings.fromPartition(partition, true); return bindings.fromPartition(partition, true)
} }
}; }
// Returns the default session. // Returns the default session.
Object.defineProperty(exports, 'defaultSession', { Object.defineProperty(exports, 'defaultSession', {
enumerable: true, enumerable: true,
get: function() { get: function () {
return bindings.fromPartition('', false); return bindings.fromPartition('', false)
} }
}); })
var wrapSession = function(session) { var wrapSession = function (session) {
// session is an EventEmitter. // session is an EventEmitter.
return session.__proto__ = EventEmitter.prototype; Object.setPrototypeOf(session, EventEmitter.prototype)
}; }
bindings._setWrapSession(wrapSession); bindings._setWrapSession(wrapSession)

View file

@ -1,23 +1,23 @@
const deprecate = require('electron').deprecate; const deprecate = require('electron').deprecate
const EventEmitter = require('events').EventEmitter; const EventEmitter = require('events').EventEmitter
const Tray = process.atomBinding('tray').Tray; const Tray = process.atomBinding('tray').Tray
Tray.prototype.__proto__ = EventEmitter.prototype; Object.setPrototypeOf(Tray.prototype, EventEmitter.prototype)
Tray.prototype._init = function() { Tray.prototype._init = function () {
// Deprecated. // Deprecated.
deprecate.rename(this, 'popContextMenu', 'popUpContextMenu'); deprecate.rename(this, 'popContextMenu', 'popUpContextMenu')
deprecate.event(this, 'clicked', 'click'); deprecate.event(this, 'clicked', 'click')
deprecate.event(this, 'double-clicked', 'double-click'); deprecate.event(this, 'double-clicked', 'double-click')
deprecate.event(this, 'right-clicked', 'right-click'); deprecate.event(this, 'right-clicked', 'right-click')
return deprecate.event(this, 'balloon-clicked', 'balloon-click'); return deprecate.event(this, 'balloon-clicked', 'balloon-click')
}; }
Tray.prototype.setContextMenu = function(menu) { Tray.prototype.setContextMenu = function (menu) {
this._setContextMenu(menu); this._setContextMenu(menu)
// Keep a strong reference of menu. // Keep a strong reference of menu.
return this.menu = menu; this.menu = menu
}; }
module.exports = Tray; module.exports = Tray

View file

@ -1,59 +1,59 @@
'use strict'; 'use strict'
const EventEmitter = require('events').EventEmitter; const EventEmitter = require('events').EventEmitter
const deprecate = require('electron').deprecate; const deprecate = require('electron').deprecate
const ipcMain = require('electron').ipcMain; const ipcMain = require('electron').ipcMain
const NavigationController = require('electron').NavigationController; const NavigationController = require('electron').NavigationController
const Menu = require('electron').Menu; const Menu = require('electron').Menu
const binding = process.atomBinding('web_contents'); const binding = process.atomBinding('web_contents')
const debuggerBinding = process.atomBinding('debugger'); const debuggerBinding = process.atomBinding('debugger')
let nextId = 0; let nextId = 0
let getNextId = function() { let getNextId = function () {
return ++nextId; return ++nextId
}; }
let PDFPageSize = { let PDFPageSize = {
A5: { A5: {
custom_display_name: "A5", custom_display_name: 'A5',
height_microns: 210000, height_microns: 210000,
name: "ISO_A5", name: 'ISO_A5',
width_microns: 148000 width_microns: 148000
}, },
A4: { A4: {
custom_display_name: "A4", custom_display_name: 'A4',
height_microns: 297000, height_microns: 297000,
name: "ISO_A4", name: 'ISO_A4',
is_default: "true", is_default: 'true',
width_microns: 210000 width_microns: 210000
}, },
A3: { A3: {
custom_display_name: "A3", custom_display_name: 'A3',
height_microns: 420000, height_microns: 420000,
name: "ISO_A3", name: 'ISO_A3',
width_microns: 297000 width_microns: 297000
}, },
Legal: { Legal: {
custom_display_name: "Legal", custom_display_name: 'Legal',
height_microns: 355600, height_microns: 355600,
name: "NA_LEGAL", name: 'NA_LEGAL',
width_microns: 215900 width_microns: 215900
}, },
Letter: { Letter: {
custom_display_name: "Letter", custom_display_name: 'Letter',
height_microns: 279400, height_microns: 279400,
name: "NA_LETTER", name: 'NA_LETTER',
width_microns: 215900 width_microns: 215900
}, },
Tabloid: { Tabloid: {
height_microns: 431800, height_microns: 431800,
name: "NA_LEDGER", name: 'NA_LEDGER',
width_microns: 279400, width_microns: 279400,
custom_display_name: "Tabloid" custom_display_name: 'Tabloid'
} }
}; }
// Following methods are mapped to webFrame. // Following methods are mapped to webFrame.
const webFrameMethods = [ const webFrameMethods = [
@ -61,112 +61,115 @@ const webFrameMethods = [
'setZoomFactor', 'setZoomFactor',
'setZoomLevel', 'setZoomLevel',
'setZoomLevelLimits' 'setZoomLevelLimits'
]; ]
let wrapWebContents = function(webContents) { let wrapWebContents = function (webContents) {
// webContents is an EventEmitter. // webContents is an EventEmitter.
var controller, method, name, ref1; var controller, method, name, ref1
webContents.__proto__ = EventEmitter.prototype; Object.setPrototypeOf(webContents, EventEmitter.prototype)
// Every remote callback from renderer process would add a listenter to the // Every remote callback from renderer process would add a listenter to the
// render-view-deleted event, so ignore the listenters warning. // render-view-deleted event, so ignore the listenters warning.
webContents.setMaxListeners(0); webContents.setMaxListeners(0)
// WebContents::send(channel, args..) // WebContents::send(channel, args..)
webContents.send = function(channel, ...args) { webContents.send = function (channel, ...args) {
if (channel == null) { if (channel == null) {
throw new Error('Missing required channel argument'); throw new Error('Missing required channel argument')
} }
return this._send(channel, args); return this._send(channel, args)
}; }
// The navigation controller. // The navigation controller.
controller = new NavigationController(webContents); controller = new NavigationController(webContents)
ref1 = NavigationController.prototype; ref1 = NavigationController.prototype
for (name in ref1) { for (name in ref1) {
method = ref1[name]; method = ref1[name]
if (method instanceof Function) { if (method instanceof Function) {
(function(name, method) { (function (name, method) {
return webContents[name] = function() { webContents[name] = function () {
return method.apply(controller, arguments); return method.apply(controller, arguments)
}; }
})(name, method); })(name, method)
} }
} }
// Mapping webFrame methods. // Mapping webFrame methods.
for (let method of webFrameMethods) { for (let method of webFrameMethods) {
webContents[method] = function(...args) { webContents[method] = function (...args) {
this.send('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, args); this.send('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, args)
}; }
} }
const asyncWebFrameMethods = function(requestId, method, callback, ...args) { const asyncWebFrameMethods = function (requestId, method, callback, ...args) {
this.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', requestId, method, args); this.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', requestId, method, args)
ipcMain.once(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, function(event, result) { ipcMain.once(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, function (event, result) {
if (callback) if (callback) callback(result)
callback(result); })
}); }
};
// Make sure webContents.executeJavaScript would run the code only when the // Make sure webContents.executeJavaScript would run the code only when the
// webContents has been loaded. // webContents has been loaded.
webContents.executeJavaScript = function(code, hasUserGesture, callback) { webContents.executeJavaScript = function (code, hasUserGesture, callback) {
let requestId = getNextId(); let requestId = getNextId()
if (typeof hasUserGesture === "function") { if (typeof hasUserGesture === 'function') {
callback = hasUserGesture; callback = hasUserGesture
hasUserGesture = false; hasUserGesture = false
} }
if (this.getURL() && !this.isLoading()) if (this.getURL() && !this.isLoading()) {
return asyncWebFrameMethods.call(this, requestId, "executeJavaScript", callback, code, hasUserGesture); return asyncWebFrameMethods.call(this, requestId, 'executeJavaScript', callback, code, hasUserGesture)
else } else {
return this.once('did-finish-load', asyncWebFrameMethods.bind(this, requestId, "executeJavaScript", callback, code, hasUserGesture)); return this.once('did-finish-load', asyncWebFrameMethods.bind(this, requestId, 'executeJavaScript', callback, code, hasUserGesture))
}; }
}
// Dispatch IPC messages to the ipc module. // Dispatch IPC messages to the ipc module.
webContents.on('ipc-message', function(event, [channel, ...args]) { webContents.on('ipc-message', function (event, [channel, ...args]) {
return ipcMain.emit.apply(ipcMain, [channel, event].concat(args)); return ipcMain.emit.apply(ipcMain, [channel, event].concat(args))
}); })
webContents.on('ipc-message-sync', function(event, [channel, ...args]) { webContents.on('ipc-message-sync', function (event, [channel, ...args]) {
Object.defineProperty(event, 'returnValue', { Object.defineProperty(event, 'returnValue', {
set: function(value) { set: function (value) {
return event.sendReply(JSON.stringify(value)); return event.sendReply(JSON.stringify(value))
},
get: function () {
return undefined
} }
}); })
return ipcMain.emit.apply(ipcMain, [channel, event].concat(args)); return ipcMain.emit.apply(ipcMain, [channel, event].concat(args))
}); })
// Handle context menu action request from pepper plugin. // Handle context menu action request from pepper plugin.
webContents.on('pepper-context-menu', function(event, params) { webContents.on('pepper-context-menu', function (event, params) {
var menu; var menu
menu = Menu.buildFromTemplate(params.menu); menu = Menu.buildFromTemplate(params.menu)
return menu.popup(params.x, params.y); return menu.popup(params.x, params.y)
}); })
// This error occurs when host could not be found. // This error occurs when host could not be found.
webContents.on('did-fail-provisional-load', function(...args) { webContents.on('did-fail-provisional-load', function (...args) {
// Calling loadURL during this event might cause crash, so delay the event // Calling loadURL during this event might cause crash, so delay the event
// until next tick. // until next tick.
setImmediate(() => { setImmediate(() => {
this.emit.apply(this, ['did-fail-load'].concat(args)); this.emit.apply(this, ['did-fail-load'].concat(args))
}); })
}); })
// Delays the page-title-updated event to next tick. // Delays the page-title-updated event to next tick.
webContents.on('-page-title-updated', function(...args) { webContents.on('-page-title-updated', function (...args) {
setImmediate(() => { setImmediate(() => {
this.emit.apply(this, ['page-title-updated'].concat(args)); this.emit.apply(this, ['page-title-updated'].concat(args))
}); })
}); })
// Deprecated. // Deprecated.
deprecate.rename(webContents, 'loadUrl', 'loadURL'); deprecate.rename(webContents, 'loadUrl', 'loadURL')
deprecate.rename(webContents, 'getUrl', 'getURL'); deprecate.rename(webContents, 'getUrl', 'getURL')
deprecate.event(webContents, 'page-title-set', 'page-title-updated', function(...args) { deprecate.event(webContents, 'page-title-set', 'page-title-updated', function (...args) {
return this.emit.apply(this, ['page-title-set'].concat(args)); return this.emit.apply(this, ['page-title-set'].concat(args))
}); })
return webContents.printToPDF = function(options, callback) { webContents.printToPDF = function (options, callback) {
var printingSetting; var printingSetting
printingSetting = { printingSetting = {
pageRage: [], pageRage: [],
mediaSize: {}, mediaSize: {},
@ -181,7 +184,7 @@ let wrapWebContents = function(webContents) {
printWithCloudPrint: false, printWithCloudPrint: false,
printWithPrivet: false, printWithPrivet: false,
printWithExtension: false, printWithExtension: false,
deviceName: "Save as PDF", deviceName: 'Save as PDF',
generateDraftData: true, generateDraftData: true,
fitToPageEnabled: false, fitToPageEnabled: false,
duplex: 0, duplex: 0,
@ -189,40 +192,40 @@ let wrapWebContents = function(webContents) {
collate: true, collate: true,
shouldPrintBackgrounds: false, shouldPrintBackgrounds: false,
shouldPrintSelectionOnly: false shouldPrintSelectionOnly: false
}; }
if (options.landscape) { if (options.landscape) {
printingSetting.landscape = options.landscape; printingSetting.landscape = options.landscape
} }
if (options.marginsType) { if (options.marginsType) {
printingSetting.marginsType = options.marginsType; printingSetting.marginsType = options.marginsType
} }
if (options.printSelectionOnly) { if (options.printSelectionOnly) {
printingSetting.shouldPrintSelectionOnly = options.printSelectionOnly; printingSetting.shouldPrintSelectionOnly = options.printSelectionOnly
} }
if (options.printBackground) { if (options.printBackground) {
printingSetting.shouldPrintBackgrounds = options.printBackground; printingSetting.shouldPrintBackgrounds = options.printBackground
} }
if (options.pageSize && PDFPageSize[options.pageSize]) { if (options.pageSize && PDFPageSize[options.pageSize]) {
printingSetting.mediaSize = PDFPageSize[options.pageSize]; printingSetting.mediaSize = PDFPageSize[options.pageSize]
} else { } else {
printingSetting.mediaSize = PDFPageSize['A4']; printingSetting.mediaSize = PDFPageSize['A4']
} }
return this._printToPDF(printingSetting, callback); return this._printToPDF(printingSetting, callback)
}; }
}; }
// Wrapper for native class. // Wrapper for native class.
let wrapDebugger = function(webContentsDebugger) { let wrapDebugger = function (webContentsDebugger) {
// debugger is an EventEmitter. // debugger is an EventEmitter.
webContentsDebugger.__proto__ = EventEmitter.prototype; Object.setPrototypeOf(webContentsDebugger, EventEmitter.prototype)
}; }
binding._setWrapWebContents(wrapWebContents); binding._setWrapWebContents(wrapWebContents)
debuggerBinding._setWrapDebugger(wrapDebugger); debuggerBinding._setWrapDebugger(wrapDebugger)
module.exports.create = function(options) { module.exports.create = function (options) {
if (options == null) { if (options == null) {
options = {}; options = {}
} }
return binding.create(options); return binding.create(options)
}; }

View file

@ -1,32 +1,31 @@
const electron = require('electron'); const electron = require('electron')
const app = electron.app; const app = electron.app
const fs = require('fs'); const fs = require('fs')
const path = require('path'); const path = require('path')
const url = require('url'); const url = require('url')
// Mapping between hostname and file path. // Mapping between hostname and file path.
var hostPathMap = {}; var hostPathMap = {}
var hostPathMapNextKey = 0; var hostPathMapNextKey = 0
var getHostForPath = function(path) { var getHostForPath = function (path) {
var key; var key
key = "extension-" + (++hostPathMapNextKey); key = 'extension-' + (++hostPathMapNextKey)
hostPathMap[key] = path; hostPathMap[key] = path
return key; return key
}; }
var getPathForHost = function(host) { var getPathForHost = function (host) {
return hostPathMap[host]; return hostPathMap[host]
}; }
// Cache extensionInfo. // Cache extensionInfo.
var extensionInfoMap = {}; var extensionInfoMap = {}
var getExtensionInfoFromPath = function(srcDirectory) { var getExtensionInfoFromPath = function (srcDirectory) {
var manifest, page; var manifest, page
manifest = JSON.parse(fs.readFileSync(path.join(srcDirectory, 'manifest.json'))); manifest = JSON.parse(fs.readFileSync(path.join(srcDirectory, 'manifest.json')))
if (extensionInfoMap[manifest.name] == null) { if (extensionInfoMap[manifest.name] == null) {
// We can not use 'file://' directly because all resources in the extension // We can not use 'file://' directly because all resources in the extension
// will be treated as relative to the root in Chrome. // will be treated as relative to the root in Chrome.
page = url.format({ page = url.format({
@ -34,112 +33,113 @@ var getExtensionInfoFromPath = function(srcDirectory) {
slashes: true, slashes: true,
hostname: getHostForPath(srcDirectory), hostname: getHostForPath(srcDirectory),
pathname: manifest.devtools_page pathname: manifest.devtools_page
}); })
extensionInfoMap[manifest.name] = { extensionInfoMap[manifest.name] = {
startPage: page, startPage: page,
name: manifest.name, name: manifest.name,
srcDirectory: srcDirectory, srcDirectory: srcDirectory,
exposeExperimentalAPIs: true exposeExperimentalAPIs: true
}; }
return extensionInfoMap[manifest.name]; return extensionInfoMap[manifest.name]
} }
}; }
// The loaded extensions cache and its persistent path. // The loaded extensions cache and its persistent path.
var loadedExtensions = null; var loadedExtensions = null
var loadedExtensionsPath = null; var loadedExtensionsPath = null
app.on('will-quit', function() { app.on('will-quit', function () {
try { try {
loadedExtensions = Object.keys(extensionInfoMap).map(function(key) { loadedExtensions = Object.keys(extensionInfoMap).map(function (key) {
return extensionInfoMap[key].srcDirectory; return extensionInfoMap[key].srcDirectory
}); })
if (loadedExtensions.length > 0) { if (loadedExtensions.length > 0) {
try { try {
fs.mkdirSync(path.dirname(loadedExtensionsPath)); fs.mkdirSync(path.dirname(loadedExtensionsPath))
} catch (error) { } catch (error) {
// Ignore error // Ignore error
} }
fs.writeFileSync(loadedExtensionsPath, JSON.stringify(loadedExtensions)); fs.writeFileSync(loadedExtensionsPath, JSON.stringify(loadedExtensions))
} else { } else {
fs.unlinkSync(loadedExtensionsPath); fs.unlinkSync(loadedExtensionsPath)
} }
} catch (error) { } catch (error) {
// Ignore error // Ignore error
} }
}); })
// We can not use protocol or BrowserWindow until app is ready. // We can not use protocol or BrowserWindow until app is ready.
app.once('ready', function() { app.once('ready', function () {
var BrowserWindow, chromeExtensionHandler, i, init, len, protocol, srcDirectory; var BrowserWindow, chromeExtensionHandler, i, init, len, protocol, srcDirectory
protocol = electron.protocol, BrowserWindow = electron.BrowserWindow; protocol = electron.protocol
BrowserWindow = electron.BrowserWindow
// Load persisted extensions. // Load persisted extensions.
loadedExtensionsPath = path.join(app.getPath('userData'), 'DevTools Extensions'); loadedExtensionsPath = path.join(app.getPath('userData'), 'DevTools Extensions')
try { try {
loadedExtensions = JSON.parse(fs.readFileSync(loadedExtensionsPath)); loadedExtensions = JSON.parse(fs.readFileSync(loadedExtensionsPath))
if (!Array.isArray(loadedExtensions)) { if (!Array.isArray(loadedExtensions)) {
loadedExtensions = []; loadedExtensions = []
} }
// Preheat the extensionInfo cache. // Preheat the extensionInfo cache.
for (i = 0, len = loadedExtensions.length; i < len; i++) { for (i = 0, len = loadedExtensions.length; i < len; i++) {
srcDirectory = loadedExtensions[i]; srcDirectory = loadedExtensions[i]
getExtensionInfoFromPath(srcDirectory); getExtensionInfoFromPath(srcDirectory)
} }
} catch (error) { } catch (error) {
// Ignore error // Ignore error
} }
// The chrome-extension: can map a extension URL request to real file path. // The chrome-extension: can map a extension URL request to real file path.
chromeExtensionHandler = function(request, callback) { chromeExtensionHandler = function (request, callback) {
var directory, parsed; var directory, parsed
parsed = url.parse(request.url); parsed = url.parse(request.url)
if (!(parsed.hostname && (parsed.path != null))) { if (!(parsed.hostname && (parsed.path != null))) {
return callback(); return callback()
} }
if (!/extension-\d+/.test(parsed.hostname)) { if (!/extension-\d+/.test(parsed.hostname)) {
return callback(); return callback()
} }
directory = getPathForHost(parsed.hostname); directory = getPathForHost(parsed.hostname)
if (directory == null) { if (directory == null) {
return callback(); return callback()
} }
return callback(path.join(directory, parsed.path)); return callback(path.join(directory, parsed.path))
}; }
protocol.registerFileProtocol('chrome-extension', chromeExtensionHandler, function(error) { protocol.registerFileProtocol('chrome-extension', chromeExtensionHandler, function (error) {
if (error) { if (error) {
return console.error('Unable to register chrome-extension protocol'); return console.error('Unable to register chrome-extension protocol')
} }
}); })
BrowserWindow.prototype._loadDevToolsExtensions = function(extensionInfoArray) { BrowserWindow.prototype._loadDevToolsExtensions = function (extensionInfoArray) {
var ref; var ref
return (ref = this.devToolsWebContents) != null ? ref.executeJavaScript("DevToolsAPI.addExtensions(" + (JSON.stringify(extensionInfoArray)) + ");") : void 0; return (ref = this.devToolsWebContents) != null ? ref.executeJavaScript('DevToolsAPI.addExtensions(' + (JSON.stringify(extensionInfoArray)) + ');') : void 0
}; }
BrowserWindow.addDevToolsExtension = function(srcDirectory) { BrowserWindow.addDevToolsExtension = function (srcDirectory) {
var extensionInfo, j, len1, ref, window; var extensionInfo, j, len1, ref, window
extensionInfo = getExtensionInfoFromPath(srcDirectory); extensionInfo = getExtensionInfoFromPath(srcDirectory)
if (extensionInfo) { if (extensionInfo) {
ref = BrowserWindow.getAllWindows(); ref = BrowserWindow.getAllWindows()
for (j = 0, len1 = ref.length; j < len1; j++) { for (j = 0, len1 = ref.length; j < len1; j++) {
window = ref[j]; window = ref[j]
window._loadDevToolsExtensions([extensionInfo]); window._loadDevToolsExtensions([extensionInfo])
} }
return extensionInfo.name; return extensionInfo.name
} }
}; }
BrowserWindow.removeDevToolsExtension = function(name) { BrowserWindow.removeDevToolsExtension = function (name) {
return delete extensionInfoMap[name]; return delete extensionInfoMap[name]
}; }
// Load persisted extensions when devtools is opened. // Load persisted extensions when devtools is opened.
init = BrowserWindow.prototype._init; init = BrowserWindow.prototype._init
return BrowserWindow.prototype._init = function() { BrowserWindow.prototype._init = function () {
init.call(this); init.call(this)
return this.on('devtools-opened', function() { return this.on('devtools-opened', function () {
return this._loadDevToolsExtensions(Object.keys(extensionInfoMap).map(function(key) { return this._loadDevToolsExtensions(Object.keys(extensionInfoMap).map(function (key) {
return extensionInfoMap[key]; return extensionInfoMap[key]
})); }))
}); })
}; }
}); })

View file

@ -1,17 +1,17 @@
'use strict'; 'use strict'
const ipcMain = require('electron').ipcMain; const ipcMain = require('electron').ipcMain
const desktopCapturer = process.atomBinding('desktop_capturer').desktopCapturer; const desktopCapturer = process.atomBinding('desktop_capturer').desktopCapturer
var deepEqual = function(opt1, opt2) { var deepEqual = function (opt1, opt2) {
return JSON.stringify(opt1) === JSON.stringify(opt2); return JSON.stringify(opt1) === JSON.stringify(opt2)
}; }
// A queue for holding all requests from renderer process. // A queue for holding all requests from renderer process.
var requestsQueue = []; var requestsQueue = []
ipcMain.on('ATOM_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', function(event, captureWindow, captureScreen, thumbnailSize, id) { ipcMain.on('ATOM_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', function (event, captureWindow, captureScreen, thumbnailSize, id) {
var request; var request
request = { request = {
id: id, id: id,
options: { options: {
@ -20,58 +20,58 @@ ipcMain.on('ATOM_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', function(event, captureW
thumbnailSize: thumbnailSize thumbnailSize: thumbnailSize
}, },
webContents: event.sender webContents: event.sender
}; }
requestsQueue.push(request); requestsQueue.push(request)
if (requestsQueue.length === 1) { if (requestsQueue.length === 1) {
desktopCapturer.startHandling(captureWindow, captureScreen, thumbnailSize); desktopCapturer.startHandling(captureWindow, captureScreen, thumbnailSize)
} }
// If the WebContents is destroyed before receiving result, just remove the // If the WebContents is destroyed before receiving result, just remove the
// reference from requestsQueue to make the module not send the result to it. // reference from requestsQueue to make the module not send the result to it.
return event.sender.once('destroyed', function() { return event.sender.once('destroyed', function () {
return request.webContents = null; request.webContents = null
}); })
}); })
desktopCapturer.emit = function(event, name, sources) { desktopCapturer.emit = function (event, name, sources) {
// Receiving sources result from main process, now send them back to renderer. // Receiving sources result from main process, now send them back to renderer.
var handledRequest, i, len, ref, ref1, request, result, source, unhandledRequestsQueue; var handledRequest, i, len, ref, ref1, request, result, source, unhandledRequestsQueue
handledRequest = requestsQueue.shift(0); handledRequest = requestsQueue.shift(0)
result = (function() { result = (function () {
var i, len, results; var i, len, results
results = []; results = []
for (i = 0, len = sources.length; i < len; i++) { for (i = 0, len = sources.length; i < len; i++) {
source = sources[i]; source = sources[i]
results.push({ results.push({
id: source.id, id: source.id,
name: source.name, name: source.name,
thumbnail: source.thumbnail.toDataUrl() thumbnail: source.thumbnail.toDataUrl()
}); })
} }
return results; return results
})(); })()
if ((ref = handledRequest.webContents) != null) { if ((ref = handledRequest.webContents) != null) {
ref.send("ATOM_RENDERER_DESKTOP_CAPTURER_RESULT_" + handledRequest.id, result); ref.send('ATOM_RENDERER_DESKTOP_CAPTURER_RESULT_' + handledRequest.id, result)
} }
// Check the queue to see whether there is other same request. If has, handle // Check the queue to see whether there is other same request. If has, handle
// it for reducing redunplicated `desktopCaptuer.startHandling` calls. // it for reducing redunplicated `desktopCaptuer.startHandling` calls.
unhandledRequestsQueue = []; unhandledRequestsQueue = []
for (i = 0, len = requestsQueue.length; i < len; i++) { for (i = 0, len = requestsQueue.length; i < len; i++) {
request = requestsQueue[i]; request = requestsQueue[i]
if (deepEqual(handledRequest.options, request.options)) { if (deepEqual(handledRequest.options, request.options)) {
if ((ref1 = request.webContents) != null) { if ((ref1 = request.webContents) != null) {
ref1.send("ATOM_RENDERER_DESKTOP_CAPTURER_RESULT_" + request.id, result); ref1.send('ATOM_RENDERER_DESKTOP_CAPTURER_RESULT_' + request.id, result)
} }
} else { } else {
unhandledRequestsQueue.push(request); unhandledRequestsQueue.push(request)
} }
} }
requestsQueue = unhandledRequestsQueue; requestsQueue = unhandledRequestsQueue
// If the requestsQueue is not empty, start a new request handling. // If the requestsQueue is not empty, start a new request handling.
if (requestsQueue.length > 0) { if (requestsQueue.length > 0) {
const {captureWindow, captureScreen, thumbnailSize} = requestsQueue[0].options; const {captureWindow, captureScreen, thumbnailSize} = requestsQueue[0].options
return desktopCapturer.startHandling(captureWindow, captureScreen, thumbnailSize); return desktopCapturer.startHandling(captureWindow, captureScreen, thumbnailSize)
} }
}; }

View file

@ -1,10 +1,10 @@
'use strict'; 'use strict'
const ipcMain = require('electron').ipcMain; const ipcMain = require('electron').ipcMain
const webContents = require('electron').webContents; const webContents = require('electron').webContents
// Doesn't exist in early initialization. // Doesn't exist in early initialization.
var webViewManager = null; var webViewManager = null
var supportedWebViewEvents = [ var supportedWebViewEvents = [
'load-commit', 'load-commit',
@ -37,75 +37,75 @@ var supportedWebViewEvents = [
'media-paused', 'media-paused',
'found-in-page', 'found-in-page',
'did-change-theme-color' 'did-change-theme-color'
]; ]
var nextInstanceId = 0; var nextInstanceId = 0
var guestInstances = {}; var guestInstances = {}
var embedderElementsMap = {}; var embedderElementsMap = {}
var reverseEmbedderElementsMap = {}; var reverseEmbedderElementsMap = {}
// Moves the last element of array to the first one. // Moves the last element of array to the first one.
var moveLastToFirst = function(list) { var moveLastToFirst = function (list) {
return list.unshift(list.pop()); return list.unshift(list.pop())
}; }
// Generate guestInstanceId. // Generate guestInstanceId.
var getNextInstanceId = function() { var getNextInstanceId = function () {
return ++nextInstanceId; return ++nextInstanceId
}; }
// Create a new guest instance. // Create a new guest instance.
var createGuest = function(embedder, params) { var createGuest = function (embedder, params) {
var destroy, destroyEvents, event, fn, guest, i, id, j, len, len1, listeners; var destroy, destroyEvents, event, fn, guest, i, id, j, len, len1, listeners
if (webViewManager == null) { if (webViewManager == null) {
webViewManager = process.atomBinding('web_view_manager'); webViewManager = process.atomBinding('web_view_manager')
} }
id = getNextInstanceId(embedder); id = getNextInstanceId(embedder)
guest = webContents.create({ guest = webContents.create({
isGuest: true, isGuest: true,
partition: params.partition, partition: params.partition,
embedder: embedder embedder: embedder
}); })
guestInstances[id] = { guestInstances[id] = {
guest: guest, guest: guest,
embedder: embedder embedder: embedder
}; }
// Destroy guest when the embedder is gone or navigated. // Destroy guest when the embedder is gone or navigated.
destroyEvents = ['will-destroy', 'crashed', 'did-navigate']; destroyEvents = ['will-destroy', 'crashed', 'did-navigate']
destroy = function() { destroy = function () {
if (guestInstances[id] != null) { if (guestInstances[id] != null) {
return destroyGuest(embedder, id); return destroyGuest(embedder, id)
} }
}; }
for (i = 0, len = destroyEvents.length; i < len; i++) { for (i = 0, len = destroyEvents.length; i < len; i++) {
event = destroyEvents[i]; event = destroyEvents[i]
embedder.once(event, destroy); embedder.once(event, destroy)
// Users might also listen to the crashed event, so We must ensure the guest // Users might also listen to the crashed event, so We must ensure the guest
// is destroyed before users' listener gets called. It is done by moving our // is destroyed before users' listener gets called. It is done by moving our
// listener to the first one in queue. // listener to the first one in queue.
listeners = embedder._events[event]; listeners = embedder._events[event]
if (Array.isArray(listeners)) { if (Array.isArray(listeners)) {
moveLastToFirst(listeners); moveLastToFirst(listeners)
} }
} }
guest.once('destroyed', function() { guest.once('destroyed', function () {
var j, len1, results; var j, len1, results
results = []; results = []
for (j = 0, len1 = destroyEvents.length; j < len1; j++) { for (j = 0, len1 = destroyEvents.length; j < len1; j++) {
event = destroyEvents[j]; event = destroyEvents[j]
results.push(embedder.removeListener(event, destroy)); results.push(embedder.removeListener(event, destroy))
} }
return results; return results
}); })
// Init guest web view after attached. // Init guest web view after attached.
guest.once('did-attach', function() { guest.once('did-attach', function () {
var opts; var opts
params = this.attachParams; params = this.attachParams
delete this.attachParams; delete this.attachParams
this.viewInstanceId = params.instanceId; this.viewInstanceId = params.instanceId
this.setSize({ this.setSize({
normal: { normal: {
width: params.elementWidth, width: params.elementWidth,
@ -120,61 +120,60 @@ var createGuest = function(embedder, params) {
width: params.maxwidth, width: params.maxwidth,
height: params.maxheight height: params.maxheight
} }
}); })
if (params.src) { if (params.src) {
opts = {}; opts = {}
if (params.httpreferrer) { if (params.httpreferrer) {
opts.httpReferrer = params.httpreferrer; opts.httpReferrer = params.httpreferrer
} }
if (params.useragent) { if (params.useragent) {
opts.userAgent = params.useragent; opts.userAgent = params.useragent
} }
this.loadURL(params.src, opts); this.loadURL(params.src, opts)
} }
return guest.allowPopups = params.allowpopups; guest.allowPopups = params.allowpopups
}); })
// Dispatch events to embedder. // Dispatch events to embedder.
fn = function(event) { fn = function (event) {
return guest.on(event, function(_, ...args) { return guest.on(event, function (_, ...args) {
return embedder.send.apply(embedder, ["ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-" + guest.viewInstanceId, event].concat(args)); return embedder.send.apply(embedder, ['ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-' + guest.viewInstanceId, event].concat(args))
}); })
}; }
for (j = 0, len1 = supportedWebViewEvents.length; j < len1; j++) { for (j = 0, len1 = supportedWebViewEvents.length; j < len1; j++) {
event = supportedWebViewEvents[j]; event = supportedWebViewEvents[j]
fn(event); fn(event)
} }
// Dispatch guest's IPC messages to embedder. // Dispatch guest's IPC messages to embedder.
guest.on('ipc-message-host', function(_, [channel, ...args]) { guest.on('ipc-message-host', function (_, [channel, ...args]) {
return embedder.send.apply(embedder, ["ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-" + guest.viewInstanceId, channel].concat(args)); return embedder.send.apply(embedder, ['ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-' + guest.viewInstanceId, channel].concat(args))
}); })
// Autosize. // Autosize.
guest.on('size-changed', function(_, ...args) { guest.on('size-changed', function (_, ...args) {
return embedder.send.apply(embedder, ["ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-" + guest.viewInstanceId].concat(args)); return embedder.send.apply(embedder, ['ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-' + guest.viewInstanceId].concat(args))
}); })
return id; return id
}; }
// Attach the guest to an element of embedder. // Attach the guest to an element of embedder.
var attachGuest = function(embedder, elementInstanceId, guestInstanceId, params) { var attachGuest = function (embedder, elementInstanceId, guestInstanceId, params) {
var guest, key, oldGuestInstanceId, ref1, webPreferences; var guest, key, oldGuestInstanceId, ref1, webPreferences
guest = guestInstances[guestInstanceId].guest; guest = guestInstances[guestInstanceId].guest
// Destroy the old guest when attaching. // Destroy the old guest when attaching.
key = (embedder.getId()) + "-" + elementInstanceId; key = (embedder.getId()) + '-' + elementInstanceId
oldGuestInstanceId = embedderElementsMap[key]; oldGuestInstanceId = embedderElementsMap[key]
if (oldGuestInstanceId != null) { if (oldGuestInstanceId != null) {
// Reattachment to the same guest is not currently supported. // Reattachment to the same guest is not currently supported.
if (oldGuestInstanceId === guestInstanceId) { if (oldGuestInstanceId === guestInstanceId) {
return; return
} }
if (guestInstances[oldGuestInstanceId] == null) { if (guestInstances[oldGuestInstanceId] == null) {
return; return
} }
destroyGuest(embedder, oldGuestInstanceId); destroyGuest(embedder, oldGuestInstanceId)
} }
webPreferences = { webPreferences = {
guestInstanceId: guestInstanceId, guestInstanceId: guestInstanceId,
@ -182,54 +181,54 @@ var attachGuest = function(embedder, elementInstanceId, guestInstanceId, params)
plugins: params.plugins, plugins: params.plugins,
webSecurity: !params.disablewebsecurity, webSecurity: !params.disablewebsecurity,
blinkFeatures: params.blinkfeatures blinkFeatures: params.blinkfeatures
};
if (params.preload) {
webPreferences.preloadURL = params.preload;
} }
webViewManager.addGuest(guestInstanceId, elementInstanceId, embedder, guest, webPreferences); if (params.preload) {
guest.attachParams = params; webPreferences.preloadURL = params.preload
embedderElementsMap[key] = guestInstanceId; }
return reverseEmbedderElementsMap[guestInstanceId] = key; webViewManager.addGuest(guestInstanceId, elementInstanceId, embedder, guest, webPreferences)
}; guest.attachParams = params
embedderElementsMap[key] = guestInstanceId
reverseEmbedderElementsMap[guestInstanceId] = key
}
// Destroy an existing guest instance. // Destroy an existing guest instance.
var destroyGuest = function(embedder, id) { var destroyGuest = function (embedder, id) {
var key; var key
webViewManager.removeGuest(embedder, id); webViewManager.removeGuest(embedder, id)
guestInstances[id].guest.destroy(); guestInstances[id].guest.destroy()
delete guestInstances[id]; delete guestInstances[id]
key = reverseEmbedderElementsMap[id]; key = reverseEmbedderElementsMap[id]
if (key != null) { if (key != null) {
delete reverseEmbedderElementsMap[id]; delete reverseEmbedderElementsMap[id]
return delete embedderElementsMap[key]; return delete embedderElementsMap[key]
} }
}; }
ipcMain.on('ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', function(event, params, requestId) { ipcMain.on('ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', function (event, params, requestId) {
return event.sender.send("ATOM_SHELL_RESPONSE_" + requestId, createGuest(event.sender, params)); return event.sender.send('ATOM_SHELL_RESPONSE_' + requestId, createGuest(event.sender, params))
}); })
ipcMain.on('ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', function(event, elementInstanceId, guestInstanceId, params) { ipcMain.on('ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', function (event, elementInstanceId, guestInstanceId, params) {
return attachGuest(event.sender, elementInstanceId, guestInstanceId, params); return attachGuest(event.sender, elementInstanceId, guestInstanceId, params)
}); })
ipcMain.on('ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', function(event, id) { ipcMain.on('ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', function (event, id) {
return destroyGuest(event.sender, id); return destroyGuest(event.sender, id)
}); })
ipcMain.on('ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', function(event, id, params) { ipcMain.on('ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', function (event, id, params) {
var ref1; var ref1
return (ref1 = guestInstances[id]) != null ? ref1.guest.setSize(params) : void 0; return (ref1 = guestInstances[id]) != null ? ref1.guest.setSize(params) : void 0
}); })
// Returns WebContents from its guest id. // Returns WebContents from its guest id.
exports.getGuest = function(id) { exports.getGuest = function (id) {
var ref1; var ref1
return (ref1 = guestInstances[id]) != null ? ref1.guest : void 0; return (ref1 = guestInstances[id]) != null ? ref1.guest : void 0
}; }
// Returns the embedder of the guest. // Returns the embedder of the guest.
exports.getEmbedder = function(id) { exports.getEmbedder = function (id) {
var ref1; var ref1
return (ref1 = guestInstances[id]) != null ? ref1.embedder : void 0; return (ref1 = guestInstances[id]) != null ? ref1.embedder : void 0
}; }

View file

@ -1,120 +1,118 @@
'use strict'; 'use strict'
const ipcMain = require('electron').ipcMain; const ipcMain = require('electron').ipcMain
const BrowserWindow = require('electron').BrowserWindow; const BrowserWindow = require('electron').BrowserWindow
var hasProp = {}.hasOwnProperty; var hasProp = {}.hasOwnProperty
var frameToGuest = {}; var frameToGuest = {}
// Copy attribute of |parent| to |child| if it is not defined in |child|. // Copy attribute of |parent| to |child| if it is not defined in |child|.
var mergeOptions = function(child, parent) { var mergeOptions = function (child, parent) {
var key, value; var key, value
for (key in parent) { for (key in parent) {
if (!hasProp.call(parent, key)) continue; if (!hasProp.call(parent, key)) continue
value = parent[key]; value = parent[key]
if (!(key in child)) { if (!(key in child)) {
if (typeof value === 'object') { if (typeof value === 'object') {
child[key] = mergeOptions({}, value); child[key] = mergeOptions({}, value)
} else { } else {
child[key] = value; child[key] = value
} }
} }
} }
return child; return child
}; }
// Merge |options| with the |embedder|'s window's options. // Merge |options| with the |embedder|'s window's options.
var mergeBrowserWindowOptions = function(embedder, options) { var mergeBrowserWindowOptions = function (embedder, options) {
if (embedder.browserWindowOptions != null) { if (embedder.browserWindowOptions != null) {
// Inherit the original options if it is a BrowserWindow. // Inherit the original options if it is a BrowserWindow.
mergeOptions(options, embedder.browserWindowOptions); mergeOptions(options, embedder.browserWindowOptions)
} else { } else {
// Or only inherit web-preferences if it is a webview. // Or only inherit web-preferences if it is a webview.
if (options.webPreferences == null) { if (options.webPreferences == null) {
options.webPreferences = {}; options.webPreferences = {}
} }
mergeOptions(options.webPreferences, embedder.getWebPreferences()); mergeOptions(options.webPreferences, embedder.getWebPreferences())
} }
return options; return options
}; }
// Create a new guest created by |embedder| with |options|. // Create a new guest created by |embedder| with |options|.
var createGuest = function(embedder, url, frameName, options) { var createGuest = function (embedder, url, frameName, options) {
var closedByEmbedder, closedByUser, guest, guestId, ref1; var closedByEmbedder, closedByUser, guest, guestId, ref1
guest = frameToGuest[frameName]; guest = frameToGuest[frameName]
if (frameName && (guest != null)) { if (frameName && (guest != null)) {
guest.loadURL(url); guest.loadURL(url)
return guest.id; return guest.id
} }
// Remember the embedder window's id. // Remember the embedder window's id.
if (options.webPreferences == null) { if (options.webPreferences == null) {
options.webPreferences = {}; options.webPreferences = {}
} }
options.webPreferences.openerId = (ref1 = BrowserWindow.fromWebContents(embedder)) != null ? ref1.id : void 0; options.webPreferences.openerId = (ref1 = BrowserWindow.fromWebContents(embedder)) != null ? ref1.id : void 0
guest = new BrowserWindow(options); guest = new BrowserWindow(options)
guest.loadURL(url); guest.loadURL(url)
// When |embedder| is destroyed we should also destroy attached guest, and if // When |embedder| is destroyed we should also destroy attached guest, and if
// guest is closed by user then we should prevent |embedder| from double // guest is closed by user then we should prevent |embedder| from double
// closing guest. // closing guest.
guestId = guest.id; guestId = guest.id
closedByEmbedder = function() { closedByEmbedder = function () {
guest.removeListener('closed', closedByUser); guest.removeListener('closed', closedByUser)
return guest.destroy(); return guest.destroy()
};
closedByUser = function() {
embedder.send("ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED_" + guestId);
return embedder.removeListener('render-view-deleted', closedByEmbedder);
};
embedder.once('render-view-deleted', closedByEmbedder);
guest.once('closed', closedByUser);
if (frameName) {
frameToGuest[frameName] = guest;
guest.frameName = frameName;
guest.once('closed', function() {
return delete frameToGuest[frameName];
});
} }
return guest.id; closedByUser = function () {
}; embedder.send('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED_' + guestId)
return embedder.removeListener('render-view-deleted', closedByEmbedder)
}
embedder.once('render-view-deleted', closedByEmbedder)
guest.once('closed', closedByUser)
if (frameName) {
frameToGuest[frameName] = guest
guest.frameName = frameName
guest.once('closed', function () {
return delete frameToGuest[frameName]
})
}
return guest.id
}
// Routed window.open messages. // Routed window.open messages.
ipcMain.on('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', function(event, url, frameName, options) { ipcMain.on('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', function (event, url, frameName, options) {
options = mergeBrowserWindowOptions(event.sender, options); options = mergeBrowserWindowOptions(event.sender, options)
event.sender.emit('new-window', event, url, frameName, 'new-window', options); event.sender.emit('new-window', event, url, frameName, 'new-window', options)
if ((event.sender.isGuest() && !event.sender.allowPopups) || event.defaultPrevented) { if ((event.sender.isGuest() && !event.sender.allowPopups) || event.defaultPrevented) {
return event.returnValue = null; event.returnValue = null
} else { } else {
return event.returnValue = createGuest(event.sender, url, frameName, options); event.returnValue = createGuest(event.sender, url, frameName, options)
} }
}); })
ipcMain.on('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', function(event, guestId) { ipcMain.on('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', function (event, guestId) {
var ref1; var ref1
return (ref1 = BrowserWindow.fromId(guestId)) != null ? ref1.destroy() : void 0; return (ref1 = BrowserWindow.fromId(guestId)) != null ? ref1.destroy() : void 0
}); })
ipcMain.on('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', function(event, guestId, method, ...args) { ipcMain.on('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', function (event, guestId, method, ...args) {
var ref1; var ref1
return event.returnValue = (ref1 = BrowserWindow.fromId(guestId)) != null ? ref1[method].apply(ref1, args) : void 0; event.returnValue = (ref1 = BrowserWindow.fromId(guestId)) != null ? ref1[method].apply(ref1, args) : void 0
}); })
ipcMain.on('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', function(event, guestId, message, targetOrigin, sourceOrigin) { ipcMain.on('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', function (event, guestId, message, targetOrigin, sourceOrigin) {
var guestContents, ref1, ref2, sourceId; var guestContents, ref1, ref2, sourceId
sourceId = (ref1 = BrowserWindow.fromWebContents(event.sender)) != null ? ref1.id : void 0; sourceId = (ref1 = BrowserWindow.fromWebContents(event.sender)) != null ? ref1.id : void 0
if (sourceId == null) { if (sourceId == null) {
return; return
} }
guestContents = (ref2 = BrowserWindow.fromId(guestId)) != null ? ref2.webContents : void 0; guestContents = (ref2 = BrowserWindow.fromId(guestId)) != null ? ref2.webContents : void 0
if ((guestContents != null ? guestContents.getURL().indexOf(targetOrigin) : void 0) === 0 || targetOrigin === '*') { if ((guestContents != null ? guestContents.getURL().indexOf(targetOrigin) : void 0) === 0 || targetOrigin === '*') {
return guestContents != null ? guestContents.send('ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', sourceId, message, sourceOrigin) : void 0; return guestContents != null ? guestContents.send('ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', sourceId, message, sourceOrigin) : void 0
} }
}); })
ipcMain.on('ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', function(event, guestId, method, ...args) { ipcMain.on('ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', function (event, guestId, method, ...args) {
var ref1, ref2; var ref1, ref2
return (ref1 = BrowserWindow.fromId(guestId)) != null ? (ref2 = ref1.webContents) != null ? ref2[method].apply(ref2, args) : void 0 : void 0; return (ref1 = BrowserWindow.fromId(guestId)) != null ? (ref2 = ref1.webContents) != null ? ref2[method].apply(ref2, args) : void 0 : void 0
}); })

View file

@ -1,80 +1,79 @@
'use strict'; 'use strict'
const fs = require('fs'); const fs = require('fs')
const path = require('path'); const path = require('path')
const util = require('util'); const util = require('util')
const Module = require('module'); const Module = require('module')
const v8 = require('v8'); const v8 = require('v8')
// We modified the original process.argv to let node.js load the atom.js, // We modified the original process.argv to let node.js load the atom.js,
// we need to restore it here. // we need to restore it here.
process.argv.splice(1, 1); process.argv.splice(1, 1)
// Clear search paths. // Clear search paths.
require('../common/reset-search-paths'); require('../common/reset-search-paths')
// Import common settings. // Import common settings.
require('../common/init'); require('../common/init')
var globalPaths = Module.globalPaths; var globalPaths = Module.globalPaths
if (!process.env.ELECTRON_HIDE_INTERNAL_MODULES) { if (!process.env.ELECTRON_HIDE_INTERNAL_MODULES) {
globalPaths.push(path.join(__dirname, 'api')); globalPaths.push(path.join(__dirname, 'api'))
} }
// Expose public APIs. // Expose public APIs.
globalPaths.push(path.join(__dirname, 'api', 'exports')); globalPaths.push(path.join(__dirname, 'api', 'exports'))
if (process.platform === 'win32') { if (process.platform === 'win32') {
// Redirect node's console to use our own implementations, since node can not // Redirect node's console to use our own implementations, since node can not
// handle console output when running as GUI program. // handle console output when running as GUI program.
var consoleLog = function(...args) { var consoleLog = function (...args) {
return process.log(util.format.apply(util, args) + "\n"); return process.log(util.format.apply(util, args) + '\n')
}; }
var streamWrite = function(chunk, encoding, callback) { var streamWrite = function (chunk, encoding, callback) {
if (Buffer.isBuffer(chunk)) { if (Buffer.isBuffer(chunk)) {
chunk = chunk.toString(encoding); chunk = chunk.toString(encoding)
} }
process.log(chunk); process.log(chunk)
if (callback) { if (callback) {
callback(); callback()
} }
return true; return true
}; }
console.log = console.error = console.warn = consoleLog; console.log = console.error = console.warn = consoleLog
process.stdout.write = process.stderr.write = streamWrite; process.stdout.write = process.stderr.write = streamWrite
// Always returns EOF for stdin stream. // Always returns EOF for stdin stream.
var Readable = require('stream').Readable; var Readable = require('stream').Readable
var stdin = new Readable; var stdin = new Readable()
stdin.push(null); stdin.push(null)
process.__defineGetter__('stdin', function() { process.__defineGetter__('stdin', function () {
return stdin; return stdin
}); })
} }
// Don't quit on fatal error. // Don't quit on fatal error.
process.on('uncaughtException', function(error) { process.on('uncaughtException', function (error) {
// Do nothing if the user has a custom uncaught exception handler. // Do nothing if the user has a custom uncaught exception handler.
var dialog, message, ref, stack; var dialog, message, ref, stack
if (process.listeners('uncaughtException').length > 1) { if (process.listeners('uncaughtException').length > 1) {
return; return
} }
// Show error in GUI. // Show error in GUI.
dialog = require('electron').dialog; dialog = require('electron').dialog
stack = (ref = error.stack) != null ? ref : error.name + ": " + error.message; stack = (ref = error.stack) != null ? ref : error.name + ': ' + error.message
message = "Uncaught Exception:\n" + stack; message = 'Uncaught Exception:\n' + stack
return dialog.showErrorBox('A JavaScript error occurred in the main process', message); return dialog.showErrorBox('A JavaScript error occurred in the main process', message)
}); })
// Emit 'exit' event on quit. // Emit 'exit' event on quit.
var app = require('electron').app; var app = require('electron').app
app.on('quit', function(event, exitCode) { app.on('quit', function (event, exitCode) {
return process.emit('exit', exitCode); return process.emit('exit', exitCode)
}); })
if (process.platform === 'win32') { if (process.platform === 'win32') {
// If we are a Squirrel.Windows-installed app, set app user model ID // If we are a Squirrel.Windows-installed app, set app user model ID
@ -94,92 +93,92 @@ if (process.platform === 'win32') {
var updateDotExe = path.join( var updateDotExe = path.join(
path.dirname(process.execPath), path.dirname(process.execPath),
'..', '..',
'update.exe'); 'update.exe')
if (fs.statSyncNoException(updateDotExe)) { if (fs.statSyncNoException(updateDotExe)) {
var packageDir = path.dirname(path.resolve(updateDotExe)); var packageDir = path.dirname(path.resolve(updateDotExe))
var packageName = path.basename(packageDir); var packageName = path.basename(packageDir)
var exeName = path.basename(process.execPath).replace(/\.exe$/i, ''); var exeName = path.basename(process.execPath).replace(/\.exe$/i, '')
app.setAppUserModelId(`com.squirrel.${packageName}.${exeName}`); app.setAppUserModelId(`com.squirrel.${packageName}.${exeName}`)
} }
} }
// Map process.exit to app.exit, which quits gracefully. // Map process.exit to app.exit, which quits gracefully.
process.exit = app.exit; process.exit = app.exit
// Load the RPC server. // Load the RPC server.
require('./rpc-server'); require('./rpc-server')
// Load the guest view manager. // Load the guest view manager.
require('./guest-view-manager'); require('./guest-view-manager')
require('./guest-window-manager'); require('./guest-window-manager')
// Now we try to load app's package.json. // Now we try to load app's package.json.
var packageJson = null; var packageJson = null
var searchPaths = ['app', 'app.asar', 'default_app']; var searchPaths = ['app', 'app.asar', 'default_app']
var i, len, packagePath; var i, len, packagePath
for (i = 0, len = searchPaths.length; i < len; i++) { for (i = 0, len = searchPaths.length; i < len; i++) {
packagePath = searchPaths[i]; packagePath = searchPaths[i]
try { try {
packagePath = path.join(process.resourcesPath, packagePath); packagePath = path.join(process.resourcesPath, packagePath)
packageJson = JSON.parse(fs.readFileSync(path.join(packagePath, 'package.json'))); packageJson = JSON.parse(fs.readFileSync(path.join(packagePath, 'package.json')))
break; break
} catch (error) { } catch (error) {
continue; continue
} }
} }
if (packageJson == null) { if (packageJson == null) {
process.nextTick(function() { process.nextTick(function () {
return process.exit(1); return process.exit(1)
}); })
throw new Error("Unable to find a valid app"); throw new Error('Unable to find a valid app')
} }
// Set application's version. // Set application's version.
if (packageJson.version != null) { if (packageJson.version != null) {
app.setVersion(packageJson.version); app.setVersion(packageJson.version)
} }
// Set application's name. // Set application's name.
if (packageJson.productName != null) { if (packageJson.productName != null) {
app.setName(packageJson.productName); app.setName(packageJson.productName)
} else if (packageJson.name != null) { } else if (packageJson.name != null) {
app.setName(packageJson.name); app.setName(packageJson.name)
} }
// Set application's desktop name. // Set application's desktop name.
if (packageJson.desktopName != null) { if (packageJson.desktopName != null) {
app.setDesktopName(packageJson.desktopName); app.setDesktopName(packageJson.desktopName)
} else { } else {
app.setDesktopName((app.getName()) + ".desktop"); app.setDesktopName((app.getName()) + '.desktop')
} }
// Set v8 flags // Set v8 flags
if (packageJson.v8Flags != null) { if (packageJson.v8Flags != null) {
v8.setFlagsFromString(packageJson.v8Flags); v8.setFlagsFromString(packageJson.v8Flags)
} }
// Chrome 42 disables NPAPI plugins by default, reenable them here // Chrome 42 disables NPAPI plugins by default, reenable them here
app.commandLine.appendSwitch('enable-npapi'); app.commandLine.appendSwitch('enable-npapi')
// Set the user path according to application's name. // Set the user path according to application's name.
app.setPath('userData', path.join(app.getPath('appData'), app.getName())); app.setPath('userData', path.join(app.getPath('appData'), app.getName()))
app.setPath('userCache', path.join(app.getPath('cache'), app.getName())); app.setPath('userCache', path.join(app.getPath('cache'), app.getName()))
app.setAppPath(packagePath); app.setAppPath(packagePath)
// Load the chrome extension support. // Load the chrome extension support.
require('./chrome-extension'); require('./chrome-extension')
// Load internal desktop-capturer module. // Load internal desktop-capturer module.
require('./desktop-capturer'); require('./desktop-capturer')
// Set main startup script of the app. // Set main startup script of the app.
var mainStartupScript = packageJson.main || 'index.js'; var mainStartupScript = packageJson.main || 'index.js'
// Finally load app's main.js and transfer control to C++. // Finally load app's main.js and transfer control to C++.
Module._load(path.join(packagePath, mainStartupScript), Module, true); Module._load(path.join(packagePath, mainStartupScript), Module, true)

View file

@ -1,94 +1,94 @@
'use strict'; 'use strict'
const v8Util = process.atomBinding('v8_util'); const v8Util = process.atomBinding('v8_util')
class ObjectsRegistry { class ObjectsRegistry {
constructor() { constructor () {
this.nextId = 0; this.nextId = 0
// Stores all objects by ref-counting. // Stores all objects by ref-counting.
// (id) => {object, count} // (id) => {object, count}
this.storage = {}; this.storage = {}
// Stores the IDs of objects referenced by WebContents. // Stores the IDs of objects referenced by WebContents.
// (webContentsId) => [id] // (webContentsId) => [id]
this.owners = {}; this.owners = {}
} }
// Register a new object and return its assigned ID. If the object is already // Register a new object and return its assigned ID. If the object is already
// registered then the already assigned ID would be returned. // registered then the already assigned ID would be returned.
add(webContents, obj) { add (webContents, obj) {
// Get or assign an ID to the object. // Get or assign an ID to the object.
let id = this.saveToStorage(obj); let id = this.saveToStorage(obj)
// Add object to the set of referenced objects. // Add object to the set of referenced objects.
let webContentsId = webContents.getId(); let webContentsId = webContents.getId()
let owner = this.owners[webContentsId]; let owner = this.owners[webContentsId]
if (!owner) { if (!owner) {
owner = this.owners[webContentsId] = new Set(); owner = this.owners[webContentsId] = new Set()
// Clear the storage when webContents is reloaded/navigated. // Clear the storage when webContents is reloaded/navigated.
webContents.once('render-view-deleted', (event, id) => { webContents.once('render-view-deleted', (event, id) => {
this.clear(id); this.clear(id)
}); })
} }
if (!owner.has(id)) { if (!owner.has(id)) {
owner.add(id); owner.add(id)
// Increase reference count if not referenced before. // Increase reference count if not referenced before.
this.storage[id].count++; this.storage[id].count++
} }
return id; return id
} }
// Get an object according to its ID. // Get an object according to its ID.
get(id) { get (id) {
return this.storage[id].object; return this.storage[id].object
} }
// Dereference an object according to its ID. // Dereference an object according to its ID.
remove(webContentsId, id) { remove (webContentsId, id) {
// Dereference from the storage. // Dereference from the storage.
this.dereference(id); this.dereference(id)
// Also remove the reference in owner. // Also remove the reference in owner.
this.owners[webContentsId].delete(id); this.owners[webContentsId].delete(id)
} }
// Clear all references to objects refrenced by the WebContents. // Clear all references to objects refrenced by the WebContents.
clear(webContentsId) { clear (webContentsId) {
let owner = this.owners[webContentsId]; let owner = this.owners[webContentsId]
if (!owner) if (!owner) return
return;
for (let id of owner) for (let id of owner) this.dereference(id)
this.dereference(id);
delete this.owners[webContentsId]; delete this.owners[webContentsId]
} }
// Private: Saves the object into storage and assigns an ID for it. // Private: Saves the object into storage and assigns an ID for it.
saveToStorage(object) { saveToStorage (object) {
let id = v8Util.getHiddenValue(object, 'atomId'); let id = v8Util.getHiddenValue(object, 'atomId')
if (!id) { if (!id) {
id = ++this.nextId; id = ++this.nextId
this.storage[id] = { this.storage[id] = {
count: 0, count: 0,
object: object object: object
}; }
v8Util.setHiddenValue(object, 'atomId', id); v8Util.setHiddenValue(object, 'atomId', id)
} }
return id; return id
} }
// Private: Dereference the object from store. // Private: Dereference the object from store.
dereference(id) { dereference (id) {
let pointer = this.storage[id]; let pointer = this.storage[id]
if (pointer == null) { if (pointer == null) {
return; return
} }
pointer.count -= 1; pointer.count -= 1
if (pointer.count === 0) { if (pointer.count === 0) {
v8Util.deleteHiddenValue(pointer.object, 'atomId'); v8Util.deleteHiddenValue(pointer.object, 'atomId')
return delete this.storage[id]; return delete this.storage[id]
} }
} }
} }
module.exports = new ObjectsRegistry; module.exports = new ObjectsRegistry()

View file

@ -1,371 +1,370 @@
'use strict'; 'use strict'
const electron = require('electron'); const electron = require('electron')
const ipcMain = electron.ipcMain; const ipcMain = electron.ipcMain
const objectsRegistry = require('./objects-registry'); const objectsRegistry = require('./objects-registry')
const v8Util = process.atomBinding('v8_util'); const v8Util = process.atomBinding('v8_util')
const IDWeakMap = process.atomBinding('id_weak_map').IDWeakMap; const IDWeakMap = process.atomBinding('id_weak_map').IDWeakMap
// The internal properties of Function. // The internal properties of Function.
const FUNCTION_PROPERTIES = [ const FUNCTION_PROPERTIES = [
'length', 'name', 'arguments', 'caller', 'prototype', 'length', 'name', 'arguments', 'caller', 'prototype'
]; ]
// The remote functions in renderer processes. // The remote functions in renderer processes.
// (webContentsId) => {id: Function} // (webContentsId) => {id: Function}
let rendererFunctions = {}; let rendererFunctions = {}
// Return the description of object's members: // Return the description of object's members:
let getObjectMembers = function(object) { let getObjectMembers = function (object) {
let names = Object.getOwnPropertyNames(object); let names = Object.getOwnPropertyNames(object)
// For Function, we should not override following properties even though they // For Function, we should not override following properties even though they
// are "own" properties. // are "own" properties.
if (typeof object === 'function') { if (typeof object === 'function') {
names = names.filter((name) => { names = names.filter((name) => {
return !FUNCTION_PROPERTIES.includes(name); return !FUNCTION_PROPERTIES.includes(name)
}); })
} }
// Map properties to descriptors. // Map properties to descriptors.
return names.map((name) => { return names.map((name) => {
let descriptor = Object.getOwnPropertyDescriptor(object, name); let descriptor = Object.getOwnPropertyDescriptor(object, name)
let member = {name, enumerable: descriptor.enumerable, writable: false}; let member = {name, enumerable: descriptor.enumerable, writable: false}
if (descriptor.get === undefined && typeof object[name] === 'function') { if (descriptor.get === undefined && typeof object[name] === 'function') {
member.type = 'method'; member.type = 'method'
} else { } else {
if (descriptor.set || descriptor.writable) if (descriptor.set || descriptor.writable) member.writable = true
member.writable = true; member.type = 'get'
member.type = 'get';
} }
return member; return member
}); })
}; }
// Return the description of object's prototype. // Return the description of object's prototype.
let getObjectPrototype = function(object) { let getObjectPrototype = function (object) {
let proto = Object.getPrototypeOf(object); let proto = Object.getPrototypeOf(object)
if (proto === null || proto === Object.prototype) if (proto === null || proto === Object.prototype) return null
return null;
return { return {
members: getObjectMembers(proto), members: getObjectMembers(proto),
proto: getObjectPrototype(proto), proto: getObjectPrototype(proto)
}; }
}; }
// Convert a real value into meta data. // Convert a real value into meta data.
var valueToMeta = function(sender, value, optimizeSimpleObject) { var valueToMeta = function (sender, value, optimizeSimpleObject) {
var el, i, len, meta; var el, i, len, meta
if (optimizeSimpleObject == null) { if (optimizeSimpleObject == null) {
optimizeSimpleObject = false; optimizeSimpleObject = false
} }
meta = { meta = {
type: typeof value type: typeof value
}; }
if (Buffer.isBuffer(value)) { if (Buffer.isBuffer(value)) {
meta.type = 'buffer'; meta.type = 'buffer'
} }
if (value === null) { if (value === null) {
meta.type = 'value'; meta.type = 'value'
} }
if (Array.isArray(value)) { if (Array.isArray(value)) {
meta.type = 'array'; meta.type = 'array'
} }
if (value instanceof Error) { if (value instanceof Error) {
meta.type = 'error'; meta.type = 'error'
} }
if (value instanceof Date) { if (value instanceof Date) {
meta.type = 'date'; meta.type = 'date'
} }
if ((value != null ? value.constructor.name : void 0) === 'Promise') { if ((value != null ? value.constructor.name : void 0) === 'Promise') {
meta.type = 'promise'; meta.type = 'promise'
} }
// Treat simple objects as value. // Treat simple objects as value.
if (optimizeSimpleObject && meta.type === 'object' && v8Util.getHiddenValue(value, 'simple')) { if (optimizeSimpleObject && meta.type === 'object' && v8Util.getHiddenValue(value, 'simple')) {
meta.type = 'value'; meta.type = 'value'
} }
// Treat the arguments object as array. // Treat the arguments object as array.
if (meta.type === 'object' && (value.hasOwnProperty('callee')) && (value.length != null)) { if (meta.type === 'object' && (value.hasOwnProperty('callee')) && (value.length != null)) {
meta.type = 'array'; meta.type = 'array'
} }
if (meta.type === 'array') { if (meta.type === 'array') {
meta.members = []; meta.members = []
for (i = 0, len = value.length; i < len; i++) { for (i = 0, len = value.length; i < len; i++) {
el = value[i]; el = value[i]
meta.members.push(valueToMeta(sender, el)); meta.members.push(valueToMeta(sender, el))
} }
} else if (meta.type === 'object' || meta.type === 'function') { } else if (meta.type === 'object' || meta.type === 'function') {
meta.name = value.constructor.name; meta.name = value.constructor.name
// Reference the original value if it's an object, because when it's // 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 // passed to renderer we would assume the renderer keeps a reference of
// it. // it.
meta.id = objectsRegistry.add(sender, value); meta.id = objectsRegistry.add(sender, value)
meta.members = getObjectMembers(value); meta.members = getObjectMembers(value)
meta.proto = getObjectPrototype(value); meta.proto = getObjectPrototype(value)
} else if (meta.type === 'buffer') { } else if (meta.type === 'buffer') {
meta.value = Array.prototype.slice.call(value, 0); meta.value = Array.prototype.slice.call(value, 0)
} else if (meta.type === 'promise') { } else if (meta.type === 'promise') {
meta.then = valueToMeta(sender, function(v) { value.then(v); }); meta.then = valueToMeta(sender, function (v) { value.then(v) })
} else if (meta.type === 'error') { } else if (meta.type === 'error') {
meta.members = plainObjectToMeta(value); meta.members = plainObjectToMeta(value)
// Error.name is not part of own properties. // Error.name is not part of own properties.
meta.members.push({ meta.members.push({
name: 'name', name: 'name',
value: value.name value: value.name
}); })
} else if (meta.type === 'date') { } else if (meta.type === 'date') {
meta.value = value.getTime(); meta.value = value.getTime()
} else { } else {
meta.type = 'value'; meta.type = 'value'
meta.value = value; meta.value = value
} }
return meta; return meta
}; }
// Convert object to meta by value. // Convert object to meta by value.
var plainObjectToMeta = function(obj) { var plainObjectToMeta = function (obj) {
return Object.getOwnPropertyNames(obj).map(function(name) { return Object.getOwnPropertyNames(obj).map(function (name) {
return { return {
name: name, name: name,
value: obj[name] value: obj[name]
}; }
}); })
}; }
// Convert Error into meta data. // Convert Error into meta data.
var exceptionToMeta = function(error) { var exceptionToMeta = function (error) {
return { return {
type: 'exception', type: 'exception',
message: error.message, message: error.message,
stack: error.stack || error stack: error.stack || error
}; }
}; }
// Convert array of meta data from renderer into array of real values. // Convert array of meta data from renderer into array of real values.
var unwrapArgs = function(sender, args) { var unwrapArgs = function (sender, args) {
var metaToValue; var metaToValue
metaToValue = function(meta) { metaToValue = function (meta) {
var i, len, member, ref, returnValue; var i, len, member, ref, returnValue
switch (meta.type) { switch (meta.type) {
case 'value': case 'value':
return meta.value; return meta.value
case 'remote-object': case 'remote-object':
return objectsRegistry.get(meta.id); return objectsRegistry.get(meta.id)
case 'array': case 'array':
return unwrapArgs(sender, meta.value); return unwrapArgs(sender, meta.value)
case 'buffer': case 'buffer':
return new Buffer(meta.value); return new Buffer(meta.value)
case 'date': case 'date':
return new Date(meta.value); return new Date(meta.value)
case 'promise': case 'promise':
return Promise.resolve({ return Promise.resolve({
then: metaToValue(meta.then) then: metaToValue(meta.then)
}); })
case 'object': { case 'object': {
let ret = {}; let ret = {}
Object.defineProperty(ret.constructor, 'name', { value: meta.name }); Object.defineProperty(ret.constructor, 'name', { value: meta.name })
ref = meta.members; ref = meta.members
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len = ref.length; i < len; i++) {
member = ref[i]; member = ref[i]
ret[member.name] = metaToValue(member.value); ret[member.name] = metaToValue(member.value)
} }
return ret; return ret
} }
case 'function-with-return-value': case 'function-with-return-value':
returnValue = metaToValue(meta.value); returnValue = metaToValue(meta.value)
return function() { return function () {
return returnValue; return returnValue
}; }
case 'function': { case 'function': {
// Cache the callbacks in renderer. // Cache the callbacks in renderer.
let webContentsId = sender.getId(); let webContentsId = sender.getId()
let callbacks = rendererFunctions[webContentsId]; let callbacks = rendererFunctions[webContentsId]
if (!callbacks) { if (!callbacks) {
callbacks = rendererFunctions[webContentsId] = new IDWeakMap; callbacks = rendererFunctions[webContentsId] = new IDWeakMap()
sender.once('render-view-deleted', function(event, id) { sender.once('render-view-deleted', function (event, id) {
callbacks.clear(); callbacks.clear()
delete rendererFunctions[id]; delete rendererFunctions[id]
}); })
} }
if (callbacks.has(meta.id)) if (callbacks.has(meta.id)) return callbacks.get(meta.id)
return callbacks.get(meta.id);
let callIntoRenderer = function(...args) { let callIntoRenderer = function (...args) {
if ((webContentsId in rendererFunctions) && !sender.isDestroyed()) if ((webContentsId in rendererFunctions) && !sender.isDestroyed()) {
sender.send('ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(sender, args)); sender.send('ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(sender, args))
else } else {
throw new Error(`Attempting to call a function in a renderer window that has been closed or released. Function provided here: ${meta.location}.`); throw new Error(`Attempting to call a function in a renderer window that has been closed or released. Function provided here: ${meta.location}.`)
}; }
v8Util.setDestructor(callIntoRenderer, function() { }
if ((webContentsId in rendererFunctions) && !sender.isDestroyed()) v8Util.setDestructor(callIntoRenderer, function () {
sender.send('ATOM_RENDERER_RELEASE_CALLBACK', meta.id); if ((webContentsId in rendererFunctions) && !sender.isDestroyed()) {
}); sender.send('ATOM_RENDERER_RELEASE_CALLBACK', meta.id)
callbacks.set(meta.id, callIntoRenderer); }
return callIntoRenderer; })
callbacks.set(meta.id, callIntoRenderer)
return callIntoRenderer
} }
default: default:
throw new TypeError("Unknown type: " + meta.type); throw new TypeError(`Unknown type: ${meta.type}`)
} }
}; }
return args.map(metaToValue); return args.map(metaToValue)
}; }
// Call a function and send reply asynchronously if it's a an asynchronous // Call a function and send reply asynchronously if it's a an asynchronous
// style function and the caller didn't pass a callback. // style function and the caller didn't pass a callback.
var callFunction = function(event, func, caller, args) { var callFunction = function (event, func, caller, args) {
var funcMarkedAsync, funcName, funcPassedCallback, ref, ret; var funcMarkedAsync, funcName, funcPassedCallback, ref, ret
funcMarkedAsync = v8Util.getHiddenValue(func, 'asynchronous'); funcMarkedAsync = v8Util.getHiddenValue(func, 'asynchronous')
funcPassedCallback = typeof args[args.length - 1] === 'function'; funcPassedCallback = typeof args[args.length - 1] === 'function'
try { try {
if (funcMarkedAsync && !funcPassedCallback) { if (funcMarkedAsync && !funcPassedCallback) {
args.push(function(ret) { args.push(function (ret) {
return event.returnValue = valueToMeta(event.sender, ret, true); event.returnValue = valueToMeta(event.sender, ret, true)
}); })
return func.apply(caller, args); return func.apply(caller, args)
} else { } else {
ret = func.apply(caller, args); ret = func.apply(caller, args)
return event.returnValue = valueToMeta(event.sender, ret, true); event.returnValue = valueToMeta(event.sender, ret, true)
} }
} catch (error) { } catch (error) {
// Catch functions thrown further down in function invocation and wrap // Catch functions thrown further down in function invocation and wrap
// them with the function name so it's easier to trace things like // them with the function name so it's easier to trace things like
// `Error processing argument -1.` // `Error processing argument -1.`
funcName = (ref = func.name) != null ? ref : "anonymous"; funcName = ((ref = func.name) != null) ? ref : 'anonymous'
throw new Error("Could not call remote function `" + funcName + "`. Check that the function signature is correct. Underlying error: " + error.message); throw new Error(`Could not call remote function '${funcName}'. Check that the function signature is correct. Underlying error: ${error.message}`)
} }
}; }
ipcMain.on('ATOM_BROWSER_REQUIRE', function(event, module) { ipcMain.on('ATOM_BROWSER_REQUIRE', function (event, module) {
try { try {
return event.returnValue = valueToMeta(event.sender, process.mainModule.require(module)); event.returnValue = valueToMeta(event.sender, process.mainModule.require(module))
} catch (error) { } catch (error) {
return event.returnValue = exceptionToMeta(error); event.returnValue = exceptionToMeta(error)
} }
}); })
ipcMain.on('ATOM_BROWSER_GET_BUILTIN', function(event, module) { ipcMain.on('ATOM_BROWSER_GET_BUILTIN', function (event, module) {
try { try {
return event.returnValue = valueToMeta(event.sender, electron[module]); event.returnValue = valueToMeta(event.sender, electron[module])
} catch (error) { } catch (error) {
return event.returnValue = exceptionToMeta(error); event.returnValue = exceptionToMeta(error)
} }
}); })
ipcMain.on('ATOM_BROWSER_GLOBAL', function(event, name) { ipcMain.on('ATOM_BROWSER_GLOBAL', function (event, name) {
try { try {
return event.returnValue = valueToMeta(event.sender, global[name]); event.returnValue = valueToMeta(event.sender, global[name])
} catch (error) { } catch (error) {
return event.returnValue = exceptionToMeta(error); event.returnValue = exceptionToMeta(error)
} }
}); })
ipcMain.on('ATOM_BROWSER_CURRENT_WINDOW', function(event) { ipcMain.on('ATOM_BROWSER_CURRENT_WINDOW', function (event) {
try { try {
return event.returnValue = valueToMeta(event.sender, event.sender.getOwnerBrowserWindow()); event.returnValue = valueToMeta(event.sender, event.sender.getOwnerBrowserWindow())
} catch (error) { } catch (error) {
return event.returnValue = exceptionToMeta(error); event.returnValue = exceptionToMeta(error)
} }
}); })
ipcMain.on('ATOM_BROWSER_CURRENT_WEB_CONTENTS', function(event) { ipcMain.on('ATOM_BROWSER_CURRENT_WEB_CONTENTS', function (event) {
return event.returnValue = valueToMeta(event.sender, event.sender); event.returnValue = valueToMeta(event.sender, event.sender)
}); })
ipcMain.on('ATOM_BROWSER_CONSTRUCTOR', function(event, id, args) { ipcMain.on('ATOM_BROWSER_CONSTRUCTOR', function (event, id, args) {
try { try {
args = unwrapArgs(event.sender, args); args = unwrapArgs(event.sender, args)
let constructor = objectsRegistry.get(id); let constructor = objectsRegistry.get(id)
// Call new with array of arguments. // Call new with array of arguments.
// http://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible // http://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible
let obj = new (Function.prototype.bind.apply(constructor, [null].concat(args))); let obj = new (Function.prototype.bind.apply(constructor, [null].concat(args)))
return event.returnValue = valueToMeta(event.sender, obj); event.returnValue = valueToMeta(event.sender, obj)
} catch (error) { } catch (error) {
return event.returnValue = exceptionToMeta(error); event.returnValue = exceptionToMeta(error)
} }
}); })
ipcMain.on('ATOM_BROWSER_FUNCTION_CALL', function(event, id, args) { ipcMain.on('ATOM_BROWSER_FUNCTION_CALL', function (event, id, args) {
try { try {
args = unwrapArgs(event.sender, args); args = unwrapArgs(event.sender, args)
let func = objectsRegistry.get(id); let func = objectsRegistry.get(id)
return callFunction(event, func, global, args); return callFunction(event, func, global, args)
} catch (error) { } catch (error) {
return event.returnValue = exceptionToMeta(error); event.returnValue = exceptionToMeta(error)
} }
}); })
ipcMain.on('ATOM_BROWSER_MEMBER_CONSTRUCTOR', function(event, id, method, args) { ipcMain.on('ATOM_BROWSER_MEMBER_CONSTRUCTOR', function (event, id, method, args) {
try { try {
args = unwrapArgs(event.sender, args); args = unwrapArgs(event.sender, args)
let constructor = objectsRegistry.get(id)[method]; let constructor = objectsRegistry.get(id)[method]
// Call new with array of arguments. // Call new with array of arguments.
let obj = new (Function.prototype.bind.apply(constructor, [null].concat(args))); let obj = new (Function.prototype.bind.apply(constructor, [null].concat(args)))
return event.returnValue = valueToMeta(event.sender, obj); event.returnValue = valueToMeta(event.sender, obj)
} catch (error) { } catch (error) {
return event.returnValue = exceptionToMeta(error); event.returnValue = exceptionToMeta(error)
} }
}); })
ipcMain.on('ATOM_BROWSER_MEMBER_CALL', function(event, id, method, args) { ipcMain.on('ATOM_BROWSER_MEMBER_CALL', function (event, id, method, args) {
try { try {
args = unwrapArgs(event.sender, args); args = unwrapArgs(event.sender, args)
let obj = objectsRegistry.get(id); let obj = objectsRegistry.get(id)
return callFunction(event, obj[method], obj, args); return callFunction(event, obj[method], obj, args)
} catch (error) { } catch (error) {
return event.returnValue = exceptionToMeta(error); event.returnValue = exceptionToMeta(error)
} }
}); })
ipcMain.on('ATOM_BROWSER_MEMBER_SET', function(event, id, name, value) { ipcMain.on('ATOM_BROWSER_MEMBER_SET', function (event, id, name, value) {
try { try {
let obj = objectsRegistry.get(id); let obj = objectsRegistry.get(id)
obj[name] = value; obj[name] = value
return event.returnValue = null; event.returnValue = null
} catch (error) { } catch (error) {
return event.returnValue = exceptionToMeta(error); event.returnValue = exceptionToMeta(error)
} }
}); })
ipcMain.on('ATOM_BROWSER_MEMBER_GET', function(event, id, name) { ipcMain.on('ATOM_BROWSER_MEMBER_GET', function (event, id, name) {
try { try {
let obj = objectsRegistry.get(id); let obj = objectsRegistry.get(id)
return event.returnValue = valueToMeta(event.sender, obj[name]); event.returnValue = valueToMeta(event.sender, obj[name])
} catch (error) { } catch (error) {
return event.returnValue = exceptionToMeta(error); event.returnValue = exceptionToMeta(error)
} }
}); })
ipcMain.on('ATOM_BROWSER_DEREFERENCE', function(event, id) { ipcMain.on('ATOM_BROWSER_DEREFERENCE', function (event, id) {
return objectsRegistry.remove(event.sender.getId(), id); return objectsRegistry.remove(event.sender.getId(), id)
}); })
ipcMain.on('ATOM_BROWSER_GUEST_WEB_CONTENTS', function(event, guestInstanceId) { ipcMain.on('ATOM_BROWSER_GUEST_WEB_CONTENTS', function (event, guestInstanceId) {
try { try {
let guestViewManager = require('./guest-view-manager'); let guestViewManager = require('./guest-view-manager')
return event.returnValue = valueToMeta(event.sender, guestViewManager.getGuest(guestInstanceId)); event.returnValue = valueToMeta(event.sender, guestViewManager.getGuest(guestInstanceId))
} catch (error) { } catch (error) {
return event.returnValue = exceptionToMeta(error); event.returnValue = exceptionToMeta(error)
} }
}); })
ipcMain.on('ATOM_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', function(event, requestId, guestInstanceId, method, ...args) { ipcMain.on('ATOM_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', function (event, requestId, guestInstanceId, method, ...args) {
try { try {
let guestViewManager = require('./guest-view-manager'); let guestViewManager = require('./guest-view-manager')
let guest = guestViewManager.getGuest(guestInstanceId); let guest = guestViewManager.getGuest(guestInstanceId)
if (requestId) { if (requestId) {
const responseCallback = function(result) { const responseCallback = function (result) {
event.sender.send(`ATOM_RENDERER_ASYNC_CALL_TO_GUEST_VIEW_RESPONSE_${requestId}`, result); event.sender.send(`ATOM_RENDERER_ASYNC_CALL_TO_GUEST_VIEW_RESPONSE_${requestId}`, result)
}; }
args.push(responseCallback); args.push(responseCallback)
} }
guest[method].apply(guest, args); guest[method].apply(guest, args)
} catch (error) { } catch (error) {
return event.returnValue = exceptionToMeta(error); event.returnValue = exceptionToMeta(error)
} }
}); })

View file

@ -1,62 +1,62 @@
'use strict'; 'use strict'
const v8Util = process.atomBinding('v8_util'); const v8Util = process.atomBinding('v8_util')
class CallbacksRegistry { class CallbacksRegistry {
constructor() { constructor () {
this.nextId = 0; this.nextId = 0
this.callbacks = {}; this.callbacks = {}
} }
add(callback) { add (callback) {
// The callback is already added. // The callback is already added.
var filenameAndLine, id, location, match, ref, regexp, stackString; var filenameAndLine, id, location, match, ref, regexp, stackString
id = v8Util.getHiddenValue(callback, 'callbackId'); id = v8Util.getHiddenValue(callback, 'callbackId')
if (id != null) { if (id != null) {
return id; return id
} }
id = ++this.nextId; id = ++this.nextId
// Capture the location of the function and put it in the ID string, // Capture the location of the function and put it in the ID string,
// so that release errors can be tracked down easily. // so that release errors can be tracked down easily.
regexp = /at (.*)/gi; regexp = /at (.*)/gi
stackString = (new Error).stack; stackString = (new Error()).stack
while ((match = regexp.exec(stackString)) !== null) { while ((match = regexp.exec(stackString)) !== null) {
location = match[1]; location = match[1]
if (location.indexOf('(native)') !== -1) { if (location.indexOf('(native)') !== -1) {
continue; continue
} }
if (location.indexOf('atom.asar') !== -1) { if (location.indexOf('atom.asar') !== -1) {
continue; continue
} }
ref = /([^\/^\)]*)\)?$/gi.exec(location); ref = /([^\/^\)]*)\)?$/gi.exec(location)
filenameAndLine = ref[1]; filenameAndLine = ref[1]
break; break
} }
this.callbacks[id] = callback; this.callbacks[id] = callback
v8Util.setHiddenValue(callback, 'callbackId', id); v8Util.setHiddenValue(callback, 'callbackId', id)
v8Util.setHiddenValue(callback, 'location', filenameAndLine); v8Util.setHiddenValue(callback, 'location', filenameAndLine)
return id; return id
} }
get(id) { get (id) {
var ref; var ref
return (ref = this.callbacks[id]) != null ? ref : function() {}; return (ref = this.callbacks[id]) != null ? ref : function () {}
} }
call(id, ...args) { call (id, ...args) {
var ref; var ref
return (ref = this.get(id)).call.apply(ref, [global].concat(args)); return (ref = this.get(id)).call.apply(ref, [global].concat(args))
} }
apply(id, ...args) { apply (id, ...args) {
var ref; var ref
return (ref = this.get(id)).apply.apply(ref, [global].concat(args)); return (ref = this.get(id)).apply.apply(ref, [global].concat(args))
} }
remove(id) { remove (id) {
return delete this.callbacks[id]; return delete this.callbacks[id]
} }
} }
module.exports = CallbacksRegistry; module.exports = CallbacksRegistry

View file

@ -1,6 +1,6 @@
if (process.platform === 'linux' && process.type === 'renderer') { if (process.platform === 'linux' && process.type === 'renderer') {
// On Linux we could not access clipboard in renderer process. // On Linux we could not access clipboard in renderer process.
module.exports = require('electron').remote.clipboard; module.exports = require('electron').remote.clipboard
} else { } else {
module.exports = process.atomBinding('clipboard'); module.exports = process.atomBinding('clipboard')
} }

View file

@ -1,94 +1,98 @@
'use strict'; 'use strict'
const os = require('os'); const os = require('os')
const path = require('path'); const path = require('path')
const spawn = require('child_process').spawn; const spawn = require('child_process').spawn
const electron = require('electron'); const electron = require('electron')
const binding = process.atomBinding('crash_reporter'); const binding = process.atomBinding('crash_reporter')
var CrashReporter = (function() { var CrashReporter = (function () {
function CrashReporter() {} function CrashReporter () {}
CrashReporter.prototype.start = function(options) { CrashReporter.prototype.start = function (options) {
var app, args, autoSubmit, companyName, deprecate, env, extra, ignoreSystemCrashHandler, start, submitURL; var app, args, autoSubmit, companyName, deprecate, env, extra, ignoreSystemCrashHandler, start, submitURL
if (options == null) { if (options == null) {
options = {}; options = {}
} }
this.productName = options.productName, companyName = options.companyName, submitURL = options.submitURL, autoSubmit = options.autoSubmit, ignoreSystemCrashHandler = options.ignoreSystemCrashHandler, extra = options.extra; this.productName = options.productName
companyName = options.companyName
submitURL = options.submitURL
autoSubmit = options.autoSubmit
ignoreSystemCrashHandler = options.ignoreSystemCrashHandler
extra = options.extra
// Deprecated. // Deprecated.
deprecate = electron.deprecate; deprecate = electron.deprecate
if (options.submitUrl) { if (options.submitUrl) {
if (submitURL == null) { if (submitURL == null) {
submitURL = options.submitUrl; submitURL = options.submitUrl
} }
deprecate.warn('submitUrl', 'submitURL'); deprecate.warn('submitUrl', 'submitURL')
} }
app = (process.type === 'browser' ? electron : electron.remote).app; app = (process.type === 'browser' ? electron : electron.remote).app
if (this.productName == null) { if (this.productName == null) {
this.productName = app.getName(); this.productName = app.getName()
} }
if (autoSubmit == null) { if (autoSubmit == null) {
autoSubmit = true; autoSubmit = true
} }
if (ignoreSystemCrashHandler == null) { if (ignoreSystemCrashHandler == null) {
ignoreSystemCrashHandler = false; ignoreSystemCrashHandler = false
} }
if (extra == null) { if (extra == null) {
extra = {}; extra = {}
} }
if (extra._productName == null) { if (extra._productName == null) {
extra._productName = this.productName; extra._productName = this.productName
} }
if (extra._companyName == null) { if (extra._companyName == null) {
extra._companyName = companyName; extra._companyName = companyName
} }
if (extra._version == null) { if (extra._version == null) {
extra._version = app.getVersion(); extra._version = app.getVersion()
} }
if (companyName == null) { if (companyName == null) {
deprecate.log('companyName is now a required option to crashReporter.start'); deprecate.log('companyName is now a required option to crashReporter.start')
return; return
} }
if (submitURL == null) { if (submitURL == null) {
deprecate.log('submitURL is now a required option to crashReporter.start'); deprecate.log('submitURL is now a required option to crashReporter.start')
return; return
} }
start = () => { start = () => {
binding.start(this.productName, companyName, submitURL, autoSubmit, ignoreSystemCrashHandler, extra); binding.start(this.productName, companyName, submitURL, autoSubmit, ignoreSystemCrashHandler, extra)
}; }
if (process.platform === 'win32') { if (process.platform === 'win32') {
args = ["--reporter-url=" + submitURL, "--application-name=" + this.productName, "--v=1"]; args = ['--reporter-url=' + submitURL, '--application-name=' + this.productName, '--v=1']
env = { env = {
ATOM_SHELL_INTERNAL_CRASH_SERVICE: 1 ATOM_SHELL_INTERNAL_CRASH_SERVICE: 1
}; }
spawn(process.execPath, args, { spawn(process.execPath, args, {
env: env, env: env,
detached: true detached: true
}); })
} }
return start(); return start()
}; }
CrashReporter.prototype.getLastCrashReport = function() { CrashReporter.prototype.getLastCrashReport = function () {
var reports; var reports
reports = this.getUploadedReports(); reports = this.getUploadedReports()
if (reports.length > 0) { if (reports.length > 0) {
return reports[0]; return reports[0]
} else { } else {
return null; return null
} }
}; }
CrashReporter.prototype.getUploadedReports = function() { CrashReporter.prototype.getUploadedReports = function () {
var log, tmpdir; var log, tmpdir
tmpdir = process.platform === 'win32' ? os.tmpdir() : '/tmp'; tmpdir = process.platform === 'win32' ? os.tmpdir() : '/tmp'
log = process.platform === 'darwin' ? path.join(tmpdir, this.productName + " Crashes") : path.join(tmpdir, this.productName + " Crashes", 'uploads.log'); log = process.platform === 'darwin' ? path.join(tmpdir, this.productName + ' Crashes') : path.join(tmpdir, this.productName + ' Crashes', 'uploads.log')
return binding._getUploadedReports(log); return binding._getUploadedReports(log)
}; }
return CrashReporter; return CrashReporter
})()
})(); module.exports = new CrashReporter()
module.exports = new CrashReporter;

View file

@ -1,108 +1,108 @@
// Deprecate a method. // Deprecate a method.
const deprecate = function(oldName, newName, fn) { const deprecate = function (oldName, newName, fn) {
var warned; var warned
warned = false; warned = false
return function() { return function () {
if (!(warned || process.noDeprecation)) { if (!(warned || process.noDeprecation)) {
warned = true; warned = true
deprecate.warn(oldName, newName); deprecate.warn(oldName, newName)
} }
return fn.apply(this, arguments); return fn.apply(this, arguments)
}; }
}; }
// The method is renamed. // The method is renamed.
deprecate.rename = function(object, oldName, newName) { deprecate.rename = function (object, oldName, newName) {
var newMethod, warned; var newMethod, warned
warned = false; warned = false
newMethod = function() { newMethod = function () {
if (!(warned || process.noDeprecation)) { if (!(warned || process.noDeprecation)) {
warned = true; warned = true
deprecate.warn(oldName, newName); deprecate.warn(oldName, newName)
} }
return this[newName].apply(this, arguments); return this[newName].apply(this, arguments)
};
if (typeof object === 'function') {
return object.prototype[oldName] = newMethod;
} else {
return object[oldName] = newMethod;
} }
}; if (typeof object === 'function') {
object.prototype[oldName] = newMethod
} else {
object[oldName] = newMethod
}
}
// Forward the method to member. // Forward the method to member.
deprecate.member = function(object, method, member) { deprecate.member = function (object, method, member) {
var warned; var warned
warned = false; warned = false
return object.prototype[method] = function() { object.prototype[method] = function () {
if (!(warned || process.noDeprecation)) { if (!(warned || process.noDeprecation)) {
warned = true; warned = true
deprecate.warn(method, member + "." + method); deprecate.warn(method, member + '.' + method)
} }
return this[member][method].apply(this[member], arguments); return this[member][method].apply(this[member], arguments)
}; }
}; }
// Deprecate a property. // Deprecate a property.
deprecate.property = function(object, property, method) { deprecate.property = function (object, property, method) {
return Object.defineProperty(object, property, { return Object.defineProperty(object, property, {
get: function() { get: function () {
var warned; var warned
warned = false; warned = false
if (!(warned || process.noDeprecation)) { if (!(warned || process.noDeprecation)) {
warned = true; warned = true
deprecate.warn(property + " property", method + " method"); deprecate.warn(property + ' property', method + ' method')
} }
return this[method](); return this[method]()
} }
}); })
}; }
// Deprecate an event. // Deprecate an event.
deprecate.event = function(emitter, oldName, newName, fn) { deprecate.event = function (emitter, oldName, newName, fn) {
var warned; var warned
warned = false; warned = false
return emitter.on(newName, function(...args) { return emitter.on(newName, function (...args) {
// there is listeners for old API. // there is listeners for old API.
if (this.listenerCount(oldName) > 0) { if (this.listenerCount(oldName) > 0) {
if (!(warned || process.noDeprecation)) { if (!(warned || process.noDeprecation)) {
warned = true; warned = true
deprecate.warn("'" + oldName + "' event", "'" + newName + "' event"); deprecate.warn("'" + oldName + "' event", "'" + newName + "' event")
} }
if (fn != null) { if (fn != null) {
return fn.apply(this, arguments); return fn.apply(this, arguments)
} else { } else {
return this.emit.apply(this, [oldName].concat(args)); return this.emit.apply(this, [oldName].concat(args))
} }
} }
}); })
}; }
// Print deprecation warning. // Print deprecation warning.
deprecate.warn = function(oldName, newName) { deprecate.warn = function (oldName, newName) {
return deprecate.log(oldName + " is deprecated. Use " + newName + " instead."); return deprecate.log(oldName + ' is deprecated. Use ' + newName + ' instead.')
}; }
var deprecationHandler = null; var deprecationHandler = null
// Print deprecation message. // Print deprecation message.
deprecate.log = function(message) { deprecate.log = function (message) {
if (typeof deprecationHandler === 'function') { if (typeof deprecationHandler === 'function') {
deprecationHandler(message); deprecationHandler(message)
} else if (process.throwDeprecation) { } else if (process.throwDeprecation) {
throw new Error(message); throw new Error(message)
} else if (process.traceDeprecation) { } else if (process.traceDeprecation) {
return console.trace(message); return console.trace(message)
} else { } else {
return console.warn("(electron) " + message); return console.warn('(electron) ' + message)
} }
}; }
deprecate.setHandler = function(handler) { deprecate.setHandler = function (handler) {
deprecationHandler = handler; deprecationHandler = handler
}; }
deprecate.getHandler = function() { deprecate.getHandler = function () {
return deprecationHandler; return deprecationHandler
}; }
module.exports = deprecate; module.exports = deprecate

View file

@ -1,11 +1,11 @@
'use strict'; 'use strict'
const deprecate = require('electron').deprecate; const deprecate = require('electron').deprecate
exports.setHandler = function (deprecationHandler) { exports.setHandler = function (deprecationHandler) {
deprecate.setHandler(deprecationHandler); deprecate.setHandler(deprecationHandler)
}; }
exports.getHandler = function () { exports.getHandler = function () {
return deprecate.getHandler(); return deprecate.getHandler()
}; }

View file

@ -1,15 +1,14 @@
// Do not expose the internal modules to `require`. // Do not expose the internal modules to `require`.
const hideInternalModules = function() { const hideInternalModules = function () {
var globalPaths = require('module').globalPaths; var globalPaths = require('module').globalPaths
if (globalPaths.length === 3) { if (globalPaths.length === 3) {
// Remove the "common/api/lib" and "browser-or-renderer/api/lib". // Remove the "common/api/lib" and "browser-or-renderer/api/lib".
return globalPaths.splice(0, 2); return globalPaths.splice(0, 2)
} }
}; }
// Attaches properties to |exports|. // Attaches properties to |exports|.
exports.defineProperties = function(exports) { exports.defineProperties = function (exports) {
return Object.defineProperties(exports, { return Object.defineProperties(exports, {
hideInternalModules: { hideInternalModules: {
enumerable: true, enumerable: true,
@ -18,48 +17,47 @@ exports.defineProperties = function(exports) {
// Common modules, please sort with alphabet order. // Common modules, please sort with alphabet order.
clipboard: { clipboard: {
// Must be enumerable, otherwise it woulde be invisible to remote module. // Must be enumerable, otherwise it woulde be invisible to remote module.
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../clipboard'); return require('../clipboard')
} }
}, },
crashReporter: { crashReporter: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../crash-reporter'); return require('../crash-reporter')
} }
}, },
deprecations: { deprecations: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../deprecations'); return require('../deprecations')
} }
}, },
nativeImage: { nativeImage: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../native-image'); return require('../native-image')
} }
}, },
shell: { shell: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../shell'); return require('../shell')
} }
}, },
// The internal modules, invisible unless you know their names. // The internal modules, invisible unless you know their names.
CallbacksRegistry: { CallbacksRegistry: {
get: function() { get: function () {
return require('../callbacks-registry'); return require('../callbacks-registry')
} }
}, },
deprecate: { deprecate: {
get: function() { get: function () {
return require('../deprecate'); return require('../deprecate')
} }
} }
}); })
}; }

View file

@ -1,7 +1,7 @@
const deprecate = require('electron').deprecate; const deprecate = require('electron').deprecate
const nativeImage = process.atomBinding('native_image'); const nativeImage = process.atomBinding('native_image')
// Deprecated. // Deprecated.
deprecate.rename(nativeImage, 'createFromDataUrl', 'createFromDataURL'); deprecate.rename(nativeImage, 'createFromDataUrl', 'createFromDataURL')
module.exports = nativeImage; module.exports = nativeImage

View file

@ -1 +1 @@
module.exports = process.atomBinding('shell'); module.exports = process.atomBinding('shell')

View file

@ -1,70 +1,71 @@
(function () { (function () {
const asar = process.binding('atom_common_asar'); const asar = process.binding('atom_common_asar')
const child_process = require('child_process'); const child_process = require('child_process')
const path = require('path'); const path = require('path')
const util = require('util'); const util = require('util')
var hasProp = {}.hasOwnProperty; var hasProp = {}.hasOwnProperty
// Cache asar archive objects. // Cache asar archive objects.
var cachedArchives = {}; var cachedArchives = {}
var getOrCreateArchive = function(p) { var getOrCreateArchive = function (p) {
var archive; var archive
archive = cachedArchives[p]; archive = cachedArchives[p]
if (archive != null) { if (archive != null) {
return archive; return archive
} }
archive = asar.createArchive(p); archive = asar.createArchive(p)
if (!archive) { if (!archive) {
return false; return false
} }
return cachedArchives[p] = archive; cachedArchives[p] = archive
}; return archive
}
// Clean cache on quit. // Clean cache on quit.
process.on('exit', function() { process.on('exit', function () {
var archive, p; var archive, p
for (p in cachedArchives) { for (p in cachedArchives) {
if (!hasProp.call(cachedArchives, p)) continue; if (!hasProp.call(cachedArchives, p)) continue
archive = cachedArchives[p]; archive = cachedArchives[p]
archive.destroy(); archive.destroy()
} }
}); })
// Separate asar package's path from full path. // Separate asar package's path from full path.
var splitPath = function(p) { var splitPath = function (p) {
var index; var index
// shortcut to disable asar. // shortcut to disable asar.
if (process.noAsar) { if (process.noAsar) {
return [false]; return [false]
} }
if (typeof p !== 'string') { if (typeof p !== 'string') {
return [false]; return [false]
} }
if (p.substr(-5) === '.asar') { if (p.substr(-5) === '.asar') {
return [true, p, '']; return [true, p, '']
} }
p = path.normalize(p); p = path.normalize(p)
index = p.lastIndexOf(".asar" + path.sep); index = p.lastIndexOf('.asar' + path.sep)
if (index === -1) { if (index === -1) {
return [false]; return [false]
} }
return [true, p.substr(0, index + 5), p.substr(index + 6)]; return [true, p.substr(0, index + 5), p.substr(index + 6)]
}; }
// Convert asar archive's Stats object to fs's Stats object. // Convert asar archive's Stats object to fs's Stats object.
var nextInode = 0; var nextInode = 0
var uid = process.getuid != null ? process.getuid() : 0; var uid = process.getuid != null ? process.getuid() : 0
var gid = process.getgid != null ? process.getgid() : 0; var gid = process.getgid != null ? process.getgid() : 0
var fakeTime = new Date(); var fakeTime = new Date()
var asarStatsToFsStats = function(stats) { var asarStatsToFsStats = function (stats) {
return { return {
dev: 1, dev: 1,
ino: ++nextInode, ino: ++nextInode,
@ -78,521 +79,521 @@
mtime: stats.mtime || fakeTime, mtime: stats.mtime || fakeTime,
ctime: stats.ctime || fakeTime, ctime: stats.ctime || fakeTime,
size: stats.size, size: stats.size,
isFile: function() { isFile: function () {
return stats.isFile; return stats.isFile
}, },
isDirectory: function() { isDirectory: function () {
return stats.isDirectory; return stats.isDirectory
}, },
isSymbolicLink: function() { isSymbolicLink: function () {
return stats.isLink; return stats.isLink
}, },
isBlockDevice: function() { isBlockDevice: function () {
return false; return false
}, },
isCharacterDevice: function() { isCharacterDevice: function () {
return false; return false
}, },
isFIFO: function() { isFIFO: function () {
return false; return false
}, },
isSocket: function() { isSocket: function () {
return false; return false
} }
}; }
}; }
// Create a ENOENT error. // Create a ENOENT error.
var notFoundError = function(asarPath, filePath, callback) { var notFoundError = function (asarPath, filePath, callback) {
var error; var error
error = new Error("ENOENT, " + filePath + " not found in " + asarPath); error = new Error(`ENOENT, ${filePath} not found in ${asarPath}`)
error.code = "ENOENT"; error.code = 'ENOENT'
error.errno = -2; error.errno = -2
if (typeof callback !== 'function') { if (typeof callback !== 'function') {
throw error; throw error
} }
return process.nextTick(function() { return process.nextTick(function () {
return callback(error); return callback(error)
}); })
}; }
// Create a ENOTDIR error. // Create a ENOTDIR error.
var notDirError = function(callback) { var notDirError = function (callback) {
var error; var error
error = new Error('ENOTDIR, not a directory'); error = new Error('ENOTDIR, not a directory')
error.code = 'ENOTDIR'; error.code = 'ENOTDIR'
error.errno = -20; error.errno = -20
if (typeof callback !== 'function') { if (typeof callback !== 'function') {
throw error; throw error
} }
return process.nextTick(function() { return process.nextTick(function () {
return callback(error); return callback(error)
}); })
}; }
// Create invalid archive error. // Create invalid archive error.
var invalidArchiveError = function(asarPath, callback) { var invalidArchiveError = function (asarPath, callback) {
var error; var error
error = new Error("Invalid package " + asarPath); error = new Error(`Invalid package ${asarPath}`)
if (typeof callback !== 'function') { if (typeof callback !== 'function') {
throw error; throw error
} }
return process.nextTick(function() { return process.nextTick(function () {
return callback(error); return callback(error)
}); })
}; }
// Override APIs that rely on passing file path instead of content to C++. // Override APIs that rely on passing file path instead of content to C++.
var overrideAPISync = function(module, name, arg) { var overrideAPISync = function (module, name, arg) {
var old; var old
if (arg == null) { if (arg == null) {
arg = 0; arg = 0
} }
old = module[name]; old = module[name]
return module[name] = function() { module[name] = function () {
var archive, newPath, p; var archive, newPath, p
p = arguments[arg]; p = arguments[arg]
const [isAsar, asarPath, filePath] = splitPath(p); const [isAsar, asarPath, filePath] = splitPath(p)
if (!isAsar) { if (!isAsar) {
return old.apply(this, arguments); return old.apply(this, arguments)
} }
archive = getOrCreateArchive(asarPath); archive = getOrCreateArchive(asarPath)
if (!archive) { if (!archive) {
invalidArchiveError(asarPath); invalidArchiveError(asarPath)
} }
newPath = archive.copyFileOut(filePath); newPath = archive.copyFileOut(filePath)
if (!newPath) { if (!newPath) {
notFoundError(asarPath, filePath); notFoundError(asarPath, filePath)
} }
arguments[arg] = newPath; arguments[arg] = newPath
return old.apply(this, arguments); return old.apply(this, arguments)
}; }
}; }
var overrideAPI = function(module, name, arg) { var overrideAPI = function (module, name, arg) {
var old; var old
if (arg == null) { if (arg == null) {
arg = 0; arg = 0
} }
old = module[name]; old = module[name]
return module[name] = function() { module[name] = function () {
var archive, callback, newPath, p; var archive, callback, newPath, p
p = arguments[arg]; p = arguments[arg]
const [isAsar, asarPath, filePath] = splitPath(p); const [isAsar, asarPath, filePath] = splitPath(p)
if (!isAsar) { if (!isAsar) {
return old.apply(this, arguments); return old.apply(this, arguments)
} }
callback = arguments[arguments.length - 1]; callback = arguments[arguments.length - 1]
if (typeof callback !== 'function') { if (typeof callback !== 'function') {
return overrideAPISync(module, name, arg); return overrideAPISync(module, name, arg)
} }
archive = getOrCreateArchive(asarPath); archive = getOrCreateArchive(asarPath)
if (!archive) { if (!archive) {
return invalidArchiveError(asarPath, callback); return invalidArchiveError(asarPath, callback)
} }
newPath = archive.copyFileOut(filePath); newPath = archive.copyFileOut(filePath)
if (!newPath) { if (!newPath) {
return notFoundError(asarPath, filePath, callback); return notFoundError(asarPath, filePath, callback)
} }
arguments[arg] = newPath; arguments[arg] = newPath
return old.apply(this, arguments); return old.apply(this, arguments)
}; }
}; }
// Override fs APIs. // Override fs APIs.
exports.wrapFsWithAsar = function(fs) { exports.wrapFsWithAsar = function (fs) {
var exists, existsSync, internalModuleReadFile, internalModuleStat, lstat, lstatSync, mkdir, mkdirSync, readFile, readFileSync, readdir, readdirSync, realpath, realpathSync, stat, statSync, statSyncNoException, logFDs, logASARAccess; var exists, existsSync, internalModuleReadFile, internalModuleStat, lstat, lstatSync, mkdir, mkdirSync, readFile, readFileSync, readdir, readdirSync, realpath, realpathSync, stat, statSync, statSyncNoException, logFDs, logASARAccess
logFDs = {}; logFDs = {}
logASARAccess = function(asarPath, filePath, offset) { logASARAccess = function (asarPath, filePath, offset) {
if (!process.env.ELECTRON_LOG_ASAR_READS) { if (!process.env.ELECTRON_LOG_ASAR_READS) {
return; return
} }
if (!logFDs[asarPath]) { if (!logFDs[asarPath]) {
var logFilename, logPath; var logFilename, logPath
const path = require('path'); const path = require('path')
logFilename = path.basename(asarPath, '.asar') + '-access-log.txt'; logFilename = path.basename(asarPath, '.asar') + '-access-log.txt'
logPath = path.join(require('os').tmpdir(), logFilename); logPath = path.join(require('os').tmpdir(), logFilename)
logFDs[asarPath] = fs.openSync(logPath, 'a'); logFDs[asarPath] = fs.openSync(logPath, 'a')
console.log('Logging ' + asarPath + ' access to ' + logPath); console.log('Logging ' + asarPath + ' access to ' + logPath)
} }
fs.writeSync(logFDs[asarPath], offset + ': ' + filePath + '\n'); fs.writeSync(logFDs[asarPath], offset + ': ' + filePath + '\n')
}; }
lstatSync = fs.lstatSync; lstatSync = fs.lstatSync
fs.lstatSync = function(p) { fs.lstatSync = function (p) {
var archive, stats; var archive, stats
const [isAsar, asarPath, filePath] = splitPath(p); const [isAsar, asarPath, filePath] = splitPath(p)
if (!isAsar) { if (!isAsar) {
return lstatSync(p); return lstatSync(p)
} }
archive = getOrCreateArchive(asarPath); archive = getOrCreateArchive(asarPath)
if (!archive) { if (!archive) {
invalidArchiveError(asarPath); invalidArchiveError(asarPath)
} }
stats = archive.stat(filePath); stats = archive.stat(filePath)
if (!stats) { if (!stats) {
notFoundError(asarPath, filePath); notFoundError(asarPath, filePath)
} }
return asarStatsToFsStats(stats); return asarStatsToFsStats(stats)
}; }
lstat = fs.lstat; lstat = fs.lstat
fs.lstat = function(p, callback) { fs.lstat = function (p, callback) {
var archive, stats; var archive, stats
const [isAsar, asarPath, filePath] = splitPath(p); const [isAsar, asarPath, filePath] = splitPath(p)
if (!isAsar) { if (!isAsar) {
return lstat(p, callback); return lstat(p, callback)
} }
archive = getOrCreateArchive(asarPath); archive = getOrCreateArchive(asarPath)
if (!archive) { if (!archive) {
return invalidArchiveError(asarPath, callback); return invalidArchiveError(asarPath, callback)
} }
stats = getOrCreateArchive(asarPath).stat(filePath); stats = getOrCreateArchive(asarPath).stat(filePath)
if (!stats) { if (!stats) {
return notFoundError(asarPath, filePath, callback); return notFoundError(asarPath, filePath, callback)
} }
return process.nextTick(function() { return process.nextTick(function () {
return callback(null, asarStatsToFsStats(stats)); return callback(null, asarStatsToFsStats(stats))
}); })
}; }
statSync = fs.statSync; statSync = fs.statSync
fs.statSync = function(p) { fs.statSync = function (p) {
const [isAsar] = splitPath(p); const [isAsar] = splitPath(p)
if (!isAsar) { if (!isAsar) {
return statSync(p); return statSync(p)
} }
// Do not distinguish links for now. // Do not distinguish links for now.
return fs.lstatSync(p); return fs.lstatSync(p)
}; }
stat = fs.stat; stat = fs.stat
fs.stat = function(p, callback) { fs.stat = function (p, callback) {
const [isAsar] = splitPath(p); const [isAsar] = splitPath(p)
if (!isAsar) { if (!isAsar) {
return stat(p, callback); return stat(p, callback)
} }
// Do not distinguish links for now. // Do not distinguish links for now.
return process.nextTick(function() { return process.nextTick(function () {
return fs.lstat(p, callback); return fs.lstat(p, callback)
}); })
}; }
statSyncNoException = fs.statSyncNoException; statSyncNoException = fs.statSyncNoException
fs.statSyncNoException = function(p) { fs.statSyncNoException = function (p) {
var archive, stats; var archive, stats
const [isAsar, asarPath, filePath] = splitPath(p); const [isAsar, asarPath, filePath] = splitPath(p)
if (!isAsar) { if (!isAsar) {
return statSyncNoException(p); return statSyncNoException(p)
} }
archive = getOrCreateArchive(asarPath); archive = getOrCreateArchive(asarPath)
if (!archive) { if (!archive) {
return false; return false
} }
stats = archive.stat(filePath); stats = archive.stat(filePath)
if (!stats) { if (!stats) {
return false; return false
} }
return asarStatsToFsStats(stats); return asarStatsToFsStats(stats)
}; }
realpathSync = fs.realpathSync; realpathSync = fs.realpathSync
fs.realpathSync = function(p) { fs.realpathSync = function (p) {
var archive, real; var archive, real
const [isAsar, asarPath, filePath] = splitPath(p); const [isAsar, asarPath, filePath] = splitPath(p)
if (!isAsar) { if (!isAsar) {
return realpathSync.apply(this, arguments); return realpathSync.apply(this, arguments)
} }
archive = getOrCreateArchive(asarPath); archive = getOrCreateArchive(asarPath)
if (!archive) { if (!archive) {
invalidArchiveError(asarPath); invalidArchiveError(asarPath)
} }
real = archive.realpath(filePath); real = archive.realpath(filePath)
if (real === false) { if (real === false) {
notFoundError(asarPath, filePath); notFoundError(asarPath, filePath)
} }
return path.join(realpathSync(asarPath), real); return path.join(realpathSync(asarPath), real)
}; }
realpath = fs.realpath; realpath = fs.realpath
fs.realpath = function(p, cache, callback) { fs.realpath = function (p, cache, callback) {
var archive, real; var archive, real
const [isAsar, asarPath, filePath] = splitPath(p); const [isAsar, asarPath, filePath] = splitPath(p)
if (!isAsar) { if (!isAsar) {
return realpath.apply(this, arguments); return realpath.apply(this, arguments)
} }
if (typeof cache === 'function') { if (typeof cache === 'function') {
callback = cache; callback = cache
cache = void 0; cache = void 0
} }
archive = getOrCreateArchive(asarPath); archive = getOrCreateArchive(asarPath)
if (!archive) { if (!archive) {
return invalidArchiveError(asarPath, callback); return invalidArchiveError(asarPath, callback)
} }
real = archive.realpath(filePath); real = archive.realpath(filePath)
if (real === false) { if (real === false) {
return notFoundError(asarPath, filePath, callback); return notFoundError(asarPath, filePath, callback)
} }
return realpath(asarPath, function(err, p) { return realpath(asarPath, function (err, p) {
if (err) { if (err) {
return callback(err); return callback(err)
} }
return callback(null, path.join(p, real)); return callback(null, path.join(p, real))
}); })
}; }
exists = fs.exists; exists = fs.exists
fs.exists = function(p, callback) { fs.exists = function (p, callback) {
var archive; var archive
const [isAsar, asarPath, filePath] = splitPath(p); const [isAsar, asarPath, filePath] = splitPath(p)
if (!isAsar) { if (!isAsar) {
return exists(p, callback); return exists(p, callback)
} }
archive = getOrCreateArchive(asarPath); archive = getOrCreateArchive(asarPath)
if (!archive) { if (!archive) {
return invalidArchiveError(asarPath, callback); return invalidArchiveError(asarPath, callback)
} }
return process.nextTick(function() { return process.nextTick(function () {
return callback(archive.stat(filePath) !== false); return callback(archive.stat(filePath) !== false)
}); })
}; }
existsSync = fs.existsSync; existsSync = fs.existsSync
fs.existsSync = function(p) { fs.existsSync = function (p) {
var archive; var archive
const [isAsar, asarPath, filePath] = splitPath(p); const [isAsar, asarPath, filePath] = splitPath(p)
if (!isAsar) { if (!isAsar) {
return existsSync(p); return existsSync(p)
} }
archive = getOrCreateArchive(asarPath); archive = getOrCreateArchive(asarPath)
if (!archive) { if (!archive) {
return false; return false
} }
return archive.stat(filePath) !== false; return archive.stat(filePath) !== false
}; }
readFile = fs.readFile; readFile = fs.readFile
fs.readFile = function(p, options, callback) { fs.readFile = function (p, options, callback) {
var archive, buffer, encoding, fd, info, realPath; var archive, buffer, encoding, fd, info, realPath
const [isAsar, asarPath, filePath] = splitPath(p); const [isAsar, asarPath, filePath] = splitPath(p)
if (!isAsar) { if (!isAsar) {
return readFile.apply(this, arguments); return readFile.apply(this, arguments)
} }
if (typeof options === 'function') { if (typeof options === 'function') {
callback = options; callback = options
options = void 0; options = void 0
} }
archive = getOrCreateArchive(asarPath); archive = getOrCreateArchive(asarPath)
if (!archive) { if (!archive) {
return invalidArchiveError(asarPath, callback); return invalidArchiveError(asarPath, callback)
} }
info = archive.getFileInfo(filePath); info = archive.getFileInfo(filePath)
if (!info) { if (!info) {
return notFoundError(asarPath, filePath, callback); return notFoundError(asarPath, filePath, callback)
} }
if (info.size === 0) { if (info.size === 0) {
return process.nextTick(function() { return process.nextTick(function () {
return callback(null, new Buffer(0)); return callback(null, new Buffer(0))
}); })
} }
if (info.unpacked) { if (info.unpacked) {
realPath = archive.copyFileOut(filePath); realPath = archive.copyFileOut(filePath)
return fs.readFile(realPath, options, callback); return fs.readFile(realPath, options, callback)
} }
if (!options) { if (!options) {
options = { options = {
encoding: null encoding: null
}; }
} else if (util.isString(options)) { } else if (util.isString(options)) {
options = { options = {
encoding: options encoding: options
}; }
} else if (!util.isObject(options)) { } else if (!util.isObject(options)) {
throw new TypeError('Bad arguments'); throw new TypeError('Bad arguments')
} }
encoding = options.encoding; encoding = options.encoding
buffer = new Buffer(info.size); buffer = new Buffer(info.size)
fd = archive.getFd(); fd = archive.getFd()
if (!(fd >= 0)) { if (!(fd >= 0)) {
return notFoundError(asarPath, filePath, callback); return notFoundError(asarPath, filePath, callback)
} }
logASARAccess(asarPath, filePath, info.offset); logASARAccess(asarPath, filePath, info.offset)
return fs.read(fd, buffer, 0, info.size, info.offset, function(error) { return fs.read(fd, buffer, 0, info.size, info.offset, function (error) {
return callback(error, encoding ? buffer.toString(encoding) : buffer); return callback(error, encoding ? buffer.toString(encoding) : buffer)
}); })
}; }
readFileSync = fs.readFileSync; readFileSync = fs.readFileSync
fs.readFileSync = function(p, opts) { fs.readFileSync = function (p, opts) {
// this allows v8 to optimize this function // this allows v8 to optimize this function
var archive, buffer, encoding, fd, info, options, realPath; var archive, buffer, encoding, fd, info, options, realPath
options = opts; options = opts
const [isAsar, asarPath, filePath] = splitPath(p); const [isAsar, asarPath, filePath] = splitPath(p)
if (!isAsar) { if (!isAsar) {
return readFileSync.apply(this, arguments); return readFileSync.apply(this, arguments)
} }
archive = getOrCreateArchive(asarPath); archive = getOrCreateArchive(asarPath)
if (!archive) { if (!archive) {
invalidArchiveError(asarPath); invalidArchiveError(asarPath)
} }
info = archive.getFileInfo(filePath); info = archive.getFileInfo(filePath)
if (!info) { if (!info) {
notFoundError(asarPath, filePath); notFoundError(asarPath, filePath)
} }
if (info.size === 0) { if (info.size === 0) {
if (options) { if (options) {
return ''; return ''
} else { } else {
return new Buffer(0); return new Buffer(0)
} }
} }
if (info.unpacked) { if (info.unpacked) {
realPath = archive.copyFileOut(filePath); realPath = archive.copyFileOut(filePath)
return fs.readFileSync(realPath, options); return fs.readFileSync(realPath, options)
} }
if (!options) { if (!options) {
options = { options = {
encoding: null encoding: null
}; }
} else if (util.isString(options)) { } else if (util.isString(options)) {
options = { options = {
encoding: options encoding: options
}; }
} else if (!util.isObject(options)) { } else if (!util.isObject(options)) {
throw new TypeError('Bad arguments'); throw new TypeError('Bad arguments')
} }
encoding = options.encoding; encoding = options.encoding
buffer = new Buffer(info.size); buffer = new Buffer(info.size)
fd = archive.getFd(); fd = archive.getFd()
if (!(fd >= 0)) { if (!(fd >= 0)) {
notFoundError(asarPath, filePath); notFoundError(asarPath, filePath)
} }
logASARAccess(asarPath, filePath, info.offset); logASARAccess(asarPath, filePath, info.offset)
fs.readSync(fd, buffer, 0, info.size, info.offset); fs.readSync(fd, buffer, 0, info.size, info.offset)
if (encoding) { if (encoding) {
return buffer.toString(encoding); return buffer.toString(encoding)
} else { } else {
return buffer; return buffer
} }
}; }
readdir = fs.readdir; readdir = fs.readdir
fs.readdir = function(p, callback) { fs.readdir = function (p, callback) {
var archive, files; var archive, files
const [isAsar, asarPath, filePath] = splitPath(p); const [isAsar, asarPath, filePath] = splitPath(p)
if (!isAsar) { if (!isAsar) {
return readdir.apply(this, arguments); return readdir.apply(this, arguments)
} }
archive = getOrCreateArchive(asarPath); archive = getOrCreateArchive(asarPath)
if (!archive) { if (!archive) {
return invalidArchiveError(asarPath, callback); return invalidArchiveError(asarPath, callback)
} }
files = archive.readdir(filePath); files = archive.readdir(filePath)
if (!files) { if (!files) {
return notFoundError(asarPath, filePath, callback); return notFoundError(asarPath, filePath, callback)
} }
return process.nextTick(function() { return process.nextTick(function () {
return callback(null, files); return callback(null, files)
}); })
}; }
readdirSync = fs.readdirSync; readdirSync = fs.readdirSync
fs.readdirSync = function(p) { fs.readdirSync = function (p) {
var archive, files; var archive, files
const [isAsar, asarPath, filePath] = splitPath(p); const [isAsar, asarPath, filePath] = splitPath(p)
if (!isAsar) { if (!isAsar) {
return readdirSync.apply(this, arguments); return readdirSync.apply(this, arguments)
} }
archive = getOrCreateArchive(asarPath); archive = getOrCreateArchive(asarPath)
if (!archive) { if (!archive) {
invalidArchiveError(asarPath); invalidArchiveError(asarPath)
} }
files = archive.readdir(filePath); files = archive.readdir(filePath)
if (!files) { if (!files) {
notFoundError(asarPath, filePath); notFoundError(asarPath, filePath)
} }
return files; return files
}; }
internalModuleReadFile = process.binding('fs').internalModuleReadFile; internalModuleReadFile = process.binding('fs').internalModuleReadFile
process.binding('fs').internalModuleReadFile = function(p) { process.binding('fs').internalModuleReadFile = function (p) {
var archive, buffer, fd, info, realPath; var archive, buffer, fd, info, realPath
const [isAsar, asarPath, filePath] = splitPath(p); const [isAsar, asarPath, filePath] = splitPath(p)
if (!isAsar) { if (!isAsar) {
return internalModuleReadFile(p); return internalModuleReadFile(p)
} }
archive = getOrCreateArchive(asarPath); archive = getOrCreateArchive(asarPath)
if (!archive) { if (!archive) {
return void 0; return void 0
} }
info = archive.getFileInfo(filePath); info = archive.getFileInfo(filePath)
if (!info) { if (!info) {
return void 0; return void 0
} }
if (info.size === 0) { if (info.size === 0) {
return ''; return ''
} }
if (info.unpacked) { if (info.unpacked) {
realPath = archive.copyFileOut(filePath); realPath = archive.copyFileOut(filePath)
return fs.readFileSync(realPath, { return fs.readFileSync(realPath, {
encoding: 'utf8' encoding: 'utf8'
}); })
} }
buffer = new Buffer(info.size); buffer = new Buffer(info.size)
fd = archive.getFd(); fd = archive.getFd()
if (!(fd >= 0)) { if (!(fd >= 0)) {
return void 0; return void 0
} }
logASARAccess(asarPath, filePath, info.offset); logASARAccess(asarPath, filePath, info.offset)
fs.readSync(fd, buffer, 0, info.size, info.offset); fs.readSync(fd, buffer, 0, info.size, info.offset)
return buffer.toString('utf8'); return buffer.toString('utf8')
}; }
internalModuleStat = process.binding('fs').internalModuleStat; internalModuleStat = process.binding('fs').internalModuleStat
process.binding('fs').internalModuleStat = function(p) { process.binding('fs').internalModuleStat = function (p) {
var archive, stats; var archive, stats
const [isAsar, asarPath, filePath] = splitPath(p); const [isAsar, asarPath, filePath] = splitPath(p)
if (!isAsar) { if (!isAsar) {
return internalModuleStat(p); return internalModuleStat(p)
} }
archive = getOrCreateArchive(asarPath); archive = getOrCreateArchive(asarPath)
// -ENOENT // -ENOENT
if (!archive) { if (!archive) {
return -34; return -34
} }
stats = archive.stat(filePath); stats = archive.stat(filePath)
// -ENOENT // -ENOENT
if (!stats) { if (!stats) {
return -34; return -34
} }
if (stats.isDirectory) { if (stats.isDirectory) {
return 1; return 1
} else { } else {
return 0; return 0
} }
}; }
// Calling mkdir for directory inside asar archive should throw ENOTDIR // Calling mkdir for directory inside asar archive should throw ENOTDIR
// error, but on Windows it throws ENOENT. // error, but on Windows it throws ENOENT.
// This is to work around the recursive looping bug of mkdirp since it is // This is to work around the recursive looping bug of mkdirp since it is
// widely used. // widely used.
if (process.platform === 'win32') { if (process.platform === 'win32') {
mkdir = fs.mkdir; mkdir = fs.mkdir
fs.mkdir = function(p, mode, callback) { fs.mkdir = function (p, mode, callback) {
if (typeof mode === 'function') { if (typeof mode === 'function') {
callback = mode; callback = mode
} }
const [isAsar, , filePath] = splitPath(p); const [isAsar, , filePath] = splitPath(p)
if (isAsar && filePath.length) { if (isAsar && filePath.length) {
return notDirError(callback); return notDirError(callback)
} }
return mkdir(p, mode, callback); return mkdir(p, mode, callback)
}; }
mkdirSync = fs.mkdirSync; mkdirSync = fs.mkdirSync
fs.mkdirSync = function(p, mode) { fs.mkdirSync = function (p, mode) {
const [isAsar, , filePath] = splitPath(p); const [isAsar, , filePath] = splitPath(p)
if (isAsar && filePath.length) { if (isAsar && filePath.length) {
notDirError(); notDirError()
} }
return mkdirSync(p, mode); return mkdirSync(p, mode)
}; }
} }
overrideAPI(fs, 'open'); overrideAPI(fs, 'open')
overrideAPI(child_process, 'execFile'); overrideAPI(child_process, 'execFile')
overrideAPISync(process, 'dlopen', 1); overrideAPISync(process, 'dlopen', 1)
overrideAPISync(require('module')._extensions, '.node', 1); overrideAPISync(require('module')._extensions, '.node', 1)
overrideAPISync(fs, 'openSync'); overrideAPISync(fs, 'openSync')
return overrideAPISync(child_process, 'execFileSync'); return overrideAPISync(child_process, 'execFileSync')
}; }
})(); })()

View file

@ -1,20 +1,20 @@
(function () { ;(function () {
return function(process, require, asarSource) { return function (process, require, asarSource) {
// Make asar.coffee accessible via "require". // Make asar.coffee accessible via "require".
process.binding('natives').ATOM_SHELL_ASAR = asarSource; process.binding('natives').ATOM_SHELL_ASAR = asarSource
// Monkey-patch the fs module. // Monkey-patch the fs module.
require('ATOM_SHELL_ASAR').wrapFsWithAsar(require('fs')); require('ATOM_SHELL_ASAR').wrapFsWithAsar(require('fs'))
// Make graceful-fs work with asar. // Make graceful-fs work with asar.
var source = process.binding('natives'); var source = process.binding('natives')
source['original-fs'] = source.fs; source['original-fs'] = source.fs
return source['fs'] = ` source['fs'] = `
var nativeModule = new process.NativeModule('original-fs'); var nativeModule = new process.NativeModule('original-fs')
nativeModule.cache(); nativeModule.cache()
nativeModule.compile(); nativeModule.compile()
var asar = require('ATOM_SHELL_ASAR'); var asar = require('ATOM_SHELL_ASAR')
asar.wrapFsWithAsar(nativeModule.exports); asar.wrapFsWithAsar(nativeModule.exports)
module.exports = nativeModule.exports`; module.exports = nativeModule.exports`
}; }
})(); })()

View file

@ -1,47 +1,46 @@
const path = require('path'); const path = require('path')
const timers = require('timers'); const timers = require('timers')
const Module = require('module'); const Module = require('module')
process.atomBinding = function(name) { process.atomBinding = function (name) {
try { try {
return process.binding("atom_" + process.type + "_" + name); return process.binding('atom_' + process.type + '_' + name)
} catch (error) { } catch (error) {
if (/No such module/.test(error.message)) { if (/No such module/.test(error.message)) {
return process.binding("atom_common_" + name); return process.binding('atom_common_' + name)
} }
} }
}; }
if (!process.env.ELECTRON_HIDE_INTERNAL_MODULES) { if (!process.env.ELECTRON_HIDE_INTERNAL_MODULES) {
// Add common/api/lib to module search paths. // Add common/api/lib to module search paths.
Module.globalPaths.push(path.join(__dirname, 'api')); Module.globalPaths.push(path.join(__dirname, 'api'))
} }
// setImmediate and process.nextTick makes use of uv_check and uv_prepare to // setImmediate and process.nextTick makes use of uv_check and uv_prepare to
// run the callbacks, however since we only run uv loop on requests, the // run the callbacks, however since we only run uv loop on requests, the
// callbacks wouldn't be called until something else activated the uv loop, // callbacks wouldn't be called until something else activated the uv loop,
// which would delay the callbacks for arbitrary long time. So we should // which would delay the callbacks for arbitrary long time. So we should
// initiatively activate the uv loop once setImmediate and process.nextTick is // initiatively activate the uv loop once setImmediate and process.nextTick is
// called. // called.
var wrapWithActivateUvLoop = function(func) { var wrapWithActivateUvLoop = function (func) {
return function() { return function () {
process.activateUvLoop(); process.activateUvLoop()
return func.apply(this, arguments); return func.apply(this, arguments)
}; }
}; }
process.nextTick = wrapWithActivateUvLoop(process.nextTick); process.nextTick = wrapWithActivateUvLoop(process.nextTick)
global.setImmediate = wrapWithActivateUvLoop(timers.setImmediate); global.setImmediate = wrapWithActivateUvLoop(timers.setImmediate)
global.clearImmediate = timers.clearImmediate; global.clearImmediate = timers.clearImmediate
if (process.type === 'browser') { if (process.type === 'browser') {
// setTimeout needs to update the polling timeout of the event loop, when // setTimeout needs to update the polling timeout of the event loop, when
// called under Chromium's event loop the node's event loop won't get a chance // called under Chromium's event loop the node's event loop won't get a chance
// to update the timeout, so we have to force the node's event loop to // to update the timeout, so we have to force the node's event loop to
// recalculate the timeout in browser process. // recalculate the timeout in browser process.
global.setTimeout = wrapWithActivateUvLoop(timers.setTimeout); global.setTimeout = wrapWithActivateUvLoop(timers.setTimeout)
global.setInterval = wrapWithActivateUvLoop(timers.setInterval); global.setInterval = wrapWithActivateUvLoop(timers.setInterval)
} }

View file

@ -1,36 +1,36 @@
const path = require('path'); const path = require('path')
const Module = require('module'); const Module = require('module')
// Clear Node's global search paths. // Clear Node's global search paths.
Module.globalPaths.length = 0; Module.globalPaths.length = 0
// Clear current and parent(init.coffee)'s search paths. // Clear current and parent(init.coffee)'s search paths.
module.paths = []; module.paths = []
module.parent.paths = []; module.parent.paths = []
// Prevent Node from adding paths outside this app to search paths. // Prevent Node from adding paths outside this app to search paths.
Module._nodeModulePaths = function(from) { Module._nodeModulePaths = function (from) {
var dir, i, part, parts, paths, skipOutsidePaths, splitRe, tip; var dir, i, part, parts, paths, skipOutsidePaths, splitRe, tip
from = path.resolve(from); from = path.resolve(from)
// If "from" is outside the app then we do nothing. // If "from" is outside the app then we do nothing.
skipOutsidePaths = from.startsWith(process.resourcesPath); skipOutsidePaths = from.startsWith(process.resourcesPath)
// Following logoic is copied from module.js. // Following logoic is copied from module.js.
splitRe = process.platform === 'win32' ? /[\/\\]/ : /\//; splitRe = process.platform === 'win32' ? /[\/\\]/ : /\//
paths = []; paths = []
parts = from.split(splitRe); parts = from.split(splitRe)
for (tip = i = parts.length - 1; i >= 0; tip = i += -1) { for (tip = i = parts.length - 1; i >= 0; tip = i += -1) {
part = parts[tip]; part = parts[tip]
if (part === 'node_modules') { if (part === 'node_modules') {
continue; continue
} }
dir = parts.slice(0, tip + 1).join(path.sep); dir = parts.slice(0, tip + 1).join(path.sep)
if (skipOutsidePaths && !dir.startsWith(process.resourcesPath)) { if (skipOutsidePaths && !dir.startsWith(process.resourcesPath)) {
break; break
} }
paths.push(path.join(dir, 'node_modules')); paths.push(path.join(dir, 'node_modules'))
} }
return paths; return paths
}; }

View file

@ -1,47 +1,47 @@
const ipcRenderer = require('electron').ipcRenderer; const ipcRenderer = require('electron').ipcRenderer
const nativeImage = require('electron').nativeImage; const nativeImage = require('electron').nativeImage
var nextId = 0; var nextId = 0
var includes = [].includes; var includes = [].includes
var getNextId = function() { var getNextId = function () {
return ++nextId; return ++nextId
}; }
// |options.type| can not be empty and has to include 'window' or 'screen'. // |options.type| can not be empty and has to include 'window' or 'screen'.
var isValid = function(options) { var isValid = function (options) {
return ((options != null ? options.types : void 0) != null) && Array.isArray(options.types); return ((options != null ? options.types : void 0) != null) && Array.isArray(options.types)
}; }
exports.getSources = function(options, callback) { exports.getSources = function (options, callback) {
var captureScreen, captureWindow, id; var captureScreen, captureWindow, id
if (!isValid(options)) { if (!isValid(options)) {
return callback(new Error('Invalid options')); return callback(new Error('Invalid options'))
} }
captureWindow = includes.call(options.types, 'window'); captureWindow = includes.call(options.types, 'window')
captureScreen = includes.call(options.types, 'screen'); captureScreen = includes.call(options.types, 'screen')
if (options.thumbnailSize == null) { if (options.thumbnailSize == null) {
options.thumbnailSize = { options.thumbnailSize = {
width: 150, width: 150,
height: 150 height: 150
}; }
} }
id = getNextId(); id = getNextId()
ipcRenderer.send('ATOM_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', captureWindow, captureScreen, options.thumbnailSize, id); ipcRenderer.send('ATOM_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', captureWindow, captureScreen, options.thumbnailSize, id)
return ipcRenderer.once("ATOM_RENDERER_DESKTOP_CAPTURER_RESULT_" + id, function(event, sources) { return ipcRenderer.once('ATOM_RENDERER_DESKTOP_CAPTURER_RESULT_' + id, function (event, sources) {
var source; var source
return callback(null, (function() { return callback(null, (function () {
var i, len, results; var i, len, results
results = []; results = []
for (i = 0, len = sources.length; i < len; i++) { for (i = 0, len = sources.length; i < len; i++) {
source = sources[i]; source = sources[i]
results.push({ results.push({
id: source.id, id: source.id,
name: source.name, name: source.name,
thumbnail: nativeImage.createFromDataURL(source.thumbnail) thumbnail: nativeImage.createFromDataURL(source.thumbnail)
}); })
} }
return results; return results
})()); })())
}); })
}; }

View file

@ -1,38 +1,38 @@
const common = require('../../../common/api/exports/electron'); const common = require('../../../common/api/exports/electron')
// Import common modules. // Import common modules.
common.defineProperties(exports); common.defineProperties(exports)
Object.defineProperties(exports, { Object.defineProperties(exports, {
// Renderer side modules, please sort with alphabet order. // Renderer side modules, please sort with alphabet order.
desktopCapturer: { desktopCapturer: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../desktop-capturer'); return require('../desktop-capturer')
} }
}, },
ipcRenderer: { ipcRenderer: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../ipc-renderer'); return require('../ipc-renderer')
} }
}, },
remote: { remote: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../remote'); return require('../remote')
} }
}, },
screen: { screen: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../screen'); return require('../screen')
} }
}, },
webFrame: { webFrame: {
enumerable: true, enumerable: true,
get: function() { get: function () {
return require('../web-frame'); return require('../web-frame')
} }
} }
}); })

View file

@ -1,21 +1,21 @@
'use strict'; 'use strict'
const binding = process.atomBinding('ipc'); const binding = process.atomBinding('ipc')
const v8Util = process.atomBinding('v8_util'); const v8Util = process.atomBinding('v8_util')
// Created by init.js. // Created by init.js.
const ipcRenderer = v8Util.getHiddenValue(global, 'ipc'); const ipcRenderer = v8Util.getHiddenValue(global, 'ipc')
ipcRenderer.send = function(...args) { ipcRenderer.send = function (...args) {
return binding.send('ipc-message', args); return binding.send('ipc-message', args)
}; }
ipcRenderer.sendSync = function(...args) { ipcRenderer.sendSync = function (...args) {
return JSON.parse(binding.sendSync('ipc-message-sync', args)); return JSON.parse(binding.sendSync('ipc-message-sync', args))
}; }
ipcRenderer.sendToHost = function(...args) { ipcRenderer.sendToHost = function (...args) {
return binding.send('ipc-message-host', args); return binding.send('ipc-message-host', args)
}; }
module.exports = ipcRenderer; module.exports = ipcRenderer

View file

@ -1,27 +1,27 @@
const ipcRenderer = require('electron').ipcRenderer; const ipcRenderer = require('electron').ipcRenderer
const deprecate = require('electron').deprecate; const deprecate = require('electron').deprecate
const EventEmitter = require('events').EventEmitter; const EventEmitter = require('events').EventEmitter
// This module is deprecated, we mirror everything from ipcRenderer. // This module is deprecated, we mirror everything from ipcRenderer.
deprecate.warn('ipc module', 'require("electron").ipcRenderer'); deprecate.warn('ipc module', 'require("electron").ipcRenderer')
// Routes events of ipcRenderer. // Routes events of ipcRenderer.
var ipc = new EventEmitter; var ipc = new EventEmitter()
ipcRenderer.emit = function(channel, event, ...args) { ipcRenderer.emit = function (channel, event, ...args) {
ipc.emit.apply(ipc, [channel].concat(args)); ipc.emit.apply(ipc, [channel].concat(args))
return EventEmitter.prototype.emit.apply(ipcRenderer, arguments); return EventEmitter.prototype.emit.apply(ipcRenderer, arguments)
}; }
// Deprecated. // Deprecated.
for (var method in ipcRenderer) { for (var method in ipcRenderer) {
if (method.startsWith('send')) { if (method.startsWith('send')) {
ipc[method] = ipcRenderer[method]; ipc[method] = ipcRenderer[method]
} }
} }
deprecate.rename(ipc, 'sendChannel', 'send'); deprecate.rename(ipc, 'sendChannel', 'send')
deprecate.rename(ipc, 'sendChannelSync', 'sendSync'); deprecate.rename(ipc, 'sendChannelSync', 'sendSync')
module.exports = ipc; module.exports = ipc

View file

@ -1,306 +1,303 @@
'use strict'; 'use strict'
const ipcRenderer = require('electron').ipcRenderer; const ipcRenderer = require('electron').ipcRenderer
const CallbacksRegistry = require('electron').CallbacksRegistry; const CallbacksRegistry = require('electron').CallbacksRegistry
const v8Util = process.atomBinding('v8_util'); const v8Util = process.atomBinding('v8_util')
const IDWeakMap = process.atomBinding('id_weak_map').IDWeakMap; const IDWeakMap = process.atomBinding('id_weak_map').IDWeakMap
const callbacksRegistry = new CallbacksRegistry; const callbacksRegistry = new CallbacksRegistry()
var includes = [].includes; var includes = [].includes
var remoteObjectCache = new IDWeakMap; var remoteObjectCache = new IDWeakMap()
// Check for circular reference. // Check for circular reference.
var isCircular = function(field, visited) { var isCircular = function (field, visited) {
if (typeof field === 'object') { if (typeof field === 'object') {
if (includes.call(visited, field)) { if (includes.call(visited, field)) {
return true; return true
} }
visited.push(field); visited.push(field)
} }
return false; return false
}; }
// Convert the arguments object into an array of meta data. // Convert the arguments object into an array of meta data.
var wrapArgs = function(args, visited) { var wrapArgs = function (args, visited) {
var valueToMeta; var valueToMeta
if (visited == null) { if (visited == null) {
visited = []; visited = []
} }
valueToMeta = function(value) { valueToMeta = function (value) {
var field, prop, ret; var field, prop, ret
if (Array.isArray(value)) { if (Array.isArray(value)) {
return { return {
type: 'array', type: 'array',
value: wrapArgs(value, visited) value: wrapArgs(value, visited)
}; }
} else if (Buffer.isBuffer(value)) { } else if (Buffer.isBuffer(value)) {
return { return {
type: 'buffer', type: 'buffer',
value: Array.prototype.slice.call(value, 0) value: Array.prototype.slice.call(value, 0)
}; }
} else if (value instanceof Date) { } else if (value instanceof Date) {
return { return {
type: 'date', type: 'date',
value: value.getTime() value: value.getTime()
}; }
} else if ((value != null ? value.constructor.name : void 0) === 'Promise') { } else if ((value != null ? value.constructor.name : void 0) === 'Promise') {
return { return {
type: 'promise', type: 'promise',
then: valueToMeta(function(v) { value.then(v); }) then: valueToMeta(function (v) { value.then(v) })
}; }
} else if ((value != null) && typeof value === 'object' && v8Util.getHiddenValue(value, 'atomId')) { } else if ((value != null) && typeof value === 'object' && v8Util.getHiddenValue(value, 'atomId')) {
return { return {
type: 'remote-object', type: 'remote-object',
id: v8Util.getHiddenValue(value, 'atomId') id: v8Util.getHiddenValue(value, 'atomId')
}; }
} else if ((value != null) && typeof value === 'object') { } else if ((value != null) && typeof value === 'object') {
ret = { ret = {
type: 'object', type: 'object',
name: value.constructor.name, name: value.constructor.name,
members: [] members: []
}; }
for (prop in value) { for (prop in value) {
field = value[prop]; field = value[prop]
ret.members.push({ ret.members.push({
name: prop, name: prop,
value: valueToMeta(isCircular(field, visited) ? null : field) value: valueToMeta(isCircular(field, visited) ? null : field)
}); })
} }
return ret; return ret
} else if (typeof value === 'function' && v8Util.getHiddenValue(value, 'returnValue')) { } else if (typeof value === 'function' && v8Util.getHiddenValue(value, 'returnValue')) {
return { return {
type: 'function-with-return-value', type: 'function-with-return-value',
value: valueToMeta(value()) value: valueToMeta(value())
}; }
} else if (typeof value === 'function') { } else if (typeof value === 'function') {
return { return {
type: 'function', type: 'function',
id: callbacksRegistry.add(value), id: callbacksRegistry.add(value),
location: v8Util.getHiddenValue(value, 'location') location: v8Util.getHiddenValue(value, 'location')
}; }
} else { } else {
return { return {
type: 'value', type: 'value',
value: value value: value
}; }
} }
}; }
return Array.prototype.slice.call(args).map(valueToMeta); return Array.prototype.slice.call(args).map(valueToMeta)
}; }
// Populate object's members from descriptors. // Populate object's members from descriptors.
// This matches |getObjectMemebers| in rpc-server. // This matches |getObjectMemebers| in rpc-server.
let setObjectMembers = function(object, metaId, members) { let setObjectMembers = function (object, metaId, members) {
for (let member of members) { for (let member of members) {
if (object.hasOwnProperty(member.name)) if (object.hasOwnProperty(member.name)) continue
continue;
let descriptor = { enumerable: member.enumerable }; let descriptor = { enumerable: member.enumerable }
if (member.type === 'method') { if (member.type === 'method') {
let remoteMemberFunction = function() { let remoteMemberFunction = function () {
if (this && this.constructor === remoteMemberFunction) { if (this && this.constructor === remoteMemberFunction) {
// Constructor call. // Constructor call.
let ret = ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_CONSTRUCTOR', metaId, member.name, wrapArgs(arguments)); let ret = ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_CONSTRUCTOR', metaId, member.name, wrapArgs(arguments))
return metaToValue(ret); return metaToValue(ret)
} else { } else {
// Call member function. // Call member function.
let ret = ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_CALL', metaId, member.name, wrapArgs(arguments)); let ret = ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_CALL', metaId, member.name, wrapArgs(arguments))
return metaToValue(ret); return metaToValue(ret)
} }
}; }
descriptor.writable = true; descriptor.writable = true
descriptor.configurable = true; descriptor.configurable = true
descriptor.value = remoteMemberFunction; descriptor.value = remoteMemberFunction
} else if (member.type === 'get') { } else if (member.type === 'get') {
descriptor.get = function() { descriptor.get = function () {
return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_GET', metaId, member.name)); return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_GET', metaId, member.name))
}; }
// Only set setter when it is writable. // Only set setter when it is writable.
if (member.writable) { if (member.writable) {
descriptor.set = function(value) { descriptor.set = function (value) {
ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_SET', metaId, member.name, value); ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_SET', metaId, member.name, value)
return value; return value
}; }
} }
} }
Object.defineProperty(object, member.name, descriptor); Object.defineProperty(object, member.name, descriptor)
} }
}; }
// Populate object's prototype from descriptor. // Populate object's prototype from descriptor.
// This matches |getObjectPrototype| in rpc-server. // This matches |getObjectPrototype| in rpc-server.
let setObjectPrototype = function(object, metaId, descriptor) { let setObjectPrototype = function (object, metaId, descriptor) {
if (descriptor === null) if (descriptor === null) return
return; let proto = {}
let proto = {}; setObjectMembers(proto, metaId, descriptor.members)
setObjectMembers(proto, metaId, descriptor.members); setObjectPrototype(proto, metaId, descriptor.proto)
setObjectPrototype(proto, metaId, descriptor.proto); Object.setPrototypeOf(object, proto)
Object.setPrototypeOf(object, proto); }
};
// Convert meta data from browser into real value. // Convert meta data from browser into real value.
let metaToValue = function(meta) { let metaToValue = function (meta) {
var el, i, len, ref1, results, ret; var el, i, len, ref1, results, ret
switch (meta.type) { switch (meta.type) {
case 'value': case 'value':
return meta.value; return meta.value
case 'array': case 'array':
ref1 = meta.members; ref1 = meta.members
results = []; results = []
for (i = 0, len = ref1.length; i < len; i++) { for (i = 0, len = ref1.length; i < len; i++) {
el = ref1[i]; el = ref1[i]
results.push(metaToValue(el)); results.push(metaToValue(el))
} }
return results; return results
case 'buffer': case 'buffer':
return new Buffer(meta.value); return new Buffer(meta.value)
case 'promise': case 'promise':
return Promise.resolve({ return Promise.resolve({
then: metaToValue(meta.then) then: metaToValue(meta.then)
}); })
case 'error': case 'error':
return metaToPlainObject(meta); return metaToPlainObject(meta)
case 'date': case 'date':
return new Date(meta.value); return new Date(meta.value)
case 'exception': case 'exception':
throw new Error(meta.message + "\n" + meta.stack); throw new Error(meta.message + '\n' + meta.stack)
default: default:
if (remoteObjectCache.has(meta.id)) if (remoteObjectCache.has(meta.id)) return remoteObjectCache.get(meta.id)
return remoteObjectCache.get(meta.id);
if (meta.type === 'function') { if (meta.type === 'function') {
// A shadow class to represent the remote function object. // A shadow class to represent the remote function object.
let remoteFunction = function() { let remoteFunction = function () {
if (this && this.constructor === remoteFunction) { if (this && this.constructor === remoteFunction) {
// Constructor call. // Constructor call.
let obj = ipcRenderer.sendSync('ATOM_BROWSER_CONSTRUCTOR', meta.id, wrapArgs(arguments)); let obj = ipcRenderer.sendSync('ATOM_BROWSER_CONSTRUCTOR', meta.id, wrapArgs(arguments))
// Returning object in constructor will replace constructed object // Returning object in constructor will replace constructed object
// with the returned object. // with the returned object.
// http://stackoverflow.com/questions/1978049/what-values-can-a-constructor-return-to-avoid-returning-this // http://stackoverflow.com/questions/1978049/what-values-can-a-constructor-return-to-avoid-returning-this
return metaToValue(obj); return metaToValue(obj)
} else { } else {
// Function call. // Function call.
let obj = ipcRenderer.sendSync('ATOM_BROWSER_FUNCTION_CALL', meta.id, wrapArgs(arguments)); let obj = ipcRenderer.sendSync('ATOM_BROWSER_FUNCTION_CALL', meta.id, wrapArgs(arguments))
return metaToValue(obj); return metaToValue(obj)
} }
}; }
ret = remoteFunction; ret = remoteFunction
} else { } else {
ret = {}; ret = {}
} }
// Populate delegate members. // Populate delegate members.
setObjectMembers(ret, meta.id, meta.members); setObjectMembers(ret, meta.id, meta.members)
// Populate delegate prototype. // Populate delegate prototype.
setObjectPrototype(ret, meta.id, meta.proto); setObjectPrototype(ret, meta.id, meta.proto)
// Set constructor.name to object's name. // Set constructor.name to object's name.
Object.defineProperty(ret.constructor, 'name', { value: meta.name }); Object.defineProperty(ret.constructor, 'name', { value: meta.name })
// Track delegate object's life time, and tell the browser to clean up // Track delegate object's life time, and tell the browser to clean up
// when the object is GCed. // when the object is GCed.
v8Util.setDestructor(ret, function() { v8Util.setDestructor(ret, function () {
ipcRenderer.send('ATOM_BROWSER_DEREFERENCE', meta.id); ipcRenderer.send('ATOM_BROWSER_DEREFERENCE', meta.id)
}); })
// Remember object's id. // Remember object's id.
v8Util.setHiddenValue(ret, 'atomId', meta.id); v8Util.setHiddenValue(ret, 'atomId', meta.id)
remoteObjectCache.set(meta.id, ret); remoteObjectCache.set(meta.id, ret)
return ret; return ret
} }
}; }
// Construct a plain object from the meta. // Construct a plain object from the meta.
var metaToPlainObject = function(meta) { var metaToPlainObject = function (meta) {
var i, len, obj, ref1; var i, len, obj, ref1
obj = (function() { obj = (function () {
switch (meta.type) { switch (meta.type) {
case 'error': case 'error':
return new Error; return new Error()
default: default:
return {}; return {}
} }
})(); })()
ref1 = meta.members; ref1 = meta.members
for (i = 0, len = ref1.length; i < len; i++) { for (i = 0, len = ref1.length; i < len; i++) {
let {name, value} = ref1[i]; let {name, value} = ref1[i]
obj[name] = value; obj[name] = value
} }
return obj; return obj
}; }
// Browser calls a callback in renderer. // Browser calls a callback in renderer.
ipcRenderer.on('ATOM_RENDERER_CALLBACK', function(event, id, args) { ipcRenderer.on('ATOM_RENDERER_CALLBACK', function (event, id, args) {
return callbacksRegistry.apply(id, metaToValue(args)); return callbacksRegistry.apply(id, metaToValue(args))
}); })
// A callback in browser is released. // A callback in browser is released.
ipcRenderer.on('ATOM_RENDERER_RELEASE_CALLBACK', function(event, id) { ipcRenderer.on('ATOM_RENDERER_RELEASE_CALLBACK', function (event, id) {
return callbacksRegistry.remove(id); return callbacksRegistry.remove(id)
}); })
// List all built-in modules in browser process. // List all built-in modules in browser process.
const browserModules = require('../../browser/api/exports/electron'); const browserModules = require('../../browser/api/exports/electron')
// And add a helper receiver for each one. // And add a helper receiver for each one.
var fn = function(name) { var fn = function (name) {
return Object.defineProperty(exports, name, { return Object.defineProperty(exports, name, {
get: function() { get: function () {
return exports.getBuiltin(name); return exports.getBuiltin(name)
} }
}); })
}; }
for (var name in browserModules) { for (var name in browserModules) {
fn(name); fn(name)
} }
// Get remote module. // Get remote module.
exports.require = function(module) { exports.require = function (module) {
return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_REQUIRE', module)); return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_REQUIRE', module))
}; }
// Alias to remote.require('electron').xxx. // Alias to remote.require('electron').xxx.
exports.getBuiltin = function(module) { exports.getBuiltin = function (module) {
return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_GET_BUILTIN', module)); return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_GET_BUILTIN', module))
}; }
// Get current BrowserWindow. // Get current BrowserWindow.
exports.getCurrentWindow = function() { exports.getCurrentWindow = function () {
return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_CURRENT_WINDOW')); return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_CURRENT_WINDOW'))
}; }
// Get current WebContents object. // Get current WebContents object.
exports.getCurrentWebContents = function() { exports.getCurrentWebContents = function () {
return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_CURRENT_WEB_CONTENTS')); return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_CURRENT_WEB_CONTENTS'))
}; }
// Get a global object in browser. // Get a global object in browser.
exports.getGlobal = function(name) { exports.getGlobal = function (name) {
return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_GLOBAL', name)); return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_GLOBAL', name))
}; }
// Get the process object in browser. // Get the process object in browser.
exports.__defineGetter__('process', function() { exports.__defineGetter__('process', function () {
return exports.getGlobal('process'); return exports.getGlobal('process')
}); })
// Create a funtion that will return the specifed value when called in browser. // Create a funtion that will return the specifed value when called in browser.
exports.createFunctionWithReturnValue = function(returnValue) { exports.createFunctionWithReturnValue = function (returnValue) {
var func; var func
func = function() { func = function () {
return returnValue; return returnValue
}; }
v8Util.setHiddenValue(func, 'returnValue', true); v8Util.setHiddenValue(func, 'returnValue', true)
return func; return func
}; }
// Get the guest WebContents from guestInstanceId. // Get the guest WebContents from guestInstanceId.
exports.getGuestWebContents = function(guestInstanceId) { exports.getGuestWebContents = function (guestInstanceId) {
var meta; var meta
meta = ipcRenderer.sendSync('ATOM_BROWSER_GUEST_WEB_CONTENTS', guestInstanceId); meta = ipcRenderer.sendSync('ATOM_BROWSER_GUEST_WEB_CONTENTS', guestInstanceId)
return metaToValue(meta); return metaToValue(meta)
}; }

View file

@ -1 +1 @@
module.exports = require('electron').remote.screen; module.exports = require('electron').remote.screen

View file

@ -1,19 +1,19 @@
'use strict'; 'use strict'
const deprecate = require('electron').deprecate; const deprecate = require('electron').deprecate
const EventEmitter = require('events').EventEmitter; const EventEmitter = require('events').EventEmitter
const webFrame = process.atomBinding('web_frame').webFrame; const webFrame = process.atomBinding('web_frame').webFrame
// webFrame is an EventEmitter. // webFrame is an EventEmitter.
webFrame.__proto__ = EventEmitter.prototype; Object.setPrototypeOf(webFrame, EventEmitter.prototype)
// Lots of webview would subscribe to webFrame's events. // Lots of webview would subscribe to webFrame's events.
webFrame.setMaxListeners(0); webFrame.setMaxListeners(0)
// Deprecated. // Deprecated.
deprecate.rename(webFrame, 'registerUrlSchemeAsSecure', 'registerURLSchemeAsSecure'); deprecate.rename(webFrame, 'registerUrlSchemeAsSecure', 'registerURLSchemeAsSecure')
deprecate.rename(webFrame, 'registerUrlSchemeAsBypassingCSP', 'registerURLSchemeAsBypassingCSP'); deprecate.rename(webFrame, 'registerUrlSchemeAsBypassingCSP', 'registerURLSchemeAsBypassingCSP')
deprecate.rename(webFrame, 'registerUrlSchemeAsPrivileged', 'registerURLSchemeAsPrivileged'); deprecate.rename(webFrame, 'registerUrlSchemeAsPrivileged', 'registerURLSchemeAsPrivileged')
module.exports = webFrame; module.exports = webFrame

View file

@ -1,13 +1,13 @@
const url = require('url'); const url = require('url')
const chrome = window.chrome = window.chrome || {}; const chrome = window.chrome = window.chrome || {}
chrome.extension = { chrome.extension = {
getURL: function(path) { getURL: function (path) {
return url.format({ return url.format({
protocol: location.protocol, protocol: window.location.protocol,
slashes: true, slashes: true,
hostname: location.hostname, hostname: window.location.hostname,
pathname: path pathname: path
}); })
} }
}; }

View file

@ -1,139 +1,139 @@
'use strict'; 'use strict'
const events = require('events'); const events = require('events')
const path = require('path'); const path = require('path')
const Module = require('module'); const Module = require('module')
// We modified the original process.argv to let node.js load the // We modified the original process.argv to let node.js load the
// atom-renderer.js, we need to restore it here. // atom-renderer.js, we need to restore it here.
process.argv.splice(1, 1); process.argv.splice(1, 1)
// Clear search paths. // Clear search paths.
require('../common/reset-search-paths'); require('../common/reset-search-paths')
// Import common settings. // Import common settings.
require('../common/init'); require('../common/init')
var globalPaths = Module.globalPaths; var globalPaths = Module.globalPaths
if (!process.env.ELECTRON_HIDE_INTERNAL_MODULES) { if (!process.env.ELECTRON_HIDE_INTERNAL_MODULES) {
globalPaths.push(path.join(__dirname, 'api')); globalPaths.push(path.join(__dirname, 'api'))
} }
// Expose public APIs. // Expose public APIs.
globalPaths.push(path.join(__dirname, 'api', 'exports')); globalPaths.push(path.join(__dirname, 'api', 'exports'))
// The global variable will be used by ipc for event dispatching // The global variable will be used by ipc for event dispatching
var v8Util = process.atomBinding('v8_util'); var v8Util = process.atomBinding('v8_util')
v8Util.setHiddenValue(global, 'ipc', new events.EventEmitter); v8Util.setHiddenValue(global, 'ipc', new events.EventEmitter())
// Use electron module after everything is ready. // Use electron module after everything is ready.
const electron = require('electron'); const electron = require('electron')
// Call webFrame method. // Call webFrame method.
electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', (event, method, args) => { electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', (event, method, args) => {
electron.webFrame[method].apply(electron.webFrame, args); electron.webFrame[method].apply(electron.webFrame, args)
}); })
electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (event, requestId, method, args) => { electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (event, requestId, method, args) => {
const responseCallback = function(result) { const responseCallback = function (result) {
event.sender.send(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, result); event.sender.send(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, result)
}; }
args.push(responseCallback); args.push(responseCallback)
electron.webFrame[method].apply(electron.webFrame, args); electron.webFrame[method].apply(electron.webFrame, args)
}); })
// Process command line arguments. // Process command line arguments.
var nodeIntegration = 'false'; var nodeIntegration = 'false'
var preloadScript = null; var preloadScript = null
var ref = process.argv; var ref = process.argv
var i, len, arg; var i, len, arg
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len = ref.length; i < len; i++) {
arg = ref[i]; arg = ref[i]
if (arg.indexOf('--guest-instance-id=') === 0) { if (arg.indexOf('--guest-instance-id=') === 0) {
// This is a guest web view. // This is a guest web view.
process.guestInstanceId = parseInt(arg.substr(arg.indexOf('=') + 1)); process.guestInstanceId = parseInt(arg.substr(arg.indexOf('=') + 1))
} else if (arg.indexOf('--opener-id=') === 0) { } else if (arg.indexOf('--opener-id=') === 0) {
// This is a guest BrowserWindow. // This is a guest BrowserWindow.
process.openerId = parseInt(arg.substr(arg.indexOf('=') + 1)); process.openerId = parseInt(arg.substr(arg.indexOf('=') + 1))
} else if (arg.indexOf('--node-integration=') === 0) { } else if (arg.indexOf('--node-integration=') === 0) {
nodeIntegration = arg.substr(arg.indexOf('=') + 1); nodeIntegration = arg.substr(arg.indexOf('=') + 1)
} else if (arg.indexOf('--preload=') === 0) { } else if (arg.indexOf('--preload=') === 0) {
preloadScript = arg.substr(arg.indexOf('=') + 1); preloadScript = arg.substr(arg.indexOf('=') + 1)
} }
} }
if (location.protocol === 'chrome-devtools:') { if (window.location.protocol === 'chrome-devtools:') {
// Override some inspector APIs. // Override some inspector APIs.
require('./inspector'); require('./inspector')
nodeIntegration = 'true'; nodeIntegration = 'true'
} else if (location.protocol === 'chrome-extension:') { } else if (window.location.protocol === 'chrome-extension:') {
// Add implementations of chrome API. // Add implementations of chrome API.
require('./chrome-api'); require('./chrome-api')
nodeIntegration = 'true'; nodeIntegration = 'true'
} else { } else {
// Override default web functions. // Override default web functions.
require('./override'); require('./override')
// Load webview tag implementation. // Load webview tag implementation.
if (process.guestInstanceId == null) { if (process.guestInstanceId == null) {
require('./web-view/web-view'); require('./web-view/web-view')
require('./web-view/web-view-attributes'); require('./web-view/web-view-attributes')
} }
} }
if (nodeIntegration === 'true' || nodeIntegration === 'all' || nodeIntegration === 'except-iframe' || nodeIntegration === 'manual-enable-iframe') { if (nodeIntegration === 'true' || nodeIntegration === 'all' || nodeIntegration === 'except-iframe' || nodeIntegration === 'manual-enable-iframe') {
// Export node bindings to global. // Export node bindings to global.
global.require = require; global.require = require
global.module = module; global.module = module
// Set the __filename to the path of html file if it is file: protocol. // Set the __filename to the path of html file if it is file: protocol.
if (window.location.protocol === 'file:') { if (window.location.protocol === 'file:') {
var pathname = process.platform === 'win32' && window.location.pathname[0] === '/' ? window.location.pathname.substr(1) : window.location.pathname; var pathname = process.platform === 'win32' && window.location.pathname[0] === '/' ? window.location.pathname.substr(1) : window.location.pathname
global.__filename = path.normalize(decodeURIComponent(pathname)); global.__filename = path.normalize(decodeURIComponent(pathname))
global.__dirname = path.dirname(global.__filename); global.__dirname = path.dirname(global.__filename)
// Set module's filename so relative require can work as expected. // Set module's filename so relative require can work as expected.
module.filename = global.__filename; module.filename = global.__filename
// Also search for module under the html file. // Also search for module under the html file.
module.paths = module.paths.concat(Module._nodeModulePaths(global.__dirname)); module.paths = module.paths.concat(Module._nodeModulePaths(global.__dirname))
} else { } else {
global.__filename = __filename; global.__filename = __filename
global.__dirname = __dirname; global.__dirname = __dirname
} }
// Redirect window.onerror to uncaughtException. // Redirect window.onerror to uncaughtException.
window.onerror = function(message, filename, lineno, colno, error) { window.onerror = function (message, filename, lineno, colno, error) {
if (global.process.listeners('uncaughtException').length > 0) { if (global.process.listeners('uncaughtException').length > 0) {
global.process.emit('uncaughtException', error); global.process.emit('uncaughtException', error)
return true; return true
} else { } else {
return false; return false
} }
}; }
} else { } else {
// Delete Node's symbols after the Environment has been loaded. // Delete Node's symbols after the Environment has been loaded.
process.once('loaded', function() { process.once('loaded', function () {
delete global.process; delete global.process
delete global.setImmediate; delete global.setImmediate
delete global.clearImmediate; delete global.clearImmediate
return delete global.global; return delete global.global
}); })
} }
// Load the script specfied by the "preload" attribute. // Load the script specfied by the "preload" attribute.
if (preloadScript) { if (preloadScript) {
try { try {
require(preloadScript); require(preloadScript)
} catch (error) { } catch (error) {
if (error.code === 'MODULE_NOT_FOUND') { if (error.code === 'MODULE_NOT_FOUND') {
console.error("Unable to load preload script " + preloadScript); console.error('Unable to load preload script ' + preloadScript)
} else { } else {
console.error(error); console.error(error)
console.error(error.stack); console.error(error.stack)
} }
} }
} }

View file

@ -1,16 +1,16 @@
window.onload = function() { window.onload = function () {
// Use menu API to show context menu. // Use menu API to show context menu.
InspectorFrontendHost.showContextMenuAtPoint = createMenu; window.InspectorFrontendHost.showContextMenuAtPoint = createMenu
// Use dialog API to override file chooser dialog. // Use dialog API to override file chooser dialog.
return (WebInspector.createFileSelectorElement = createFileSelectorElement); return (window.WebInspector.createFileSelectorElement = createFileSelectorElement)
}; }
var convertToMenuTemplate = function(items) { var convertToMenuTemplate = function (items) {
var fn, i, item, len, template; var fn, i, item, len, template
template = []; template = []
fn = function(item) { fn = function (item) {
var transformed; var transformed
transformed = item.type === 'subMenu' ? { transformed = item.type === 'subMenu' ? {
type: 'submenu', type: 'submenu',
label: item.label, label: item.label,
@ -27,55 +27,55 @@ var convertToMenuTemplate = function(items) {
type: 'normal', type: 'normal',
label: item.label, label: item.label,
enabled: item.enabled enabled: item.enabled
};
if (item.id != null) {
transformed.click = function() {
DevToolsAPI.contextMenuItemSelected(item.id);
return DevToolsAPI.contextMenuCleared();
};
} }
return template.push(transformed); if (item.id != null) {
}; transformed.click = function () {
for (i = 0, len = items.length; i < len; i++) { window.DevToolsAPI.contextMenuItemSelected(item.id)
item = items[i]; return window.DevToolsAPI.contextMenuCleared()
fn(item); }
}
return template.push(transformed)
} }
return template; for (i = 0, len = items.length; i < len; i++) {
}; item = items[i]
fn(item)
}
return template
}
var createMenu = function(x, y, items) { var createMenu = function (x, y, items) {
const remote = require('electron').remote; const remote = require('electron').remote
const Menu = remote.Menu; const Menu = remote.Menu
const menu = Menu.buildFromTemplate(convertToMenuTemplate(items)); const menu = Menu.buildFromTemplate(convertToMenuTemplate(items))
// The menu is expected to show asynchronously. // The menu is expected to show asynchronously.
return setTimeout(function() { return setTimeout(function () {
return menu.popup(remote.getCurrentWindow()); return menu.popup(remote.getCurrentWindow())
}); })
}; }
var showFileChooserDialog = function(callback) { var showFileChooserDialog = function (callback) {
var dialog, files, remote; var dialog, files, remote
remote = require('electron').remote; remote = require('electron').remote
dialog = remote.dialog; dialog = remote.dialog
files = dialog.showOpenDialog({}); files = dialog.showOpenDialog({})
if (files != null) { if (files != null) {
return callback(pathToHtml5FileObject(files[0])); return callback(pathToHtml5FileObject(files[0]))
} }
}; }
var pathToHtml5FileObject = function(path) { var pathToHtml5FileObject = function (path) {
var blob, fs; var blob, fs
fs = require('fs'); fs = require('fs')
blob = new Blob([fs.readFileSync(path)]); blob = new Blob([fs.readFileSync(path)])
blob.name = path; blob.name = path
return blob; return blob
}; }
var createFileSelectorElement = function(callback) { var createFileSelectorElement = function (callback) {
var fileSelectorElement; var fileSelectorElement
fileSelectorElement = document.createElement('span'); fileSelectorElement = document.createElement('span')
fileSelectorElement.style.display = 'none'; fileSelectorElement.style.display = 'none'
fileSelectorElement.click = showFileChooserDialog.bind(this, callback); fileSelectorElement.click = showFileChooserDialog.bind(this, callback)
return fileSelectorElement; return fileSelectorElement
}; }

View file

@ -1,266 +1,266 @@
'use strict'; 'use strict'
const ipcRenderer = require('electron').ipcRenderer; const ipcRenderer = require('electron').ipcRenderer
const remote = require('electron').remote; const remote = require('electron').remote
// Cache browser window visibility // Cache browser window visibility
var _isVisible = true; var _isVisible = true
var _isMinimized = false; var _isMinimized = false
(function() { var initWindow = function initWindow () {
var currentWindow; var currentWindow
currentWindow = remote.getCurrentWindow(); currentWindow = remote.getCurrentWindow()
_isVisible = currentWindow.isVisible(); _isVisible = currentWindow.isVisible()
_isMinimized = currentWindow.isMinimized(); _isMinimized = currentWindow.isMinimized()
})(); }
initWindow()
// Helper function to resolve relative url. // Helper function to resolve relative url.
var a = window.top.document.createElement('a'); var a = window.top.document.createElement('a')
var resolveURL = function(url) { var resolveURL = function (url) {
a.href = url; a.href = url
return a.href; return a.href
}; }
// Window object returned by "window.open". // Window object returned by "window.open".
var BrowserWindowProxy = (function() { var BrowserWindowProxy = (function () {
BrowserWindowProxy.proxies = {}; BrowserWindowProxy.proxies = {}
BrowserWindowProxy.getOrCreate = function(guestId) { BrowserWindowProxy.getOrCreate = function (guestId) {
var base; var base
return (base = this.proxies)[guestId] != null ? base[guestId] : base[guestId] = new BrowserWindowProxy(guestId); return (base = this.proxies)[guestId] != null ? base[guestId] : base[guestId] = new BrowserWindowProxy(guestId)
};
BrowserWindowProxy.remove = function(guestId) {
return delete this.proxies[guestId];
};
function BrowserWindowProxy(guestId1) {
this.guestId = guestId1;
this.closed = false;
ipcRenderer.once("ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED_" + this.guestId, () => {
BrowserWindowProxy.remove(this.guestId);
this.closed = true;
});
} }
BrowserWindowProxy.prototype.close = function() { BrowserWindowProxy.remove = function (guestId) {
return ipcRenderer.send('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', this.guestId); return delete this.proxies[guestId]
}; }
BrowserWindowProxy.prototype.focus = function() { function BrowserWindowProxy (guestId1) {
return ipcRenderer.send('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', this.guestId, 'focus'); this.guestId = guestId1
}; this.closed = false
ipcRenderer.once('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED_' + this.guestId, () => {
BrowserWindowProxy.remove(this.guestId)
this.closed = true
})
}
BrowserWindowProxy.prototype.blur = function() { BrowserWindowProxy.prototype.close = function () {
return ipcRenderer.send('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', this.guestId, 'blur'); return ipcRenderer.send('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', this.guestId)
}; }
BrowserWindowProxy.prototype.focus = function () {
return ipcRenderer.send('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', this.guestId, 'focus')
}
BrowserWindowProxy.prototype.blur = function () {
return ipcRenderer.send('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', this.guestId, 'blur')
}
Object.defineProperty(BrowserWindowProxy.prototype, 'location', { Object.defineProperty(BrowserWindowProxy.prototype, 'location', {
get: function() { get: function () {
return ipcRenderer.sendSync('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', this.guestId, 'getURL'); return ipcRenderer.sendSync('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', this.guestId, 'getURL')
}, },
set: function(url) { set: function (url) {
return ipcRenderer.sendSync('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', this.guestId, 'loadURL', url); return ipcRenderer.sendSync('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', this.guestId, 'loadURL', url)
} }
}); })
BrowserWindowProxy.prototype.postMessage = function(message, targetOrigin) { BrowserWindowProxy.prototype.postMessage = function (message, targetOrigin) {
if (targetOrigin == null) { if (targetOrigin == null) {
targetOrigin = '*'; targetOrigin = '*'
} }
return ipcRenderer.send('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', this.guestId, message, targetOrigin, location.origin); return ipcRenderer.send('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', this.guestId, message, targetOrigin, window.location.origin)
}; }
BrowserWindowProxy.prototype["eval"] = function(...args) { BrowserWindowProxy.prototype['eval'] = function (...args) {
return ipcRenderer.send.apply(ipcRenderer, ['ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', this.guestId, 'executeJavaScript'].concat(args)); return ipcRenderer.send.apply(ipcRenderer, ['ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', this.guestId, 'executeJavaScript'].concat(args))
}; }
return BrowserWindowProxy; return BrowserWindowProxy
})()
})();
if (process.guestInstanceId == null) { if (process.guestInstanceId == null) {
// Override default window.close. // Override default window.close.
window.close = function() { window.close = function () {
return remote.getCurrentWindow().close(); return remote.getCurrentWindow().close()
}; }
} }
// Make the browser window or guest view emit "new-window" event. // Make the browser window or guest view emit "new-window" event.
window.open = function(url, frameName, features) { window.open = function (url, frameName, features) {
var feature, guestId, i, j, len, len1, name, options, ref1, ref2, value; var feature, guestId, i, j, len, len1, name, options, ref1, ref2, value
if (frameName == null) { if (frameName == null) {
frameName = ''; frameName = ''
} }
if (features == null) { if (features == null) {
features = ''; features = ''
} }
options = {}; options = {}
// TODO remove hyphenated options in both of the following arrays for 1.0 // TODO remove hyphenated options in both of the following arrays for 1.0
const ints = ['x', 'y', 'width', 'height', 'min-width', 'minWidth', 'max-width', 'maxWidth', 'min-height', 'minHeight', 'max-height', 'maxHeight', 'zoom-factor', 'zoomFactor']; const ints = ['x', 'y', 'width', 'height', 'min-width', 'minWidth', 'max-width', 'maxWidth', 'min-height', 'minHeight', 'max-height', 'maxHeight', 'zoom-factor', 'zoomFactor']
const webPreferences = ['zoom-factor', 'zoomFactor', 'node-integration', 'nodeIntegration', 'preload']; const webPreferences = ['zoom-factor', 'zoomFactor', 'node-integration', 'nodeIntegration', 'preload']
// Make sure to get rid of excessive whitespace in the property name // Make sure to get rid of excessive whitespace in the property name
ref1 = features.split(/,\s*/); ref1 = features.split(/,\s*/)
for (i = 0, len = ref1.length; i < len; i++) { for (i = 0, len = ref1.length; i < len; i++) {
feature = ref1[i]; feature = ref1[i]
ref2 = feature.split(/\s*=/); ref2 = feature.split(/\s*=/)
name = ref2[0]; name = ref2[0]
value = ref2[1]; value = ref2[1]
value = value === 'yes' || value === '1' ? true : value === 'no' || value === '0' ? false : value; value = value === 'yes' || value === '1' ? true : value === 'no' || value === '0' ? false : value
if (webPreferences.includes(name)) { if (webPreferences.includes(name)) {
if (options.webPreferences == null) { if (options.webPreferences == null) {
options.webPreferences = {}; options.webPreferences = {}
} }
options.webPreferences[name] = value; options.webPreferences[name] = value
} else { } else {
options[name] = value; options[name] = value
} }
} }
if (options.left) { if (options.left) {
if (options.x == null) { if (options.x == null) {
options.x = options.left; options.x = options.left
} }
} }
if (options.top) { if (options.top) {
if (options.y == null) { if (options.y == null) {
options.y = options.top; options.y = options.top
} }
} }
if (options.title == null) { if (options.title == null) {
options.title = frameName; options.title = frameName
} }
if (options.width == null) { if (options.width == null) {
options.width = 800; options.width = 800
} }
if (options.height == null) { if (options.height == null) {
options.height = 600; options.height = 600
} }
// Resolve relative urls. // Resolve relative urls.
url = resolveURL(url); url = resolveURL(url)
for (j = 0, len1 = ints.length; j < len1; j++) { for (j = 0, len1 = ints.length; j < len1; j++) {
name = ints[j]; name = ints[j]
if (options[name] != null) { if (options[name] != null) {
options[name] = parseInt(options[name], 10); options[name] = parseInt(options[name], 10)
} }
} }
guestId = ipcRenderer.sendSync('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', url, frameName, options); guestId = ipcRenderer.sendSync('ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', url, frameName, options)
if (guestId) { if (guestId) {
return BrowserWindowProxy.getOrCreate(guestId); return BrowserWindowProxy.getOrCreate(guestId)
} else { } else {
return null; return null
} }
}; }
// Use the dialog API to implement alert(). // Use the dialog API to implement alert().
window.alert = function(message, title) { window.alert = function (message, title) {
var buttons; var buttons
if (arguments.length == 0) { if (arguments.length === 0) {
message = ''; message = ''
} }
if (title == null) { if (title == null) {
title = ''; title = ''
} }
buttons = ['OK']; buttons = ['OK']
message = String(message); message = String(message)
remote.dialog.showMessageBox(remote.getCurrentWindow(), { remote.dialog.showMessageBox(remote.getCurrentWindow(), {
message: message, message: message,
title: title, title: title,
buttons: buttons buttons: buttons
}); })
// Alert should always return undefined. // Alert should always return undefined.
}; }
// And the confirm(). // And the confirm().
window.confirm = function(message, title) { window.confirm = function (message, title) {
var buttons, cancelId; var buttons, cancelId
if (title == null) { if (title == null) {
title = ''; title = ''
} }
buttons = ['OK', 'Cancel']; buttons = ['OK', 'Cancel']
cancelId = 1; cancelId = 1
return !remote.dialog.showMessageBox(remote.getCurrentWindow(), { return !remote.dialog.showMessageBox(remote.getCurrentWindow(), {
message: message, message: message,
title: title, title: title,
buttons: buttons, buttons: buttons,
cancelId: cancelId cancelId: cancelId
}); })
}; }
// But we do not support prompt(). // But we do not support prompt().
window.prompt = function() { window.prompt = function () {
throw new Error('prompt() is and will not be supported.'); throw new Error('prompt() is and will not be supported.')
}; }
if (process.openerId != null) { if (process.openerId != null) {
window.opener = BrowserWindowProxy.getOrCreate(process.openerId); window.opener = BrowserWindowProxy.getOrCreate(process.openerId)
} }
ipcRenderer.on('ATOM_RENDERER_WINDOW_VISIBILITY_CHANGE', function (event, isVisible, isMinimized) { ipcRenderer.on('ATOM_RENDERER_WINDOW_VISIBILITY_CHANGE', function (event, isVisible, isMinimized) {
var hasChanged = _isVisible != isVisible || _isMinimized != isMinimized; var hasChanged = _isVisible !== isVisible || _isMinimized !== isMinimized
if (hasChanged) { if (hasChanged) {
_isVisible = isVisible; _isVisible = isVisible
_isMinimized = isMinimized; _isMinimized = isMinimized
document.dispatchEvent(new Event('visibilitychange')); document.dispatchEvent(new Event('visibilitychange'))
} }
}); })
ipcRenderer.on('ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', function(event, sourceId, message, sourceOrigin) { ipcRenderer.on('ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', function (event, sourceId, message, sourceOrigin) {
// Manually dispatch event instead of using postMessage because we also need to // Manually dispatch event instead of using postMessage because we also need to
// set event.source. // set event.source.
event = document.createEvent('Event'); event = document.createEvent('Event')
event.initEvent('message', false, false); event.initEvent('message', false, false)
event.data = message; event.data = message
event.origin = sourceOrigin; event.origin = sourceOrigin
event.source = BrowserWindowProxy.getOrCreate(sourceId); event.source = BrowserWindowProxy.getOrCreate(sourceId)
return window.dispatchEvent(event); return window.dispatchEvent(event)
}); })
// Forward history operations to browser. // Forward history operations to browser.
var sendHistoryOperation = function(...args) { var sendHistoryOperation = function (...args) {
return ipcRenderer.send.apply(ipcRenderer, ['ATOM_SHELL_NAVIGATION_CONTROLLER'].concat(args)); return ipcRenderer.send.apply(ipcRenderer, ['ATOM_SHELL_NAVIGATION_CONTROLLER'].concat(args))
}; }
var getHistoryOperation = function(...args) { var getHistoryOperation = function (...args) {
return ipcRenderer.sendSync.apply(ipcRenderer, ['ATOM_SHELL_SYNC_NAVIGATION_CONTROLLER'].concat(args)); return ipcRenderer.sendSync.apply(ipcRenderer, ['ATOM_SHELL_SYNC_NAVIGATION_CONTROLLER'].concat(args))
}; }
window.history.back = function() { window.history.back = function () {
return sendHistoryOperation('goBack'); return sendHistoryOperation('goBack')
}; }
window.history.forward = function() { window.history.forward = function () {
return sendHistoryOperation('goForward'); return sendHistoryOperation('goForward')
}; }
window.history.go = function(offset) { window.history.go = function (offset) {
return sendHistoryOperation('goToOffset', offset); return sendHistoryOperation('goToOffset', offset)
}; }
Object.defineProperty(window.history, 'length', { Object.defineProperty(window.history, 'length', {
get: function() { get: function () {
return getHistoryOperation('length'); return getHistoryOperation('length')
} }
}); })
// Make document.hidden and document.visibilityState return the correct value. // Make document.hidden and document.visibilityState return the correct value.
Object.defineProperty(document, 'hidden', { Object.defineProperty(document, 'hidden', {
get: function () { get: function () {
return _isMinimized || !_isVisible; return _isMinimized || !_isVisible
} }
}); })
Object.defineProperty(document, 'visibilityState', { Object.defineProperty(document, 'visibilityState', {
get: function() { get: function () {
if (_isVisible && !_isMinimized) { if (_isVisible && !_isMinimized) {
return "visible"; return 'visible'
} else { } else {
return "hidden"; return 'hidden'
} }
} }
}); })

View file

@ -1,9 +1,9 @@
'use strict'; 'use strict'
const ipcRenderer = require('electron').ipcRenderer; const ipcRenderer = require('electron').ipcRenderer
const webFrame = require('electron').webFrame; const webFrame = require('electron').webFrame
var requestId= 0; var requestId = 0
var WEB_VIEW_EVENTS = { var WEB_VIEW_EVENTS = {
'load-commit': ['url', 'isMainFrame'], 'load-commit': ['url', 'isMainFrame'],
@ -36,71 +36,71 @@ var WEB_VIEW_EVENTS = {
'enter-html-full-screen': [], 'enter-html-full-screen': [],
'leave-html-full-screen': [], 'leave-html-full-screen': [],
'found-in-page': ['result'] 'found-in-page': ['result']
}; }
var DEPRECATED_EVENTS = { var DEPRECATED_EVENTS = {
'page-title-updated': 'page-title-set' 'page-title-updated': 'page-title-set'
}; }
var dispatchEvent = function(webView, eventName, eventKey, ...args) { var dispatchEvent = function (webView, eventName, eventKey, ...args) {
var domEvent, f, i, j, len, ref1; var domEvent, f, i, j, len, ref1
if (DEPRECATED_EVENTS[eventName] != null) { if (DEPRECATED_EVENTS[eventName] != null) {
dispatchEvent.apply(null, [webView, DEPRECATED_EVENTS[eventName], eventKey].concat(args)); dispatchEvent.apply(null, [webView, DEPRECATED_EVENTS[eventName], eventKey].concat(args))
} }
domEvent = new Event(eventName); domEvent = new Event(eventName)
ref1 = WEB_VIEW_EVENTS[eventKey]; ref1 = WEB_VIEW_EVENTS[eventKey]
for (i = j = 0, len = ref1.length; j < len; i = ++j) { for (i = j = 0, len = ref1.length; j < len; i = ++j) {
f = ref1[i]; f = ref1[i]
domEvent[f] = args[i]; domEvent[f] = args[i]
} }
webView.dispatchEvent(domEvent); webView.dispatchEvent(domEvent)
if (eventName === 'load-commit') { if (eventName === 'load-commit') {
return webView.onLoadCommit(domEvent); return webView.onLoadCommit(domEvent)
} }
}; }
module.exports = { module.exports = {
registerEvents: function(webView, viewInstanceId) { registerEvents: function (webView, viewInstanceId) {
ipcRenderer.on("ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-" + viewInstanceId, function(event, eventName, ...args) { ipcRenderer.on('ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-' + viewInstanceId, function (event, eventName, ...args) {
return dispatchEvent.apply(null, [webView, eventName, eventName].concat(args)); return dispatchEvent.apply(null, [webView, eventName, eventName].concat(args))
}); })
ipcRenderer.on("ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-" + viewInstanceId, function(event, channel, ...args) { ipcRenderer.on('ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-' + viewInstanceId, function (event, channel, ...args) {
var domEvent = new Event('ipc-message'); var domEvent = new Event('ipc-message')
domEvent.channel = channel; domEvent.channel = channel
domEvent.args = args; domEvent.args = args
return webView.dispatchEvent(domEvent); return webView.dispatchEvent(domEvent)
}); })
return ipcRenderer.on("ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-" + viewInstanceId, function(event, ...args) { return ipcRenderer.on('ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-' + viewInstanceId, function (event, ...args) {
var domEvent, f, i, j, len, ref1; var domEvent, f, i, j, len, ref1
domEvent = new Event('size-changed'); domEvent = new Event('size-changed')
ref1 = ['oldWidth', 'oldHeight', 'newWidth', 'newHeight']; ref1 = ['oldWidth', 'oldHeight', 'newWidth', 'newHeight']
for (i = j = 0, len = ref1.length; j < len; i = ++j) { for (i = j = 0, len = ref1.length; j < len; i = ++j) {
f = ref1[i]; f = ref1[i]
domEvent[f] = args[i]; domEvent[f] = args[i]
} }
return webView.onSizeChanged(domEvent); return webView.onSizeChanged(domEvent)
}); })
}, },
deregisterEvents: function(viewInstanceId) { deregisterEvents: function (viewInstanceId) {
ipcRenderer.removeAllListeners("ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-" + viewInstanceId); ipcRenderer.removeAllListeners('ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-' + viewInstanceId)
ipcRenderer.removeAllListeners("ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-" + viewInstanceId); ipcRenderer.removeAllListeners('ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-' + viewInstanceId)
return ipcRenderer.removeAllListeners("ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-" + viewInstanceId); return ipcRenderer.removeAllListeners('ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-' + viewInstanceId)
}, },
createGuest: function(params, callback) { createGuest: function (params, callback) {
requestId++; requestId++
ipcRenderer.send('ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', params, requestId); ipcRenderer.send('ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', params, requestId)
return ipcRenderer.once("ATOM_SHELL_RESPONSE_" + requestId, callback); return ipcRenderer.once('ATOM_SHELL_RESPONSE_' + requestId, callback)
}, },
attachGuest: function(elementInstanceId, guestInstanceId, params) { attachGuest: function (elementInstanceId, guestInstanceId, params) {
ipcRenderer.send('ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', elementInstanceId, guestInstanceId, params); ipcRenderer.send('ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', elementInstanceId, guestInstanceId, params)
return webFrame.attachGuest(elementInstanceId); return webFrame.attachGuest(elementInstanceId)
}, },
destroyGuest: function(guestInstanceId) { destroyGuest: function (guestInstanceId) {
return ipcRenderer.send('ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', guestInstanceId); return ipcRenderer.send('ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', guestInstanceId)
}, },
setSize: function(guestInstanceId, params) { setSize: function (guestInstanceId, params) {
return ipcRenderer.send('ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', guestInstanceId, params); return ipcRenderer.send('ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', guestInstanceId, params)
}, }
}; }

View file

@ -1,95 +1,87 @@
'use strict'; 'use strict'
const WebViewImpl = require('./web-view'); const WebViewImpl = require('./web-view')
const guestViewInternal = require('./guest-view-internal'); const guestViewInternal = require('./guest-view-internal')
const webViewConstants = require('./web-view-constants'); const webViewConstants = require('./web-view-constants')
const remote = require('electron').remote; const remote = require('electron').remote
// Helper function to resolve url set in attribute. // Helper function to resolve url set in attribute.
var a = document.createElement('a'); var a = document.createElement('a')
var resolveURL = function(url) { var resolveURL = function (url) {
a.href = url; a.href = url
return a.href; return a.href
}; }
// Attribute objects. // Attribute objects.
// Default implementation of a WebView attribute. // Default implementation of a WebView attribute.
class WebViewAttribute { class WebViewAttribute {
constructor(name, webViewImpl) { constructor (name, webViewImpl) {
this.name = name; this.name = name
this.value = webViewImpl.webviewNode[name] || ''; this.value = webViewImpl.webviewNode[name] || ''
this.webViewImpl = webViewImpl; this.webViewImpl = webViewImpl
this.ignoreMutation = false; this.ignoreMutation = false
this.defineProperty(); this.defineProperty()
} }
// Retrieves and returns the attribute's value. // Retrieves and returns the attribute's value.
getValue() { getValue () {
return this.webViewImpl.webviewNode.getAttribute(this.name) || this.value; return this.webViewImpl.webviewNode.getAttribute(this.name) || this.value
} }
// Sets the attribute's value. // Sets the attribute's value.
setValue(value) { setValue (value) {
return this.webViewImpl.webviewNode.setAttribute(this.name, value || ''); return this.webViewImpl.webviewNode.setAttribute(this.name, value || '')
} }
// Changes the attribute's value without triggering its mutation handler. // Changes the attribute's value without triggering its mutation handler.
setValueIgnoreMutation(value) { setValueIgnoreMutation (value) {
this.ignoreMutation = true; this.ignoreMutation = true
this.setValue(value); this.setValue(value)
return this.ignoreMutation = false; this.ignoreMutation = false
} }
// Defines this attribute as a property on the webview node. // Defines this attribute as a property on the webview node.
defineProperty() { defineProperty () {
return Object.defineProperty(this.webViewImpl.webviewNode, this.name, { return Object.defineProperty(this.webViewImpl.webviewNode, this.name, {
get: () => { get: () => {
return this.getValue(); return this.getValue()
}, },
set: (value) => { set: (value) => {
return this.setValue(value); return this.setValue(value)
}, },
enumerable: true enumerable: true
}); })
} }
// Called when the attribute's value changes. // Called when the attribute's value changes.
handleMutation() {} handleMutation () {}
} }
// An attribute that is treated as a Boolean. // An attribute that is treated as a Boolean.
class BooleanAttribute extends WebViewAttribute { class BooleanAttribute extends WebViewAttribute {
constructor(name, webViewImpl) { getValue () {
super(name, webViewImpl); return this.webViewImpl.webviewNode.hasAttribute(this.name)
} }
getValue() { setValue (value) {
return this.webViewImpl.webviewNode.hasAttribute(this.name);
}
setValue(value) {
if (!value) { if (!value) {
return this.webViewImpl.webviewNode.removeAttribute(this.name); return this.webViewImpl.webviewNode.removeAttribute(this.name)
} else { } else {
return this.webViewImpl.webviewNode.setAttribute(this.name, ''); return this.webViewImpl.webviewNode.setAttribute(this.name, '')
} }
} }
} }
// Attribute used to define the demension limits of autosizing. // Attribute used to define the demension limits of autosizing.
class AutosizeDimensionAttribute extends WebViewAttribute { class AutosizeDimensionAttribute extends WebViewAttribute {
constructor(name, webViewImpl) { getValue () {
super(name, webViewImpl); return parseInt(this.webViewImpl.webviewNode.getAttribute(this.name)) || 0
} }
getValue() { handleMutation () {
return parseInt(this.webViewImpl.webviewNode.getAttribute(this.name)) || 0;
}
handleMutation() {
if (!this.webViewImpl.guestInstanceId) { if (!this.webViewImpl.guestInstanceId) {
return; return
} }
return guestViewInternal.setSize(this.webViewImpl.guestInstanceId, { return guestViewInternal.setSize(this.webViewImpl.guestInstanceId, {
enableAutoSize: this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue(), enableAutoSize: this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue(),
@ -101,197 +93,194 @@ class AutosizeDimensionAttribute extends WebViewAttribute {
width: parseInt(this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_MAXWIDTH].getValue() || 0), width: parseInt(this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_MAXWIDTH].getValue() || 0),
height: parseInt(this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() || 0) height: parseInt(this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() || 0)
} }
}); })
} }
} }
// Attribute that specifies whether the webview should be autosized. // Attribute that specifies whether the webview should be autosized.
class AutosizeAttribute extends BooleanAttribute { class AutosizeAttribute extends BooleanAttribute {
constructor(webViewImpl) { constructor (webViewImpl) {
super(webViewConstants.ATTRIBUTE_AUTOSIZE, webViewImpl); super(webViewConstants.ATTRIBUTE_AUTOSIZE, webViewImpl)
} }
} }
AutosizeAttribute.prototype.handleMutation = AutosizeDimensionAttribute.prototype.handleMutation; AutosizeAttribute.prototype.handleMutation = AutosizeDimensionAttribute.prototype.handleMutation
// Attribute representing the state of the storage partition. // Attribute representing the state of the storage partition.
class PartitionAttribute extends WebViewAttribute { class PartitionAttribute extends WebViewAttribute {
constructor(webViewImpl) { constructor (webViewImpl) {
super(webViewConstants.ATTRIBUTE_PARTITION, webViewImpl); super(webViewConstants.ATTRIBUTE_PARTITION, webViewImpl)
this.validPartitionId = true; this.validPartitionId = true
} }
handleMutation(oldValue, newValue) { handleMutation (oldValue, newValue) {
newValue = newValue || ''; newValue = newValue || ''
// The partition cannot change if the webview has already navigated. // The partition cannot change if the webview has already navigated.
if (!this.webViewImpl.beforeFirstNavigation) { if (!this.webViewImpl.beforeFirstNavigation) {
window.console.error(webViewConstants.ERROR_MSG_ALREADY_NAVIGATED); window.console.error(webViewConstants.ERROR_MSG_ALREADY_NAVIGATED)
this.setValueIgnoreMutation(oldValue); this.setValueIgnoreMutation(oldValue)
return; return
} }
if (newValue === 'persist:') { if (newValue === 'persist:') {
this.validPartitionId = false; this.validPartitionId = false
return window.console.error(webViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE); return window.console.error(webViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE)
} }
} }
} }
// Attribute that handles the location and navigation of the webview. // Attribute that handles the location and navigation of the webview.
class SrcAttribute extends WebViewAttribute { class SrcAttribute extends WebViewAttribute {
constructor(webViewImpl) { constructor (webViewImpl) {
super(webViewConstants.ATTRIBUTE_SRC, webViewImpl); super(webViewConstants.ATTRIBUTE_SRC, webViewImpl)
this.setupMutationObserver(); this.setupMutationObserver()
} }
getValue() { getValue () {
if (this.webViewImpl.webviewNode.hasAttribute(this.name)) { if (this.webViewImpl.webviewNode.hasAttribute(this.name)) {
return resolveURL(this.webViewImpl.webviewNode.getAttribute(this.name)); return resolveURL(this.webViewImpl.webviewNode.getAttribute(this.name))
} else { } else {
return this.value; return this.value
} }
} }
setValueIgnoreMutation(value) { setValueIgnoreMutation (value) {
super.setValueIgnoreMutation(value); super.setValueIgnoreMutation(value)
// takeRecords() is needed to clear queued up src mutations. Without it, it // takeRecords() is needed to clear queued up src mutations. Without it, it
// is possible for this change to get picked up asyncronously by src's // is possible for this change to get picked up asyncronously by src's
// mutation observer |observer|, and then get handled even though we do not // mutation observer |observer|, and then get handled even though we do not
// want to handle this mutation. // want to handle this mutation.
return this.observer.takeRecords(); return this.observer.takeRecords()
} }
handleMutation(oldValue, newValue) { handleMutation (oldValue, newValue) {
// Once we have navigated, we don't allow clearing the src attribute. // Once we have navigated, we don't allow clearing the src attribute.
// Once <webview> enters a navigated state, it cannot return to a // Once <webview> enters a navigated state, it cannot return to a
// placeholder state. // placeholder state.
if (!newValue && oldValue) { if (!newValue && oldValue) {
// src attribute changes normally initiate a navigation. We suppress // src attribute changes normally initiate a navigation. We suppress
// the next src attribute handler call to avoid reloading the page // the next src attribute handler call to avoid reloading the page
// on every guest-initiated navigation. // on every guest-initiated navigation.
this.setValueIgnoreMutation(oldValue); this.setValueIgnoreMutation(oldValue)
return; return
} }
return this.parse(); return this.parse()
} }
// The purpose of this mutation observer is to catch assignment to the src // The purpose of this mutation observer is to catch assignment to the src
// attribute without any changes to its value. This is useful in the case // attribute without any changes to its value. This is useful in the case
// where the webview guest has crashed and navigating to the same address // where the webview guest has crashed and navigating to the same address
// spawns off a new process. // spawns off a new process.
setupMutationObserver() { setupMutationObserver () {
var params; var params
this.observer = new MutationObserver((mutations) => { this.observer = new MutationObserver((mutations) => {
var i, len, mutation, newValue, oldValue; var i, len, mutation, newValue, oldValue
for (i = 0, len = mutations.length; i < len; i++) { for (i = 0, len = mutations.length; i < len; i++) {
mutation = mutations[i]; mutation = mutations[i]
oldValue = mutation.oldValue; oldValue = mutation.oldValue
newValue = this.getValue(); newValue = this.getValue()
if (oldValue !== newValue) { if (oldValue !== newValue) {
return; return
} }
this.handleMutation(oldValue, newValue); this.handleMutation(oldValue, newValue)
} }
}); })
params = { params = {
attributes: true, attributes: true,
attributeOldValue: true, attributeOldValue: true,
attributeFilter: [this.name] attributeFilter: [this.name]
}; }
return this.observer.observe(this.webViewImpl.webviewNode, params); return this.observer.observe(this.webViewImpl.webviewNode, params)
} }
parse() { parse () {
var guestContents, httpreferrer, opts, useragent; var guestContents, httpreferrer, opts, useragent
if (!this.webViewImpl.elementAttached || !this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId || !this.getValue()) { if (!this.webViewImpl.elementAttached || !this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId || !this.getValue()) {
return; return
} }
if (this.webViewImpl.guestInstanceId == null) { if (this.webViewImpl.guestInstanceId == null) {
if (this.webViewImpl.beforeFirstNavigation) { if (this.webViewImpl.beforeFirstNavigation) {
this.webViewImpl.beforeFirstNavigation = false; this.webViewImpl.beforeFirstNavigation = false
this.webViewImpl.createGuest(); this.webViewImpl.createGuest()
} }
return; return
} }
// Navigate to |this.src|. // Navigate to |this.src|.
opts = {}; opts = {}
httpreferrer = this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].getValue(); httpreferrer = this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].getValue()
if (httpreferrer) { if (httpreferrer) {
opts.httpReferrer = httpreferrer; opts.httpReferrer = httpreferrer
} }
useragent = this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_USERAGENT].getValue(); useragent = this.webViewImpl.attributes[webViewConstants.ATTRIBUTE_USERAGENT].getValue()
if (useragent) { if (useragent) {
opts.userAgent = useragent; opts.userAgent = useragent
} }
guestContents = remote.getGuestWebContents(this.webViewImpl.guestInstanceId); guestContents = remote.getGuestWebContents(this.webViewImpl.guestInstanceId)
return guestContents.loadURL(this.getValue(), opts); return guestContents.loadURL(this.getValue(), opts)
} }
} }
// Attribute specifies HTTP referrer. // Attribute specifies HTTP referrer.
class HttpReferrerAttribute extends WebViewAttribute { class HttpReferrerAttribute extends WebViewAttribute {
constructor(webViewImpl) { constructor (webViewImpl) {
super(webViewConstants.ATTRIBUTE_HTTPREFERRER, webViewImpl); super(webViewConstants.ATTRIBUTE_HTTPREFERRER, webViewImpl)
} }
} }
// Attribute specifies user agent // Attribute specifies user agent
class UserAgentAttribute extends WebViewAttribute { class UserAgentAttribute extends WebViewAttribute {
constructor(webViewImpl) { constructor (webViewImpl) {
super(webViewConstants.ATTRIBUTE_USERAGENT, webViewImpl); super(webViewConstants.ATTRIBUTE_USERAGENT, webViewImpl)
} }
} }
// Attribute that set preload script. // Attribute that set preload script.
class PreloadAttribute extends WebViewAttribute { class PreloadAttribute extends WebViewAttribute {
constructor(webViewImpl) { constructor (webViewImpl) {
super(webViewConstants.ATTRIBUTE_PRELOAD, webViewImpl); super(webViewConstants.ATTRIBUTE_PRELOAD, webViewImpl)
} }
getValue() { getValue () {
var preload, protocol; var preload, protocol
if (!this.webViewImpl.webviewNode.hasAttribute(this.name)) { if (!this.webViewImpl.webviewNode.hasAttribute(this.name)) {
return this.value; return this.value
} }
preload = resolveURL(this.webViewImpl.webviewNode.getAttribute(this.name)); preload = resolveURL(this.webViewImpl.webviewNode.getAttribute(this.name))
protocol = preload.substr(0, 5); protocol = preload.substr(0, 5)
if (protocol !== 'file:') { if (protocol !== 'file:') {
console.error(webViewConstants.ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE); console.error(webViewConstants.ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE)
preload = ''; preload = ''
} }
return preload; return preload
} }
} }
// Attribute that specifies the blink features to be enabled. // Attribute that specifies the blink features to be enabled.
class BlinkFeaturesAttribute extends WebViewAttribute { class BlinkFeaturesAttribute extends WebViewAttribute {
constructor(webViewImpl) { constructor (webViewImpl) {
super(webViewConstants.ATTRIBUTE_BLINKFEATURES, webViewImpl); super(webViewConstants.ATTRIBUTE_BLINKFEATURES, webViewImpl)
} }
} }
// Sets up all of the webview attributes. // Sets up all of the webview attributes.
WebViewImpl.prototype.setupWebViewAttributes = function() { WebViewImpl.prototype.setupWebViewAttributes = function () {
this.attributes = {}; this.attributes = {}
this.attributes[webViewConstants.ATTRIBUTE_AUTOSIZE] = new AutosizeAttribute(this); this.attributes[webViewConstants.ATTRIBUTE_AUTOSIZE] = new AutosizeAttribute(this)
this.attributes[webViewConstants.ATTRIBUTE_PARTITION] = new PartitionAttribute(this); this.attributes[webViewConstants.ATTRIBUTE_PARTITION] = new PartitionAttribute(this)
this.attributes[webViewConstants.ATTRIBUTE_SRC] = new SrcAttribute(this); this.attributes[webViewConstants.ATTRIBUTE_SRC] = new SrcAttribute(this)
this.attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER] = new HttpReferrerAttribute(this); this.attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER] = new HttpReferrerAttribute(this)
this.attributes[webViewConstants.ATTRIBUTE_USERAGENT] = new UserAgentAttribute(this); this.attributes[webViewConstants.ATTRIBUTE_USERAGENT] = new UserAgentAttribute(this)
this.attributes[webViewConstants.ATTRIBUTE_NODEINTEGRATION] = new BooleanAttribute(webViewConstants.ATTRIBUTE_NODEINTEGRATION, this); this.attributes[webViewConstants.ATTRIBUTE_NODEINTEGRATION] = new BooleanAttribute(webViewConstants.ATTRIBUTE_NODEINTEGRATION, this)
this.attributes[webViewConstants.ATTRIBUTE_PLUGINS] = new BooleanAttribute(webViewConstants.ATTRIBUTE_PLUGINS, this); this.attributes[webViewConstants.ATTRIBUTE_PLUGINS] = new BooleanAttribute(webViewConstants.ATTRIBUTE_PLUGINS, this)
this.attributes[webViewConstants.ATTRIBUTE_DISABLEWEBSECURITY] = new BooleanAttribute(webViewConstants.ATTRIBUTE_DISABLEWEBSECURITY, this); this.attributes[webViewConstants.ATTRIBUTE_DISABLEWEBSECURITY] = new BooleanAttribute(webViewConstants.ATTRIBUTE_DISABLEWEBSECURITY, this)
this.attributes[webViewConstants.ATTRIBUTE_ALLOWPOPUPS] = new BooleanAttribute(webViewConstants.ATTRIBUTE_ALLOWPOPUPS, this); this.attributes[webViewConstants.ATTRIBUTE_ALLOWPOPUPS] = new BooleanAttribute(webViewConstants.ATTRIBUTE_ALLOWPOPUPS, this)
this.attributes[webViewConstants.ATTRIBUTE_PRELOAD] = new PreloadAttribute(this); this.attributes[webViewConstants.ATTRIBUTE_PRELOAD] = new PreloadAttribute(this)
this.attributes[webViewConstants.ATTRIBUTE_BLINKFEATURES] = new BlinkFeaturesAttribute(this); this.attributes[webViewConstants.ATTRIBUTE_BLINKFEATURES] = new BlinkFeaturesAttribute(this)
const autosizeAttributes = [webViewConstants.ATTRIBUTE_MAXHEIGHT, webViewConstants.ATTRIBUTE_MAXWIDTH, webViewConstants.ATTRIBUTE_MINHEIGHT, webViewConstants.ATTRIBUTE_MINWIDTH]; const autosizeAttributes = [webViewConstants.ATTRIBUTE_MAXHEIGHT, webViewConstants.ATTRIBUTE_MAXWIDTH, webViewConstants.ATTRIBUTE_MINHEIGHT, webViewConstants.ATTRIBUTE_MINWIDTH]
autosizeAttributes.forEach((attribute) => { autosizeAttributes.forEach((attribute) => {
this.attributes[attribute] = new AutosizeDimensionAttribute(attribute, this); this.attributes[attribute] = new AutosizeDimensionAttribute(attribute, this)
}); })
}; }

View file

@ -25,4 +25,4 @@ module.exports = {
ERROR_MSG_CANNOT_INJECT_SCRIPT: '<webview>: ' + 'Script cannot be injected into content until the page has loaded.', ERROR_MSG_CANNOT_INJECT_SCRIPT: '<webview>: ' + 'Script cannot be injected into content until the page has loaded.',
ERROR_MSG_INVALID_PARTITION_ATTRIBUTE: 'Invalid partition attribute.', ERROR_MSG_INVALID_PARTITION_ATTRIBUTE: 'Invalid partition attribute.',
ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE: 'Only "file:" protocol is supported in "preload" attribute.' ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE: 'Only "file:" protocol is supported in "preload" attribute.'
}; }

View file

@ -1,63 +1,63 @@
'use strict'; 'use strict'
const deprecate = require('electron').deprecate; const deprecate = require('electron').deprecate
const webFrame = require('electron').webFrame; const webFrame = require('electron').webFrame
const remote = require('electron').remote; const remote = require('electron').remote
const ipcRenderer = require('electron').ipcRenderer; const ipcRenderer = require('electron').ipcRenderer
const v8Util = process.atomBinding('v8_util'); const v8Util = process.atomBinding('v8_util')
const guestViewInternal = require('./guest-view-internal'); const guestViewInternal = require('./guest-view-internal')
const webViewConstants = require('./web-view-constants'); const webViewConstants = require('./web-view-constants')
var hasProp = {}.hasOwnProperty; var hasProp = {}.hasOwnProperty
// ID generator. // ID generator.
var nextId = 0; var nextId = 0
var getNextId = function() { var getNextId = function () {
return ++nextId; return ++nextId
}; }
// Represents the internal state of the WebView node. // Represents the internal state of the WebView node.
var WebViewImpl = (function() { var WebViewImpl = (function () {
function WebViewImpl(webviewNode) { function WebViewImpl (webviewNode) {
var shadowRoot; var shadowRoot
this.webviewNode = webviewNode; this.webviewNode = webviewNode
v8Util.setHiddenValue(this.webviewNode, 'internal', this); v8Util.setHiddenValue(this.webviewNode, 'internal', this)
this.attached = false; this.attached = false
this.elementAttached = false; this.elementAttached = false
this.beforeFirstNavigation = true; this.beforeFirstNavigation = true
// on* Event handlers. // on* Event handlers.
this.on = {}; this.on = {}
this.browserPluginNode = this.createBrowserPluginNode(); this.browserPluginNode = this.createBrowserPluginNode()
shadowRoot = this.webviewNode.createShadowRoot(); shadowRoot = this.webviewNode.createShadowRoot()
shadowRoot.innerHTML = '<style>:host { display: flex; }</style>'; shadowRoot.innerHTML = '<style>:host { display: flex; }</style>'
this.setupWebViewAttributes(); this.setupWebViewAttributes()
this.setupFocusPropagation(); this.setupFocusPropagation()
this.viewInstanceId = getNextId(); this.viewInstanceId = getNextId()
shadowRoot.appendChild(this.browserPluginNode); shadowRoot.appendChild(this.browserPluginNode)
// Subscribe to host's zoom level changes. // Subscribe to host's zoom level changes.
this.onZoomLevelChanged = (zoomLevel) => { this.onZoomLevelChanged = (zoomLevel) => {
this.webviewNode.setZoomLevel(zoomLevel); this.webviewNode.setZoomLevel(zoomLevel)
}; }
webFrame.on('zoom-level-changed', this.onZoomLevelChanged); webFrame.on('zoom-level-changed', this.onZoomLevelChanged)
} }
WebViewImpl.prototype.createBrowserPluginNode = function() { WebViewImpl.prototype.createBrowserPluginNode = function () {
// We create BrowserPlugin as a custom element in order to observe changes // We create BrowserPlugin as a custom element in order to observe changes
// to attributes synchronously. // to attributes synchronously.
var browserPluginNode; var browserPluginNode
browserPluginNode = new WebViewImpl.BrowserPlugin(); browserPluginNode = new WebViewImpl.BrowserPlugin()
v8Util.setHiddenValue(browserPluginNode, 'internal', this); v8Util.setHiddenValue(browserPluginNode, 'internal', this)
return browserPluginNode; return browserPluginNode
}; }
// Resets some state upon reattaching <webview> element to the DOM. // Resets some state upon reattaching <webview> element to the DOM.
WebViewImpl.prototype.reset = function() { WebViewImpl.prototype.reset = function () {
// Unlisten the zoom-level-changed event. // Unlisten the zoom-level-changed event.
webFrame.removeListener('zoom-level-changed', this.onZoomLevelChanged); webFrame.removeListener('zoom-level-changed', this.onZoomLevelChanged)
// If guestInstanceId is defined then the <webview> has navigated and has // If guestInstanceId is defined then the <webview> has navigated and has
// already picked up a partition ID. Thus, we need to reset the initialization // already picked up a partition ID. Thus, we need to reset the initialization
@ -66,174 +66,172 @@ var WebViewImpl = (function() {
// heard back from createGuest yet. We will not reset the flag in this case so // heard back from createGuest yet. We will not reset the flag in this case so
// that we don't end up allocating a second guest. // that we don't end up allocating a second guest.
if (this.guestInstanceId) { if (this.guestInstanceId) {
guestViewInternal.destroyGuest(this.guestInstanceId); guestViewInternal.destroyGuest(this.guestInstanceId)
this.webContents = null; this.webContents = null
this.guestInstanceId = void 0; this.guestInstanceId = void 0
this.beforeFirstNavigation = true; this.beforeFirstNavigation = true
this.attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId = true; this.attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId = true
} }
return this.internalInstanceId = 0; this.internalInstanceId = 0
}; }
// Sets the <webview>.request property. // Sets the <webview>.request property.
WebViewImpl.prototype.setRequestPropertyOnWebViewNode = function(request) { WebViewImpl.prototype.setRequestPropertyOnWebViewNode = function (request) {
return Object.defineProperty(this.webviewNode, 'request', { return Object.defineProperty(this.webviewNode, 'request', {
value: request, value: request,
enumerable: true enumerable: true
}); })
}; }
WebViewImpl.prototype.setupFocusPropagation = function() { WebViewImpl.prototype.setupFocusPropagation = function () {
if (!this.webviewNode.hasAttribute('tabIndex')) { if (!this.webviewNode.hasAttribute('tabIndex')) {
// <webview> needs a tabIndex in order to be focusable. // <webview> needs a tabIndex in order to be focusable.
// TODO(fsamuel): It would be nice to avoid exposing a tabIndex attribute // TODO(fsamuel): It would be nice to avoid exposing a tabIndex attribute
// to allow <webview> to be focusable. // to allow <webview> to be focusable.
// See http://crbug.com/231664. // See http://crbug.com/231664.
this.webviewNode.setAttribute('tabIndex', -1); this.webviewNode.setAttribute('tabIndex', -1)
} }
// Focus the BrowserPlugin when the <webview> takes focus. // Focus the BrowserPlugin when the <webview> takes focus.
this.webviewNode.addEventListener('focus', () => { this.webviewNode.addEventListener('focus', () => {
this.browserPluginNode.focus(); this.browserPluginNode.focus()
}); })
// Blur the BrowserPlugin when the <webview> loses focus. // Blur the BrowserPlugin when the <webview> loses focus.
this.webviewNode.addEventListener('blur', () => { this.webviewNode.addEventListener('blur', () => {
this.browserPluginNode.blur(); this.browserPluginNode.blur()
}); })
}; }
// This observer monitors mutations to attributes of the <webview> and // This observer monitors mutations to attributes of the <webview> and
// updates the BrowserPlugin properties accordingly. In turn, updating // updates the BrowserPlugin properties accordingly. In turn, updating
// a BrowserPlugin property will update the corresponding BrowserPlugin // a BrowserPlugin property will update the corresponding BrowserPlugin
// attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more // attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more
// details. // details.
WebViewImpl.prototype.handleWebviewAttributeMutation = function(attributeName, oldValue, newValue) { WebViewImpl.prototype.handleWebviewAttributeMutation = function (attributeName, oldValue, newValue) {
if (!this.attributes[attributeName] || this.attributes[attributeName].ignoreMutation) { if (!this.attributes[attributeName] || this.attributes[attributeName].ignoreMutation) {
return; return
} }
// Let the changed attribute handle its own mutation; // Let the changed attribute handle its own mutation
return this.attributes[attributeName].handleMutation(oldValue, newValue); return this.attributes[attributeName].handleMutation(oldValue, newValue)
}; }
WebViewImpl.prototype.handleBrowserPluginAttributeMutation = function(attributeName, oldValue, newValue) { WebViewImpl.prototype.handleBrowserPluginAttributeMutation = function (attributeName, oldValue, newValue) {
if (attributeName === webViewConstants.ATTRIBUTE_INTERNALINSTANCEID && !oldValue && !!newValue) { if (attributeName === webViewConstants.ATTRIBUTE_INTERNALINSTANCEID && !oldValue && !!newValue) {
this.browserPluginNode.removeAttribute(webViewConstants.ATTRIBUTE_INTERNALINSTANCEID); this.browserPluginNode.removeAttribute(webViewConstants.ATTRIBUTE_INTERNALINSTANCEID)
this.internalInstanceId = parseInt(newValue); this.internalInstanceId = parseInt(newValue)
// Track when the element resizes using the element resize callback. // Track when the element resizes using the element resize callback.
webFrame.registerElementResizeCallback(this.internalInstanceId, this.onElementResize.bind(this)); webFrame.registerElementResizeCallback(this.internalInstanceId, this.onElementResize.bind(this))
if (!this.guestInstanceId) { if (!this.guestInstanceId) {
return; return
} }
return guestViewInternal.attachGuest(this.internalInstanceId, this.guestInstanceId, this.buildParams()); return guestViewInternal.attachGuest(this.internalInstanceId, this.guestInstanceId, this.buildParams())
} }
}; }
WebViewImpl.prototype.onSizeChanged = function(webViewEvent) { WebViewImpl.prototype.onSizeChanged = function (webViewEvent) {
var maxHeight, maxWidth, minHeight, minWidth, newHeight, newWidth, node, width; var maxHeight, maxWidth, minHeight, minWidth, newHeight, newWidth, node, width
newWidth = webViewEvent.newWidth; newWidth = webViewEvent.newWidth
newHeight = webViewEvent.newHeight; newHeight = webViewEvent.newHeight
node = this.webviewNode; node = this.webviewNode
width = node.offsetWidth; width = node.offsetWidth
// Check the current bounds to make sure we do not resize <webview> // Check the current bounds to make sure we do not resize <webview>
// outside of current constraints. // outside of current constraints.
maxWidth = this.attributes[webViewConstants.ATTRIBUTE_MAXWIDTH].getValue() | width; maxWidth = this.attributes[webViewConstants.ATTRIBUTE_MAXWIDTH].getValue() | width
maxHeight = this.attributes[webViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() | width; maxHeight = this.attributes[webViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() | width
minWidth = this.attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() | width; minWidth = this.attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() | width
minHeight = this.attributes[webViewConstants.ATTRIBUTE_MINHEIGHT].getValue() | width; minHeight = this.attributes[webViewConstants.ATTRIBUTE_MINHEIGHT].getValue() | width
minWidth = Math.min(minWidth, maxWidth); minWidth = Math.min(minWidth, maxWidth)
minHeight = Math.min(minHeight, maxHeight); minHeight = Math.min(minHeight, maxHeight)
if (!this.attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue() || (newWidth >= minWidth && newWidth <= maxWidth && newHeight >= minHeight && newHeight <= maxHeight)) { if (!this.attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue() || (newWidth >= minWidth && newWidth <= maxWidth && newHeight >= minHeight && newHeight <= maxHeight)) {
node.style.width = newWidth + 'px'; node.style.width = newWidth + 'px'
node.style.height = newHeight + 'px'; node.style.height = newHeight + 'px'
// Only fire the DOM event if the size of the <webview> has actually // Only fire the DOM event if the size of the <webview> has actually
// changed. // changed.
return this.dispatchEvent(webViewEvent); return this.dispatchEvent(webViewEvent)
} }
}; }
WebViewImpl.prototype.onElementResize = function(newSize) { WebViewImpl.prototype.onElementResize = function (newSize) {
// Dispatch the 'resize' event. // Dispatch the 'resize' event.
var resizeEvent; var resizeEvent
resizeEvent = new Event('resize', { resizeEvent = new Event('resize', {
bubbles: true bubbles: true
}); })
resizeEvent.newWidth = newSize.width; resizeEvent.newWidth = newSize.width
resizeEvent.newHeight = newSize.height; resizeEvent.newHeight = newSize.height
this.dispatchEvent(resizeEvent); this.dispatchEvent(resizeEvent)
if (this.guestInstanceId) { if (this.guestInstanceId) {
return guestViewInternal.setSize(this.guestInstanceId, { return guestViewInternal.setSize(this.guestInstanceId, {
normal: newSize normal: newSize
}); })
} }
}; }
WebViewImpl.prototype.createGuest = function() { WebViewImpl.prototype.createGuest = function () {
return guestViewInternal.createGuest(this.buildParams(), (event, guestInstanceId) => { return guestViewInternal.createGuest(this.buildParams(), (event, guestInstanceId) => {
this.attachWindow(guestInstanceId); this.attachWindow(guestInstanceId)
}); })
}; }
WebViewImpl.prototype.dispatchEvent = function(webViewEvent) { WebViewImpl.prototype.dispatchEvent = function (webViewEvent) {
return this.webviewNode.dispatchEvent(webViewEvent); return this.webviewNode.dispatchEvent(webViewEvent)
}; }
// Adds an 'on<event>' property on the webview, which can be used to set/unset // Adds an 'on<event>' property on the webview, which can be used to set/unset
// an event handler. // an event handler.
WebViewImpl.prototype.setupEventProperty = function(eventName) { WebViewImpl.prototype.setupEventProperty = function (eventName) {
var propertyName; var propertyName
propertyName = 'on' + eventName.toLowerCase(); propertyName = 'on' + eventName.toLowerCase()
return Object.defineProperty(this.webviewNode, propertyName, { return Object.defineProperty(this.webviewNode, propertyName, {
get: () => { get: () => {
return this.on[propertyName]; return this.on[propertyName]
}, },
set: (value) => { set: (value) => {
if (this.on[propertyName]) { if (this.on[propertyName]) {
this.webviewNode.removeEventListener(eventName, this.on[propertyName]); this.webviewNode.removeEventListener(eventName, this.on[propertyName])
} }
this.on[propertyName] = value; this.on[propertyName] = value
if (value) { if (value) {
return this.webviewNode.addEventListener(eventName, value); return this.webviewNode.addEventListener(eventName, value)
} }
}, },
enumerable: true enumerable: true
}); })
}; }
// Updates state upon loadcommit. // Updates state upon loadcommit.
WebViewImpl.prototype.onLoadCommit = function(webViewEvent) { WebViewImpl.prototype.onLoadCommit = function (webViewEvent) {
var newValue, oldValue; var newValue, oldValue
oldValue = this.webviewNode.getAttribute(webViewConstants.ATTRIBUTE_SRC); oldValue = this.webviewNode.getAttribute(webViewConstants.ATTRIBUTE_SRC)
newValue = webViewEvent.url; newValue = webViewEvent.url
if (webViewEvent.isMainFrame && (oldValue !== newValue)) { if (webViewEvent.isMainFrame && (oldValue !== newValue)) {
// Touching the src attribute triggers a navigation. To avoid // Touching the src attribute triggers a navigation. To avoid
// triggering a page reload on every guest-initiated navigation, // triggering a page reload on every guest-initiated navigation,
// we do not handle this mutation. // we do not handle this mutation.
return this.attributes[webViewConstants.ATTRIBUTE_SRC].setValueIgnoreMutation(newValue); return this.attributes[webViewConstants.ATTRIBUTE_SRC].setValueIgnoreMutation(newValue)
} }
}; }
WebViewImpl.prototype.onAttach = function(storagePartitionId) { WebViewImpl.prototype.onAttach = function (storagePartitionId) {
return this.attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue(storagePartitionId); return this.attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue(storagePartitionId)
}; }
WebViewImpl.prototype.buildParams = function() { WebViewImpl.prototype.buildParams = function () {
var attribute, attributeName, css, elementRect, params, ref1; var attribute, attributeName, css, elementRect, params, ref1
params = { params = {
instanceId: this.viewInstanceId, instanceId: this.viewInstanceId,
userAgentOverride: this.userAgentOverride userAgentOverride: this.userAgentOverride
}; }
ref1 = this.attributes; ref1 = this.attributes
for (attributeName in ref1) { for (attributeName in ref1) {
if (!hasProp.call(ref1, attributeName)) continue; if (!hasProp.call(ref1, attributeName)) continue
attribute = ref1[attributeName]; attribute = ref1[attributeName]
params[attributeName] = attribute.getValue(); params[attributeName] = attribute.getValue()
} }
// When the WebView is not participating in layout (display:none) // When the WebView is not participating in layout (display:none)
@ -241,96 +239,95 @@ var WebViewImpl = (function() {
// However, in the case where the WebView has a fixed size we can // However, in the case where the WebView has a fixed size we can
// use that value to initially size the guest so as to avoid a relayout of // use that value to initially size the guest so as to avoid a relayout of
// the on display:block. // the on display:block.
css = window.getComputedStyle(this.webviewNode, null); css = window.getComputedStyle(this.webviewNode, null)
elementRect = this.webviewNode.getBoundingClientRect(); elementRect = this.webviewNode.getBoundingClientRect()
params.elementWidth = parseInt(elementRect.width) || parseInt(css.getPropertyValue('width')); params.elementWidth = parseInt(elementRect.width) || parseInt(css.getPropertyValue('width'))
params.elementHeight = parseInt(elementRect.height) || parseInt(css.getPropertyValue('height')); params.elementHeight = parseInt(elementRect.height) || parseInt(css.getPropertyValue('height'))
return params; return params
}; }
WebViewImpl.prototype.attachWindow = function(guestInstanceId) { WebViewImpl.prototype.attachWindow = function (guestInstanceId) {
this.guestInstanceId = guestInstanceId; this.guestInstanceId = guestInstanceId
this.webContents = remote.getGuestWebContents(this.guestInstanceId); this.webContents = remote.getGuestWebContents(this.guestInstanceId)
if (!this.internalInstanceId) { if (!this.internalInstanceId) {
return true; return true
} }
return guestViewInternal.attachGuest(this.internalInstanceId, this.guestInstanceId, this.buildParams()); return guestViewInternal.attachGuest(this.internalInstanceId, this.guestInstanceId, this.buildParams())
}; }
return WebViewImpl; return WebViewImpl
})()
})();
// Registers browser plugin <object> custom element. // Registers browser plugin <object> custom element.
var registerBrowserPluginElement = function() { var registerBrowserPluginElement = function () {
var proto; var proto
proto = Object.create(HTMLObjectElement.prototype); proto = Object.create(HTMLObjectElement.prototype)
proto.createdCallback = function() { proto.createdCallback = function () {
this.setAttribute('type', 'application/browser-plugin'); this.setAttribute('type', 'application/browser-plugin')
this.setAttribute('id', 'browser-plugin-' + getNextId()); this.setAttribute('id', 'browser-plugin-' + getNextId())
// The <object> node fills in the <webview> container. // The <object> node fills in the <webview> container.
return this.style.flex = '1 1 auto'; this.style.flex = '1 1 auto'
}; }
proto.attributeChangedCallback = function(name, oldValue, newValue) { proto.attributeChangedCallback = function (name, oldValue, newValue) {
var internal; var internal
internal = v8Util.getHiddenValue(this, 'internal'); internal = v8Util.getHiddenValue(this, 'internal')
if (!internal) { if (!internal) {
return; return
} }
return internal.handleBrowserPluginAttributeMutation(name, oldValue, newValue); return internal.handleBrowserPluginAttributeMutation(name, oldValue, newValue)
}; }
proto.attachedCallback = function() { proto.attachedCallback = function () {
// Load the plugin immediately. // Load the plugin immediately.
return this.nonExistentAttribute; return this.nonExistentAttribute
}; }
WebViewImpl.BrowserPlugin = webFrame.registerEmbedderCustomElement('browserplugin', { WebViewImpl.BrowserPlugin = webFrame.registerEmbedderCustomElement('browserplugin', {
"extends": 'object', 'extends': 'object',
prototype: proto prototype: proto
}); })
delete proto.createdCallback; delete proto.createdCallback
delete proto.attachedCallback; delete proto.attachedCallback
delete proto.detachedCallback; delete proto.detachedCallback
return delete proto.attributeChangedCallback; return delete proto.attributeChangedCallback
}; }
// Registers <webview> custom element. // Registers <webview> custom element.
var registerWebViewElement = function() { var registerWebViewElement = function () {
var createBlockHandler, createNonBlockHandler, i, j, len, len1, m, methods, nonblockMethods, proto; var createBlockHandler, createNonBlockHandler, i, j, len, len1, m, methods, nonblockMethods, proto
proto = Object.create(HTMLObjectElement.prototype); proto = Object.create(HTMLObjectElement.prototype)
proto.createdCallback = function() { proto.createdCallback = function () {
return new WebViewImpl(this); return new WebViewImpl(this)
}; }
proto.attributeChangedCallback = function(name, oldValue, newValue) { proto.attributeChangedCallback = function (name, oldValue, newValue) {
var internal; var internal
internal = v8Util.getHiddenValue(this, 'internal'); internal = v8Util.getHiddenValue(this, 'internal')
if (!internal) { if (!internal) {
return; return
} }
return internal.handleWebviewAttributeMutation(name, oldValue, newValue); return internal.handleWebviewAttributeMutation(name, oldValue, newValue)
}; }
proto.detachedCallback = function() { proto.detachedCallback = function () {
var internal; var internal
internal = v8Util.getHiddenValue(this, 'internal'); internal = v8Util.getHiddenValue(this, 'internal')
if (!internal) { if (!internal) {
return; return
} }
guestViewInternal.deregisterEvents(internal.viewInstanceId); guestViewInternal.deregisterEvents(internal.viewInstanceId)
internal.elementAttached = false; internal.elementAttached = false
return internal.reset(); return internal.reset()
}; }
proto.attachedCallback = function() { proto.attachedCallback = function () {
var internal; var internal
internal = v8Util.getHiddenValue(this, 'internal'); internal = v8Util.getHiddenValue(this, 'internal')
if (!internal) { if (!internal) {
return; return
} }
if (!internal.elementAttached) { if (!internal.elementAttached) {
guestViewInternal.registerEvents(internal, internal.viewInstanceId); guestViewInternal.registerEvents(internal, internal.viewInstanceId)
internal.elementAttached = true; internal.elementAttached = true
return internal.attributes[webViewConstants.ATTRIBUTE_SRC].parse(); return internal.attributes[webViewConstants.ATTRIBUTE_SRC].parse()
} }
}; }
// Public-facing API methods. // Public-facing API methods.
methods = [ methods = [
@ -377,8 +374,8 @@ var registerWebViewElement = function() {
'downloadURL', 'downloadURL',
'inspectServiceWorker', 'inspectServiceWorker',
'print', 'print',
'printToPDF', 'printToPDF'
]; ]
nonblockMethods = [ nonblockMethods = [
'insertCSS', 'insertCSS',
'insertText', 'insertText',
@ -386,80 +383,79 @@ var registerWebViewElement = function() {
'sendInputEvent', 'sendInputEvent',
'setZoomFactor', 'setZoomFactor',
'setZoomLevel', 'setZoomLevel',
'setZoomLevelLimits', 'setZoomLevelLimits'
]; ]
// Forward proto.foo* method calls to WebViewImpl.foo*. // Forward proto.foo* method calls to WebViewImpl.foo*.
createBlockHandler = function(m) { createBlockHandler = function (m) {
return function(...args) { return function (...args) {
const internal = v8Util.getHiddenValue(this, 'internal'); const internal = v8Util.getHiddenValue(this, 'internal')
if (internal.webContents) { if (internal.webContents) {
return internal.webContents[m].apply(internal.webContents, args); return internal.webContents[m].apply(internal.webContents, args)
} else { } else {
throw new Error(`Cannot call ${m} because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emitted before this method can be called.`); throw new Error(`Cannot call ${m} because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emitted before this method can be called.`)
} }
}; }
}; }
for (i = 0, len = methods.length; i < len; i++) { for (i = 0, len = methods.length; i < len; i++) {
m = methods[i]; m = methods[i]
proto[m] = createBlockHandler(m); proto[m] = createBlockHandler(m)
}
createNonBlockHandler = function (m) {
return function (...args) {
const internal = v8Util.getHiddenValue(this, 'internal')
return ipcRenderer.send.apply(ipcRenderer, ['ATOM_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', null, internal.guestInstanceId, m].concat(args))
}
} }
createNonBlockHandler = function(m) {
return function(...args) {
const internal = v8Util.getHiddenValue(this, 'internal');
return ipcRenderer.send.apply(ipcRenderer, ['ATOM_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', null, internal.guestInstanceId, m].concat(args));
};
};
for (j = 0, len1 = nonblockMethods.length; j < len1; j++) { for (j = 0, len1 = nonblockMethods.length; j < len1; j++) {
m = nonblockMethods[j]; m = nonblockMethods[j]
proto[m] = createNonBlockHandler(m); proto[m] = createNonBlockHandler(m)
} }
proto.executeJavaScript = function(code, hasUserGesture, callback) { proto.executeJavaScript = function (code, hasUserGesture, callback) {
var internal = v8Util.getHiddenValue(this, 'internal'); var internal = v8Util.getHiddenValue(this, 'internal')
if (typeof hasUserGesture === "function") { if (typeof hasUserGesture === 'function') {
callback = hasUserGesture; callback = hasUserGesture
hasUserGesture = false; hasUserGesture = false
} }
let requestId = getNextId(); let requestId = getNextId()
ipcRenderer.send('ATOM_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', requestId, internal.guestInstanceId, "executeJavaScript", code, hasUserGesture); ipcRenderer.send('ATOM_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', requestId, internal.guestInstanceId, 'executeJavaScript', code, hasUserGesture)
ipcRenderer.once(`ATOM_RENDERER_ASYNC_CALL_TO_GUEST_VIEW_RESPONSE_${requestId}`, function(event, result) { ipcRenderer.once(`ATOM_RENDERER_ASYNC_CALL_TO_GUEST_VIEW_RESPONSE_${requestId}`, function (event, result) {
if (callback) if (callback) callback(result)
callback(result); })
}); }
};
// WebContents associated with this webview. // WebContents associated with this webview.
proto.getWebContents = function() { proto.getWebContents = function () {
var internal = v8Util.getHiddenValue(this, 'internal'); var internal = v8Util.getHiddenValue(this, 'internal')
return internal.webContents; return internal.webContents
}; }
// Deprecated. // Deprecated.
deprecate.rename(proto, 'getUrl', 'getURL'); deprecate.rename(proto, 'getUrl', 'getURL')
window.WebView = webFrame.registerEmbedderCustomElement('webview', { window.WebView = webFrame.registerEmbedderCustomElement('webview', {
prototype: proto prototype: proto
}); })
// Delete the callbacks so developers cannot call them and produce unexpected // Delete the callbacks so developers cannot call them and produce unexpected
// behavior. // behavior.
delete proto.createdCallback; delete proto.createdCallback
delete proto.attachedCallback; delete proto.attachedCallback
delete proto.detachedCallback; delete proto.detachedCallback
return delete proto.attributeChangedCallback; return delete proto.attributeChangedCallback
}; }
var useCapture = true; var useCapture = true
var listener = function(event) { var listener = function (event) {
if (document.readyState === 'loading') { if (document.readyState === 'loading') {
return; return
} }
registerBrowserPluginElement(); registerBrowserPluginElement()
registerWebViewElement(); registerWebViewElement()
return window.removeEventListener(event.type, listener, useCapture); return window.removeEventListener(event.type, listener, useCapture)
}; }
window.addEventListener('readystatechange', listener, true); window.addEventListener('readystatechange', listener, true)
module.exports = WebViewImpl; module.exports = WebViewImpl

View file

@ -3,17 +3,29 @@
"version": "0.37.3", "version": "0.37.3",
"devDependencies": { "devDependencies": {
"asar": "^0.10.0", "asar": "^0.10.0",
"eslint": "^2.1.0", "request": "*",
"request": "*" "standard": "^6.0.8"
}, },
"optionalDependencies": { "optionalDependencies": {
"runas": "^3.0.0" "runas": "^3.0.0"
}, },
"standard": {
"ignore": [
"/out",
"/spec",
"/vendor"
],
"env": {
"browser": true
}
},
"private": true, "private": true,
"scripts": { "scripts": {
"bootstrap": "python ./script/bootstrap.py", "bootstrap": "python ./script/bootstrap.py",
"build": "python ./script/build.py -c D", "build": "python ./script/build.py -c D",
"lint": "python ./script/eslint.py && python ./script/cpplint.py", "lint": "npm run lint-js && npm run lint-cpp",
"lint-js": "standard && standard spec",
"lint-cpp": "python ./script/cpplint.py",
"preinstall": "node -e 'process.exit(0)'", "preinstall": "node -e 'process.exit(0)'",
"repl": "python ./script/start.py --interactive", "repl": "python ./script/start.py --interactive",
"start": "python ./script/start.py", "start": "python ./script/start.py",

View file

@ -62,9 +62,10 @@ def main():
args += ['--dev'] args += ['--dev']
run_script('bootstrap.py', args) run_script('bootstrap.py', args)
run_script('cpplint.py')
run_script('eslint.py')
if PLATFORM != 'win32': if PLATFORM != 'win32':
sys.stderr.write('\nRunning `npm run lint`\n')
sys.stderr.flush()
execute([npm, 'run', 'lint'])
run_script('pylint.py') run_script('pylint.py')
if is_release: if is_release:
run_script('build.py', ['-c', 'R']) run_script('build.py', ['-c', 'R'])

View file

@ -1,36 +0,0 @@
#!/usr/bin/env python
import glob
import os
import sys
from lib.config import PLATFORM
from lib.util import execute
SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
def main():
os.chdir(SOURCE_ROOT)
# Skip eslint on our Windows build machine for now.
if PLATFORM == 'win32' and os.getenv('JANKY_SHA1'):
return
eslint = os.path.join(SOURCE_ROOT, 'node_modules', '.bin', 'eslint')
if sys.platform in ['win32', 'cygwin']:
eslint += '.cmd'
settings = ['--quiet', '--config']
sourceConfig = os.path.join('script', 'eslintrc-base.json')
sourceFiles = ['lib']
execute([eslint] + settings + [sourceConfig] + sourceFiles)
specConfig = os.path.join('script', 'eslintrc-spec.json')
specFiles = glob.glob('spec/*.js')
execute([eslint] + settings + [specConfig] + specFiles)
if __name__ == '__main__':
sys.exit(main())

View file

@ -1,36 +0,0 @@
{
"rules": {
"indent": [
2,
2,
{
"SwitchCase": 1
}
],
"quotes": [
0,
"single"
],
"semi": [
2,
"always"
],
"comma-dangle": 0,
"linebreak-style": 0,
"no-console": 0,
"no-undef": 2,
"no-unused-vars": 2
},
"env": {
"es6": true,
"node": true,
"browser": true
},
"extends": "eslint:recommended",
"globals": {
"DevToolsAPI": false,
"InspectorFrontendHost": false,
"WebInspector": false,
"WebView": false
}
}

View file

@ -1,7 +0,0 @@
{
"env": {
"jquery": true,
"mocha": true
},
"extends": "./eslintrc-base.json"
}

View file

@ -1,135 +1,135 @@
const assert = require('assert'); const assert = require('assert')
const ChildProcess = require('child_process'); const ChildProcess = require('child_process')
const path = require('path'); const path = require('path')
const remote = require('electron').remote; const remote = require('electron').remote
const app = remote.require('electron').app; const app = remote.require('electron').app
const BrowserWindow = remote.require('electron').BrowserWindow; const BrowserWindow = remote.require('electron').BrowserWindow
describe('electron module', function() { describe('electron module', function () {
it('allows old style require by default', function() { it('allows old style require by default', function () {
require('shell'); require('shell')
}); })
it('can prevent exposing internal modules to require', function(done) { it('can prevent exposing internal modules to require', function (done) {
const electron = require('electron'); const electron = require('electron')
const clipboard = require('clipboard'); const clipboard = require('clipboard')
assert.equal(typeof clipboard, 'object'); assert.equal(typeof clipboard, 'object')
electron.hideInternalModules(); electron.hideInternalModules()
try { try {
require('clipboard'); require('clipboard')
} catch(err) { } catch (err) {
assert.equal(err.message, 'Cannot find module \'clipboard\''); assert.equal(err.message, "Cannot find module 'clipboard'")
done(); done()
} }
}); })
}); })
describe('app module', function() { describe('app module', function () {
describe('app.getVersion()', function() { describe('app.getVersion()', function () {
it('returns the version field of package.json', function() { it('returns the version field of package.json', function () {
assert.equal(app.getVersion(), '0.1.0'); assert.equal(app.getVersion(), '0.1.0')
}); })
}); })
describe('app.setVersion(version)', function() { describe('app.setVersion(version)', function () {
it('overrides the version', function() { it('overrides the version', function () {
assert.equal(app.getVersion(), '0.1.0'); assert.equal(app.getVersion(), '0.1.0')
app.setVersion('test-version'); app.setVersion('test-version')
assert.equal(app.getVersion(), 'test-version'); assert.equal(app.getVersion(), 'test-version')
app.setVersion('0.1.0'); app.setVersion('0.1.0')
}); })
}); })
describe('app.getName()', function() { describe('app.getName()', function () {
it('returns the name field of package.json', function() { it('returns the name field of package.json', function () {
assert.equal(app.getName(), 'Electron Test'); assert.equal(app.getName(), 'Electron Test')
}); })
}); })
describe('app.setName(name)', function() { describe('app.setName(name)', function () {
it('overrides the name', function() { it('overrides the name', function () {
assert.equal(app.getName(), 'Electron Test'); assert.equal(app.getName(), 'Electron Test')
app.setName('test-name'); app.setName('test-name')
assert.equal(app.getName(), 'test-name'); assert.equal(app.getName(), 'test-name')
app.setName('Electron Test'); app.setName('Electron Test')
}); })
}); })
describe('app.getLocale()', function() { describe('app.getLocale()', function () {
it('should not be empty', function() { it('should not be empty', function () {
assert.notEqual(app.getLocale(), ''); assert.notEqual(app.getLocale(), '')
}); })
}); })
describe('app.exit(exitCode)', function() { describe('app.exit(exitCode)', function () {
var appProcess = null; var appProcess = null
afterEach(function() { afterEach(function () {
appProcess != null ? appProcess.kill() : void 0; appProcess != null ? appProcess.kill() : void 0
}); })
it('emits a process exit event with the code', function(done) { it('emits a process exit event with the code', function (done) {
var appPath = path.join(__dirname, 'fixtures', 'api', 'quit-app'); var appPath = path.join(__dirname, 'fixtures', 'api', 'quit-app')
var electronPath = remote.getGlobal('process').execPath; var electronPath = remote.getGlobal('process').execPath
var output = ''; var output = ''
appProcess = ChildProcess.spawn(electronPath, [appPath]); appProcess = ChildProcess.spawn(electronPath, [appPath])
appProcess.stdout.on('data', function(data) { appProcess.stdout.on('data', function (data) {
output += data; output += data
}); })
appProcess.on('close', function(code) { appProcess.on('close', function (code) {
if (process.platform !== 'win32') { if (process.platform !== 'win32') {
assert.notEqual(output.indexOf('Exit event with code: 123'), -1); assert.notEqual(output.indexOf('Exit event with code: 123'), -1)
} }
assert.equal(code, 123); assert.equal(code, 123)
done(); done()
}); })
}); })
}); })
describe('BrowserWindow events', function() { describe('BrowserWindow events', function () {
var w = null; var w = null
afterEach(function() { afterEach(function () {
if (w != null) { if (w != null) {
w.destroy(); w.destroy()
} }
w = null; w = null
}); })
it('should emit browser-window-focus event when window is focused', function(done) { it('should emit browser-window-focus event when window is focused', function (done) {
app.once('browser-window-focus', function(e, window) { app.once('browser-window-focus', function (e, window) {
assert.equal(w.id, window.id); assert.equal(w.id, window.id)
done(); done()
}); })
w = new BrowserWindow({ w = new BrowserWindow({
show: false show: false
}); })
w.emit('focus'); w.emit('focus')
}); })
it('should emit browser-window-blur event when window is blured', function(done) { it('should emit browser-window-blur event when window is blured', function (done) {
app.once('browser-window-blur', function(e, window) { app.once('browser-window-blur', function (e, window) {
assert.equal(w.id, window.id); assert.equal(w.id, window.id)
done(); done()
}); })
w = new BrowserWindow({ w = new BrowserWindow({
show: false show: false
}); })
w.emit('blur'); w.emit('blur')
}); })
it('should emit browser-window-created event when window is created', function(done) { it('should emit browser-window-created event when window is created', function (done) {
app.once('browser-window-created', function(e, window) { app.once('browser-window-created', function (e, window) {
setImmediate(function() { setImmediate(function () {
assert.equal(w.id, window.id); assert.equal(w.id, window.id)
done(); done()
}); })
}); })
w = new BrowserWindow({ w = new BrowserWindow({
show: false show: false
}); })
w.emit('blur'); w.emit('blur')
}); })
}); })
}); })

View file

@ -1,38 +1,37 @@
const assert = require('assert'); const assert = require('assert')
const autoUpdater = require('electron').remote.autoUpdater; const autoUpdater = require('electron').remote.autoUpdater
const ipcRenderer = require('electron').ipcRenderer; const ipcRenderer = require('electron').ipcRenderer
// Skip autoUpdater tests in MAS build. // Skip autoUpdater tests in MAS build.
if (process.mas) if (!process.mas) {
return; describe('autoUpdater module', function () {
describe('checkForUpdates', function () {
it('emits an error on Windows when called the feed URL is not set', function (done) {
if (process.platform !== 'win32') {
return done()
}
describe('autoUpdater module', function() { ipcRenderer.once('auto-updater-error', function (event, message) {
describe('checkForUpdates', function() { assert.equal(message, 'Update URL is not set')
it('emits an error on Windows when called the feed URL is not set', function (done) { done()
if (process.platform !== 'win32') { })
return done(); autoUpdater.setFeedURL('')
} autoUpdater.checkForUpdates()
})
})
ipcRenderer.once('auto-updater-error', function(event, message) { describe('setFeedURL', function () {
assert.equal(message, 'Update URL is not set'); it('emits an error on Mac OS X when the application is unsigned', function (done) {
done(); if (process.platform !== 'darwin') {
}); return done()
autoUpdater.setFeedURL(''); }
autoUpdater.checkForUpdates();
});
});
describe('setFeedURL', function() { ipcRenderer.once('auto-updater-error', function (event, message) {
it('emits an error on Mac OS X when the application is unsigned', function (done) { assert.equal(message, 'Could not get code signature for running application')
if (process.platform !== 'darwin') { done()
return done(); })
} autoUpdater.setFeedURL('')
})
ipcRenderer.once('auto-updater-error', function(event, message) { })
assert.equal(message, 'Could not get code signature for running application'); })
done(); }
});
autoUpdater.setFeedURL('');
});
});
});

File diff suppressed because it is too large Load diff

View file

@ -1,63 +1,63 @@
const assert = require('assert'); const assert = require('assert')
const path = require('path'); const path = require('path')
const clipboard = require('electron').clipboard; const clipboard = require('electron').clipboard
const nativeImage = require('electron').nativeImage; const nativeImage = require('electron').nativeImage
describe('clipboard module', function() { describe('clipboard module', function () {
var fixtures = path.resolve(__dirname, 'fixtures'); var fixtures = path.resolve(__dirname, 'fixtures')
describe('clipboard.readImage()', function() { describe('clipboard.readImage()', function () {
it('returns NativeImage intance', function() { it('returns NativeImage intance', function () {
var p = path.join(fixtures, 'assets', 'logo.png'); var p = path.join(fixtures, 'assets', 'logo.png')
var i = nativeImage.createFromPath(p); var i = nativeImage.createFromPath(p)
clipboard.writeImage(p); clipboard.writeImage(p)
assert.equal(clipboard.readImage().toDataURL(), i.toDataURL()); assert.equal(clipboard.readImage().toDataURL(), i.toDataURL())
}); })
}); })
describe('clipboard.readText()', function() { describe('clipboard.readText()', function () {
it('returns unicode string correctly', function() { it('returns unicode string correctly', function () {
var text = '千江有水千江月,万里无云万里天'; var text = '千江有水千江月,万里无云万里天'
clipboard.writeText(text); clipboard.writeText(text)
assert.equal(clipboard.readText(), text); assert.equal(clipboard.readText(), text)
}); })
}); })
describe('clipboard.readHtml()', function() { describe('clipboard.readHtml()', function () {
it('returns markup correctly', function() { it('returns markup correctly', function () {
var text = '<string>Hi</string>'; var text = '<string>Hi</string>'
var markup = process.platform === 'darwin' ? '<meta charset=\'utf-8\'><string>Hi</string>' : process.platform === 'linux' ? '<meta http-equiv="content-type" ' + 'content="text/html; charset=utf-8"><string>Hi</string>' : '<string>Hi</string>'; var markup = process.platform === 'darwin' ? "<meta charset='utf-8'><string>Hi</string>" : process.platform === 'linux' ? '<meta http-equiv="content-type" ' + 'content="text/html; charset=utf-8"><string>Hi</string>' : '<string>Hi</string>'
clipboard.writeHtml(text); clipboard.writeHtml(text)
assert.equal(clipboard.readHtml(), markup); assert.equal(clipboard.readHtml(), markup)
}); })
}); })
describe('clipboard.readRtf', function() { describe('clipboard.readRtf', function () {
it('returns rtf text correctly', function() { it('returns rtf text correctly', function () {
var rtf = "{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\nThis is some {\\b bold} text.\\par\n}"; var rtf = '{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\nThis is some {\\b bold} text.\\par\n}'
clipboard.writeRtf(rtf); clipboard.writeRtf(rtf)
assert.equal(clipboard.readRtf(), rtf); assert.equal(clipboard.readRtf(), rtf)
}); })
}); })
describe('clipboard.write()', function() { describe('clipboard.write()', function () {
it('returns data correctly', function() { it('returns data correctly', function () {
var text = 'test'; var text = 'test'
var rtf = '{\\rtf1\\utf8 text}'; var rtf = '{\\rtf1\\utf8 text}'
var p = path.join(fixtures, 'assets', 'logo.png'); var p = path.join(fixtures, 'assets', 'logo.png')
var i = nativeImage.createFromPath(p); var i = nativeImage.createFromPath(p)
var markup = process.platform === 'darwin' ? '<meta charset=\'utf-8\'><b>Hi</b>' : process.platform === 'linux' ? '<meta http-equiv="content-type" ' + 'content="text/html; charset=utf-8"><b>Hi</b>' : '<b>Hi</b>'; var markup = process.platform === 'darwin' ? "<meta charset='utf-8'><b>Hi</b>" : process.platform === 'linux' ? '<meta http-equiv="content-type" ' + 'content="text/html; charset=utf-8"><b>Hi</b>' : '<b>Hi</b>'
clipboard.write({ clipboard.write({
text: "test", text: 'test',
html: '<b>Hi</b>', html: '<b>Hi</b>',
rtf: '{\\rtf1\\utf8 text}', rtf: '{\\rtf1\\utf8 text}',
image: p image: p
}); })
assert.equal(clipboard.readText(), text); assert.equal(clipboard.readText(), text)
assert.equal(clipboard.readHtml(), markup); assert.equal(clipboard.readHtml(), markup)
assert.equal(clipboard.readRtf(), rtf); assert.equal(clipboard.readRtf(), rtf)
assert.equal(clipboard.readImage().toDataURL(), i.toDataURL()); assert.equal(clipboard.readImage().toDataURL(), i.toDataURL())
}); })
}); })
}); })

View file

@ -1,93 +1,92 @@
const assert = require('assert'); const assert = require('assert')
const http = require('http'); const http = require('http')
const multiparty = require('multiparty'); const multiparty = require('multiparty')
const path = require('path'); const path = require('path')
const url = require('url'); const url = require('url')
const remote = require('electron').remote; const remote = require('electron').remote
const app = remote.require('electron').app; const app = remote.require('electron').app
const crashReporter = remote.require('electron').crashReporter; const crashReporter = remote.require('electron').crashReporter
const BrowserWindow = remote.require('electron').BrowserWindow; const BrowserWindow = remote.require('electron').BrowserWindow
describe('crash-reporter module', function() { describe('crash-reporter module', function () {
var fixtures = path.resolve(__dirname, 'fixtures'); var fixtures = path.resolve(__dirname, 'fixtures')
var w = null; var w = null
beforeEach(function() { beforeEach(function () {
w = new BrowserWindow({ w = new BrowserWindow({
show: false show: false
}); })
}); })
afterEach(function() { afterEach(function () {
w.destroy(); w.destroy()
}); })
if (process.mas) { if (process.mas) {
return; return
} }
var isCI = remote.getGlobal('isCi'); var isCI = remote.getGlobal('isCi')
if (isCI) { if (isCI) {
return; return
} }
it('should send minidump when renderer crashes', function(done) { it('should send minidump when renderer crashes', function (done) {
this.timeout(120000); this.timeout(120000)
var called = false; var called = false
var server = http.createServer(function(req, res) { var server = http.createServer(function (req, res) {
server.close(); server.close()
var form = new multiparty.Form(); var form = new multiparty.Form()
form.parse(req, function(error, fields) { form.parse(req, function (error, fields) {
if (called) { if (error) throw error
return; if (called) return
} called = true
called = true; assert.equal(fields['prod'], 'Electron')
assert.equal(fields['prod'], 'Electron'); assert.equal(fields['ver'], process.versions['electron'])
assert.equal(fields['ver'], process.versions['electron']); assert.equal(fields['process_type'], 'renderer')
assert.equal(fields['process_type'], 'renderer'); assert.equal(fields['platform'], process.platform)
assert.equal(fields['platform'], process.platform); assert.equal(fields['extra1'], 'extra1')
assert.equal(fields['extra1'], 'extra1'); assert.equal(fields['extra2'], 'extra2')
assert.equal(fields['extra2'], 'extra2'); assert.equal(fields['_productName'], 'Zombies')
assert.equal(fields['_productName'], 'Zombies'); assert.equal(fields['_companyName'], 'Umbrella Corporation')
assert.equal(fields['_companyName'], 'Umbrella Corporation'); assert.equal(fields['_version'], app.getVersion())
assert.equal(fields['_version'], app.getVersion()); res.end('abc-123-def')
res.end('abc-123-def'); done()
done(); })
}); })
}); var port = remote.process.port
var port = remote.process.port; server.listen(port, '127.0.0.1', function () {
server.listen(port, '127.0.0.1', function() { port = server.address().port
port = server.address().port; remote.process.port = port
remote.process.port = port;
const crashUrl = url.format({ const crashUrl = url.format({
protocol: 'file', protocol: 'file',
pathname: path.join(fixtures, 'api', 'crash.html'), pathname: path.join(fixtures, 'api', 'crash.html'),
search: "?port=" + port search: '?port=' + port
}); })
if (process.platform === 'darwin') { if (process.platform === 'darwin') {
crashReporter.start({ crashReporter.start({
companyName: 'Umbrella Corporation', companyName: 'Umbrella Corporation',
submitURL: "http://127.0.0.1:" + port submitURL: 'http://127.0.0.1:' + port
}); })
} }
w.loadURL(crashUrl); w.loadURL(crashUrl)
}); })
}); })
describe(".start(options)", function() { describe('.start(options)', function () {
it('requires that the companyName and submitURL options be specified', function() { it('requires that the companyName and submitURL options be specified', function () {
assert.throws(function() { assert.throws(function () {
crashReporter.start({ crashReporter.start({
companyName: 'Missing submitURL' companyName: 'Missing submitURL'
}); })
}); })
assert.throws(function() { assert.throws(function () {
crashReporter.start({ crashReporter.start({
submitURL: 'Missing companyName' submitURL: 'Missing companyName'
}); })
}); })
}); })
}); })
}); })

View file

@ -1,133 +1,134 @@
const assert = require('assert'); const assert = require('assert')
const path = require('path'); const path = require('path')
const BrowserWindow = require('electron').remote.BrowserWindow; const BrowserWindow = require('electron').remote.BrowserWindow
describe('debugger module', function() { describe('debugger module', function () {
var fixtures = path.resolve(__dirname, 'fixtures'); var fixtures = path.resolve(__dirname, 'fixtures')
var w = null; var w = null
beforeEach(function() { beforeEach(function () {
if (w != null) { if (w != null) {
w.destroy(); w.destroy()
} }
w = new BrowserWindow({ w = new BrowserWindow({
show: false, show: false,
width: 400, width: 400,
height: 400 height: 400
}); })
}); })
afterEach(function() { afterEach(function () {
if (w != null) { if (w != null) {
w.destroy(); w.destroy()
} }
w = null; w = null
}); })
describe('debugger.attach', function() { describe('debugger.attach', function () {
it('fails when devtools is already open', function(done) { it('fails when devtools is already open', function (done) {
w.webContents.on('did-finish-load', function() { w.webContents.on('did-finish-load', function () {
w.webContents.openDevTools(); w.webContents.openDevTools()
try { try {
w.webContents.debugger.attach(); w.webContents.debugger.attach()
} catch(err) { } catch (err) {
assert(w.webContents.debugger.isAttached()); assert(w.webContents.debugger.isAttached())
done(); done()
} }
}); })
w.webContents.loadURL('file://' + path.join(fixtures, 'pages', 'a.html')); w.webContents.loadURL('file://' + path.join(fixtures, 'pages', 'a.html'))
}); })
it('fails when protocol version is not supported', function(done) { it('fails when protocol version is not supported', function (done) {
try { try {
w.webContents.debugger.attach("2.0"); w.webContents.debugger.attach('2.0')
} catch(err) { } catch (err) {
assert(!w.webContents.debugger.isAttached()); assert(!w.webContents.debugger.isAttached())
done(); done()
} }
}); })
it('attaches when no protocol version is specified', function(done) { it('attaches when no protocol version is specified', function (done) {
try { try {
w.webContents.debugger.attach(); w.webContents.debugger.attach()
} catch(err) { } catch (err) {
done('unexpected error : ' + err); done('unexpected error : ' + err)
} }
assert(w.webContents.debugger.isAttached()); assert(w.webContents.debugger.isAttached())
done(); done()
}); })
}); })
describe('debugger.detach', function() { describe('debugger.detach', function () {
it('fires detach event', function(done) { it('fires detach event', function (done) {
w.webContents.debugger.on('detach', function(e, reason) { w.webContents.debugger.on('detach', function (e, reason) {
assert.equal(reason, 'target closed'); assert.equal(reason, 'target closed')
assert(!w.webContents.debugger.isAttached()); assert(!w.webContents.debugger.isAttached())
done(); done()
}); })
try { try {
w.webContents.debugger.attach(); w.webContents.debugger.attach()
} catch(err) { } catch (err) {
done('unexpected error : ' + err); done('unexpected error : ' + err)
} }
w.webContents.debugger.detach(); w.webContents.debugger.detach()
}); })
}); })
describe('debugger.sendCommand', function() { describe('debugger.sendCommand', function () {
it('retuns response', function(done) { it('retuns response', function (done) {
w.webContents.loadURL('about:blank'); w.webContents.loadURL('about:blank')
try { try {
w.webContents.debugger.attach(); w.webContents.debugger.attach()
} catch(err) { } catch (err) {
done('unexpected error : ' + err); return done('unexpected error : ' + err)
}
var callback = function (err, res) {
assert(!err.message)
assert(!res.wasThrown)
assert.equal(res.result.value, 6)
w.webContents.debugger.detach()
done()
} }
var callback = function(err, res) {
assert(!res.wasThrown);
assert.equal(res.result.value, 6);
w.webContents.debugger.detach();
done();
};
const params = { const params = {
"expression": "4+2", 'expression': '4+2'
};
w.webContents.debugger.sendCommand("Runtime.evaluate", params, callback);
});
it('fires message event', function(done) {
var url = process.platform != 'win32' ?
'file://' + path.join(fixtures, 'pages', 'a.html') :
'file:///' + path.join(fixtures, 'pages', 'a.html').replace(/\\/g, '/');
w.webContents.loadURL(url);
try {
w.webContents.debugger.attach();
} catch(err) {
done('unexpected error : ' + err);
} }
w.webContents.debugger.on('message', function(e, method, params) { w.webContents.debugger.sendCommand('Runtime.evaluate', params, callback)
if(method == "Console.messageAdded") { })
assert.equal(params.message.type, 'log');
assert.equal(params.message.url, url); it('fires message event', function (done) {
assert.equal(params.message.text, 'a'); var url = process.platform !== 'win32'
w.webContents.debugger.detach(); ? 'file://' + path.join(fixtures, 'pages', 'a.html')
done(); : 'file:///' + path.join(fixtures, 'pages', 'a.html').replace(/\\/g, '/')
w.webContents.loadURL(url)
try {
w.webContents.debugger.attach()
} catch (err) {
done('unexpected error : ' + err)
}
w.webContents.debugger.on('message', function (e, method, params) {
if (method === 'Console.messageAdded') {
assert.equal(params.message.type, 'log')
assert.equal(params.message.url, url)
assert.equal(params.message.text, 'a')
w.webContents.debugger.detach()
done()
} }
}); })
w.webContents.debugger.sendCommand("Console.enable"); w.webContents.debugger.sendCommand('Console.enable')
}); })
it('returns error message when command fails', function(done) { it('returns error message when command fails', function (done) {
w.webContents.loadURL('about:blank'); w.webContents.loadURL('about:blank')
try { try {
w.webContents.debugger.attach(); w.webContents.debugger.attach()
} catch(err) { } catch (err) {
done('unexpected error : ' + err); done('unexpected error : ' + err)
} }
w.webContents.debugger.sendCommand("Test", function(err) { w.webContents.debugger.sendCommand('Test', function (err) {
assert.equal(err.message, '\'Test\' wasn\'t found'); assert.equal(err.message, "'Test' wasn't found")
w.webContents.debugger.detach(); w.webContents.debugger.detach()
done(); done()
}); })
}); })
}); })
}); })

View file

@ -1,27 +1,27 @@
const assert = require('assert'); const assert = require('assert')
const deprecations = require('electron').deprecations; const deprecations = require('electron').deprecations
describe('deprecations', function() { describe('deprecations', function () {
beforeEach(function() { beforeEach(function () {
deprecations.setHandler(null); deprecations.setHandler(null)
process.throwDeprecation = true; process.throwDeprecation = true
}); })
it('allows a deprecation handler function to be specified', function() { it('allows a deprecation handler function to be specified', function () {
var messages = []; var messages = []
deprecations.setHandler(function (message) { deprecations.setHandler(function (message) {
messages.push(message); messages.push(message)
}); })
require('electron').webFrame.registerUrlSchemeAsSecure('some-scheme'); require('electron').webFrame.registerUrlSchemeAsSecure('some-scheme')
assert.deepEqual(messages, ['registerUrlSchemeAsSecure is deprecated. Use registerURLSchemeAsSecure instead.']); assert.deepEqual(messages, ['registerUrlSchemeAsSecure is deprecated. Use registerURLSchemeAsSecure instead.'])
}); })
it('throws an exception if no deprecation handler is specified', function() { it('throws an exception if no deprecation handler is specified', function () {
assert.throws(function() { assert.throws(function () {
require('electron').webFrame.registerUrlSchemeAsPrivileged('some-scheme'); require('electron').webFrame.registerUrlSchemeAsPrivileged('some-scheme')
}, "registerUrlSchemeAsPrivileged is deprecated. Use registerURLSchemeAsPrivileged instead."); }, 'registerUrlSchemeAsPrivileged is deprecated. Use registerURLSchemeAsPrivileged instead.')
}); })
}); })

View file

@ -1,27 +1,27 @@
const assert = require('assert'); const assert = require('assert')
const desktopCapturer = require('electron').desktopCapturer; const desktopCapturer = require('electron').desktopCapturer
describe('desktopCapturer', function() { describe('desktopCapturer', function () {
it('should return a non-empty array of sources', function(done) { it('should return a non-empty array of sources', function (done) {
desktopCapturer.getSources({ desktopCapturer.getSources({
types: ['window', 'screen'] types: ['window', 'screen']
}, function(error, sources) { }, function (error, sources) {
assert.equal(error, null); assert.equal(error, null)
assert.notEqual(sources.length, 0); assert.notEqual(sources.length, 0)
done(); done()
}); })
}); })
it('does not throw an error when called more than once (regression)', function(done) { it('does not throw an error when called more than once (regression)', function (done) {
var callCount = 0; var callCount = 0
var callback = function (error, sources) { var callback = function (error, sources) {
callCount++; callCount++
assert.equal(error, null); assert.equal(error, null)
assert.notEqual(sources.length, 0); assert.notEqual(sources.length, 0)
if (callCount === 2) done(); if (callCount === 2) done()
}; }
desktopCapturer.getSources({types: ['window', 'screen']}, callback); desktopCapturer.getSources({types: ['window', 'screen']}, callback)
desktopCapturer.getSources({types: ['window', 'screen']}, callback); desktopCapturer.getSources({types: ['window', 'screen']}, callback)
}); })
}); })

View file

@ -1,210 +1,210 @@
'use strict'; 'use strict'
const assert = require('assert'); const assert = require('assert')
const path = require('path'); const path = require('path')
const ipcRenderer = require('electron').ipcRenderer; const ipcRenderer = require('electron').ipcRenderer
const remote = require('electron').remote; const remote = require('electron').remote
const ipcMain = remote.require('electron').ipcMain; const ipcMain = remote.require('electron').ipcMain
const BrowserWindow = remote.require('electron').BrowserWindow; const BrowserWindow = remote.require('electron').BrowserWindow
const comparePaths = function(path1, path2) { const comparePaths = function (path1, path2) {
if (process.platform === 'win32') { if (process.platform === 'win32') {
path1 = path1.toLowerCase(); path1 = path1.toLowerCase()
path2 = path2.toLowerCase(); path2 = path2.toLowerCase()
} }
assert.equal(path1, path2); assert.equal(path1, path2)
}; }
describe('ipc module', function() { describe('ipc module', function () {
var fixtures = path.join(__dirname, 'fixtures'); var fixtures = path.join(__dirname, 'fixtures')
describe('remote.require', function() { describe('remote.require', function () {
it('should returns same object for the same module', function() { it('should returns same object for the same module', function () {
var dialog1 = remote.require('electron'); var dialog1 = remote.require('electron')
var dialog2 = remote.require('electron'); var dialog2 = remote.require('electron')
assert.equal(dialog1, dialog2); assert.equal(dialog1, dialog2)
}); })
it('should work when object contains id property', function() { it('should work when object contains id property', function () {
var a = remote.require(path.join(fixtures, 'module', 'id.js')); var a = remote.require(path.join(fixtures, 'module', 'id.js'))
assert.equal(a.id, 1127); assert.equal(a.id, 1127)
}); })
it('should search module from the user app', function() { it('should search module from the user app', function () {
comparePaths(path.normalize(remote.process.mainModule.filename), path.resolve(__dirname, 'static', 'main.js')); comparePaths(path.normalize(remote.process.mainModule.filename), path.resolve(__dirname, 'static', 'main.js'))
comparePaths(path.normalize(remote.process.mainModule.paths[0]), path.resolve(__dirname, 'static', 'node_modules')); comparePaths(path.normalize(remote.process.mainModule.paths[0]), path.resolve(__dirname, 'static', 'node_modules'))
}); })
}); })
describe('remote.createFunctionWithReturnValue', function() { describe('remote.createFunctionWithReturnValue', function () {
it('should be called in browser synchronously', function() { it('should be called in browser synchronously', function () {
var buf = new Buffer('test'); var buf = new Buffer('test')
var call = remote.require(path.join(fixtures, 'module', 'call.js')); var call = remote.require(path.join(fixtures, 'module', 'call.js'))
var result = call.call(remote.createFunctionWithReturnValue(buf)); var result = call.call(remote.createFunctionWithReturnValue(buf))
assert.equal(result.constructor.name, 'Buffer'); assert.equal(result.constructor.name, 'Buffer')
}); })
}); })
describe('remote object in renderer', function() { describe('remote object in renderer', function () {
it('can change its properties', function() { it('can change its properties', function () {
var property = remote.require(path.join(fixtures, 'module', 'property.js')); var property = remote.require(path.join(fixtures, 'module', 'property.js'))
assert.equal(property.property, 1127); assert.equal(property.property, 1127)
property.property = 1007; property.property = 1007
assert.equal(property.property, 1007); assert.equal(property.property, 1007)
var property2 = remote.require(path.join(fixtures, 'module', 'property.js')); var property2 = remote.require(path.join(fixtures, 'module', 'property.js'))
assert.equal(property2.property, 1007); assert.equal(property2.property, 1007)
property.property = 1127; property.property = 1127
}); })
it('can construct an object from its member', function() { it('can construct an object from its member', function () {
var call = remote.require(path.join(fixtures, 'module', 'call.js')); var call = remote.require(path.join(fixtures, 'module', 'call.js'))
var obj = new call.constructor; var obj = new call.constructor()
assert.equal(obj.test, 'test'); assert.equal(obj.test, 'test')
}); })
it('can reassign and delete its member functions', function() { it('can reassign and delete its member functions', function () {
var remoteFunctions = remote.require(path.join(fixtures, 'module', 'function.js')); var remoteFunctions = remote.require(path.join(fixtures, 'module', 'function.js'))
assert.equal(remoteFunctions.aFunction(), 1127); assert.equal(remoteFunctions.aFunction(), 1127)
remoteFunctions.aFunction = function () { return 1234; }; remoteFunctions.aFunction = function () { return 1234 }
assert.equal(remoteFunctions.aFunction(), 1234); assert.equal(remoteFunctions.aFunction(), 1234)
assert.equal(delete remoteFunctions.aFunction, true); assert.equal(delete remoteFunctions.aFunction, true)
}); })
}); })
describe('remote value in browser', function() { describe('remote value in browser', function () {
var print = path.join(fixtures, 'module', 'print_name.js'); var print = path.join(fixtures, 'module', 'print_name.js')
it('keeps its constructor name for objects', function() { it('keeps its constructor name for objects', function () {
var buf = new Buffer('test'); var buf = new Buffer('test')
var print_name = remote.require(print); var print_name = remote.require(print)
assert.equal(print_name.print(buf), 'Buffer'); assert.equal(print_name.print(buf), 'Buffer')
}); })
it('supports instanceof Date', function() { it('supports instanceof Date', function () {
var now = new Date(); var now = new Date()
var print_name = remote.require(print); var print_name = remote.require(print)
assert.equal(print_name.print(now), 'Date'); assert.equal(print_name.print(now), 'Date')
assert.deepEqual(print_name.echo(now), now); assert.deepEqual(print_name.echo(now), now)
}); })
}); })
describe('remote promise', function() { describe('remote promise', function () {
it('can be used as promise in each side', function(done) { it('can be used as promise in each side', function (done) {
var promise = remote.require(path.join(fixtures, 'module', 'promise.js')); var promise = remote.require(path.join(fixtures, 'module', 'promise.js'))
promise.twicePromise(Promise.resolve(1234)).then(function(value) { promise.twicePromise(Promise.resolve(1234)).then(function (value) {
assert.equal(value, 2468); assert.equal(value, 2468)
done(); done()
}); })
}); })
}); })
describe('remote webContents', function() { describe('remote webContents', function () {
it('can return same object with different getters', function() { it('can return same object with different getters', function () {
var contents1 = remote.getCurrentWindow().webContents; var contents1 = remote.getCurrentWindow().webContents
var contents2 = remote.getCurrentWebContents(); var contents2 = remote.getCurrentWebContents()
assert(contents1 == contents2); assert(contents1 === contents2)
}); })
}); })
describe('remote class', function() { describe('remote class', function () {
let cl = remote.require(path.join(fixtures, 'module', 'class.js')); let cl = remote.require(path.join(fixtures, 'module', 'class.js'))
let base = cl.base; let base = cl.base
let derived = cl.derived; let derived = cl.derived
it('can get methods', function() { it('can get methods', function () {
assert.equal(base.method(), 'method'); assert.equal(base.method(), 'method')
}); })
it('can get properties', function() { it('can get properties', function () {
assert.equal(base.readonly, 'readonly'); assert.equal(base.readonly, 'readonly')
}); })
it('can change properties', function() { it('can change properties', function () {
assert.equal(base.value, 'old'); assert.equal(base.value, 'old')
base.value = 'new'; base.value = 'new'
assert.equal(base.value, 'new'); assert.equal(base.value, 'new')
base.value = 'old'; base.value = 'old'
}); })
it('has unenumerable methods', function() { it('has unenumerable methods', function () {
assert(!base.hasOwnProperty('method')); assert(!base.hasOwnProperty('method'))
assert(Object.getPrototypeOf(base).hasOwnProperty('method')); assert(Object.getPrototypeOf(base).hasOwnProperty('method'))
}); })
it('keeps prototype chain in derived class', function() { it('keeps prototype chain in derived class', function () {
assert.equal(derived.method(), 'method'); assert.equal(derived.method(), 'method')
assert.equal(derived.readonly, 'readonly'); assert.equal(derived.readonly, 'readonly')
assert(!derived.hasOwnProperty('method')); assert(!derived.hasOwnProperty('method'))
let proto = Object.getPrototypeOf(derived); let proto = Object.getPrototypeOf(derived)
assert(!proto.hasOwnProperty('method')); assert(!proto.hasOwnProperty('method'))
assert(Object.getPrototypeOf(proto).hasOwnProperty('method')); assert(Object.getPrototypeOf(proto).hasOwnProperty('method'))
}); })
}); })
describe('ipc.sender.send', function() { describe('ipc.sender.send', function () {
it('should work when sending an object containing id property', function(done) { it('should work when sending an object containing id property', function (done) {
var obj = { var obj = {
id: 1, id: 1,
name: 'ly' name: 'ly'
}; }
ipcRenderer.once('message', function(event, message) { ipcRenderer.once('message', function (event, message) {
assert.deepEqual(message, obj); assert.deepEqual(message, obj)
done(); done()
}); })
ipcRenderer.send('message', obj); ipcRenderer.send('message', obj)
}); })
it('can send instance of Date', function(done) { it('can send instance of Date', function (done) {
const currentDate = new Date(); const currentDate = new Date()
ipcRenderer.once('message', function(event, value) { ipcRenderer.once('message', function (event, value) {
assert.equal(value, currentDate.toISOString()); assert.equal(value, currentDate.toISOString())
done(); done()
}); })
ipcRenderer.send('message', currentDate); ipcRenderer.send('message', currentDate)
}); })
}); })
describe('ipc.sendSync', function() { describe('ipc.sendSync', function () {
it('can be replied by setting event.returnValue', function() { it('can be replied by setting event.returnValue', function () {
var msg = ipcRenderer.sendSync('echo', 'test'); var msg = ipcRenderer.sendSync('echo', 'test')
assert.equal(msg, 'test'); assert.equal(msg, 'test')
}); })
it('does not crash when reply is not sent and browser is destroyed', function(done) { it('does not crash when reply is not sent and browser is destroyed', function (done) {
this.timeout(10000); this.timeout(10000)
var w = new BrowserWindow({ var w = new BrowserWindow({
show: false show: false
}); })
ipcMain.once('send-sync-message', function(event) { ipcMain.once('send-sync-message', function (event) {
event.returnValue = null; event.returnValue = null
w.destroy(); w.destroy()
done(); done()
}); })
w.loadURL('file://' + path.join(fixtures, 'api', 'send-sync-message.html')); w.loadURL('file://' + path.join(fixtures, 'api', 'send-sync-message.html'))
}); })
}); })
describe('remote listeners', function() { describe('remote listeners', function () {
var w = null; var w = null
afterEach(function() { afterEach(function () {
w.destroy(); w.destroy()
}); })
it('can be added and removed correctly', function() { it('can be added and removed correctly', function () {
w = new BrowserWindow({ w = new BrowserWindow({
show: false show: false
}); })
var listener = function() {}; var listener = function () {}
w.on('test', listener); w.on('test', listener)
assert.equal(w.listenerCount('test'), 1); assert.equal(w.listenerCount('test'), 1)
w.removeListener('test', listener); w.removeListener('test', listener)
assert.equal(w.listenerCount('test'), 0); assert.equal(w.listenerCount('test'), 0)
}); })
}); })
}); })

View file

@ -1,25 +1,25 @@
const assert = require('assert'); const assert = require('assert')
const remote = require('electron').remote; const remote = require('electron').remote
const ipcRenderer = require('electron').ipcRenderer; const ipcRenderer = require('electron').ipcRenderer
const Menu = remote.require('electron').Menu; const Menu = remote.require('electron').Menu
const MenuItem = remote.require('electron').MenuItem; const MenuItem = remote.require('electron').MenuItem
describe('menu module', function() { describe('menu module', function () {
describe('Menu.buildFromTemplate', function() { describe('Menu.buildFromTemplate', function () {
it('should be able to attach extra fields', function() { it('should be able to attach extra fields', function () {
var menu = Menu.buildFromTemplate([ var menu = Menu.buildFromTemplate([
{ {
label: 'text', label: 'text',
extra: 'field' extra: 'field'
} }
]); ])
assert.equal(menu.items[0].extra, 'field'); assert.equal(menu.items[0].extra, 'field')
}); })
it('does not modify the specified template', function() { it('does not modify the specified template', function () {
var template = ipcRenderer.sendSync('eval', "var template = [{label: 'text', submenu: [{label: 'sub'}]}];\nrequire('electron').Menu.buildFromTemplate(template);\ntemplate;"); var template = ipcRenderer.sendSync('eval', "var template = [{label: 'text', submenu: [{label: 'sub'}]}];\nrequire('electron').Menu.buildFromTemplate(template);\ntemplate;")
assert.deepStrictEqual(template, [ assert.deepStrictEqual(template, [
{ {
label: 'text', label: 'text',
@ -29,11 +29,11 @@ describe('menu module', function() {
} }
] ]
} }
]); ])
}); })
it('does not throw exceptions for undefined/null values', function() { it('does not throw exceptions for undefined/null values', function () {
assert.doesNotThrow(function() { assert.doesNotThrow(function () {
Menu.buildFromTemplate([ Menu.buildFromTemplate([
{ {
label: 'text', label: 'text',
@ -43,12 +43,12 @@ describe('menu module', function() {
label: 'text again', label: 'text again',
accelerator: null accelerator: null
} }
]); ])
}); })
}); })
describe('Menu.buildFromTemplate should reorder based on item position specifiers', function() { describe('Menu.buildFromTemplate should reorder based on item position specifiers', function () {
it('should position before existing item', function() { it('should position before existing item', function () {
var menu = Menu.buildFromTemplate([ var menu = Menu.buildFromTemplate([
{ {
label: '2', label: '2',
@ -61,13 +61,13 @@ describe('menu module', function() {
id: '1', id: '1',
position: 'before=2' position: 'before=2'
} }
]); ])
assert.equal(menu.items[0].label, '1'); assert.equal(menu.items[0].label, '1')
assert.equal(menu.items[1].label, '2'); assert.equal(menu.items[1].label, '2')
assert.equal(menu.items[2].label, '3'); assert.equal(menu.items[2].label, '3')
}); })
it('should position after existing item', function() { it('should position after existing item', function () {
var menu = Menu.buildFromTemplate([ var menu = Menu.buildFromTemplate([
{ {
label: '1', label: '1',
@ -80,13 +80,13 @@ describe('menu module', function() {
id: '2', id: '2',
position: 'after=1' position: 'after=1'
} }
]); ])
assert.equal(menu.items[0].label, '1'); assert.equal(menu.items[0].label, '1')
assert.equal(menu.items[1].label, '2'); assert.equal(menu.items[1].label, '2')
assert.equal(menu.items[2].label, '3'); assert.equal(menu.items[2].label, '3')
}); })
it('should position at endof existing separator groups', function() { it('should position at endof existing separator groups', function () {
var menu = Menu.buildFromTemplate([ var menu = Menu.buildFromTemplate([
{ {
type: 'separator', type: 'separator',
@ -119,18 +119,18 @@ describe('menu module', function() {
id: '3', id: '3',
position: 'endof=numbers' position: 'endof=numbers'
} }
]); ])
assert.equal(menu.items[0].id, 'numbers'); assert.equal(menu.items[0].id, 'numbers')
assert.equal(menu.items[1].label, '1'); assert.equal(menu.items[1].label, '1')
assert.equal(menu.items[2].label, '2'); assert.equal(menu.items[2].label, '2')
assert.equal(menu.items[3].label, '3'); assert.equal(menu.items[3].label, '3')
assert.equal(menu.items[4].id, 'letters'); assert.equal(menu.items[4].id, 'letters')
assert.equal(menu.items[5].label, 'a'); assert.equal(menu.items[5].label, 'a')
assert.equal(menu.items[6].label, 'b'); assert.equal(menu.items[6].label, 'b')
assert.equal(menu.items[7].label, 'c'); assert.equal(menu.items[7].label, 'c')
}); })
it('should create separator group if endof does not reference existing separator group', function() { it('should create separator group if endof does not reference existing separator group', function () {
var menu = Menu.buildFromTemplate([ var menu = Menu.buildFromTemplate([
{ {
label: 'a', label: 'a',
@ -157,18 +157,18 @@ describe('menu module', function() {
id: '3', id: '3',
position: 'endof=numbers' position: 'endof=numbers'
} }
]); ])
assert.equal(menu.items[0].id, 'letters'); assert.equal(menu.items[0].id, 'letters')
assert.equal(menu.items[1].label, 'a'); assert.equal(menu.items[1].label, 'a')
assert.equal(menu.items[2].label, 'b'); assert.equal(menu.items[2].label, 'b')
assert.equal(menu.items[3].label, 'c'); assert.equal(menu.items[3].label, 'c')
assert.equal(menu.items[4].id, 'numbers'); assert.equal(menu.items[4].id, 'numbers')
assert.equal(menu.items[5].label, '1'); assert.equal(menu.items[5].label, '1')
assert.equal(menu.items[6].label, '2'); assert.equal(menu.items[6].label, '2')
assert.equal(menu.items[7].label, '3'); assert.equal(menu.items[7].label, '3')
}); })
it('should continue inserting items at next index when no specifier is present', function() { it('should continue inserting items at next index when no specifier is present', function () {
var menu = Menu.buildFromTemplate([ var menu = Menu.buildFromTemplate([
{ {
label: '4', label: '4',
@ -187,18 +187,18 @@ describe('menu module', function() {
label: '3', label: '3',
id: '3' id: '3'
} }
]); ])
assert.equal(menu.items[0].label, '1'); assert.equal(menu.items[0].label, '1')
assert.equal(menu.items[1].label, '2'); assert.equal(menu.items[1].label, '2')
assert.equal(menu.items[2].label, '3'); assert.equal(menu.items[2].label, '3')
assert.equal(menu.items[3].label, '4'); assert.equal(menu.items[3].label, '4')
assert.equal(menu.items[4].label, '5'); assert.equal(menu.items[4].label, '5')
}); })
}); })
}); })
describe('Menu.insert', function() { describe('Menu.insert', function () {
it('should store item in @items by its index', function() { it('should store item in @items by its index', function () {
var menu = Menu.buildFromTemplate([ var menu = Menu.buildFromTemplate([
{ {
label: '1' label: '1'
@ -207,156 +207,156 @@ describe('menu module', function() {
}, { }, {
label: '3' label: '3'
} }
]); ])
var item = new MenuItem({ var item = new MenuItem({
label: 'inserted' label: 'inserted'
}); })
menu.insert(1, item); menu.insert(1, item)
assert.equal(menu.items[0].label, '1'); assert.equal(menu.items[0].label, '1')
assert.equal(menu.items[1].label, 'inserted'); assert.equal(menu.items[1].label, 'inserted')
assert.equal(menu.items[2].label, '2'); assert.equal(menu.items[2].label, '2')
assert.equal(menu.items[3].label, '3'); assert.equal(menu.items[3].label, '3')
}); })
}); })
describe('MenuItem.click', function() { describe('MenuItem.click', function () {
it('should be called with the item object passed', function(done) { it('should be called with the item object passed', function (done) {
var menu = Menu.buildFromTemplate([ var menu = Menu.buildFromTemplate([
{ {
label: 'text', label: 'text',
click: function(item) { click: function (item) {
assert.equal(item.constructor.name, 'MenuItem'); assert.equal(item.constructor.name, 'MenuItem')
assert.equal(item.label, 'text'); assert.equal(item.label, 'text')
done(); done()
} }
} }
]); ])
menu.delegate.executeCommand(menu.items[0].commandId); menu.delegate.executeCommand(menu.items[0].commandId)
}); })
}); })
describe('MenuItem with checked property', function() { describe('MenuItem with checked property', function () {
it('clicking an checkbox item should flip the checked property', function() { it('clicking an checkbox item should flip the checked property', function () {
var menu = Menu.buildFromTemplate([ var menu = Menu.buildFromTemplate([
{ {
label: 'text', label: 'text',
type: 'checkbox' type: 'checkbox'
} }
]); ])
assert.equal(menu.items[0].checked, false); assert.equal(menu.items[0].checked, false)
menu.delegate.executeCommand(menu.items[0].commandId); menu.delegate.executeCommand(menu.items[0].commandId)
assert.equal(menu.items[0].checked, true); assert.equal(menu.items[0].checked, true)
}); })
it('clicking an radio item should always make checked property true', function() { it('clicking an radio item should always make checked property true', function () {
var menu = Menu.buildFromTemplate([ var menu = Menu.buildFromTemplate([
{ {
label: 'text', label: 'text',
type: 'radio' type: 'radio'
} }
]); ])
menu.delegate.executeCommand(menu.items[0].commandId); menu.delegate.executeCommand(menu.items[0].commandId)
assert.equal(menu.items[0].checked, true); assert.equal(menu.items[0].checked, true)
menu.delegate.executeCommand(menu.items[0].commandId); menu.delegate.executeCommand(menu.items[0].commandId)
assert.equal(menu.items[0].checked, true); assert.equal(menu.items[0].checked, true)
}); })
it('at least have one item checked in each group', function() { it('at least have one item checked in each group', function () {
var i, j, k, menu, template; var i, j, k, menu, template
template = []; template = []
for (i = j = 0; j <= 10; i = ++j) { for (i = j = 0; j <= 10; i = ++j) {
template.push({ template.push({
label: "" + i, label: '' + i,
type: 'radio' type: 'radio'
}); })
} }
template.push({ template.push({
type: 'separator' type: 'separator'
}); })
for (i = k = 12; k <= 20; i = ++k) { for (i = k = 12; k <= 20; i = ++k) {
template.push({ template.push({
label: "" + i, label: '' + i,
type: 'radio' type: 'radio'
}); })
} }
menu = Menu.buildFromTemplate(template); menu = Menu.buildFromTemplate(template)
menu.delegate.menuWillShow(); menu.delegate.menuWillShow()
assert.equal(menu.items[0].checked, true); assert.equal(menu.items[0].checked, true)
assert.equal(menu.items[12].checked, true); assert.equal(menu.items[12].checked, true)
}); })
it('should assign groupId automatically', function() { it('should assign groupId automatically', function () {
var groupId, i, j, k, l, m, menu, template; var groupId, i, j, k, l, m, menu, template
template = []; template = []
for (i = j = 0; j <= 10; i = ++j) { for (i = j = 0; j <= 10; i = ++j) {
template.push({ template.push({
label: "" + i, label: '' + i,
type: 'radio' type: 'radio'
}); })
} }
template.push({ template.push({
type: 'separator' type: 'separator'
}); })
for (i = k = 12; k <= 20; i = ++k) { for (i = k = 12; k <= 20; i = ++k) {
template.push({ template.push({
label: "" + i, label: '' + i,
type: 'radio' type: 'radio'
}); })
} }
menu = Menu.buildFromTemplate(template); menu = Menu.buildFromTemplate(template)
groupId = menu.items[0].groupId; groupId = menu.items[0].groupId
for (i = l = 0; l <= 10; i = ++l) { for (i = l = 0; l <= 10; i = ++l) {
assert.equal(menu.items[i].groupId, groupId); assert.equal(menu.items[i].groupId, groupId)
} }
for (i = m = 12; m <= 20; i = ++m) { for (i = m = 12; m <= 20; i = ++m) {
assert.equal(menu.items[i].groupId, groupId + 1); assert.equal(menu.items[i].groupId, groupId + 1)
} }
}); })
it("setting 'checked' should flip other items' 'checked' property", function() { it("setting 'checked' should flip other items' 'checked' property", function () {
var i, j, k, l, m, menu, n, o, p, q, template; var i, j, k, l, m, menu, n, o, p, q, template
template = []; template = []
for (i = j = 0; j <= 10; i = ++j) { for (i = j = 0; j <= 10; i = ++j) {
template.push({ template.push({
label: "" + i, label: '' + i,
type: 'radio' type: 'radio'
}); })
} }
template.push({ template.push({
type: 'separator' type: 'separator'
}); })
for (i = k = 12; k <= 20; i = ++k) { for (i = k = 12; k <= 20; i = ++k) {
template.push({ template.push({
label: "" + i, label: '' + i,
type: 'radio' type: 'radio'
}); })
} }
menu = Menu.buildFromTemplate(template); menu = Menu.buildFromTemplate(template)
for (i = l = 0; l <= 10; i = ++l) { for (i = l = 0; l <= 10; i = ++l) {
assert.equal(menu.items[i].checked, false); assert.equal(menu.items[i].checked, false)
} }
menu.items[0].checked = true; menu.items[0].checked = true
assert.equal(menu.items[0].checked, true); assert.equal(menu.items[0].checked, true)
for (i = m = 1; m <= 10; i = ++m) { for (i = m = 1; m <= 10; i = ++m) {
assert.equal(menu.items[i].checked, false); assert.equal(menu.items[i].checked, false)
} }
menu.items[10].checked = true; menu.items[10].checked = true
assert.equal(menu.items[10].checked, true); assert.equal(menu.items[10].checked, true)
for (i = n = 0; n <= 9; i = ++n) { for (i = n = 0; n <= 9; i = ++n) {
assert.equal(menu.items[i].checked, false); assert.equal(menu.items[i].checked, false)
} }
for (i = o = 12; o <= 20; i = ++o) { for (i = o = 12; o <= 20; i = ++o) {
assert.equal(menu.items[i].checked, false); assert.equal(menu.items[i].checked, false)
} }
menu.items[12].checked = true; menu.items[12].checked = true
assert.equal(menu.items[10].checked, true); assert.equal(menu.items[10].checked, true)
for (i = p = 0; p <= 9; i = ++p) { for (i = p = 0; p <= 9; i = ++p) {
assert.equal(menu.items[i].checked, false); assert.equal(menu.items[i].checked, false)
} }
assert.equal(menu.items[12].checked, true); assert.equal(menu.items[12].checked, true)
for (i = q = 13; q <= 20; i = ++q) { for (i = q = 13; q <= 20; i = ++q) {
assert.equal(menu.items[i].checked, false); assert.equal(menu.items[i].checked, false)
} }
}); })
}); })
}); })

View file

@ -1,51 +1,51 @@
'use strict'; 'use strict'
const assert = require('assert'); const assert = require('assert')
const nativeImage = require('electron').nativeImage; const nativeImage = require('electron').nativeImage
const path = require('path'); const path = require('path')
describe('nativeImage module', () => { describe('nativeImage module', () => {
describe('createFromPath(path)', () => { describe('createFromPath(path)', () => {
it('returns an empty image for invalid paths', () => { it('returns an empty image for invalid paths', () => {
assert(nativeImage.createFromPath('').isEmpty()); assert(nativeImage.createFromPath('').isEmpty())
assert(nativeImage.createFromPath('does-not-exist.png').isEmpty()); assert(nativeImage.createFromPath('does-not-exist.png').isEmpty())
}); })
it('loads images from paths relative to the current working directory', () => { it('loads images from paths relative to the current working directory', () => {
const imagePath = `.${path.sep}${path.join('spec', 'fixtures', 'assets', 'logo.png')}`; const imagePath = `.${path.sep}${path.join('spec', 'fixtures', 'assets', 'logo.png')}`
const image = nativeImage.createFromPath(imagePath); const image = nativeImage.createFromPath(imagePath)
assert(!image.isEmpty()); assert(!image.isEmpty())
assert.equal(image.getSize().height, 190); assert.equal(image.getSize().height, 190)
assert.equal(image.getSize().width, 538); assert.equal(image.getSize().width, 538)
}); })
it('loads images from paths with `.` segments', () => { it('loads images from paths with `.` segments', () => {
const imagePath = `${path.join(__dirname, 'fixtures')}${path.sep}.${path.sep}${path.join('assets', 'logo.png')}`; const imagePath = `${path.join(__dirname, 'fixtures')}${path.sep}.${path.sep}${path.join('assets', 'logo.png')}`
const image = nativeImage.createFromPath(imagePath); const image = nativeImage.createFromPath(imagePath)
assert(!image.isEmpty()); assert(!image.isEmpty())
assert.equal(image.getSize().height, 190); assert.equal(image.getSize().height, 190)
assert.equal(image.getSize().width, 538); assert.equal(image.getSize().width, 538)
}); })
it('loads images from paths with `..` segments', () => { it('loads images from paths with `..` segments', () => {
const imagePath = `${path.join(__dirname, 'fixtures', 'api')}${path.sep}..${path.sep}${path.join('assets', 'logo.png')}`; const imagePath = `${path.join(__dirname, 'fixtures', 'api')}${path.sep}..${path.sep}${path.join('assets', 'logo.png')}`
const image = nativeImage.createFromPath(imagePath); const image = nativeImage.createFromPath(imagePath)
assert(!image.isEmpty()); assert(!image.isEmpty())
assert.equal(image.getSize().height, 190); assert.equal(image.getSize().height, 190)
assert.equal(image.getSize().width, 538); assert.equal(image.getSize().width, 538)
}); })
it('Gets an NSImage pointer on OS X', () => { it('Gets an NSImage pointer on OS X', () => {
if (process.platform !== 'darwin') return; if (process.platform !== 'darwin') return
const imagePath = `${path.join(__dirname, 'fixtures', 'api')}${path.sep}..${path.sep}${path.join('assets', 'logo.png')}`; const imagePath = `${path.join(__dirname, 'fixtures', 'api')}${path.sep}..${path.sep}${path.join('assets', 'logo.png')}`
const image = nativeImage.createFromPath(imagePath); const image = nativeImage.createFromPath(imagePath)
const nsimage = image.getNativeHandle(); const nsimage = image.getNativeHandle()
assert.equal(nsimage.length, 8); assert.equal(nsimage.length, 8)
// If all bytes are null, that's Bad // If all bytes are null, that's Bad
assert.equal(nsimage.reduce((acc,x) => acc || (x != 0), false), true); assert.equal(nsimage.reduce((acc, x) => acc || (x !== 0), false), true)
}); })
}); })
}); })

File diff suppressed because it is too large Load diff

View file

@ -1,21 +1,21 @@
const assert = require('assert'); const assert = require('assert')
const screen = require('electron').screen; const screen = require('electron').screen
describe('screen module', function() { describe('screen module', function () {
describe('screen.getCursorScreenPoint()', function() { describe('screen.getCursorScreenPoint()', function () {
it('returns a point object', function() { it('returns a point object', function () {
var point = screen.getCursorScreenPoint(); var point = screen.getCursorScreenPoint()
assert.equal(typeof point.x, 'number'); assert.equal(typeof point.x, 'number')
assert.equal(typeof point.y, 'number'); assert.equal(typeof point.y, 'number')
}); })
}); })
describe('screen.getPrimaryDisplay()', function() { describe('screen.getPrimaryDisplay()', function () {
it('returns a display object', function() { it('returns a display object', function () {
var display = screen.getPrimaryDisplay(); var display = screen.getPrimaryDisplay()
assert.equal(typeof display.scaleFactor, 'number'); assert.equal(typeof display.scaleFactor, 'number')
assert(display.size.width > 0); assert(display.size.width > 0)
assert(display.size.height > 0); assert(display.size.height > 0)
}); })
}); })
}); })

View file

@ -1,265 +1,265 @@
const assert = require('assert'); const assert = require('assert')
const http = require('http'); const http = require('http')
const path = require('path'); const path = require('path')
const fs = require('fs'); const fs = require('fs')
const ipcRenderer = require('electron').ipcRenderer; const ipcRenderer = require('electron').ipcRenderer
const remote = require('electron').remote; const remote = require('electron').remote
const ipcMain = remote.ipcMain; const ipcMain = remote.ipcMain
const session = remote.session; const session = remote.session
const BrowserWindow = remote.BrowserWindow; const BrowserWindow = remote.BrowserWindow
describe('session module', function() { describe('session module', function () {
this.timeout(10000); this.timeout(10000)
var fixtures = path.resolve(__dirname, 'fixtures'); var fixtures = path.resolve(__dirname, 'fixtures')
var w = null; var w = null
var url = "http://127.0.0.1"; var url = 'http://127.0.0.1'
beforeEach(function() { beforeEach(function () {
w = new BrowserWindow({ w = new BrowserWindow({
show: false, show: false,
width: 400, width: 400,
height: 400 height: 400
}); })
}); })
afterEach(function() { afterEach(function () {
w.destroy(); w.destroy()
}); })
describe('session.cookies', function() { describe('session.cookies', function () {
it('should get cookies', function(done) { it('should get cookies', function (done) {
var server = http.createServer(function(req, res) { var server = http.createServer(function (req, res) {
res.setHeader('Set-Cookie', ['0=0']); res.setHeader('Set-Cookie', ['0=0'])
res.end('finished'); res.end('finished')
server.close(); server.close()
}); })
server.listen(0, '127.0.0.1', function() { server.listen(0, '127.0.0.1', function () {
var port = server.address().port; var port = server.address().port
w.loadURL(url + ":" + port); w.loadURL(url + ':' + port)
w.webContents.on('did-finish-load', function() { w.webContents.on('did-finish-load', function () {
w.webContents.session.cookies.get({ w.webContents.session.cookies.get({
url: url url: url
}, function(error, list) { }, function (error, list) {
var cookie, i, len; var cookie, i, len
if (error) { if (error) {
return done(error); return done(error)
} }
for (i = 0, len = list.length; i < len; i++) { for (i = 0, len = list.length; i < len; i++) {
cookie = list[i]; cookie = list[i]
if (cookie.name === '0') { if (cookie.name === '0') {
if (cookie.value === '0') { if (cookie.value === '0') {
return done(); return done()
} else { } else {
return done("cookie value is " + cookie.value + " while expecting 0"); return done('cookie value is ' + cookie.value + ' while expecting 0')
} }
} }
} }
done('Can not find cookie'); done('Can not find cookie')
}); })
}); })
}); })
}); })
it('should over-write the existent cookie', function(done) { it('should over-write the existent cookie', function (done) {
session.defaultSession.cookies.set({ session.defaultSession.cookies.set({
url: url, url: url,
name: '1', name: '1',
value: '1' value: '1'
}, function(error) { }, function (error) {
if (error) { if (error) {
return done(error); return done(error)
} }
session.defaultSession.cookies.get({ session.defaultSession.cookies.get({
url: url url: url
}, function(error, list) { }, function (error, list) {
var cookie, i, len; var cookie, i, len
if (error) { if (error) {
return done(error); return done(error)
} }
for (i = 0, len = list.length; i < len; i++) { for (i = 0, len = list.length; i < len; i++) {
cookie = list[i]; cookie = list[i]
if (cookie.name === '1') { if (cookie.name === '1') {
if (cookie.value === '1') { if (cookie.value === '1') {
return done(); return done()
} else { } else {
return done("cookie value is " + cookie.value + " while expecting 1"); return done('cookie value is ' + cookie.value + ' while expecting 1')
} }
} }
} }
done('Can not find cookie'); done('Can not find cookie')
}); })
}); })
}); })
it('should remove cookies', function(done) { it('should remove cookies', function (done) {
session.defaultSession.cookies.set({ session.defaultSession.cookies.set({
url: url, url: url,
name: '2', name: '2',
value: '2' value: '2'
}, function(error) { }, function (error) {
if (error) { if (error) {
return done(error); return done(error)
} }
session.defaultSession.cookies.remove(url, '2', function() { session.defaultSession.cookies.remove(url, '2', function () {
session.defaultSession.cookies.get({ session.defaultSession.cookies.get({
url: url url: url
}, function(error, list) { }, function (error, list) {
var cookie, i, len; var cookie, i, len
if (error) { if (error) {
return done(error); return done(error)
} }
for (i = 0, len = list.length; i < len; i++) { for (i = 0, len = list.length; i < len; i++) {
cookie = list[i]; cookie = list[i]
if (cookie.name === '2') { if (cookie.name === '2') {
return done('Cookie not deleted'); return done('Cookie not deleted')
} }
} }
done(); done()
}); })
}); })
}); })
}); })
}); })
describe('session.clearStorageData(options)', function() { describe('session.clearStorageData(options)', function () {
fixtures = path.resolve(__dirname, 'fixtures'); fixtures = path.resolve(__dirname, 'fixtures')
it('clears localstorage data', function(done) { it('clears localstorage data', function (done) {
ipcMain.on('count', function(event, count) { ipcMain.on('count', function (event, count) {
ipcMain.removeAllListeners('count'); ipcMain.removeAllListeners('count')
assert(!count); assert(!count)
done(); done()
}); })
w.loadURL('file://' + path.join(fixtures, 'api', 'localstorage.html')); w.loadURL('file://' + path.join(fixtures, 'api', 'localstorage.html'))
w.webContents.on('did-finish-load', function() { w.webContents.on('did-finish-load', function () {
var options = { var options = {
origin: "file://", origin: 'file://',
storages: ['localstorage'], storages: ['localstorage'],
quotas: ['persistent'] quotas: ['persistent']
}; }
w.webContents.session.clearStorageData(options, function() { w.webContents.session.clearStorageData(options, function () {
w.webContents.send('getcount'); w.webContents.send('getcount')
}); })
}); })
}); })
}); })
describe('session will-download event', function() { describe('session will-download event', function () {
var w = null; var w = null
beforeEach(function() { beforeEach(function () {
w = new BrowserWindow({ w = new BrowserWindow({
show: false, show: false,
width: 400, width: 400,
height: 400 height: 400
}); })
}); })
afterEach(function() { afterEach(function () {
w.destroy(); w.destroy()
}); })
it('can cancel default download behavior', function(done) { it('can cancel default download behavior', function (done) {
const mockFile = new Buffer(1024); const mockFile = new Buffer(1024)
const contentDisposition = 'inline; filename="mockFile.txt"'; const contentDisposition = 'inline; filename="mockFile.txt"'
const downloadServer = http.createServer(function(req, res) { const downloadServer = http.createServer(function (req, res) {
res.writeHead(200, { res.writeHead(200, {
'Content-Length': mockFile.length, 'Content-Length': mockFile.length,
'Content-Type': 'application/plain', 'Content-Type': 'application/plain',
'Content-Disposition': contentDisposition 'Content-Disposition': contentDisposition
}); })
res.end(mockFile); res.end(mockFile)
downloadServer.close(); downloadServer.close()
}); })
downloadServer.listen(0, '127.0.0.1', function() { downloadServer.listen(0, '127.0.0.1', function () {
const port = downloadServer.address().port; const port = downloadServer.address().port
const url = "http://127.0.0.1:" + port + '/'; const url = 'http://127.0.0.1:' + port + '/'
ipcRenderer.sendSync('set-download-option', false, true); ipcRenderer.sendSync('set-download-option', false, true)
w.loadURL(url); w.loadURL(url)
ipcRenderer.once('download-error', function(event, downloadUrl, filename, error) { ipcRenderer.once('download-error', function (event, downloadUrl, filename, error) {
assert.equal(downloadUrl, url); assert.equal(downloadUrl, url)
assert.equal(filename, 'mockFile.txt'); assert.equal(filename, 'mockFile.txt')
assert.equal(error, 'Object has been destroyed'); assert.equal(error, 'Object has been destroyed')
done(); done()
}); })
}); })
}); })
}); })
describe('DownloadItem', function() { describe('DownloadItem', function () {
var mockPDF = new Buffer(1024 * 1024 * 5); var mockPDF = new Buffer(1024 * 1024 * 5)
var contentDisposition = 'inline; filename="mock.pdf"'; var contentDisposition = 'inline; filename="mock.pdf"'
var downloadFilePath = path.join(fixtures, 'mock.pdf'); var downloadFilePath = path.join(fixtures, 'mock.pdf')
var downloadServer = http.createServer(function(req, res) { var downloadServer = http.createServer(function (req, res) {
res.writeHead(200, { res.writeHead(200, {
'Content-Length': mockPDF.length, 'Content-Length': mockPDF.length,
'Content-Type': 'application/pdf', 'Content-Type': 'application/pdf',
'Content-Disposition': contentDisposition 'Content-Disposition': contentDisposition
}); })
res.end(mockPDF); res.end(mockPDF)
downloadServer.close(); downloadServer.close()
}); })
var assertDownload = function(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename, port) { var assertDownload = function (event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename, port) {
assert.equal(state, 'completed'); assert.equal(state, 'completed')
assert.equal(filename, 'mock.pdf'); assert.equal(filename, 'mock.pdf')
assert.equal(url, "http://127.0.0.1:" + port + "/"); assert.equal(url, 'http://127.0.0.1:' + port + '/')
assert.equal(mimeType, 'application/pdf'); assert.equal(mimeType, 'application/pdf')
assert.equal(receivedBytes, mockPDF.length); assert.equal(receivedBytes, mockPDF.length)
assert.equal(totalBytes, mockPDF.length); assert.equal(totalBytes, mockPDF.length)
assert.equal(disposition, contentDisposition); assert.equal(disposition, contentDisposition)
assert(fs.existsSync(downloadFilePath)); assert(fs.existsSync(downloadFilePath))
fs.unlinkSync(downloadFilePath); fs.unlinkSync(downloadFilePath)
}; }
it('can download using BrowserWindow.loadURL', function(done) { it('can download using BrowserWindow.loadURL', function (done) {
downloadServer.listen(0, '127.0.0.1', function() { downloadServer.listen(0, '127.0.0.1', function () {
var port = downloadServer.address().port; var port = downloadServer.address().port
ipcRenderer.sendSync('set-download-option', false, false); ipcRenderer.sendSync('set-download-option', false, false)
w.loadURL(url + ":" + port); w.loadURL(url + ':' + port)
ipcRenderer.once('download-done', function(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) { ipcRenderer.once('download-done', function (event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) {
assertDownload(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename, port); assertDownload(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename, port)
done(); done()
}); })
}); })
}); })
it('can download using WebView.downloadURL', function(done) { it('can download using WebView.downloadURL', function (done) {
downloadServer.listen(0, '127.0.0.1', function() { downloadServer.listen(0, '127.0.0.1', function () {
var port = downloadServer.address().port; var port = downloadServer.address().port
ipcRenderer.sendSync('set-download-option', false, false); ipcRenderer.sendSync('set-download-option', false, false)
var webview = new WebView; var webview = new WebView()
webview.src = "file://" + fixtures + "/api/blank.html"; webview.src = 'file://' + fixtures + '/api/blank.html'
webview.addEventListener('did-finish-load', function() { webview.addEventListener('did-finish-load', function () {
webview.downloadURL(url + ":" + port + "/"); webview.downloadURL(url + ':' + port + '/')
}); })
ipcRenderer.once('download-done', function(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) { ipcRenderer.once('download-done', function (event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) {
assertDownload(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename, port); assertDownload(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename, port)
document.body.removeChild(webview); document.body.removeChild(webview)
done(); done()
}); })
document.body.appendChild(webview); document.body.appendChild(webview)
}); })
}); })
it('can cancel download', function(done) { it('can cancel download', function (done) {
downloadServer.listen(0, '127.0.0.1', function() { downloadServer.listen(0, '127.0.0.1', function () {
var port = downloadServer.address().port; var port = downloadServer.address().port
ipcRenderer.sendSync('set-download-option', true, false); ipcRenderer.sendSync('set-download-option', true, false)
w.loadURL(url + ":" + port + "/"); w.loadURL(url + ':' + port + '/')
ipcRenderer.once('download-done', function(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) { ipcRenderer.once('download-done', function (event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) {
assert.equal(state, 'cancelled'); assert.equal(state, 'cancelled')
assert.equal(filename, 'mock.pdf'); assert.equal(filename, 'mock.pdf')
assert.equal(mimeType, 'application/pdf'); assert.equal(mimeType, 'application/pdf')
assert.equal(receivedBytes, 0); assert.equal(receivedBytes, 0)
assert.equal(totalBytes, mockPDF.length); assert.equal(totalBytes, mockPDF.length)
assert.equal(disposition, contentDisposition); assert.equal(disposition, contentDisposition)
done(); done()
}); })
}); })
}); })
}); })
}); })

View file

@ -1,19 +1,19 @@
const assert = require('assert'); const assert = require('assert')
const path = require('path'); const path = require('path')
const webFrame = require('electron').webFrame; const webFrame = require('electron').webFrame
describe('webFrame module', function() { describe('webFrame module', function () {
var fixtures = path.resolve(__dirname, 'fixtures'); var fixtures = path.resolve(__dirname, 'fixtures')
describe('webFrame.registerURLSchemeAsPrivileged', function() { describe('webFrame.registerURLSchemeAsPrivileged', function () {
it('supports fetch api', function(done) { it('supports fetch api', function (done) {
webFrame.registerURLSchemeAsPrivileged('file'); webFrame.registerURLSchemeAsPrivileged('file')
var url = "file://" + fixtures + "/assets/logo.png"; var url = 'file://' + fixtures + '/assets/logo.png'
fetch(url).then(function(response) { window.fetch(url).then(function (response) {
assert(response.ok); assert(response.ok)
done(); done()
}).catch(function(err) { }).catch(function (err) {
done('unexpected error : ' + err); done('unexpected error : ' + err)
}); })
}); })
}); })
}); })

View file

@ -1,413 +1,412 @@
const assert = require('assert'); const assert = require('assert')
const http = require('http'); const http = require('http')
const qs = require('querystring'); const qs = require('querystring')
const remote = require('electron').remote; const remote = require('electron').remote
const session = remote.session; const session = remote.session
describe('webRequest module', function() { describe('webRequest module', function () {
var ses = session.defaultSession; var ses = session.defaultSession
var server = http.createServer(function(req, res) { var server = http.createServer(function (req, res) {
res.setHeader('Custom', ['Header']); res.setHeader('Custom', ['Header'])
var content = req.url; var content = req.url
if (req.headers.accept === '*/*;test/header') { if (req.headers.accept === '*/*;test/header') {
content += 'header/received'; content += 'header/received'
} }
res.end(content); res.end(content)
}); })
var defaultURL = null; var defaultURL = null
before(function(done) { before(function (done) {
server.listen(0, '127.0.0.1', function() { server.listen(0, '127.0.0.1', function () {
var port = server.address().port; var port = server.address().port
defaultURL = "http://127.0.0.1:" + port + "/"; defaultURL = 'http://127.0.0.1:' + port + '/'
done(); done()
}); })
}); })
after(function() { after(function () {
server.close(); server.close()
}); })
describe('webRequest.onBeforeRequest', function() { describe('webRequest.onBeforeRequest', function () {
afterEach(function() { afterEach(function () {
ses.webRequest.onBeforeRequest(null); ses.webRequest.onBeforeRequest(null)
}); })
it('can cancel the request', function(done) { it('can cancel the request', function (done) {
ses.webRequest.onBeforeRequest(function(details, callback) { ses.webRequest.onBeforeRequest(function (details, callback) {
callback({ callback({
cancel: true cancel: true
}); })
}); })
$.ajax({ $.ajax({
url: defaultURL, url: defaultURL,
success: function() { success: function () {
done('unexpected success'); done('unexpected success')
}, },
error: function() { error: function () {
done(); done()
} }
}); })
}); })
it('can filter URLs', function(done) { it('can filter URLs', function (done) {
var filter = { var filter = {
urls: [defaultURL + "filter/*"] urls: [defaultURL + 'filter/*']
}; }
ses.webRequest.onBeforeRequest(filter, function(details, callback) { ses.webRequest.onBeforeRequest(filter, function (details, callback) {
callback({ callback({
cancel: true cancel: true
}); })
}); })
$.ajax({ $.ajax({
url: defaultURL + "nofilter/test", url: defaultURL + 'nofilter/test',
success: function(data) { success: function (data) {
assert.equal(data, '/nofilter/test'); assert.equal(data, '/nofilter/test')
$.ajax({ $.ajax({
url: defaultURL + "filter/test", url: defaultURL + 'filter/test',
success: function() { success: function () {
done('unexpected success'); done('unexpected success')
}, },
error: function() { error: function () {
done(); done()
} }
}); })
}, },
error: function(xhr, errorType) { error: function (xhr, errorType) {
done(errorType); done(errorType)
} }
}); })
}); })
it('receives details object', function(done) { it('receives details object', function (done) {
ses.webRequest.onBeforeRequest(function(details, callback) { ses.webRequest.onBeforeRequest(function (details, callback) {
assert.equal(typeof details.id, 'number'); assert.equal(typeof details.id, 'number')
assert.equal(typeof details.timestamp, 'number'); assert.equal(typeof details.timestamp, 'number')
assert.equal(details.url, defaultURL); assert.equal(details.url, defaultURL)
assert.equal(details.method, 'GET'); assert.equal(details.method, 'GET')
assert.equal(details.resourceType, 'xhr'); assert.equal(details.resourceType, 'xhr')
assert(!details.uploadData); assert(!details.uploadData)
callback({}); callback({})
}); })
$.ajax({ $.ajax({
url: defaultURL, url: defaultURL,
success: function(data) { success: function (data) {
assert.equal(data, '/'); assert.equal(data, '/')
done(); done()
}, },
error: function(xhr, errorType) { error: function (xhr, errorType) {
done(errorType); done(errorType)
} }
}); })
}); })
it('receives post data in details object', function(done) { it('receives post data in details object', function (done) {
var postData = { var postData = {
name: 'post test', name: 'post test',
type: 'string' type: 'string'
}; }
ses.webRequest.onBeforeRequest(function(details, callback) { ses.webRequest.onBeforeRequest(function (details, callback) {
assert.equal(details.url, defaultURL); assert.equal(details.url, defaultURL)
assert.equal(details.method, 'POST'); assert.equal(details.method, 'POST')
assert.equal(details.uploadData.length, 1); assert.equal(details.uploadData.length, 1)
var data = qs.parse(details.uploadData[0].bytes.toString()); var data = qs.parse(details.uploadData[0].bytes.toString())
assert.deepEqual(data, postData); assert.deepEqual(data, postData)
callback({ callback({
cancel: true cancel: true
}); })
}); })
$.ajax({ $.ajax({
url: defaultURL, url: defaultURL,
type: 'POST', type: 'POST',
data: postData, data: postData,
success: function() { success: function () {},
}, error: function () {
error: function() { done()
done();
} }
}); })
}); })
it('can redirect the request', function(done) { it('can redirect the request', function (done) {
ses.webRequest.onBeforeRequest(function(details, callback) { ses.webRequest.onBeforeRequest(function (details, callback) {
if (details.url === defaultURL) { if (details.url === defaultURL) {
callback({ callback({
redirectURL: defaultURL + "redirect" redirectURL: defaultURL + 'redirect'
}); })
} else { } else {
callback({}); callback({})
} }
}); })
$.ajax({ $.ajax({
url: defaultURL, url: defaultURL,
success: function(data) { success: function (data) {
assert.equal(data, '/redirect'); assert.equal(data, '/redirect')
done(); done()
}, },
error: function(xhr, errorType) { error: function (xhr, errorType) {
done(errorType); done(errorType)
} }
}); })
}); })
}); })
describe('webRequest.onBeforeSendHeaders', function() { describe('webRequest.onBeforeSendHeaders', function () {
afterEach(function() { afterEach(function () {
ses.webRequest.onBeforeSendHeaders(null); ses.webRequest.onBeforeSendHeaders(null)
}); })
it('receives details object', function(done) { it('receives details object', function (done) {
ses.webRequest.onBeforeSendHeaders(function(details, callback) { ses.webRequest.onBeforeSendHeaders(function (details, callback) {
assert.equal(typeof details.requestHeaders, 'object'); assert.equal(typeof details.requestHeaders, 'object')
callback({}); callback({})
}); })
$.ajax({ $.ajax({
url: defaultURL, url: defaultURL,
success: function(data) { success: function (data) {
assert.equal(data, '/'); assert.equal(data, '/')
done(); done()
}, },
error: function(xhr, errorType) { error: function (xhr, errorType) {
done(errorType); done(errorType)
} }
}); })
}); })
it('can change the request headers', function(done) { it('can change the request headers', function (done) {
ses.webRequest.onBeforeSendHeaders(function(details, callback) { ses.webRequest.onBeforeSendHeaders(function (details, callback) {
var requestHeaders = details.requestHeaders; var requestHeaders = details.requestHeaders
requestHeaders.Accept = '*/*;test/header'; requestHeaders.Accept = '*/*;test/header'
callback({ callback({
requestHeaders: requestHeaders requestHeaders: requestHeaders
}); })
}); })
$.ajax({ $.ajax({
url: defaultURL, url: defaultURL,
success: function(data) { success: function (data) {
assert.equal(data, '/header/received'); assert.equal(data, '/header/received')
done(); done()
}, },
error: function(xhr, errorType) { error: function (xhr, errorType) {
done(errorType); done(errorType)
} }
}); })
}); })
it('resets the whole headers', function(done) { it('resets the whole headers', function (done) {
var requestHeaders = { var requestHeaders = {
Test: 'header' Test: 'header'
}; }
ses.webRequest.onBeforeSendHeaders(function(details, callback) { ses.webRequest.onBeforeSendHeaders(function (details, callback) {
callback({ callback({
requestHeaders: requestHeaders requestHeaders: requestHeaders
}); })
}); })
ses.webRequest.onSendHeaders(function(details) { ses.webRequest.onSendHeaders(function (details) {
assert.deepEqual(details.requestHeaders, requestHeaders); assert.deepEqual(details.requestHeaders, requestHeaders)
done(); done()
}); })
$.ajax({ $.ajax({
url: defaultURL, url: defaultURL,
error: function(xhr, errorType) { error: function (xhr, errorType) {
done(errorType); done(errorType)
} }
}); })
}); })
}); })
describe('webRequest.onSendHeaders', function() { describe('webRequest.onSendHeaders', function () {
afterEach(function() { afterEach(function () {
ses.webRequest.onSendHeaders(null); ses.webRequest.onSendHeaders(null)
}); })
it('receives details object', function(done) { it('receives details object', function (done) {
ses.webRequest.onSendHeaders(function(details) { ses.webRequest.onSendHeaders(function (details) {
assert.equal(typeof details.requestHeaders, 'object'); assert.equal(typeof details.requestHeaders, 'object')
}); })
$.ajax({ $.ajax({
url: defaultURL, url: defaultURL,
success: function(data) { success: function (data) {
assert.equal(data, '/'); assert.equal(data, '/')
done(); done()
}, },
error: function(xhr, errorType) { error: function (xhr, errorType) {
done(errorType); done(errorType)
} }
}); })
}); })
}); })
describe('webRequest.onHeadersReceived', function() { describe('webRequest.onHeadersReceived', function () {
afterEach(function() { afterEach(function () {
ses.webRequest.onHeadersReceived(null); ses.webRequest.onHeadersReceived(null)
}); })
it('receives details object', function(done) { it('receives details object', function (done) {
ses.webRequest.onHeadersReceived(function(details, callback) { ses.webRequest.onHeadersReceived(function (details, callback) {
assert.equal(details.statusLine, 'HTTP/1.1 200 OK'); assert.equal(details.statusLine, 'HTTP/1.1 200 OK')
assert.equal(details.statusCode, 200); assert.equal(details.statusCode, 200)
assert.equal(details.responseHeaders['Custom'], 'Header'); assert.equal(details.responseHeaders['Custom'], 'Header')
callback({}); callback({})
}); })
$.ajax({ $.ajax({
url: defaultURL, url: defaultURL,
success: function(data) { success: function (data) {
assert.equal(data, '/'); assert.equal(data, '/')
done(); done()
}, },
error: function(xhr, errorType) { error: function (xhr, errorType) {
done(errorType); done(errorType)
} }
}); })
}); })
it('can change the response header', function(done) { it('can change the response header', function (done) {
ses.webRequest.onHeadersReceived(function(details, callback) { ses.webRequest.onHeadersReceived(function (details, callback) {
var responseHeaders = details.responseHeaders; var responseHeaders = details.responseHeaders
responseHeaders['Custom'] = ['Changed']; responseHeaders['Custom'] = ['Changed']
callback({ callback({
responseHeaders: responseHeaders responseHeaders: responseHeaders
}); })
}); })
$.ajax({ $.ajax({
url: defaultURL, url: defaultURL,
success: function(data, status, xhr) { success: function (data, status, xhr) {
assert.equal(xhr.getResponseHeader('Custom'), 'Changed'); assert.equal(xhr.getResponseHeader('Custom'), 'Changed')
assert.equal(data, '/'); assert.equal(data, '/')
done(); done()
}, },
error: function(xhr, errorType) { error: function (xhr, errorType) {
done(errorType); done(errorType)
} }
}); })
}); })
it('does not change header by default', function(done) { it('does not change header by default', function (done) {
ses.webRequest.onHeadersReceived(function(details, callback) { ses.webRequest.onHeadersReceived(function (details, callback) {
callback({}); callback({})
}); })
$.ajax({ $.ajax({
url: defaultURL, url: defaultURL,
success: function(data, status, xhr) { success: function (data, status, xhr) {
assert.equal(xhr.getResponseHeader('Custom'), 'Header'); assert.equal(xhr.getResponseHeader('Custom'), 'Header')
assert.equal(data, '/'); assert.equal(data, '/')
done(); done()
}, },
error: function(xhr, errorType) { error: function (xhr, errorType) {
done(errorType); done(errorType)
} }
}); })
}); })
}); })
describe('webRequest.onResponseStarted', function() { describe('webRequest.onResponseStarted', function () {
afterEach(function() { afterEach(function () {
ses.webRequest.onResponseStarted(null); ses.webRequest.onResponseStarted(null)
}); })
it('receives details object', function(done) { it('receives details object', function (done) {
ses.webRequest.onResponseStarted(function(details) { ses.webRequest.onResponseStarted(function (details) {
assert.equal(typeof details.fromCache, 'boolean'); assert.equal(typeof details.fromCache, 'boolean')
assert.equal(details.statusLine, 'HTTP/1.1 200 OK'); assert.equal(details.statusLine, 'HTTP/1.1 200 OK')
assert.equal(details.statusCode, 200); assert.equal(details.statusCode, 200)
assert.equal(details.responseHeaders['Custom'], 'Header'); assert.equal(details.responseHeaders['Custom'], 'Header')
}); })
$.ajax({ $.ajax({
url: defaultURL, url: defaultURL,
success: function(data, status, xhr) { success: function (data, status, xhr) {
assert.equal(xhr.getResponseHeader('Custom'), 'Header'); assert.equal(xhr.getResponseHeader('Custom'), 'Header')
assert.equal(data, '/'); assert.equal(data, '/')
done(); done()
}, },
error: function(xhr, errorType) { error: function (xhr, errorType) {
done(errorType); done(errorType)
} }
}); })
}); })
}); })
describe('webRequest.onBeforeRedirect', function() { describe('webRequest.onBeforeRedirect', function () {
afterEach(function() { afterEach(function () {
ses.webRequest.onBeforeRedirect(null); ses.webRequest.onBeforeRedirect(null)
ses.webRequest.onBeforeRequest(null); ses.webRequest.onBeforeRequest(null)
}); })
it('receives details object', function(done) { it('receives details object', function (done) {
var redirectURL = defaultURL + "redirect"; var redirectURL = defaultURL + 'redirect'
ses.webRequest.onBeforeRequest(function(details, callback) { ses.webRequest.onBeforeRequest(function (details, callback) {
if (details.url === defaultURL) { if (details.url === defaultURL) {
callback({ callback({
redirectURL: redirectURL redirectURL: redirectURL
}); })
} else { } else {
callback({}); callback({})
} }
}); })
ses.webRequest.onBeforeRedirect(function(details) { ses.webRequest.onBeforeRedirect(function (details) {
assert.equal(typeof details.fromCache, 'boolean'); assert.equal(typeof details.fromCache, 'boolean')
assert.equal(details.statusLine, 'HTTP/1.1 307 Internal Redirect'); assert.equal(details.statusLine, 'HTTP/1.1 307 Internal Redirect')
assert.equal(details.statusCode, 307); assert.equal(details.statusCode, 307)
assert.equal(details.redirectURL, redirectURL); assert.equal(details.redirectURL, redirectURL)
}); })
$.ajax({ $.ajax({
url: defaultURL, url: defaultURL,
success: function(data) { success: function (data) {
assert.equal(data, '/redirect'); assert.equal(data, '/redirect')
done(); done()
}, },
error: function(xhr, errorType) { error: function (xhr, errorType) {
done(errorType); done(errorType)
} }
}); })
}); })
}); })
describe('webRequest.onCompleted', function() { describe('webRequest.onCompleted', function () {
afterEach(function() { afterEach(function () {
ses.webRequest.onCompleted(null); ses.webRequest.onCompleted(null)
}); })
it('receives details object', function(done) { it('receives details object', function (done) {
ses.webRequest.onCompleted(function(details) { ses.webRequest.onCompleted(function (details) {
assert.equal(typeof details.fromCache, 'boolean'); assert.equal(typeof details.fromCache, 'boolean')
assert.equal(details.statusLine, 'HTTP/1.1 200 OK'); assert.equal(details.statusLine, 'HTTP/1.1 200 OK')
assert.equal(details.statusCode, 200); assert.equal(details.statusCode, 200)
}); })
$.ajax({ $.ajax({
url: defaultURL, url: defaultURL,
success: function(data) { success: function (data) {
assert.equal(data, '/'); assert.equal(data, '/')
done(); done()
}, },
error: function(xhr, errorType) { error: function (xhr, errorType) {
done(errorType); done(errorType)
} }
}); })
}); })
}); })
describe('webRequest.onErrorOccurred', function() { describe('webRequest.onErrorOccurred', function () {
afterEach(function() { afterEach(function () {
ses.webRequest.onErrorOccurred(null); ses.webRequest.onErrorOccurred(null)
ses.webRequest.onBeforeRequest(null); ses.webRequest.onBeforeRequest(null)
}); })
it('receives details object', function(done) { it('receives details object', function (done) {
ses.webRequest.onBeforeRequest(function(details, callback) { ses.webRequest.onBeforeRequest(function (details, callback) {
callback({ callback({
cancel: true cancel: true
}); })
}); })
ses.webRequest.onErrorOccurred(function(details) { ses.webRequest.onErrorOccurred(function (details) {
assert.equal(details.error, 'net::ERR_BLOCKED_BY_CLIENT'); assert.equal(details.error, 'net::ERR_BLOCKED_BY_CLIENT')
done(); done()
}); })
$.ajax({ $.ajax({
url: defaultURL, url: defaultURL,
success: function() { success: function () {
done('unexpected success'); done('unexpected success')
} }
}); })
}); })
}); })
}); })

File diff suppressed because it is too large Load diff

View file

@ -1,432 +1,436 @@
const assert = require('assert');
const http = require('http');
const path = require('path');
const ws = require('ws');
const remote = require('electron').remote;
const BrowserWindow = remote.require('electron').BrowserWindow; const assert = require('assert')
const session = remote.require('electron').session; const http = require('http')
const path = require('path')
const ws = require('ws')
const remote = require('electron').remote
const isCI = remote.getGlobal('isCi'); const BrowserWindow = remote.require('electron').BrowserWindow
const session = remote.require('electron').session
describe('chromium feature', function() { const isCI = remote.getGlobal('isCi')
var fixtures = path.resolve(__dirname, 'fixtures');
var listener = null;
afterEach(function() { describe('chromium feature', function () {
var fixtures = path.resolve(__dirname, 'fixtures')
var listener = null
afterEach(function () {
if (listener != null) { if (listener != null) {
window.removeEventListener('message', listener); window.removeEventListener('message', listener)
} }
listener = null; listener = null
}); })
xdescribe('heap snapshot', function() { xdescribe('heap snapshot', function () {
it('does not crash', function() { it('does not crash', function () {
process.atomBinding('v8_util').takeHeapSnapshot(); process.atomBinding('v8_util').takeHeapSnapshot()
}); })
}); })
describe('sending request of http protocol urls', function() { describe('sending request of http protocol urls', function () {
it('does not crash', function(done) { it('does not crash', function (done) {
this.timeout(5000); this.timeout(5000)
var server = http.createServer(function(req, res) { var server = http.createServer(function (req, res) {
res.end(); res.end()
server.close(); server.close()
done(); done()
}); })
server.listen(0, '127.0.0.1', function() { server.listen(0, '127.0.0.1', function () {
var port = server.address().port; var port = server.address().port
$.get("http://127.0.0.1:" + port); $.get('http://127.0.0.1:' + port)
}); })
}); })
}); })
describe('document.hidden', function() { describe('document.hidden', function () {
var url = "file://" + fixtures + "/pages/document-hidden.html"; var url = 'file://' + fixtures + '/pages/document-hidden.html'
var w = null; var w = null
afterEach(function() { afterEach(function () {
w != null ? w.destroy() : void 0; w != null ? w.destroy() : void 0
}); })
it('is set correctly when window is not shown', function(done) { it('is set correctly when window is not shown', function (done) {
w = new BrowserWindow({ w = new BrowserWindow({
show: false show: false
}); })
w.webContents.on('ipc-message', function(event, args) { w.webContents.on('ipc-message', function (event, args) {
assert.deepEqual(args, ['hidden', true]); assert.deepEqual(args, ['hidden', true])
done(); done()
}); })
w.loadURL(url); w.loadURL(url)
}); })
it('is set correctly when window is inactive', function(done) { it('is set correctly when window is inactive', function (done) {
w = new BrowserWindow({ w = new BrowserWindow({
show: false show: false
}); })
w.webContents.on('ipc-message', function(event, args) { w.webContents.on('ipc-message', function (event, args) {
assert.deepEqual(args, ['hidden', false]); assert.deepEqual(args, ['hidden', false])
done(); done()
}); })
w.showInactive(); w.showInactive()
w.loadURL(url); w.loadURL(url)
}); })
}); })
xdescribe('navigator.webkitGetUserMedia', function() { xdescribe('navigator.webkitGetUserMedia', function () {
it('calls its callbacks', function(done) { it('calls its callbacks', function (done) {
this.timeout(5000); this.timeout(5000)
navigator.webkitGetUserMedia({ navigator.webkitGetUserMedia({
audio: true, audio: true,
video: false video: false
}, function() { }, function () {
done(); done()
}, function() { }, function () {
done(); done()
}); })
}); })
}); })
describe('navigator.mediaDevices', function() { describe('navigator.mediaDevices', function () {
if (process.env.TRAVIS === 'true') { if (process.env.TRAVIS === 'true') {
return; return
} }
if (isCI && process.platform === 'linux') { if (isCI && process.platform === 'linux') {
return; return
} }
it('can return labels of enumerated devices', function(done) { it('can return labels of enumerated devices', function (done) {
navigator.mediaDevices.enumerateDevices().then((devices) => { navigator.mediaDevices.enumerateDevices().then((devices) => {
const labels = devices.map((device) => device.label); const labels = devices.map((device) => device.label)
const labelFound = labels.some((label) => !!label); const labelFound = labels.some((label) => !!label)
if (labelFound) if (labelFound) {
done(); done()
else } else {
done('No device labels found: ' + JSON.stringify(labels)); done('No device labels found: ' + JSON.stringify(labels))
}).catch(done); }
}); }).catch(done)
}); })
})
describe('navigator.language', function() { describe('navigator.language', function () {
it('should not be empty', function() { it('should not be empty', function () {
assert.notEqual(navigator.language, ''); assert.notEqual(navigator.language, '')
}); })
}); })
describe('navigator.serviceWorker', function() { describe('navigator.serviceWorker', function () {
var url = "file://" + fixtures + "/pages/service-worker/index.html"; var url = 'file://' + fixtures + '/pages/service-worker/index.html'
var w = null; var w = null
afterEach(function() { afterEach(function () {
w != null ? w.destroy() : void 0; w != null ? w.destroy() : void 0
}); })
it('should register for file scheme', function(done) { it('should register for file scheme', function (done) {
w = new BrowserWindow({ w = new BrowserWindow({
show: false show: false
}); })
w.webContents.on('ipc-message', function(event, args) { w.webContents.on('ipc-message', function (event, args) {
if (args[0] === 'reload') { if (args[0] === 'reload') {
w.webContents.reload(); w.webContents.reload()
} else if (args[0] === 'error') { } else if (args[0] === 'error') {
done('unexpected error : ' + args[1]); done('unexpected error : ' + args[1])
} else if (args[0] === 'response') { } else if (args[0] === 'response') {
assert.equal(args[1], 'Hello from serviceWorker!'); assert.equal(args[1], 'Hello from serviceWorker!')
session.defaultSession.clearStorageData({ session.defaultSession.clearStorageData({
storages: ['serviceworkers'] storages: ['serviceworkers']
}, function() { }, function () {
done(); done()
}); })
} }
}); })
w.loadURL(url); w.loadURL(url)
}); })
}); })
describe('window.open', function() { describe('window.open', function () {
this.timeout(20000); this.timeout(20000)
it('returns a BrowserWindowProxy object', function() { it('returns a BrowserWindowProxy object', function () {
var b = window.open('about:blank', '', 'show=no'); var b = window.open('about:blank', '', 'show=no')
assert.equal(b.closed, false); assert.equal(b.closed, false)
assert.equal(b.constructor.name, 'BrowserWindowProxy'); assert.equal(b.constructor.name, 'BrowserWindowProxy')
b.close(); b.close()
}); })
it('accepts "nodeIntegration" as feature', function(done) { it('accepts "nodeIntegration" as feature', function (done) {
var b; var b
listener = function(event) { listener = function (event) {
assert.equal(event.data, 'undefined'); assert.equal(event.data, 'undefined')
b.close(); b.close()
done(); done()
}; }
window.addEventListener('message', listener); window.addEventListener('message', listener)
b = window.open("file://" + fixtures + "/pages/window-opener-node.html", '', 'nodeIntegration=no,show=no'); b = window.open('file://' + fixtures + '/pages/window-opener-node.html', '', 'nodeIntegration=no,show=no')
}); })
it('inherit options of parent window', function(done) { it('inherit options of parent window', function (done) {
var b; var b
listener = function(event) { listener = function (event) {
var height, ref1, width; var ref1 = remote.getCurrentWindow().getSize()
ref1 = remote.getCurrentWindow().getSize(), width = ref1[0], height = ref1[1]; var width = ref1[0]
assert.equal(event.data, "size: " + width + " " + height); var height = ref1[1]
b.close(); assert.equal(event.data, 'size: ' + width + ' ' + height)
done(); b.close()
}; done()
window.addEventListener('message', listener); }
b = window.open("file://" + fixtures + "/pages/window-open-size.html", '', 'show=no'); window.addEventListener('message', listener)
}); b = window.open('file://' + fixtures + '/pages/window-open-size.html', '', 'show=no')
})
it('does not override child options', function(done) { it('does not override child options', function (done) {
var b, size; var b, size
size = { size = {
width: 350, width: 350,
height: 450 height: 450
}; }
listener = function(event) { listener = function (event) {
assert.equal(event.data, "size: " + size.width + " " + size.height); assert.equal(event.data, 'size: ' + size.width + ' ' + size.height)
b.close(); b.close()
done(); done()
}; }
window.addEventListener('message', listener); window.addEventListener('message', listener)
b = window.open("file://" + fixtures + "/pages/window-open-size.html", '', "show=no,width=" + size.width + ",height=" + size.height); b = window.open('file://' + fixtures + '/pages/window-open-size.html', '', 'show=no,width=' + size.width + ',height=' + size.height)
}); })
it('defines a window.location getter', function(done) { it('defines a window.location getter', function (done) {
var b, targetURL; var b, targetURL
targetURL = "file://" + fixtures + "/pages/base-page.html"; targetURL = 'file://' + fixtures + '/pages/base-page.html'
b = window.open(targetURL); b = window.open(targetURL)
BrowserWindow.fromId(b.guestId).webContents.once('did-finish-load', function() { BrowserWindow.fromId(b.guestId).webContents.once('did-finish-load', function () {
assert.equal(b.location, targetURL); assert.equal(b.location, targetURL)
b.close(); b.close()
done(); done()
}); })
}); })
it('defines a window.location setter', function(done) { it('defines a window.location setter', function (done) {
// Load a page that definitely won't redirect // Load a page that definitely won't redirect
var b; var b
b = window.open("about:blank"); b = window.open('about:blank')
BrowserWindow.fromId(b.guestId).webContents.once('did-finish-load', function() { BrowserWindow.fromId(b.guestId).webContents.once('did-finish-load', function () {
// When it loads, redirect // When it loads, redirect
b.location = "file://" + fixtures + "/pages/base-page.html"; b.location = 'file://' + fixtures + '/pages/base-page.html'
BrowserWindow.fromId(b.guestId).webContents.once('did-finish-load', function() { BrowserWindow.fromId(b.guestId).webContents.once('did-finish-load', function () {
// After our second redirect, cleanup and callback // After our second redirect, cleanup and callback
b.close(); b.close()
done(); done()
}); })
}); })
}); })
}); })
describe('window.opener', function() { describe('window.opener', function () {
this.timeout(10000); this.timeout(10000)
var url = "file://" + fixtures + "/pages/window-opener.html"; var url = 'file://' + fixtures + '/pages/window-opener.html'
var w = null; var w = null
afterEach(function() { afterEach(function () {
w != null ? w.destroy() : void 0; w != null ? w.destroy() : void 0
}); })
it('is null for main window', function(done) { it('is null for main window', function (done) {
w = new BrowserWindow({ w = new BrowserWindow({
show: false show: false
}); })
w.webContents.on('ipc-message', function(event, args) { w.webContents.on('ipc-message', function (event, args) {
assert.deepEqual(args, ['opener', null]); assert.deepEqual(args, ['opener', null])
done(); done()
}); })
w.loadURL(url); w.loadURL(url)
}); })
it('is not null for window opened by window.open', function(done) { it('is not null for window opened by window.open', function (done) {
var b; var b
listener = function(event) { listener = function (event) {
assert.equal(event.data, 'object'); assert.equal(event.data, 'object')
b.close(); b.close()
done(); done()
};
window.addEventListener('message', listener);
b = window.open(url, '', 'show=no');
});
});
describe('window.postMessage', function() {
it('sets the source and origin correctly', function(done) {
var b, sourceId;
sourceId = remote.getCurrentWindow().id;
listener = function(event) {
window.removeEventListener('message', listener);
b.close();
var message = JSON.parse(event.data);
assert.equal(message.data, 'testing');
assert.equal(message.origin, 'file://');
assert.equal(message.sourceEqualsOpener, true);
assert.equal(message.sourceId, sourceId);
assert.equal(event.origin, 'file://');
done();
};
window.addEventListener('message', listener);
b = window.open("file://" + fixtures + "/pages/window-open-postMessage.html", '', 'show=no');
BrowserWindow.fromId(b.guestId).webContents.once('did-finish-load', function() {
b.postMessage('testing', '*');
});
});
});
describe('window.opener.postMessage', function() {
it('sets source and origin correctly', function(done) {
var b;
listener = function(event) {
window.removeEventListener('message', listener);
b.close();
assert.equal(event.source, b);
assert.equal(event.origin, 'file://');
done();
};
window.addEventListener('message', listener);
b = window.open("file://" + fixtures + "/pages/window-opener-postMessage.html", '', 'show=no');
});
});
describe('creating a Uint8Array under browser side', function() {
it('does not crash', function() {
var RUint8Array = remote.getGlobal('Uint8Array');
new RUint8Array;
});
});
describe('webgl', function() {
it('can be get as context in canvas', function() {
if (process.platform === 'linux') {
return;
} }
var webgl = document.createElement('canvas').getContext('webgl'); window.addEventListener('message', listener)
assert.notEqual(webgl, null); b = window.open(url, '', 'show=no')
}); })
}); })
describe('web workers', function() { describe('window.postMessage', function () {
it('Worker can work', function(done) { it('sets the source and origin correctly', function (done) {
var worker = new Worker('../fixtures/workers/worker.js'); var b, sourceId
var message = 'ping'; sourceId = remote.getCurrentWindow().id
worker.onmessage = function(event) { listener = function (event) {
assert.equal(event.data, message); window.removeEventListener('message', listener)
worker.terminate(); b.close()
done(); var message = JSON.parse(event.data)
}; assert.equal(message.data, 'testing')
worker.postMessage(message); assert.equal(message.origin, 'file://')
}); assert.equal(message.sourceEqualsOpener, true)
assert.equal(message.sourceId, sourceId)
assert.equal(event.origin, 'file://')
done()
}
window.addEventListener('message', listener)
b = window.open('file://' + fixtures + '/pages/window-open-postMessage.html', '', 'show=no')
BrowserWindow.fromId(b.guestId).webContents.once('did-finish-load', function () {
b.postMessage('testing', '*')
})
})
})
it('SharedWorker can work', function(done) { describe('window.opener.postMessage', function () {
var worker = new SharedWorker('../fixtures/workers/shared_worker.js'); it('sets source and origin correctly', function (done) {
var message = 'ping'; var b
worker.port.onmessage = function(event) { listener = function (event) {
assert.equal(event.data, message); window.removeEventListener('message', listener)
done(); b.close()
}; assert.equal(event.source, b)
worker.port.postMessage(message); assert.equal(event.origin, 'file://')
}); done()
}); }
window.addEventListener('message', listener)
b = window.open('file://' + fixtures + '/pages/window-opener-postMessage.html', '', 'show=no')
})
})
describe('iframe', function() { describe('creating a Uint8Array under browser side', function () {
var iframe = null; it('does not crash', function () {
var RUint8Array = remote.getGlobal('Uint8Array')
var arr = new RUint8Array()
assert(arr)
})
})
beforeEach(function() { describe('webgl', function () {
iframe = document.createElement('iframe'); it('can be get as context in canvas', function () {
}); if (process.platform === 'linux') return
afterEach(function() { var webgl = document.createElement('canvas').getContext('webgl')
document.body.removeChild(iframe); assert.notEqual(webgl, null)
}); })
})
it('does not have node integration', function(done) { describe('web workers', function () {
iframe.src = "file://" + fixtures + "/pages/set-global.html"; it('Worker can work', function (done) {
document.body.appendChild(iframe); var worker = new Worker('../fixtures/workers/worker.js')
iframe.onload = function() { var message = 'ping'
assert.equal(iframe.contentWindow.test, 'undefined undefined undefined'); worker.onmessage = function (event) {
done(); assert.equal(event.data, message)
}; worker.terminate()
}); done()
}); }
worker.postMessage(message)
})
describe('storage', function() { it('SharedWorker can work', function (done) {
it('requesting persitent quota works', function(done) { var worker = new SharedWorker('../fixtures/workers/shared_worker.js')
navigator.webkitPersistentStorage.requestQuota(1024 * 1024, function(grantedBytes) { var message = 'ping'
assert.equal(grantedBytes, 1048576); worker.port.onmessage = function (event) {
done(); assert.equal(event.data, message)
}); done()
}); }
}); worker.port.postMessage(message)
})
})
describe('websockets', function() { describe('iframe', function () {
var wss = null; var iframe = null
var server = null;
var WebSocketServer = ws.Server;
afterEach(function() { beforeEach(function () {
wss.close(); iframe = document.createElement('iframe')
server.close(); })
});
it('has user agent', function(done) { afterEach(function () {
server = http.createServer(); document.body.removeChild(iframe)
server.listen(0, '127.0.0.1', function() { })
var port = server.address().port;
it('does not have node integration', function (done) {
iframe.src = 'file://' + fixtures + '/pages/set-global.html'
document.body.appendChild(iframe)
iframe.onload = function () {
assert.equal(iframe.contentWindow.test, 'undefined undefined undefined')
done()
}
})
})
describe('storage', function () {
it('requesting persitent quota works', function (done) {
navigator.webkitPersistentStorage.requestQuota(1024 * 1024, function (grantedBytes) {
assert.equal(grantedBytes, 1048576)
done()
})
})
})
describe('websockets', function () {
var wss = null
var server = null
var WebSocketServer = ws.Server
afterEach(function () {
wss.close()
server.close()
})
it('has user agent', function (done) {
server = http.createServer()
server.listen(0, '127.0.0.1', function () {
var port = server.address().port
wss = new WebSocketServer({ wss = new WebSocketServer({
server: server server: server
}); })
wss.on('error', done); wss.on('error', done)
wss.on('connection', function(ws) { wss.on('connection', function (ws) {
if (ws.upgradeReq.headers['user-agent']) { if (ws.upgradeReq.headers['user-agent']) {
done(); done()
} else { } else {
done('user agent is empty'); done('user agent is empty')
} }
}); })
new WebSocket("ws://127.0.0.1:" + port); var socket = new WebSocket(`ws://127.0.0.1:${port}`)
}); assert(socket)
}); })
}); })
})
describe('Promise', function() { describe('Promise', function () {
it('resolves correctly in Node.js calls', function(done) { it('resolves correctly in Node.js calls', function (done) {
document.registerElement('x-element', { document.registerElement('x-element', {
prototype: Object.create(HTMLElement.prototype, { prototype: Object.create(HTMLElement.prototype, {
createdCallback: { createdCallback: {
value: function() {} value: function () {}
} }
}) })
}); })
setImmediate(function() { setImmediate(function () {
var called = false; var called = false
Promise.resolve().then(function() { Promise.resolve().then(function () {
done(called ? void 0 : new Error('wrong sequence')); done(called ? void 0 : new Error('wrong sequence'))
}); })
document.createElement('x-element'); document.createElement('x-element')
called = true; called = true
}); })
}); })
it('resolves correctly in Electron calls', function(done) { it('resolves correctly in Electron calls', function (done) {
document.registerElement('y-element', { document.registerElement('y-element', {
prototype: Object.create(HTMLElement.prototype, { prototype: Object.create(HTMLElement.prototype, {
createdCallback: { createdCallback: {
value: function() {} value: function () {}
} }
}) })
}); })
remote.getGlobal('setImmediate')(function() { remote.getGlobal('setImmediate')(function () {
var called = false; var called = false
Promise.resolve().then(function() { Promise.resolve().then(function () {
done(called ? void 0 : new Error('wrong sequence')); done(called ? void 0 : new Error('wrong sequence'))
}); })
document.createElement('y-element'); document.createElement('y-element')
called = true; called = true
}); })
}); })
}); })
}); })

View file

@ -1,12 +1,12 @@
var app = require('electron').app; var app = require('electron').app
app.on('ready', function () { app.on('ready', function () {
// This setImmediate call gets the spec passing on Linux // This setImmediate call gets the spec passing on Linux
setImmediate(function () { setImmediate(function () {
app.exit(123); app.exit(123)
}); })
}); })
process.on('exit', function (code) { process.on('exit', function (code) {
console.log('Exit event with code: ' + code); console.log('Exit event with code: ' + code)
}); })

View file

@ -1,4 +1,4 @@
var fs = require('fs'); var fs = require('fs')
process.on('message', function(file) { process.on('message', function (file) {
process.send(fs.readFileSync(file).toString()); process.send(fs.readFileSync(file).toString())
}); })

View file

@ -1,7 +1,7 @@
exports.call = function(func) { exports.call = function (func) {
return func(); return func()
}; }
exports.constructor = function() { exports.constructor = function () {
this.test = 'test'; this.test = 'test'
}; }

View file

@ -1,22 +1,22 @@
'use strict'; 'use strict'
let value = 'old'; let value = 'old'
class BaseClass { class BaseClass {
method() { method () {
return 'method'; return 'method'
} }
get readonly() { get readonly () {
return 'readonly'; return 'readonly'
} }
get value() { get value () {
return value; return value
} }
set value(val) { set value (val) {
value = val; value = val
} }
} }
@ -24,6 +24,6 @@ class DerivedClass extends BaseClass {
} }
module.exports = { module.exports = {
base: new BaseClass, base: new BaseClass(),
derived: new DerivedClass, derived: new DerivedClass()
} }

View file

@ -1,4 +1,4 @@
var net = require('net'); var net = require('net')
var server = net.createServer(function() {}); var server = net.createServer(function () {})
server.listen(process.argv[2]); server.listen(process.argv[2])
process.exit(0); process.exit(0)

View file

@ -1,14 +1,16 @@
process.on('uncaughtException', function(error) { const path = require('path')
process.send(error.stack);
});
var child = require('child_process').fork(__dirname + '/ping.js'); process.on('uncaughtException', function (error) {
process.on('message', function(msg) { process.send(error.stack)
child.send(msg); })
});
var child = require('child_process').fork(path.join(__dirname, '/ping.js'))
process.on('message', function (msg) {
child.send(msg)
})
child.on('message', function (msg) { child.on('message', function (msg) {
process.send(msg); process.send(msg)
}); })
child.on('exit', function(code) { child.on('exit', function (code) {
process.exit(code); process.exit(code)
}); })

View file

@ -1 +1 @@
exports.aFunction = function() { return 1127; }; exports.aFunction = function () { return 1127 }

View file

@ -1 +1 @@
exports.id = 1127; exports.id = 1127

View file

@ -2,6 +2,6 @@ process.on('message', function () {
process.send([ process.send([
'a'.localeCompare('a'), 'a'.localeCompare('a'),
'ä'.localeCompare('z', 'de'), 'ä'.localeCompare('z', 'de'),
'ä'.localeCompare('a', 'sv', { sensitivity: 'base' }), 'ä'.localeCompare('a', 'sv', { sensitivity: 'base' })
]); ])
}); })

View file

@ -1,3 +1,3 @@
process.on('message', function () { process.on('message', function () {
process.send(typeof require('original-fs')); process.send(typeof require('original-fs'))
}); })

View file

@ -1,4 +1,4 @@
process.on('message', function(msg) { process.on('message', function (msg) {
process.send(msg); process.send(msg)
process.exit(0); process.exit(0)
}); })

View file

@ -1,4 +1,4 @@
var ipcRenderer = require('electron').ipcRenderer; var ipcRenderer = require('electron').ipcRenderer
ipcRenderer.on('ping', function(event, message) { ipcRenderer.on('ping', function (event, message) {
ipcRenderer.sendToHost('pong', message); ipcRenderer.sendToHost('pong', message)
}); })

View file

@ -1,7 +1,7 @@
setImmediate(function() { setImmediate(function () {
try { try {
console.log([typeof process, typeof setImmediate, typeof global].join(' ')); console.log([typeof process, typeof setImmediate, typeof global].join(' '))
} catch (e) { } catch (e) {
console.log(e.message); console.log(e.message)
} }
}); })

View file

@ -1 +1 @@
console.log([typeof require, typeof module, typeof process].join(' ')); console.log([typeof require, typeof module, typeof process].join(' '))

View file

@ -1,7 +1,7 @@
exports.print = function(obj) { exports.print = function (obj) {
return obj.constructor.name; return obj.constructor.name
}; }
exports.echo = function(obj) { exports.echo = function (obj) {
return obj; return obj
}; }

View file

@ -1,4 +1,4 @@
process.on('message', function() { process.on('message', function () {
process.send(process.argv); process.send(process.argv)
process.exit(0); process.exit(0)
}); })

View file

@ -1,5 +1,5 @@
exports.twicePromise = function (promise) { exports.twicePromise = function (promise) {
return promise.then(function (value) { return promise.then(function (value) {
return value * 2; return value * 2
}); })
}; }

Some files were not shown because too many files have changed in this diff Show more