diff options
Diffstat (limited to 'packages/service-preload/src/index.ts')
-rw-r--r-- | packages/service-preload/src/index.ts | 41 |
1 files changed, 16 insertions, 25 deletions
diff --git a/packages/service-preload/src/index.ts b/packages/service-preload/src/index.ts index fb19107..eee8551 100644 --- a/packages/service-preload/src/index.ts +++ b/packages/service-preload/src/index.ts | |||
@@ -18,45 +18,36 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { ServiceToMainIpcMessage, WebSource } from '@sophie/service-shared'; | 21 | import { webFrame } from 'electron'; |
22 | import { ipcRenderer, webFrame } from 'electron'; | 22 | // eslint-disable-next-line import/no-unresolved -- Synthetic import provided by an eslint plugin. |
23 | 23 | import injectSource from 'sophie-src:@sophie/service-inject'; | |
24 | if (webFrame.parent === null) { | ||
25 | // Inject CSS to simulate `browserView.setBackgroundColor`. | ||
26 | // This is injected before the page loads, so the styles from the website will overwrite it. | ||
27 | webFrame.insertCSS('body { background-color: #fff; }'); | ||
28 | } | ||
29 | 24 | ||
30 | /** | 25 | /** |
31 | * Fetches and executes the service inject script in the isolated world. | 26 | * Executes the service inject script in the isolated world. |
32 | * | 27 | * |
33 | * The service inject script relies on exposed APIs, so this function can only | 28 | * The service inject script relies on exposed APIs, so this function can only |
34 | * be called after APIs have been exposed via `contextBridge` to the main world. | 29 | * be called after APIs have been exposed via `contextBridge` to the main world. |
35 | * | 30 | * |
36 | * We have to call `executeJavaScriptInIsolatedWorld` from the service preload script, | 31 | * We embed the source code of the inject script into the preload script |
37 | * beause there is no way currently (electron 16) to execute a script on a | 32 | * with an esbuild plugin, so there is no need to fetch it separately. |
38 | * `WebFrameMain` in the main process by specifying a `WebSource`. | 33 | * |
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` | 34 | * As a tradeoff, the promise returned by `executeJavaScriptInIsolatedWorld` |
43 | * will resolve to `unknown` (instead of rejecting) even if the injected script fails, | 35 | * 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. | 36 | * because chromium doesn't dispatch main world errors to isolated worlds. |
45 | * | 37 | * |
46 | * @return A promise that only rejects if we fail to fetch the inject script. | 38 | * @return A promise that always resolves to `undefined`. |
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 | */ | 39 | */ |
51 | async function fetchAndExecuteInjectScript(): Promise<void> { | 40 | async function fetchAndExecuteInjectScript(): Promise<void> { |
52 | const apiExposedResponse: unknown = await ipcRenderer.invoke( | ||
53 | ServiceToMainIpcMessage.ApiExposedInMainWorld, | ||
54 | ); | ||
55 | const injectSource = WebSource.parse(apiExposedResponse); | ||
56 | // Isolated world 0 is the main world. | 41 | // Isolated world 0 is the main world. |
57 | await webFrame.executeJavaScriptInIsolatedWorld(0, [injectSource]); | 42 | await webFrame.executeJavaScriptInIsolatedWorld(0, [ |
43 | { | ||
44 | code: injectSource, | ||
45 | }, | ||
46 | ]); | ||
58 | } | 47 | } |
59 | 48 | ||
60 | fetchAndExecuteInjectScript().catch((error) => { | 49 | fetchAndExecuteInjectScript().catch((error) => { |
61 | console.error('Failed to fetch inject source:', error); | 50 | // This will never happen because of |
51 | // https://www.electronjs.org/docs/latest/api/web-frame#webframeexecutejavascriptinisolatedworldworldid-scripts-usergesture-callback | ||
52 | console.error('Failed to execute service inject:', error); | ||
62 | }); | 53 | }); |