forked from matrix/element-web
Remove rest of the origin migrator
This commit is contained in:
parent
33284302b9
commit
bd57ff793f
|
@ -64,11 +64,6 @@ if (argv["help"]) {
|
||||||
app.exit();
|
app.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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-dir']) {
|
if (argv['profile-dir']) {
|
||||||
app.setPath('userData', argv['profile-dir']);
|
app.setPath('userData', argv['profile-dir']);
|
||||||
} else if (argv['profile']) {
|
} else if (argv['profile']) {
|
||||||
|
@ -231,17 +226,6 @@ ipcMain.on('ipcCall', async function(ev, payload) {
|
||||||
mainWindow.focus();
|
mainWindow.focus();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'origin_migrate':
|
|
||||||
// NB. The code to call this has now been removed so this
|
|
||||||
// should never be called. This code itself has been removed
|
|
||||||
// with the migration to the riot-desktop repo, with the
|
|
||||||
// expectation that this version will go away and be superseeded
|
|
||||||
// by the riot-desktop version, after which this version will
|
|
||||||
// be removed and all the origin migrationm code will go away.
|
|
||||||
migratingOrigin = true;
|
|
||||||
await migrateFromOldOrigin();
|
|
||||||
migratingOrigin = false;
|
|
||||||
break;
|
|
||||||
case 'getConfig':
|
case 'getConfig':
|
||||||
ret = vectorConfig;
|
ret = vectorConfig;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
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,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const onOriginMigrationComplete = (e, success, sentSummary, storedSummary) => {
|
|
||||||
// we use once but we'll only get one of these events,
|
|
||||||
// so remove the listener for the other one
|
|
||||||
ipcMain.removeListener('origin_migration_nodata', onOriginMigrationNoData);
|
|
||||||
|
|
||||||
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();
|
|
||||||
};
|
|
||||||
const onOriginMigrationNoData = (e, success, sentSummary, storedSummary) => {
|
|
||||||
ipcMain.removeListener('origin_migration_complete', onOriginMigrationComplete);
|
|
||||||
|
|
||||||
console.log("No session to migrate from old origin");
|
|
||||||
migrateWindow.close();
|
|
||||||
resolve();
|
|
||||||
};
|
|
||||||
|
|
||||||
ipcMain.once('origin_migration_complete', onOriginMigrationComplete);
|
|
||||||
ipcMain.once('origin_migration_nodata', onOriginMigrationNoData);
|
|
||||||
|
|
||||||
// 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,
|
|
||||||
};
|
|
File diff suppressed because one or more lines are too long
|
@ -1,6 +0,0 @@
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
<script src="browser-matrix.min.js"></script>
|
|
||||||
<script src="dest.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,125 +0,0 @@
|
||||||
/*
|
|
||||||
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 SOURCE_ORIGIN = 'file://';
|
|
||||||
|
|
||||||
const IndexedDBCryptoStore = window.matrixcs.IndexedDBCryptoStore;
|
|
||||||
const cryptoStore = new IndexedDBCryptoStore(window.indexedDB, 'matrix-js-sdk:crypto');
|
|
||||||
|
|
||||||
let accountStored = 0;
|
|
||||||
let sessionsStored = 0;
|
|
||||||
let inboundGroupSessionsStored = 0;
|
|
||||||
let deviceDataStored = 0;
|
|
||||||
let roomsStored = 0;
|
|
||||||
let localStorageKeysStored = 0;
|
|
||||||
|
|
||||||
const promises = [];
|
|
||||||
|
|
||||||
async function onMessage(e) {
|
|
||||||
if (e.origin !== SOURCE_ORIGIN) return;
|
|
||||||
|
|
||||||
const data = e.data.data; // bleh, naming clash
|
|
||||||
switch (e.data.cmd) {
|
|
||||||
case 'init':
|
|
||||||
// start with clean stores before we migrate data in
|
|
||||||
window.localStorage.clear();
|
|
||||||
await cryptoStore.deleteAllData();
|
|
||||||
|
|
||||||
e.source.postMessage({
|
|
||||||
cmd: 'initOK',
|
|
||||||
}, SOURCE_ORIGIN);
|
|
||||||
break;
|
|
||||||
case 'storeAccount':
|
|
||||||
promises.push(cryptoStore.doTxn(
|
|
||||||
'readwrite', [IndexedDBCryptoStore.STORE_ACCOUNT],
|
|
||||||
(txn) => {
|
|
||||||
cryptoStore.storeAccount(txn, data);
|
|
||||||
},
|
|
||||||
).then(() => {
|
|
||||||
++accountStored;
|
|
||||||
}));
|
|
||||||
break;
|
|
||||||
case 'storeSessions':
|
|
||||||
promises.push(cryptoStore.doTxn(
|
|
||||||
'readwrite', [IndexedDBCryptoStore.STORE_SESSIONS],
|
|
||||||
(txn) => {
|
|
||||||
for (const sess of data) {
|
|
||||||
cryptoStore.storeEndToEndSession(sess.deviceKey, sess.sessionId, sess, txn);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
).then(() => {
|
|
||||||
sessionsStored += data.length;
|
|
||||||
}));
|
|
||||||
break;
|
|
||||||
case 'storeInboundGroupSessions':
|
|
||||||
promises.push(cryptoStore.doTxn(
|
|
||||||
'readwrite', [IndexedDBCryptoStore.STORE_INBOUND_GROUP_SESSIONS],
|
|
||||||
(txn) => {
|
|
||||||
for (const sess of data) {
|
|
||||||
cryptoStore.addEndToEndInboundGroupSession(
|
|
||||||
sess.senderKey, sess.sessionId, sess.sessionData, txn,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
).then(() => {
|
|
||||||
inboundGroupSessionsStored += data.length;
|
|
||||||
}));
|
|
||||||
break;
|
|
||||||
case 'storeDeviceData':
|
|
||||||
promises.push(cryptoStore.doTxn(
|
|
||||||
'readwrite', [IndexedDBCryptoStore.STORE_DEVICE_DATA],
|
|
||||||
(txn) => {
|
|
||||||
cryptoStore.storeEndToEndDeviceData(data, txn);
|
|
||||||
},
|
|
||||||
).then(() => {
|
|
||||||
++deviceDataStored;
|
|
||||||
}));
|
|
||||||
break;
|
|
||||||
case 'storeRooms':
|
|
||||||
promises.push(cryptoStore.doTxn(
|
|
||||||
'readwrite', [IndexedDBCryptoStore.STORE_ROOMS],
|
|
||||||
(txn) => {
|
|
||||||
for (const [roomId, roomInfo] of Object.entries(data)) {
|
|
||||||
cryptoStore.storeEndToEndRoom(roomId, roomInfo, txn);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
).then(() => {
|
|
||||||
++roomsStored;
|
|
||||||
}));
|
|
||||||
break;
|
|
||||||
case 'storeLocalStorage':
|
|
||||||
window.localStorage.setItem(data.key, data.val);
|
|
||||||
++localStorageKeysStored;
|
|
||||||
break;
|
|
||||||
case 'getSummary':
|
|
||||||
await Promise.all(promises);
|
|
||||||
e.source.postMessage({
|
|
||||||
cmd: 'summary',
|
|
||||||
data: {
|
|
||||||
accountStored,
|
|
||||||
sessionsStored,
|
|
||||||
inboundGroupSessionsStored,
|
|
||||||
deviceDataStored,
|
|
||||||
roomsStored,
|
|
||||||
localStorageKeysStored,
|
|
||||||
},
|
|
||||||
}, SOURCE_ORIGIN);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('message', onMessage);
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
<script src="dest/browser-matrix.min.js"></script>
|
|
||||||
<script src="source.js"></script>
|
|
||||||
<iframe name="dest" src="vector://vector/origin_migrator_dest/dest.html" onload="doMigrate()"></iframe>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,210 +0,0 @@
|
||||||
/*
|
|
||||||
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 TARGET_ORIGIN = 'vector://vector';
|
|
||||||
const BATCH_SIZE = 500;
|
|
||||||
let destFrame;
|
|
||||||
|
|
||||||
let initResolver = null;
|
|
||||||
let getSummaryResolver = null;
|
|
||||||
|
|
||||||
function onMessage(e) {
|
|
||||||
if (e.origin !== TARGET_ORIGIN) return;
|
|
||||||
|
|
||||||
if (e.data.cmd === 'initOK' && initResolver) {
|
|
||||||
initResolver();
|
|
||||||
initResolver = null;
|
|
||||||
} else if (e.data.cmd === 'summary' && getSummaryResolver) {
|
|
||||||
getSummaryResolver(e.data.data);
|
|
||||||
getSummaryResolver = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function initDestFrame() {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
initResolver = resolve;
|
|
||||||
destFrame.postMessage({
|
|
||||||
cmd: 'init',
|
|
||||||
}, TARGET_ORIGIN);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getSummary() {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
getSummaryResolver = resolve;
|
|
||||||
destFrame.postMessage({
|
|
||||||
cmd: 'getSummary',
|
|
||||||
}, TARGET_ORIGIN);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function doMigrate() {
|
|
||||||
let accountSent = 0;
|
|
||||||
let sessionsSent = 0;
|
|
||||||
let inboundGroupSessionsSent = 0;
|
|
||||||
let deviceDataSent = 0;
|
|
||||||
let roomsSent = 0;
|
|
||||||
let localStorageKeysSent = 0;
|
|
||||||
|
|
||||||
if (!window.ipcRenderer) {
|
|
||||||
console.error("ipcRenderer not found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window.localStorage.getItem('mx_user_id') === null) {
|
|
||||||
window.ipcRenderer.send("origin_migration_nodata");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
destFrame = window.parent.frames.dest;
|
|
||||||
|
|
||||||
await initDestFrame();
|
|
||||||
|
|
||||||
const IndexedDBCryptoStore = window.matrixcs.IndexedDBCryptoStore;
|
|
||||||
|
|
||||||
const cryptoStore = new IndexedDBCryptoStore(window.indexedDB, 'matrix-js-sdk:crypto');
|
|
||||||
|
|
||||||
await cryptoStore.doTxn(
|
|
||||||
'readonly', [IndexedDBCryptoStore.STORE_ACCOUNT],
|
|
||||||
(txn) => {
|
|
||||||
cryptoStore.getAccount(txn, (account) => {
|
|
||||||
destFrame.postMessage({
|
|
||||||
cmd: 'storeAccount',
|
|
||||||
data: account,
|
|
||||||
}, TARGET_ORIGIN);
|
|
||||||
++accountSent;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await cryptoStore.doTxn(
|
|
||||||
'readonly', [IndexedDBCryptoStore.STORE_SESSIONS],
|
|
||||||
(txn) => {
|
|
||||||
let sessBatch = [];
|
|
||||||
cryptoStore.getAllEndToEndSessions(txn, (sessInfo) => {
|
|
||||||
if (sessInfo) {
|
|
||||||
++sessionsSent;
|
|
||||||
sessBatch.push(sessInfo);
|
|
||||||
}
|
|
||||||
if (sessBatch.length >= BATCH_SIZE || sessInfo === null) {
|
|
||||||
destFrame.postMessage({
|
|
||||||
cmd: 'storeSessions',
|
|
||||||
data: sessBatch,
|
|
||||||
}, TARGET_ORIGIN);
|
|
||||||
sessBatch = [];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await cryptoStore.doTxn(
|
|
||||||
'readonly', [IndexedDBCryptoStore.STORE_INBOUND_GROUP_SESSIONS],
|
|
||||||
(txn) => {
|
|
||||||
let sessBatch = [];
|
|
||||||
cryptoStore.getAllEndToEndInboundGroupSessions(txn, (sessInfo) => {
|
|
||||||
if (sessInfo) {
|
|
||||||
++inboundGroupSessionsSent;
|
|
||||||
sessBatch.push(sessInfo);
|
|
||||||
}
|
|
||||||
if (sessBatch.length >= BATCH_SIZE || sessInfo === null) {
|
|
||||||
destFrame.postMessage({
|
|
||||||
cmd: 'storeInboundGroupSessions',
|
|
||||||
data: sessBatch,
|
|
||||||
}, TARGET_ORIGIN);
|
|
||||||
sessBatch = [];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await cryptoStore.doTxn(
|
|
||||||
'readonly', [IndexedDBCryptoStore.STORE_DEVICE_DATA],
|
|
||||||
(txn) => {
|
|
||||||
cryptoStore.getEndToEndDeviceData(txn, (deviceData) => {
|
|
||||||
destFrame.postMessage({
|
|
||||||
cmd: 'storeDeviceData',
|
|
||||||
data: deviceData,
|
|
||||||
}, TARGET_ORIGIN);
|
|
||||||
++deviceDataSent;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await cryptoStore.doTxn(
|
|
||||||
'readonly', [IndexedDBCryptoStore.STORE_ROOMS],
|
|
||||||
(txn) => {
|
|
||||||
cryptoStore.getEndToEndRooms(txn, (rooms) => {
|
|
||||||
destFrame.postMessage({
|
|
||||||
cmd: 'storeRooms',
|
|
||||||
data: rooms,
|
|
||||||
}, TARGET_ORIGIN);
|
|
||||||
++roomsSent;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
// we don't bother migrating;
|
|
||||||
// * sync data (we can just initialsync again)
|
|
||||||
// * logs
|
|
||||||
// * key requests (worst case they'll just be re-sent)
|
|
||||||
// * sessions needing backup (feature isn't available on Electron)
|
|
||||||
|
|
||||||
for (let i = 0; i < window.localStorage.length; ++i) {
|
|
||||||
const key = window.localStorage.key(i);
|
|
||||||
const val = window.localStorage.getItem(key);
|
|
||||||
|
|
||||||
destFrame.postMessage({
|
|
||||||
cmd: 'storeLocalStorage',
|
|
||||||
data: { key, val },
|
|
||||||
}, TARGET_ORIGIN);
|
|
||||||
++localStorageKeysSent;
|
|
||||||
}
|
|
||||||
|
|
||||||
const summary = await getSummary();
|
|
||||||
let success = false;
|
|
||||||
if (
|
|
||||||
summary.accountStored === accountSent &&
|
|
||||||
summary.sessionsStored === sessionsSent &&
|
|
||||||
summary.inboundGroupSessionsStored === inboundGroupSessionsSent &&
|
|
||||||
summary.deviceDataStored === deviceDataSent &&
|
|
||||||
summary.roomsStored === roomsSent &&
|
|
||||||
summary.localStorageKeysStored === localStorageKeysSent
|
|
||||||
) {
|
|
||||||
success = true;
|
|
||||||
window.localStorage.clear();
|
|
||||||
await cryptoStore.deleteAllData();
|
|
||||||
|
|
||||||
// we don't bother migrating them, but also blow away the sync & logs db,
|
|
||||||
// otherwise they'll just hang about taking up space
|
|
||||||
await new Promise(resolve => {
|
|
||||||
const req = window.indexedDB.deleteDatabase('matrix-js-sdk:riot-web-sync');
|
|
||||||
req.onsuccess = resolve;
|
|
||||||
req.onerror = resolve;
|
|
||||||
});
|
|
||||||
await new Promise(resolve => {
|
|
||||||
const req = window.indexedDB.deleteDatabase('logs');
|
|
||||||
req.onsuccess = resolve;
|
|
||||||
req.onerror = resolve;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
window.ipcRenderer.send("origin_migration_complete", success, {
|
|
||||||
accountSent, sessionsSent, inboundGroupSessionsSent,
|
|
||||||
deviceDataSent, roomsSent, localStorageKeysSent,
|
|
||||||
}, summary);
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('message', onMessage);
|
|
|
@ -165,8 +165,7 @@
|
||||||
"from": "electron_app/img",
|
"from": "electron_app/img",
|
||||||
"to": "img"
|
"to": "img"
|
||||||
},
|
},
|
||||||
"webapp/**/*",
|
"webapp/**/*"
|
||||||
"origin_migrator/**/*"
|
|
||||||
],
|
],
|
||||||
"linux": {
|
"linux": {
|
||||||
"target": "deb",
|
"target": "deb",
|
||||||
|
|
|
@ -190,7 +190,7 @@ module.exports = {
|
||||||
chunks: ['mobileguide'],
|
chunks: ['mobileguide'],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
devtool: 'source-map',
|
devtool: 'eval-source-map',
|
||||||
|
|
||||||
// configuration for the webpack-dev-server
|
// configuration for the webpack-dev-server
|
||||||
devServer: {
|
devServer: {
|
||||||
|
|
Loading…
Reference in New Issue