diff --git a/ts/background.ts b/ts/background.ts index 074b82f63ed..1fc429d9600 100644 --- a/ts/background.ts +++ b/ts/background.ts @@ -246,8 +246,8 @@ export async function startApp(): Promise { }, requestChallenge(request) { - if (window.Signal.CI) { - window.Signal.CI.handleEvent('challenge', request); + if (window.SignalCI) { + window.SignalCI.handleEvent('challenge', request); return; } window.sendChallengeRequest(request); diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index bac590f7a9a..dbeeb8d1617 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -520,7 +520,7 @@ export class Message extends React.PureComponent { status === 'viewed') ) { const delta = Date.now() - timestamp; - window.Signal.CI?.handleEvent('message:send-complete', { + window.SignalCI?.handleEvent('message:send-complete', { timestamp, delta, }); diff --git a/ts/messageModifiers/MessageReceipts.ts b/ts/messageModifiers/MessageReceipts.ts index 8b33b8ad9d0..95f86367bb2 100644 --- a/ts/messageModifiers/MessageReceipts.ts +++ b/ts/messageModifiers/MessageReceipts.ts @@ -266,7 +266,7 @@ export class MessageReceipts extends Collection { // We want the above call to not be delayed when testing with // CI. - window.Signal.CI + window.SignalCI ? deleteSentProtoBatcher.flushAndWait() : Promise.resolve(), ]); diff --git a/ts/models/conversations.ts b/ts/models/conversations.ts index 3006885d247..785f27c98d5 100644 --- a/ts/models/conversations.ts +++ b/ts/models/conversations.ts @@ -5529,7 +5529,7 @@ export class ConversationModel extends window.Backbone const delta = now - startedAt; log.info(`conversation ${this.idForLogging()} open took ${delta}ms`); - window.Signal.CI?.handleEvent('conversation:open', { delta }); + window.SignalCI?.handleEvent('conversation:open', { delta }); } async flushDebouncedUpdates(): Promise { diff --git a/ts/services/calling.ts b/ts/services/calling.ts index a97e7aba51c..cf8ba761e2f 100644 --- a/ts/services/calling.ts +++ b/ts/services/calling.ts @@ -276,7 +276,7 @@ export class CallingClass { private reduxInterface?: CallingReduxInterface; - private sfuUrl?: string; + public _sfuUrl?: string; private lastMediaDeviceSettings?: MediaDeviceSettings; @@ -307,7 +307,7 @@ export class CallingClass { throw new Error('CallingClass.initialize: Invalid uxActions.'); } - this.sfuUrl = sfuUrl; + this._sfuUrl = sfuUrl; this.previousAudioDeviceModule = parseAudioDeviceModule( window.storage.get('previousAudioDeviceModule') @@ -610,7 +610,7 @@ export class CallingClass { return statefulPeekInfo; } - if (!this.sfuUrl) { + if (!this._sfuUrl) { throw new Error('Missing SFU URL; not peeking group call'); } @@ -633,7 +633,7 @@ export class CallingClass { const membershipProof = Bytes.fromString(proof); return RingRTC.peekGroupCall( - this.sfuUrl, + this._sfuUrl, Buffer.from(membershipProof), this.getGroupCallMembers(conversationId) ); @@ -669,7 +669,7 @@ export class CallingClass { return existing; } - if (!this.sfuUrl) { + if (!this._sfuUrl) { throw new Error('Missing SFU URL; not connecting group call'); } @@ -680,7 +680,7 @@ export class CallingClass { const outerGroupCall = RingRTC.getGroupCall( groupIdBuffer, - this.sfuUrl, + this._sfuUrl, Buffer.alloc(0), AUDIO_LEVEL_INTERVAL_MS, { diff --git a/ts/services/storage.ts b/ts/services/storage.ts index b8833d7534a..06ff5f734ca 100644 --- a/ts/services/storage.ts +++ b/ts/services/storage.ts @@ -1733,8 +1733,8 @@ async function sync( // We now know that we've successfully completed a storage service fetch await window.storage.put('storageFetchComplete', true); - if (window.Signal.CI) { - window.Signal.CI.handleEvent('storageServiceComplete', { + if (window.SignalCI) { + window.SignalCI.handleEvent('storageServiceComplete', { manifestVersion: version, }); } diff --git a/ts/state/smart/InstallScreen.tsx b/ts/state/smart/InstallScreen.tsx index cedc585d32c..6efb84d8591 100644 --- a/ts/state/smart/InstallScreen.tsx +++ b/ts/state/smart/InstallScreen.tsx @@ -164,9 +164,9 @@ export function SmartInstallScreen(): ReactElement { } onQrCodeScanned(); - if (window.Signal.CI) { + if (window.SignalCI) { chooseDeviceNamePromiseWrapperRef.current.resolve( - window.Signal.CI.deviceName + window.SignalCI.deviceName ); } diff --git a/ts/test-mock/playwright.ts b/ts/test-mock/playwright.ts index c6736e7a3ce..c76b149da28 100644 --- a/ts/test-mock/playwright.ts +++ b/ts/test-mock/playwright.ts @@ -89,7 +89,7 @@ export class App { const window = await this.getWindow(); await window.evaluate( - `window.Signal.CI.solveChallenge(${JSON.stringify(response)})` + `window.SignalCI.solveChallenge(${JSON.stringify(response)})` ); } @@ -105,7 +105,7 @@ export class App { const window = await this.getWindow(); const result = await window.evaluate( - `window.Signal.CI.waitForEvent(${JSON.stringify(event)})` + `window.SignalCI.waitForEvent(${JSON.stringify(event)})` ); return result as T; diff --git a/ts/textsecure/AccountManager.ts b/ts/textsecure/AccountManager.ts index cf56f6caf55..9bb6efa4722 100644 --- a/ts/textsecure/AccountManager.ts +++ b/ts/textsecure/AccountManager.ts @@ -224,7 +224,7 @@ export default class AccountManager extends EventTarget { } const url = getProvisioningUrl(uuid, pubKey); - window.Signal.CI?.setProvisioningURL(url); + window.SignalCI?.setProvisioningURL(url); setProvisioningUrl(url); request.respond(200, 'OK'); diff --git a/ts/window.d.ts b/ts/window.d.ts index 5b6ff7df76d..0c1a3b63425 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -93,6 +93,15 @@ export type IPCType = { updateTrayIcon: (count: number) => void; }; +export type FeatureFlagType = { + GV2_ENABLE_SINGLE_CHANGE_PROCESSING: boolean; + GV2_ENABLE_CHANGE_PROCESSING: boolean; + GV2_ENABLE_STATE_PROCESSING: boolean; + GV2_ENABLE_PRE_JOIN_FETCH: boolean; + GV2_MIGRATION_DISABLE_ADD: boolean; + GV2_MIGRATION_DISABLE_INVITE: boolean; +}; + export type SignalCoreType = { Crypto: typeof Crypto; Curve: typeof Curve; @@ -128,9 +137,6 @@ export type SignalCoreType = { }; conversationControllerStart: () => void; challengeHandler?: ChallengeHandler; - - // Test only - CI?: CIType; }; declare global { @@ -214,14 +220,7 @@ declare global { reduxStore: Store; // Feature Flags - Flags: { - GV2_ENABLE_SINGLE_CHANGE_PROCESSING: boolean; - GV2_ENABLE_CHANGE_PROCESSING: boolean; - GV2_ENABLE_STATE_PROCESSING: boolean; - GV2_ENABLE_PRE_JOIN_FETCH: boolean; - GV2_MIGRATION_DISABLE_ADD: boolean; - GV2_MIGRATION_DISABLE_INVITE: boolean; - }; + Flags: FeatureFlagType; // Paths BasePaths: { @@ -231,6 +230,9 @@ declare global { temp: string; }; + // Test only + SignalCI?: CIType; + // TODO DESKTOP-4801 SignalContext: SignalContextType; diff --git a/ts/windows/main/phase4-test.ts b/ts/windows/main/phase4-test.ts index 3d5cba0f5a6..94872bc3821 100644 --- a/ts/windows/main/phase4-test.ts +++ b/ts/windows/main/phase4-test.ts @@ -14,5 +14,5 @@ if (config.environment === 'test') { if (config.enableCI) { console.log('Importing CI infrastructure...'); const { getCI } = require('../../CI'); - window.Signal.CI = getCI(window.getTitle()); + window.SignalCI = getCI(window.getTitle()); } diff --git a/ts/windows/main/preload_test.ts b/ts/windows/main/preload_test.ts index 363049c1654..22e9179abab 100644 --- a/ts/windows/main/preload_test.ts +++ b/ts/windows/main/preload_test.ts @@ -9,6 +9,8 @@ import { sync } from 'fast-glob'; // eslint-disable-next-line import/no-extraneous-dependencies import { assert } from 'chai'; +import { getSignalProtocolStore } from '../../SignalProtocolStore'; + window.assert = assert; // This is a hack to let us run TypeScript tests in the renderer process. See the @@ -26,3 +28,5 @@ window.testUtilities = { }).forEach(require); }, }; + +window.getSignalProtocolStore = getSignalProtocolStore; diff --git a/ts/windows/main/start.ts b/ts/windows/main/start.ts index 3616e6413c4..acaebf73c5f 100644 --- a/ts/windows/main/start.ts +++ b/ts/windows/main/start.ts @@ -1,11 +1,10 @@ // Copyright 2017 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import { clone } from 'lodash'; +import { clone, has } from 'lodash'; import { contextBridge } from 'electron'; import * as log from '../../logging/log'; -import { SignalContext } from '../context'; import './phase1-ipc'; import '../preload'; @@ -14,10 +13,11 @@ import './phase3-post-signal'; import './phase4-test'; import '../../backbone/reliable_trigger'; -import { WebAudioRecorder } from '../../WebAudioRecorder'; -import { getSignalProtocolStore } from '../../SignalProtocolStore'; +import type { FeatureFlagType } from '../../window.d'; +import type { StorageAccessType } from '../../types/Storage.d'; import { start as startConversationController } from '../../ConversationController'; import { MessageController } from '../../util/MessageController'; +import { Environment, getEnvironment } from '../../environment'; window.addEventListener('contextmenu', e => { const node = e.target as Element | null; @@ -38,124 +38,45 @@ if (window.SignalContext.config.proxyUrl) { log.info('Using provided proxy url'); } -const isTestElectron = process.env.TEST_QUIT_ON_COMPLETE; - window.Whisper.events = clone(window.Backbone.Events); MessageController.install(); startConversationController(); -if (isTestElectron) { - window.getSignalProtocolStore = getSignalProtocolStore; -} else { - contextBridge.exposeInMainWorld('SignalContext', SignalContext); +if (getEnvironment() !== Environment.Production) { + const SignalDebug = { + Data: window.Signal.Data, + getConversation: (id: string) => window.ConversationController.get(id), + getMessageById: (id: string) => window.MessageController.getById(id), + getReduxState: () => window.reduxStore.getState(), + getSfuUrl: () => window.Signal.Services.calling._sfuUrl, + getStorageItem: (name: keyof StorageAccessType) => window.storage.get(name), + putStorageItem: ( + name: K, + value: StorageAccessType[K] + ) => window.storage.put(name, value), + setFlag: (name: keyof FeatureFlagType, value: boolean) => { + if (!has(window.Flags, name)) { + return; + } + window.Flags[name] = value; + }, + setSfuUrl: (url: string) => { + window.Signal.Services.calling._sfuUrl = url; + }, + }; - contextBridge.exposeInMainWorld('Backbone', window.Backbone); + contextBridge.exposeInMainWorld('SignalDebug', SignalDebug); +} - contextBridge.exposeInMainWorld('BasePaths', window.BasePaths); - contextBridge.exposeInMainWorld( - 'ConversationController', - window.ConversationController - ); - contextBridge.exposeInMainWorld('Events', window.Events); - contextBridge.exposeInMainWorld('Flags', window.Flags); - contextBridge.exposeInMainWorld('IPC', window.IPC); - contextBridge.exposeInMainWorld( - 'SignalProtocolStore', - window.SignalProtocolStore - ); - contextBridge.exposeInMainWorld( - 'getSignalProtocolStore', - getSignalProtocolStore - ); - contextBridge.exposeInMainWorld( - 'MessageController', - window.MessageController - ); - contextBridge.exposeInMainWorld('WebAudioRecorder', WebAudioRecorder); - contextBridge.exposeInMainWorld('WebAPI', window.WebAPI); - contextBridge.exposeInMainWorld('Whisper', window.Whisper); - contextBridge.exposeInMainWorld('i18n', window.i18n); - contextBridge.exposeInMainWorld('reduxActions', window.reduxActions); - contextBridge.exposeInMainWorld('reduxStore', window.reduxStore); - contextBridge.exposeInMainWorld('startApp', window.startApp); - contextBridge.exposeInMainWorld('textsecure', window.textsecure); - - // TODO DESKTOP-4801 - contextBridge.exposeInMainWorld('ROOT_PATH', window.ROOT_PATH); - contextBridge.exposeInMainWorld('Signal', window.Signal); - contextBridge.exposeInMainWorld( - 'enterKeyboardMode', - window.enterKeyboardMode - ); - contextBridge.exposeInMainWorld('enterMouseMode', window.enterMouseMode); - contextBridge.exposeInMainWorld( - 'getAccountManager', - window.getAccountManager - ); - contextBridge.exposeInMainWorld('getAppInstance', window.getAppInstance); - contextBridge.exposeInMainWorld('getBuildCreation', window.getBuildCreation); - contextBridge.exposeInMainWorld( - 'getBuildExpiration', - window.getBuildExpiration - ); - contextBridge.exposeInMainWorld('getConversations', window.getConversations); - contextBridge.exposeInMainWorld('getEnvironment', window.getEnvironment); - contextBridge.exposeInMainWorld('getHostName', window.getHostName); - contextBridge.exposeInMainWorld( - 'getInteractionMode', - window.getInteractionMode - ); - contextBridge.exposeInMainWorld('getLocale', window.getLocale); - contextBridge.exposeInMainWorld( - 'getServerPublicParams', - window.getServerPublicParams - ); - contextBridge.exposeInMainWorld( - 'getServerTrustRoot', - window.getServerTrustRoot - ); - contextBridge.exposeInMainWorld('getSfuUrl', window.getSfuUrl); - contextBridge.exposeInMainWorld('getSocketStatus', window.getSocketStatus); - contextBridge.exposeInMainWorld('getSyncRequest', window.getSyncRequest); - contextBridge.exposeInMainWorld('getTitle', window.getTitle); - contextBridge.exposeInMainWorld('getVersion', window.getVersion); - contextBridge.exposeInMainWorld('initialTheme', window.initialTheme); - contextBridge.exposeInMainWorld('isAfterVersion', window.isAfterVersion); - contextBridge.exposeInMainWorld('isBeforeVersion', window.isBeforeVersion); - contextBridge.exposeInMainWorld('isBehindProxy', window.isBehindProxy); - contextBridge.exposeInMainWorld( - 'libphonenumberFormat', - window.libphonenumberFormat - ); - contextBridge.exposeInMainWorld( - 'libphonenumberInstance', - window.libphonenumberInstance - ); - contextBridge.exposeInMainWorld('localeMessages', window.localeMessages); - contextBridge.exposeInMainWorld( - 'logAuthenticatedConnect', - window.logAuthenticatedConnect - ); - contextBridge.exposeInMainWorld('nodeSetImmediate', window.nodeSetImmediate); - contextBridge.exposeInMainWorld('platform', window.platform); - contextBridge.exposeInMainWorld('preloadedImages', window.preloadedImages); - contextBridge.exposeInMainWorld( - 'sendChallengeRequest', - window.sendChallengeRequest - ); - contextBridge.exposeInMainWorld('setImmediate', window.setImmediate); - contextBridge.exposeInMainWorld( - 'showKeyboardShortcuts', - window.showKeyboardShortcuts - ); - contextBridge.exposeInMainWorld('storage', window.storage); - contextBridge.exposeInMainWorld('systemTheme', window.systemTheme); - contextBridge.exposeInMainWorld( - 'waitForEmptyEventQueue', - window.waitForEmptyEventQueue - ); - - contextBridge.exposeInMainWorld('assert', window.assert); +if (getEnvironment() === Environment.Test) { contextBridge.exposeInMainWorld('RETRY_DELAY', window.RETRY_DELAY); + contextBridge.exposeInMainWorld('assert', window.assert); contextBridge.exposeInMainWorld('testUtilities', window.testUtilities); } + +if (process.env.SIGNAL_CI_CONFIG) { + contextBridge.exposeInMainWorld('SignalCI', window.SignalCI); +} + +contextBridge.exposeInMainWorld('showDebugLog', window.IPC.showDebugLog); +contextBridge.exposeInMainWorld('startApp', window.startApp);