-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8003 from vector-im/develop
Merge develop into experimental
- Loading branch information
Showing
22 changed files
with
860 additions
and
178 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
Contributing code to Riot | ||
========================= | ||
|
||
Riot follows the same pattern as https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.rst. | ||
Riot follows the same pattern as https://github.com/matrix-org/matrix-js-sdk/blob/master/CONTRIBUTING.rst. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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. | ||
|
@@ -23,16 +24,23 @@ 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, protocol} = require('electron'); | ||
const AutoLaunch = require('auto-launch'); | ||
const path = require('path'); | ||
|
||
const tray = require('./tray'); | ||
const vectorMenu = require('./vectormenu'); | ||
const webContentsHandler = require('./webcontents-handler'); | ||
const updater = require('./updater'); | ||
const { migrateFromOldOrigin } = require('./originMigrator'); | ||
|
||
const windowStateKeeper = require('electron-window-state'); | ||
|
||
// boolean flag set whilst we are doing one-time origin migration | ||
// We only serve the origin migration script while we're actually | ||
// migrating to mitigate any risk of it being used maliciously. | ||
let migratingOrigin = false; | ||
|
||
if (argv['profile']) { | ||
app.setPath('userData', `${app.getPath('userData')}-${argv['profile']}`); | ||
} | ||
|
@@ -97,27 +105,75 @@ 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, | ||
}); | ||
}); | ||
|
||
app.commandLine.appendSwitch('--enable-usermedia-screen-capturing'); | ||
ipcMain.on('ipcCall', async function(ev, payload) { | ||
if (!mainWindow) return; | ||
|
||
const shouldQuit = app.makeSingleInstance((commandLine, workingDirectory) => { | ||
// If other instance launched with --hidden then skip showing window | ||
if (commandLine.includes('--hidden')) return; | ||
const args = payload.args || []; | ||
let ret; | ||
|
||
// Someone tried to run a second instance, we should focus our window. | ||
if (mainWindow) { | ||
if (!mainWindow.isVisible()) mainWindow.show(); | ||
if (mainWindow.isMinimized()) mainWindow.restore(); | ||
mainWindow.focus(); | ||
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(); | ||
} | ||
case 'origin_migrate': | ||
migratingOrigin = true; | ||
await migrateFromOldOrigin(); | ||
migratingOrigin = false; | ||
break; | ||
default: | ||
mainWindow.webContents.send('ipcReply', { | ||
id: payload.id, | ||
error: "Unknown IPC Call: " + payload.name, | ||
}); | ||
return; | ||
} | ||
|
||
mainWindow.webContents.send('ipcReply', { | ||
id: payload.id, | ||
reply: ret, | ||
}); | ||
}); | ||
|
||
if (shouldQuit) { | ||
app.commandLine.appendSwitch('--enable-usermedia-screen-capturing'); | ||
|
||
const gotLock = app.requestSingleInstanceLock(); | ||
if (!gotLock) { | ||
console.log('Other instance detected: exiting'); | ||
app.exit(); | ||
} | ||
|
||
|
||
const launcher = new AutoLaunch({ | ||
name: vectorConfig.brand || 'Riot', | ||
isHidden: true, | ||
|
@@ -126,39 +182,12 @@ 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); | ||
} | ||
}); | ||
// 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']) { | ||
|
@@ -175,6 +204,66 @@ 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('/'); | ||
|
||
// path starts with a '/' | ||
if (target[0] !== '') { | ||
callback({error: -6}); // FILE_NOT_FOUND | ||
return; | ||
} | ||
|
||
if (target[target.length - 1] == '') { | ||
target[target.length - 1] = 'index.html'; | ||
} | ||
|
||
let baseDir; | ||
// first part of the path determines where we serve from | ||
if (migratingOrigin && target[1] === 'origin_migrator_dest') { | ||
// the origin migrator destination page | ||
// (only the destination script needs to come from the | ||
// custom protocol: the source part is loaded from a | ||
// file:// as that's the origin we're migrating from). | ||
baseDir = __dirname + "/../../origin_migrator/dest"; | ||
} else if (target[1] === 'webapp') { | ||
baseDir = __dirname + "/../../webapp"; | ||
} else { | ||
callback({error: -6}); // FILE_NOT_FOUND | ||
return; | ||
} | ||
|
||
// Normalise the base dir and the target path separately, then make sure | ||
// the target path isn't trying to back out beyond its root | ||
baseDir = path.normalize(baseDir); | ||
|
||
const relTarget = path.normalize(path.join(...target.slice(2))); | ||
if (relTarget.startsWith('..')) { | ||
callback({error: -6}); // FILE_NOT_FOUND | ||
return; | ||
} | ||
const absTarget = path.join(baseDir, 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']}`); | ||
|
@@ -191,6 +280,7 @@ app.on('ready', () => { | |
defaultHeight: 768, | ||
}); | ||
|
||
const preloadScript = path.normalize(`${__dirname}/preload.js`); | ||
mainWindow = global.mainWindow = new BrowserWindow({ | ||
icon: iconPath, | ||
show: false, | ||
|
@@ -200,8 +290,20 @@ 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`); | ||
mainWindow.loadURL('vector://vector/webapp/'); | ||
Menu.setApplicationMenu(vectorMenu); | ||
|
||
// explicitly hide because setApplicationMenu on Linux otherwise shows... | ||
|
@@ -268,6 +370,18 @@ app.on('before-quit', () => { | |
} | ||
}); | ||
|
||
app.on('second-instance', (ev, commandLine, workingDirectory) => { | ||
// If other instance launched with --hidden then skip showing window | ||
if (commandLine.includes('--hidden')) return; | ||
|
||
// Someone tried to run a second instance, we should focus our window. | ||
if (mainWindow) { | ||
if (!mainWindow.isVisible()) mainWindow.show(); | ||
if (mainWindow.isMinimized()) mainWindow.restore(); | ||
mainWindow.focus(); | ||
} | ||
}); | ||
|
||
// Set the App User Model ID to match what the squirrel | ||
// installer uses for the shortcut icon. | ||
// This makes notifications work on windows 8.1 (and is | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* | ||
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. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
const { BrowserWindow, ipcMain } = require('electron'); | ||
const path = require('path'); | ||
|
||
async function migrateFromOldOrigin() { | ||
console.log("Attempting to migrate data between origins"); | ||
|
||
// We can use the same preload script: we just need ipcRenderer exposed | ||
const preloadScript = path.normalize(`${__dirname}/preload.js`); | ||
await new Promise(resolve => { | ||
const migrateWindow = new BrowserWindow({ | ||
show: false, | ||
webPreferences: { | ||
preload: preloadScript, | ||
nodeIntegration: false, | ||
sandbox: true, | ||
enableRemoteModule: false, | ||
webgl: false, | ||
}, | ||
}); | ||
ipcMain.on('origin_migration_complete', (e, success, sentSummary, storedSummary) => { | ||
if (success) { | ||
console.log("Origin migration completed successfully!"); | ||
} else { | ||
console.error("Origin migration failed!"); | ||
} | ||
console.error("Data sent", sentSummary); | ||
console.error("Data stored", storedSummary); | ||
migrateWindow.close(); | ||
resolve(); | ||
}); | ||
ipcMain.on('origin_migration_nodata', (e) => { | ||
console.log("No session to migrate from old origin"); | ||
migrateWindow.close(); | ||
resolve(); | ||
}); | ||
// Normalise the path because in the distribution, __dirname will be inside the | ||
// electron asar. | ||
const sourcePagePath = path.normalize(__dirname + '/../../origin_migrator/source.html'); | ||
console.log("Loading path: " + sourcePagePath); | ||
migrateWindow.loadURL('file://' + sourcePagePath); | ||
}); | ||
} | ||
|
||
module.exports = { | ||
migrateFromOldOrigin, | ||
}; |
Oops, something went wrong.