bitwarden-estensione-browser/src/main/menu.main.ts

526 lines
21 KiB
TypeScript
Raw Normal View History

2018-02-08 21:58:47 +01:00
import {
app,
BrowserWindow,
2018-02-12 22:07:14 +01:00
clipboard,
2018-02-09 19:21:23 +01:00
dialog,
2018-02-10 21:30:42 +01:00
ipcMain,
2018-02-08 21:58:47 +01:00
Menu,
2018-02-13 21:00:38 +01:00
MenuItem,
2018-02-08 21:58:47 +01:00
MenuItemConstructorOptions,
2018-02-09 18:36:37 +01:00
shell,
2018-02-08 21:58:47 +01:00
} from 'electron';
2018-02-14 05:38:18 +01:00
import { Main } from '../main';
2018-04-24 22:30:47 +02:00
import { BaseMenu } from 'jslib-electron/baseMenu';
import { isMacAppStore, isSnapStore, isWindowsStore } from 'jslib-electron/utils';
2018-02-09 06:21:00 +01:00
import { ConstantsService } from 'jslib-common/services/constants.service';
2018-02-19 14:52:53 +01:00
export class MenuMain extends BaseMenu {
2018-02-14 06:26:32 +01:00
menu: Menu;
updateMenuItem: MenuItem;
addNewLogin: MenuItem;
addNewItem: MenuItem;
addNewFolder: MenuItem;
syncVault: MenuItem;
2018-08-02 05:21:32 +02:00
exportVault: MenuItem;
2018-02-14 06:26:32 +01:00
settings: MenuItem;
lockNow: MenuItem;
logOut: MenuItem;
twoStepLogin: MenuItem;
2018-11-16 16:34:31 +01:00
fingerprintPhrase: MenuItem;
2018-02-14 06:26:32 +01:00
changeMasterPass: MenuItem;
premiumMembership: MenuItem;
passwordGenerator: MenuItem;
2018-02-18 04:37:43 +01:00
passwordHistory: MenuItem;
2018-02-14 06:26:32 +01:00
searchVault: MenuItem;
copyUsername: MenuItem;
copyPassword: MenuItem;
copyTotp: MenuItem;
2018-02-14 06:26:32 +01:00
unlockedRequiredMenuItems: MenuItem[] = [];
constructor(private main: Main) {
2018-05-08 15:40:33 +02:00
super(main.i18nService, main.windowMain);
}
2018-02-08 19:10:13 +01:00
init() {
this.initProperties();
2018-02-14 05:06:45 +01:00
this.initContextMenu();
this.initApplicationMenu();
2018-02-14 06:26:32 +01:00
this.updateMenuItem = this.menu.getMenuItemById('checkForUpdates');
this.addNewLogin = this.menu.getMenuItemById('addNewLogin');
this.addNewItem = this.menu.getMenuItemById('addNewItem');
this.addNewFolder = this.menu.getMenuItemById('addNewFolder');
this.syncVault = this.menu.getMenuItemById('syncVault');
2018-08-02 05:21:32 +02:00
this.exportVault = this.menu.getMenuItemById('exportVault');
2018-02-14 06:26:32 +01:00
this.settings = this.menu.getMenuItemById('settings');
this.lockNow = this.menu.getMenuItemById('lockNow');
this.logOut = this.menu.getMenuItemById('logOut');
this.twoStepLogin = this.menu.getMenuItemById('twoStepLogin');
2018-11-16 16:34:31 +01:00
this.fingerprintPhrase = this.menu.getMenuItemById('fingerprintPhrase');
2018-02-14 06:26:32 +01:00
this.changeMasterPass = this.menu.getMenuItemById('changeMasterPass');
this.premiumMembership = this.menu.getMenuItemById('premiumMembership');
this.passwordGenerator = this.menu.getMenuItemById('passwordGenerator');
2018-02-18 04:37:43 +01:00
this.passwordHistory = this.menu.getMenuItemById('passwordHistory');
2018-02-14 06:26:32 +01:00
this.searchVault = this.menu.getMenuItemById('searchVault');
this.copyUsername = this.menu.getMenuItemById('copyUsername');
this.copyPassword = this.menu.getMenuItemById('copyPassword');
this.copyTotp = this.menu.getMenuItemById('copyTotp');
2018-02-14 06:26:32 +01:00
this.unlockedRequiredMenuItems = [
this.addNewLogin, this.addNewItem, this.addNewFolder,
2018-11-16 16:34:31 +01:00
this.syncVault, this.exportVault, this.settings, this.lockNow, this.twoStepLogin, this.fingerprintPhrase,
2018-02-18 04:37:43 +01:00
this.changeMasterPass, this.premiumMembership, this.passwordGenerator, this.passwordHistory,
this.searchVault, this.copyUsername, this.copyPassword];
this.updateApplicationMenuState(false, true, false);
2018-02-14 06:26:32 +01:00
}
updateApplicationMenuState(isAuthenticated: boolean, isLocked: boolean, hideChangeMasterPass: boolean) {
if (isAuthenticated != null && isLocked != null) {
this.unlockedRequiredMenuItems.forEach((mi: MenuItem) => {
if (mi != null) {
mi.enabled = isAuthenticated && !isLocked;
}
});
if (this.logOut != null) {
this.logOut.enabled = isAuthenticated;
2019-03-12 21:08:14 +01:00
}
}
2018-02-14 06:26:32 +01:00
if (this.changeMasterPass != null) {
this.changeMasterPass.visible = !(hideChangeMasterPass ?? false);
2021-02-05 20:36:49 +01:00
}
if (this.menu != null) {
Menu.setApplicationMenu(this.menu);
2019-03-12 21:08:14 +01:00
}
2018-02-14 05:06:45 +01:00
}
private initApplicationMenu() {
2018-02-28 04:15:52 +01:00
const accountSubmenu: MenuItemConstructorOptions[] = [
{
label: this.main.i18nService.t('changeMasterPass'),
id: 'changeMasterPass',
click: async () => {
2020-01-27 15:46:50 +01:00
const result = await dialog.showMessageBox(this.main.windowMain.win, {
2018-02-28 04:15:52 +01:00
title: this.main.i18nService.t('changeMasterPass'),
message: this.main.i18nService.t('changeMasterPass'),
detail: this.main.i18nService.t('changeMasterPasswordConfirmation'),
buttons: [this.main.i18nService.t('yes'), this.main.i18nService.t('no')],
cancelId: 1,
defaultId: 0,
noLink: true,
});
2020-01-27 15:46:50 +01:00
if (result.response === 0) {
2018-02-28 04:15:52 +01:00
await this.openWebVault();
}
},
},
{
label: this.main.i18nService.t('twoStepLogin'),
id: 'twoStepLogin',
click: async () => {
2020-01-27 15:46:50 +01:00
const result = await dialog.showMessageBox(this.main.windowMain.win, {
2018-02-28 04:15:52 +01:00
title: this.main.i18nService.t('twoStepLogin'),
message: this.main.i18nService.t('twoStepLogin'),
detail: this.main.i18nService.t('twoStepLoginConfirmation'),
buttons: [this.main.i18nService.t('yes'), this.main.i18nService.t('no')],
cancelId: 1,
defaultId: 0,
noLink: true,
});
2020-01-27 15:46:50 +01:00
if (result.response === 0) {
2018-02-28 04:15:52 +01:00
await this.openWebVault();
}
},
},
2018-11-16 16:34:31 +01:00
{
label: this.main.i18nService.t('fingerprintPhrase'),
id: 'fingerprintPhrase',
click: () => this.main.messagingService.send('showFingerprintPhrase'),
},
2018-02-28 04:15:52 +01:00
{ type: 'separator' },
2018-05-08 15:40:33 +02:00
{
label: this.i18nService.t('logOut'),
id: 'logOut',
2020-01-27 15:46:50 +01:00
click: async () => {
const result = await dialog.showMessageBox(this.windowMain.win, {
2018-05-08 15:40:33 +02:00
title: this.i18nService.t('logOut'),
message: this.i18nService.t('logOut'),
detail: this.i18nService.t('logOutConfirmation'),
buttons: [this.i18nService.t('logOut'), this.i18nService.t('cancel')],
cancelId: 1,
defaultId: 0,
noLink: true,
});
2020-01-27 15:46:50 +01:00
if (result.response === 0) {
2018-05-08 15:40:33 +02:00
this.main.messagingService.send('logout');
}
},
},
2018-02-28 04:15:52 +01:00
];
this.editMenuItemOptions.submenu = (this.editMenuItemOptions.submenu as MenuItemConstructorOptions[]).concat([
{ type: 'separator' },
{
label: this.main.i18nService.t('copyUsername'),
id: 'copyUsername',
click: () => this.main.messagingService.send('copyUsername'),
accelerator: 'CmdOrCtrl+U',
},
{
label: this.main.i18nService.t('copyPassword'),
id: 'copyPassword',
click: () => this.main.messagingService.send('copyPassword'),
accelerator: 'CmdOrCtrl+P',
},
{
label: this.main.i18nService.t('copyVerificationCodeTotp'),
id: 'copyTotp',
click: () => this.main.messagingService.send('copyTotp'),
2021-02-08 19:58:44 +01:00
accelerator: 'CmdOrCtrl+T',
},
]);
if (!isWindowsStore() && !isMacAppStore()) {
2018-02-28 04:15:52 +01:00
accountSubmenu.unshift({
label: this.main.i18nService.t('premiumMembership'),
click: () => this.main.messagingService.send('openPremium'),
id: 'premiumMembership',
});
}
2019-09-26 02:56:57 +02:00
let helpSubmenu: MenuItemConstructorOptions[] = [
{
label: this.main.i18nService.t('emailUs'),
click: () => shell.openExternal('mailTo:hello@bitwarden.com'),
},
{
label: this.main.i18nService.t('visitOurWebsite'),
click: () => shell.openExternal('https://bitwarden.com/contact'),
},
{
label: this.main.i18nService.t('fileBugReport'),
click: () => shell.openExternal('https://github.com/bitwarden/desktop/issues'),
},
2019-09-26 02:56:57 +02:00
];
if (isMacAppStore()) {
helpSubmenu.push({
label: this.main.i18nService.t('legal'),
submenu: [
{
label: this.main.i18nService.t('termsOfService'),
click: () => shell.openExternal('https://bitwarden.com/terms/'),
},
{
label: this.main.i18nService.t('privacyPolicy'),
click: () => shell.openExternal('https://bitwarden.com/privacy/'),
},
],
});
}
helpSubmenu = helpSubmenu.concat([
{ type: 'separator' },
{
label: this.main.i18nService.t('followUs'),
submenu: [
{
label: this.main.i18nService.t('blog'),
click: () => shell.openExternal('https://blog.bitwarden.com'),
},
{
label: 'Twitter',
2019-03-06 21:47:03 +01:00
click: () => shell.openExternal('https://twitter.com/bitwarden'),
},
{
label: 'Facebook',
click: () => shell.openExternal('https://www.facebook.com/bitwarden/'),
},
{
label: 'GitHub',
click: () => shell.openExternal('https://github.com/bitwarden'),
},
],
},
{ type: 'separator' },
{
label: this.main.i18nService.t('goToWebVault'),
click: async () => await this.openWebVault(),
},
2019-09-26 02:56:57 +02:00
]);
if (!isWindowsStore()) {
helpSubmenu.push({
label: this.main.i18nService.t('getMobileApp'),
submenu: [
{
label: 'iOS',
click: () => {
shell.openExternal('https://itunes.apple.com/app/' +
'bitwarden-free-password-manager/id1137397744?mt=8');
},
},
{
label: 'Android',
click: () => {
shell.openExternal('https://play.google.com/store/apps/' +
'details?id=com.x8bit.bitwarden');
},
},
],
});
helpSubmenu.push({
label: this.main.i18nService.t('getBrowserExtension'),
submenu: [
{
label: 'Chrome',
click: () => {
shell.openExternal('https://chrome.google.com/webstore/detail/' +
'bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb');
},
},
{
label: 'Firefox',
click: () => {
shell.openExternal('https://addons.mozilla.org/firefox/addon/' +
'bitwarden-password-manager/');
},
},
{
label: 'Opera',
click: () => {
shell.openExternal('https://addons.opera.com/extensions/details/' +
'bitwarden-free-password-manager/');
},
},
{
label: 'Edge',
click: () => {
shell.openExternal('https://microsoftedge.microsoft.com/addons/' +
'detail/jbkfoedolllekgbhcbcoahefnbanhhlh');
},
},
{
label: 'Safari',
click: () => {
2020-07-29 04:51:49 +02:00
shell.openExternal('https://bitwarden.com/download/');
},
},
],
});
}
2018-02-08 19:10:13 +01:00
const template: MenuItemConstructorOptions[] = [
2018-02-08 21:58:47 +01:00
{
2018-02-14 05:38:18 +01:00
label: this.main.i18nService.t('file'),
2018-02-08 21:58:47 +01:00
submenu: [
{
2018-02-14 05:38:18 +01:00
label: this.main.i18nService.t('addNewLogin'),
click: () => this.main.messagingService.send('newLogin'),
2018-02-10 21:30:42 +01:00
accelerator: 'CmdOrCtrl+N',
2018-02-14 06:26:32 +01:00
id: 'addNewLogin',
2018-02-09 06:21:00 +01:00
},
{
2018-02-14 05:38:18 +01:00
label: this.main.i18nService.t('addNewItem'),
2018-02-14 06:26:32 +01:00
id: 'addNewItem',
2018-02-08 21:58:47 +01:00
submenu: [
{
2018-02-14 05:38:18 +01:00
label: this.main.i18nService.t('typeLogin'),
click: () => this.main.messagingService.send('newLogin'),
accelerator: 'CmdOrCtrl+Shift+L',
2018-02-08 21:58:47 +01:00
},
{
2018-02-14 05:38:18 +01:00
label: this.main.i18nService.t('typeCard'),
click: () => this.main.messagingService.send('newCard'),
accelerator: 'CmdOrCtrl+Shift+C',
2018-02-08 21:58:47 +01:00
},
{
2018-02-14 05:38:18 +01:00
label: this.main.i18nService.t('typeIdentity'),
click: () => this.main.messagingService.send('newIdentity'),
accelerator: 'CmdOrCtrl+Shift+I',
2018-02-08 21:58:47 +01:00
},
{
2018-02-14 05:38:18 +01:00
label: this.main.i18nService.t('typeSecureNote'),
click: () => this.main.messagingService.send('newSecureNote'),
accelerator: 'CmdOrCtrl+Shift+S',
2018-02-10 21:30:42 +01:00
},
],
2018-02-08 21:58:47 +01:00
},
{
2018-02-14 05:38:18 +01:00
label: this.main.i18nService.t('addNewFolder'),
2018-02-14 06:26:32 +01:00
id: 'addNewFolder',
2018-02-14 05:38:18 +01:00
click: () => this.main.messagingService.send('newFolder'),
2018-02-08 21:58:47 +01:00
},
2018-02-09 06:21:00 +01:00
{ type: 'separator' },
2018-02-09 19:21:23 +01:00
{
2018-02-14 05:38:18 +01:00
label: this.main.i18nService.t('syncVault'),
2018-02-14 06:26:32 +01:00
id: 'syncVault',
2018-02-14 05:38:18 +01:00
click: () => this.main.messagingService.send('syncVault'),
2018-02-09 19:21:23 +01:00
},
2018-08-02 05:21:32 +02:00
{
label: this.main.i18nService.t('exportVault'),
id: 'exportVault',
click: () => this.main.messagingService.send('exportVault'),
},
2018-02-10 21:30:42 +01:00
],
2018-02-08 21:58:47 +01:00
},
this.editMenuItemOptions,
2018-02-08 19:10:13 +01:00
{
2018-02-14 05:38:18 +01:00
label: this.main.i18nService.t('view'),
submenu: ([
2018-02-18 04:37:43 +01:00
{
label: this.main.i18nService.t('searchVault'),
id: 'searchVault',
click: () => this.main.messagingService.send('focusSearch'),
accelerator: 'CmdOrCtrl+F',
},
{ type: 'separator' },
2018-02-09 06:21:00 +01:00
{
2018-02-14 05:38:18 +01:00
label: this.main.i18nService.t('passwordGenerator'),
2018-02-14 06:26:32 +01:00
id: 'passwordGenerator',
2018-02-14 05:38:18 +01:00
click: () => this.main.messagingService.send('openPasswordGenerator'),
2018-02-10 21:30:42 +01:00
accelerator: 'CmdOrCtrl+G',
2018-02-09 18:12:41 +01:00
},
2018-02-09 06:21:00 +01:00
{
2018-02-18 04:37:43 +01:00
label: this.main.i18nService.t('passwordHistory'),
id: 'passwordHistory',
click: () => this.main.messagingService.send('openPasswordHistory'),
2018-02-09 06:21:00 +01:00
},
2018-02-08 19:10:13 +01:00
{ type: 'separator' },
] as MenuItemConstructorOptions[]).concat(this.viewSubMenuItemOptions),
2018-02-08 19:10:13 +01:00
},
2018-02-08 21:58:47 +01:00
{
2018-02-14 05:38:18 +01:00
label: this.main.i18nService.t('account'),
2018-02-28 04:15:52 +01:00
submenu: accountSubmenu,
2018-02-08 21:58:47 +01:00
},
this.windowMenuItemOptions,
2018-02-08 19:10:13 +01:00
{
2018-02-26 03:37:00 +01:00
label: this.main.i18nService.t('help'),
2018-02-08 19:10:13 +01:00
role: 'help',
submenu: helpSubmenu,
2018-02-10 21:30:42 +01:00
},
2018-02-08 19:10:13 +01:00
];
2018-02-10 23:07:46 +01:00
const firstMenuOptions: MenuItemConstructorOptions[] = [
{ type: 'separator' },
{
label: this.main.i18nService.t(process.platform === 'darwin' ? 'preferences' : 'settings'),
2018-02-14 06:26:32 +01:00
id: 'settings',
2018-02-14 05:38:18 +01:00
click: () => this.main.messagingService.send('openSettings'),
2018-10-22 19:45:27 +02:00
accelerator: 'CmdOrCtrl+,',
2018-02-10 23:07:46 +01:00
},
{
2018-02-14 05:38:18 +01:00
label: this.main.i18nService.t('lockNow'),
2018-02-14 06:26:32 +01:00
id: 'lockNow',
2018-02-14 05:38:18 +01:00
click: () => this.main.messagingService.send('lockVault'),
2018-02-10 23:07:46 +01:00
accelerator: 'CmdOrCtrl+L',
},
];
2018-02-14 04:33:01 +01:00
const updateMenuItem = {
2018-02-14 05:38:18 +01:00
label: this.main.i18nService.t('checkForUpdates'),
click: () => this.main.updaterMain.checkForUpdate(true),
2018-02-14 04:33:01 +01:00
id: 'checkForUpdates',
};
2018-02-08 19:10:13 +01:00
if (process.platform === 'darwin') {
2018-02-10 23:07:46 +01:00
const firstMenuPart: MenuItemConstructorOptions[] = [
2018-02-23 05:19:35 +01:00
{
label: this.main.i18nService.t('aboutBitwarden'),
role: 'about',
},
2018-02-10 23:07:46 +01:00
];
2018-02-27 05:43:27 +01:00
if (!isMacAppStore()) {
firstMenuPart.push(updateMenuItem);
}
2018-02-10 23:07:46 +01:00
template.unshift({
2018-05-08 15:40:33 +02:00
label: 'Bitwarden',
2018-02-10 23:07:46 +01:00
submenu: firstMenuPart.concat(firstMenuOptions, [
{ type: 'separator' },
], this.macAppMenuItemOptions),
2018-02-10 23:07:46 +01:00
});
2018-02-08 19:10:13 +01:00
// Window menu
template[template.length - 2].submenu = this.macWindowSubmenuOptions;
2018-02-10 23:07:46 +01:00
} else {
2018-02-12 22:07:14 +01:00
// File menu
2018-02-10 23:07:46 +01:00
template[0].submenu = (template[0].submenu as MenuItemConstructorOptions[]).concat(
2018-12-03 22:07:03 +01:00
firstMenuOptions, {
2019-09-26 02:56:57 +02:00
label: this.i18nService.t('quitBitwarden'),
role: 'quit',
});
2018-02-12 22:07:14 +01:00
// About menu
2018-03-15 18:00:08 +01:00
const aboutMenuAdditions: MenuItemConstructorOptions[] = [
{ type: 'separator' },
];
if (!isWindowsStore() && !isSnapStore()) {
2018-03-15 18:00:08 +01:00
aboutMenuAdditions.push(updateMenuItem);
}
2018-05-08 15:40:33 +02:00
aboutMenuAdditions.push({
label: this.i18nService.t('aboutBitwarden'),
2020-01-27 15:46:50 +01:00
click: async () => {
2018-05-08 15:40:33 +02:00
const aboutInformation = this.i18nService.t('version', app.getVersion()) +
'\nShell ' + process.versions.electron +
'\nRenderer ' + process.versions.chrome +
'\nNode ' + process.versions.node +
'\nArchitecture ' + process.arch;
2020-01-27 15:46:50 +01:00
const result = await dialog.showMessageBox(this.windowMain.win, {
2018-05-08 15:40:33 +02:00
title: 'Bitwarden',
message: 'Bitwarden',
detail: aboutInformation,
type: 'info',
noLink: true,
buttons: [this.i18nService.t('ok'), this.i18nService.t('copy')],
});
2020-01-27 15:46:50 +01:00
if (result.response === 1) {
2018-05-08 15:40:33 +02:00
clipboard.writeText(aboutInformation);
}
},
});
2018-03-15 18:00:08 +01:00
2018-02-12 22:07:14 +01:00
template[template.length - 1].submenu =
2018-03-15 18:00:08 +01:00
(template[template.length - 1].submenu as MenuItemConstructorOptions[]).concat(aboutMenuAdditions);
2018-02-08 21:58:47 +01:00
}
2018-02-08 19:10:13 +01:00
(template[template.length - 2].submenu as MenuItemConstructorOptions[]).splice(1, 0,
2019-06-03 14:37:05 +02:00
{
label: this.main.i18nService.t(process.platform === 'darwin' ? 'hideToMenuBar' : 'hideToTray'),
click: () => this.main.messagingService.send('hideToTray'),
accelerator: 'CmdOrCtrl+Shift+M',
},
{
type: 'checkbox',
label: this.main.i18nService.t('alwaysOnTop'),
checked: this.windowMain.win.isAlwaysOnTop(),
click: () => this.main.windowMain.toggleAlwaysOnTop(),
accelerator: 'CmdOrCtrl+Shift+T',
});
2018-02-14 06:26:32 +01:00
this.menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(this.menu);
2018-02-08 19:10:13 +01:00
}
2018-02-19 14:52:53 +01:00
private async openWebVault() {
let webUrl = 'https://vault.bitwarden.com';
const urlsObj: any = await this.main.storageService.get(ConstantsService.environmentUrlsKey);
if (urlsObj != null) {
if (urlsObj.base != null) {
webUrl = urlsObj.base;
} else if (urlsObj.webVault != null) {
webUrl = urlsObj.webVault;
}
}
shell.openExternal(webUrl);
}
2018-02-08 19:10:13 +01:00
}