Reputation: 882
I am new to electron and converting an web app to desktop application.I am loading pages from file system.Cookies are working if pages are served from web server but when I load pages from local folder I am not able to save them. I am saving cookie using document.cookie in web.I want to know how I can I enable file:// cookies in electron .
Regards
Upvotes: 9
Views: 25620
Reputation: 33
There are two possible scenarios:
1- Remote URL if you are trying to load a remote URl i.e
new BrowserWindow().loadURL('www.example.com')
than you can set/get cookies by modifying default session and these cookies will be used in all requests to that URL
const { session } = require('electron')
// Query all cookies.
session.defaultSession.cookies.get({})
.then((cookies) => {
console.log(cookies)
}).catch((error) => {
console.log(error)
})
// Query all cookies associated with a specific url.
session.defaultSession.cookies.get({ url: 'http://www.github.com' })
.then((cookies) => {
console.log(cookies)
}).catch((error) => {
console.log(error)
})
// Set a cookie with the given cookie data;
// may overwrite equivalent cookies if they exist.
const cookie = { url: 'http://www.github.com', name: 'dummy_name', value: 'dummy' }
session.defaultSession.cookies.set(cookie)
.then(() => {
// success
}, (error) => {
console.error(error)
})
refrence : electron cookies api
2-Local URL if you are trying to load a local URl i.e
new BrowserWindow().loadURL(`file://${__dirname}/index.html`)
OR
new BrowserWindow().loadFile('index.html')
and you are using fetch API or XMLHTTPrequest in your local HTML file(index.html) to send GET/POST request to a webserver and trying to set or retrieve cookies, I have bad news for you, I searched for four to five hours and didnt found any simple method that allows you to set or retrieve cookies using fetch or XMLHTTPRequest. Only solution I went for is to enable node integration in BrowserWindow and use nodes https and http modules. My code:
app.js/index.js (entry point)
const { app, BrowserWindow } = require('electron');
app.on('ready', () => {
let mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
},
});
mainWindow.loadURL(`file://${__dirname}/main.html`);
});
main.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Data Set</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
</head>
<body>
<div class="d-flex vw-100 vh-100 justify-content-center align-items-center">
<form id="jform" class="text-center">
<input type="text" class=" mt-3 form-control" id="jcaptcha" placeholder="Type captcha here">
<button type="submit" id="sbmt" class="btn w-100 btn-primary mt-2 d-block">Submit</button>
</form>
</div>
<script src="helper.js"></script>
<script src="main.js"></script>
</body>
</html>
helper.js
const https = require('https');
// proxy setup to debug requests using Fiddler
// process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
// const proxy = require("node-global-proxy").default;
// proxy.setConfig({
// http: "http://127.0.0.1:8888",
// https: "http://127.0.0.1:8888",
// });
// proxy.start();
function sendHttpsGetRequest(targetUrl, cookies, callback) {
const requestOptions = {
method: 'GET',
headers: {
'Cookie': cookies.join('; ')
},
};
const getRequest = https.get(targetUrl, requestOptions, (response) => {
let data = '';
response.on('data', (chunk) => {
data += chunk;
});
response.on('end', () => {
callback(null, data, response.headers);
});
});
getRequest.on('error', (error) => {
callback(error, null);
});
getRequest.end();
}
function sendHttpsPostRequest(targetUrl, cookies, postData, callback) {
const postRequestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': postData.length,
'Cookie': cookies.join('; '),
},
};
const postRequest = https.request(targetUrl, postRequestOptions, (response) => {
let data = '';
response.on('data', (chunk) => {
data += chunk;
});
response.on('end', () => {
callback(null, data, response.headers);
});
});
postRequest.on('error', (error) => {
callback(error, null, null);
});
postRequest.write(postData);
postRequest.end();
}
// Usage :
const targetUrl = 'https://example.com';
const cookies = ['cookie1=abc', 'cookie2=def'];
const postData = 'key1=value1&key2=value2';
sendHttpsGetRequest(targetUrl, cookies, (error, data, headers) => {
if (error) {
console.log('GET Request Error:', error);
} else {
var redirect = headers['location']
var cookie = headers['set-cookie']
var response_text = data
}
});
sendHttpsPostRequest(targetUrl, cookies, postData, (error, data, headers)=>{
if (error) {
console.log('POST Request Error:', error);
} else {
var redirect = headers['location']
var cookie = headers['set-cookie']
var response_text = data
}
})
Upvotes: 0
Reputation: 882
Well, I want to answer my question in case somebody is having the same problem. I have fixed the cookie problem by registerStandardSchemes. The sample code is as follows and code works for saving cookies from web pages as well:
protocol.registerStandardSchemes(["app"], {
secure: true
});
and on ready event
protocol.registerFileProtocol('app', (request, callback) => {
const urls = request.url.substr(6)
const parsedUrl = url.parse(urls);
// extract URL path
const pathname = `.${parsedUrl.pathname}`;
// based on the URL path, extract the file extention. e.g. .js, .doc, ...
const ext = path.parse(pathname).ext;
callback({
path: path.normalize(`${__dirname}/${parsedUrl.pathname}`)
})
}, (error) => {
if (error) {
console.error('Failed to register protocol');
}
});
Upvotes: 6
Reputation: 447
OK, I got it working with Electron 5. Below are the relevant bits based on @zahid-nisar's solution, and below that a full sample Electron main.js to show how it all fits together. Obviously, change the location of your app in mainWindow.loadURL('app://www/index.html');
.
Relevant code to insert in main.js:
const { protocol } = require('electron');
protocol.registerSchemesAsPrivileged([{
scheme: 'app',
privileges: {
standard: true,
secure: true
}
}]);
Inside app.on('ready')
function:
protocol.registerFileProtocol('app', (request, callback) => {
const url = request.url.substr(6);
callback({
path: path.normalize(`${__dirname}/${url}`)
});
}, (error) => {
if (error) console.error('Failed to register protocol');
});
Then, inside your createWindow function, load your app like this:
mainWindow.loadURL('app://www/index.html');
And finally, here is a complete sample main.js with the above code (plus extras that I need, like Service Worker):
// Modules to control application life and create native browser window
const {
app,
protocol,
BrowserWindow
} = require('electron');
const path = require('path');
// This is used to set capabilities of the app: protocol in onready event below
protocol.registerSchemesAsPrivileged([{
scheme: 'app',
privileges: {
standard: true,
secure: true,
allowServiceWorkers: true,
supportFetchAPI: true
}
}]);
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;
function createWindow() {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600
//, webPreferences: {
// preload: path.join(__dirname, 'preload.js')
// }
});
// and load the index.html of the app.
mainWindow.loadURL('app://www/index.html');
// DEV: Enable code below to check cookies saved by app in console log
// mainWindow.webContents.on('did-finish-load', function() {
// mainWindow.webContents.session.cookies.get({}, (error, cookies) => {
// console.log(cookies);
// });
// });
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null;
});
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', () => {
protocol.registerFileProtocol('app', (request, callback) => {
const url = request.url.substr(6);
callback({
path: path.normalize(`${__dirname}/${url}`)
});
}, (error) => {
if (error) console.error('Failed to register protocol');
});
// Create the new window
createWindow();
});
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') app.quit();
});
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) createWindow();
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
Upvotes: 3
Reputation: 1969
Follow the documentation to get it done, and use the standard.https://electronjs.org/docs/api/cookies
const {session} = require('electron')
// Query all cookies.
session.defaultSession.cookies.get({}, (error, cookies) => {
console.log(error, cookies)
})
// Query all cookies associated with a specific url.
session.defaultSession.cookies.get({url: 'http://www.github.com'}, (error, cookies) => {
console.log(error, cookies)
})
// Set a cookie with the given cookie data;
// may overwrite equivalent cookies if they exist.
const cookie = {url: 'http://www.github.com', name: 'dummy_name', value: 'dummy'}
session.defaultSession.cookies.set(cookie, (error) => {
if (error) console.error(error)
})
Upvotes: 6