Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3383535
D11272.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
11 KB
Referenced Files
None
Subscribers
None
D11272.diff
View Options
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,169 @@
+// @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(
+ "Couldn't persist crypto store because database is not initialized",
+ );
+ }
+ if (!cryptoStore) {
+ throw new Error("Couldn't persist crypto store because it 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 = {
@@ -93,6 +100,12 @@
+backupLogDataKey: string,
};
+export type InitializeCryptoAccountRequestMessage = {
+ +type: 12,
+ +olmWasmPath: string,
+ +initialCryptoStore?: CryptoStore,
+};
+
export type WorkerRequestMessage =
| PingWorkerRequestMessage
| InitWorkerRequestMessage
@@ -105,7 +118,8 @@
| SetPersistStorageItemRequestMessage
| RemovePersistStorageItemRequestMessage
| ClearSensitiveDataRequestMessage
- | BackupRestoreRequestMessage;
+ | BackupRestoreRequestMessage
+ | InitializeCryptoAccountRequestMessage;
export type WorkerRequestProxyMessage = {
+id: number,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Nov 29, 4:30 PM (20 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2597473
Default Alt Text
D11272.diff (11 KB)
Attached To
Mode
D11272: [web] Add cryptoStore to shared worker
Attached
Detach File
Event Timeline
Log In to Comment