Setting session or partition in BrowserWindow / Webpreferences not working - electron

I am trying to save cookies to a named session. The cookies are saved in session.defaultSession and get() does return them.
Here I'm attempting to set the partition
mainSession = session.fromPartition("persist:myapi");
Then this function when app.on('ready') is event.
const createMainWindow = () => {
mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
webviewTag: true,
//session: mainSession,
partition: mainSession
},
.....
});
Later after response received I check mainSession and it is empty {}.
Using v 7.1.11
Perhaps the problem is related to my cookie. My electron browserWindow.loadUrl is a local html file. It presents a log in screen to an API. The cookie is returned from the API and while it shows up in session.defaultSession it does not show in devtools (like a typical cookie would in a browser).

Related

Cookie is not set in browser with express-session

Setup
I run two docker containers locally. One express backend and one next.js frontend. My database is on a remote server.
Backend snippet:
const corsOptions = {
origin: '*',
credentials: true,
};
app.use(cors(corsOptions));
app.use(express.static("public"));
app.use(express.json()); // lets us interpret(parse) post requests and returns an Object
app.use(express.urlencoded({ extended: true }));
// import (own) database config
const database = require("./database");
// session middleware
const session = require('express-session');
const MySQLStore = require('express-mysql-session')(session);
const sessionStore = new MySQLStore({}, database);
sessionStore.all(function(error, sessions) {
console.log('all sessions:', sessions);
});
// setting up session middleware
app.use(session({
secret: 'asdasdcads',
createDatabaseTable: true,
store: sessionStore,
resave: false,
saveUninitialized: false,
expiration: 600000,
cookie: {
sameSite: 'lax',
domain: 'localhost'
},
secure: false
}));
When I open the site in localhost:80 (docker container mapped 80:3000), the sessions get created with IDs and when saveUninitialized is set to true the sessions are even stored in my db. The last step, setting the cookie in the browser fails. Instead, if I refresh the site, a new session is created.
I guess the session middleware is not adding a Set-Cookie to the response but I really wonder why and how I can look into it more deeply. I asked chatGPT and added a bunch of stuff to the cookie and session config to make it work, like you can see, but no success. ChatGPT also recommended to set cors after session but later reverted that.

How to access Web app DOM window.MyCollection in electron

I'm trying to get count number from my web application for update badge number & using electron loadURL to run my application.
Also, I'm using the Electron Windows Badge plugin for the badge number on the app icon in windows electron-windows-badge.
This is my web app code for update badge number
window.MyCollection.on('PENDING', (type, contactIdParams) => {
console.log(window.getBadgeCount())
})
I was trying to execute the below code but ipcRenderer unable import & update-badge not working inside executeJavaScript.
let mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
preload: path.join(__dirname, "renderer", "renderer.js"),
}
});
mainWindow.loadURL("https://my-web-application.com");
mainWindow.webContents.on('dom-ready', e => {
mainWindow.webContents.executeJavaScript(`
window.MyCollection.on('PENDING', (type, Id) => {
ipcRenderer.sendSync('update-badge', window.getBadgeCount());
})
`)
});
What's the way to get this count number from my web application and update the badge number of the app icon.
The application object was not being accessed due to a contextIsolation:true.

"Not allowed to load local resource" with file image URL in Electron app

I am working on a note taking Electron app that uses Markdown. Currently, I'm working on inserting images into notes (using the Markdown syntax).
When inserting an image, my main process copies the image into the notes directory, then returns a file:/// URL to the image file. However, when I try to render the image, it doesn't load - and I get the error Not allowed to load local resource: file:///Users/joe/notes/images/foo.jpg.
Is there a way I can configure Electron to allow these local image URLs?
Option 1
Turning the web security off
mainWindow = new BrowserWindow({
height: 563,
useContentSize: true,
width: 1000,
webPreferences: {
webSecurity: false
}
});
Option 2
You can create your own protocol like this answer
Also here is the user that answered that question
You need register a file protocol to remove the file:/// prefix.
import { protocol } from "electron";
app.whenReady().then(() => {
protocol.registerFileProtocol('file', (request, callback) => {
const pathname = decodeURI(request.url.replace('file:///', ''));
callback(pathname);
});
});
https://github.com/electron/electron/issues/23757#issuecomment-640146333

Accessing webContents from within preload script in BrowserWindow

