Add preliminary message backup harness
This commit is contained in:
parent
231bf91a22
commit
d85a1d5074
38 changed files with 2997 additions and 121 deletions
|
@ -26,6 +26,7 @@ import createTaskWithTimeout from './TaskWithTimeout';
|
|||
import * as Bytes from '../Bytes';
|
||||
import * as Errors from '../types/errors';
|
||||
import { senderCertificateService } from '../services/senderCertificate';
|
||||
import { backupsService } from '../services/backups';
|
||||
import {
|
||||
deriveAccessKey,
|
||||
generateRegistrationId,
|
||||
|
@ -123,6 +124,7 @@ type CreateAccountSharedOptionsType = Readonly<{
|
|||
pniKeyPair: KeyPairType;
|
||||
profileKey: Uint8Array;
|
||||
masterKey: Uint8Array | undefined;
|
||||
backupFile?: Uint8Array;
|
||||
}>;
|
||||
|
||||
type CreatePrimaryDeviceOptionsType = Readonly<{
|
||||
|
@ -213,6 +215,11 @@ function signedPreKeyToUploadSignedPreKey({
|
|||
};
|
||||
}
|
||||
|
||||
export type ConfirmNumberResultType = Readonly<{
|
||||
deviceName: string;
|
||||
backupFile: Uint8Array | undefined;
|
||||
}>;
|
||||
|
||||
export default class AccountManager extends EventTarget {
|
||||
pending: Promise<void>;
|
||||
|
||||
|
@ -339,7 +346,7 @@ export default class AccountManager extends EventTarget {
|
|||
|
||||
async registerSecondDevice(
|
||||
setProvisioningUrl: (url: string) => void,
|
||||
confirmNumber: (number?: string) => Promise<string>
|
||||
confirmNumber: (number?: string) => Promise<ConfirmNumberResultType>
|
||||
): Promise<void> {
|
||||
const provisioningCipher = new ProvisioningCipher();
|
||||
const pubKey = await provisioningCipher.getPublicKey();
|
||||
|
@ -407,7 +414,9 @@ export default class AccountManager extends EventTarget {
|
|||
const provisionMessage = await provisioningCipher.decrypt(envelope);
|
||||
|
||||
await this.queueTask(async () => {
|
||||
const deviceName = await confirmNumber(provisionMessage.number);
|
||||
const { deviceName, backupFile } = await confirmNumber(
|
||||
provisionMessage.number
|
||||
);
|
||||
if (typeof deviceName !== 'string' || deviceName.length === 0) {
|
||||
throw new Error(
|
||||
'AccountManager.registerSecondDevice: Invalid device name'
|
||||
|
@ -443,6 +452,7 @@ export default class AccountManager extends EventTarget {
|
|||
pniKeyPair: provisionMessage.pniKeyPair,
|
||||
profileKey: provisionMessage.profileKey,
|
||||
deviceName,
|
||||
backupFile,
|
||||
userAgent: provisionMessage.userAgent,
|
||||
ourAci,
|
||||
ourPni,
|
||||
|
@ -1018,6 +1028,7 @@ export default class AccountManager extends EventTarget {
|
|||
masterKey,
|
||||
readReceipts,
|
||||
userAgent,
|
||||
backupFile,
|
||||
} = options;
|
||||
|
||||
const { storage } = window.textsecure;
|
||||
|
@ -1049,7 +1060,7 @@ export default class AccountManager extends EventTarget {
|
|||
const numberChanged =
|
||||
!previousACI && previousNumber && previousNumber !== number;
|
||||
|
||||
if (uuidChanged || numberChanged) {
|
||||
if (uuidChanged || numberChanged || backupFile !== undefined) {
|
||||
if (uuidChanged) {
|
||||
log.warn(
|
||||
'createAccount: New uuid is different from old uuid; deleting all previous data'
|
||||
|
@ -1060,6 +1071,11 @@ export default class AccountManager extends EventTarget {
|
|||
'createAccount: New number is different from old number; deleting all previous data'
|
||||
);
|
||||
}
|
||||
if (backupFile !== undefined) {
|
||||
log.warn(
|
||||
'createAccount: Restoring from backup; deleting all previous data'
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
await storage.protocol.removeAllData();
|
||||
|
@ -1200,17 +1216,13 @@ export default class AccountManager extends EventTarget {
|
|||
// This needs to be done very early, because it changes how things are saved in the
|
||||
// database. Your identity, for example, in the saveIdentityWithAttributes call
|
||||
// below.
|
||||
const { conversation } = window.ConversationController.maybeMergeContacts({
|
||||
window.ConversationController.maybeMergeContacts({
|
||||
aci: ourAci,
|
||||
pni: ourPni,
|
||||
e164: number,
|
||||
reason: 'createAccount',
|
||||
});
|
||||
|
||||
if (!conversation) {
|
||||
throw new Error('registrationDone: no conversation!');
|
||||
}
|
||||
|
||||
const identityAttrs = {
|
||||
firstUse: true,
|
||||
timestamp: Date.now(),
|
||||
|
@ -1317,6 +1329,10 @@ export default class AccountManager extends EventTarget {
|
|||
uploadKeys(ServiceIdKind.ACI),
|
||||
uploadKeys(ServiceIdKind.PNI),
|
||||
]);
|
||||
|
||||
if (backupFile !== undefined) {
|
||||
await backupsService.importBackup(backupFile);
|
||||
}
|
||||
}
|
||||
|
||||
// Exposed only for testing
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue