Use synchronous IPC for passing config
This commit is contained in:
parent
3e586be46a
commit
bd41d7b216
6 changed files with 87 additions and 97 deletions
146
app/main.ts
146
app/main.ts
|
@ -402,79 +402,7 @@ async function prepareUrl(
|
||||||
url: URL,
|
url: URL,
|
||||||
{ forCalling, forCamera }: PrepareUrlOptions = {}
|
{ forCalling, forCamera }: PrepareUrlOptions = {}
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const theme = await getResolvedThemeSetting();
|
return setUrlSearchParams(url, { forCalling, forCamera }).href;
|
||||||
|
|
||||||
const directoryConfig = directoryConfigSchema.safeParse({
|
|
||||||
directoryUrl: config.get<string | null>('directoryUrl') || undefined,
|
|
||||||
directoryMRENCLAVE:
|
|
||||||
config.get<string | null>('directoryMRENCLAVE') || undefined,
|
|
||||||
});
|
|
||||||
if (!directoryConfig.success) {
|
|
||||||
throw new Error(
|
|
||||||
`prepareUrl: Failed to parse renderer directory config ${JSON.stringify(
|
|
||||||
directoryConfig.error.flatten()
|
|
||||||
)}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const urlParams: RendererConfigType = {
|
|
||||||
name: packageJson.productName,
|
|
||||||
resolvedTranslationsLocale: getResolvedMessagesLocale().name,
|
|
||||||
preferredSystemLocales: getPreferredSystemLocales(),
|
|
||||||
version: app.getVersion(),
|
|
||||||
buildCreation: config.get<number>('buildCreation'),
|
|
||||||
buildExpiration: config.get<number>('buildExpiration'),
|
|
||||||
challengeUrl: config.get<string>('challengeUrl'),
|
|
||||||
serverUrl: config.get<string>('serverUrl'),
|
|
||||||
storageUrl: config.get<string>('storageUrl'),
|
|
||||||
updatesUrl: config.get<string>('updatesUrl'),
|
|
||||||
resourcesUrl: config.get<string>('resourcesUrl'),
|
|
||||||
artCreatorUrl: config.get<string>('artCreatorUrl'),
|
|
||||||
cdnUrl0: config.get<ConfigType>('cdn').get<string>('0'),
|
|
||||||
cdnUrl2: config.get<ConfigType>('cdn').get<string>('2'),
|
|
||||||
certificateAuthority: config.get<string>('certificateAuthority'),
|
|
||||||
environment: enableCI ? Environment.Production : getEnvironment(),
|
|
||||||
enableCI,
|
|
||||||
nodeVersion: process.versions.node,
|
|
||||||
hostname: os.hostname(),
|
|
||||||
appInstance: process.env.NODE_APP_INSTANCE || undefined,
|
|
||||||
proxyUrl: process.env.HTTPS_PROXY || process.env.https_proxy || undefined,
|
|
||||||
contentProxyUrl: config.get<string>('contentProxyUrl'),
|
|
||||||
sfuUrl: config.get('sfuUrl'),
|
|
||||||
reducedMotionSetting: animationSettings.prefersReducedMotion,
|
|
||||||
registrationChallengeUrl: config.get<string>('registrationChallengeUrl'),
|
|
||||||
serverPublicParams: config.get<string>('serverPublicParams'),
|
|
||||||
serverTrustRoot: config.get<string>('serverTrustRoot'),
|
|
||||||
theme,
|
|
||||||
appStartInitialSpellcheckSetting,
|
|
||||||
userDataPath: app.getPath('userData'),
|
|
||||||
homePath: app.getPath('home'),
|
|
||||||
crashDumpsPath: app.getPath('crashDumps'),
|
|
||||||
|
|
||||||
directoryConfig: directoryConfig.data,
|
|
||||||
|
|
||||||
// Only used by the main window
|
|
||||||
isMainWindowFullScreen: Boolean(mainWindow?.isFullScreen()),
|
|
||||||
isMainWindowMaximized: Boolean(mainWindow?.isMaximized()),
|
|
||||||
|
|
||||||
// Only for tests
|
|
||||||
argv: JSON.stringify(process.argv),
|
|
||||||
|
|
||||||
// Only for permission popup window
|
|
||||||
forCalling: Boolean(forCalling),
|
|
||||||
forCamera: Boolean(forCamera),
|
|
||||||
};
|
|
||||||
|
|
||||||
const parsed = rendererConfigSchema.safeParse(urlParams);
|
|
||||||
if (!parsed.success) {
|
|
||||||
throw new Error(
|
|
||||||
`prepareUrl: Failed to parse renderer config ${JSON.stringify(
|
|
||||||
parsed.error.flatten()
|
|
||||||
)}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return setUrlSearchParams(url, { config: JSON.stringify(parsed.data) }).href;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleUrl(rawTarget: string) {
|
async function handleUrl(rawTarget: string) {
|
||||||
|
@ -2287,6 +2215,78 @@ ipc.on('get-built-in-images', async () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipc.on('get-config', async event => {
|
||||||
|
const theme = await getResolvedThemeSetting();
|
||||||
|
|
||||||
|
const directoryConfig = directoryConfigSchema.safeParse({
|
||||||
|
directoryUrl: config.get<string | null>('directoryUrl') || undefined,
|
||||||
|
directoryMRENCLAVE:
|
||||||
|
config.get<string | null>('directoryMRENCLAVE') || undefined,
|
||||||
|
});
|
||||||
|
if (!directoryConfig.success) {
|
||||||
|
throw new Error(
|
||||||
|
`prepareUrl: Failed to parse renderer directory config ${JSON.stringify(
|
||||||
|
directoryConfig.error.flatten()
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsed = rendererConfigSchema.safeParse({
|
||||||
|
name: packageJson.productName,
|
||||||
|
resolvedTranslationsLocale: getResolvedMessagesLocale().name,
|
||||||
|
preferredSystemLocales: getPreferredSystemLocales(),
|
||||||
|
version: app.getVersion(),
|
||||||
|
buildCreation: config.get<number>('buildCreation'),
|
||||||
|
buildExpiration: config.get<number>('buildExpiration'),
|
||||||
|
challengeUrl: config.get<string>('challengeUrl'),
|
||||||
|
serverUrl: config.get<string>('serverUrl'),
|
||||||
|
storageUrl: config.get<string>('storageUrl'),
|
||||||
|
updatesUrl: config.get<string>('updatesUrl'),
|
||||||
|
resourcesUrl: config.get<string>('resourcesUrl'),
|
||||||
|
artCreatorUrl: config.get<string>('artCreatorUrl'),
|
||||||
|
cdnUrl0: config.get<ConfigType>('cdn').get<string>('0'),
|
||||||
|
cdnUrl2: config.get<ConfigType>('cdn').get<string>('2'),
|
||||||
|
certificateAuthority: config.get<string>('certificateAuthority'),
|
||||||
|
environment: enableCI ? Environment.Production : getEnvironment(),
|
||||||
|
enableCI,
|
||||||
|
nodeVersion: process.versions.node,
|
||||||
|
hostname: os.hostname(),
|
||||||
|
appInstance: process.env.NODE_APP_INSTANCE || undefined,
|
||||||
|
proxyUrl: process.env.HTTPS_PROXY || process.env.https_proxy || undefined,
|
||||||
|
contentProxyUrl: config.get<string>('contentProxyUrl'),
|
||||||
|
sfuUrl: config.get('sfuUrl'),
|
||||||
|
reducedMotionSetting: animationSettings.prefersReducedMotion,
|
||||||
|
registrationChallengeUrl: config.get<string>('registrationChallengeUrl'),
|
||||||
|
serverPublicParams: config.get<string>('serverPublicParams'),
|
||||||
|
serverTrustRoot: config.get<string>('serverTrustRoot'),
|
||||||
|
theme,
|
||||||
|
appStartInitialSpellcheckSetting,
|
||||||
|
userDataPath: app.getPath('userData'),
|
||||||
|
homePath: app.getPath('home'),
|
||||||
|
crashDumpsPath: app.getPath('crashDumps'),
|
||||||
|
|
||||||
|
directoryConfig: directoryConfig.data,
|
||||||
|
|
||||||
|
// Only used by the main window
|
||||||
|
isMainWindowFullScreen: Boolean(mainWindow?.isFullScreen()),
|
||||||
|
isMainWindowMaximized: Boolean(mainWindow?.isMaximized()),
|
||||||
|
|
||||||
|
// Only for tests
|
||||||
|
argv: JSON.stringify(process.argv),
|
||||||
|
} satisfies RendererConfigType);
|
||||||
|
|
||||||
|
if (!parsed.success) {
|
||||||
|
throw new Error(
|
||||||
|
`prepareUrl: Failed to parse renderer config ${JSON.stringify(
|
||||||
|
parsed.error.flatten()
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
event.returnValue = parsed.data;
|
||||||
|
});
|
||||||
|
|
||||||
// Ingested in preload.js via a sendSync call
|
// Ingested in preload.js via a sendSync call
|
||||||
ipc.on('locale-data', event => {
|
ipc.on('locale-data', event => {
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
// Copyright 2023 Signal Messenger, LLC
|
// Copyright 2023 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { RendererConfigType } from '../types/RendererConfig';
|
import { ipcRenderer } from 'electron';
|
||||||
import { strictAssert } from '../util/assert';
|
|
||||||
|
|
||||||
const params = new URLSearchParams(document.location.search);
|
import type { RendererConfigType } from '../types/RendererConfig';
|
||||||
const configParam = params.get('config');
|
|
||||||
strictAssert(typeof configParam === 'string', 'config is not a string');
|
const config: RendererConfigType = ipcRenderer.sendSync('get-config');
|
||||||
const config: RendererConfigType = JSON.parse(configParam);
|
|
||||||
|
|
||||||
export { config };
|
export { config };
|
||||||
|
|
|
@ -44,8 +44,6 @@ describe('URL utilities', () => {
|
||||||
number: 123,
|
number: 123,
|
||||||
true_bool: true,
|
true_bool: true,
|
||||||
false_bool: false,
|
false_bool: false,
|
||||||
null_value: null,
|
|
||||||
undefined_value: undefined,
|
|
||||||
array: ['ok', 'wow'],
|
array: ['ok', 'wow'],
|
||||||
stringified: { toString: () => 'bar' },
|
stringified: { toString: () => 'bar' },
|
||||||
};
|
};
|
||||||
|
@ -67,8 +65,6 @@ describe('URL utilities', () => {
|
||||||
assert.strictEqual(newUrl.searchParams.get('number'), '123');
|
assert.strictEqual(newUrl.searchParams.get('number'), '123');
|
||||||
assert.strictEqual(newUrl.searchParams.get('true_bool'), 'true');
|
assert.strictEqual(newUrl.searchParams.get('true_bool'), 'true');
|
||||||
assert.strictEqual(newUrl.searchParams.get('false_bool'), 'false');
|
assert.strictEqual(newUrl.searchParams.get('false_bool'), 'false');
|
||||||
assert.strictEqual(newUrl.searchParams.get('null_value'), '');
|
|
||||||
assert.strictEqual(newUrl.searchParams.get('undefined_value'), '');
|
|
||||||
assert.strictEqual(newUrl.searchParams.get('array'), 'ok,wow');
|
assert.strictEqual(newUrl.searchParams.get('array'), 'ok,wow');
|
||||||
assert.strictEqual(newUrl.searchParams.get('stringified'), 'bar');
|
assert.strictEqual(newUrl.searchParams.get('stringified'), 'bar');
|
||||||
});
|
});
|
||||||
|
|
|
@ -64,10 +64,6 @@ export const rendererConfigSchema = z.object({
|
||||||
|
|
||||||
// Only for tests
|
// Only for tests
|
||||||
argv: configOptionalStringSchema,
|
argv: configOptionalStringSchema,
|
||||||
|
|
||||||
// Only for permission popup window
|
|
||||||
forCalling: z.boolean(),
|
|
||||||
forCamera: z.boolean(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export type RendererConfigType = z.infer<typeof rendererConfigSchema>;
|
export type RendererConfigType = z.infer<typeof rendererConfigSchema>;
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
// Copyright 2021 Signal Messenger, LLC
|
// Copyright 2021 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import { mapValues } from 'lodash';
|
|
||||||
|
|
||||||
export function maybeParseUrl(value: string): undefined | URL {
|
export function maybeParseUrl(value: string): undefined | URL {
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
try {
|
try {
|
||||||
|
@ -20,9 +18,13 @@ export function setUrlSearchParams(
|
||||||
searchParams: Readonly<Record<string, unknown>>
|
searchParams: Readonly<Record<string, unknown>>
|
||||||
): URL {
|
): URL {
|
||||||
const result = cloneUrl(url);
|
const result = cloneUrl(url);
|
||||||
result.search = new URLSearchParams(
|
result.search = '';
|
||||||
mapValues(searchParams, stringifySearchParamValue)
|
for (const [key, value] of Object.entries(searchParams)) {
|
||||||
).toString();
|
if (value == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.searchParams.append(key, String(value));
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,10 +32,6 @@ function cloneUrl(url: Readonly<URL>): URL {
|
||||||
return new URL(url.href);
|
return new URL(url.href);
|
||||||
}
|
}
|
||||||
|
|
||||||
function stringifySearchParamValue(value: unknown): string {
|
|
||||||
return value == null ? '' : String(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function urlPathFromComponents(
|
export function urlPathFromComponents(
|
||||||
components: ReadonlyArray<string>
|
components: ReadonlyArray<string>
|
||||||
): string {
|
): string {
|
||||||
|
|
|
@ -25,7 +25,9 @@ contextBridge.exposeInMainWorld(
|
||||||
contextBridge.exposeInMainWorld('SignalContext', {
|
contextBridge.exposeInMainWorld('SignalContext', {
|
||||||
...SignalContext,
|
...SignalContext,
|
||||||
renderWindow: () => {
|
renderWindow: () => {
|
||||||
const { forCalling, forCamera } = SignalContext.config;
|
const params = new URLSearchParams(document.location.search);
|
||||||
|
const forCalling = params.get('forCalling') === 'true';
|
||||||
|
const forCamera = params.get('forCamera') === 'true';
|
||||||
|
|
||||||
let message;
|
let message;
|
||||||
if (forCalling) {
|
if (forCalling) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue