Storage Service: Write

This commit is contained in:
Josh Perez 2020-09-08 20:56:23 -04:00 committed by Scott Nonnenberg
parent 8a2c17f65f
commit 1ce0959fa1
15 changed files with 1374 additions and 540 deletions

View file

@ -549,7 +549,7 @@
window.isBeforeVersion(lastVersion, 'v1.35.0-beta.11') &&
window.isAfterVersion(lastVersion, 'v1.35.0-beta.1')
) {
await window.Signal.Util.eraseAllStorageServiceState();
await window.Signal.Services.eraseAllStorageServiceState();
}
// This one should always be last - it could restart the app
@ -2818,7 +2818,7 @@
break;
case FETCH_LATEST_ENUM.STORAGE_MANIFEST:
window.log.info('onFetchLatestSync: fetching latest manifest');
await window.Signal.Util.runStorageServiceSyncJob();
await window.Signal.Services.runStorageServiceSyncJob();
break;
default:
window.log.info(
@ -2832,6 +2832,11 @@
const { storageServiceKey } = ev;
if (storageServiceKey === null) {
window.log.info('onKeysSync: deleting storageKey');
storage.remove('storageKey');
}
if (storageServiceKey) {
window.log.info('onKeysSync: received keys');
const storageServiceKeyBase64 = window.Signal.Crypto.arrayBufferToBase64(
@ -2839,7 +2844,7 @@
);
storage.put('storageKey', storageServiceKeyBase64);
await window.Signal.Util.runStorageServiceSyncJob();
await window.Signal.Services.runStorageServiceSyncJob();
}
}

View file

