title: Electron.js: how to create a separate download webContents.session for a window?
body: <p>I have an Electron <a href="https://github.com/aleksey-hoffman/sigma-file-manager" rel="nofollow noreferrer">file manager app</a>, which creates 2 windows for different purposes:</p>
  <ul>
  <li><p><code>quickView</code> a renderer window used for previewing local files. It uses &quot;will-download&quot; listener for detecting unsupported files by preventing download.</p>
  </li>
  <li><p><code>main</code> the main renderer window. It uses &quot;will-download&quot; listener for downloading files.</p>
  </li>
  </ul>
  <p>Each with their own <code>will-download</code> listeners attached to their session. But for some reason the <code>quickView</code> listener overwrites the <code>main</code> listener.</p>
  <h4>Window 1</h4>
  <p>In the following line I'm creating a <code>will-download</code> listener for the &quot;main&quot; process. The purpose of this listener is to download files:</p>
  <p><a href="https://github.com/aleksey-hoffman/sigma-file-manager/blob/55fd2462cf83898610883191807b7488fb5bdf89/src/utils/downloadManager.js#L133" rel="nofollow noreferrer">https://github.com/aleksey-hoffman/sigma-file-manager/blob/55fd2462cf83898610883191807b7488fb5bdf89/src/utils/downloadManager.js#L133</a></p>
  <pre class="lang-js prettyprint-override"><code>win.webContents.session.on('will-download', listener)
  </code></pre>
  <p>The <code>windows.main</code> parameter in the line below is the <code>win</code> reference in the line above:</p>
  <p><a href="https://github.com/aleksey-hoffman/sigma-file-manager/blob/55fd2462cf83898610883191807b7488fb5bdf89/src/electronMain.js#L516" rel="nofollow noreferrer">https://github.com/aleksey-hoffman/sigma-file-manager/blob/55fd2462cf83898610883191807b7488fb5bdf89/src/electronMain.js#L516</a></p>
  <pre class="lang-js prettyprint-override"><code>const resultInfo = await downloadManager.download(windows.main, {
  </code></pre>
  <h4>Window 2</h4>
  <p>In the following line I'm creating a <code>will-download</code> listener for the &quot;quickView&quot; window. The purpose of this listener is to detect unsupported files (which triggers download event in Chromium) and prevent the download event:</p>
  <p><a href="https://github.com/aleksey-hoffman/sigma-file-manager/blob/55fd2462cf83898610883191807b7488fb5bdf89/src/electronMain.js#L232" rel="nofollow noreferrer">https://github.com/aleksey-hoffman/sigma-file-manager/blob/55fd2462cf83898610883191807b7488fb5bdf89/src/electronMain.js#L232</a></p>
  <pre class="lang-js prettyprint-override"><code>windows.quickViewWindow.webContents.session.once('will-download', _willDownloadHandler)
  </code></pre>
  <p>I haven't found another way to detect unsupported files, which is why I'm using a <code>will-download</code> event in the first place.</p>
  <h2>Problem</h2>
  <p>For some reason the <code>will-download</code> handler of the <code>quickView</code> window overrides the handler of the <code>main</code>:</p>
  <p>When I trigger the app update download event here (from the <code>main</code> process):</p>
  <p><a href="https://github.com/aleksey-hoffman/sigma-file-manager/blob/55fd2462cf83898610883191807b7488fb5bdf89/src/electronMain.js#L516" rel="nofollow noreferrer">https://github.com/aleksey-hoffman/sigma-file-manager/blob/55fd2462cf83898610883191807b7488fb5bdf89/src/electronMain.js#L516</a></p>
  <pre class="lang-js prettyprint-override"><code>const resultInfo = await downloadManager.download(windows.main, {
  </code></pre>
  <p>It triggers the event handler of the <code>quickView</code> renderer window:</p>
  <p><a href="https://github.com/aleksey-hoffman/sigma-file-manager/blob/55fd2462cf83898610883191807b7488fb5bdf89/src/electronMain.js#L241" rel="nofollow noreferrer">https://github.com/aleksey-hoffman/sigma-file-manager/blob/55fd2462cf83898610883191807b7488fb5bdf89/src/electronMain.js#L241</a></p>
  <pre class="lang-js prettyprint-override"><code>function _willDownloadHandler (event, item, webContents) {
    ...
    windows.main.webContents.send('load:webview::failed', {path: fileURL})
  </code></pre>
  <h3>Partial fix</h3>
  <p>I partially fixed the problem in <a href="https://github.com/aleksey-hoffman/sigma-file-manager/commit/47ce65bdac78e5c9b17315f16623d40d81dcf1bb" rel="nofollow noreferrer">this commit</a> by specifying a custom partition name for the session of the <code>quickView</code> window, so it doesn't use the default session and do not overwrite the <code>will-download</code> listener created by <code>main</code>:</p>
  <h4>Main process:</h4>
  <pre class="lang-js prettyprint-override"><code>windows.quickViewWindow = new electron.BrowserWindow({
    ...
    webPreferences: {
      partition: 'quickPreview',
  
  ...
  
  windows.quickViewWindow.webContents.session.once(
    'will-download',
    (event, item, webContents) =&gt; {
      event.preventDefault()
      ...
    }
  )
  </code></pre>
  <h4>quickViewWindow.html:</h4>
  <pre class="lang-js prettyprint-override"><code>ipcRenderer.on('load:webview', (event, data) =&gt; {
    ...
    webviewNode.setAttribute('partition', 'quickPreview')
  </code></pre>
  <p>But this fix resulted in another problem:</p>
  <ul>
  <li><p>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)</p>
  </li>
  <li><p>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:</p>
  </li>
  </ul>
  <p><img src="https://user-images.githubusercontent.com/61761672/121809351-20dc3e00-cc65-11eb-94f6-3def22e1b8ef.png" alt="image" /></p>
  <p>I think it might be caused by the custom <code>app://</code> protocol created by the <a href="https://github.com/nklayman/vue-cli-plugin-electron-builder" rel="nofollow noreferrer">electron-builder-plugin</a>. It seems the pop up is triggered by the &quot;app&quot; link.</p>
  <p>Or maybe it's happening because I'm setting the protocol incorrectly when I'm creating the window somewhere around this line:</p>
  <p><a href="https://github.com/aleksey-hoffman/sigma-file-manager/blob/47ce65bdac78e5c9b17315f16623d40d81dcf1bb/src/electronMain.js#L203" rel="nofollow noreferrer">https://github.com/aleksey-hoffman/sigma-file-manager/blob/47ce65bdac78e5c9b17315f16623d40d81dcf1bb/src/electronMain.js#L203</a></p>
  <h2>To reproduce:</h2>
  <ol>
  <li>Download the project</li>
  </ol>
  <pre><code>git clone https://github.com/aleksey-hoffman/sigma-file-manager.git
  cd sigma-file-manager
  npm install
  git checkout 47ce65b
  npm run electron:build
  </code></pre>
  <ol start="2">
  <li>Install the built app from <code>./dist_electron</code></li>
  <li>During the app launch you can see the pop up</li>
  </ol>
  <h4>Notes:</h4>
  <p>I just rolled back the 47ce65b commit and added some test values
  so it's easier to debug</p>
  <p>To switch to the latest commit and create the production build:</p>
  <pre><code>git checkout 5246252
  npm run electron:build
  </code></pre>
  <p>All the <code>console.log()</code> inside <code>electronMain.js</code> are displayed in the terminal (command line) window (not the developer tools console).</p>
  <p>To trigger quick view feature:</p>
  <ul>
  <li>Select any supported file (image/ text / etc) on the navigator page</li>
  <li>Press Space (the quick view window should open)</li>
  </ul>
  <p>To trigger a download event, you can just open &quot;Navigator&quot; page and drag &amp; 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.</p>
  <p>The quickView window containing this webview is created on <code>app.ready</code> event. When partition is specified, the pop up will appear right after the quickView window is created:</p>
  <p><a href="https://github.com/aleksey-hoffman/sigma-file-manager/blob/47ce65bdac78e5c9b17315f16623d40d81dcf1bb/src/electronMain.js#L698" rel="nofollow noreferrer">https://github.com/aleksey-hoffman/sigma-file-manager/blob/47ce65bdac78e5c9b17315f16623d40d81dcf1bb/src/electronMain.js#L698</a></p>
  <h1>UPDATE:</h1>
  <h2>Smaller reproduction example:</h2>
  <p>I was able to reproduce it with this code:</p>
  <pre class="lang-js prettyprint-override"><code>let window1 = null
  let window2 = null
  
  electron.app.on('ready', async () =&gt; {
    createWindow1()
    createWindow2()
  
    setTimeout(() =&gt; {
      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')
  }
  
  </code></pre>
  <p>When the <code>setTimeout</code> runs, I see the following <code>console.log()</code> messages:</p>
  <pre><code>trigger window 1 download
  window will-download handler 1
  window will-download handler 2
  </code></pre>
  <p>As you can see from the log, the will-download event triggers event handlers of both windows</p>
  <p>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</p>
  <pre class="lang-js prettyprint-override"><code>window1 = new electron.BrowserWindow({
    webPreferences: {
      partition: 'partition1',
    }
  })
  window2 = new electron.BrowserWindow({
    webPreferences: {
      partition: 'partition2',
    }
  })
  </code></pre>