diff --git a/js/child-preload.js b/js/child-preload.js new file mode 100644 index 00000000..0d9632f6 --- /dev/null +++ b/js/child-preload.js @@ -0,0 +1,26 @@ +// script run before others and still has access to node integration, even +// when turned off - also 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 +// as suggested above: consider injecting key into window that can be used to +// validate operations. +// +// also to bring pieces of node.js: +// https://github.com/electron/electron/issues/2984 +// + +const { ipcRenderer } = require('electron'); + +// hold ref so doesn't get GC'ed +const local = { + ipcRenderer: ipcRenderer +} + +// JS can detect if in wrapper mode by looking for window.ELECTRON_API obj +window.ELECTRON_API = { +}; + +Object.freeze(window.ELECTRON_API); diff --git a/js/main-preload.js b/js/main-preload.js new file mode 100644 index 00000000..96439ad0 --- /dev/null +++ b/js/main-preload.js @@ -0,0 +1,32 @@ +// script run before others and still has access to node integration, even +// when turned off - also 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 +// as suggested above: consider injecting key into window that can be used to +// validate operations. +// +// also to bring pieces of node.js: +// https://github.com/electron/electron/issues/2984 +// + +const { ipcRenderer } = require('electron'); + +// hold ref so doesn't get GC'ed +const local = { + ipcRenderer: ipcRenderer +} + +// JS can detect if in wrapper mode by looking for window.ELECTRON_API obj +window.ELECTRON_API = { + openWindow: function(url) { + local.ipcRenderer.send('symphony-msg', { + cmd: 'open', + url: url + }); + } +}; + +Object.freeze(window.ELECTRON_API); diff --git a/main.js b/js/main.js similarity index 71% rename from main.js rename to js/main.js index e91d07f0..bd06831c 100644 --- a/main.js +++ b/js/main.js @@ -1,6 +1,7 @@ const electron = require('electron'); -const packageJSON = require('./package.json'); +const packageJSON = require('../package.json'); const menuTemplate = require('./menuTemplate.js'); +const path = require('path'); const app = electron.app const BrowserWindow = electron.BrowserWindow; @@ -17,6 +18,7 @@ if (isDevEnv()) { // Keep a global reference of the window object, if you don't, the window will // be closed automatically when the JavaScript object is garbage collected. let mainWindow; +let childWindows = []; function isDevEnv() { var isDev = process.env.ELECTRON_DEV ? @@ -24,7 +26,7 @@ function isDevEnv() { return isDev; } -function createWindow () { +function createMainWindow () { // note: for now, turning off node integration as this is causing failure with // onelogin, jquery can not get initialized. electron's node integration // conflicts on the window object. @@ -33,12 +35,13 @@ function createWindow () { width: 1024, height: 768, webPreferences: { sandbox: false, - nodeIntegration: false + nodeIntegration: false, + preload: path.join(__dirname, '/main-preload.js') } }); mainWindow.loadURL(packageJSON.homepage); - + const menu = electron.Menu.buildFromTemplate(menuTemplate(app)); electron.Menu.setApplicationMenu(menu); @@ -60,18 +63,41 @@ function createWindow () { mainWindow = null; }); - // open external links in default browser + // open external links in default browser - window.open mainWindow.webContents.on('new-window', function(event, url) { event.preventDefault(); electron.shell.openExternal(url); }); } +electron.ipcMain.on('symphony-msg', (event, arg) => { + if (arg && arg.cmd === 'open' && arg.url) { + var width = arg.width || 1024; + var height = arg.height || 768; + var title = arg.title || 'Symphony'; + + let childWindow = new BrowserWindow({ + title: title, + width: width, + height: height, + webPreferences: { + sandbox: false, + nodeIntegration: false, + preload: path.join(__dirname, '/child-preload.js') + } + }); + + childWindows.push(childWindow); + childWindow.loadURL(arg.url); + return; + } +}); + // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. app.on('ready', function() { - createWindow(); + createMainWindow(); }); app.on('before-quit', function() { @@ -88,7 +114,7 @@ app.on('window-all-closed', function () { app.on('activate', function () { if (mainWindow === null) { - createWindow(); + createMainWindow(); } else { mainWindow.show(); } diff --git a/menuTemplate.js b/js/menuTemplate.js similarity index 100% rename from menuTemplate.js rename to js/menuTemplate.js diff --git a/package.json b/package.json index a2dd17d8..0b45222d 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "version": "1.0.1", "description": "Symphony desktop app", "author": "Symphony", - "main": "main.js", + "main": "js/main.js", "scripts": { "dev:mac": "ELECTRON_DEV=true npm run start", "dev:win": "SET ELECTRON_DEV=true && npm run start",