Files
Tooloop-Kiosk-Browser/main.js
T

177 lines
4.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const { app, BrowserWindow } = require('electron/main');
const path = require('node:path');
const fs = require('fs');
const os = require('os');
const log = require('electron-log/main');
const { linkExists } = require('link-exists');
const { setInterval } = require('node:timers/promises');
//------------------------------------------------------------------------------
// Properties
//------------------------------------------------------------------------------
let config;
let win;
//------------------------------------------------------------------------------
// Function
//------------------------------------------------------------------------------
/**
* Loads a config file from disc.
* The file is expected to be named `config.json` and is searched for in these
* locations and in this order:
*
* 1. `/assets/presentation/config.json` (Tooloop OS)
* 2. Path of the executable
* - Linux: `app.getPath('exe')`
* - MacOS: `path.resolve(app.getPath('exe'), "../../../../")`
* 3. `__dirname` (Development)
*/
function loadConfig() {
const locations = [
'/assets/presentation',
os.platform() == 'darwin' ?
path.resolve(app.getPath('exe'), "../../../../") : app.getPath('exe'),
__dirname
];
let filePath;
// Check all locations
for (const location of locations) {
// Update the filepath
filePath = path.join(location, 'config.json');
try {
// Try access
fs.accessSync(filePath);
// Parse the file if found
console.info('Found config file at ' + filePath);
const data = fs.readFileSync(filePath, { encoding: 'utf8' });
config = JSON.parse(data);
// Break the loop
break;
} catch (err) {
console.warn('No config file found at ' + filePath);
}
}
}
/**
* Creates the browser window
*/
async function createWindow() {
win = new BrowserWindow({
width: 1920,
height: 1080,
backgroundColor: '#000000',
icon: 'images/icon-512.png',
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
nodeIntegration: true,
webSecurity: false,
},
show: false,
autoHideMenuBar: true
});
win.on("closed", function () {
win = null;
});
win.webContents.addListener("will-navigate", validateDomain);
win.once("ready-to-show", () => {
win.setKiosk(true);
win.show();
});
// load fallback page
win.loadFile('index.html');
// load actual page from config file
if (config != undefined && 'url' in config) {
testAndLoadUrl(config.url);
}
}
/**
* Validates the url of a navigatio event against the list of allowed domains in
* the config file. See https://www.electronjs.org/docs/latest/api/web-contents#event-will-frame-navigate
* @param {Event} event
*/
function validateDomain(event) {
let url = new URL(event.url);
if ('allowedDomains' in config && !config.allowedDomains.includes(url.hostname)) {
event.preventDefault();
log.info("Navigation to " + event.url + " prevented");
}
}
/**
* Tests if the host of the url is reachable.
* Access is tried in a 1 second interval and the url is loaded if successfull.
* @param {string} testurl
*/
function testAndLoadUrl(testurl) {
try {
let url = new URL(testurl);
// Its an online url, test if its reachable
if (['https:', 'http:', 'https', 'http'].includes(url.protocol)) {
(async function () {
for await (const startTime of setInterval(1000)) {
let reachable = linkExists(url.hostname);
if (reachable) {
log.info("Successfull access to " + url.hostname)
log.info("Loading " + config.url)
win.loadURL(config.url);
// break the interval
break;
} else {
log.warn("Could not reach " + url.hostname)
}
}
})();
}
// Load other protocols (i. e. offline) immedately
else {
win.loadURL(config.url);
}
} catch (err) {
log.error(err);
}
}
//------------------------------------------------------------------------------
// Init electon app
//------------------------------------------------------------------------------
app.whenReady().then(() => {
loadConfig();
log.initialize();
if (config != undefined && 'logPath' in config) {
log.transports.file.resolvePathFn = () => config.logPath;
}
createWindow();
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
})
});
app.on('window-all-closed', () => {
app.quit()
});