aboutsummaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/main/src/index.ts7
-rw-r--r--packages/service-preload/src/index.ts41
2 files changed, 36 insertions, 12 deletions
diff --git a/packages/main/src/index.ts b/packages/main/src/index.ts
index 4a51518..b134002 100644
--- a/packages/main/src/index.ts
+++ b/packages/main/src/index.ts
@@ -219,8 +219,8 @@ function createWindow(): Promise<unknown> {
219 webContents.send(MainToRendererIpcMessage.SharedStorePatch, patch); 219 webContents.send(MainToRendererIpcMessage.SharedStorePatch, patch);
220 }); 220 });
221 221
222 ipcMain.on(ServiceToMainIpcMessage.ApiExposedInMainWorld, (event) => { 222 ipcMain.handle(ServiceToMainIpcMessage.ApiExposedInMainWorld, (event) => {
223 event.returnValue = event.sender.id == browserView.webContents.id 223 return event.sender.id == browserView.webContents.id
224 ? serviceInject 224 ? serviceInject
225 : null; 225 : null;
226 }); 226 });
@@ -229,7 +229,8 @@ function createWindow(): Promise<unknown> {
229 try { 229 try {
230 switch (channel) { 230 switch (channel) {
231 case ServiceToMainIpcMessage.ApiExposedInMainWorld: 231 case ServiceToMainIpcMessage.ApiExposedInMainWorld:
232 // Synchronous message must be handled with `ipcMain.on` 232 // Asynchronous message with reply must be handled in `ipcMain.handle`,
233 // otherwise electron emits a no handler registered warning.
233 break; 234 break;
234 case ServiceToMainIpcMessage.SetUnreadCount: 235 case ServiceToMainIpcMessage.SetUnreadCount:
235 console.log('Unread count:', unreadCount.parse(args[0])); 236 console.log('Unread count:', unreadCount.parse(args[0]));
diff --git a/packages/service-preload/src/index.ts b/packages/service-preload/src/index.ts
index e42c406..d1ea13c 100644
--- a/packages/service-preload/src/index.ts
+++ b/packages/service-preload/src/index.ts
@@ -27,13 +27,36 @@ if (webFrame.parent === null) {
27 webFrame.insertCSS('html { background-color: #fff; }'); 27 webFrame.insertCSS('html { background-color: #fff; }');
28} 28}
29 29
30const injectSource = webSource.safeParse(ipcRenderer.sendSync(ServiceToMainIpcMessage.ApiExposedInMainWorld)); 30/**
31if (injectSource.success) { 31 * Fetches and executes the service inject script in the isolated world.
32 webFrame.executeJavaScriptInIsolatedWorld(0, [ 32 *
33 injectSource.data, 33 * The service inject script relies on exposed APIs, so this function can only
34 ]).catch((err) => { 34 * be called after APIs have been exposed via `contextBridge` to the main world.
35 console.log('Failed to inject source:', err); 35 *
36 }); 36 * We have to call `executeJavaScriptInIsolatedWorld` from the service preload script,
37} else { 37 * beause there is no way currently (electron 16) to execute a script on a
38 console.log('Invalid source to inject:', injectSource.error); 38 * `WebFrameMain` in the main process by specifying a `WebSource`.
39 * Calling `executeJavaScriptInInsolatedWorld` on a `WebContents` in the main process
40 * will always inject the script into the _top-level_ frame, but here we
41 * are injecting into the _current_ frame instead.
42 * As a tradeoff, the promise returned by `executeJavaScriptInIsolatedWorld`
43 * will resolve to `unknown` (instead of rejecting) even if the injected script fails,
44 * because chromium doesn't dispatch main world errors to isolated worlds.
45 *
46 * @return A promise that only rejects if we fail to fetch the inject script.
47 * @see https://www.electronjs.org/docs/latest/api/web-frame#webframeexecutejavascriptinisolatedworldworldid-scripts-usergesture-callback
48 * @see https://www.electronjs.org/docs/latest/api/web-frame-main#frameexecutejavascriptcode-usergesture
49 * @see https://www.electronjs.org/docs/latest/api/web-contents#contentsexecutejavascriptinisolatedworldworldid-scripts-usergesture
50 */
51async function fetchAndExecuteInjectScript(): Promise<void> {
52 const apiExposedResponse = await ipcRenderer.invoke(
53 ServiceToMainIpcMessage.ApiExposedInMainWorld,
54 );
55 const injectSource = webSource.parse(apiExposedResponse);
56 // Isolated world 0 is the main world.
57 return webFrame.executeJavaScriptInIsolatedWorld(0, [injectSource]);
39} 58}
59
60fetchAndExecuteInjectScript().catch((err) => {
61 console.log('Failed to fetch inject source:', err);
62});