diff --git a/keyserver/Dockerfile b/keyserver/Dockerfile --- a/keyserver/Dockerfile +++ b/keyserver/Dockerfile @@ -126,6 +126,7 @@ native/expo-modules/comm-expo-package/ COPY --chown=comm services/electron-update-server/package.json \ services/electron-update-server/ +COPY --chown=comm web/backup-client-wasm/package.json web/backup-client-wasm/ # Create empty Rust library and copy in Cargo.toml file RUN cargo init keyserver/addons/rust-node-addon --lib diff --git a/keyserver/src/responders/website-responders.js b/keyserver/src/responders/website-responders.js --- a/keyserver/src/responders/website-responders.js +++ b/keyserver/src/responders/website-responders.js @@ -44,6 +44,7 @@ +olmFilename: string, +commQueryExecutorFilename: string, +opaqueURL: string, + +backupClientFilename: string, }; let assetInfo: ?AssetInfo = null; async function getAssetInfo() { @@ -59,6 +60,7 @@ olmFilename: '', commQueryExecutorFilename: '', opaqueURL: 'http://localhost:8080/opaque-ke.wasm', + backupClientFilename: '', }; return assetInfo; } @@ -83,6 +85,7 @@ olmFilename: manifest['olm.wasm'], commQueryExecutorFilename: webworkersManifest['comm_query_executor.wasm'], opaqueURL: `compiled/${manifest['comm_opaque2_wasm_bg.wasm']}`, + backupClientFilename: webworkersManifest['backup_client_wasm_bg.wasm'], }; return assetInfo; } catch { @@ -134,6 +137,7 @@ olmFilename, opaqueURL, commQueryExecutorFilename, + backupClientFilename, } = await assetInfoPromise; // prettier-ignore @@ -185,6 +189,7 @@ var baseURL = "${baseURL}"; var olmFilename = "${olmFilename}"; var commQueryExecutorFilename = "${commQueryExecutorFilename}"; + var backupClientFilename = "${backupClientFilename}"; var opaqueURL = "${opaqueURL}"; diff --git a/web/database/database-module-provider.js b/web/database/database-module-provider.js --- a/web/database/database-module-provider.js +++ b/web/database/database-module-provider.js @@ -24,6 +24,8 @@ declare var baseURL: string; declare var commQueryExecutorFilename: string; +declare var backupClientFilename: string; + const databaseStatuses = Object.freeze({ notRunning: 'NOT_RUNNING', initSuccess: 'INIT_SUCCESS', @@ -93,6 +95,7 @@ databaseModuleFilePath: `${origin}${baseURL}${WORKERS_MODULES_DIR_PATH}`, encryptionKey, commQueryExecutorFilename, + backupClientFilename, }); this.status = { type: databaseStatuses.initSuccess }; console.info('Database initialization success'); diff --git a/web/database/utils/constants.js b/web/database/utils/constants.js --- a/web/database/utils/constants.js +++ b/web/database/utils/constants.js @@ -11,6 +11,7 @@ export const WORKERS_MODULES_DIR_PATH = '/compiled/webworkers'; export const DEFAULT_COMM_QUERY_EXECUTOR_FILENAME = 'comm_query_executor.wasm'; +export const DEFAULT_BACKUP_CLIENT_FILENAME = 'backup-client.wasm'; export const DEFAULT_OLM_FILENAME = 'olm.wasm'; diff --git a/web/database/worker/db-worker.js b/web/database/worker/db-worker.js --- a/web/database/worker/db-worker.js +++ b/web/database/worker/db-worker.js @@ -6,6 +6,7 @@ getClientStoreFromQueryExecutor, processDBStoreOperations, } from './process-operations.js'; +import initBackupClientModule from '../../backup-client-wasm/_generated/backup-client-wasm.js'; import { decryptData, encryptData, @@ -31,6 +32,7 @@ localforageConfig, SQLITE_CONTENT, SQLITE_ENCRYPTION_KEY, + DEFAULT_BACKUP_CLIENT_FILENAME, } from '../utils/constants.js'; import { clearSensitiveData, @@ -102,6 +104,19 @@ ); } +async function initBackupClient( + databaseModuleFilePath: string, + backupClientFilename: ?string, +) { + let modulePath; + if (backupClientFilename) { + modulePath = `${databaseModuleFilePath}/${backupClientFilename}`; + } else { + modulePath = `http://localhost:8080/${DEFAULT_BACKUP_CLIENT_FILENAME}`; + } + await initBackupClientModule(modulePath); +} + async function persist() { persistInProgress = true; const module = dbModule; @@ -148,11 +163,19 @@ // database operations if (message.type === workerRequestMessageTypes.INIT) { - await initDatabase( + const databasePromise = initDatabase( message.databaseModuleFilePath, message.commQueryExecutorFilename, message.encryptionKey, ); + let backupClientPromise = new Promise(resolve => resolve()); + if (!(message.backupClientFilename === undefined)) { + backupClientPromise = initBackupClient( + message.databaseModuleFilePath, + message.backupClientFilename, + ); + } + await Promise.all([databasePromise, backupClientPromise]); return undefined; } else if (message.type === workerRequestMessageTypes.CLEAR_SENSITIVE_DATA) { encryptionKey = null; 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 @@ -37,6 +37,7 @@ +databaseModuleFilePath: string, +commQueryExecutorFilename: ?string, +encryptionKey?: ?SubtleCrypto$JsonWebKey, + +backupClientFilename?: ?string, }; export type GenerateDatabaseEncryptionKeyRequestMessage = { diff --git a/web/webpack.config.cjs b/web/webpack.config.cjs --- a/web/webpack.config.cjs +++ b/web/webpack.config.cjs @@ -152,6 +152,14 @@ }, ], }), + new CopyPlugin({ + patterns: [ + { + from: 'backup-client-wasm/_generated/backup-client-wasm_bg.wasm', + to: path.join(__dirname, 'dist', 'backup-client.wasm'), + }, + ], + }), ]; const prodWebWorkersPlugins = [ @@ -181,6 +189,19 @@ }, ], }), + new CopyPlugin({ + patterns: [ + { + from: 'backup-client-wasm/_generated/backup-client-wasm_bg.wasm', + to: path.join( + __dirname, + 'dist', + 'webworkers', + 'backup-client.[contenthash:12].wasm', + ), + }, + ], + }), new WebpackManifestPlugin({ publicPath: '', }),