javascriptelectronipcipcrendereripcmain

Electron: How to get webContents (to check on backgroundThrottling)?


To check on the state of backgroundThrottling I want to access the webContents inside an event handler:

window.addEventListener('blur', ()=>{
    if(window.webContents.backgroundThrottling)
        ...
});

But when the event occurs I get the error message: "Cannot read property 'backgroundThrottling' of undefined". I tried a few things, but I could never get a defined webContents.

As requested I add: This runs in index.html, so the renderer process? The window "was just available". I don't know where it was defined (but neither in index.html nor in renderer.js). (I'm quite new to JS and even newer to Electron.)

When I print the window in console.log I get:

globalĀ {window: global, self: global, document: ...

So maybe this isn't the browser window, but the Electron one? But how do I get the browser window from within index.html (not creating a new one, but getting the current one)?

EDIT: But since it has all of my document's things in it it should be the browser window, shouldn't it?


Solution

  • TL;DR: The window global is, for security reasons, not an Electron BrowserWindow but the pure window global you'll find inside any given (actual) browser. You'll need to execute your code on the main process.


    webContents is an additional class by Electron and as such only available in the main process (see its docs). Thus, the renderer process (the window you open) cannot access it.

    window.webContents only works if window is a variable of the BrowserWindow class, this means that you need the same object you create in your main process when opening a window.

    To resolve your problem, pass a message via IPC (inter-process communication) to your main process in the event listener and execute the code depending on webContents.backgroundThrottling inside the ipcMain listener. This could be done like so:

    // renderer process (index.html)
    const { ipcRenderer } = require ("electron");
    
    window.addEventListener ("blur", () => { ipcRenderer.send ("window-blur", null); });
    
    // main process (app.js or main.js or whatever you call it)
    const { ipcMain } = require ("electron");
    
    ipcMain.on ("window-blur", (event, args) => {
        // args === null, but event.sender is the webContents of the BrowserWindow
        // which sent the event
        if (event.sender.backgroundThrottling) {
            // ...
        }
    });
    

    However, it could be worthwhile to read up on IPC in Electron (there are more elegant ways to solve this problem, especially if you only need webContents.backgroundThrottling from the main process) as well as the dual-process-model (main and renderer process) as you seem to be lacking understanding of the concept which is important not only for programming in Electron, but also for the security of Electron applications.

    These documentation pages could be helpful resources:


    Note: Above code only works if you have nodeIntegration set to true in the BrowserWindow's settings when creating it. This, however, is not in the scope of this question and has been answered countless times here on SO before.