#javascript #node.js #electron #chromium
Вопрос:
У меня есть приложение для электронного файлового менеджера, которое создает 2 окна для разных целей:
quickView
окно визуализации, используемое для предварительного просмотра локальных файлов. Он использует прослушиватель «будет загружаться» для обнаружения неподдерживаемых файлов путем предотвращения загрузки.main
главное окно визуализации. Он использует прослушиватель «will-download» для загрузки файлов.
Каждый со своими собственными will-download
слушателями, прикрепленными к их сеансу. Но по какой-то причине quickView
слушатель перезаписывает main
слушателя.
Окно 1
В следующей строке я создаю will-download
прослушиватель для «основного» процесса. Целью этого прослушивателя является загрузка файлов:
win.webContents.session.on('will-download', listener)
windows.main
Параметр в строке ниже является win
ссылкой в строке выше:
const resultInfo = await downloadManager.download(windows.main, {
Окно 2
В следующей строке я создаю will-download
прослушиватель для окна «Быстрый просмотр». Цель этого прослушивателя-обнаружить неподдерживаемые файлы (что запускает событие загрузки в Chromium) и предотвратить событие загрузки:
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):
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})
Частичное исправление
Я частично исправил проблему в этой фиксации, указав пользовательское имя раздела для сеанса 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. Похоже, всплывающее окно запускается ссылкой «приложение».
Или, может быть, это происходит потому, что я неправильно устанавливаю протокол, когда создаю окно где-то в этой строке:
Чтобы воспроизвести:
- Загрузите проект
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
- Во время запуска приложения вы можете увидеть всплывающее окно
Примечания:
Я просто откатил фиксацию 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:
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