I want to create a "Worker" BrowserWindow from within a render process. The worker process will do some long running calculations and periodically report back.
Instead of creating the worker BrowserWindow from within the main process directly, it looks like I can use the remote module to do so from within the renderer process:
import remote from 'electron'
const workerWindow = new remote.BrowserWindow({
show: false,
webPreferences: {
preload: path.join(__dirname, 'preloadWorker.js')
}
});
workerWindow.loadURL('file://' + __dirname + '/worker.html');
I figured I can use the webContents object of the workerWindow to listen for updates like this:
workerWindow.webContents.on('worker-result', (event, msg) => console.log(msg));
But what I can't figure out how to do is emit events from the 'preloadWorker.js' file. I want to do something this in the preloadWorker.js,
setInterval(() =>{
this.webContents.send('worker-result', 'hello from worker');
}, 1000);
Now I know I could do all of this by sending messages using ipcMain and ipcRemote, but I'm trying to save myself some work...it seems like I should be able to access the webContents from within the preload.js script somehow.
This is a really old question, and you might not need it anymore. However, you can use ipcRenderer.sendToHost to communicate with the webview that your preload script is bound to.
const { ipcRenderer } = require('electron');
setInterval(() => {
ipcRenderer.sendToHost('worker-result', 'hello from worker');
}, 1000);

Passing Data to Windows in Electron

I'm learning Electron and working with multiple windows and IPC. In my main script I have the following:
var storeWindow = new BrowserWindow({
width: 400,
height: 400,
show: false
});
ipc.on('show-store-edit', function(event, store) {
console.log(store);
storeWindow.loadURL('file://' + __dirname + '/app/store.html');
storeWindow.show();
});
And in my primary window's script, I have the following inside of a click event handler, pulling in a list of stores:
$.getJSON("http://localhost:8080/stores/" + item.id).done(function(store) {
ipc.send('show-store-edit', store);
});
On the console, I am printing the store data from my server. What I'm unclear on is how to get that data into the view for my storeWindow:store.html. I'm not even sure I'm handling the sequence of events correctly but they would be:
click Edit Store
get store data from server
open new window to display store data
or
click Edit Store
open new window to display store data
get store data from server
In the latter, I'm not sure how I would get the ID required to fetch the store from the storeWindow's script.
To send events to particular window you can use webContents.send(EVENT_NAME, ARGS) (see docs). webContents is a property of a window instance:
// main process
storeWindow.webContents.send('store-data', store);
To listen for this event being sent, you need a listener in a window process (renderer):
// renderer process
var ipcRenderer = require('electron').ipcRenderer;
ipcRenderer.on('store-data', function (event,store) {
console.log(store);
});
You need the ipcMain module to achieve this... As stated in the API "When used in the main process, it handles asynchronous and synchronous messages sent from a renderer process (web page). Messages sent from a renderer will be emitted to this module."
API Docs for the ipcMain module:
https://electronjs.org/docs/api/ipc-main
To use the ipcMain you need to have nodeIntegration enabled on webPreferences
win = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
}
})
Be careful this may cause security issues.
For example: Let's say we want to pass a configuration (json) file to the web page
(Triple dots (...) represent your code that is already placed inside the file, but is not relevant to this example)
main.js
...
const { readFileSync } = require('fs') // used to read files
const { ipcMain } = require('electron') // used to communicate asynchronously from the main process to renderer processes.
...
// function to read from a json file
function readConfig () {
const data = readFileSync('./package.json', 'utf8')
return data
}
...
// this is the event listener that will respond when we will request it in the web page
ipcMain.on('synchronous-message', (event, arg) => {
console.log(arg)
event.returnValue = readConfig()
})
...
index.html
...
<script>
<!-- import the module -->
const { ipcRenderer } = require('electron')
<!-- here we request our message and the event listener we added before, will respond and because it's JSON file we need to parse it -->
var config = JSON.parse(ipcRenderer.sendSync('synchronous-message', ''))
<!-- process our data however we want, in this example we print it on the browser console -->
console.log(config)
<!-- since we read our package.json file we can echo our electron app name -->
console.log(config.name)
</script>
To see the console of the browser you need to open the dev tools, either from the default Electron menu or from your code.
e.g. inside the createWindow() function
win.webContents.openDevTools()

Resources