From fc4e1485ad745a89e8d43f9d35fb1462484ae357 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 19 Dec 2018 12:04:40 +0000 Subject: [PATCH] Electron: Load app from custom protocol This puts the app into its own origin so it doesn't have access to the filesystem via file:// URIs. Next step: migrate over localstorage & indexeddb data from the old origin... --- electron_app/src/electron-main.js | 50 +++++++++++++++++++++++++++++-- electron_app/src/preload.js | 8 +++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/electron_app/src/electron-main.js b/electron_app/src/electron-main.js index dbd2ff670c..b8201070a0 100644 --- a/electron_app/src/electron-main.js +++ b/electron_app/src/electron-main.js @@ -24,7 +24,7 @@ const checkSquirrelHooks = require('./squirrelhooks'); if (checkSquirrelHooks()) return; const argv = require('minimist')(process.argv); -const {app, ipcMain, powerSaveBlocker, BrowserWindow, Menu, autoUpdater} = require('electron'); +const {app, ipcMain, powerSaveBlocker, BrowserWindow, Menu, autoUpdater, protocol} = require('electron'); const AutoLaunch = require('auto-launch'); const path = require('path'); @@ -171,6 +171,13 @@ const launcher = new AutoLaunch({ }, }); +// Register the scheme the app is served from as 'standard' +// which allows things like relative URLs and IndexedDB to +// work. +// Also mark it as secure (ie. accessing resources from this +// protocol and HTTPS won't trigger mixed content warnings). +protocol.registerStandardSchemes(['vector'], {secure: true}); + app.on('ready', () => { if (argv['devtools']) { try { @@ -186,6 +193,45 @@ app.on('ready', () => { } } + protocol.registerFileProtocol('vector', (request, callback) => { + if (request.method !== 'GET') { + callback({error: -322}); // METHOD_NOT_SUPPORTED from chromium/src/net/base/net_error_list.h + return null; + } + + const parsedUrl = new URL(request.url); + if (parsedUrl.protocol !== 'vector:') { + callback({error: -302}); // UNKNOWN_URL_SCHEME + return; + } + if (parsedUrl.host !== 'vector') { + callback({error: -105}); // NAME_NOT_RESOLVED + return; + } + + const target = parsedUrl.pathname.split('/'); + if (target[target.length - 1] == '') { + target[target.length - 1] = 'index.html'; + } + + // Normalise the base dir and the target path separately, then make sure + // the target path isn't trying to back out beyond its root + const appBaseDir = path.normalize(__dirname + "/../../webapp"); + const relTarget = path.normalize(path.join(...target)); + if (relTarget.startsWith('..')) { + callback({error: -6}); // FILE_NOT_FOUND + return; + } + const absTarget = path.join(appBaseDir, relTarget); + + callback({ + path: absTarget, + }); + }, (error) => { + if (error) console.error('Failed to register protocol') + }); + + if (vectorConfig['update_base_url']) { console.log(`Starting auto update with base URL: ${vectorConfig['update_base_url']}`); @@ -225,7 +271,7 @@ app.on('ready', () => { webgl: false, }, }); - mainWindow.loadURL(`file://${__dirname}/../../webapp/index.html`); + mainWindow.loadURL('vector://vector/'); Menu.setApplicationMenu(vectorMenu); // explicitly hide because setApplicationMenu on Linux otherwise shows... diff --git a/electron_app/src/preload.js b/electron_app/src/preload.js index 4c926d2145..bf6e23bbaa 100644 --- a/electron_app/src/preload.js +++ b/electron_app/src/preload.js @@ -19,3 +19,11 @@ const { ipcRenderer } = require('electron'); // expose ipcRenderer to the renderer process window.ipcRenderer = ipcRenderer; +// Allow the fetch API to load resources from this +// protocol: this is necessary to load olm.wasm. +// (Also mark it a secure although we've already +// done this in the main process). +webFrame.registerURLSchemeAsPrivileged('vector', { + secure: true, + supportFetchAPI: true, +});