Using the latest stable Electron (29)
Sample code is taken from the official docs:
import { app, BrowserWindow, protocol, net } from 'electron';
protocol.registerSchemesAsPrivileged([
{
scheme: 'foo',
privileges: {
bypassCSP: true,
standard: true,
secure: true,
supportFetchAPI: true,
}
}
]);
app.whenReady().then(() => {
console.log("app rdy")
protocol.handle('foo', (req) => {
console.log("yo", req.url); // <-- never executed
return new Response('bad', {
status: 400,
headers: { 'content-type': 'text/html' }
})
})
})
app.on('ready', () => {
win = new BrowserWindow({
width,
height,
x,
y,
frame: false,
closable: true,
webPreferences: {
preload: `preload.js`,
nodeIntegration: false,
nodeIntegrationInSubFrames: false,
contextIsolation: true,
},
});
win.loadURL(`foo://main.html`);
});
So what is supposed to do - is to register the foo
protocol, then load in the main window an url with the foo://
scheme. This should be handled by the foo
handler function, but it's not.
The function never runs, and instead some Windows window is opened with a box telling me I need to download some app from the windows store to open "foo" files!? wtf?
So I did some more research and found this function: app.setAsDefaultProtocolClient(protocol)
which I assume is supposed to make the electron app be the default app that opens foo://
links..
So after I added app.setAsDefaultProtocolClient('foo')
hell ensued and the electron app kept opening new instances of itself continuously until I had to forcibly power down my PC because it become unresponsive.
My guess is that Electron passes any non-http or file urls to Windows for some weird reason, and it doesn't take into account protocol.handle
and/or registerSchemesAsPrivileged
...
Anyone else facing the same issue?
Its to do with sessions! from: Official docs
A protocol is registered to a specific Electron session object. If you don't specify a session, then your protocol will be applied to the default session that Electron uses. However, if you define a partition or session on your browserWindow's webPreferences, then that window will use a different session and your custom protocol will not work if you just use electron.protocol.XXX
This works:
import { app, BrowserWindow, protocol, session } from 'electron';
const path = require('node:path')
const url = require('url')
protocol.registerSchemesAsPrivileged([
{
scheme: 'foo',
privileges: {
bypassCSP: true,
standard: true,
secure: true,
supportFetchAPI: true,
}
}
]);
app.whenReady().then(() => {
const partition = 'persist:subdeveloper'
const ses = session.fromPartition(partition)
console.log("app rdy")
ses.protocol.handle('foo', (req) => {
console.log("yo", req.url); // <-- never executed
return new Response('bad', {
status: 400,
headers: { 'content-type': 'text/html' }
})
})
const mainWindow = new BrowserWindow({ webPreferences: { partition } });
mainWindow.loadURL(`foo://main.html`);
})