Electron.js: как создать отдельный сеанс загрузки webContents.для окна?

#javascript #node.js #electron #chromium

Вопрос:

У меня есть приложение для электронного файлового менеджера, которое создает 2 окна для разных целей:

  • quickView окно визуализации, используемое для предварительного просмотра локальных файлов. Он использует прослушиватель «будет загружаться» для обнаружения неподдерживаемых файлов путем предотвращения загрузки.
  • main главное окно визуализации. Он использует прослушиватель «will-download» для загрузки файлов.

Каждый со своими собственными will-download слушателями, прикрепленными к их сеансу. Но по какой-то причине quickView слушатель перезаписывает main слушателя.

Окно 1

В следующей строке я создаю will-download прослушиватель для «основного» процесса. Целью этого прослушивателя является загрузка файлов:

https://github.com/aleksey-hoffman/sigma-file-manager/blob/55fd2462cf83898610883191807b7488fb5bdf89/src/utils/downloadManager.js#L133

 win.webContents.session.on('will-download', listener)
 

windows.main Параметр в строке ниже является win ссылкой в строке выше:

https://github.com/aleksey-hoffman/sigma-file-manager/blob/55fd2462cf83898610883191807b7488fb5bdf89/src/electronMain.js#L516

 const resultInfo = await downloadManager.download(windows.main, {
 

Окно 2

В следующей строке я создаю will-download прослушиватель для окна «Быстрый просмотр». Цель этого прослушивателя-обнаружить неподдерживаемые файлы (что запускает событие загрузки в Chromium) и предотвратить событие загрузки:

https://github.com/aleksey-hoffman/sigma-file-manager/blob/55fd2462cf83898610883191807b7488fb5bdf89/src/electronMain.js#L232

 windows.quickViewWindow.webContents.session.once('will-download', _willDownloadHandler)
 

Я не нашел другого способа обнаружения неподдерживаемых файлов, поэтому я will-download в первую очередь использую событие.

Problem

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):

https://github.com/aleksey-hoffman/sigma-file-manager/blob/55fd2462cf83898610883191807b7488fb5bdf89/src/electronMain.js#L516

 const resultInfo = await downloadManager.download(windows.main, {
 

It triggers the event handler of the quickView renderer window:

https://github.com/aleksey-hoffman/sigma-file-manager/blob/55fd2462cf83898610883191807b7488fb5bdf89/src/electronMain.js#L241

 function _willDownloadHandler (event, item, webContents) {
  ...
  windows.main.webContents.send('load:webview::failed', {path: fileURL})
 

Частичное исправление

Я частично исправил проблему в этой фиксации, указав пользовательское имя раздела для сеанса quickView окна, чтобы оно не использовало сеанс по умолчанию и не перезаписывало will-download прослушиватель, созданный main :

Основной процесс:

 windows.quickViewWindow = new electron.BrowserWindow({
  ...
  webPreferences: {
    partition: 'quickPreview',

...

windows.quickViewWindow.webContents.session.once(
  'will-download',
  (event, item, webContents) => {
    event.preventDefault()
    ...
  }
)
 

quickViewWindow.html:

 ipcRenderer.on('load:webview', (event, data) => {
  ...
  webviewNode.setAttribute('partition', 'quickPreview')
 

Но это исправление привело к другой проблеме:

  • Окно быстрого просмотра перестало работать в рабочей сборке (возможно, это связано с тем, что протокол не работает с разделом сеанса, отличным от стандартного).
  • Установка пользовательского раздела в веб-представление приводит к появлению в рабочей среде ассоциации ссылок на протокол Windows при создании окна, содержащего это веб-представление:

изображение

Я думаю, что это может быть вызвано пользовательским app:// протоколом, созданным плагином electron-builder. Похоже, всплывающее окно запускается ссылкой «приложение».

Или, может быть, это происходит потому, что я неправильно устанавливаю протокол, когда создаю окно где-то в этой строке:

https://github.com/aleksey-hoffman/sigma-file-manager/blob/47ce65bdac78e5c9b17315f16623d40d81dcf1bb/src/electronMain.js#L203

Чтобы воспроизвести:

  1. Загрузите проект
 git clone https://github.com/aleksey-hoffman/sigma-file-manager.git
cd sigma-file-manager
npm install
git checkout 47ce65b
npm run electron:build
 
  1. Установите встроенное приложение с ./dist_electron
  2. Во время запуска приложения вы можете увидеть всплывающее окно

Примечания:

Я просто откатил фиксацию 47ce65b и добавил некоторые тестовые значения, чтобы упростить отладку

Чтобы переключиться на последнюю фиксацию и создать производственную сборку:

 git checkout 5246252
npm run electron:build
 

Все console.log() содержимое electronMain.js отображается в окне терминала (командной строки) (не в консоли инструментов разработчика).

Для запуска функции быстрого просмотра:

  • Выберите любой поддерживаемый файл (изображение/ текст / и т.д.) На странице навигатора
  • Нажмите Пробел (должно открыться окно быстрого просмотра)

To trigger a download event, you can just open «Navigator» 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.

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:

https://github.com/aleksey-hoffman/sigma-file-manager/blob/47ce65bdac78e5c9b17315f16623d40d81dcf1bb/src/electronMain.js#L698

UPDATE:

Smaller reproduction example:

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')
}

 

При setTimeout запуске я вижу следующие console.log() сообщения:

 trigger window 1 download
window will-download handler 1
window will-download handler 2
 

Как вы можете видеть из журнала, событие «загрузка» запускает обработчики событий обоих окон

Если я укажу отдельный раздел для каждого окна, проблема с обработчиками общих событий будет решена, но я получу 2 — ю проблему, упомянутую выше, — при запуске всплывает ассоциация ссылок

 window1 = new electron.BrowserWindow({
  webPreferences: {
    partition: 'partition1',
  }
})
window2 = new electron.BrowserWindow({
  webPreferences: {
    partition: 'partition2',
  }
})
 

Комментарии:

1. В принципе, вы хотите обработать одно и то же событие из двух процессов? Почему бы вам не использовать ipc.send() для отправки сообщения из основного процесса в процесс визуализации? Таким образом, вы обработаете загрузку в основном процессе и отправите сообщение с необходимыми данными в процесс визуализации внутри обработчика

2. @TasosBu ну, я прикрепляю отдельные will-download события к windows.main и к windows.quickViewWindow , но по какой-то причине, когда will-download происходит событие windows.main , оно запускает обработчик windows.quickViewWindow событий прослушивателя событий. Я не знаю, почему обработчик 2-го окна переопределяет обработчик событий 1-го окна. Я исправил это, указав отдельное имя раздела для 2-го окна, чтобы они не использовали одни и те же webContents.session, но, как я уже упоминал, это вызвало еще одну проблему

3. Понял! Что, если в вашем частичном исправлении вместо windows.quickViewWindow.webContents.session.once вас это сделаете windows.quickViewWindow.webContents.session.fromPartition('quickPreview').on вы ? Я думаю, вам нужно указать, к какому сеансу будет прикреплен обработчик

4. Я полагаю, что это может привести к появлению окна «Магазин Windows», поскольку вы прикрепляете обработчик к событию сеанса, которого не существует. Событие существует в вашем quickPreview сеансе, и у него нет обработчика

5. @TasosBu спасибо за предложение, приятель, но, к сожалению, это не решило проблему, всплывающее окно все еще появляется в производственной сборке. Я думаю, что это как-то связано с протоколом. Приложение app:// по умолчанию использует протокол. Я попытался указать пользовательский (что Electron заставляет вас делать, чтобы открывать локальные файлы по соображениям безопасности), поэтому я добавил эту строку в ./src/electronMain.js строку 196: productionPath = `sigma-file-manager://${__static}/quickViewWindow.html` но теперь появляется всплывающее окно Windows, в котором говорится, что мне нужно приложение для открытия ссылки «sigma-файловый менеджер».

Ответ №1:

Я все понял. Если это неправильный способ сделать это, пожалуйста, кто-нибудь, дайте мне знать.

Вот как я это исправил:

Исправление проблемы № 1:

Установите для окна пользовательское имя раздела, чтобы оно использовало свое собственное webContents.session имя вместо общего имени по умолчанию.

Основной процесс:

 windows.quickViewWindow = new electron.BrowserWindow({
  ...
  webPreferences: {
    partition: 'quickView',

...

windows.quickViewWindow.webContents.session.once(
  'will-download',
  (event, item, webContents) => {
    event.preventDefault()
    ...
  }
)
 

quickViewWindow.html:

 ipcRenderer.on('load:webview', (event, data) => {
  ...
  webviewNode.setAttribute('partition', 'quickView')
 

Исправление проблемы № 2:

Установите file:// протокол в рабочем пути для URL-адреса окна:

 productionPath = `file://${__static}/quickViewWindow.html`
 

Вот фиксация: https://github.com/aleksey-hoffman/sigma-file-manager/commit/31208809cda7614a7c2f32237ae14f6c9c602f8f