909 lines
25 KiB
JavaScript
909 lines
25 KiB
JavaScript
// Modules to control application life and create native browser window
|
|
|
|
const {app, BrowserWindow, Tray, nativeImage, Menu, dialog} = require('electron');
|
|
const {ipcMain} = require('electron');
|
|
const Constants = require('../src/constants');
|
|
const path = require('path');
|
|
const url = require('url');
|
|
require('electron-debug/index')();
|
|
const os = require('os');
|
|
const helpers = require('../src/helpers');
|
|
const fs = require('fs');
|
|
const unzip = require('unzipper');
|
|
const AutoLaunch = require('auto-launch');
|
|
|
|
require.extensions['.sh'] = function (module, filename) {
|
|
module.exports = fs.readFileSync(filename, 'utf8');
|
|
};
|
|
const detectScript = require('./detect_linux.sh');
|
|
const installScript = require('./update_linux.sh');
|
|
|
|
// 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 trayContextMenu;
|
|
let mainWindow;
|
|
let mainWindowTray;
|
|
let mountedData = {};
|
|
let mountedLocations = [];
|
|
let expectedUnmount = {};
|
|
let launchHidden = false;
|
|
let firstMountCheck = true;
|
|
let manualMountDetection = {};
|
|
|
|
let isQuiting = false;
|
|
|
|
app.on('before-quit', function () {
|
|
isQuiting = true;
|
|
});
|
|
|
|
function closeApplication() {
|
|
app.quit();
|
|
}
|
|
|
|
function setWindowVisibility(show) {
|
|
if (show) {
|
|
mainWindow.show();
|
|
if (os.platform() === 'darwin') {
|
|
app.dock.show();
|
|
}
|
|
|
|
if (mainWindow.isMinimized()) {
|
|
mainWindow.restore();
|
|
}
|
|
mainWindow.focus();
|
|
} else {
|
|
mainWindow.hide();
|
|
if (os.platform() === 'darwin') {
|
|
app.dock.hide();
|
|
}
|
|
}
|
|
|
|
if (trayContextMenu && mainWindowTray) {
|
|
trayContextMenu.items[0].checked = show;
|
|
mainWindowTray.setContextMenu(trayContextMenu)
|
|
}
|
|
}
|
|
|
|
function createWindow() {
|
|
loadUiSettings();
|
|
|
|
let extra = {};
|
|
if (os.platform() === 'linux') {
|
|
extra = {
|
|
icon: path.join(__dirname, '../', 'icon.png'),
|
|
}
|
|
}
|
|
|
|
// Create the browser window.
|
|
const height = (process.env.ELECTRON_START_URL || (os.platform() === 'darwin') ? 364 : 344) - ((os.platform() === 'win32') ? 0 : 20);
|
|
mainWindow = new BrowserWindow({
|
|
width: 428 + ((os.platform() === 'win32') ? 0 : (os.platform() === 'darwin') ? 150 : 160),
|
|
height: height,
|
|
fullscreen: false,
|
|
resizable: false,
|
|
show: !launchHidden,
|
|
title: 'Repertory UI',
|
|
...extra,
|
|
webPreferences: {
|
|
webSecurity: !process.env.ELECTRON_START_URL
|
|
}
|
|
});
|
|
|
|
if ((os.platform() === 'darwin') && launchHidden) {
|
|
app.dock.hide();
|
|
}
|
|
|
|
// and load the index.html of the app.
|
|
const startUrl = process.env.ELECTRON_START_URL || url.format({
|
|
pathname: path.join(__dirname, '../build/index.html'),
|
|
protocol: 'file:',
|
|
slashes: true
|
|
});
|
|
|
|
mainWindow.on('close', function (event) {
|
|
if (!isQuiting) {
|
|
event.preventDefault();
|
|
if (mainWindow.isVisible()) {
|
|
setWindowVisibility(false);
|
|
}
|
|
event.returnValue = false;
|
|
}
|
|
});
|
|
|
|
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;
|
|
|
|
// Unmount all items
|
|
for (const i in mountedLocations) {
|
|
const data = mountedData[mountedLocations[i]];
|
|
helpers.stopMountProcessSync(data.DataDirectory, data.Version, data.StorageType);
|
|
}
|
|
|
|
mountedLocations = [];
|
|
mountedData = {};
|
|
});
|
|
|
|
const appPath = (os.platform() === 'win32') ? path.resolve(path.join(app.getAppPath(), '..\\..\\repertory-ui.exe')) :
|
|
(os.platform() === 'darwin') ? path.resolve(path.join(path.dirname(app.getAppPath()), '../MacOS/repertory-ui')) :
|
|
process.env.APPIMAGE;
|
|
|
|
const autoLauncher = new AutoLaunch({
|
|
name: 'Repertory UI',
|
|
path: appPath,
|
|
});
|
|
|
|
trayContextMenu = Menu.buildFromTemplate([
|
|
{
|
|
label: 'Visible', type: 'checkbox', click(item) {
|
|
setWindowVisibility(item.checked);
|
|
},
|
|
checked: !launchHidden,
|
|
},
|
|
{
|
|
label: 'Auto-start', type: 'checkbox', click(item) {
|
|
if (item.checked) {
|
|
autoLauncher.enable();
|
|
} else {
|
|
autoLauncher.disable();
|
|
}
|
|
}
|
|
},
|
|
{
|
|
type: 'separator'
|
|
},
|
|
{
|
|
label: 'Launch Hidden', type: 'checkbox', click(item) {
|
|
launchHidden = !!item.checked;
|
|
saveUiSettings();
|
|
},
|
|
checked: launchHidden,
|
|
},
|
|
{
|
|
type: 'separator'
|
|
},
|
|
{
|
|
label: 'Exit and Unmount', click() {
|
|
closeApplication();
|
|
}
|
|
}
|
|
]);
|
|
|
|
const image = nativeImage.createFromPath(path.join(__dirname, (os.platform() === 'darwin') ? '../build/logo_mac.png' : '../build/logo.png'));
|
|
mainWindowTray = new Tray(image);
|
|
|
|
autoLauncher
|
|
.isEnabled()
|
|
.then((enabled) => {
|
|
trayContextMenu.items[1].checked = enabled;
|
|
mainWindowTray.setToolTip('Repertory UI');
|
|
mainWindowTray.setContextMenu(trayContextMenu)
|
|
})
|
|
.catch(() => {
|
|
closeApplication();
|
|
});
|
|
|
|
mainWindow.loadURL(startUrl);
|
|
}
|
|
|
|
const instanceLock = app.requestSingleInstanceLock();
|
|
if (!instanceLock) {
|
|
closeApplication();
|
|
} else {
|
|
app.on('second-instance', () => {
|
|
if (mainWindow) {
|
|
setWindowVisibility(true);
|
|
}
|
|
});
|
|
|
|
app.on('ready', createWindow);
|
|
|
|
app.on('window-all-closed', () => {
|
|
closeApplication();
|
|
});
|
|
}
|
|
|
|
const clearManualMountDetection = (storageType) => {
|
|
if (manualMountDetection[storageType]) {
|
|
clearInterval(manualMountDetection[storageType]);
|
|
delete manualMountDetection[storageType];
|
|
}
|
|
};
|
|
|
|
const loadUiSettings = () => {
|
|
const settingFile = path.join(helpers.resolvePath(Constants.DATA_LOCATIONS[os.platform()]), 'ui.json');
|
|
try {
|
|
if (fs.statSync(settingFile).isFile()) {
|
|
const settings = JSON.parse(fs.readFileSync(settingFile, 'utf8'));
|
|
launchHidden = settings.launch_hidden;
|
|
}
|
|
} catch (e) {
|
|
}
|
|
};
|
|
|
|
const monitorMount = (sender, storageType, dataDirectory, version, pid, location) => {
|
|
manualMountDetection[storageType] = setInterval(() => {
|
|
helpers
|
|
.detectRepertoryMounts(dataDirectory, version)
|
|
.then(result => {
|
|
if (result[storageType].PID !== pid) {
|
|
if (result[storageType].PID === -1) {
|
|
clearManualMountDetection(storageType);
|
|
sender.send(Constants.IPC_Unmount_Drive_Reply, {
|
|
data: {
|
|
Expected: expectedUnmount[storageType],
|
|
Location: location,
|
|
StorageType: storageType,
|
|
Error: Error(storageType + ' Unmounted').toString(),
|
|
Success: false,
|
|
}
|
|
});
|
|
} else {
|
|
pid = result[storageType].PID;
|
|
}
|
|
}
|
|
})
|
|
.catch(e => {
|
|
console.log(e);
|
|
});
|
|
},6000);
|
|
};
|
|
|
|
const saveUiSettings = () => {
|
|
const settingFile = path.join(helpers.resolvePath(Constants.DATA_LOCATIONS[os.platform()]), 'ui.json');
|
|
try {
|
|
fs.writeFileSync(settingFile, JSON.stringify({
|
|
launch_hidden: launchHidden,
|
|
}), 'utf-8');
|
|
} catch (e) {
|
|
}
|
|
};
|
|
|
|
const standardIPCReply = (event, channel, data, error) => {
|
|
if (mainWindow) {
|
|
event.sender.send(channel, {
|
|
data: {
|
|
...data,
|
|
Error: error instanceof Error ? error.toString() : error,
|
|
Success: !error,
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
ipcMain.on(Constants.IPC_Browse_Directory + '_sync', (event, data) => {
|
|
dialog.showOpenDialog(mainWindow, {
|
|
defaultPath: data.Location,
|
|
properties: ['openDirectory'],
|
|
title: data.Title,
|
|
}, (filePaths) => {
|
|
if (filePaths && (filePaths.length > 0)) {
|
|
event.returnValue = filePaths[0];
|
|
} else {
|
|
event.returnValue = '';
|
|
}
|
|
});
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Check_Daemon_Version, (event, data) => {
|
|
const dataDirectory = helpers.resolvePath(data.Directory);
|
|
helpers
|
|
.checkDaemonVersion(dataDirectory, data.Version, data.StorageType)
|
|
.then(code => {
|
|
standardIPCReply(event, Constants.IPC_Check_Daemon_Version_Reply, {
|
|
Valid: (code === 0),
|
|
});
|
|
})
|
|
.catch(e=> {
|
|
standardIPCReply(event, Constants.IPC_Check_Daemon_Version_Reply, {
|
|
Valid: false,
|
|
}, e);
|
|
});
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Check_Daemon_Version + '_sync', (event, data) => {
|
|
const dataDirectory = helpers.resolvePath(data.Directory);
|
|
helpers
|
|
.checkDaemonVersion(dataDirectory, data.Version, data.StorageType)
|
|
.then(code => {
|
|
event.returnValue = {
|
|
data: {
|
|
Success: true,
|
|
Valid: (code === 0),
|
|
},
|
|
};
|
|
})
|
|
.catch(e => {
|
|
event.returnValue = {
|
|
data: {
|
|
Error: e.toString(),
|
|
Success: false,
|
|
Valid: false
|
|
},
|
|
};
|
|
});
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Check_Dependency_Installed, (event, data) => {
|
|
try {
|
|
const exists = fs.lstatSync(data.File).isFile();
|
|
standardIPCReply(event, Constants.IPC_Check_Dependency_Installed_Reply, {
|
|
data: {
|
|
Exists: exists,
|
|
},
|
|
});
|
|
} catch (e) {
|
|
standardIPCReply(event, Constants.IPC_Check_Dependency_Installed_Reply, {
|
|
data : {
|
|
Exists: false,
|
|
},
|
|
});
|
|
}
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Check_Dependency_Installed + '_sync', (event, data) => {
|
|
try {
|
|
const ls = fs.lstatSync(data.File);
|
|
event.returnValue = {
|
|
data: {
|
|
Exists: ls.isFile() || ls.isSymbolicLink(),
|
|
},
|
|
};
|
|
} catch (e) {
|
|
event.returnValue = {
|
|
data: {
|
|
Exists: false
|
|
},
|
|
};
|
|
}
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Check_Installed, (event, data) => {
|
|
const dataDirectory = helpers.resolvePath(data.Directory);
|
|
const destination = path.join(dataDirectory, data.Version);
|
|
helpers
|
|
.getMissingDependencies(data.Dependencies)
|
|
.then((dependencies) => {
|
|
let exists = false;
|
|
try {
|
|
exists = fs.existsSync(destination) && fs.lstatSync(destination).isDirectory();
|
|
} catch (e) {
|
|
}
|
|
standardIPCReply(event, Constants.IPC_Check_Installed_Reply, {
|
|
Dependencies: dependencies,
|
|
Exists: exists,
|
|
Version: data.Version,
|
|
});
|
|
}).catch(error => {
|
|
standardIPCReply(event, Constants.IPC_Check_Installed_Reply, {
|
|
Dependencies: [],
|
|
Version: data.Version,
|
|
}, error);
|
|
});
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Check_Mount_Location + '_sync', (event, data) => {
|
|
let response = {
|
|
Success: true,
|
|
Error: ''
|
|
};
|
|
|
|
try {
|
|
if (fs.existsSync(data.Location) && fs.statSync(data.Location).isDirectory()) {
|
|
if (fs.readdirSync(data.Location).length !== 0) {
|
|
response.Success = false;
|
|
response.Error = 'Directory not empty: ' + data.Location;
|
|
}
|
|
} else {
|
|
response.Success = false;
|
|
response.Error = 'Directory not found: ' + data.Location;
|
|
}
|
|
} catch (e) {
|
|
response.Success = false;
|
|
response.Error = e.toString();
|
|
}
|
|
event.returnValue = response;
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Delete_File, (event, data) => {
|
|
try {
|
|
if (fs.existsSync(data.FilePath)) {
|
|
fs.unlinkSync(data.FilePath);
|
|
}
|
|
} catch (e) {
|
|
}
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Delete_File + '_sync', (event, data) => {
|
|
try {
|
|
if (fs.existsSync(data.FilePath)) {
|
|
fs.unlinkSync(data.FilePath);
|
|
}
|
|
event.returnValue = {
|
|
data: true,
|
|
};
|
|
} catch (e) {
|
|
event.returnValue = {
|
|
data: false,
|
|
};
|
|
}
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Detect_Mounts, (event, data) => {
|
|
let driveLetters = {};
|
|
for (const provider of Constants.PROVIDER_LIST) {
|
|
driveLetters[provider] = [];
|
|
}
|
|
|
|
const grabDriveLetters = (locations) => {
|
|
for (let i = 'c'.charCodeAt(0); i <= 'z'.charCodeAt(0); i++) {
|
|
const drive = (String.fromCharCode(i) + ':').toUpperCase();
|
|
let driveInUse;
|
|
if (Object.keys(locations).length > 0) {
|
|
for (const provider of Constants.PROVIDER_LIST) {
|
|
driveInUse = locations[provider].startsWith(drive);
|
|
if (driveInUse)
|
|
break;
|
|
}
|
|
}
|
|
if (!driveInUse) {
|
|
try {
|
|
if (!fs.existsSync(drive)) {
|
|
for (const provider of Constants.PROVIDER_LIST) {
|
|
driveLetters[provider].push(drive);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Object.keys(locations).length > 0) {
|
|
for (const provider of Constants.PROVIDER_LIST) {
|
|
if (locations[provider].length > 0) {
|
|
if (!driveLetters[provider].find((driveLetter) => {
|
|
return driveLetter === locations[provider];
|
|
})) {
|
|
driveLetters[provider].push(locations[provider]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
const setImage = (locations) => {
|
|
let driveInUse;
|
|
if (Object.keys(locations).length > 0) {
|
|
for (const provider of Constants.PROVIDER_LIST) {
|
|
driveInUse = locations[provider].length > 0;
|
|
if (driveInUse)
|
|
break;
|
|
}
|
|
}
|
|
|
|
let image;
|
|
if (driveInUse) {
|
|
image = nativeImage.createFromPath(path.join(__dirname, os.platform() === 'darwin' ? '../build/logo_both_mac.png' : '../build/logo_both.png'));
|
|
} else {
|
|
image = nativeImage.createFromPath(path.join(__dirname, os.platform() === 'darwin' ? '../build/logo_mac.png' : '../build/logo.png'));
|
|
}
|
|
|
|
mainWindowTray.setImage(image);
|
|
};
|
|
|
|
const dataDirectory = helpers.resolvePath(data.Directory);
|
|
helpers
|
|
.detectRepertoryMounts(dataDirectory, data.Version)
|
|
.then((results) => {
|
|
let storageData = {};
|
|
let locations = {};
|
|
for (const provider of Constants.PROVIDER_LIST) {
|
|
storageData[provider] = results[provider] ? results[provider] : {
|
|
Active: false,
|
|
Location: '',
|
|
PID: -1,
|
|
};
|
|
locations[provider] = storageData[provider].Location;
|
|
|
|
if (storageData[provider].PID !== -1) {
|
|
expectedUnmount[provider] = false;
|
|
if (firstMountCheck) {
|
|
monitorMount(event.sender, provider, dataDirectory, data.Version, storageData[provider].PID, storageData[provider].Location);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (os.platform() === 'win32') {
|
|
grabDriveLetters(locations);
|
|
}
|
|
|
|
setImage(locations);
|
|
if (firstMountCheck) {
|
|
firstMountCheck = false;
|
|
}
|
|
standardIPCReply(event, Constants.IPC_Detect_Mounts_Reply, {
|
|
DriveLetters: driveLetters,
|
|
Locations: locations,
|
|
});
|
|
})
|
|
.catch(error => {
|
|
if (os.platform() === 'win32') {
|
|
grabDriveLetters({});
|
|
}
|
|
setImage({});
|
|
standardIPCReply(event, Constants.IPC_Detect_Mounts_Reply, {
|
|
DriveLetters: driveLetters,
|
|
}, error);
|
|
});
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Download_File, (event, data) => {
|
|
const dataDirectory = helpers.resolvePath(data.Directory);
|
|
const destination = path.join(dataDirectory, data.Filename);
|
|
helpers.downloadFile(data.URL, destination, (progress) => {
|
|
standardIPCReply(event, Constants.IPC_Download_File_Progress, {
|
|
Destination: destination,
|
|
Progress: progress,
|
|
URL: data.URL,
|
|
});
|
|
}, error => {
|
|
standardIPCReply(event, Constants.IPC_Download_File_Complete, {
|
|
Destination: destination,
|
|
URL: data.URL,
|
|
}, error);
|
|
});
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Extract_Release, (event, data) => {
|
|
const dataDirectory = helpers.resolvePath(data.Directory);
|
|
const destination = path.join(dataDirectory, data.Version);
|
|
helpers.mkDirByPathSync(destination);
|
|
|
|
const stream = fs.createReadStream(data.Source);
|
|
stream
|
|
.pipe(unzip.Extract({ path: destination }))
|
|
.on('error', error => {
|
|
try {
|
|
helpers.removeDirectoryRecursively(destination);
|
|
} catch (e) {
|
|
}
|
|
stream.close();
|
|
standardIPCReply(event, Constants.IPC_Extract_Release_Complete, {
|
|
Source: data.Source,
|
|
}, error);
|
|
})
|
|
.on('finish', () => {
|
|
stream.close();
|
|
if (os.platform() !== 'win32') {
|
|
helpers
|
|
.executeAndWait("chmod +x \"" + path.join(destination, 'repertory') + "\"")
|
|
.then(() => {
|
|
standardIPCReply(event, Constants.IPC_Extract_Release_Complete, {
|
|
Source: data.Source,
|
|
});
|
|
})
|
|
.catch(error => {
|
|
standardIPCReply(event, Constants.IPC_Extract_Release_Complete, {
|
|
Source: data.Source,
|
|
}, error);
|
|
})
|
|
} else {
|
|
standardIPCReply(event, Constants.IPC_Extract_Release_Complete, {
|
|
Source: data.Source,
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Get_Config, (event, data) => {
|
|
const dataDirectory = helpers.resolvePath(data.Directory);
|
|
helpers
|
|
.getConfig(dataDirectory, data.Version, data.StorageType)
|
|
.then((data) => {
|
|
if (data.Code === 0) {
|
|
standardIPCReply(event, Constants.IPC_Get_Config_Reply, {
|
|
Config: data.Data,
|
|
});
|
|
} else {
|
|
standardIPCReply(event, Constants.IPC_Get_Config_Reply, {}, data.Code);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
standardIPCReply(event, Constants.IPC_Get_Config_Reply, {}, error);
|
|
});
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Get_Config_Template, (event, data) => {
|
|
const dataDirectory = helpers.resolvePath(data.Directory);
|
|
helpers
|
|
.getConfigTemplate(dataDirectory, data.Version, data.StorageType)
|
|
.then((data) => {
|
|
standardIPCReply(event, Constants.IPC_Get_Config_Template_Reply, {
|
|
Template: data,
|
|
});
|
|
})
|
|
.catch(error => {
|
|
standardIPCReply(event, Constants.IPC_Get_Config_Template_Reply, {}, error);
|
|
});
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Get_Platform, (event) => {
|
|
let platform = os.platform();
|
|
if (platform === 'linux') {
|
|
const scriptFile = path.join(os.tmpdir(), 'repertory_detect_linux.sh');
|
|
fs.writeFileSync(scriptFile, detectScript);
|
|
helpers
|
|
.executeScript(scriptFile)
|
|
.then(data => {
|
|
platform = data.replace(/(\r\n|\n|\r)/gm,"");
|
|
event.sender.send(Constants.IPC_Get_Platform_Reply, {
|
|
OSPlatform: os.platform(),
|
|
Platform: platform,
|
|
});
|
|
})
|
|
.catch(() => {
|
|
event.sender.send(Constants.IPC_Get_Platform_Reply, {
|
|
OSPlatform: os.platform(),
|
|
Platform: platform,
|
|
});
|
|
});
|
|
} else {
|
|
event.sender.send(Constants.IPC_Get_Platform_Reply, {
|
|
OSPlatform: os.platform(),
|
|
Platform: platform,
|
|
});
|
|
}
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Get_State, (event, data) => {
|
|
const dataDirectory = helpers.resolvePath(data);
|
|
helpers.mkDirByPathSync(dataDirectory);
|
|
const configFile = path.join(dataDirectory, 'settings.json');
|
|
if (fs.existsSync(configFile)) {
|
|
event.sender.send(Constants.IPC_Get_State_Reply, {
|
|
data: JSON.parse(fs.readFileSync(configFile, 'utf8')),
|
|
});
|
|
} else {
|
|
event.sender.send(Constants.IPC_Get_State_Reply, {
|
|
data: null,
|
|
});
|
|
}
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Grab_Releases, (event) => {
|
|
standardIPCReply(event, Constants.IPC_Grab_Releases_Reply);
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Grab_UI_Releases, (event) => {
|
|
standardIPCReply(event, Constants.IPC_Grab_UI_Releases_Reply);
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Install_Dependency, (event, data) => {
|
|
if (data.Source.toLowerCase().endsWith('.dmg')) {
|
|
helpers
|
|
.executeAsync('open', ['-a', 'Finder', '-W', data.Source])
|
|
.then(() => {
|
|
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
|
Source: data.Source,
|
|
URL: data.URL,
|
|
});
|
|
})
|
|
.catch(error=> {
|
|
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
|
Source: data.Source,
|
|
URL: data.URL,
|
|
}, error);
|
|
});
|
|
} else {
|
|
helpers
|
|
.executeAndWait(data.Source)
|
|
.then(() => {
|
|
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
|
Source: data.Source,
|
|
URL: data.URL,
|
|
});
|
|
})
|
|
.catch(error => {
|
|
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
|
Source: data.Source,
|
|
URL: data.URL,
|
|
}, error);
|
|
});
|
|
}
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Install_Upgrade, (event, data) => {
|
|
let allowSkipVerification = false;
|
|
|
|
let tempSig;
|
|
let tempPub;
|
|
const cleanupFiles = () => {
|
|
try {
|
|
if (tempSig) {
|
|
fs.unlinkSync(tempSig);
|
|
}
|
|
if (tempPub) {
|
|
fs.unlinkSync(tempPub);
|
|
}
|
|
} catch (e) {
|
|
}
|
|
};
|
|
|
|
const errorHandler = err => {
|
|
cleanupFiles();
|
|
standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, {
|
|
AllowSkipVerification: allowSkipVerification,
|
|
Source: data.Source,
|
|
}, err);
|
|
};
|
|
|
|
const hasSignature = !data.SkipVerification && data.Signature && (data.Signature.length > 0);
|
|
const hasHash = !data.SkipVerification && data.Sha256 && (data.Sha256.length > 0);
|
|
if (hasSignature) {
|
|
try {
|
|
const files = helpers.createSignatureFiles(data.Signature, Constants.DEV_PUBLIC_KEY);
|
|
tempPub = files.PublicKeyFile;
|
|
tempSig = files.SignatureFile;
|
|
} catch (e) {
|
|
errorHandler(e);
|
|
return;
|
|
}
|
|
}
|
|
|
|
let command;
|
|
let args;
|
|
const platform = os.platform();
|
|
if (platform === 'win32') {
|
|
command = data.Source;
|
|
} else if (platform === 'darwin') {
|
|
command = 'open';
|
|
args = ['-a', 'Finder', data.Source];
|
|
} else if (platform === 'linux') {
|
|
try {
|
|
const execPath = path.join(os.tmpdir(), 'install_linux.sh');
|
|
fs.writeFileSync(execPath, installScript);
|
|
fs.chmodSync(execPath, '750');
|
|
command = execPath;
|
|
args = [data.Source];
|
|
} catch (e) {
|
|
errorHandler(e);
|
|
}
|
|
} else {
|
|
errorHandler(Error('Platform not supported: ' + os.platform()));
|
|
}
|
|
|
|
if (command) {
|
|
const executeInstall = () => {
|
|
helpers
|
|
.executeAsync(command, args)
|
|
.then(() => {
|
|
cleanupFiles();
|
|
closeApplication();
|
|
})
|
|
.catch(error => {
|
|
errorHandler(error);
|
|
});
|
|
};
|
|
|
|
if (hasSignature) {
|
|
helpers
|
|
.verifySignature(data.Source, tempSig, tempPub)
|
|
.then(() => {
|
|
executeInstall();
|
|
})
|
|
.catch(() => {
|
|
errorHandler(Error('Failed to verify installation package signature'));
|
|
});
|
|
} else if (hasHash) {
|
|
helpers
|
|
.verifyHash(data.Source, data.Sha256)
|
|
.then(()=> {
|
|
executeInstall();
|
|
})
|
|
.catch(() => {
|
|
errorHandler(Error('Failed to verify installation package hash'));
|
|
});
|
|
} else {
|
|
executeInstall();
|
|
}
|
|
} else {
|
|
errorHandler(Error('Unsupported upgrade: ' + data.Source));
|
|
}
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Mount_Drive, (event, data) => {
|
|
expectedUnmount[data.StorageType] = false;
|
|
const dataDirectory = helpers.resolvePath(data.Directory);
|
|
|
|
if (mountedLocations.indexOf(data.Location) !== -1) {
|
|
console.log(data.StorageType + ' already mounted: ' + data.Location);
|
|
} else {
|
|
mountedLocations.push(data.Location);
|
|
mountedData[data.Location] = {
|
|
DataDirectory: dataDirectory,
|
|
Version: data.Version,
|
|
StorageType: data.StorageType,
|
|
};
|
|
const errorHandler = (pid, error) => {
|
|
if (mountedLocations.indexOf(data.Location) !== -1) {
|
|
mountedLocations.splice(mountedLocations.indexOf(data.Location), 1);
|
|
delete mountedData[data.Location];
|
|
}
|
|
|
|
standardIPCReply(event, Constants.IPC_Unmount_Drive_Reply, {
|
|
Expected: expectedUnmount[data.StorageType],
|
|
Location: data.Location,
|
|
StorageType: data.StorageType,
|
|
}, error || Error(data.StorageType + ' Unmounted'));
|
|
};
|
|
helpers
|
|
.executeMount(dataDirectory, data.Version, data.StorageType, data.Location, data.NoConsoleSupported, (error, pid) => {
|
|
errorHandler(pid, error);
|
|
})
|
|
.then(() => {
|
|
standardIPCReply(event, Constants.IPC_Mount_Drive_Reply, {
|
|
StorageType: data.StorageType,
|
|
});
|
|
})
|
|
.catch(error => {
|
|
errorHandler(-1, error);
|
|
});
|
|
}
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Save_State, (event, data) => {
|
|
const dataDirectory = helpers.resolvePath(data.Directory);
|
|
helpers.mkDirByPathSync(dataDirectory);
|
|
const configFile = path.join(dataDirectory, 'settings.json');
|
|
fs.writeFileSync(configFile, JSON.stringify(data.State), 'utf8');
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Set_Config_Values, (event, data) => {
|
|
const dataDirectory = helpers.resolvePath(data.Directory);
|
|
const setConfigValue = (i) => {
|
|
if (i < data.Items.length) {
|
|
helpers
|
|
.setConfigValue(data.Items[i].Name, data.Items[i].Value, dataDirectory, data.StorageType, data.Version)
|
|
.then(() => {
|
|
setConfigValue(++i);
|
|
})
|
|
.catch(() => {
|
|
setConfigValue(++i);
|
|
});
|
|
} else {
|
|
standardIPCReply(event, Constants.IPC_Set_Config_Values_Reply, {});
|
|
}
|
|
};
|
|
setConfigValue(0);
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Shutdown, () => {
|
|
closeApplication();
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Show_Window, () => {
|
|
setWindowVisibility(true);
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Show_Window + '_sync', event => {
|
|
setWindowVisibility(true);
|
|
event.returnValue = true;
|
|
});
|
|
|
|
ipcMain.on(Constants.IPC_Unmount_Drive, (event, data) => {
|
|
clearManualMountDetection(data.StorageType);
|
|
|
|
const dataDirectory = helpers.resolvePath(data.Directory);
|
|
expectedUnmount[data.StorageType] = true;
|
|
helpers
|
|
.stopMountProcess(dataDirectory, data.Version, data.StorageType)
|
|
.then((result)=> {
|
|
console.log(result);
|
|
})
|
|
.catch((e) => {
|
|
console.log(e);
|
|
});
|
|
});
|