browserify preload scripts (#30)

This commit is contained in:
Lynn
2017-03-07 14:44:31 -08:00
committed by GitHub
parent 4645f3a21e
commit 38f92b8849
8 changed files with 92 additions and 70 deletions

View File

@@ -4,3 +4,4 @@ coverage
dist
installer
node_modules
js/preload/_*.js

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
node_modules
dist
.DS_Store
js/preload/_*.js

16
js/enums/api.js Normal file
View File

@@ -0,0 +1,16 @@
'use strict';
var keyMirror = require('keymirror');
const cmds = keyMirror({
isOnline: null,
open: null,
registerLogger: null,
setBadgeCount: null,
badgeDataUrl: null,
});
module.exports = {
cmds: cmds,
apiName: 'symphony-api'
}

View File

@@ -10,6 +10,10 @@ const windowMgr = require('./windowMgr.js');
const log = require('./log.js');
const badgeCount = require('./badgeCount.js');
const apiEnums = require('./enums/api.js');
const apiCmds = apiEnums.cmds;
const apiName = apiEnums.apiName;
/**
* Ensure events comes from a window that we have created.
* @param {EventEmitter} event node emitter event to be tested
@@ -29,38 +33,11 @@ function isValidWindow(event) {
return false;
}
// only these cmds are allowed by main window
let cmdBlackList = [ 'open', 'registerLogger' ];
/**
* Only permit certain cmds for some windows
* @param {EventEmitter} event node emitter event to be tested
* @param {String} cmd cmd name
* @return {Boolean} true if cmd is allowed for window, otherwise false
*/
function isCmdAllowed(event, cmd) {
if (event && event.sender && cmd) {
// validate that event sender is from window we created
let browserWin = electron.BrowserWindow.fromWebContents(event.sender);
if (!windowMgr.isMainWindow(browserWin)) {
// allow all commands for main window
return true;
}
// allow only certain cmds for child windows
// e.g., open cmd not allowed for child windows
return (cmdBlackList.indexOf(cmd) === -1)
}
return false;
}
/**
* Handle API related ipc messages from renderers. Only messages from windows
* we have created are allowed.
*/
electron.ipcMain.on('symphony-api', (event, arg) => {
electron.ipcMain.on(apiName, (event, arg) => {
if (!isValidWindow(event)) {
/* eslint-disable no-console */
console.log('invalid window try to perform action, ignoring action.');
@@ -68,40 +45,33 @@ electron.ipcMain.on('symphony-api', (event, arg) => {
return;
}
if (!isCmdAllowed(event, arg && arg.cmd)) {
/* eslint-disable no-console */
console.log('cmd not allowed for this window: ' + arg.cmd);
/* eslint-enable no-console */
return;
}
if (!arg) {
return;
}
if (arg.cmd === 'isOnline' && typeof arg.isOnline === 'boolean') {
if (arg.cmd === apiCmds.isOnline && typeof arg.isOnline === 'boolean') {
windowMgr.setIsOnline(arg.isOnline);
return;
}
if (arg.cmd === 'setBadgeCount' && typeof arg.count === 'number') {
if (arg.cmd === apiCmds.setBadgeCount && typeof arg.count === 'number') {
badgeCount.show(arg.count);
return;
}
if (arg.cmd === 'badgeDataUrl' && typeof arg.dataUrl === 'string' &&
if (arg.cmd === apiCmds.badgeDataUrl && typeof arg.dataUrl === 'string' &&
typeof arg.count === 'number') {
badgeCount.setDataUrl(arg.dataUrl, arg.count);
return;
}
if (arg.cmd === 'registerLogger') {
if (arg.cmd === apiCmds.registerLogger) {
// renderer window that has a registered logger from JS.
log.setLogWindow(event.sender);
return;
}
if (arg.cmd === 'open' && typeof arg.url === 'string') {
if (arg.cmd === apiCmds.open && typeof arg.url === 'string') {
let title = arg.title || 'Symphony';
let width = arg.width || 1024;
let height = arg.height || 768;

View File

@@ -0,0 +1,25 @@
'use strict';
// script run before others and still has access to node integration, even
// when turned off - allows us to leak only what want into window object.
// see: http://electron.atom.io/docs/api/browser-window/
//
// to leak some node module into:
// https://medium.com/@leonli/securing-embedded-external-content-in-electron-node-js-8b6ef665cd8e#.fex4e68p7
// https://slack.engineering/building-hybrid-applications-with-electron-dc67686de5fb#.tp6zz1nrk
//
// also to bring pieces of node.js:
// https://github.com/electron/electron/issues/2984
//
//
// API exposed to renderer child window process (aka pop-outs).
//
window.SYM_API = {
// api version
version: '1.0.0'
// currently no funcs are exposed to child windows
};
Object.freeze(window.SYM_API);

View File

@@ -14,24 +14,25 @@
const { ipcRenderer } = require('electron');
const apiEnums = require('../enums/api.js');
const apiCmds = apiEnums.cmds;
const apiName = apiEnums.apiName;
// hold ref so doesn't get GC'ed
const local = {
ipcRenderer: ipcRenderer
};
const api = 'symphony-api';
// API exposed by Symphony to renderer processes:
// Note: certain cmds are only allowed on some windows, this is checked by
// main process.
//
// API exposed to renderer main window process.
//
window.SYM_API = {
// api version
version: '1.0.0',
// only allowed by main window - enforced by main process.
openWindow: function(url) {
local.ipcRenderer.send(api, {
cmd: 'open',
local.ipcRenderer.send(apiName, {
cmd: apiCmds.open,
url: url
});
},
@@ -45,8 +46,8 @@ window.SYM_API = {
* are used here).
*/
setBadgeCount: function(count) {
local.ipcRenderer.send(api, {
cmd: 'setBadgeCount',
local.ipcRenderer.send(apiName, {
cmd: apiCmds.setBadgeCount,
count: count
});
},
@@ -67,8 +68,8 @@ window.SYM_API = {
local.logger = logger;
// only main window can register
local.ipcRenderer.send(api, {
cmd: 'registerLogger'
local.ipcRenderer.send(apiName, {
cmd: apiCmds.registerLogger
});
}
}
@@ -127,16 +128,16 @@ local.ipcRenderer.on('createBadgeDataUrl', (arg) => {
let dataUrl = canvas.toDataURL('image/png', 1.0);
local.ipcRenderer.send(api, {
cmd: 'badgeDataUrl',
local.ipcRenderer.send(apiName, {
cmd: apiCmds.badgeDataUrl,
dataUrl: dataUrl,
count: count
});
});
function updateOnlineStatus() {
local.ipcRenderer.send(api, {
cmd: 'isOnline',
local.ipcRenderer.send(apiName, {
cmd: apiCmds.isOnline,
isOnline: window.navigator.onLine
});
}

View File

@@ -19,7 +19,11 @@ let mainWindow;
let windows = {};
let willQuitApp = false;
let isOnline = true;
const preloadScript = path.join(__dirname, '/RendererPreload.js');
// different preload script for main window and child windows.
// note: these files are generated by browserify prebuild process.
const preloadMainScript = path.join(__dirname, 'preload/_preloadMain.js');
const preloadChildScript = path.join(__dirname, 'preloda/_preloadChild.js');
function addWindowKey(key, browserWin) {
windows[ key ] = browserWin;
@@ -39,7 +43,7 @@ function createMainWindow(url) {
webPreferences: {
sandbox: true,
nodeIntegration: false,
preload: preloadScript,
preload: preloadMainScript,
winKey: key
}
});
@@ -143,7 +147,7 @@ function createChildWindow(url, title, width, height) {
webPreferences: {
sandbox: true,
nodeIntegration: false,
preload: preloadScript,
preload: preloadChildScript,
winKey: winKey
}
});

View File

@@ -8,19 +8,22 @@
"scripts": {
"dev:mac": "ELECTRON_DEV=true npm run start",
"dev:win": "SET ELECTRON_DEV=true && npm run start",
"start": "electron .",
"dist-mac": "npm run test && npm run lint && build --mac",
"dist-win": "npm run test && npm run lint && build --win --x64",
"dist-win-x86": "npm run test && npm run lint && build --win --ia32",
"unpacked-win": "npm run test && npm run lint && build --win --x64 --dir",
"unpacked-win-x86": "npm run test && npm run lint && build --win --ia32 --dir",
"test": "jest --coverage",
"lint": "eslint js/**"
"start": "npm run browserify-preload && electron .",
"dist-mac": "npm run prebuild && build --mac",
"dist-win": "npm run prebuild && build --win --x64",
"dist-win-x86": "npm run prebuild && build --win --ia32",
"unpacked-win": "npm run prebuild && build --win --x64 --dir",
"unpacked-win-x86": "npm run prebuild && build --win --ia32 --dir",
"prebuild": "npm run lint && npm run test && npm run browserify-preload",
"lint": "eslint js/**",
"test": "jest --coverage tests/*.test.js",
"browserify-preload": "browserify -o js/preload/_preloadMain.js -x electron js/preload/preloadMain.js && browserify -o js/preload/_preloadChild.js -x electron js/preload/preloadChild.js"
},
"build": {
"files": [
"!installer/*",
"!tests/*"
"!coverage/*",
"!installer/*",
"!tests/*"
],
"extraFiles": "config/Symphony.config",
"appId": "symphony-electron-desktop",
@@ -68,7 +71,8 @@
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-jsx-a11y": "^4.0.0",
"eslint-plugin-react": "^6.10.0",
"jest": "^19.0.2"
"jest": "^19.0.2",
"browserify": "^14.1.0"
},
"dependencies": {
"electron-squirrel-startup": "^1.0.0",