Problems with blocking a webview's network requests


#1

So I’m trying to figure out how to make a plugin system for an electron app I’m making, so I made a small test app with the electron-vue template and what I’m trying to do is use a webview to sandbox the plugins. I got that all working nicely. But now I also want to prevent all network requests from the webview, except to a very limited set of urls. To start off I just blocked everything. But this is causing problems.

Here’s the code. In the renderer I have a button which adds a webview element to the dom. And then after it’s ready tries to intercept the requests:

//vue add method
add() {
    let webview = document.createElement('webview');
    webview.setAttribute('src', this.pluginPath+"/index.html");
    webview.setAttribute('preload', this.preloadPath);     
    let place = this.$el.querySelector("#plugin")
    place.appendChild(webview);

    webview.addEventListener("dom-ready", () => {
       let session = webview.getWebContents().session
       session.webRequest.onBeforeSendHeaders(["*"], (details, callback) => {
          console.log(details)
      
          //if (!details.url.indexOf("http://localhost") == 0) {
              callback({cancel: true, requestHeaders: details.requestHeaders})
          //} else {
          //    callback({cancel: false, requestHeaders: details.requestHeaders})
          //}
        })
        webview.openDevTools();
    })
}

Now everything seems to work fine but then when I reload the app it goes blank. In the developer tools it says GET http://localhost:9080/ net::ERR_BLOCKED_BY_CLIENT. If I allow localhost through the error goes away but then in the console I get the following and the app still doesn’t reload:

Attempting to call a function in a renderer window that has been closed or released.
Function provided here: 28:68:32

I then tried all this with a plain electron template without vue. Blocking is working correctly and reloading works, localhost never gets blocked, but the error is still logging, although now it’s a little more helpful:

Attempting to call a function in a renderer window that has been closed or released.
Function provided here: HTMLElement.webview.addEventListener (A:\User Folders\Documents\GitHub\electron-test2\renderer.js:14:21

Anybody have any idea what’s happening?


#2

Okay so after rereading the docs I tried passing null for the filters to remove the listener when deleting the webview and that finally allowed me to reload properly.

I thought okay, I’ll add a listener for when the webview closes:

To manually close it:

del() {
   this.webview.executeJavaScript("window.close()")
}

which triggers:

this.webview.addEventListener("close", ()=> {
   console.log("closed")
   let session = this.webview.getWebContents().session
   session.webRequest.onBeforeSendHeaders(null)
   this.webview.remove()
   this.webview = undefined
})

But… this doesn’t actually fire on reload so I had to deal with that separately, though in the future each component will have one webview and can just call this.del() on beforeDestroy

beforeMount() {
   window.onbeforeunload = (e) => {
      document.querySelectorAll("webview").forEach(el=>{
         let session = el.getWebContents().session
         session.webRequest.onBeforeSendHeaders(null)
         el.remove()
      })
   }
},

But is this the correct way to close a webview? Because window.close() doesn’t actually do anything at all except fire the event. Also I’m looking at the memory heap and the elements seem to stay there in the detached dom tree in red. Not too familiar with how to debug this though.