diff --git a/electron/src/electron-main.js b/electron/src/electron-main.js index bd3a1b5cc2..8f11d789b2 100644 --- a/electron/src/electron-main.js +++ b/electron/src/electron-main.js @@ -1,9 +1,39 @@ // @flow const {app, BrowserWindow} = require('electron'); +const open = require('open'); +const url = require('url'); + +const PERMITTED_URL_SCHEMES = [ + 'http:', + 'https:', + 'mailto:', +]; let mainWindow = null; let appQuitting = false; +function onWindowOrNavigate(ev, target) { + // always prevent the default: if something goes wrong, + // we don't want to end up opening it in the electron + // app, as we could end up opening any sort of random + // url in a window that has node scripting access. + ev.preventDefault(); + debugger; + + // node-open passes the target to open/start/xdg-open, + // so put fairly stringent limits on what can be opened + // (for instance, open /bin/sh does indeed open a terminal + // with a shell, albeit with no arguments) + const parsed_url = url.parse(target); + if (PERMITTED_URL_SCHEMES.indexOf(parsed_url.protocol) > -1) { + // explicitly use the URL re-assembled by the url library, + // so we know the url parser has understood all the parts + // of the input string + const new_target = url.format(parsed_url); + open(new_target); + } +} + app.on('ready', () => { mainWindow = new BrowserWindow({ icon: `${__dirname}/../../vector/img/logo.png`, @@ -23,6 +53,9 @@ app.on('ready', () => { return false; } }); + + mainWindow.webContents.on('new-window', onWindowOrNavigate); + mainWindow.webContents.on('will-navigate', onWindowOrNavigate); }); app.on('window-all-closed', () => { diff --git a/package.json b/package.json index 8e0c55305d..6915b3080c 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "matrix-js-sdk": "matrix-org/matrix-js-sdk#develop", "matrix-react-sdk": "matrix-org/matrix-react-sdk#develop", "modernizr": "^3.1.0", + "open": "0.0.5", "q": "^1.4.1", "react": "^15.2.1", "react-dnd": "^2.1.4",