mirror of
https://github.com/finos/SymphonyElectron.git
synced 2025-02-25 18:55:29 -06:00
Electron-401 (fixes crash reporter) (#334)
- fix crash reporter - fix typo - Add support to generate crash report - Add logic to store globally and return - PR review fixes - Add logic to validate file mime type
This commit is contained in:
parent
2de86c8003
commit
3be2986c7e
@ -7,6 +7,7 @@ const fs = require('fs');
|
||||
const log = require('../log.js');
|
||||
const logLevels = require('../enums/logLevels.js');
|
||||
const buildNumber = require('../../package.json').buildNumber;
|
||||
const { initCrashReporterMain, initCrashReporterRenderer } = require('../crashReporter.js');
|
||||
|
||||
let aboutWindow;
|
||||
|
||||
@ -80,9 +81,27 @@ function openAboutWindow(windowName) {
|
||||
});
|
||||
|
||||
aboutWindow.webContents.on('did-finish-load', () => {
|
||||
// initialize crash reporter
|
||||
initCrashReporterMain({ process: 'about app window' });
|
||||
initCrashReporterRenderer(aboutWindow, { process: 'render | about app window' });
|
||||
aboutWindow.webContents.send('buildNumber', buildNumber || '0');
|
||||
});
|
||||
|
||||
aboutWindow.webContents.on('crashed', function () {
|
||||
const options = {
|
||||
type: 'error',
|
||||
title: 'Renderer Process Crashed',
|
||||
message: 'Oops! Looks like we have had a crash.',
|
||||
buttons: ['Close']
|
||||
};
|
||||
|
||||
electron.dialog.showMessageBox(options, function () {
|
||||
if (aboutWindow && !aboutWindow.isDestroyed()) {
|
||||
aboutWindow.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
aboutWindow.on('close', () => {
|
||||
destroyWindow();
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
const { remote, ipcRenderer } = require('electron');
|
||||
const { remote, ipcRenderer, crashReporter } = require('electron');
|
||||
|
||||
renderDom();
|
||||
|
||||
@ -24,4 +24,10 @@ ipcRenderer.on('buildNumber', (event, buildNumber) => {
|
||||
if (versionText) {
|
||||
versionText.innerHTML = version ? `Version ${version} (${version}.${buildNumber})` : 'N/A';
|
||||
}
|
||||
});
|
||||
|
||||
ipcRenderer.on('register-crash-reporter', (event, arg) => {
|
||||
if (arg && typeof arg === 'object') {
|
||||
crashReporter.start(arg);
|
||||
}
|
||||
});
|
@ -8,6 +8,7 @@ const fs = require('fs');
|
||||
const log = require('../log.js');
|
||||
const logLevels = require('../enums/logLevels.js');
|
||||
const { isMac } = require('../utils/misc');
|
||||
const { initCrashReporterMain, initCrashReporterRenderer } = require('../crashReporter.js');
|
||||
|
||||
let basicAuthWindow;
|
||||
|
||||
@ -95,10 +96,26 @@ function openBasicAuthWindow(windowName, hostname, isValidCredentials, clearSett
|
||||
});
|
||||
|
||||
basicAuthWindow.webContents.on('did-finish-load', () => {
|
||||
// initialize crash reporter
|
||||
initCrashReporterMain({ process: 'basic auth window' });
|
||||
initCrashReporterRenderer(basicAuthWindow, { process: 'render | basic auth window' });
|
||||
basicAuthWindow.webContents.send('hostname', hostname);
|
||||
basicAuthWindow.webContents.send('isValidCredentials', isValidCredentials);
|
||||
});
|
||||
|
||||
basicAuthWindow.webContents.on('crashed', function () {
|
||||
const options = {
|
||||
type: 'error',
|
||||
title: 'Renderer Process Crashed',
|
||||
message: 'Oops! Looks like we have had a crash.',
|
||||
buttons: ['Close']
|
||||
};
|
||||
|
||||
electron.dialog.showMessageBox(options, function () {
|
||||
closeAuthWindow(true);
|
||||
});
|
||||
});
|
||||
|
||||
basicAuthWindow.on('close', () => {
|
||||
destroyWindow();
|
||||
});
|
||||
|
@ -1,6 +1,5 @@
|
||||
'use strict';
|
||||
const electron = require('electron');
|
||||
const ipc = electron.ipcRenderer;
|
||||
const { ipcRenderer, crashReporter } = require('electron');
|
||||
|
||||
renderDom();
|
||||
|
||||
@ -26,7 +25,7 @@ function loadContent() {
|
||||
|
||||
if (cancel) {
|
||||
cancel.addEventListener('click', () => {
|
||||
ipc.send('close-basic-auth');
|
||||
ipcRenderer.send('close-basic-auth');
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -39,14 +38,14 @@ function submitForm() {
|
||||
let password = document.getElementById('password').value;
|
||||
|
||||
if (username && password) {
|
||||
ipc.send('login', { username, password });
|
||||
ipcRenderer.send('login', { username, password });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the hosts name
|
||||
*/
|
||||
ipc.on('hostname', (event, host) => {
|
||||
ipcRenderer.on('hostname', (event, host) => {
|
||||
let hostname = document.getElementById('hostname');
|
||||
|
||||
if (hostname){
|
||||
@ -57,10 +56,16 @@ ipc.on('hostname', (event, host) => {
|
||||
/**
|
||||
* Triggered if user credentials are invalid
|
||||
*/
|
||||
ipc.on('isValidCredentials', (event, isValidCredentials) => {
|
||||
ipcRenderer.on('isValidCredentials', (event, isValidCredentials) => {
|
||||
let credentialsError = document.getElementById('credentialsError');
|
||||
|
||||
if (credentialsError){
|
||||
credentialsError.style.display = isValidCredentials ? 'none' : 'block'
|
||||
}
|
||||
});
|
||||
|
||||
ipcRenderer.on('register-crash-reporter', (event, arg) => {
|
||||
if (arg && typeof arg === 'object') {
|
||||
crashReporter.start(arg);
|
||||
}
|
||||
});
|
85
js/crashReporter.js
Normal file
85
js/crashReporter.js
Normal file
@ -0,0 +1,85 @@
|
||||
const { crashReporter } = require('electron');
|
||||
const { getMultipleConfigField } = require('./config.js');
|
||||
|
||||
const log = require('./log.js');
|
||||
const logLevels = require('./enums/logLevels.js');
|
||||
|
||||
const configFields = ['url', 'crashReporter'];
|
||||
let crashReporterData;
|
||||
|
||||
/**
|
||||
* Method that returns all the required field for crash reporter
|
||||
*
|
||||
* @param extras {object}
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
function getCrashReporterConfig(extras) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
if (crashReporterData && crashReporterData.companyName) {
|
||||
crashReporterData.extra = Object.assign(crashReporterData.extra, extras);
|
||||
resolve(crashReporterData);
|
||||
return;
|
||||
}
|
||||
|
||||
getMultipleConfigField(configFields)
|
||||
.then((data) => {
|
||||
|
||||
if (!data && !data.crashReporter && !data.crashReporter.companyName) {
|
||||
reject('Company name cannot be empty');
|
||||
return;
|
||||
}
|
||||
|
||||
crashReporterData = {
|
||||
companyName: data.crashReporter.companyName,
|
||||
submitURL: data.crashReporter.submitURL,
|
||||
uploadToServer: data.crashReporter.uploadToServer,
|
||||
extra: Object.assign(
|
||||
{podUrl: data.url},
|
||||
extras
|
||||
)
|
||||
};
|
||||
resolve(crashReporterData);
|
||||
})
|
||||
.catch((err) => log.send(
|
||||
logLevels.ERROR,
|
||||
'Unable to initialize crash reporter failed to read config file. Error is -> ' + err
|
||||
));
|
||||
})
|
||||
}
|
||||
|
||||
function initCrashReporterMain(extras) {
|
||||
getCrashReporterConfig(extras).then((mainCrashReporterData) => {
|
||||
try {
|
||||
crashReporter.start(mainCrashReporterData);
|
||||
} catch (err) {
|
||||
log.send(logLevels.ERROR, 'Failed to start crash reporter main process. Error is -> ' + err);
|
||||
}
|
||||
}).catch((err) => log.send(
|
||||
logLevels.ERROR,
|
||||
'Unable to initialize crash reporter for main process. Error is -> ' + err
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method to initialize crash reporter for renderer process
|
||||
*
|
||||
* @param browserWindow {Electron.BrowserWindow}
|
||||
* @param extras {Object}
|
||||
*/
|
||||
function initCrashReporterRenderer(browserWindow, extras) {
|
||||
if (browserWindow && browserWindow.webContents && !browserWindow.isDestroyed()) {
|
||||
getCrashReporterConfig(extras).then((rendererCrashReporterData) => {
|
||||
browserWindow.webContents.send('register-crash-reporter', rendererCrashReporterData);
|
||||
}).catch((err) => log.send(
|
||||
logLevels.ERROR,
|
||||
'Unable to initialize crash reporter for renderer process. Error is -> ' + err
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
initCrashReporterMain,
|
||||
initCrashReporterRenderer,
|
||||
};
|
@ -8,6 +8,7 @@ const fs = require('fs');
|
||||
const log = require('../log.js');
|
||||
const logLevels = require('../enums/logLevels.js');
|
||||
const { isMac, isWindowsOS } = require('./../utils/misc.js');
|
||||
const { initCrashReporterMain, initCrashReporterRenderer } = require('../crashReporter.js');
|
||||
|
||||
let screenPickerWindow;
|
||||
let preloadWindow;
|
||||
@ -91,9 +92,27 @@ function openScreenPickerWindow(eventSender, sources, id) {
|
||||
});
|
||||
|
||||
screenPickerWindow.webContents.on('did-finish-load', () => {
|
||||
// initialize crash reporter
|
||||
initCrashReporterMain({ process: 'desktop capture window' });
|
||||
initCrashReporterRenderer(screenPickerWindow, { process: 'render | desktop capture window' });
|
||||
screenPickerWindow.webContents.send('desktop-capturer-sources', sources, isWindowsOS);
|
||||
});
|
||||
|
||||
screenPickerWindow.webContents.on('crashed', function () {
|
||||
const options = {
|
||||
type: 'error',
|
||||
title: 'Renderer Process Crashed',
|
||||
message: 'Oops! Looks like we have had a crash.',
|
||||
buttons: ['Close']
|
||||
};
|
||||
|
||||
electron.dialog.showMessageBox(options, function () {
|
||||
if (screenPickerWindow && !screenPickerWindow.isDestroyed()) {
|
||||
screenPickerWindow.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
screenPickerWindow.on('close', () => {
|
||||
destroyWindow();
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
const { ipcRenderer } = require('electron');
|
||||
const { ipcRenderer, crashReporter } = require('electron');
|
||||
|
||||
const screenRegExp = new RegExp(/^Screen \d+$/gmi);
|
||||
|
||||
@ -265,4 +265,10 @@ function updateSelectedSource(index) {
|
||||
function closeScreenPickerWindow() {
|
||||
document.removeEventListener('keyUp', handleKeyUpPress.bind(this), true);
|
||||
ipcRenderer.send('close-screen-picker');
|
||||
}
|
||||
}
|
||||
|
||||
ipcRenderer.on('register-crash-reporter', (event, arg) => {
|
||||
if (arg && typeof arg === 'object') {
|
||||
crashReporter.start(arg);
|
||||
}
|
||||
});
|
@ -129,7 +129,8 @@ const template = [{
|
||||
{
|
||||
label: isMac ? 'Show Logs in Finder' : 'Show Logs in Explorer',
|
||||
click() {
|
||||
|
||||
|
||||
const FILE_EXTENSIONS = [ '.log' ];
|
||||
const MAC_LOGS_PATH = '/Library/Logs/Symphony/';
|
||||
const WINDOWS_LOGS_PATH = '\\AppData\\Roaming\\Symphony\\';
|
||||
|
||||
@ -146,7 +147,7 @@ const template = [{
|
||||
|
||||
let destination = electron.app.getPath('downloads') + destPath + timestamp + '.zip';
|
||||
|
||||
archiveHandler.generateArchiveForDirectory(source, destination)
|
||||
archiveHandler.generateArchiveForDirectory(source, destination, FILE_EXTENSIONS)
|
||||
.then(() => {
|
||||
electron.shell.showItemInFolder(destination);
|
||||
})
|
||||
@ -157,10 +158,29 @@ const template = [{
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Open Crashes Directory',
|
||||
label: isMac ? 'Show crash dump in Finder' : 'Show crash dump in Explorer',
|
||||
click() {
|
||||
const crashesDirectory = electron.crashReporter.getCrashesDirectory() + '/completed';
|
||||
electron.shell.showItemInFolder(crashesDirectory);
|
||||
const FILE_EXTENSIONS = isMac ? [ '.dmp' ] : [ '.dmp', '.txt' ];
|
||||
const crashesDirectory = electron.crashReporter.getCrashesDirectory();
|
||||
let source = isMac ? crashesDirectory + '/completed' : crashesDirectory;
|
||||
|
||||
if (!fs.existsSync(source) || fs.readdirSync(source).length === 0) {
|
||||
electron.dialog.showErrorBox('Failed!', 'No crashes available to share');
|
||||
return;
|
||||
}
|
||||
|
||||
let destPath = isMac ? '/crashes_symphony_' : '\\crashes_symphony_';
|
||||
let timestamp = new Date().getTime();
|
||||
|
||||
let destination = electron.app.getPath('downloads') + destPath + timestamp + '.zip';
|
||||
|
||||
archiveHandler.generateArchiveForDirectory(source, destination, FILE_EXTENSIONS)
|
||||
.then(() => {
|
||||
electron.shell.showItemInFolder(destination);
|
||||
})
|
||||
.catch((err) => {
|
||||
electron.dialog.showErrorBox('Failed!', 'Unable to generate crash report due to -> ' + err);
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -130,19 +130,6 @@ function createAPI() {
|
||||
*/
|
||||
ScreenSnippet: remote.require('./screenSnippet/index.js').ScreenSnippet,
|
||||
|
||||
/**
|
||||
* Provides API to crash the renderer process that calls this function
|
||||
* Is only used for demos.
|
||||
*/
|
||||
crashRendererProcess: function () {
|
||||
// For practical purposes, we don't allow
|
||||
// this method to work in non-dev environments
|
||||
if (!process.env.ELECTRON_DEV) {
|
||||
return;
|
||||
}
|
||||
process.crash();
|
||||
},
|
||||
|
||||
/**
|
||||
* Provides api for client side searching
|
||||
* using the SymphonySearchEngine library
|
||||
@ -394,9 +381,13 @@ function createAPI() {
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* an event triggered by the main process to start crash reporter
|
||||
* in the render thread
|
||||
*/
|
||||
local.ipcRenderer.on('register-crash-reporter', (event, arg) => {
|
||||
if (arg) {
|
||||
crashReporter.start({companyName: arg.companyName, submitURL: arg.submitURL, uploadToServer: arg.uploadToServer, extra: {'process': arg.process, podUrl: arg.podUrl}});
|
||||
if (arg && typeof arg === 'object') {
|
||||
crashReporter.start(arg);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -3,11 +3,25 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const archiver = require('archiver');
|
||||
const log = require('../log.js');
|
||||
const logLevels = require('../enums/logLevels.js');
|
||||
const mmm = require('mmmagic');
|
||||
const Magic = mmm.Magic;
|
||||
const magic = new Magic(mmm.MAGIC_MIME_TYPE);
|
||||
|
||||
function generateArchiveForDirectory(source, destination) {
|
||||
/**
|
||||
* Archives files in the source directory
|
||||
* that matches the given file extension
|
||||
*
|
||||
* @param source {String} source path
|
||||
* @param destination {String} destination path
|
||||
* @param fileExtensions {Array} array of file ext
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
function generateArchiveForDirectory(source, destination, fileExtensions) {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
|
||||
let output = fs.createWriteStream(destination);
|
||||
let archive = archiver('zip', {zlib: {level: 9}});
|
||||
|
||||
@ -20,20 +34,55 @@ function generateArchiveForDirectory(source, destination) {
|
||||
});
|
||||
|
||||
archive.pipe(output);
|
||||
|
||||
|
||||
let files = fs.readdirSync(source);
|
||||
files.forEach((file) => {
|
||||
if (path.extname(file) === '.log') {
|
||||
archive.file(source + '/' + file, { name: 'logs/' + file });
|
||||
}
|
||||
});
|
||||
|
||||
archive.finalize();
|
||||
|
||||
|
||||
let filtered = files.filter((file) => fileExtensions.indexOf(path.extname(file)) !== -1);
|
||||
mapMimeType(filtered, source)
|
||||
.then((mappedData) => {
|
||||
if (mappedData.length > 0) {
|
||||
mappedData.map((data) => {
|
||||
switch (data.mimeType) {
|
||||
case 'text/plain':
|
||||
if (path.extname(data.file) === '.txt') {
|
||||
archive.file(source + '/' + data.file, { name: 'crashes/' + data.file });
|
||||
} else {
|
||||
archive.file(source + '/' + data.file, { name: 'logs/' + data.file });
|
||||
}
|
||||
break;
|
||||
case 'application/x-dmp':
|
||||
archive.file(source + '/' + data.file, { name: 'crashes/' + data.file });
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
archive.finalize();
|
||||
})
|
||||
.catch((err) => {
|
||||
log.send(logLevels.ERROR, 'Failed to find mime type. Error is -> ' + err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function mapMimeType(files, source) {
|
||||
return Promise.all(files.map((file) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
return magic.detectFile(source + '/' + file, (err, result) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
return resolve({file: file, mimeType: result});
|
||||
});
|
||||
});
|
||||
}))
|
||||
.then((data) => data)
|
||||
.catch((err) => log.send(logLevels.ERROR, 'Failed to find mime type. Error is -> ' + err));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
generateArchiveForDirectory: generateArchiveForDirectory
|
||||
};
|
@ -4,7 +4,6 @@ const fs = require('fs');
|
||||
const electron = require('electron');
|
||||
const app = electron.app;
|
||||
const globalShortcut = electron.globalShortcut;
|
||||
const crashReporter = electron.crashReporter;
|
||||
const BrowserWindow = electron.BrowserWindow;
|
||||
const path = require('path');
|
||||
const nodeURL = require('url');
|
||||
@ -24,6 +23,7 @@ const { getConfigField, updateConfigField, getGlobalConfigField } = require('./c
|
||||
const { isMac, isNodeEnv, isWindows10, isWindowsOS } = require('./utils/misc');
|
||||
const { deleteIndexFolder } = require('./search/search.js');
|
||||
const { isWhitelisted } = require('./utils/whitelistHandler');
|
||||
const { initCrashReporterMain, initCrashReporterRenderer } = require('./crashReporter.js');
|
||||
|
||||
// show dialog when certificate errors occur
|
||||
require('./dialogs/showCertError.js');
|
||||
@ -188,6 +188,10 @@ function doCreateMainWindow(initialUrl, initialBounds, isCustomTitleBar) {
|
||||
// content can be cached and will still finish load but
|
||||
// we might not have network connectivity, so warn the user.
|
||||
mainWindow.webContents.on('did-finish-load', function () {
|
||||
// Initialize crash reporter
|
||||
initCrashReporterMain({ process: 'main window' });
|
||||
initCrashReporterRenderer(mainWindow, { process: 'render | main window' });
|
||||
|
||||
url = mainWindow.webContents.getURL();
|
||||
if (isCustomTitleBarEnabled) {
|
||||
mainWindow.webContents.insertCSS(fs.readFileSync(path.join(__dirname, '/windowsTitleBar/style.css'), 'utf8').toString());
|
||||
@ -318,23 +322,6 @@ function doCreateMainWindow(initialUrl, initialBounds, isCustomTitleBar) {
|
||||
});
|
||||
});
|
||||
|
||||
getConfigField('url')
|
||||
.then(initializeCrashReporter)
|
||||
.catch(app.quit);
|
||||
|
||||
function initializeCrashReporter(podUrl) {
|
||||
getConfigField('crashReporter')
|
||||
.then((crashReporterConfig) => {
|
||||
log.send(logLevels.INFO, 'Initializing crash reporter on the main window!');
|
||||
crashReporter.start({ companyName: crashReporterConfig.companyName, submitURL: crashReporterConfig.submitURL, uploadToServer: crashReporterConfig.uploadToServer, extra: { 'process': 'renderer / main window', podUrl: podUrl } });
|
||||
log.send(logLevels.INFO, 'initialized crash reporter on the main window!');
|
||||
mainWindow.webContents.send('register-crash-reporter', { companyName: crashReporterConfig.companyName, submitURL: crashReporterConfig.submitURL, uploadToServer: crashReporterConfig.uploadToServer, process: 'preload script / main window renderer' });
|
||||
})
|
||||
.catch((err) => {
|
||||
log.send(logLevels.ERROR, 'Unable to initialize crash reporter in the main window. Error is -> ' + err);
|
||||
});
|
||||
}
|
||||
|
||||
// open external links in default browser - a tag with href='_blank' or window.open
|
||||
mainWindow.webContents.on('new-window', handleNewWindow);
|
||||
|
||||
@ -420,19 +407,8 @@ function doCreateMainWindow(initialUrl, initialBounds, isCustomTitleBar) {
|
||||
browserWin.setMenu(null);
|
||||
}
|
||||
|
||||
getConfigField('url')
|
||||
.then((podUrl) => {
|
||||
getConfigField('crashReporter')
|
||||
.then((crashReporterConfig) => {
|
||||
crashReporter.start({ companyName: crashReporterConfig.companyName, submitURL: crashReporterConfig.submitURL, uploadToServer: crashReporterConfig.uploadToServer, extra: { 'process': 'renderer / child window', podUrl: podUrl } });
|
||||
log.send(logLevels.INFO, 'initialized crash reporter on a child window!');
|
||||
browserWin.webContents.send('register-crash-reporter', { companyName: crashReporterConfig.companyName, submitURL: crashReporterConfig.submitURL, uploadToServer: crashReporterConfig.uploadToServer, process: 'preload script / child window renderer' });
|
||||
})
|
||||
.catch((err) => {
|
||||
log.send(logLevels.ERROR, 'Unable to initialize crash reporter in the child window. Error is -> ' + err);
|
||||
});
|
||||
})
|
||||
.catch(app.quit);
|
||||
initCrashReporterMain({ process: 'pop-out window' });
|
||||
initCrashReporterRenderer(browserWin, { process: 'render | pop-out window' });
|
||||
|
||||
browserWin.winName = frameName;
|
||||
browserWin.setAlwaysOnTop(alwaysOnTop);
|
||||
@ -452,7 +428,7 @@ function doCreateMainWindow(initialUrl, initialBounds, isCustomTitleBar) {
|
||||
browserWin.webContents.removeListener('crashed', handleChildWindowCrashEvent);
|
||||
});
|
||||
|
||||
let handleChildWindowCrashEvent = () => {
|
||||
let handleChildWindowCrashEvent = (e) => {
|
||||
const options = {
|
||||
type: 'error',
|
||||
title: 'Renderer Process Crashed',
|
||||
@ -460,14 +436,16 @@ function doCreateMainWindow(initialUrl, initialBounds, isCustomTitleBar) {
|
||||
buttons: ['Reload', 'Close']
|
||||
};
|
||||
|
||||
electron.dialog.showMessageBox(options, function (index) {
|
||||
if (index === 0) {
|
||||
browserWin.reload();
|
||||
}
|
||||
else {
|
||||
browserWin.close();
|
||||
}
|
||||
});
|
||||
let childBrowserWindow = BrowserWindow.fromWebContents(e.sender);
|
||||
if (childBrowserWindow && !childBrowserWindow.isDestroyed()) {
|
||||
electron.dialog.showMessageBox(childBrowserWindow, options, function (index) {
|
||||
if (index === 0) {
|
||||
childBrowserWindow.reload();
|
||||
} else {
|
||||
childBrowserWindow.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
browserWin.webContents.on('crashed', handleChildWindowCrashEvent);
|
||||
|
@ -122,6 +122,7 @@
|
||||
"lodash.isequal": "4.5.0",
|
||||
"lodash.omit": "4.5.0",
|
||||
"lodash.pick": "4.4.0",
|
||||
"mmmagic": "0.5.0",
|
||||
"parse-domain": "2.0.0",
|
||||
"ref": "1.3.5",
|
||||
"shell-path": "2.1.0",
|
||||
|
Loading…
Reference in New Issue
Block a user