I have an Electron file manager app, which creates 2 windows for different purposes:
quickView
a renderer window used for previewing local files. It uses "will-download" listener for detecting unsupported files by preventing download.
main
the main renderer window. It uses "will-download" listener for downloading files.
Each with their own will-download
listeners attached to their session. But for some reason the quickView
listener overwrites the main
listener.
In the following line I'm creating a will-download
listener for the "main" process. The purpose of this listener is to download files:
win.webContents.session.on('will-download', listener)
The windows.main
parameter in the line below is the win
reference in the line above:
const resultInfo = await downloadManager.download(windows.main, {
In the following line I'm creating a will-download
listener for the "quickView" window. The purpose of this listener is to detect unsupported files (which triggers download event in Chromium) and prevent the download event:
windows.quickViewWindow.webContents.session.once('will-download', _willDownloadHandler)
I haven't found another way to detect unsupported files, which is why I'm using a will-download
event in the first place.
For some reason the will-download
handler of the quickView
window overrides the handler of the main
:
When I trigger the app update download event here (from the main
process):
const resultInfo = await downloadManager.download(windows.main, {
It triggers the event handler of the quickView
renderer window:
function _willDownloadHandler (event, item, webContents) {
...
windows.main.webContents.send('load:webview::failed', {path: fileURL})
I partially fixed the problem in this commit by specifying a custom partition name for the session of the quickView
window, so it doesn't use the default session and do not overwrite the will-download
listener created by main
:
windows.quickViewWindow = new electron.BrowserWindow({
...
webPreferences: {
partition: 'quickPreview',
...
windows.quickViewWindow.webContents.session.once(
'will-download',
(event, item, webContents) => {
event.preventDefault()
...
}
)
ipcRenderer.on('load:webview', (event, data) => {
...
webviewNode.setAttribute('partition', 'quickPreview')
But this fix resulted in another problem:
The quick view window stopped working in production build (perhaps it has something to do with the protocol not working with non default session partition)
Setting a custom partition to a webview causes the Windows protocol link association pop up in production when the window containing this webview is created:
I think it might be caused by the custom app://
protocol created by the electron-builder-plugin. It seems the pop up is triggered by the "app" link.
Or maybe it's happening because I'm setting the protocol incorrectly when I'm creating the window somewhere around this line:
git clone https://github.com/aleksey-hoffman/sigma-file-manager.git
cd sigma-file-manager
npm install
git checkout 47ce65b
npm run electron:build
./dist_electron
I just rolled back the 47ce65b commit and added some test values so it's easier to debug
To switch to the latest commit and create the production build:
git checkout 5246252
npm run electron:build
All the console.log()
inside electronMain.js
are displayed in the terminal (command line) window (not the developer tools console).
To trigger quick view feature:
To trigger a download event, you can just open "Navigator" page and drag & drop any file (or website URL) from the internet. It will trigger the wrong will-download event handler (the handler of quickView window), and you should see the console message.
The quickView window containing this webview is created on app.ready
event. When partition is specified, the pop up will appear right after the quickView window is created:
I was able to reproduce it with this code:
let window1 = null
let window2 = null
electron.app.on('ready', async () => {
createWindow1()
createWindow2()
setTimeout(() => {
console.log('trigger window 1 download')
window1.webContents.downloadURL('https://stackoverflow.com')
}, 1000)
})
function createWindow2 () {
window1.webContents.session.once('will-download', downloadHandler1)
window2.webContents.session.once('will-download', downloadHandler2)
}
function createWindow1 () {
window1 = new electron.BrowserWindow()
window1.loadURL('app://./quickViewWindow.html')
window1.webContents.session.once('will-download', downloadHandler1)
}
function createWindow2 () {
window2 = new electron.BrowserWindow()
window2.loadURL('app://./quickViewWindow.html')
window2.webContents.session.once('will-download', downloadHandler2)
}
function downloadHandler1 (event, item, webContents) {
console.log('window will-download handler 1')
}
function downloadHandler2 (event, item, webContents) {
console.log('window will-download handler 2')
}
When the setTimeout
runs, I see the following console.log()
messages:
trigger window 1 download
window will-download handler 1
window will-download handler 2
As you can see from the log, the will-download event triggers event handlers of both windows
If I specify a separate partition for each window, the problem with shared event handlers gets resolved, but I get the 2nd problem mentioned above - the link association pop up on launch
window1 = new electron.BrowserWindow({
webPreferences: {
partition: 'partition1',
}
})
window2 = new electron.BrowserWindow({
webPreferences: {
partition: 'partition2',
}
})
I figured it out. If that's a wrong way to do it, please someone let me know.
Here's how I fixed it:
Set a custom partition name for the window, so it uses its own webContents.session
instead of sharing the default one.
windows.quickViewWindow = new electron.BrowserWindow({
...
webPreferences: {
partition: 'quickView',
...
windows.quickViewWindow.webContents.session.once(
'will-download',
(event, item, webContents) => {
event.preventDefault()
...
}
)
ipcRenderer.on('load:webview', (event, data) => {
...
webviewNode.setAttribute('partition', 'quickView')
Set file://
protocol in the production path for the window URL:
productionPath = `file://${__static}/quickViewWindow.html`
Here's the commit: https://github.com/aleksey-hoffman/sigma-file-manager/commit/31208809cda7614a7c2f32237ae14f6c9c602f8f