Move conversations to SQLCipher

This commit is contained in:
Scott Nonnenberg 2018-09-20 18:47:19 -07:00
parent 8cd3db0262
commit cd60bdd08a
31 changed files with 1354 additions and 774 deletions

View file

@ -1,13 +1,13 @@
/* global Backbone: false */
/* global $: false */
/* global dcodeIO: false */
/* global ConversationController: false */
/* global getAccountManager: false */
/* global Signal: false */
/* global storage: false */
/* global textsecure: false */
/* global Whisper: false */
/* global wrapDeferred: false */
/* global _: false */
// eslint-disable-next-line func-names
@ -125,8 +125,16 @@
const { IdleDetector, MessageDataMigrator } = Signal.Workflow;
const { Errors, Message } = window.Signal.Types;
const { upgradeMessageSchema } = window.Signal.Migrations;
const { Migrations0DatabaseWithAttachmentData } = window.Signal.Migrations;
const {
upgradeMessageSchema,
writeNewAttachmentData,
deleteAttachmentData,
getCurrentVersion,
} = window.Signal.Migrations;
const {
Migrations0DatabaseWithAttachmentData,
Migrations1DatabaseWithoutAttachmentData,
} = window.Signal.Migrations;
const { Views } = window.Signal;
// Implicitly used in `indexeddb-backbonejs-adapter`:
@ -183,6 +191,9 @@
logger: window.log,
});
const latestDBVersion2 = await getCurrentVersion();
Whisper.Database.migrations[0].version = latestDBVersion2;
window.log.info('Storage fetch');
storage.fetch();
@ -337,9 +348,18 @@
await upgradeMessages();
const db = await Whisper.Database.open();
const totalMessages = await MessageDataMigrator.getNumMessages({
connection: db,
});
let totalMessages;
try {
totalMessages = await MessageDataMigrator.getNumMessages({
connection: db,
});
} catch (error) {
window.log.error(
'background.getNumMessages error:',
error && error.stack ? error.stack : error
);
totalMessages = 0;
}
function showMigrationStatus(current) {
const status = `${current}/${totalMessages}`;
@ -350,23 +370,41 @@
if (totalMessages) {
window.log.info(`About to migrate ${totalMessages} messages`);
showMigrationStatus(0);
await window.Signal.migrateToSQL({
db,
clearStores: Whisper.Database.clearStores,
handleDOMException: Whisper.Database.handleDOMException,
arrayBufferToString:
textsecure.MessageReceiver.arrayBufferToStringBase64,
countCallback: count => {
window.log.info(`Migration: ${count} messages complete`);
showMigrationStatus(count);
},
});
} else {
window.log.info('About to migrate non-messages');
}
await window.Signal.migrateToSQL({
db,
clearStores: Whisper.Database.clearStores,
handleDOMException: Whisper.Database.handleDOMException,
arrayBufferToString: textsecure.MessageReceiver.arrayBufferToStringBase64,
countCallback: count => {
window.log.info(`Migration: ${count} messages complete`);
showMigrationStatus(count);
},
writeNewAttachmentData,
});
db.close();
Views.Initialization.setMessage(window.i18n('optimizingApplication'));
window.log.info('Running cleanup IndexedDB migrations...');
await Whisper.Database.close();
// Now we clean up IndexedDB database after extracting data from it
await Migrations1DatabaseWithoutAttachmentData.run({
Backbone,
logger: window.log,
});
const latestDBVersion = _.last(
Migrations1DatabaseWithoutAttachmentData.migrations
).version;
Whisper.Database.migrations[0].version = latestDBVersion;
window.log.info('Cleanup: starting...');
const messagesForCleanup = await window.Signal.Data.getOutgoingWithoutExpiresAt(
{
@ -844,7 +882,10 @@
}
if (details.profileKey) {
conversation.set({ profileKey: details.profileKey });
const profileKey = dcodeIO.ByteBuffer.wrap(details.profileKey).toString(
'base64'
);
conversation.set({ profileKey });
}
if (typeof details.blocked !== 'undefined') {
@ -855,14 +896,29 @@
}
}
await wrapDeferred(
conversation.save({
name: details.name,
avatar: details.avatar,
color: details.color,
active_at: activeAt,
})
);
conversation.set({
name: details.name,
color: details.color,
active_at: activeAt,
});
// Update the conversation avatar only if new avatar exists and hash differs
const { avatar } = details;
if (avatar && avatar.data) {
const newAttributes = await window.Signal.Types.Conversation.maybeUpdateAvatar(
conversation.attributes,
avatar.data,
{
writeNewAttachmentData,
deleteAttachmentData,
}
);
conversation.set(newAttributes);
}
await window.Signal.Data.updateConversation(id, conversation.attributes, {
Conversation: Whisper.Conversation,
});
const { expireTimer } = details;
const isValidExpireTimer = typeof expireTimer === 'number';
if (isValidExpireTimer) {
@ -901,12 +957,13 @@
id,
'group'
);
const updates = {
name: details.name,
members: details.members,
avatar: details.avatar,
type: 'group',
};
if (details.active) {
const activeAt = conversation.get('active_at');
@ -926,7 +983,25 @@
storage.removeBlockedGroup(id);
}
await wrapDeferred(conversation.save(updates));
conversation.set(updates);
// Update the conversation avatar only if new avatar exists and hash differs
const { avatar } = details;
if (avatar && avatar.data) {
const newAttributes = await window.Signal.Types.Conversation.maybeUpdateAvatar(
conversation.attributes,
avatar.data,
{
writeNewAttachmentData,
deleteAttachmentData,
}
);
conversation.set(newAttributes);
}
await window.Signal.Data.updateConversation(id, conversation.attributes, {
Conversation: Whisper.Conversation,
});
const { expireTimer } = details;
const isValidExpireTimer = typeof expireTimer === 'number';
if (!isValidExpireTimer) {
@ -1077,12 +1152,15 @@
confirm,
messageDescriptor,
}) {
const profileKey = data.message.profileKey.toArrayBuffer();
const profileKey = data.message.profileKey.toString('base64');
const sender = await ConversationController.getOrCreateAndWait(
messageDescriptor.id,
'private'
);
// Will do the save for us
await sender.setProfileKey(profileKey);
return confirm();
}
@ -1097,11 +1175,17 @@
confirm,
messageDescriptor,
}) {
const { id, type } = messageDescriptor;
const conversation = await ConversationController.getOrCreateAndWait(
messageDescriptor.id,
messageDescriptor.type
id,
type
);
await wrapDeferred(conversation.save({ profileSharing: true }));
conversation.set({ profileSharing: true });
await window.Signal.Data.updateConversation(id, conversation.attributes, {
Conversation: Whisper.Conversation,
});
return confirm();
}
@ -1174,6 +1258,7 @@
Whisper.Registration.remove();
const NUMBER_ID_KEY = 'number_id';
const VERSION_KEY = 'version';
const LAST_PROCESSED_INDEX_KEY = 'attachmentMigration_lastProcessedIndex';
const IS_MIGRATION_COMPLETE_KEY = 'attachmentMigration_isComplete';
@ -1203,6 +1288,7 @@
LAST_PROCESSED_INDEX_KEY,
lastProcessedIndex || null
);
textsecure.storage.put(VERSION_KEY, window.getVersion());
window.log.info('Successfully cleared local configuration');
} catch (eraseError) {
@ -1262,7 +1348,9 @@
ev.confirm();
}
await wrapDeferred(conversation.save());
await window.Signal.Data.updateConversation(id, conversation.attributes, {
Conversation: Whisper.Conversation,
});
}
throw error;