mirror of
https://github.com/finos/SymphonyElectron.git
synced 2024-12-28 09:51:06 -06:00
feat: SDA-2559: clean app cache on install & crash (#1091)
* SDA-2559: clean app cache on install - Clean app cache on a fresh install of SDA to avoid upgradation problems - Clean app cache and restart SDA when it crashes or is unresponsive * SDA-2559: fix failing unit test * SDA-2559: add dialog before restarting the app * SDA-2559: add translations * SDA-2559: fix failing unit tests and refactor code
This commit is contained in:
parent
c13a6a16ad
commit
e3720c22f6
@ -118,6 +118,7 @@
|
||||
"@types/react": "16.8.3",
|
||||
"@types/react-dom": "16.0.9",
|
||||
"@types/ref-napi": "1.4.0",
|
||||
"@types/rimraf": "^3.0.0",
|
||||
"ava": "2.4.0",
|
||||
"browserify": "16.5.1",
|
||||
"cross-env": "5.2.0",
|
||||
@ -161,6 +162,7 @@
|
||||
"react": "16.13.0",
|
||||
"react-dom": "16.13.0",
|
||||
"ref-napi": "1.4.3",
|
||||
"rimraf": "^3.0.2",
|
||||
"shell-path": "2.1.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
|
@ -1,12 +1,27 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { cleanUpAppCache, createAppCacheFile } from '../src/app/app-cache-handler';
|
||||
import * as rimraf from 'rimraf';
|
||||
import { cleanAppCacheOnInstall, cleanUpAppCache, createAppCacheFile } from '../src/app/app-cache-handler';
|
||||
import { app, session } from './__mocks__/electron';
|
||||
|
||||
jest.mock('fs', () => ({
|
||||
writeFileSync: jest.fn(),
|
||||
existsSync: jest.fn(() => true),
|
||||
unlinkSync: jest.fn(),
|
||||
readdirSync: jest.fn(() => ['fake1', 'fake2', 'Symphony.config', 'cloudConfig.config']),
|
||||
lstatSync: jest.fn(() => {
|
||||
return {
|
||||
isDirectory: jest.fn(() => true),
|
||||
};
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('path', () => ({
|
||||
join: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('rimraf', () => ({
|
||||
sync: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('../src/common/logger', () => {
|
||||
@ -19,6 +34,7 @@ jest.mock('../src/common/logger', () => {
|
||||
});
|
||||
|
||||
describe('app cache handler', () => {
|
||||
describe('check app cache file', () => {
|
||||
const cachePathExpected = path.join(app.getPath('userData'), 'CacheCheck');
|
||||
|
||||
it('should call `cleanUpAppCache` correctly', () => {
|
||||
@ -43,3 +59,28 @@ describe('app cache handler', () => {
|
||||
expect(spy).lastCalledWith(cachePathExpected, '');
|
||||
});
|
||||
});
|
||||
|
||||
describe('clean app cache on install', () => {
|
||||
it('should clean app cache and cookies on install', () => {
|
||||
|
||||
const pathSpy = jest.spyOn(path, 'join');
|
||||
|
||||
const fsReadDirSpy = jest.spyOn(fs, 'readdirSync');
|
||||
const fsStatSpy = jest.spyOn(fs, 'lstatSync');
|
||||
const fsUnlinkSpy = jest.spyOn(fs, 'unlinkSync');
|
||||
|
||||
const rimrafSpy = jest.spyOn(rimraf, 'sync');
|
||||
|
||||
cleanAppCacheOnInstall();
|
||||
|
||||
expect(pathSpy).toBeCalled();
|
||||
|
||||
expect(fsReadDirSpy).toBeCalled();
|
||||
expect(fsStatSpy).toBeCalled();
|
||||
expect(fsUnlinkSpy).toBeCalled();
|
||||
|
||||
expect(rimrafSpy).toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -1,11 +1,37 @@
|
||||
import { app, session } from 'electron';
|
||||
import { app, BrowserWindow, dialog, session } from 'electron';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as rimraf from 'rimraf';
|
||||
import { i18n } from '../common/i18n';
|
||||
|
||||
import { logger } from '../common/logger';
|
||||
|
||||
// Cache check file path
|
||||
const cacheCheckFilePath: string = path.join(app.getPath('userData'), 'CacheCheck');
|
||||
const userDataPath: string = app.getPath('userData');
|
||||
const cacheCheckFilePath: string = path.join(userDataPath, 'CacheCheck');
|
||||
|
||||
/**
|
||||
* Cleans old cache
|
||||
*/
|
||||
const cleanOldCache = (): void => {
|
||||
const configFilename = 'Symphony.config';
|
||||
const cloudConfigFilename = 'cloudConfig.config';
|
||||
|
||||
const files = fs.readdirSync(userDataPath);
|
||||
|
||||
files.forEach((file) => {
|
||||
const filePath = path.join(userDataPath, file);
|
||||
if (file === configFilename || file === cloudConfigFilename) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fs.lstatSync(filePath).isDirectory()) {
|
||||
rimraf.sync(filePath);
|
||||
return;
|
||||
}
|
||||
fs.unlinkSync(filePath);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes app cache file if exists or clears
|
||||
@ -30,3 +56,45 @@ export const createAppCacheFile = (): void => {
|
||||
logger.info(`app-cache-handler: this is a clean exit, creating app cache file`);
|
||||
fs.writeFileSync(cacheCheckFilePath, '');
|
||||
};
|
||||
|
||||
/**
|
||||
* Cleans the app cache on new install
|
||||
*/
|
||||
export const cleanAppCacheOnInstall = (): void => {
|
||||
logger.info(`app-cache-handler: cleaning app cache and cookies on new install`);
|
||||
cleanOldCache();
|
||||
};
|
||||
|
||||
/**
|
||||
* Cleans app cache and restarts the app on crash or unresponsive events
|
||||
* @param window Browser window to listen to for crash events
|
||||
*/
|
||||
export const cleanAppCacheOnCrash = (window: BrowserWindow): void => {
|
||||
logger.info(`app-cache-handler: listening to crash events & cleaning app cache`);
|
||||
const events = ['unresponsive', 'crashed', 'plugin-crashed'];
|
||||
|
||||
events.forEach((windowEvent: any) => {
|
||||
window.webContents.on(windowEvent, async () => {
|
||||
logger.info(`app-cache-handler: Window Event '${windowEvent}' occurred. Clearing cache & restarting app`);
|
||||
const focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (!focusedWindow || (typeof focusedWindow.isDestroyed === 'function' && focusedWindow.isDestroyed())) {
|
||||
return;
|
||||
}
|
||||
const options = {
|
||||
type: 'question',
|
||||
title: i18n.t('Relaunch Application')(),
|
||||
message: i18n.t('Oops! Something went wrong. Would you like to restart the app?')(),
|
||||
buttons: [i18n.t('Restart')(), i18n.t('Cancel')()],
|
||||
cancelId: 1,
|
||||
};
|
||||
|
||||
const { response } = await dialog.showMessageBox(focusedWindow, options);
|
||||
|
||||
if (response === 0) {
|
||||
cleanOldCache();
|
||||
app.relaunch();
|
||||
app.exit();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -5,7 +5,7 @@ import * as shellPath from 'shell-path';
|
||||
import { isDevEnv, isElectronQA, isLinux, isMac } from '../common/env';
|
||||
import { logger } from '../common/logger';
|
||||
import { getCommandLineArgs } from '../common/utils';
|
||||
import { cleanUpAppCache, createAppCacheFile } from './app-cache-handler';
|
||||
import { cleanAppCacheOnInstall, cleanUpAppCache, createAppCacheFile } from './app-cache-handler';
|
||||
import { autoLaunchInstance } from './auto-launch-controller';
|
||||
import { setChromeFlags, setSessionProperties } from './chrome-flags';
|
||||
import { config } from './config-handler';
|
||||
@ -81,6 +81,7 @@ const startApplication = async () => {
|
||||
createAppCacheFile();
|
||||
if (config.isFirstTimeLaunch()) {
|
||||
logger.info(`main: This is a first time launch! will update config and handle auto launch`);
|
||||
cleanAppCacheOnInstall();
|
||||
await config.setUpFirstTimeLaunch();
|
||||
if (!isLinux) {
|
||||
await autoLaunchInstance.handleAutoLaunch();
|
||||
|
@ -19,6 +19,7 @@ import { i18n, LocaleType } from '../common/i18n';
|
||||
import { logger } from '../common/logger';
|
||||
import { getCommandLineArgs, getGuid } from '../common/utils';
|
||||
import { notification } from '../renderer/notification';
|
||||
import { cleanAppCacheOnCrash } from './app-cache-handler';
|
||||
import { AppMenu } from './app-menu';
|
||||
import { handleChildWindow } from './child-window-handler';
|
||||
import { CloudConfigDataTypes, config, IConfig, IGlobalConfig } from './config-handler';
|
||||
@ -289,6 +290,7 @@ export class WindowHandler {
|
||||
this.handleWelcomeScreen();
|
||||
}
|
||||
|
||||
cleanAppCacheOnCrash(this.mainWindow);
|
||||
// loads the main window with url from config/cmd line
|
||||
this.mainWindow.loadURL(this.url);
|
||||
// check for build expiry in case of test builds
|
||||
|
@ -111,6 +111,7 @@
|
||||
},
|
||||
"Oops! Looks like we have had a crash.": "Oops! Looks like we have had a crash.",
|
||||
"Oops! Looks like we have had a crash. Please reload or close this window.": "Oops! Looks like we have had a crash. Please reload or close this window.",
|
||||
"Oops! Something went wrong. Would you like to restart the app?": "Oops! Something went wrong. Would you like to restart the app?",
|
||||
"Paste": "Paste",
|
||||
"Paste and Match Style": "Paste and Match Style",
|
||||
"Permission Denied": "Permission Denied",
|
||||
|
@ -111,6 +111,7 @@
|
||||
},
|
||||
"Oops! Looks like we have had a crash.": "Oops! Looks like we have had a crash.",
|
||||
"Oops! Looks like we have had a crash. Please reload or close this window.": "Oops! Looks like we have had a crash. Please reload or close this window.",
|
||||
"Oops! Something went wrong. Would you like to restart the app?": "Oops! Something went wrong. Would you like to restart the app?",
|
||||
"Paste": "Paste",
|
||||
"Paste and Match Style": "Paste and Match Style",
|
||||
"Permission Denied": "Permission Denied",
|
||||
|
@ -112,6 +112,7 @@
|
||||
},
|
||||
"Oops! Looks like we have had a crash.": "Oops! On dirait que nous avons eu un crash.",
|
||||
"Oops! Looks like we have had a crash. Please reload or close this window.": "Oops! On dirait que nous avons eu un crash. Veuillez recharger ou fermer cette fenêtre.",
|
||||
"Oops! Something went wrong. Would you like to restart the app?": "Oups ! Quelque chose s'est mal passé. Voulez-vous redémarrer l'application ?",
|
||||
"Paste": "Coller",
|
||||
"Paste and Match Style": "Coller et appliquer le style",
|
||||
"Permission Denied": "Permission refusée",
|
||||
|
@ -111,6 +111,7 @@
|
||||
},
|
||||
"Oops! Looks like we have had a crash.": "Oops! On dirait que nous avons eu un crash.",
|
||||
"Oops! Looks like we have had a crash. Please reload or close this window.": "Oops! On dirait que nous avons eu un crash. Veuillez recharger ou fermer cette fenêtre.",
|
||||
"Oops! Something went wrong. Would you like to restart the app?": "Oups ! Quelque chose s'est mal passé. Voulez-vous redémarrer l'application ?",
|
||||
"Paste": "Coller",
|
||||
"Paste and Match Style": "Coller et appliquer le style",
|
||||
"Permission Denied": "Permission refusée",
|
||||
|
@ -111,6 +111,7 @@
|
||||
},
|
||||
"Oops! Looks like we have had a crash.": "おっと!クラッシュしたようです。",
|
||||
"Oops! Looks like we have had a crash. Please reload or close this window.": "おっと!クラッシュしたようです。このウィンドウを再度読み込むか閉じてください。",
|
||||
"Oops! Something went wrong. Would you like to restart the app?": "おっと!何か問題が起こった。アプリを再開しますか?",
|
||||
"Paste": "貼り付け",
|
||||
"Paste and Match Style": "貼り付けでスタイルを合わせる",
|
||||
"Permission Denied": "アクセス許可が拒否されています",
|
||||
|
@ -111,6 +111,7 @@
|
||||
},
|
||||
"Oops! Looks like we have had a crash.": "おっと!クラッシュしたようです。",
|
||||
"Oops! Looks like we have had a crash. Please reload or close this window.": "おっと!クラッシュしたようです。このウィンドウを再度読み込むか閉じてください。",
|
||||
"Oops! Something went wrong. Would you like to restart the app?": "おっと!何か問題が起こった。アプリを再開しますか?",
|
||||
"Paste": "貼り付け",
|
||||
"Paste and Match Style": "貼り付けでスタイルを合わせる",
|
||||
"Permission Denied": "アクセス許可が拒否されています",
|
||||
|
Loading…
Reference in New Issue
Block a user