diff --git a/lib/browser/guest-window-manager.js b/lib/browser/guest-window-manager.js index 0c2a433e64ca..3d920ab54ea2 100644 --- a/lib/browser/guest-window-manager.js +++ b/lib/browser/guest-window-manager.js @@ -138,10 +138,7 @@ const createGuest = function (embedder, url, frameName, options, postData) { return setupGuest(embedder, frameName, guest, options) } -const getGuestWindow = function (guestId) { - const guestContents = webContents.fromId(guestId) - if (guestContents == null) return - +const getGuestWindow = function (guestContents) { let guestWindow = BrowserWindow.fromWebContents(guestContents) if (guestWindow == null) { const hostContents = guestContents.hostWebContents @@ -187,27 +184,35 @@ ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', function (event, url, fr }) ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', function (event, guestId) { - const guestWindow = getGuestWindow(guestId) - if (guestWindow == null) return + const guestContents = webContents.fromId(guestId) + if (guestContents == null) return - if (canAccessWindow(event.sender, guestWindow.webContents)) { - guestWindow.destroy() - } else { + if (!canAccessWindow(event.sender, guestContents)) { console.error(`Blocked ${event.sender.getURL()} from closing its opener.`) + return } + + const guestWindow = getGuestWindow(guestContents) + if (guestWindow != null) guestWindow.destroy() }) ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_METHOD', function (event, guestId, method, ...args) { - const guestWindow = getGuestWindow(guestId) - if (guestWindow == null) { + const guestContents = webContents.fromId(guestId) + if (guestContents == null) { event.returnValue = null return } - if (canAccessWindow(event.sender, guestWindow.webContents)) { + if (!canAccessWindow(event.sender, guestContents)) { + console.error(`Blocked ${event.sender.getURL()} from calling ${method} on its opener.`) + event.returnValue = null + return + } + + const guestWindow = getGuestWindow(guestContents) + if (guestWindow != null) { event.returnValue = guestWindow[method].apply(guestWindow, args) } else { - console.error(`Blocked ${event.sender.getURL()} from calling ${method} on its opener.`) event.returnValue = null } }) diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index a63bba1b4837..7d58bee37471 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -313,7 +313,7 @@ describe('chromium feature', function () { }) }) - describe('window.opener security', function () { + describe('window.opener access from BrowserWindow', function () { this.timeout(10000) const scheme = 'other' @@ -355,6 +355,69 @@ describe('chromium feature', function () { }) }) + describe('window.opener access from ', function () { + this.timeout(10000) + + const scheme = 'other' + const srcPath = `${fixtures}/pages/webview-opener-postMessage.html` + const pageURL = `file://${fixtures}/pages/window-opener-location.html` + let webview = null + + before(function (done) { + protocol.registerFileProtocol(scheme, function (request, callback) { + callback(srcPath) + }, function (error) { + done(error) + }) + }) + + after(function () { + protocol.unregisterProtocol(scheme) + }) + + afterEach(function () { + if (webview != null) webview.remove() + }) + + it('does nothing when origin of webview src URL does not match opener', function (done) { + webview = new WebView() + webview.addEventListener('console-message', function (e) { + assert.equal(e.message, 'null') + done() + }) + webview.setAttribute('allowpopups', 'on') + webview.src = url.format({ + pathname: srcPath, + protocol: scheme, + query: { + p: pageURL + }, + slashes: true + }) + document.body.appendChild(webview) + }) + + it('works when origin does not match opener but has node integration', function (done) { + webview = new WebView() + webview.addEventListener('console-message', function (e) { + webview.remove() + assert.equal(e.message, location.href) + done() + }) + webview.setAttribute('allowpopups', 'on') + webview.setAttribute('nodeintegration', 'on') + webview.src = url.format({ + pathname: srcPath, + protocol: scheme, + query: { + p: pageURL + }, + slashes: true + }) + document.body.appendChild(webview) + }) + }) + describe('window.postMessage', function () { it('sets the source and origin correctly', function (done) { var b, sourceId