diff options
author | Kristóf Marussy <kristof@marussy.com> | 2021-12-25 13:08:22 +0100 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2021-12-25 13:26:32 +0100 |
commit | faeceb71f3303dd36e8ac506cf6a9aaf25fa5862 (patch) | |
tree | e889845d53ff87e262bf03a29abba060bb14399a /packages/service-preload | |
parent | feat: Fuse the electron binary (diff) | |
download | sophie-faeceb71f3303dd36e8ac506cf6a9aaf25fa5862.tar.gz sophie-faeceb71f3303dd36e8ac506cf6a9aaf25fa5862.tar.zst sophie-faeceb71f3303dd36e8ac506cf6a9aaf25fa5862.zip |
refactor: Fetch service inject asynchronously
Since we don't plan to shim any APIs that must be present immediately
when the service loads, we might as well switch to asynchronous IPC for
fetching the script to inject into the main world.
Diffstat (limited to 'packages/service-preload')
-rw-r--r-- | packages/service-preload/src/index.ts | 41 |
1 files changed, 32 insertions, 9 deletions
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 | ||
30 | const injectSource = webSource.safeParse(ipcRenderer.sendSync(ServiceToMainIpcMessage.ApiExposedInMainWorld)); | 30 | /** |
31 | if (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 | */ | ||
51 | async 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 | |||
60 | fetchAndExecuteInjectScript().catch((err) => { | ||
61 | console.log('Failed to fetch inject source:', err); | ||
62 | }); | ||