How to return value from webContents.executeJavaScript


#1

Hi,

I wrote a program for browser automation, and instead of using some external library, I decided to use electron only tools such as Web Contents and Browser Window. It was all ok. I was using webContents.executeJavaScript, to send all commands to fill inputs, and click buttons. But now I need to check if some input/button exists, before clicking on it.

I can do something like webContents.executeJavaScript(“typeof document.querySelector(’#login’) != ‘undefined’”); But webContents.executeJavaScript function doesn’t return anything, it just executes. Do you guys have any ideas/hack, how to return using executeJavaScript or something similar?


#2

You could use the && operator which will only execute its second argument if the first one evaluates to true.

webContents.executeJavaScript(
  `typeof document.querySelector('#login') != 'undefined' &&
    document.querySelector('#login').dispatchEvent(new MouseEvent('click'))`
);

#3

Ok, what if I just want to check if some element exists or not? Just like, if some element exists, I’ll print user its content. How can I do that?


#4

The C++ WebContents::ExecuteJavaScript method does not return anything, so you can’t use executeJavaScript to retrieve data from a renderer process. Instead, you could use the ipc module.

If possible, an alternative would be to move all this logic into the renderer process, leaving just the OS stuff in the main process.


#5

I tried to read ipc module. But I don’t think that it will solve my problem.

Maybe I don’t understand something? Can you provide some simple code example?


#6

ipcRenderer can send any number of things to ipcMain. If you get into longer strings of code, put the code in a variable, concatenate the strings, and pass the variable name to executeJavaScript. I have run over 100 lines of code this way triggered by a did-finish-load event. Specifically addressing your code, if you want to get the boolean value of the your query, assign the value to a variable, then say something like ipcRenderer.send(‘got-bool-val’, boolVal); in your string of code to execute, then in your main something like ipcMain.on(‘got-bool-val’, function(event, boolVal){ /function code/ }); Since you know it now exists, you can use webContents to print whatever.


#7

Just a note that electron supports ES6 template strings. These strings can be multi-line strings with interpolation. They are marked with ` and interpolation is ${variable}. This can make setting up your js strings to be executed much easier.


#9

Working code example.

Note, you cannot pass the document object or any DOM objects back to the ipcMain event listener.

File: app.js

var BrowserWindow = require('electron').remote.BrowserWindow;
var win = new BrowserWindow({ show : false });
var ipcMain = require("electron").remote.ipcMain;

win.webContents.openDevTools();

win.loadURL('http://discuss.atom.io');

win.webContents.on('dom-ready', function (e) {
  win.webContents.executeJavaScript(`
    var ipcRenderer = require('electron').ipcRenderer;
    var value = ''; // Must be a prototype which does not reference the DOM
    ipcRenderer.send('query', value);
  `);
});

ipcMain.on('query', function (event, value) {
  console.log(value);
});