最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Electron: how to open an url in the same window and after the user do some action go back to application in the sam

programmeradmin1浏览0评论

I have an Electron app that is displayed using BrowserWindow. I want to open an external URL in the same window so that the user can log in (to an external website) and after the user logs in it should display the Electron application again instead of the external website that the user used to log in.

I've been able to open the external url in the same window by using:

<a href="; target="_blank" rel="noreferrer">
  site where you have to log in
</a>

However, I don't know how to show the Electron application again after the user successfully logs in to the external website. Also, I would like to keep the session from the external website so that I could consume its API inside the electron application.

I have an Electron app that is displayed using BrowserWindow. I want to open an external URL in the same window so that the user can log in (to an external website) and after the user logs in it should display the Electron application again instead of the external website that the user used to log in.

I've been able to open the external url in the same window by using:

<a href="https://loginsite-example." target="_blank" rel="noreferrer">
  site where you have to log in
</a>

However, I don't know how to show the Electron application again after the user successfully logs in to the external website. Also, I would like to keep the session from the external website so that I could consume its API inside the electron application.

Share Improve this question edited Mar 25, 2022 at 3:19 ash 1,0551 gold badge7 silver badges22 bronze badges asked Mar 24, 2022 at 12:56 Caio NakaiCaio Nakai 2921 gold badge4 silver badges16 bronze badges 7
  • 1 You should look for some topics related to electron and OAuth (stackoverflow./questions/37546656/…) – slawciu Commented Mar 24, 2022 at 13:08
  • Just to confirm, are you wanting your Electron app to load a local (file) window, upon clicking a 'login' button or link, load a remote (URL) and then once logged in, appear to go back by loading a local (file) window (again)? – midnight-coding Commented Mar 24, 2022 at 13:16
  • @midnight-coding exactly that – Caio Nakai Commented Mar 24, 2022 at 13:21
  • Ok, that can be done (I think). As an alternative solution, could you create a local login (file) window that posts the users login details (over https) and receives a (successful or failed) response? You mentioned that you wish to keep the session information. If your application (once logged in) can already use the API, can the API handle a login as well? – midnight-coding Commented Mar 24, 2022 at 13:36
  • @midnight-coding nice idea maybe I will try this approach later.. thanks :) – Caio Nakai Commented Mar 24, 2022 at 15:03
 |  Show 2 more ments

1 Answer 1

Reset to default 5

Moving between window sources, whether it be local (file) or remote (URL) can be acplished by just calling window.loadFile(...) or window.loadURL(...), but only after the instance of the window has been created.

main.js (main thread)

const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;
const electronIpcMain = require('electron').ipcMain;

const nodePath = require("path");

// Prevent garbage collection
let window;

function createWindow() {
    return new electronBrowserWindow({
        x: 0,
        y: 0,
        width: 800,
        height: 600,
        show: false,
        webPreferences: {
            nodeIntegration: false,
            contextIsolation: true,
            preload: nodePath.join(__dirname, 'preload.js')
        }
    });
}

function showMainWindow() {
    window.loadFile('index.html')
        .then(() => { window.show(); })
}

function showLoginWindow() {
    // window.loadURL('https://www.your-site./login')
    window.loadFile('login.html') // For testing purposes only
        .then(() => { window.show(); })
}

electronApp.on('ready', () => {
    window = createWindow();
    showMainWindow();
});

electronApp.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
        electronApp.quit();
    }
});

electronApp.on('activate', () => {
    if (electronBrowserWindow.getAllWindows().length === 0) {
        createWindow();
    }
});

// ----- IPC -----

electronIpcMain.on('message:loginShow', (event) => {
    showLoginWindow();
})

electronIpcMain.on('message:loginSuccessful', (event, session) => {
    showMainWindow();
})

index.html (render thread)

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Main Window</title>
    </head>

    <body>
        <div>Main Window</div><hr>

        <button type="button" id="show-login">Login</button>
    </body>

    <script>
        document.getElementById('show-login').addEventListener('click', () => {
            window.ipcRender.send('message:loginShow');
        });
    </script>
</html>

login.html (render thread)

Used for testing purposes only as we do not have access to a real login page.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Login Window</title>
    </head>

    <body>
        <div>Login Window</div><hr>

        <label for="username">Username: </label>
        <input type="text" id="username"><br>

        <label for="password">Password: </label>
        <input type="password" id="password"><br>

        <button type="button" id="login">Login</button>
    </body>

    <script>
        // For testing purposes only.
        document.getElementById('login').addEventListener('click', () => {
            window.ipcRender.send('message:loginSuccessful');
        });
    </script>
</html>

And finally, a preload.js script to municate safely between the main thread and render thread(s).

preload.js (main thread)

// Import the necessary Electron ponents.
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;

// White-listed channels.
const ipc = {
    'render': {
        // From render to main.
        'send': [
            'message:loginShow',
            'message:loginSuccessful'
        ],
        // From main to render.
        'receive': [],
        // From render to main and back again.
        'sendReceive': []
    }
};

// Exposed protected methods in the render process.
contextBridge.exposeInMainWorld(
    // Allowed 'ipcRenderer' methods.
    'ipcRender', {
        // From render to main.
        send: (channel, args) => {
            let validChannels = ipc.render.send;
            if (validChannels.includes(channel)) {
                ipcRenderer.send(channel, args);
            }
        },
        // From main to render.
        receive: (channel, listener) => {
            let validChannels = ipc.render.receive;
            if (validChannels.includes(channel)) {
                // Deliberately strip event as it includes `sender`.
                ipcRenderer.on(channel, (event, ...args) => listener(...args));
            }
        },
        // From render to main and back again.
        invoke: (channel, args) => {
            let validChannels = ipc.render.sendReceive;
            if (validChannels.includes(channel)) {
                return ipcRenderer.invoke(channel, args);
            }
        }
    }
);

A problem that will need to be overe is once you submit your login credentials to the server, how are you going to get the session data? Your html Javascript will need to detect if and when the necessary session data is available. Once the session data is available, it is an easy process of transferring the session via IPC from the render thread to the main thread. To figure this out, one will require some additional information and understanding of your login system (a separate StackOverflow question).

As a pre-cursor, I suspect one would need to detect in the main thread when the login page has been submitted to the server via something like window.webContents.on('did-navigate', ...). Once detected, check the next loaded page quickly to see if a session exists. If so, get it, send it to the main thread and then redirect back to the index.html page.

I think there should be an easier way if you can login via an API. Then the whole process can be self-contained in your Electron application. IE: Show local (file) login.html, submit data to server and await a "success" or "fail" response. If successful, pass the session data in the response. If unsuccessful, display an appropriate error message.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论