diff --git a/src/main/anr.ts b/src/main/anr.ts index a6c8f68e..01913d15 100644 --- a/src/main/anr.ts +++ b/src/main/anr.ts @@ -90,7 +90,7 @@ export function isAnrChildProcess(): boolean { } /** Creates a renderer ANR status hook */ -export function createRendererAnrStatusHook(): (status: RendererStatus, contents: WebContents) => void { +export function createRendererAnrStatusHandler(): (status: RendererStatus, contents: WebContents) => void { function log(message: string, ...args: unknown[]): void { logger.log(`[Renderer ANR] ${message}`, ...args); } diff --git a/src/main/ipc.ts b/src/main/ipc.ts index 4d8bb460..4a4772de 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -12,13 +12,18 @@ import { PROTOCOL_SCHEME, RendererStatus, } from '../common'; -import { createRendererAnrStatusHook } from './anr'; +import { createRendererAnrStatusHandler } from './anr'; import { registerProtocol, supportsFullProtocol, whenAppReady } from './electron-normalize'; import { ElectronMainOptionsInternal } from './sdk'; let KNOWN_RENDERERS: Set | undefined; let WINDOW_ID_TO_WEB_CONTENTS: Map | undefined; +const SENTRY_CUSTOM_SCHEME = { + scheme: PROTOCOL_SCHEME, + privileges: { bypassCSP: true, corsEnabled: true, supportFetchAPI: true, secure: true }, +}; + async function newProtocolRenderer(): Promise { KNOWN_RENDERERS = KNOWN_RENDERERS || new Set(); WINDOW_ID_TO_WEB_CONTENTS = WINDOW_ID_TO_WEB_CONTENTS || new Map(); @@ -169,14 +174,17 @@ function configureProtocol(options: ElectronMainOptionsInternal): void { throw new SentryError("Sentry SDK should be initialized before the Electron app 'ready' event is fired"); } - protocol.registerSchemesAsPrivileged([ - { - scheme: PROTOCOL_SCHEME, - privileges: { bypassCSP: true, corsEnabled: true, supportFetchAPI: true, secure: true }, + protocol.registerSchemesAsPrivileged([SENTRY_CUSTOM_SCHEME]); + + // We Proxy this function so that later user calls to registerSchemesAsPrivileged don't overwrite our custom scheme + // eslint-disable-next-line @typescript-eslint/unbound-method + protocol.registerSchemesAsPrivileged = new Proxy(protocol.registerSchemesAsPrivileged, { + apply: (target, __, args: Parameters) => { + target([...args[0], SENTRY_CUSTOM_SCHEME]); }, - ]); + }); - const rendererStatusChanged = createRendererAnrStatusHook(); + const rendererStatusChanged = createRendererAnrStatusHandler(); whenAppReady .then(() => { @@ -231,7 +239,7 @@ function configureClassic(options: ElectronMainOptionsInternal): void { ipcMain.on(IPCChannel.SCOPE, (_, jsonScope: string) => handleScope(options, jsonScope)); ipcMain.on(IPCChannel.ENVELOPE, ({ sender }, env: Uint8Array | string) => handleEnvelope(options, env, sender)); - const rendererStatusChanged = createRendererAnrStatusHook(); + const rendererStatusChanged = createRendererAnrStatusHandler(); ipcMain.on(IPCChannel.STATUS, ({ sender }, status: RendererStatus) => rendererStatusChanged(status, sender)); } diff --git a/test/e2e/test-apps/javascript/renderer-error-protocol/src/main.js b/test/e2e/test-apps/javascript/renderer-error-protocol/src/main.js index 72ca4f53..84c3fbd8 100644 --- a/test/e2e/test-apps/javascript/renderer-error-protocol/src/main.js +++ b/test/e2e/test-apps/javascript/renderer-error-protocol/src/main.js @@ -1,6 +1,6 @@ const path = require('path'); -const { app, BrowserWindow } = require('electron'); +const { app, BrowserWindow, protocol } = require('electron'); const { init, IPCMode } = require('@sentry/electron'); init({ @@ -11,6 +11,18 @@ init({ onFatalError: () => {}, }); +// Since we patch registerSchemesAsPrivileged, this should not overwrite the sentry scheme +protocol.registerSchemesAsPrivileged([ + { + scheme: 'custom1', + privileges: { + standard: true, + secure: true, + supportFetchAPI: true, + }, + }, +]); + app.on('ready', () => { const mainWindow = new BrowserWindow({ show: false,