Skip to content

Commit

Permalink
Run the Desktop app in a sandbox
Browse files Browse the repository at this point in the history
 * Turn off node integration in the electron renderer process
 * Enable the chromium sandbox to put the renderer into its own process
 * Expose just the ipc module with a preload script
 * Introduce a little IPC call wrapper so we can call into the
   renderer process and await on the result.
 * Use this in a bunch of places we previously used direct calls
   to electron modules.
 * Convert other uses of node, eg. use of process to derive the
   platform (just look at the user agent)
 * Strip out the desktopCapturer integration which doesn't appear
   to have ever worked (probably best to just wait until
   getDisplayMedia() is available in chrome at this point:
   https://github.com/vector-im/riot-web/issues/4880).
  • Loading branch information
dbkr committed Dec 18, 2018
1 parent df15529 commit 19f1489
Show file tree
Hide file tree
Showing 7 changed files with 200 additions and 146 deletions.
106 changes: 71 additions & 35 deletions electron_app/src/electron-main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Copyright 2016 Aviral Dasgupta
Copyright 2016 OpenMarket Ltd
Copyright 2017 Michael Telatynski <[email protected]>
Copyright 2018 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -23,8 +24,9 @@ const checkSquirrelHooks = require('./squirrelhooks');
if (checkSquirrelHooks()) return;

const argv = require('minimist')(process.argv);
const {app, ipcMain, powerSaveBlocker, BrowserWindow, Menu} = require('electron');
const {app, ipcMain, powerSaveBlocker, BrowserWindow, Menu, autoUpdater} = require('electron');
const AutoLaunch = require('auto-launch');
const path = require('path');

const tray = require('./tray');
const vectorMenu = require('./vectormenu');
Expand Down Expand Up @@ -97,6 +99,61 @@ ipcMain.on('app_onAction', function(ev, payload) {
}
});

autoUpdater.on('update-downloaded', (ev, releaseNotes, releaseName, releaseDate, updateURL) => {
if (!mainWindow) return;
// forward to renderer
mainWindow.webContents.send('update-downloaded', {
releaseNotes,
releaseName,
releaseDate,
updateURL,
});
});

ipcMain.on('ipcCall', function(ev, payload) {
if (!mainWindow) return;

const args = payload.args || [];
let ret;

switch (payload.name) {
case 'getUpdateFeedUrl':
ret = autoUpdater.getFeedURL();
break;
case 'getAutoLaunchEnabled':
ret = launcher.isEnabled;
break;
case 'setAutoLaunchEnabled':
if (args[0]) {
launcher.enable();
} else {
launcher.disable();
}
break;
case 'getAppVersion':
ret = app.getVersion();
break;
case 'focusWindow':
if (mainWindow.isMinimized()) {
mainWindow.restore();
} else if (!mainWindow.isVisible()) {
mainWindow.show();
} else {
mainWindow.focus();
}
default:
mainWindow.webContents.send('ipcReply', {
id: payload.id,
error: new Error("Unknown IPC Call: "+payload.name),
});
return;
}

mainWindow.webContents.send('ipcReply', {
id: payload.id,
reply: ret,
});
});

app.commandLine.appendSwitch('--enable-usermedia-screen-capturing');

Expand Down Expand Up @@ -126,40 +183,6 @@ const launcher = new AutoLaunch({
},
});

const settings = {
'auto-launch': {
get: launcher.isEnabled,
set: function(bool) {
if (bool) {
return launcher.enable();
} else {
return launcher.disable();
}
},
},
};

ipcMain.on('settings_get', async function(ev) {
const data = {};

try {
await Promise.all(Object.keys(settings).map(async function (setting) {
data[setting] = await settings[setting].get();
}));

ev.sender.send('settings', data);
} catch (e) {
console.error(e);
}
});

ipcMain.on('settings_set', function(ev, key, value) {
console.log(key, value);
if (settings[key] && settings[key].set) {
settings[key].set(value);
}
});

app.on('ready', () => {
if (argv['devtools']) {
try {
Expand Down Expand Up @@ -191,6 +214,7 @@ app.on('ready', () => {
defaultHeight: 768,
});

const preloadScript = path.normalize(`${__dirname}/preload.js`);
mainWindow = global.mainWindow = new BrowserWindow({
icon: iconPath,
show: false,
Expand All @@ -200,6 +224,18 @@ app.on('ready', () => {
y: mainWindowState.y,
width: mainWindowState.width,
height: mainWindowState.height,
webPreferences: {
preload: preloadScript,
nodeIntegration: false,
sandbox: true,
enableRemoteModule: false,
// We don't use this: it's useful for the preload script to
// share a context with the main page so we can give select
// objects to the main page. The sandbox option isolates the
// main page from the background script.
contextIsolation: false,
webgl: false,
},
});
mainWindow.loadURL(`file://${__dirname}/../../webapp/index.html`);
Menu.setApplicationMenu(vectorMenu);
Expand Down
16 changes: 4 additions & 12 deletions src/vector/platform/index.js → electron_app/src/preload.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
// @flow

/*
Copyright 2016 Aviral Dasgupta
Copyright 2016 OpenMarket Ltd
Copyright 2018 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -17,13 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

let Platform = null;
const { ipcRenderer } = require('electron');

if (window && window.process && window.process && window.process.type === 'renderer') {
// we're running inside electron
Platform = require('./ElectronPlatform');
} else {
Platform = require('./WebPlatform');
}
// expose ipcRenderer to the renderer process
window.ipcRenderer = ipcRenderer;

export default Platform;
15 changes: 12 additions & 3 deletions src/vector/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ import * as languageHandler from 'matrix-react-sdk/lib/languageHandler';
import url from 'url';

import {parseQs, parseQsFromFragment} from './url_utils';
import Platform from './platform';

import ElectronPlatform from './platform/ElectronPlatform';
import WebPlatform from './platform/WebPlatform';

import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
import SettingsStore from "matrix-react-sdk/lib/settings/SettingsStore";
Expand Down Expand Up @@ -219,8 +221,15 @@ async function loadApp() {
const fragparts = parseQsFromFragment(window.location);
const params = parseQs(window.location);

// set the platform for react sdk (our Platform object automatically picks the right one)
PlatformPeg.set(new Platform());
// set the platform for react sdk
//if (navigator.userAgent.toLowerCase().indexOf('electron') > 0) {
if (window.ipcRenderer) {
console.log("Using Electron platform");
PlatformPeg.set(new ElectronPlatform());
} else {
console.log("Using Web platform");
PlatformPeg.set(new WebPlatform());
}

// Load the config file. First try to load up a domain-specific config of the
// form "config.$domain.json" and if that fails, fall back to config.json.
Expand Down
Loading

0 comments on commit 19f1489

Please sign in to comment.