Skip to content

Commit 15e39f3

Browse files
authored
fix: Preload script in sandboxed iframes (#1925)
* Pass initialization data at once on server view * Lift code injection to the main process
1 parent 76734a3 commit 15e39f3

5 files changed

Lines changed: 41 additions & 24 deletions

File tree

src/ipc/channels.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { AnyAction } from 'redux';
22

33
import { Download } from '../downloads/common';
4+
import { Server } from '../servers/common';
45
import { SystemIdleState } from '../userPresence/common';
56

67
type ChannelToArgsMap = {
@@ -16,6 +17,8 @@ type ChannelToArgsMap = {
1617
'downloads/cancel': (itemId: Download['itemId']) => void;
1718
'downloads/retry': (itemId: Download['itemId']) => void;
1819
'downloads/remove': (itemId: Download['itemId']) => void;
20+
'server-view/get-url': () => Server['url'];
21+
'server-view/ready': () => void;
1922
};
2023

2124
export type Channel = keyof ChannelToArgsMap;

src/ipc/main.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ export const invoke = <N extends Channel>(
2828
export const handle = <N extends Channel>(
2929
channel: N,
3030
handler: (webContents: WebContents, ...args: Parameters<Handler<N>>) => Promise<ReturnType<Handler<N>>>,
31-
): void => {
31+
): (() => void) => {
3232
ipcMain.handle(channel, (event, ...args: Parameters<Handler<N>>) => handler(event.sender, ...args));
33+
34+
return () => {
35+
ipcMain.removeHandler(channel);
36+
};
3337
};

src/ipc/renderer.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { ipcRenderer } from 'electron';
1+
import { ipcRenderer, IpcRendererEvent } from 'electron';
22

33
import { Handler, Channel } from './channels';
44

55
export const handle = <N extends Channel>(
66
channel: N,
77
handler: (...args: Parameters<Handler<N>>) => Promise<ReturnType<Handler<N>>>,
8-
): void => {
9-
ipcRenderer.on(channel, async (_, id: string, ...args: Parameters<typeof handler>): Promise<void> => {
8+
): (() => void) => {
9+
const listener = async (_: IpcRendererEvent, id: string, ...args: Parameters<typeof handler>): Promise<void> => {
1010
try {
1111
const resolved = await handler(...args);
1212

@@ -20,7 +20,13 @@ export const handle = <N extends Channel>(
2020
},
2121
});
2222
}
23-
});
23+
};
24+
25+
ipcRenderer.on(channel, listener);
26+
27+
return () => {
28+
ipcRenderer.removeListener(channel, listener);
29+
};
2430
};
2531

2632
export const invoke = <N extends Channel>(

src/preload.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
import fs from 'fs';
2-
import path from 'path';
3-
4-
import { contextBridge, ipcRenderer, webFrame } from 'electron';
1+
import { contextBridge } from 'electron';
52

63
import { setupRendererErrorHandling } from './errors';
4+
import { invoke } from './ipc/renderer';
75
import { JitsiMeetElectron, JitsiMeetElectronAPI } from './jitsi/preload';
86
import { listenToNotificationsRequests } from './notifications/preload';
97
import { listenToScreenSharingRequests } from './screenSharing/preload';
108
import { RocketChatDesktop, RocketChatDesktopAPI, serverInfo } from './servers/preload/api';
119
import { setServerUrl } from './servers/preload/urls';
12-
import { createRendererReduxStore, select } from './store';
10+
import { createRendererReduxStore } from './store';
1311
import { listenToMessageBoxEvents } from './ui/preload/messageBox';
1412
import { handleTrafficLightsSpacing } from './ui/preload/sidebar';
1513
import { listenToUserPresenceChanges } from './userPresence/preload';
@@ -26,7 +24,8 @@ contextBridge.exposeInMainWorld('JitsiMeetElectron', JitsiMeetElectron);
2624
contextBridge.exposeInMainWorld('RocketChatDesktop', RocketChatDesktop);
2725

2826
const start = async (): Promise<void> => {
29-
const serverUrl = await ipcRenderer.invoke('server-url');
27+
const serverUrl = await invoke('server-view/get-url');
28+
3029
setServerUrl(serverUrl);
3130

3231
await createRendererReduxStore();
@@ -35,11 +34,7 @@ const start = async (): Promise<void> => {
3534

3635
setupRendererErrorHandling('webviewPreload');
3736

38-
const injectedCode = await fs.promises.readFile(
39-
path.join(select(({ appPath }) => appPath), 'app/injected.js'),
40-
'utf8',
41-
);
42-
await webFrame.executeJavaScript(injectedCode);
37+
await invoke('server-view/ready');
4338

4439
if (!serverInfo) {
4540
return;

src/ui/main/serverView/index.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import fs from 'fs';
12
import path from 'path';
23

34
import {
@@ -8,7 +9,6 @@ import {
89
DidNavigateEvent,
910
Event,
1011
Input,
11-
ipcMain,
1212
Menu,
1313
MenuItemConstructorOptions,
1414
Session,
@@ -25,6 +25,7 @@ import i18next from 'i18next';
2525

2626
import { setupPreloadReload } from '../../../app/main/dev';
2727
import { handleWillDownloadEvent } from '../../../downloads/main';
28+
import { handle } from '../../../ipc/main';
2829
import { CERTIFICATES_CLEARED } from '../../../navigation/actions';
2930
import { isProtocolAllowed } from '../../../navigation/main';
3031
import { Server } from '../../../servers/common';
@@ -304,11 +305,19 @@ export const attachGuestWebContentsEvents = async (): Promise<void> => {
304305
rootWindow.webContents.addListener('will-attach-webview', handleWillAttachWebview);
305306
rootWindow.webContents.addListener('did-attach-webview', handleDidAttachWebview);
306307

307-
ipcMain.handle(
308-
'server-url',
309-
(event) =>
310-
Array.from(webContentsByServerUrl.entries())
311-
.filter(([, v]) => v === event.sender)
312-
.map(([k]) => k)[0],
313-
);
308+
handle('server-view/get-url', async (webContents) =>
309+
Array.from(webContentsByServerUrl.entries())
310+
.find(([, v]) => v === webContents)?.[0]);
311+
312+
let injectableCode: string;
313+
handle('server-view/ready', async (webContents) => {
314+
if (!injectableCode) {
315+
injectableCode = await fs.promises.readFile(
316+
path.join(select(({ appPath }) => appPath), 'app/injected.js'),
317+
'utf8',
318+
);
319+
}
320+
321+
webContents.executeJavaScript(injectableCode, true);
322+
});
314323
};

0 commit comments

Comments
 (0)