Browse Source

Merge pull request #8584 from electron/new-webview-event

Add will-attach-webview event
Kevin Sawicki 8 years ago
parent
commit
acedc3e726
4 changed files with 59 additions and 3 deletions
  1. 14 0
      docs/api/web-contents.md
  2. 11 2
      lib/browser/guest-view-manager.js
  3. 11 0
      spec/static/main.js
  4. 23 1
      spec/webview-spec.js

+ 14 - 0
docs/api/web-contents.md

@@ -502,6 +502,20 @@ win.loadURL('http://github.com')
 
 Emitted when the devtools window instructs the webContents to reload
 
+#### Event: 'will-attach-webview'
+
+Returns:
+
+* `event` Event
+* `webPreferences` Object - The web preferences that will be used by the guest
+  page. This object can be modified to adjust the preferences for the guest
+  page.
+* `params` Object - The other `<webview>` parameters such as the `src` URL.
+  This object can be modified to adjust the parameters of the guest page.
+
+Emitted when a `<webview>`'s web contents is being attached to this web
+contents. Calling `event.preventDefault()` will destroy the guest page.
+
 ### Instance Methods
 
 #### `contents.loadURL(url[, options])`

+ 11 - 2
lib/browser/guest-view-manager.js

@@ -147,7 +147,8 @@ const createGuest = function (embedder, params) {
 }
 
 // Attach the guest to an element of embedder.
-const attachGuest = function (embedder, elementInstanceId, guestInstanceId, params) {
+const attachGuest = function (event, elementInstanceId, guestInstanceId, params) {
+  const embedder = event.sender
   // Destroy the old guest when attaching.
   const key = `${embedder.getId()}-${elementInstanceId}`
   const oldGuestInstanceId = embedderElementsMap[key]
@@ -204,6 +205,14 @@ const attachGuest = function (embedder, elementInstanceId, guestInstanceId, para
   if (params.preload) {
     webPreferences.preloadURL = params.preload
   }
+
+  embedder.emit('will-attach-webview', event, webPreferences, params)
+  if (event.defaultPrevented) {
+    if (guest.viewInstanceId == null) guest.viewInstanceId = params.instanceId
+    destroyGuest(embedder, guestInstanceId)
+    return
+  }
+
   webViewManager.addGuest(guestInstanceId, elementInstanceId, embedder, guest, webPreferences)
   guest.attachParams = params
   embedderElementsMap[key] = guestInstanceId
@@ -276,7 +285,7 @@ ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST', function (event, params,
 })
 
 ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_ATTACH_GUEST', function (event, elementInstanceId, guestInstanceId, params) {
-  attachGuest(event.sender, elementInstanceId, guestInstanceId, params)
+  attachGuest(event, elementInstanceId, guestInstanceId, params)
 })
 
 ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_DESTROY_GUEST', function (event, guestInstanceId) {

+ 11 - 0
spec/static/main.js

@@ -250,6 +250,17 @@ ipcMain.on('prevent-next-new-window', (event, id) => {
   webContents.fromId(id).once('new-window', event => event.preventDefault())
 })
 
+ipcMain.on('prevent-next-will-attach-webview', (event) => {
+  event.sender.once('will-attach-webview', event => event.preventDefault())
+})
+
+ipcMain.on('disable-node-on-next-will-attach-webview', (event, id) => {
+  event.sender.once('will-attach-webview', (event, webPreferences, params) => {
+    params.src = `file://${path.join(__dirname, '..', 'fixtures', 'pages', 'c.html')}`
+    webPreferences.nodeIntegration = false
+  })
+})
+
 ipcMain.on('try-emit-web-contents-event', (event, id, eventName) => {
   const consoleWarn = console.warn
   let warningMessage = null

+ 23 - 1
spec/webview-spec.js

@@ -2,7 +2,7 @@ const assert = require('assert')
 const path = require('path')
 const http = require('http')
 const url = require('url')
-const {remote} = require('electron')
+const {ipcRenderer, remote} = require('electron')
 const {app, session, getGuestWebContents, ipcMain, BrowserWindow, webContents} = remote
 const {closeWindow} = require('./window-helpers')
 
@@ -1100,6 +1100,28 @@ describe('<webview> tag', function () {
     w.loadURL('file://' + fixtures + '/pages/webview-visibilitychange.html')
   })
 
+  describe('will-attach-webview event', () => {
+    it('supports changing the web preferences', (done) => {
+      ipcRenderer.send('disable-node-on-next-will-attach-webview')
+      webview.addEventListener('console-message', (event) => {
+        assert.equal(event.message, 'undefined undefined undefined undefined')
+        done()
+      })
+      webview.setAttribute('nodeintegration', 'yes')
+      webview.src = 'file://' + fixtures + '/pages/a.html'
+      document.body.appendChild(webview)
+    })
+
+    it('supports preventing a webview from being created', (done) => {
+      ipcRenderer.send('prevent-next-will-attach-webview')
+      webview.addEventListener('destroyed', () => {
+        done()
+      })
+      webview.src = 'file://' + fixtures + '/pages/c.html'
+      document.body.appendChild(webview)
+    })
+  })
+
   it('loads devtools extensions registered on the parent window', function (done) {
     w = new BrowserWindow({
       show: false