Search code examples
javascriptnpmelectronchromium

Extract Input field filled data from Electron BrowserView


For example, here is a simple BrowserWindow with appropriate security settings except for webviewTag: true which is necessary for this project.

let webPrefs = {
    plugins: false,
    nodeIntegration: false,
    nodeIntegrationInWorker: false,
    webviewTag: true,
    sandbox: true,
    enableRemoteModule: false,
    contextIsolation: true,
    disableBlinkFeatures: "Auxclick",
    webSecurity: true
};

let winOpts = {
    ...
    show: true,
    webPreferences: webPrefs
};

...

win = new BrowserWindow(winOpts);
const view = new BrowserView(winOpts);
win.setBrowserView(view);

...

view.webContents.loadURL("https://example.com").then(result => {
....
});

Suppose that the example.com website contains <form> with several <input> fields.

Users will type text on these <input> fields.

I want to extract the 'manually filled' text from those <input> fields. The webpage is not mine and thus cannot modify the website.

webContents.executeJavaScript() can be a start point, but couldn't find how to 'extract' the value itself to the main process.

(filling the forms from main process can be done by using the function above.)

How can I achieve this?


Solution

  • in your main import ipcMain from electron like this

    const { ipcMain, app, BrowserWindow,BrowserView } = require("electron");
    

    in your webPrefs add preload file. for example

    let webPrefs = {
        plugins: false,
        nodeIntegration: false,
        nodeIntegrationInWorker: false,
        webviewTag: true,
        sandbox: true,
        enableRemoteModule: false,
        contextIsolation: true,
        disableBlinkFeatures: "Auxclick",
        webSecurity: true,
        preload:"./preload.js"
    };
    

    create a new preload file and named it "preload.js". of course you can name it and to anything you want just make sure you set the correct filename in the preload above.

    this file is like a bridge between you webview and main process. A preload script runs before the renderer process is loaded, and has access to both renderer globals (e.g. window and document) and a Node.js environment.

    put the following code in preload.js file

    const { ipcRenderer } = require("electron");
    
    window.addEventListener("input", (e) => {
      //dom_element_id = the id of input element you want
      if (e.target.id === "dom_element_id")
        ipcRenderer.invoke("INPUT_OCCURED", e.target.value);
    });
    

    now go back to your main file and and for example you can add

      win.loadURL("https://www.example.com");
    
      ipcMain.handle("INPUT_OCCURED", (event, data) => {
        console.log(data);
      });
    

    that all the code you need. now with some more explanation.
    the preload file is loaded before the webview content and can run anything you want. its also had access to node stuff. what we do it communicate between the preload and the main using ipc. we adding a global listener in the preload which listing to all input event. then he checks and if the id is match the dom_element_id its send the dom element value to main. the main got the event data in INPUT_OCCURED he listing on

    the reason i add a global listener instead of get the element and add listener to him is just for simplicity of the example