@ -25,7 +25,7 @@
UNRESTRICTED: 3,
};
const { Util } = window.Signal;
const { Services, Util } = window.Signal;
const { Contact, Message } = window.Signal.Types;
const {
deleteAttachmentData,
@ -234,48 +234,84 @@
return false;
},
block() {
block({ viaStorageServiceSync = false } = {}) {
let blocked = false;
const isBlocked = this.isBlocked();
const uuid = this.get('uuid');
if (uuid) {
window.storage.addBlockedUuid(uuid);
blocked = true;
}
const e164 = this.get('e164');
if (e164) {
window.storage.addBlockedNumber(e164);
blocked = true;
}
const groupId = this.get('groupId');
if (groupId) {
window.storage.addBlockedGroup(groupId);
blocked = true;
}
if (!viaStorageServiceSync && !isBlocked && blocked) {
this.captureChange();
}
},
unblock() {
unblock({ viaStorageServiceSync = false } = {}) {
let unblocked = false;
const isBlocked = this.isBlocked();
const uuid = this.get('uuid');
if (uuid) {
window.storage.removeBlockedUuid(uuid);
unblocked = true;
}
const e164 = this.get('e164');
if (e164) {
window.storage.removeBlockedNumber(e164);
unblocked = true;
}
const groupId = this.get('groupId');
if (groupId) {
window.storage.removeBlockedGroup(groupId);
unblocked = true;
}
return false;
if (!viaStorageServiceSync && isBlocked && unblocked) {
this.captureChange();
}
return unblocked;
},
enableProfileSharing() {
enableProfileSharing({ viaStorageServiceSync = false } = {}) {
const before = this.get('profileSharing');
this.set({ profileSharing: true });
const after = this.get('profileSharing');
if (!viaStorageServiceSync && Boolean(before) !== Boolean(after)) {
this.captureChange();
}
},
disableProfileSharing() {
disableProfileSharing({ viaStorageServiceSync = false } = {}) {
const before = this.get('profileSharing');
this.set({ profileSharing: false });
const after = this.get('profileSharing');
if (!viaStorageServiceSync && Boolean(before) !== Boolean(after)) {
this.captureChange();
}
},
hasDraft() {
@ -662,7 +698,10 @@
} while (messages.length > 0);
},
async applyMessageRequestResponse(response, { fromSync = false } = {}) {
async applyMessageRequestResponse(
response,
{ fromSync = false, viaStorageServiceSync = false } = {}
) {
// Apply message request response locally
this.set({
messageRequestResponseType: response,
@ -670,8 +709,8 @@
window.Signal.Data.updateConversation(this.attributes);
if (response === this.messageRequestEnum.ACCEPT) {
this.unblock();
this.enableProfileSharing();
this.unblock({ viaStorageServiceSync });
this.enableProfileSharing({ viaStorageServiceSync });
if (!fromSync) {
this.sendProfileKeyUpdate();
@ -680,13 +719,13 @@
}
} else if (response === this.messageRequestEnum.BLOCK) {
// Block locally, other devices should block upon receiving the sync message
this.block();
this.disableProfileSharing();
this.block({ viaStorageServiceSync });
this.disableProfileSharing({ viaStorageServiceSync });
} else if (response === this.messageRequestEnum.DELETE) {
// Delete messages locally, other devices should delete upon receiving
// the sync message
this.destroyMessages();
this.disableProfileSharing();
this.disableProfileSharing({ viaStorageServiceSync });
this.updateLastMessage();
if (!fromSync) {
this.trigger('unload', 'deleted from message request');
@ -695,10 +734,10 @@
// Delete messages locally, other devices should delete upon receiving
// the sync message
this.destroyMessages();
this.disableProfileSharing();
this.disableProfileSharing({ viaStorageServiceSync });
this.updateLastMessage();
// Block locally, other devices should block upon receiving the sync message
this.block();
this.block({ viaStorageServiceSync });
// Leave group if this was a local action
if (!fromSync) {
this.leaveGroup();
@ -780,6 +819,7 @@
async _setVerified(verified, providedOptions) {
const options = providedOptions || {};
_.defaults(options, {
viaStorageServiceSync: false,
viaSyncMessage: false,
viaContactSync: false,
key: null,
@ -814,6 +854,14 @@
this.set({ verified });
window.Signal.Data.updateConversation(this.attributes);
if (
!options.viaStorageServiceSync &&
!keyChange &&
beginningVerified !== verified
) {
this.captureChange();
}
// Three situations result in a verification notice in the conversation:
// 1) The message came from an explicit verification in another client (not
// a contact sync)
@ -1982,9 +2030,17 @@
window.Signal.Data.updateConversation(this.attributes);
},
async setArchived(isArchived) {
setArchived(isArchived) {
const before = this.get('isArchived');
this.set({ isArchived });
window.Signal.Data.updateConversation(this.attributes);
const after = this.get('isArchived');
if (Boolean(before) !== Boolean(after)) {
this.captureChange();
}
},
async updateExpirationTimer(
@ -2573,7 +2629,7 @@
}
try {
await c.setProfileName(profile.name);
await c.setEncryptedProfileName(profile.name);
} catch (error) {
window.log.warn(
'getProfile decryption failure:',
@ -2598,7 +2654,7 @@
window.Signal.Data.updateConversation(c.attributes);
},
async setProfileName(encryptedName) {
async setEncryptedProfileName(encryptedName) {
if (!encryptedName) {
return;
}
@ -2648,6 +2704,10 @@
return;
}
if (this.isMe()) {
window.storage.put('avatarUrl', avatarPath);
}
const avatar = await textsecure.messaging.getAvatar(avatarPath);
const key = this.get('profileKey');
if (!key) {
@ -2675,7 +2735,7 @@
this.set(newAttributes);
}
},
async setProfileKey(profileKey) {
async setProfileKey(profileKey, { viaStorageServiceSync = false } = {}) {
// profileKey is a string so we can compare it directly
if (this.get('profileKey') !== profileKey) {
window.log.info(
@ -2689,6 +2749,10 @@
sealedSender: SEALED_SENDER.UNKNOWN,
});
if (!viaStorageServiceSync) {
this.captureChange();
}
await Promise.all([
this.deriveAccessKeyIfNeeded(),
this.deriveProfileKeyVersionIfNeeded(),
@ -2883,6 +2947,25 @@
return null;
},
// Set of items to captureChanges on:
// [-] uuid
// [-] e164
// [X] profileKey
// [-] identityKey
// [X] verified!
// [-] profileName
// [-] profileFamilyName
// [X] blocked
// [X] whitelisted
// [X] archived
captureChange() {
this.set({ needsStorageServiceSync: true });
this.queueJob(() => {
Services.storageServiceUploadJob();
});
},
async notify(message, reaction) {
if (this.get('muteExpiresAt') && Date.now() < this.get('muteExpiresAt')) {
return;

View file

@ -116,6 +116,12 @@ const {
} = require('../../ts/services/updateListener');
const { notify } = require('../../ts/services/notify');
const { calling } = require('../../ts/services/calling');
const {
eraseAllStorageServiceState,
handleUnknownRecords,
runStorageServiceSyncJob,
storageServiceUploadJob,
} = require('../../ts/services/storage');
function initializeMigrations({
userDataPath,
@ -324,10 +330,14 @@ exports.setup = (options = {}) => {
};
const Services = {
calling,
eraseAllStorageServiceState,
handleUnknownRecords,
initializeNetworkObserver,
initializeUpdateListener,
notify,
calling,
runStorageServiceSyncJob,
storageServiceUploadJob,
};
const State = {