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

2.3k Views Asked by At

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?

2

There are 2 best solutions below

0
On BEST ANSWER

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.

0
On

I hope it is ok to post the final solution here, which I found thanks to the previous answer?

The task was to pause a clock if background throttling was active. Since the reaction had to happen in the renderer process, the renderer process event needed to be mirrored back from main to the renderer, but only in case background throttling was active:

//-------------------------------------
// renderer process (index.html):

const { ipcRenderer }   = require ("electron")
let boolClockPausing    = 0 // stores the user's setting, not the pausing because of throttling

window.addEventListener ( "blur",  ()=>{
    if(!boolClockPausing) ipcRenderer.send ("window-focus", 0) })   // tell main about blur

window.addEventListener ( "focus", ()=>{
    if(!boolClockPausing) ipcRenderer.send ("window-focus", 1) })   // tell main about focus

// main tells us our previous blur/focus event happened with bgThrottling:
ipcRenderer.on ("window-focus-throttling", (event, boolFocus)=>{
    ClockOff( boolFocus ? 0 : 1 ) })

//-------------------------------------
// main process (main.js):

const { ipcMain } = require ("electron");

ipcMain.on ("window-focus", (event, boolFocus) => {
    const webContents = event.sender
    if (webContents.backgroundThrottling)
        webContents.send ("window-focus-throttling", boolFocus)
})

With a working example I find it much easier to find and understand more information from the Electron documentation.