Sunday, June 2, 2024
 Popular · Latest · Hot · Upcoming
33
rated 0 times [  39] [ 6]  / answers: 1 / hits: 6969  / 2 Years ago, thu, march 24, 2022, 12:00:00

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.com" 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.


More From » reactjs

 Answers
16

Moving between window sources, whether it be local (file) or remote (URL) can be accomplished 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.com/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 communicate safely between the main thread and render thread(s).


preload.js (main thread)


// Import the necessary Electron components.
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 overcome 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.


[#256] Friday, March 11, 2022, 2 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
stephonkeandrer

Total Points: 392
Total Questions: 94
Total Answers: 100

Location: Tajikistan
Member since Sun, Aug 29, 2021
3 Years ago
;