mirror of
https://github.com/vector-im/element-web.git
synced 2024-09-10 07:05:14 +00:00
Run the Desktop app in a sandbox
* 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).
This commit is contained in:
parent
df155293b1
commit
19f1489c92
7 changed files with 198 additions and 144 deletions
|
@ -2,6 +2,7 @@
|
||||||
Copyright 2016 Aviral Dasgupta
|
Copyright 2016 Aviral Dasgupta
|
||||||
Copyright 2016 OpenMarket Ltd
|
Copyright 2016 OpenMarket Ltd
|
||||||
Copyright 2017 Michael Telatynski <7t3chguy@gmail.com>
|
Copyright 2017 Michael Telatynski <7t3chguy@gmail.com>
|
||||||
|
Copyright 2018 New Vector Ltd
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -23,8 +24,9 @@ const checkSquirrelHooks = require('./squirrelhooks');
|
||||||
if (checkSquirrelHooks()) return;
|
if (checkSquirrelHooks()) return;
|
||||||
|
|
||||||
const argv = require('minimist')(process.argv);
|
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 AutoLaunch = require('auto-launch');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
const tray = require('./tray');
|
const tray = require('./tray');
|
||||||
const vectorMenu = require('./vectormenu');
|
const vectorMenu = require('./vectormenu');
|
||||||
|
@ -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');
|
app.commandLine.appendSwitch('--enable-usermedia-screen-capturing');
|
||||||
|
|
||||||
|
@ -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', () => {
|
app.on('ready', () => {
|
||||||
if (argv['devtools']) {
|
if (argv['devtools']) {
|
||||||
try {
|
try {
|
||||||
|
@ -191,6 +214,7 @@ app.on('ready', () => {
|
||||||
defaultHeight: 768,
|
defaultHeight: 768,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const preloadScript = path.normalize(`${__dirname}/preload.js`);
|
||||||
mainWindow = global.mainWindow = new BrowserWindow({
|
mainWindow = global.mainWindow = new BrowserWindow({
|
||||||
icon: iconPath,
|
icon: iconPath,
|
||||||
show: false,
|
show: false,
|
||||||
|
@ -200,6 +224,18 @@ app.on('ready', () => {
|
||||||
y: mainWindowState.y,
|
y: mainWindowState.y,
|
||||||
width: mainWindowState.width,
|
width: mainWindowState.width,
|
||||||
height: mainWindowState.height,
|
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`);
|
mainWindow.loadURL(`file://${__dirname}/../../webapp/index.html`);
|
||||||
Menu.setApplicationMenu(vectorMenu);
|
Menu.setApplicationMenu(vectorMenu);
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016 Aviral Dasgupta
|
Copyright 2018 New Vector Ltd
|
||||||
Copyright 2016 OpenMarket Ltd
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -17,13 +14,8 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let Platform = null;
|
const { ipcRenderer } = require('electron');
|
||||||
|
|
||||||
if (window && window.process && window.process && window.process.type === 'renderer') {
|
// expose ipcRenderer to the renderer process
|
||||||
// we're running inside electron
|
window.ipcRenderer = ipcRenderer;
|
||||||
Platform = require('./ElectronPlatform');
|
|
||||||
} else {
|
|
||||||
Platform = require('./WebPlatform');
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Platform;
|
|
|
@ -47,7 +47,9 @@ import * as languageHandler from 'matrix-react-sdk/lib/languageHandler';
|
||||||
import url from 'url';
|
import url from 'url';
|
||||||
|
|
||||||
import {parseQs, parseQsFromFragment} from './url_utils';
|
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 MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
||||||
import SettingsStore from "matrix-react-sdk/lib/settings/SettingsStore";
|
import SettingsStore from "matrix-react-sdk/lib/settings/SettingsStore";
|
||||||
|
@ -219,8 +221,15 @@ async function loadApp() {
|
||||||
const fragparts = parseQsFromFragment(window.location);
|
const fragparts = parseQsFromFragment(window.location);
|
||||||
const params = parseQs(window.location);
|
const params = parseQs(window.location);
|
||||||
|
|
||||||
// set the platform for react sdk (our Platform object automatically picks the right one)
|
// set the platform for react sdk
|
||||||
PlatformPeg.set(new Platform());
|
//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
|
// 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.
|
// form "config.$domain.json" and if that fails, fall back to config.json.
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016 Aviral Dasgupta
|
Copyright 2016 Aviral Dasgupta
|
||||||
Copyright 2016 OpenMarket Ltd
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2018 New Vector Ltd
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -21,44 +22,24 @@ import VectorBasePlatform, {updateCheckStatusEnum} from './VectorBasePlatform';
|
||||||
import dis from 'matrix-react-sdk/lib/dispatcher';
|
import dis from 'matrix-react-sdk/lib/dispatcher';
|
||||||
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
||||||
import Promise from 'bluebird';
|
import Promise from 'bluebird';
|
||||||
import {remote, ipcRenderer, desktopCapturer} from 'electron';
|
|
||||||
import rageshake from 'matrix-react-sdk/lib/rageshake/rageshake';
|
import rageshake from 'matrix-react-sdk/lib/rageshake/rageshake';
|
||||||
|
|
||||||
remote.autoUpdater.on('update-downloaded', onUpdateDownloaded);
|
|
||||||
|
|
||||||
// try to flush the rageshake logs to indexeddb before quit.
|
|
||||||
ipcRenderer.on('before-quit', function() {
|
|
||||||
console.log('riot-desktop closing');
|
|
||||||
rageshake.flush();
|
|
||||||
});
|
|
||||||
|
|
||||||
function onUpdateDownloaded(ev: Event, releaseNotes: string, ver: string, date: Date, updateURL: string) {
|
|
||||||
dis.dispatch({
|
|
||||||
action: 'new_version',
|
|
||||||
currentVersion: remote.app.getVersion(),
|
|
||||||
newVersion: ver,
|
|
||||||
releaseNotes: releaseNotes,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function platformFriendlyName(): string {
|
function platformFriendlyName(): string {
|
||||||
console.log(window.process);
|
// used to use window.process but the same info is available here
|
||||||
switch (window.process.platform) {
|
if (navigator.userAgent.indexOf('Macintosh')) {
|
||||||
case 'darwin':
|
return 'macOS';
|
||||||
return 'macOS';
|
} else if (navigator.userAgent.indexOf('FreeBSD')) {
|
||||||
case 'freebsd':
|
return 'FreeBSD';
|
||||||
return 'FreeBSD';
|
} else if (navigator.userAgent.indexOf('OpenBSD')) {
|
||||||
case 'openbsd':
|
return 'OpenBSD';
|
||||||
return 'OpenBSD';
|
} else if (navigator.userAgent.indexOf('SunOS')) {
|
||||||
case 'sunos':
|
return 'SunOS';
|
||||||
return 'SunOS';
|
} else if (navigator.userAgent.indexOf('Windows')) {
|
||||||
case 'win32':
|
return 'Windows';
|
||||||
return 'Windows';
|
} else if (navigator.userAgent.indexOf('Linux')) {
|
||||||
default:
|
return 'Linux';
|
||||||
// Sorry, Linux users: you get lumped into here,
|
} else {
|
||||||
// but only because Linux's capitalisation is
|
return 'Unknown';
|
||||||
// normal. We do care about you.
|
|
||||||
return window.process.platform[0].toUpperCase() + window.process.platform.slice(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,9 +66,11 @@ function getUpdateCheckStatus(status) {
|
||||||
export default class ElectronPlatform extends VectorBasePlatform {
|
export default class ElectronPlatform extends VectorBasePlatform {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
dis.register(_onAction);
|
|
||||||
this.updatable = Boolean(remote.autoUpdater.getFeedURL());
|
|
||||||
|
|
||||||
|
this._pendingIpcCalls = {};
|
||||||
|
this._nextIpcCallId = 0;
|
||||||
|
|
||||||
|
dis.register(_onAction);
|
||||||
/*
|
/*
|
||||||
IPC Call `check_updates` returns:
|
IPC Call `check_updates` returns:
|
||||||
true if there is an update available
|
true if there is an update available
|
||||||
|
@ -103,10 +86,28 @@ export default class ElectronPlatform extends VectorBasePlatform {
|
||||||
this.showUpdateCheck = false;
|
this.showUpdateCheck = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// try to flush the rageshake logs to indexeddb before quit.
|
||||||
|
ipcRenderer.on('before-quit', function() {
|
||||||
|
console.log('riot-desktop closing');
|
||||||
|
rageshake.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcRenderer.on('ipcReply', this._onIpcReply.bind(this));
|
||||||
|
ipcRenderer.on('update-downloaded', this.onUpdateDownloaded.bind(this));
|
||||||
|
|
||||||
this.startUpdateCheck = this.startUpdateCheck.bind(this);
|
this.startUpdateCheck = this.startUpdateCheck.bind(this);
|
||||||
this.stopUpdateCheck = this.stopUpdateCheck.bind(this);
|
this.stopUpdateCheck = this.stopUpdateCheck.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onUpdateDownloaded(ev, updateInfo) {
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'new_version',
|
||||||
|
currentVersion: await this.getAppVersion(),
|
||||||
|
newVersion: updateInfo,
|
||||||
|
releaseNotes: updateInfo.releaseNotes,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getHumanReadableName(): string {
|
getHumanReadableName(): string {
|
||||||
return 'Electron Platform'; // no translation required: only used for analytics
|
return 'Electron Platform'; // no translation required: only used for analytics
|
||||||
}
|
}
|
||||||
|
@ -133,7 +134,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
|
||||||
// maybe we should pass basic styling (italics, bold, underline) through from MD
|
// maybe we should pass basic styling (italics, bold, underline) through from MD
|
||||||
// we only have to strip out < and > as the spec doesn't include anything about things like &
|
// we only have to strip out < and > as the spec doesn't include anything about things like &
|
||||||
// so we shouldn't assume that all implementations will treat those properly. Very basic tag parsing is done.
|
// so we shouldn't assume that all implementations will treat those properly. Very basic tag parsing is done.
|
||||||
if (window.process.platform === 'linux') {
|
if (navigator.userAgent.indexOf('Linux')) {
|
||||||
msg = msg.replace(/</g, '<').replace(/>/g, '>');
|
msg = msg.replace(/</g, '<').replace(/>/g, '>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,17 +148,13 @@ export default class ElectronPlatform extends VectorBasePlatform {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
notification.onclick = function() {
|
notification.onclick = () => {
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'view_room',
|
action: 'view_room',
|
||||||
room_id: room.roomId,
|
room_id: room.roomId,
|
||||||
});
|
});
|
||||||
global.focus();
|
global.focus();
|
||||||
const win = remote.getCurrentWindow();
|
this._ipcCall('focusWindow');
|
||||||
|
|
||||||
if (win.isMinimized()) win.restore();
|
|
||||||
else if (!win.isVisible()) win.show();
|
|
||||||
else win.focus();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return notification;
|
return notification;
|
||||||
|
@ -171,8 +168,25 @@ export default class ElectronPlatform extends VectorBasePlatform {
|
||||||
notif.close();
|
notif.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
getAppVersion(): Promise<string> {
|
async getAppVersion(): Promise<string> {
|
||||||
return Promise.resolve(remote.app.getVersion());
|
return await this._ipcCall('getAppVersion');
|
||||||
|
}
|
||||||
|
|
||||||
|
supportsAutoLaunch() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAutoLaunchEnabled() {
|
||||||
|
return await this._ipcCall('getAutoLaunchEnabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
async setAutoLaunchEnabled(enabled) {
|
||||||
|
return await this._ipcCall('setAutoLaunchEnabled', enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
async canSelfUpdate(): boolean {
|
||||||
|
const feedUrl = await this._ipcCall('getUpdateFeedUrl');
|
||||||
|
return Boolean(feedUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
startUpdateCheck() {
|
startUpdateCheck() {
|
||||||
|
@ -197,52 +211,43 @@ export default class ElectronPlatform extends VectorBasePlatform {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
isElectron(): boolean { return true; }
|
|
||||||
|
|
||||||
requestNotificationPermission(): Promise<string> {
|
requestNotificationPermission(): Promise<string> {
|
||||||
return Promise.resolve('granted');
|
return Promise.resolve('granted');
|
||||||
}
|
}
|
||||||
|
|
||||||
reload() {
|
reload() {
|
||||||
remote.getCurrentWebContents().reload();
|
// we used to remote to the main process to get it to
|
||||||
|
// reload the webcontents, but in practice this is unnecessary:
|
||||||
|
// the normal way works fine.
|
||||||
|
window.location.reload(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BEGIN copied and slightly-modified code
|
async _ipcCall(name, ...args) {
|
||||||
* setupScreenSharingForIframe function from:
|
const ipcCallId = ++this._nextIpcCallId;
|
||||||
* https://github.com/jitsi/jitsi-meet-electron-utils
|
return new Promise((resolve, reject) => {
|
||||||
* Copied directly here to avoid the need for a native electron module for
|
this._pendingIpcCalls[ipcCallId] = {resolve, reject};
|
||||||
* 'just a bit of JavaScript'
|
window.ipcRenderer.send('ipcCall', {id: ipcCallId, name, args});
|
||||||
* NOTE: Apache v2.0 licensed
|
// Maybe add a timeout to these? Probably not necessary.
|
||||||
*/
|
});
|
||||||
setupScreenSharingForIframe(iframe: Object) {
|
}
|
||||||
iframe.contentWindow.JitsiMeetElectron = {
|
|
||||||
/**
|
_onIpcReply(ev, payload) {
|
||||||
* Get sources available for screensharing. The callback is invoked
|
if (payload.id === undefined) {
|
||||||
* with an array of DesktopCapturerSources.
|
console.warn("Ignoring IPC reply with no ID");
|
||||||
*
|
return;
|
||||||
* @param {Function} callback - The success callback.
|
}
|
||||||
* @param {Function} errorCallback - The callback for errors.
|
|
||||||
* @param {Object} options - Configuration for getting sources.
|
if (this._pendingIpcCalls[payload.id] === undefined) {
|
||||||
* @param {Array} options.types - Specify the desktop source types
|
console.warn("Unknown IPC payload ID: " + payload.id);
|
||||||
* to get, with valid sources being "window" and "screen".
|
return;
|
||||||
* @param {Object} options.thumbnailSize - Specify how big the
|
}
|
||||||
* preview images for the sources should be. The valid keys are
|
|
||||||
* height and width, e.g. { height: number, width: number}. By
|
const callbacks = this._pendingIpcCalls[payload.id];
|
||||||
* default electron will return images with height and width of
|
delete this._pendingIpcCalls[payload.id];
|
||||||
* 150px.
|
if (payload.error) {
|
||||||
*/
|
callbacks.reject(payload.error);
|
||||||
obtainDesktopStreams(callback, errorCallback, options = {}) {
|
} else {
|
||||||
desktopCapturer.getSources(options,
|
callbacks.resolve(payload.reply);
|
||||||
(error, sources) => {
|
}
|
||||||
if (error) {
|
|
||||||
errorCallback(error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(sources);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
/* END of copied and slightly-modified code */
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016 Aviral Dasgupta
|
Copyright 2016 Aviral Dasgupta
|
||||||
Copyright 2016 OpenMarket Ltd
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2018 New Vector Ltd
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -45,7 +46,6 @@ export default class VectorBasePlatform extends BasePlatform {
|
||||||
this.favicon = new Favico({animation: 'none'});
|
this.favicon = new Favico({animation: 'none'});
|
||||||
this.showUpdateCheck = false;
|
this.showUpdateCheck = false;
|
||||||
this._updateFavicon();
|
this._updateFavicon();
|
||||||
this.updatable = true;
|
|
||||||
|
|
||||||
this.startUpdateCheck = this.startUpdateCheck.bind(this);
|
this.startUpdateCheck = this.startUpdateCheck.bind(this);
|
||||||
this.stopUpdateCheck = this.stopUpdateCheck.bind(this);
|
this.stopUpdateCheck = this.stopUpdateCheck.bind(this);
|
||||||
|
@ -88,6 +88,19 @@ export default class VectorBasePlatform extends BasePlatform {
|
||||||
this._updateFavicon();
|
this._updateFavicon();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
supportsAutoLaunch() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX: Surely this should be a setting like any other?
|
||||||
|
async getAutoLaunchEnabled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async setAutoLaunchEnabled(enabled) {
|
||||||
|
throw new Error("Unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begin update polling, if applicable
|
* Begin update polling, if applicable
|
||||||
*/
|
*/
|
||||||
|
@ -97,8 +110,8 @@ export default class VectorBasePlatform extends BasePlatform {
|
||||||
/**
|
/**
|
||||||
* Whether we can call checkForUpdate on this platform build
|
* Whether we can call checkForUpdate on this platform build
|
||||||
*/
|
*/
|
||||||
canSelfUpdate(): boolean {
|
async canSelfUpdate(): boolean {
|
||||||
return this.updatable;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
startUpdateCheck() {
|
startUpdateCheck() {
|
||||||
|
|
|
@ -142,6 +142,10 @@ export default class WebPlatform extends VectorBasePlatform {
|
||||||
setInterval(this.pollForUpdate.bind(this), POKE_RATE_MS);
|
setInterval(this.pollForUpdate.bind(this), POKE_RATE_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async canSelfUpdate(): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
pollForUpdate() {
|
pollForUpdate() {
|
||||||
return this._getVersion().then((ver) => {
|
return this._getVersion().then((ver) => {
|
||||||
if (this.runningVersion === null) {
|
if (this.runningVersion === null) {
|
||||||
|
|
|
@ -108,11 +108,6 @@ module.exports = {
|
||||||
"matrix-js-sdk": path.resolve('./node_modules/matrix-js-sdk'),
|
"matrix-js-sdk": path.resolve('./node_modules/matrix-js-sdk'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
externals: {
|
|
||||||
// Don't try to bundle electron: leave it as a commonjs dependency
|
|
||||||
// (the 'commonjs' here means it will output a 'require')
|
|
||||||
"electron": "commonjs electron",
|
|
||||||
},
|
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
'process.env': {
|
'process.env': {
|
||||||
|
|
Loading…
Reference in a new issue