diff --git a/web/shared-worker/types/sqlite-query-executor.js b/web/shared-worker/types/sqlite-query-executor.js --- a/web/shared-worker/types/sqlite-query-executor.js +++ b/web/shared-worker/types/sqlite-query-executor.js @@ -33,7 +33,7 @@ +extras: string, }; -type OlmPersistSession = { +export type OlmPersistSession = { +targetUserID: string, +sessionData: string, }; diff --git a/web/shared-worker/worker/worker-crypto.js b/web/shared-worker/worker/worker-crypto.js --- a/web/shared-worker/worker/worker-crypto.js +++ b/web/shared-worker/worker/worker-crypto.js @@ -13,6 +13,7 @@ IdentityNewDeviceKeyUpload, IdentityExistingDeviceKeyUpload, } from 'lib/types/identity-service-types.js'; +import { entries } from 'lib/utils/objects.js'; import { retrieveIdentityKeysAndPrekeys, retrieveAccountKeysSet, @@ -25,10 +26,12 @@ type WorkerResponseMessage, workerRequestMessageTypes, } from '../../types/worker-types.js'; +import type { OlmPersistSession } from '../types/sqlite-query-executor.js'; type WorkerCryptoStore = { +contentAccountPickleKey: string, +contentAccount: olm.Account, + +contentSessions: { [deviceID: string]: olm.Session }, +notificationAccountPickleKey: string, +notificationAccount: olm.Account, }; @@ -54,6 +57,7 @@ const { contentAccountPickleKey, contentAccount, + contentSessions, notificationAccountPickleKey, notificationAccount, } = cryptoStore; @@ -63,6 +67,13 @@ pickledAccount: contentAccount.pickle(contentAccountPickleKey), }; + const pickledContentSessions: OlmPersistSession[] = entries( + contentSessions, + ).map(([deviceID, session]) => ({ + targetUserID: deviceID, + sessionData: session.pickle(contentAccountPickleKey), + })); + const pickledNotificationAccount: PickledOLMAccount = { picklingKey: notificationAccountPickleKey, pickledAccount: notificationAccount.pickle(notificationAccountPickleKey), @@ -73,6 +84,9 @@ sqliteQueryExecutor.getContentAccountID(), JSON.stringify(pickledContentAccount), ); + for (const pickledSession of pickledContentSessions) { + sqliteQueryExecutor.storeOlmPersistSession(pickledSession); + } sqliteQueryExecutor.storeOlmPersistAccount( sqliteQueryExecutor.getNotifsAccountID(), JSON.stringify(pickledNotificationAccount), @@ -115,6 +129,34 @@ return { picklingKey, account }; } +function getOlmSessions(picklingKey: string): { + [deviceID: string]: olm.Session, +} { + const sqliteQueryExecutor = getSQLiteQueryExecutor(); + const dbModule = getDBModule(); + if (!sqliteQueryExecutor || !dbModule) { + throw new Error( + "Couldn't get olm sessions because database is not initialized", + ); + } + + let sessionsData; + try { + sessionsData = sqliteQueryExecutor.getOlmPersistSessionsData(); + } catch (err) { + throw new Error(getProcessingStoreOpsExceptionMessage(err, dbModule)); + } + + const sessions: { [deviceID: string]: olm.Session } = {}; + for (const sessionData of sessionsData) { + const session = new olm.Session(); + session.unpickle(picklingKey, sessionData.sessionData); + sessions[sessionData.targetUserID] = session; + } + + return sessions; +} + function unpickleInitialCryptoStoreAccount( account: PickledOLMAccount, ): olm.Account { @@ -141,6 +183,7 @@ contentAccount: unpickleInitialCryptoStoreAccount( initialCryptoStore.primaryAccount, ), + contentSessions: {}, notificationAccountPickleKey: initialCryptoStore.notificationAccount.picklingKey, notificationAccount: unpickleInitialCryptoStoreAccount( @@ -154,6 +197,7 @@ const contentAccountResult = getOrCreateOlmAccount( sqliteQueryExecutor.getContentAccountID(), ); + const contentSessions = getOlmSessions(contentAccountResult.picklingKey); const notificationAccountResult = getOrCreateOlmAccount( sqliteQueryExecutor.getNotifsAccountID(), ); @@ -161,6 +205,7 @@ cryptoStore = { contentAccountPickleKey: contentAccountResult.picklingKey, contentAccount: contentAccountResult.account, + contentSessions, notificationAccountPickleKey: notificationAccountResult.picklingKey, notificationAccount: notificationAccountResult.account, };