Use base64 strings for incoming message cache instead of binary

pull/1/head
Scott Nonnenberg 7 years ago
parent 9eefc0c29b
commit 7983300f4a

@ -338,7 +338,8 @@
db, db,
clearStores: Whisper.Database.clearStores, clearStores: Whisper.Database.clearStores,
handleDOMException: Whisper.Database.handleDOMException, handleDOMException: Whisper.Database.handleDOMException,
arrayBufferToString: textsecure.MessageReceiver.arrayBufferToString, arrayBufferToString:
textsecure.MessageReceiver.arrayBufferToStringBase64,
countCallback: count => { countCallback: count => {
window.log.info(`Migration: ${count} messages complete`); window.log.info(`Migration: ${count} messages complete`);
showMigrationStatus(count); showMigrationStatus(count);

@ -59,7 +59,6 @@ module.exports = {
getUnprocessedById, getUnprocessedById,
saveUnprocessed, saveUnprocessed,
saveUnprocesseds, saveUnprocesseds,
updateUnprocessed,
removeUnprocessed, removeUnprocessed,
removeAllUnprocessed, removeAllUnprocessed,
@ -374,19 +373,6 @@ async function saveUnprocesseds(arrayOfUnprocessed, { forceSave } = {}) {
}); });
} }
async function updateUnprocessed(id, updates) {
const existing = await channels.getUnprocessedById(id);
if (!existing) {
throw new Error(`Unprocessed id ${id} does not exist in the database!`);
}
const toSave = {
...existing,
...updates,
};
await saveUnprocessed(toSave);
}
async function removeUnprocessed(id) { async function removeUnprocessed(id) {
await channels.removeUnprocessed(id); await channels.removeUnprocessed(id);
} }

