Skip to content

Commit 8fd5f36

Browse files
authored
Migrate from BrowserView to WebContentsView (#2542)
* update popup handling * rough draft of BaseWindow/WebContentsView conversion * fix error on window destruction * cleanup * Upgrade electron
1 parent 7b7334c commit 8fd5f36

File tree

9 files changed

+119
-101
lines changed

9 files changed

+119
-101
lines changed

js/tabState/tab.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class TabList {
66

77
//tab properties that shouldn't be saved to disk
88

9-
static temporaryProperties = ['hasAudio', 'previewImage', 'loaded', 'hasBrowserView']
9+
static temporaryProperties = ['hasAudio', 'previewImage', 'loaded', 'hasWebContents']
1010

1111
add (tab = {}, options = {}, emit=true) {
1212
var tabId = String(tab.id || Math.round(Math.random() * 100000000000000000)) // you can pass an id that will be used, or a random one will be generated.
@@ -28,7 +28,7 @@ class TabList {
2828
hasAudio: false,
2929
previewImage: '',
3030
isFileView: false,
31-
hasBrowserView: false,
31+
hasWebContents: false,
3232
}
3333

3434
if (options.atEnd) {

js/util/settings/settingsMain.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ var settings = {
6363
settings.runChangeCallbacks(key)
6464

6565
windows.getAll().forEach(function (win) {
66-
win.webContents.send('settingChanged', key, value)
66+
getWindowWebContents(win).send('settingChanged', key, value)
6767
})
6868
},
6969
initialize: function (userDataPath) {
@@ -86,8 +86,8 @@ var settings = {
8686
settings.runChangeCallbacks(key)
8787

8888
windows.getAll().forEach(function (win) {
89-
if (win.webContents.id !== e.sender.id) {
90-
win.webContents.send('settingChanged', key, value)
89+
if (getWindowWebContents(win).id !== e.sender.id) {
90+
getWindowWebContents(win).send('settingChanged', key, value)
9191
}
9292
})
9393
})

js/webviews.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ const webviews = {
109109
events: [],
110110
IPCEvents: [],
111111
hasViewForTab: function(tabId) {
112-
return tabId && tasks.getTaskContainingTab(tabId) && tasks.getTaskContainingTab(tabId).tabs.get(tabId).hasBrowserView
112+
return tabId && tasks.getTaskContainingTab(tabId) && tasks.getTaskContainingTab(tabId).tabs.get(tabId).hasWebContents
113113
},
114114
bindEvent: function (event, fn) {
115115
webviews.events.push({
@@ -214,7 +214,7 @@ const webviews = {
214214
}
215215

216216
tasks.getTaskContainingTab(tabId).tabs.update(tabId, {
217-
hasBrowserView: true
217+
hasWebContents: true
218218
})
219219
},
220220
setSelected: function (id, options) { // options.focus - whether to focus the view. Defaults to true.
@@ -248,7 +248,7 @@ const webviews = {
248248

249249
if (webviews.hasViewForTab(id)) {
250250
tasks.getTaskContainingTab(id).tabs.update(id, {
251-
hasBrowserView: false
251+
hasWebContents: false
252252
})
253253
}
254254
//we may be destroying a view for which the tab object no longer exists, so this message should be sent unconditionally

main/download.js

+2-9
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,7 @@ function isAttachment (header) {
1111
}
1212

1313
function downloadHandler (event, item, webContents) {
14-
const sourceView = Object.values(viewMap).find(view => view.webContents.id === webContents.id)
15-
let sourceWindow
16-
if (sourceView) {
17-
sourceWindow = BrowserWindow.fromBrowserView(sourceView)
18-
}
14+
let sourceWindow = windows.windowFromContents(webContents)?.win
1915
if (!sourceWindow) {
2016
sourceWindow = windows.getCurrent()
2117
}
@@ -64,10 +60,7 @@ function listenForDownloadHeaders (ses) {
6460
if (details.resourceType === 'mainFrame' && details.responseHeaders) {
6561
let sourceWindow
6662
if (details.webContents) {
67-
const sourceView = Object.values(viewMap).find(view => view.webContents.id === details.webContents.id)
68-
if (sourceView) {
69-
sourceWindow = BrowserWindow.fromBrowserView(sourceView)
70-
}
63+
sourceWindow = windows.windowFromContents(details.webContents)?.win
7164
}
7265
if (!sourceWindow) {
7366
sourceWindow = windows.getCurrent()

main/main.js

+49-31
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ const path = require('path')
55
const {
66
app, // Module to control application life.
77
protocol, // Module to control protocol handling
8-
BrowserWindow, // Module to create native browser window.
8+
BaseWindow, // Module to create native browser window.
9+
BrowserWindow,
910
webContents,
1011
session,
1112
ipcMain: ipc,
@@ -14,7 +15,8 @@ const {
1415
dialog,
1516
nativeTheme,
1617
shell,
17-
net
18+
net,
19+
WebContentsView
1820
} = electron
1921

2022
crashReporter.start({
@@ -98,24 +100,24 @@ function sendIPCToWindow (window, action, data) {
98100
return
99101
}
100102

101-
if (window && window.webContents && window.webContents.isLoadingMainFrame()) {
103+
if (window && getWindowWebContents(window).isLoadingMainFrame()) {
102104
// immediately after a did-finish-load event, isLoading can still be true,
103105
// so wait a bit to confirm that the page is really loading
104106
setTimeout(function() {
105-
if (window.webContents.isLoadingMainFrame()) {
106-
window.webContents.once('did-finish-load', function () {
107-
window.webContents.send(action, data || {})
107+
if (getWindowWebContents(window).isLoadingMainFrame()) {
108+
getWindowWebContents(window).once('did-finish-load', function () {
109+
getWindowWebContents(window).send(action, data || {})
108110
})
109111
} else {
110-
window.webContents.send(action, data || {})
112+
getWindowWebContents(window).send(action, data || {})
111113
}
112114
}, 0)
113115
} else if (window) {
114-
window.webContents.send(action, data || {})
116+
getWindowWebContents(window).send(action, data || {})
115117
} else {
116118
var window = createWindow()
117-
window.webContents.once('did-finish-load', function () {
118-
window.webContents.send(action, data || {})
119+
getWindowWebContents(window).once('did-finish-load', function () {
120+
getWindowWebContents(window).send(action, data || {})
119121
})
120122
}
121123
}
@@ -188,7 +190,7 @@ function createWindow (customArgs = {}) {
188190
}
189191

190192
function createWindowWithBounds (bounds, customArgs) {
191-
const newWin = new BrowserWindow({
193+
const newWin = new BaseWindow({
192194
width: bounds.width,
193195
height: bounds.height,
194196
x: bounds.x,
@@ -201,6 +203,15 @@ function createWindowWithBounds (bounds, customArgs) {
201203
frame: settings.get('useSeparateTitlebar'),
202204
alwaysOnTop: settings.get('windowAlwaysOnTop'),
203205
backgroundColor: '#fff', // the value of this is ignored, but setting it seems to work around https://github.com/electron/electron/issues/10559
206+
})
207+
208+
// windows and linux always use a menu button in the upper-left corner instead
209+
// if frame: false is set, this won't have any effect, but it does apply on Linux if "use separate titlebar" is enabled
210+
if (process.platform !== 'darwin') {
211+
newWin.setMenuBarVisibility(false)
212+
}
213+
214+
const mainView = new WebContentsView({
204215
webPreferences: {
205216
nodeIntegration: true,
206217
contextIsolation: false,
@@ -217,20 +228,19 @@ function createWindowWithBounds (bounds, customArgs) {
217228
]
218229
}
219230
})
231+
mainView.webContents.loadURL(browserPage)
232+
mainView.setBounds({x: 0, y: 0, width: bounds.width, height: bounds.height})
233+
newWin.contentView.addChildView(mainView)
220234

221-
// windows and linux always use a menu button in the upper-left corner instead
222-
// if frame: false is set, this won't have any effect, but it does apply on Linux if "use separate titlebar" is enabled
223-
if (process.platform !== 'darwin') {
224-
newWin.setMenuBarVisibility(false)
225-
}
226-
227-
// and load the index.html of the app.
228-
newWin.loadURL(browserPage)
235+
newWin.on('resize', function() {
236+
const winBounds = newWin.getBounds()
237+
mainView.setBounds({x: 0, y: 0, width: winBounds.width, height: winBounds.height})
238+
})
229239

230240
if (bounds.maximized) {
231241
newWin.maximize()
232242

233-
newWin.webContents.once('did-finish-load', function () {
243+
mainView.webContents.once('did-finish-load', function () {
234244
sendIPCToWindow(newWin, 'maximize')
235245
})
236246
}
@@ -269,7 +279,7 @@ function createWindowWithBounds (bounds, customArgs) {
269279

270280
newWin.on('blur', function () {
271281
// if the devtools for this window are focused, this check will be false, and we keep the focused class on the window
272-
if (BrowserWindow.getFocusedWindow() !== newWin) {
282+
if (BaseWindow.getFocusedWindow() !== newWin) {
273283
sendIPCToWindow(newWin, 'blur')
274284
}
275285
})
@@ -311,7 +321,7 @@ function createWindowWithBounds (bounds, customArgs) {
311321
}
312322

313323
// prevent remote pages from being loaded using drag-and-drop, since they would have node access
314-
newWin.webContents.on('will-navigate', function (e, url) {
324+
mainView.webContents.on('will-navigate', function (e, url) {
315325
if (url !== browserPage) {
316326
e.preventDefault()
317327
}
@@ -340,7 +350,7 @@ app.on('ready', function () {
340350

341351
const newWin = createWindow()
342352

343-
newWin.webContents.on('did-finish-load', function () {
353+
getWindowWebContents(newWin).on('did-finish-load', function () {
344354
// if a URL was passed as a command line argument (probably because Min is set as the default browser on Linux), open it.
345355
handleCommandLineArguments(process.argv)
346356

@@ -403,8 +413,7 @@ app.on('activate', function (/* e, hasVisibleWindows */) {
403413
})
404414

405415
ipc.on('focusMainWebContents', function () {
406-
//TODO fix
407-
windows.getCurrent().webContents.focus()
416+
getWindowWebContents(windows.getCurrent()).focus()
408417
})
409418

410419
ipc.on('showSecondaryMenu', function (event, data) {
@@ -430,25 +439,30 @@ ipc.on('quit', function () {
430439
})
431440

432441
ipc.on('tab-state-change', function(e, events) {
442+
const sourceWindowId = windows.windowFromContents(e.sender)?.id
443+
if (!sourceWindowId) {
444+
console.warn('warning: received tab state update from window after destruction, ignoring')
445+
return
446+
}
433447
windows.getAll().forEach(function(window) {
434-
if (window.webContents.id !== e.sender.id) {
435-
window.webContents.send('tab-state-change-receive', {
436-
sourceWindowId: windows.windowFromContents(e.sender).id,
448+
if (getWindowWebContents(window).id !== e.sender.id) {
449+
getWindowWebContents(window).send('tab-state-change-receive', {
450+
sourceWindowId,
437451
events
438452
})
439453
}
440454
})
441455
})
442456

443457
ipc.on('request-tab-state', function(e) {
444-
const otherWindow = windows.getAll().find(w => w.webContents.id !== e.sender.id)
458+
const otherWindow = windows.getAll().find(w => getWindowWebContents(w).id !== e.sender.id)
445459
if (!otherWindow) {
446460
throw new Error('secondary window doesn\'t exist as source for tab state')
447461
}
448462
ipc.once('return-tab-state', function(e2, data) {
449463
e.returnValue = data
450464
})
451-
otherWindow.webContents.send('read-tab-state')
465+
getWindowWebContents(otherWindow).send('read-tab-state')
452466
})
453467

454468
/* places service */
@@ -472,4 +486,8 @@ app.once('ready', function() {
472486

473487
ipc.on('places-connect', function (e) {
474488
placesWindow.webContents.postMessage('places-connect', null, e.ports)
475-
})
489+
})
490+
491+
function getWindowWebContents (win) {
492+
return win.getContentView().children[0].webContents
493+
}

main/menu.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ function buildAppMenu (options = {}) {
337337
if (process.platform === 'darwin') { return 'Shift+Cmd+Alt+I' } else { return 'Ctrl+Shift+Alt+I' }
338338
})(),
339339
click: function (item, focusedWindow) {
340-
if (focusedWindow) focusedWindow.toggleDevTools()
340+
if (focusedWindow) getWindowWebContents(focusedWindow).toggleDevTools()
341341
}
342342
},
343343
{

0 commit comments

Comments
 (0)