/* * Copyright (C) 2021-2022 Kristóf Marussy * * This file is part of Sophie. * * Sophie is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * SPDX-License-Identifier: AGPL-3.0-only */ import { ipcRenderer, webFrame } from 'electron'; import { ServiceToMainIpcMessage, webSource } from '@sophie/service-shared'; if (webFrame.parent === null) { // Inject CSS to simulate `browserView.setBackgroundColor`. // This is injected before the page loads, so the styles from the website will overwrite it. webFrame.insertCSS('html { background-color: #fff; }'); } /** * Fetches and executes the service inject script in the isolated world. * * The service inject script relies on exposed APIs, so this function can only * be called after APIs have been exposed via `contextBridge` to the main world. * * We have to call `executeJavaScriptInIsolatedWorld` from the service preload script, * beause there is no way currently (electron 16) to execute a script on a * `WebFrameMain` in the main process by specifying a `WebSource`. * Calling `executeJavaScriptInInsolatedWorld` on a `WebContents` in the main process * will always inject the script into the _top-level_ frame, but here we * are injecting into the _current_ frame instead. * As a tradeoff, the promise returned by `executeJavaScriptInIsolatedWorld` * will resolve to `unknown` (instead of rejecting) even if the injected script fails, * because chromium doesn't dispatch main world errors to isolated worlds. * * @return A promise that only rejects if we fail to fetch the inject script. * @see https://www.electronjs.org/docs/latest/api/web-frame#webframeexecutejavascriptinisolatedworldworldid-scripts-usergesture-callback * @see https://www.electronjs.org/docs/latest/api/web-frame-main#frameexecutejavascriptcode-usergesture * @see https://www.electronjs.org/docs/latest/api/web-contents#contentsexecutejavascriptinisolatedworldworldid-scripts-usergesture */ async function fetchAndExecuteInjectScript(): Promise { const apiExposedResponse = await ipcRenderer.invoke( ServiceToMainIpcMessage.ApiExposedInMainWorld, ); const injectSource = webSource.parse(apiExposedResponse); // Isolated world 0 is the main world. return webFrame.executeJavaScriptInIsolatedWorld(0, [injectSource]); } fetchAndExecuteInjectScript().catch((err) => { console.log('Failed to fetch inject source:', err); });