@ -86,6 +86,11 @@ async function migrateToSQL({
forEach(array, item => { forEach(array, item => {
// In the new database, we can't store ArrayBuffers, so we turn these two fields // In the new database, we can't store ArrayBuffers, so we turn these two fields
// into strings like MessageReceiver now does before save. // into strings like MessageReceiver now does before save.
// Need to set it to version two, since we're using Base64 strings now
// eslint-disable-next-line no-param-reassign
item.version = 2;
if (item.envelope) { if (item.envelope) {
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
item.envelope = arrayBufferToString(item.envelope); item.envelope = arrayBufferToString(item.envelope);

@ -942,6 +942,9 @@
getAllUnprocessed() { getAllUnprocessed() {
return window.Signal.Data.getAllUnprocessed(); return window.Signal.Data.getAllUnprocessed();
}, },
getUnprocessedById(id) {
return window.Signal.Data.getUnprocessedById(id, { Unprocessed });
},
addUnprocessed(data) { addUnprocessed(data) {
// We need to pass forceSave because the data has an id already, which will cause // We need to pass forceSave because the data has an id already, which will cause
// an update instead of an insert. // an update instead of an insert.
@ -950,8 +953,8 @@
Unprocessed, Unprocessed,
}); });
}, },
updateUnprocessed(id, updates) { saveUnprocessed(data) {
return window.Signal.Data.updateUnprocessed(id, updates, { Unprocessed }); return window.Signal.Data.saveUnprocessed(data, { Unprocessed });
}, },
removeUnprocessed(id) { removeUnprocessed(id) {
return window.Signal.Data.removeUnprocessed(id, { Unprocessed }); return window.Signal.Data.removeUnprocessed(id, { Unprocessed });

@ -35,6 +35,10 @@ MessageReceiver.stringToArrayBuffer = string =>
dcodeIO.ByteBuffer.wrap(string, 'binary').toArrayBuffer(); dcodeIO.ByteBuffer.wrap(string, 'binary').toArrayBuffer();
MessageReceiver.arrayBufferToString = arrayBuffer => MessageReceiver.arrayBufferToString = arrayBuffer =>
dcodeIO.ByteBuffer.wrap(arrayBuffer).toString('binary'); dcodeIO.ByteBuffer.wrap(arrayBuffer).toString('binary');
MessageReceiver.stringToArrayBufferBase64 = string =>
dcodeIO.ByteBuffer.wrap(string, 'base64').toArrayBuffer();
MessageReceiver.arrayBufferToStringBase64 = arrayBuffer =>
dcodeIO.ByteBuffer.wrap(arrayBuffer).toString('base64');
MessageReceiver.prototype = new textsecure.EventTarget(); MessageReceiver.prototype = new textsecure.EventTarget();
MessageReceiver.prototype.extend({ MessageReceiver.prototype.extend({
@ -275,6 +279,12 @@ MessageReceiver.prototype.extend({
try { try {
let envelopePlaintext = item.envelope; let envelopePlaintext = item.envelope;
if (item.version === 2) {
envelopePlaintext = MessageReceiver.stringToArrayBufferBase64(
envelopePlaintext
);
}
if (typeof envelopePlaintext === 'string') { if (typeof envelopePlaintext === 'string') {
envelopePlaintext = MessageReceiver.stringToArrayBuffer( envelopePlaintext = MessageReceiver.stringToArrayBuffer(
envelopePlaintext envelopePlaintext
@ -285,6 +295,13 @@ MessageReceiver.prototype.extend({
const { decrypted } = item; const { decrypted } = item;
if (decrypted) { if (decrypted) {
let payloadPlaintext = decrypted; let payloadPlaintext = decrypted;
if (item.version === 2) {
payloadPlaintext = MessageReceiver.stringToArrayBufferBase64(
payloadPlaintext
);
}
if (typeof payloadPlaintext === 'string') { if (typeof payloadPlaintext === 'string') {
payloadPlaintext = MessageReceiver.stringToArrayBuffer( payloadPlaintext = MessageReceiver.stringToArrayBuffer(
payloadPlaintext payloadPlaintext
@ -339,7 +356,7 @@ MessageReceiver.prototype.extend({
); );
return textsecure.storage.unprocessed.remove(item.id); return textsecure.storage.unprocessed.remove(item.id);
} }
return textsecure.storage.unprocessed.update(item.id, { attempts }); return textsecure.storage.unprocessed.save({ ...item, attempts });
}) })
).then( ).then(
() => items, () => items,
@ -357,18 +374,33 @@ MessageReceiver.prototype.extend({
const id = this.getEnvelopeId(envelope); const id = this.getEnvelopeId(envelope);
const data = { const data = {
id, id,
envelope: MessageReceiver.arrayBufferToString(plaintext), version: 2,
envelope: MessageReceiver.arrayBufferToStringBase64(plaintext),
timestamp: Date.now(), timestamp: Date.now(),
attempts: 1, attempts: 1,
}; };
return textsecure.storage.unprocessed.add(data); return textsecure.storage.unprocessed.add(data);
}, },
updateCache(envelope, plaintext) { async updateCache(envelope, plaintext) {
const id = this.getEnvelopeId(envelope); const id = this.getEnvelopeId(envelope);
const data = { const item = await textsecure.storage.unprocessed.get(id);
decrypted: MessageReceiver.arrayBufferToString(plaintext), if (!item) {
}; window.log.error(
return textsecure.storage.unprocessed.update(id, data); `updateCache: Didn't find item ${id} in cache to update`
);
return null;
}
if (item.get('version') === 2) {
item.set(
'decrypted',
MessageReceiver.arrayBufferToStringBase64(plaintext)
);
} else {
item.set('decrypted', MessageReceiver.arrayBufferToString(plaintext));
}
return textsecure.storage.unprocessed.save(item.attributes);
}, },
removeFromCache(envelope) { removeFromCache(envelope) {
const id = this.getEnvelopeId(envelope); const id = this.getEnvelopeId(envelope);
@ -1189,3 +1221,7 @@ textsecure.MessageReceiver.stringToArrayBuffer =
MessageReceiver.stringToArrayBuffer; MessageReceiver.stringToArrayBuffer;
textsecure.MessageReceiver.arrayBufferToString = textsecure.MessageReceiver.arrayBufferToString =
MessageReceiver.arrayBufferToString; MessageReceiver.arrayBufferToString;
textsecure.MessageReceiver.stringToArrayBufferBase64 =
MessageReceiver.stringToArrayBufferBase64;
textsecure.MessageReceiver.arrayBufferToStringBase64 =
MessageReceiver.arrayBufferToStringBase64;

@ -12,11 +12,14 @@
getAll() { getAll() {
return textsecure.storage.protocol.getAllUnprocessed(); return textsecure.storage.protocol.getAllUnprocessed();
}, },
get(id) {
return textsecure.storage.protocol.getUnprocessedById(id);
},
add(data) { add(data) {
return textsecure.storage.protocol.addUnprocessed(data); return textsecure.storage.protocol.addUnprocessed(data);
}, },
update(id, updates) { save(data) {
return textsecure.storage.protocol.updateUnprocessed(id, updates); return textsecure.storage.protocol.saveUnprocessed(data);
}, },
remove(id) { remove(id) {
return textsecure.storage.protocol.removeUnprocessed(id); return textsecure.storage.protocol.removeUnprocessed(id);

@ -1241,12 +1241,12 @@ describe('SignalProtocolStore', function() {
}); });
}); });
it('updateUnprocessed successfully updates only part of itme', function() { it('saveUnprocessed successfully updates item', function() {
var id = 1; var id = 1;
return store return store
.addUnprocessed({ id: id, name: 'first', timestamp: 1 }) .addUnprocessed({ id: id, name: 'first', timestamp: 1 })
.then(function() { .then(function() {
return store.updateUnprocessed(id, { name: 'updated' }); return store.saveUnprocessed({ id, name: 'updated', timestamp: 1 });
}) })
.then(function() { .then(function() {
return store.getAllUnprocessed(); return store.getAllUnprocessed();

Loading…
Cancel
Save