Page MenuHomePhabricator

D11272.id38055.diff
No OneTemporary

D11272.id38055.diff

diff --git a/web/crypto/olm-api.js b/web/crypto/olm-api.js
--- a/web/crypto/olm-api.js
+++ b/web/crypto/olm-api.js
@@ -17,6 +17,11 @@
shouldRotatePrekey,
} from 'lib/utils/olm-utils.js';
+import { getCommSharedWorker } from '../shared-worker/shared-worker-provider.js';
+import { getOlmWasmPath } from '../shared-worker/utils/constants.js';
+import { workerRequestMessageTypes } from '../types/worker-types.js';
+
+const usingSharedWorker = false;
// methods below are just mocks to SQLite API
// implement proper methods tracked in ENG-6462
@@ -36,7 +41,15 @@
const olmAPI: OlmAPI = {
async initializeCryptoAccount(): Promise<void> {
- await olm.init();
+ if (usingSharedWorker) {
+ const sharedWorker = await getCommSharedWorker();
+ await sharedWorker.schedule({
+ type: workerRequestMessageTypes.INITIALIZE_CRYPTO_ACCOUNT,
+ olmWasmPath: getOlmWasmPath(),
+ });
+ } else {
+ await olm.init();
+ }
},
async encrypt(content: string, deviceID: string): Promise<string> {
const session = getOlmSession(deviceID);
diff --git a/web/push-notif/push-notifs-handler.js b/web/push-notif/push-notifs-handler.js
--- a/web/push-notif/push-notifs-handler.js
+++ b/web/push-notif/push-notifs-handler.js
@@ -22,15 +22,9 @@
import PushNotifModal from '../modals/push-notif-modal.react.js';
import { updateNavInfoActionType } from '../redux/action-types.js';
import { useSelector } from '../redux/redux-utils.js';
-import {
- WORKERS_MODULES_DIR_PATH,
- DEFAULT_OLM_FILENAME,
-} from '../shared-worker/utils/constants.js';
+import { getOlmWasmPath } from '../shared-worker/utils/constants.js';
import { useStaffCanSee } from '../utils/staff-utils.js';
-declare var baseURL: string;
-declare var olmFilename: string;
-
function useCreateDesktopPushSubscription() {
const dispatchActionPromise = useDispatchActionPromise();
const callSetDeviceToken = useSetDeviceTokenFanout();
@@ -106,11 +100,10 @@
return;
}
- const origin = window.location.origin;
- const olmWasmDirPath = `${origin}${baseURL}${WORKERS_MODULES_DIR_PATH}`;
- const olmWasmFilename = olmFilename ? olmFilename : DEFAULT_OLM_FILENAME;
- const olmWasmPath = `${olmWasmDirPath}/${olmWasmFilename}`;
- workerRegistration.active?.postMessage({ olmWasmPath, staffCanSee });
+ workerRegistration.active?.postMessage({
+ olmWasmPath: getOlmWasmPath(),
+ staffCanSee,
+ });
const subscription = await workerRegistration.pushManager.subscribe({
userVisibleOnly: true,
diff --git a/web/shared-worker/utils/constants.js b/web/shared-worker/utils/constants.js
--- a/web/shared-worker/utils/constants.js
+++ b/web/shared-worker/utils/constants.js
@@ -46,3 +46,12 @@
description: 'Comm encrypted database storage',
version: '1.0',
};
+
+declare var baseURL: string;
+declare var olmFilename: string;
+export function getOlmWasmPath(): string {
+ const origin = window.location.origin;
+ const olmWasmDirPath = `${origin}${baseURL}${WORKERS_MODULES_DIR_PATH}`;
+ const olmWasmFilename = olmFilename ? olmFilename : DEFAULT_OLM_FILENAME;
+ return `${olmWasmDirPath}/${olmWasmFilename}`;
+}
diff --git a/web/shared-worker/worker/shared-worker.js b/web/shared-worker/worker/shared-worker.js
--- a/web/shared-worker/worker/shared-worker.js
+++ b/web/shared-worker/worker/shared-worker.js
@@ -7,6 +7,7 @@
getClientStoreFromQueryExecutor,
processDBStoreOperations,
} from './process-operations.js';
+import { clearCryptoStore, processAppOlmApiRequest } from './worker-crypto.js';
import {
getDBModule,
getSQLiteQueryExecutor,
@@ -29,6 +30,7 @@
workerResponseMessageTypes,
type WorkerRequestProxyMessage,
workerWriteRequests,
+ workerOlmAPIRequests,
} from '../../types/worker-types.js';
import { getDatabaseModule } from '../db-module.js';
import {
@@ -189,6 +191,7 @@
await Promise.all(promises);
return undefined;
} else if (message.type === workerRequestMessageTypes.CLEAR_SENSITIVE_DATA) {
+ clearCryptoStore();
encryptionKey = null;
await localforage.clear();
if (dbModule && sqliteQueryExecutor) {
@@ -229,8 +232,9 @@
}
// write operations
- if (!workerWriteRequests.includes(message.type)) {
- throw new Error('Request type not supported');
+ const isOlmAPIRequest = workerOlmAPIRequests.includes(message.type);
+ if (!workerWriteRequests.includes(message.type) && !isOlmAPIRequest) {
+ throw new Error(`Request type ${message.type} not supported`);
}
if (!sqliteQueryExecutor || !dbModule) {
throw new Error(
@@ -238,7 +242,11 @@
);
}
- if (message.type === workerRequestMessageTypes.PROCESS_STORE_OPERATIONS) {
+ if (isOlmAPIRequest) {
+ await processAppOlmApiRequest(message);
+ } else if (
+ message.type === workerRequestMessageTypes.PROCESS_STORE_OPERATIONS
+ ) {
processDBStoreOperations(
sqliteQueryExecutor,
message.storeOperations,
diff --git a/web/shared-worker/worker/worker-crypto.js b/web/shared-worker/worker/worker-crypto.js
new file mode 100644
--- /dev/null
+++ b/web/shared-worker/worker/worker-crypto.js
@@ -0,0 +1,167 @@
+// @flow
+
+import olm from '@commapp/olm';
+import uuid from 'uuid';
+
+import type { CryptoStore, PickledOLMAccount } from 'lib/types/crypto-types.js';
+
+import { getProcessingStoreOpsExceptionMessage } from './process-operations.js';
+import { getDBModule, getSQLiteQueryExecutor } from './worker-database.js';
+import {
+ type WorkerRequestMessage,
+ type WorkerResponseMessage,
+ workerRequestMessageTypes,
+} from '../../types/worker-types.js';
+
+type WorkerCryptoStore = {
+ +contentAccountPickleKey: string,
+ +contentAccount: olm.Account,
+ +notificationAccountPickleKey: string,
+ +notificationAccount: olm.Account,
+};
+
+let cryptoStore: ?WorkerCryptoStore = null;
+
+function clearCryptoStore() {
+ cryptoStore = null;
+}
+
+function persistCryptoStore() {
+ const sqliteQueryExecutor = getSQLiteQueryExecutor();
+ const dbModule = getDBModule();
+ if (!sqliteQueryExecutor || !dbModule) {
+ throw new Error('Database not initialized');
+ }
+ if (!cryptoStore) {
+ throw new Error("CryptoStore doesn't exist");
+ }
+
+ const {
+ contentAccountPickleKey,
+ contentAccount,
+ notificationAccountPickleKey,
+ notificationAccount,
+ } = cryptoStore;
+
+ const pickledContentAccount: PickledOLMAccount = {
+ picklingKey: contentAccountPickleKey,
+ pickledAccount: contentAccount.pickle(contentAccountPickleKey),
+ };
+
+ const pickledNotificationAccount: PickledOLMAccount = {
+ picklingKey: notificationAccountPickleKey,
+ pickledAccount: notificationAccount.pickle(notificationAccountPickleKey),
+ };
+
+ try {
+ sqliteQueryExecutor.storeOlmPersistAccount(
+ sqliteQueryExecutor.getContentAccountID(),
+ JSON.stringify(pickledContentAccount),
+ );
+ sqliteQueryExecutor.storeOlmPersistAccount(
+ sqliteQueryExecutor.getNotifsAccountID(),
+ JSON.stringify(pickledNotificationAccount),
+ );
+ } catch (err) {
+ throw new Error(getProcessingStoreOpsExceptionMessage(err, dbModule));
+ }
+}
+
+function getOrCreateOlmAccount(accountIDInDB: number): {
+ +picklingKey: string,
+ +account: olm.Account,
+} {
+ const sqliteQueryExecutor = getSQLiteQueryExecutor();
+ const dbModule = getDBModule();
+ if (!sqliteQueryExecutor || !dbModule) {
+ throw new Error('Database not initialized');
+ }
+
+ const account = new olm.Account();
+ let picklingKey;
+
+ let accountDBString;
+ try {
+ accountDBString =
+ sqliteQueryExecutor.getOlmPersistAccountDataWeb(accountIDInDB);
+ } catch (err) {
+ throw new Error(getProcessingStoreOpsExceptionMessage(err, dbModule));
+ }
+
+ if (accountDBString.isNull) {
+ picklingKey = uuid.v4();
+ account.create();
+ } else {
+ const dbAccount: PickledOLMAccount = JSON.parse(accountDBString.value);
+ picklingKey = dbAccount.picklingKey;
+ account.unpickle(picklingKey, dbAccount.pickledAccount);
+ }
+
+ return { picklingKey, account };
+}
+
+function unpickleInitialCryptoStoreAccount(
+ account: PickledOLMAccount,
+): olm.Account {
+ const { picklingKey, pickledAccount } = account;
+ const olmAccount = new olm.Account();
+ olmAccount.unpickle(picklingKey, pickledAccount);
+ return olmAccount;
+}
+
+async function initializeCryptoAccount(
+ olmWasmPath: string,
+ initialCryptoStore: ?CryptoStore,
+) {
+ const sqliteQueryExecutor = getSQLiteQueryExecutor();
+ if (!sqliteQueryExecutor) {
+ throw new Error('Database not initialized');
+ }
+
+ await olm.init({ locateFile: () => olmWasmPath });
+
+ if (initialCryptoStore) {
+ cryptoStore = {
+ contentAccountPickleKey: initialCryptoStore.primaryAccount.picklingKey,
+ contentAccount: unpickleInitialCryptoStoreAccount(
+ initialCryptoStore.primaryAccount,
+ ),
+ notificationAccountPickleKey:
+ initialCryptoStore.notificationAccount.picklingKey,
+ notificationAccount: unpickleInitialCryptoStoreAccount(
+ initialCryptoStore.notificationAccount,
+ ),
+ };
+ persistCryptoStore();
+ return;
+ }
+
+ const contentAccountResult = getOrCreateOlmAccount(
+ sqliteQueryExecutor.getContentAccountID(),
+ );
+ const notificationAccountResult = getOrCreateOlmAccount(
+ sqliteQueryExecutor.getNotifsAccountID(),
+ );
+
+ cryptoStore = {
+ contentAccountPickleKey: contentAccountResult.picklingKey,
+ contentAccount: contentAccountResult.account,
+ notificationAccountPickleKey: notificationAccountResult.picklingKey,
+ notificationAccount: notificationAccountResult.account,
+ };
+
+ persistCryptoStore();
+}
+
+async function processAppOlmApiRequest(
+ message: WorkerRequestMessage,
+): Promise<?WorkerResponseMessage> {
+ if (message.type === workerRequestMessageTypes.INITIALIZE_CRYPTO_ACCOUNT) {
+ await initializeCryptoAccount(
+ message.olmWasmPath,
+ message.initialCryptoStore,
+ );
+ }
+}
+
+export { clearCryptoStore, processAppOlmApiRequest };
diff --git a/web/types/worker-types.js b/web/types/worker-types.js
--- a/web/types/worker-types.js
+++ b/web/types/worker-types.js
@@ -1,6 +1,7 @@
// @flow
import type { AuthMetadata } from 'lib/shared/identity-client-context.js';
+import type { CryptoStore } from 'lib/types/crypto-types.js';
import type {
ClientDBStore,
ClientDBStoreOperations,
@@ -20,6 +21,7 @@
REMOVE_PERSIST_STORAGE_ITEM: 9,
CLEAR_SENSITIVE_DATA: 10,
BACKUP_RESTORE: 11,
+ INITIALIZE_CRYPTO_ACCOUNT: 12,
});
export const workerWriteRequests: $ReadOnlyArray<number> = [
@@ -28,6 +30,11 @@
workerRequestMessageTypes.SET_PERSIST_STORAGE_ITEM,
workerRequestMessageTypes.REMOVE_PERSIST_STORAGE_ITEM,
workerRequestMessageTypes.BACKUP_RESTORE,
+ workerRequestMessageTypes.INITIALIZE_CRYPTO_ACCOUNT,
+];
+
+export const workerOlmAPIRequests: $ReadOnlyArray<number> = [
+ workerRequestMessageTypes.INITIALIZE_CRYPTO_ACCOUNT,
];
export type PingWorkerRequestMessage = {
@@ -41,6 +48,7 @@
+commQueryExecutorFilename: ?string,
+encryptionKey?: ?SubtleCrypto$JsonWebKey,
+backupClientFilename?: ?string,
+ +initialCryptoStore?: CryptoStore,
};
export type GenerateDatabaseEncryptionKeyRequestMessage = {
@@ -93,6 +101,12 @@
+backupLogDataKey: string,
};
+export type InitializeCryptoAccountRequestMessage = {
+ +type: 12,
+ +olmWasmPath: string,
+ +initialCryptoStore?: CryptoStore,
+};
+
export type WorkerRequestMessage =
| PingWorkerRequestMessage
| InitWorkerRequestMessage
@@ -105,7 +119,8 @@
| SetPersistStorageItemRequestMessage
| RemovePersistStorageItemRequestMessage
| ClearSensitiveDataRequestMessage
- | BackupRestoreRequestMessage;
+ | BackupRestoreRequestMessage
+ | InitializeCryptoAccountRequestMessage;
export type WorkerRequestProxyMessage = {
+id: number,

File Metadata

Mime Type
text/plain
Expires
Tue, Nov 26, 3:19 AM (21 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2582276
Default Alt Text
D11272.id38055.diff (11 KB)

Event Timeline