import { app, ipcMain } from 'electron'; import * as fs from 'fs'; import * as path from 'path'; import { Main } from '../main'; import { StateService } from 'jslib-common/abstractions/state.service'; import { MenuUpdateRequest } from './menu.updater'; const SyncInterval = 5 * 60 * 1000; // 5 minutes export class MessagingMain { private syncTimeout: NodeJS.Timer; constructor(private main: Main, private stateService: StateService) { } init() { this.scheduleNextSync(); if (process.platform === 'linux') { this.stateService.setOpenAtLogin(fs.existsSync(this.linuxStartupFile())); } else { const loginSettings = app.getLoginItemSettings(); this.stateService.setOpenAtLogin(loginSettings.openAtLogin); } ipcMain.on('messagingService', async (event: any, message: any) => this.onMessage(message)); } onMessage(message: any) { switch (message.command) { case 'scheduleNextSync': this.scheduleNextSync(); break; case 'updateAppMenu': this.main.menuMain.updateApplicationMenuState(message.updateRequest); this.updateTrayMenu(message.updateRequest); break; case 'minimizeOnCopy': this.stateService.getMinimizeOnCopyToClipboard().then( shouldMinimize => { if (shouldMinimize && this.main.windowMain.win !== null) { this.main.windowMain.win.minimize(); } }); break; case 'showTray': this.main.trayMain.showTray(); break; case 'removeTray': this.main.trayMain.removeTray(); break; case 'hideToTray': this.main.trayMain.hideToTray(); break; case 'addOpenAtLogin': this.addOpenAtLogin(); break; case 'removeOpenAtLogin': this.removeOpenAtLogin(); case 'setFocus': this.setFocus(); break; case 'getWindowIsFocused': this.windowIsFocused(); break; case 'enableBrowserIntegration': this.main.nativeMessagingMain.generateManifests(); this.main.nativeMessagingMain.listen(); break; case 'disableBrowserIntegration': this.main.nativeMessagingMain.removeManifests(); this.main.nativeMessagingMain.stop(); break; default: break; } } private scheduleNextSync() { if (this.syncTimeout) { global.clearTimeout(this.syncTimeout); } this.syncTimeout = global.setTimeout(() => { if (this.main.windowMain.win == null) { return; } this.main.windowMain.win.webContents.send('messagingService', { command: 'checkSyncVault', }); }, SyncInterval); } private updateTrayMenu(updateRequest: MenuUpdateRequest) { if (this.main.trayMain == null || this.main.trayMain.contextMenu == null || updateRequest?.activeUserId == null) { return; } const lockNowTrayMenuItem = this.main.trayMain.contextMenu.getMenuItemById('lockNow'); const activeAccount = updateRequest.accounts[updateRequest.activeUserId]; if (lockNowTrayMenuItem != null && activeAccount != null) { lockNowTrayMenuItem.enabled = activeAccount.isAuthenticated && !activeAccount.isLocked; } this.main.trayMain.updateContextMenu(); } private addOpenAtLogin() { if (process.platform === 'linux') { const data = `[Desktop Entry] Type=Application Version=${app.getVersion()} Name=Bitwarden Comment=Bitwarden startup script Exec=${app.getPath('exe')} StartupNotify=false Terminal=false`; const dir = path.dirname(this.linuxStartupFile()); if (!fs.existsSync(dir)) { fs.mkdirSync(dir); } fs.writeFileSync(this.linuxStartupFile(), data); } else { app.setLoginItemSettings({openAtLogin: true}); } } private removeOpenAtLogin() { if (process.platform === 'linux') { if (fs.existsSync(this.linuxStartupFile())) { fs.unlinkSync(this.linuxStartupFile()); } } else { app.setLoginItemSettings({openAtLogin: false}); } } private linuxStartupFile(): string { return path.join(app.getPath('home'), '.config', 'autostart', 'bitwarden.desktop'); } private setFocus() { this.main.trayMain.restoreFromTray(); this.main.windowMain.win.focusOnWebView(); } private windowIsFocused() { const windowIsFocused = this.main.windowMain.win.isFocused(); this.main.windowMain.win.webContents.send('messagingService', { command: 'windowIsFocused', windowIsFocused: windowIsFocused, }); } }