1
0
mirror of https://github.com/bitwarden/browser synced 2026-01-20 09:23:23 +00:00

Apply Prettier (#1202)

This commit is contained in:
Oscar Hinton
2021-12-20 15:47:17 +01:00
committed by GitHub
parent b4df834b16
commit 521feae535
141 changed files with 12454 additions and 10311 deletions

View File

@@ -1,96 +1,92 @@
import {
BrowserWindow,
clipboard,
dialog,
MenuItemConstructorOptions,
} from 'electron';
import { BrowserWindow, clipboard, dialog, MenuItemConstructorOptions } from "electron";
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { I18nService } from "jslib-common/abstractions/i18n.service";
import { UpdaterMain } from 'jslib-electron/updater.main';
import { isMac, isSnapStore, isWindowsStore } from 'jslib-electron/utils';
import { UpdaterMain } from "jslib-electron/updater.main";
import { isMac, isSnapStore, isWindowsStore } from "jslib-electron/utils";
import { IMenubarMenu } from './menubar';
import { IMenubarMenu } from "./menubar";
export class AboutMenu implements IMenubarMenu {
readonly id: string = 'about';
readonly id: string = "about";
get visible(): boolean {
return !isMac();
}
get visible(): boolean {
return !isMac();
}
get label(): string {
return this.localize('about');
}
get label(): string {
return this.localize("about");
}
get items(): MenuItemConstructorOptions[] {
return [
this.separator,
this.checkForUpdates,
this.aboutBitwarden,
];
}
get items(): MenuItemConstructorOptions[] {
return [this.separator, this.checkForUpdates, this.aboutBitwarden];
}
private readonly _i18nService: I18nService;
private readonly _updater: UpdaterMain;
private readonly _window: BrowserWindow;
private readonly _version: string;
private readonly _i18nService: I18nService;
private readonly _updater: UpdaterMain;
private readonly _window: BrowserWindow;
private readonly _version: string;
constructor(
i18nService: I18nService,
version: string,
window: BrowserWindow,
updater: UpdaterMain,
) {
this._i18nService = i18nService;
this._updater = updater;
this._version = version;
this._window = window;
}
constructor(
i18nService: I18nService,
version: string,
window: BrowserWindow,
updater: UpdaterMain
) {
this._i18nService = i18nService;
this._updater = updater;
this._version = version;
this._window = window;
}
private get separator(): MenuItemConstructorOptions {
return { type: 'separator' };
}
private get separator(): MenuItemConstructorOptions {
return { type: "separator" };
}
private get checkForUpdates(): MenuItemConstructorOptions {
return {
id: 'checkForUpdates',
label: this.localize('checkForUpdates'),
visible: !isWindowsStore() && !isSnapStore(),
click: () => this.checkForUpdate(),
};
}
private get checkForUpdates(): MenuItemConstructorOptions {
return {
id: "checkForUpdates",
label: this.localize("checkForUpdates"),
visible: !isWindowsStore() && !isSnapStore(),
click: () => this.checkForUpdate(),
};
}
private get aboutBitwarden(): MenuItemConstructorOptions {
return {
id: 'aboutBitwarden',
label: this.localize('aboutBitwarden'),
click: async () => {
const aboutInformation = this.localize('version', this._version) +
'\nShell ' + process.versions.electron +
'\nRenderer ' + process.versions.chrome +
'\nNode ' + process.versions.node +
'\nArchitecture ' + process.arch;
const result = await dialog.showMessageBox(this._window, {
title: 'Bitwarden',
message: 'Bitwarden',
detail: aboutInformation,
type: 'info',
noLink: true,
buttons: [this.localize('ok'), this.localize('copy')],
});
if (result.response === 1) {
clipboard.writeText(aboutInformation);
}
},
};
}
private get aboutBitwarden(): MenuItemConstructorOptions {
return {
id: "aboutBitwarden",
label: this.localize("aboutBitwarden"),
click: async () => {
const aboutInformation =
this.localize("version", this._version) +
"\nShell " +
process.versions.electron +
"\nRenderer " +
process.versions.chrome +
"\nNode " +
process.versions.node +
"\nArchitecture " +
process.arch;
const result = await dialog.showMessageBox(this._window, {
title: "Bitwarden",
message: "Bitwarden",
detail: aboutInformation,
type: "info",
noLink: true,
buttons: [this.localize("ok"), this.localize("copy")],
});
if (result.response === 1) {
clipboard.writeText(aboutInformation);
}
},
};
}
private localize(s: string, p?: string) {
return this._i18nService.t(s, p);
}
private localize(s: string, p?: string) {
return this._i18nService.t(s, p);
}
private async checkForUpdate() {
this._updater.checkForUpdate(true);
}
private async checkForUpdate() {
this._updater.checkForUpdate(true);
}
}

View File

@@ -1,121 +1,116 @@
import {
BrowserWindow,
dialog,
MenuItemConstructorOptions,
shell,
} from 'electron';
import { BrowserWindow, dialog, MenuItemConstructorOptions, shell } from "electron";
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { I18nService } from "jslib-common/abstractions/i18n.service";
import { MessagingService } from "jslib-common/abstractions/messaging.service";
import { isMacAppStore, isWindowsStore } from 'jslib-electron/utils';
import { isMacAppStore, isWindowsStore } from "jslib-electron/utils";
import { IMenubarMenu } from './menubar';
import { IMenubarMenu } from "./menubar";
export class AccountMenu implements IMenubarMenu {
readonly id: string = 'accountMenu';
readonly id: string = "accountMenu";
get label(): string {
return this.localize('account');
}
get label(): string {
return this.localize("account");
}
get items(): MenuItemConstructorOptions[] {
return [
this.premiumMembership,
this.changeMasterPassword,
this.twoStepLogin,
this.fingerprintPhrase,
];
}
get items(): MenuItemConstructorOptions[] {
return [
this.premiumMembership,
this.changeMasterPassword,
this.twoStepLogin,
this.fingerprintPhrase,
];
}
private readonly _i18nService: I18nService;
private readonly _messagingService: MessagingService;
private readonly _webVaultUrl: string;
private readonly _window: BrowserWindow;
private readonly _isAuthenticated: boolean;
private readonly _i18nService: I18nService;
private readonly _messagingService: MessagingService;
private readonly _webVaultUrl: string;
private readonly _window: BrowserWindow;
private readonly _isAuthenticated: boolean;
constructor(
i18nService: I18nService,
messagingService: MessagingService,
webVaultUrl: string,
window: BrowserWindow,
isAuthenticated: boolean,
) {
this._i18nService = i18nService;
this._messagingService = messagingService;
this._webVaultUrl = webVaultUrl;
this._window = window;
this._isAuthenticated = isAuthenticated;
}
constructor(
i18nService: I18nService,
messagingService: MessagingService,
webVaultUrl: string,
window: BrowserWindow,
isAuthenticated: boolean
) {
this._i18nService = i18nService;
this._messagingService = messagingService;
this._webVaultUrl = webVaultUrl;
this._window = window;
this._isAuthenticated = isAuthenticated;
}
private get premiumMembership(): MenuItemConstructorOptions {
return {
label: this.localize('premiumMembership'),
click: () => this.sendMessage('openPremium'),
id: 'premiumMembership',
visible: !isWindowsStore() && !isMacAppStore(),
enabled: this._isAuthenticated,
};
}
private get premiumMembership(): MenuItemConstructorOptions {
return {
label: this.localize("premiumMembership"),
click: () => this.sendMessage("openPremium"),
id: "premiumMembership",
visible: !isWindowsStore() && !isMacAppStore(),
enabled: this._isAuthenticated,
};
}
private get changeMasterPassword(): MenuItemConstructorOptions {
return {
label: this.localize('changeMasterPass'),
id: 'changeMasterPass',
click: async () => {
const result = await dialog.showMessageBox(this._window, {
title: this.localize('changeMasterPass'),
message: this.localize('changeMasterPass'),
detail: this.localize('changeMasterPasswordConfirmation'),
buttons: [this.localize('yes'), this.localize('no')],
cancelId: 1,
defaultId: 0,
noLink: true,
});
if (result.response === 0) {
shell.openExternal(this._webVaultUrl);
}
},
enabled: this._isAuthenticated,
};
}
private get changeMasterPassword(): MenuItemConstructorOptions {
return {
label: this.localize("changeMasterPass"),
id: "changeMasterPass",
click: async () => {
const result = await dialog.showMessageBox(this._window, {
title: this.localize("changeMasterPass"),
message: this.localize("changeMasterPass"),
detail: this.localize("changeMasterPasswordConfirmation"),
buttons: [this.localize("yes"), this.localize("no")],
cancelId: 1,
defaultId: 0,
noLink: true,
});
if (result.response === 0) {
shell.openExternal(this._webVaultUrl);
}
},
enabled: this._isAuthenticated,
};
}
private get twoStepLogin(): MenuItemConstructorOptions {
return {
label: this.localize('twoStepLogin'),
id: 'twoStepLogin',
click: async () => {
const result = await dialog.showMessageBox(this._window, {
title: this.localize('twoStepLogin'),
message: this.localize('twoStepLogin'),
detail: this.localize('twoStepLoginConfirmation'),
buttons: [this.localize('yes'), this.localize('no')],
cancelId: 1,
defaultId: 0,
noLink: true,
});
if (result.response === 0) {
shell.openExternal(this._webVaultUrl);
}
},
enabled: this._isAuthenticated,
};
}
private get twoStepLogin(): MenuItemConstructorOptions {
return {
label: this.localize("twoStepLogin"),
id: "twoStepLogin",
click: async () => {
const result = await dialog.showMessageBox(this._window, {
title: this.localize("twoStepLogin"),
message: this.localize("twoStepLogin"),
detail: this.localize("twoStepLoginConfirmation"),
buttons: [this.localize("yes"), this.localize("no")],
cancelId: 1,
defaultId: 0,
noLink: true,
});
if (result.response === 0) {
shell.openExternal(this._webVaultUrl);
}
},
enabled: this._isAuthenticated,
};
}
private get fingerprintPhrase(): MenuItemConstructorOptions {
return {
label: this.localize('fingerprintPhrase'),
id: 'fingerprintPhrase',
click: () => this.sendMessage('showFingerprintPhrase'),
enabled: this._isAuthenticated,
};
}
private get fingerprintPhrase(): MenuItemConstructorOptions {
return {
label: this.localize("fingerprintPhrase"),
id: "fingerprintPhrase",
click: () => this.sendMessage("showFingerprintPhrase"),
enabled: this._isAuthenticated,
};
}
private localize(s: string) {
return this._i18nService.t(s);
}
private localize(s: string) {
return this._i18nService.t(s);
}
private sendMessage(message: string, args?: any) {
this._messagingService.send(message, args);
}
private sendMessage(message: string, args?: any) {
this._messagingService.send(message, args);
}
}

View File

@@ -1,237 +1,229 @@
import {
BrowserWindow,
dialog,
MenuItem,
MenuItemConstructorOptions,
} from 'electron';
import { BrowserWindow, dialog, MenuItem, MenuItemConstructorOptions } from "electron";
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { I18nService } from "jslib-common/abstractions/i18n.service";
import { MessagingService } from "jslib-common/abstractions/messaging.service";
import { UpdaterMain } from 'jslib-electron/updater.main';
import { isMacAppStore, isSnapStore, isWindowsStore } from 'jslib-electron/utils';
import { UpdaterMain } from "jslib-electron/updater.main";
import { isMacAppStore, isSnapStore, isWindowsStore } from "jslib-electron/utils";
import { IMenubarMenu } from './menubar';
import { IMenubarMenu } from "./menubar";
import { MenuAccount } from './menu.updater';
import { MenuAccount } from "./menu.updater";
// AKA: "FirstMenu" or "MacMenu" - the first menu that shows on all macOs apps
export class BitwardenMenu implements IMenubarMenu {
readonly id: string = 'bitwarden';
readonly label: string = 'Bitwarden';
readonly id: string = "bitwarden";
readonly label: string = "Bitwarden";
get items(): MenuItemConstructorOptions[] {
return [
this.aboutBitwarden,
this.checkForUpdates,
this.separator,
this.settings,
this.lock,
this.lockAll,
this.logOut,
this.services,
this.separator,
this.hideBitwarden,
this.hideOthers,
this.showAll,
this.separator,
this.quitBitwarden,
];
get items(): MenuItemConstructorOptions[] {
return [
this.aboutBitwarden,
this.checkForUpdates,
this.separator,
this.settings,
this.lock,
this.lockAll,
this.logOut,
this.services,
this.separator,
this.hideBitwarden,
this.hideOthers,
this.showAll,
this.separator,
this.quitBitwarden,
];
}
private readonly _i18nService: I18nService;
private readonly _updater: UpdaterMain;
private readonly _messagingService: MessagingService;
private readonly _accounts: { [userId: string]: MenuAccount };
private readonly _window: BrowserWindow;
constructor(
i18nService: I18nService,
messagingService: MessagingService,
updater: UpdaterMain,
window: BrowserWindow,
accounts: { [userId: string]: MenuAccount }
) {
this._i18nService = i18nService;
this._updater = updater;
this._messagingService = messagingService;
this._window = window;
this._accounts = accounts;
}
private get hasAccounts(): boolean {
return this._accounts != null && Object.keys(this._accounts).length > 0;
}
private get aboutBitwarden(): MenuItemConstructorOptions {
return {
id: "aboutBitwarden",
label: this.localize("aboutBitwarden"),
role: "about",
visible: isMacAppStore(),
};
}
private get checkForUpdates(): MenuItemConstructorOptions {
return {
id: "checkForUpdates",
label: this.localize("checkForUpdates"),
click: (menuItem) => this.checkForUpdate(menuItem),
visible: !isMacAppStore() && !isWindowsStore() && !isSnapStore(),
};
}
private get separator(): MenuItemConstructorOptions {
return {
type: "separator",
};
}
private get settings(): MenuItemConstructorOptions {
return {
id: "settings",
label: this.localize(process.platform === "darwin" ? "preferences" : "settings"),
click: () => this.sendMessage("openSettings"),
accelerator: "CmdOrCtrl+,",
};
}
private get lock(): MenuItemConstructorOptions {
return {
id: "lock",
label: this.localize("lockVault"),
submenu: this.lockSubmenu,
enabled: this.hasAccounts,
};
}
private get lockSubmenu(): MenuItemConstructorOptions[] {
const value: MenuItemConstructorOptions[] = [];
for (const userId in this._accounts) {
if (userId == null) {
continue;
}
value.push({
label: this._accounts[userId].email,
id: `lockNow_${this._accounts[userId].userId}`,
click: () => this.sendMessage("lockVault", { userId: this._accounts[userId].userId }),
enabled: !this._accounts[userId].isLocked,
visible: this._accounts[userId].isAuthenticated,
});
}
return value;
}
private readonly _i18nService: I18nService;
private readonly _updater: UpdaterMain;
private readonly _messagingService: MessagingService;
private readonly _accounts: { [userId: string]: MenuAccount };
private readonly _window: BrowserWindow;
private get lockAll(): MenuItemConstructorOptions {
return {
id: "lockAllNow",
label: this.localize("lockAllVaults"),
click: () => this.sendMessage("lockAllVaults"),
accelerator: "CmdOrCtrl+L",
enabled: this.hasAccounts,
};
}
constructor(
i18nService: I18nService,
messagingService: MessagingService,
updater: UpdaterMain,
window: BrowserWindow,
accounts: { [userId: string]: MenuAccount },
) {
this._i18nService = i18nService;
this._updater = updater;
this._messagingService = messagingService;
this._window = window;
this._accounts = accounts;
private get logOut(): MenuItemConstructorOptions {
return {
id: "logOut",
label: this.localize("logOut"),
submenu: this.logOutSubmenu,
enabled: this.hasAccounts,
};
}
private get logOutSubmenu(): MenuItemConstructorOptions[] {
const value: MenuItemConstructorOptions[] = [];
for (const userId in this._accounts) {
if (userId == null) {
continue;
}
value.push({
label: this._accounts[userId].email,
id: `logOut_${this._accounts[userId].userId}`,
click: async () => {
const result = await dialog.showMessageBox(this._window, {
title: this.localize("logOut"),
message: this.localize("logOut"),
detail: this.localize("logOutConfirmation"),
buttons: [this.localize("logOut"), this.localize("cancel")],
cancelId: 1,
defaultId: 0,
noLink: true,
});
if (result.response === 0) {
this.sendMessage("logout", { userId: this._accounts[userId].userId });
}
},
visible: this._accounts[userId].isAuthenticated,
});
}
return value;
}
private get hasAccounts(): boolean {
return this._accounts != null && Object.keys(this._accounts).length > 0;
}
private get services(): MenuItemConstructorOptions {
return {
id: "services",
label: this.localize("services"),
role: "services",
submenu: [],
visible: isMacAppStore(),
};
}
private get aboutBitwarden(): MenuItemConstructorOptions {
return {
id: 'aboutBitwarden',
label: this.localize('aboutBitwarden'),
role: 'about',
visible: isMacAppStore(),
};
}
private get hideBitwarden(): MenuItemConstructorOptions {
return {
id: "hideBitwarden",
label: this.localize("hideBitwarden"),
role: "hide",
visible: isMacAppStore(),
};
}
private get checkForUpdates(): MenuItemConstructorOptions {
return {
id: 'checkForUpdates',
label: this.localize('checkForUpdates'),
click: menuItem => this.checkForUpdate(menuItem),
visible: !isMacAppStore() && !isWindowsStore() && !isSnapStore(),
};
}
private get hideOthers(): MenuItemConstructorOptions {
return {
id: "hideOthers",
label: this.localize("hideOthers"),
role: "hideOthers",
visible: isMacAppStore(),
};
}
private get separator(): MenuItemConstructorOptions {
return {
type: 'separator',
};
}
private get showAll(): MenuItemConstructorOptions {
return {
id: "showAll",
label: this.localize("showAll"),
role: "unhide",
visible: isMacAppStore(),
};
}
private get settings(): MenuItemConstructorOptions {
return {
id: 'settings',
label: this.localize(process.platform === 'darwin' ?
'preferences' :
'settings'
),
click: () => this.sendMessage('openSettings'),
accelerator: 'CmdOrCtrl+,',
};
}
private get quitBitwarden(): MenuItemConstructorOptions {
return {
id: "quitBitwarden",
label: this.localize("quitBitwarden"),
role: "quit",
visible: isMacAppStore(),
};
}
private get lock(): MenuItemConstructorOptions {
return {
id: 'lock',
label: this.localize('lockVault'),
submenu: this.lockSubmenu,
enabled: this.hasAccounts,
};
}
private localize(s: string) {
return this._i18nService.t(s);
}
private get lockSubmenu(): MenuItemConstructorOptions[] {
const value: MenuItemConstructorOptions[] = [];
for (const userId in this._accounts) {
if (userId == null) {
continue;
}
private async checkForUpdate(menuItem: MenuItem) {
menuItem.enabled = false;
this._updater.checkForUpdate(true);
menuItem.enabled = true;
}
value.push({
label: this._accounts[userId].email,
id: `lockNow_${this._accounts[userId].userId}`,
click: () => this.sendMessage('lockVault', { userId: this._accounts[userId].userId }),
enabled: !this._accounts[userId].isLocked,
visible: this._accounts[userId].isAuthenticated,
});
}
return value;
}
private get lockAll(): MenuItemConstructorOptions {
return {
id: 'lockAllNow',
label: this.localize('lockAllVaults'),
click: () => this.sendMessage('lockAllVaults'),
accelerator: 'CmdOrCtrl+L',
enabled: this.hasAccounts,
};
}
private get logOut(): MenuItemConstructorOptions {
return {
id: 'logOut',
label: this.localize('logOut'),
submenu: this.logOutSubmenu,
enabled: this.hasAccounts,
};
}
private get logOutSubmenu(): MenuItemConstructorOptions[] {
const value: MenuItemConstructorOptions[] = [];
for (const userId in this._accounts) {
if (userId == null) {
continue;
}
value.push({
label: this._accounts[userId].email,
id: `logOut_${this._accounts[userId].userId}`,
click: async () => {
const result = await dialog.showMessageBox(this._window, {
title: this.localize('logOut'),
message: this.localize('logOut'),
detail: this.localize('logOutConfirmation'),
buttons: [this.localize('logOut'), this.localize('cancel')],
cancelId: 1,
defaultId: 0,
noLink: true,
});
if (result.response === 0) {
this.sendMessage('logout', { userId: this._accounts[userId].userId });
}
},
visible: this._accounts[userId].isAuthenticated,
});
}
return value;
}
private get services(): MenuItemConstructorOptions {
return {
id: 'services',
label: this.localize('services'),
role: 'services',
submenu: [],
visible: isMacAppStore(),
};
}
private get hideBitwarden(): MenuItemConstructorOptions {
return {
id: 'hideBitwarden',
label: this.localize('hideBitwarden'),
role: 'hide',
visible: isMacAppStore(),
};
}
private get hideOthers(): MenuItemConstructorOptions {
return {
id: 'hideOthers',
label: this.localize('hideOthers'),
role: 'hideOthers',
visible: isMacAppStore(),
};
}
private get showAll(): MenuItemConstructorOptions {
return {
id: 'showAll',
label: this.localize('showAll'),
role: 'unhide',
visible: isMacAppStore(),
};
}
private get quitBitwarden(): MenuItemConstructorOptions {
return {
id: 'quitBitwarden',
label: this.localize('quitBitwarden'),
role: 'quit',
visible: isMacAppStore(),
};
}
private localize(s: string) {
return this._i18nService.t(s);
}
private async checkForUpdate(menuItem: MenuItem) {
menuItem.enabled = false;
this._updater.checkForUpdate(true);
menuItem.enabled = true;
}
private sendMessage(message: string, args?: any) {
this._messagingService.send(message, args);
}
private sendMessage(message: string, args?: any) {
this._messagingService.send(message, args);
}
}

View File

@@ -1,134 +1,134 @@
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { I18nService } from "jslib-common/abstractions/i18n.service";
import { MessagingService } from "jslib-common/abstractions/messaging.service";
import { IMenubarMenu } from './menubar';
import { IMenubarMenu } from "./menubar";
import { MenuItemConstructorOptions } from 'electron';
import { MenuItemConstructorOptions } from "electron";
export class EditMenu implements IMenubarMenu {
readonly id: string = 'editMenu';
readonly id: string = "editMenu";
get label(): string {
return this.localize('edit');
}
get label(): string {
return this.localize("edit");
}
get items(): MenuItemConstructorOptions[] {
return [
this.undo,
this.redo,
this.separator,
this.cut,
this.copy,
this.paste,
this.separator,
this.selectAll,
this.separator,
this.copyUsername,
this.copyPassword,
this.copyVerificationCodeTotp,
];
}
get items(): MenuItemConstructorOptions[] {
return [
this.undo,
this.redo,
this.separator,
this.cut,
this.copy,
this.paste,
this.separator,
this.selectAll,
this.separator,
this.copyUsername,
this.copyPassword,
this.copyVerificationCodeTotp,
];
}
private readonly _i18nService: I18nService;
private readonly _messagingService: MessagingService;
private readonly _isAuthenticated: boolean;
private readonly _i18nService: I18nService;
private readonly _messagingService: MessagingService;
private readonly _isAuthenticated: boolean;
constructor(
i18nService: I18nService,
messagingService: MessagingService,
isAuthenticated: boolean,
) {
this._i18nService = i18nService;
this._messagingService = messagingService;
this._isAuthenticated = isAuthenticated;
}
constructor(
i18nService: I18nService,
messagingService: MessagingService,
isAuthenticated: boolean
) {
this._i18nService = i18nService;
this._messagingService = messagingService;
this._isAuthenticated = isAuthenticated;
}
private get undo(): MenuItemConstructorOptions {
return {
id: 'undo',
label: this.localize('undo'),
role: 'undo',
};
}
private get undo(): MenuItemConstructorOptions {
return {
id: "undo",
label: this.localize("undo"),
role: "undo",
};
}
private get redo(): MenuItemConstructorOptions {
return {
id: 'redo',
label: this.localize('redo'),
role: 'redo',
};
}
private get redo(): MenuItemConstructorOptions {
return {
id: "redo",
label: this.localize("redo"),
role: "redo",
};
}
private get separator(): MenuItemConstructorOptions {
return { type: 'separator' };
}
private get separator(): MenuItemConstructorOptions {
return { type: "separator" };
}
private get cut(): MenuItemConstructorOptions {
return {
id: 'cut',
label: this.localize('cut'),
role: 'cut',
};
}
private get cut(): MenuItemConstructorOptions {
return {
id: "cut",
label: this.localize("cut"),
role: "cut",
};
}
private get copy(): MenuItemConstructorOptions {
return {
id: 'copy',
label: this.localize('copy'),
role: 'copy',
};
}
private get copy(): MenuItemConstructorOptions {
return {
id: "copy",
label: this.localize("copy"),
role: "copy",
};
}
private get paste(): MenuItemConstructorOptions {
return {
id: 'paste',
label: this.localize('paste'),
role: 'paste',
};
}
private get paste(): MenuItemConstructorOptions {
return {
id: "paste",
label: this.localize("paste"),
role: "paste",
};
}
private get selectAll(): MenuItemConstructorOptions {
return {
id: 'selectAll',
label: this.localize('selectAll'),
role: 'selectAll',
};
}
private get selectAll(): MenuItemConstructorOptions {
return {
id: "selectAll",
label: this.localize("selectAll"),
role: "selectAll",
};
}
private get copyUsername(): MenuItemConstructorOptions {
return {
label: this.localize('copyUsername'),
id: 'copyUsername',
click: () => this.sendMessage('copyUsername'),
accelerator: 'CmdOrCtrl+U',
enabled: this._isAuthenticated,
};
}
private get copyUsername(): MenuItemConstructorOptions {
return {
label: this.localize("copyUsername"),
id: "copyUsername",
click: () => this.sendMessage("copyUsername"),
accelerator: "CmdOrCtrl+U",
enabled: this._isAuthenticated,
};
}
private get copyPassword(): MenuItemConstructorOptions {
return {
label: this.localize('copyPassword'),
id: 'copyPassword',
click: () => this.sendMessage('copyPassword'),
accelerator: 'CmdOrCtrl+P',
enabled: this._isAuthenticated,
};
}
private get copyPassword(): MenuItemConstructorOptions {
return {
label: this.localize("copyPassword"),
id: "copyPassword",
click: () => this.sendMessage("copyPassword"),
accelerator: "CmdOrCtrl+P",
enabled: this._isAuthenticated,
};
}
private get copyVerificationCodeTotp(): MenuItemConstructorOptions {
return {
label: this.localize('copyVerificationCodeTotp'),
id: 'copyTotp',
click: () => this.sendMessage('copyTotp'),
accelerator: 'CmdOrCtrl+T',
};
}
private get copyVerificationCodeTotp(): MenuItemConstructorOptions {
return {
label: this.localize("copyVerificationCodeTotp"),
id: "copyTotp",
click: () => this.sendMessage("copyTotp"),
accelerator: "CmdOrCtrl+T",
};
}
private localize(s: string) {
return this._i18nService.t(s);
}
private localize(s: string) {
return this._i18nService.t(s);
}
private sendMessage(message: string) {
this._messagingService.send(message);
}
private sendMessage(message: string) {
this._messagingService.send(message);
}
}

View File

@@ -1,134 +1,134 @@
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { I18nService } from "jslib-common/abstractions/i18n.service";
import { MessagingService } from "jslib-common/abstractions/messaging.service";
import { isMacAppStore } from 'jslib-electron/utils';
import { isMacAppStore } from "jslib-electron/utils";
import { IMenubarMenu } from './menubar';
import { IMenubarMenu } from "./menubar";
import { MenuItemConstructorOptions } from 'electron';
import { MenuItemConstructorOptions } from "electron";
export class FileMenu implements IMenubarMenu {
readonly id: string = 'fileMenu';
readonly id: string = "fileMenu";
get label(): string {
return this.localize('file');
}
get label(): string {
return this.localize("file");
}
get items(): MenuItemConstructorOptions[] {
return [
this.addNewLogin,
this.addNewItem,
this.addNewFolder,
this.separator,
this.syncVault,
this.exportVault,
this.quitBitwarden,
];
}
get items(): MenuItemConstructorOptions[] {
return [
this.addNewLogin,
this.addNewItem,
this.addNewFolder,
this.separator,
this.syncVault,
this.exportVault,
this.quitBitwarden,
];
}
private readonly _i18nService: I18nService;
private readonly _messagingService: MessagingService;
private readonly _isAuthenticated: boolean;
private readonly _i18nService: I18nService;
private readonly _messagingService: MessagingService;
private readonly _isAuthenticated: boolean;
constructor(
i18nService: I18nService,
messagingService: MessagingService,
isAuthenticated: boolean,
) {
this._i18nService = i18nService;
this._messagingService = messagingService;
this._isAuthenticated = isAuthenticated;
}
constructor(
i18nService: I18nService,
messagingService: MessagingService,
isAuthenticated: boolean
) {
this._i18nService = i18nService;
this._messagingService = messagingService;
this._isAuthenticated = isAuthenticated;
}
private get addNewLogin(): MenuItemConstructorOptions {
return {
label: this.localize('addNewLogin'),
click: () => this.sendMessage('newLogin'),
accelerator: 'CmdOrCtrl+N',
id: 'addNewLogin',
};
}
private get addNewLogin(): MenuItemConstructorOptions {
return {
label: this.localize("addNewLogin"),
click: () => this.sendMessage("newLogin"),
accelerator: "CmdOrCtrl+N",
id: "addNewLogin",
};
}
private get addNewItem(): MenuItemConstructorOptions {
return {
label: this.localize('addNewItem'),
id: 'addNewItem',
submenu: this.addNewItemSubmenu,
enabled: this._isAuthenticated,
};
}
private get addNewItem(): MenuItemConstructorOptions {
return {
label: this.localize("addNewItem"),
id: "addNewItem",
submenu: this.addNewItemSubmenu,
enabled: this._isAuthenticated,
};
}
private get addNewItemSubmenu(): MenuItemConstructorOptions[] {
return [
{
id: 'typeLogin',
label: this.localize('typeLogin'),
click: () => this.sendMessage('newLogin'),
accelerator: 'CmdOrCtrl+Shift+L',
},
{
id: 'typeCard',
label: this.localize('typeCard'),
click: () => this.sendMessage('newCard'),
accelerator: 'CmdOrCtrl+Shift+C',
},
{
id: 'typeIdentity',
label: this.localize('typeIdentity'),
click: () => this.sendMessage('newIdentity'),
accelerator: 'CmdOrCtrl+Shift+I',
},
{
id: 'typeSecureNote',
label: this.localize('typeSecureNote'),
click: () => this.sendMessage('newSecureNote'),
accelerator: 'CmdOrCtrl+Shift+S',
},
];
}
private get addNewItemSubmenu(): MenuItemConstructorOptions[] {
return [
{
id: "typeLogin",
label: this.localize("typeLogin"),
click: () => this.sendMessage("newLogin"),
accelerator: "CmdOrCtrl+Shift+L",
},
{
id: "typeCard",
label: this.localize("typeCard"),
click: () => this.sendMessage("newCard"),
accelerator: "CmdOrCtrl+Shift+C",
},
{
id: "typeIdentity",
label: this.localize("typeIdentity"),
click: () => this.sendMessage("newIdentity"),
accelerator: "CmdOrCtrl+Shift+I",
},
{
id: "typeSecureNote",
label: this.localize("typeSecureNote"),
click: () => this.sendMessage("newSecureNote"),
accelerator: "CmdOrCtrl+Shift+S",
},
];
}
private get addNewFolder(): MenuItemConstructorOptions {
return {
id: 'addNewFolder',
label: this.localize('addNewFolder'),
click: () => this.sendMessage('newFolder'),
};
}
private get addNewFolder(): MenuItemConstructorOptions {
return {
id: "addNewFolder",
label: this.localize("addNewFolder"),
click: () => this.sendMessage("newFolder"),
};
}
private get separator(): MenuItemConstructorOptions {
return { type: 'separator' };
}
private get separator(): MenuItemConstructorOptions {
return { type: "separator" };
}
private get syncVault(): MenuItemConstructorOptions {
return {
id: 'syncVault',
label: this.localize('syncVault'),
click: () => this.sendMessage('syncVault'),
};
}
private get syncVault(): MenuItemConstructorOptions {
return {
id: "syncVault",
label: this.localize("syncVault"),
click: () => this.sendMessage("syncVault"),
};
}
private get exportVault(): MenuItemConstructorOptions {
return {
id: 'exportVault',
label: this.localize('exportVault'),
click: () => this.sendMessage('exportVault'),
};
}
private get exportVault(): MenuItemConstructorOptions {
return {
id: "exportVault",
label: this.localize("exportVault"),
click: () => this.sendMessage("exportVault"),
};
}
private get quitBitwarden(): MenuItemConstructorOptions {
return {
id: 'quitBitwarden',
label: this.localize('quitBitwarden'),
visible: !isMacAppStore(),
role: 'quit',
};
}
private get quitBitwarden(): MenuItemConstructorOptions {
return {
id: "quitBitwarden",
label: this.localize("quitBitwarden"),
visible: !isMacAppStore(),
role: "quit",
};
}
private localize(s: string) {
return this._i18nService.t(s);
}
private localize(s: string) {
return this._i18nService.t(s);
}
private sendMessage(message: string) {
this._messagingService.send(message);
}
private sendMessage(message: string) {
this._messagingService.send(message);
}
}

View File

@@ -1,223 +1,228 @@
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { IMenubarMenu } from './menubar';
import { I18nService } from "jslib-common/abstractions/i18n.service";
import { IMenubarMenu } from "./menubar";
import { shell } from 'electron';
import { shell } from "electron";
import { isMacAppStore, isWindowsStore } from 'jslib-electron/utils';
import { isMacAppStore, isWindowsStore } from "jslib-electron/utils";
import { MenuItemConstructorOptions } from 'electron';
import { MenuItemConstructorOptions } from "electron";
export class HelpMenu implements IMenubarMenu {
readonly id: string = 'help';
readonly id: string = "help";
get label(): string {
return this.localize('help');
}
get label(): string {
return this.localize("help");
}
get items(): MenuItemConstructorOptions[] {
return [
this.emailUs,
this.visitOurWebsite,
this.fileBugReport,
this.legal,
this.separator,
this.followUs,
this.separator,
this.goToWebVault,
this.separator,
this.getMobileApp,
this.getBrowserExtension,
];
}
get items(): MenuItemConstructorOptions[] {
return [
this.emailUs,
this.visitOurWebsite,
this.fileBugReport,
this.legal,
this.separator,
this.followUs,
this.separator,
this.goToWebVault,
this.separator,
this.getMobileApp,
this.getBrowserExtension,
];
}
private readonly _i18nService: I18nService;
private readonly _webVaultUrl: string;
private readonly _i18nService: I18nService;
private readonly _webVaultUrl: string;
constructor(
i18nService: I18nService,
webVaultUrl: string
) {
this._i18nService = i18nService;
this._webVaultUrl = webVaultUrl;
}
constructor(i18nService: I18nService, webVaultUrl: string) {
this._i18nService = i18nService;
this._webVaultUrl = webVaultUrl;
}
private get emailUs(): MenuItemConstructorOptions {
return {
id: 'emailUs',
label: this.localize('emailUs'),
click: () => shell.openExternal('mailTo:hello@bitwarden.com'),
};
}
private get emailUs(): MenuItemConstructorOptions {
return {
id: "emailUs",
label: this.localize("emailUs"),
click: () => shell.openExternal("mailTo:hello@bitwarden.com"),
};
}
private get visitOurWebsite(): MenuItemConstructorOptions {
return {
id: 'visitOurWebsite',
label: this.localize('visitOurWebsite'),
click: () => shell.openExternal('https://bitwarden.com/contact'),
};
}
private get visitOurWebsite(): MenuItemConstructorOptions {
return {
id: "visitOurWebsite",
label: this.localize("visitOurWebsite"),
click: () => shell.openExternal("https://bitwarden.com/contact"),
};
}
private get fileBugReport(): MenuItemConstructorOptions {
return {
id: 'fileBugReport',
label: this.localize('fileBugReport'),
click: () => shell.openExternal('https://github.com/bitwarden/desktop/issues'),
};
}
private get fileBugReport(): MenuItemConstructorOptions {
return {
id: "fileBugReport",
label: this.localize("fileBugReport"),
click: () => shell.openExternal("https://github.com/bitwarden/desktop/issues"),
};
}
private get legal(): MenuItemConstructorOptions {
return {
id: 'legal',
label: this.localize('legal'),
visible: !isMacAppStore(),
submenu: this.legalSubmenu,
};
}
private get legal(): MenuItemConstructorOptions {
return {
id: "legal",
label: this.localize("legal"),
visible: !isMacAppStore(),
submenu: this.legalSubmenu,
};
}
private get legalSubmenu(): MenuItemConstructorOptions[] {
return [
{
id: 'termsOfService',
label: this.localize('termsOfService'),
click: () => shell.openExternal('https://bitwarden.com/terms/'),
},
{
id: 'privacyPolicy',
label: this.localize('privacyPolicy'),
click: () => shell.openExternal('https://bitwarden.com/privacy/'),
},
];
}
private get legalSubmenu(): MenuItemConstructorOptions[] {
return [
{
id: "termsOfService",
label: this.localize("termsOfService"),
click: () => shell.openExternal("https://bitwarden.com/terms/"),
},
{
id: "privacyPolicy",
label: this.localize("privacyPolicy"),
click: () => shell.openExternal("https://bitwarden.com/privacy/"),
},
];
}
private get separator(): MenuItemConstructorOptions {
return { type: 'separator' };
}
private get separator(): MenuItemConstructorOptions {
return { type: "separator" };
}
private get followUs(): MenuItemConstructorOptions {
return {
id: 'followUs',
label: this.localize('followUs'),
submenu: this.followUsSubmenu,
};
}
private get followUs(): MenuItemConstructorOptions {
return {
id: "followUs",
label: this.localize("followUs"),
submenu: this.followUsSubmenu,
};
}
private get followUsSubmenu(): MenuItemConstructorOptions[] {
return [
{
id: 'blog',
label: this.localize('blog'),
click: () => shell.openExternal('https://blog.bitwarden.com'),
},
{
id: 'twitter',
label: 'Twitter',
click: () => shell.openExternal('https://twitter.com/bitwarden'),
},
{
id: 'facebook',
label: 'Facebook',
click: () => shell.openExternal('https://www.facebook.com/bitwarden/'),
},
{
id: 'github',
label: 'GitHub',
click: () => shell.openExternal('https://github.com/bitwarden'),
},
];
}
private get followUsSubmenu(): MenuItemConstructorOptions[] {
return [
{
id: "blog",
label: this.localize("blog"),
click: () => shell.openExternal("https://blog.bitwarden.com"),
},
{
id: "twitter",
label: "Twitter",
click: () => shell.openExternal("https://twitter.com/bitwarden"),
},
{
id: "facebook",
label: "Facebook",
click: () => shell.openExternal("https://www.facebook.com/bitwarden/"),
},
{
id: "github",
label: "GitHub",
click: () => shell.openExternal("https://github.com/bitwarden"),
},
];
}
private get goToWebVault(): MenuItemConstructorOptions {
return {
id: 'goToWebVault',
label: this.localize('goToWebVault'),
click: () => shell.openExternal(this._webVaultUrl),
};
}
private get goToWebVault(): MenuItemConstructorOptions {
return {
id: "goToWebVault",
label: this.localize("goToWebVault"),
click: () => shell.openExternal(this._webVaultUrl),
};
}
private get getMobileApp(): MenuItemConstructorOptions {
return {
id: 'getMobileApp',
label: this.localize('getMobileApp'),
visible: !isWindowsStore(),
submenu: this.getMobileAppSubmenu,
};
}
private get getMobileApp(): MenuItemConstructorOptions {
return {
id: "getMobileApp",
label: this.localize("getMobileApp"),
visible: !isWindowsStore(),
submenu: this.getMobileAppSubmenu,
};
}
private get getMobileAppSubmenu(): MenuItemConstructorOptions[] {
return [
{
id: 'iOS',
label: 'iOS',
click: () => {
shell.openExternal('https://itunes.apple.com/app/' +
'bitwarden-free-password-manager/id1137397744?mt=8');
},
},
{
id: 'android',
label: 'Android',
click: () => {
shell.openExternal('https://play.google.com/store/apps/' +
'details?id=com.x8bit.bitwarden');
},
},
];
}
private get getMobileAppSubmenu(): MenuItemConstructorOptions[] {
return [
{
id: "iOS",
label: "iOS",
click: () => {
shell.openExternal(
"https://itunes.apple.com/app/" + "bitwarden-free-password-manager/id1137397744?mt=8"
);
},
},
{
id: "android",
label: "Android",
click: () => {
shell.openExternal(
"https://play.google.com/store/apps/" + "details?id=com.x8bit.bitwarden"
);
},
},
];
}
private get getBrowserExtension(): MenuItemConstructorOptions {
return {
id: 'getBrowserExtension',
label: this.localize('getBrowserExtension'),
visible: !isWindowsStore(),
submenu: this.getBrowserExtensionSubmenu,
};
}
private get getBrowserExtension(): MenuItemConstructorOptions {
return {
id: "getBrowserExtension",
label: this.localize("getBrowserExtension"),
visible: !isWindowsStore(),
submenu: this.getBrowserExtensionSubmenu,
};
}
private get getBrowserExtensionSubmenu(): MenuItemConstructorOptions[] {
return [
{
id: 'chrome',
label: 'Chrome',
click: () => {
shell.openExternal('https://chrome.google.com/webstore/detail/' +
'bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb');
},
},
{
id: 'firefox',
label: 'Firefox',
click: () => {
shell.openExternal('https://addons.mozilla.org/firefox/addon/' +
'bitwarden-password-manager/');
},
},
{
id: 'firefox',
label: 'Opera',
click: () => {
shell.openExternal('https://addons.opera.com/extensions/details/' +
'bitwarden-free-password-manager/');
},
},
{
id: 'firefox',
label: 'Edge',
click: () => {
shell.openExternal('https://microsoftedge.microsoft.com/addons/' +
'detail/jbkfoedolllekgbhcbcoahefnbanhhlh');
},
},
{
id: 'safari',
label: 'Safari',
click: () => {
shell.openExternal('https://bitwarden.com/download/');
},
},
];
}
private get getBrowserExtensionSubmenu(): MenuItemConstructorOptions[] {
return [
{
id: "chrome",
label: "Chrome",
click: () => {
shell.openExternal(
"https://chrome.google.com/webstore/detail/" +
"bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb"
);
},
},
{
id: "firefox",
label: "Firefox",
click: () => {
shell.openExternal(
"https://addons.mozilla.org/firefox/addon/" + "bitwarden-password-manager/"
);
},
},
{
id: "firefox",
label: "Opera",
click: () => {
shell.openExternal(
"https://addons.opera.com/extensions/details/" + "bitwarden-free-password-manager/"
);
},
},
{
id: "firefox",
label: "Edge",
click: () => {
shell.openExternal(
"https://microsoftedge.microsoft.com/addons/" +
"detail/jbkfoedolllekgbhcbcoahefnbanhhlh"
);
},
},
{
id: "safari",
label: "Safari",
click: () => {
shell.openExternal("https://bitwarden.com/download/");
},
},
];
}
private localize(s: string) {
return this._i18nService.t(s);
}
private localize(s: string) {
return this._i18nService.t(s);
}
}

View File

@@ -1,54 +1,52 @@
import {
app,
Menu,
} from 'electron';
import { app, Menu } from "electron";
import { Main } from '../main';
import { Main } from "../main";
import { BaseMenu } from 'jslib-electron/baseMenu';
import { BaseMenu } from "jslib-electron/baseMenu";
import { MenuUpdateRequest } from './menu.updater';
import { Menubar } from './menubar';
import { MenuUpdateRequest } from "./menu.updater";
import { Menubar } from "./menubar";
const cloudWebVaultUrl: string = 'https://vault.bitwarden.com';
const cloudWebVaultUrl: string = "https://vault.bitwarden.com";
export class MenuMain extends BaseMenu {
constructor(private main: Main) {
super(main.i18nService, main.windowMain);
}
constructor(private main: Main) {
super(main.i18nService, main.windowMain);
}
async init() {
this.initContextMenu();
await this.setMenu();
}
async init() {
this.initContextMenu();
await this.setMenu();
}
async updateApplicationMenuState(updateRequest: MenuUpdateRequest) {
await this.setMenu(updateRequest);
}
async updateApplicationMenuState(updateRequest: MenuUpdateRequest) {
await this.setMenu(updateRequest);
}
private async setMenu(updateRequest?: MenuUpdateRequest) {
Menu.setApplicationMenu(new Menubar(
this.main.i18nService,
this.main.messagingService,
this.main.updaterMain,
this.windowMain,
await this.getWebVaultUrl(),
app.getVersion(),
updateRequest,
).menu);
}
private async setMenu(updateRequest?: MenuUpdateRequest) {
Menu.setApplicationMenu(
new Menubar(
this.main.i18nService,
this.main.messagingService,
this.main.updaterMain,
this.windowMain,
await this.getWebVaultUrl(),
app.getVersion(),
updateRequest
).menu
);
}
private async getWebVaultUrl() {
let webVaultUrl = cloudWebVaultUrl;
const urlsObj: any = await this.main.stateService.getEnvironmentUrls();
if (urlsObj != null) {
if (urlsObj.base != null) {
webVaultUrl = urlsObj.base;
} else if (urlsObj.webVault != null) {
webVaultUrl = urlsObj.webVault;
}
}
return webVaultUrl;
private async getWebVaultUrl() {
let webVaultUrl = cloudWebVaultUrl;
const urlsObj: any = await this.main.stateService.getEnvironmentUrls();
if (urlsObj != null) {
if (urlsObj.base != null) {
webVaultUrl = urlsObj.base;
} else if (urlsObj.webVault != null) {
webVaultUrl = urlsObj.webVault;
}
}
return webVaultUrl;
}
}

View File

@@ -1,12 +1,12 @@
export class MenuUpdateRequest {
hideChangeMasterPassword: boolean;
activeUserId: string;
accounts: { [userId: string]: MenuAccount };
hideChangeMasterPassword: boolean;
activeUserId: string;
accounts: { [userId: string]: MenuAccount };
}
export class MenuAccount {
isAuthenticated: boolean;
isLocked: boolean;
userId: string;
email: string;
isAuthenticated: boolean;
isLocked: boolean;
userId: string;
email: string;
}

View File

@@ -1,140 +1,139 @@
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { I18nService } from "jslib-common/abstractions/i18n.service";
import { MessagingService } from "jslib-common/abstractions/messaging.service";
import { IMenubarMenu } from './menubar';
import { IMenubarMenu } from "./menubar";
import { MenuItemConstructorOptions } from 'electron';
import { MenuItemConstructorOptions } from "electron";
export class ViewMenu implements IMenubarMenu {
readonly id: 'viewMenu';
readonly id: "viewMenu";
get label(): string {
return this.localize('view');
}
get label(): string {
return this.localize("view");
}
get items(): MenuItemConstructorOptions[] {
return [
this.searchVault,
this.separator,
this.passwordGenerator,
this.passwordHistory,
this.separator,
this.zoomIn,
this.zoomOut,
this.resetZoom,
this.separator,
this.toggleFullscreen,
this.separator,
this.reload,
this.toggleDevTools,
];
}
get items(): MenuItemConstructorOptions[] {
return [
this.searchVault,
this.separator,
this.passwordGenerator,
this.passwordHistory,
this.separator,
this.zoomIn,
this.zoomOut,
this.resetZoom,
this.separator,
this.toggleFullscreen,
this.separator,
this.reload,
this.toggleDevTools,
];
}
private readonly _i18nService: I18nService;
private readonly _messagingService: MessagingService;
private readonly _isAuthenticated: boolean;
private readonly _i18nService: I18nService;
private readonly _messagingService: MessagingService;
private readonly _isAuthenticated: boolean;
constructor(
i18nService: I18nService,
messagingService: MessagingService,
isAuthenticated: boolean,
)
{
this._i18nService = i18nService;
this._messagingService = messagingService;
this._isAuthenticated = isAuthenticated;
}
constructor(
i18nService: I18nService,
messagingService: MessagingService,
isAuthenticated: boolean
) {
this._i18nService = i18nService;
this._messagingService = messagingService;
this._isAuthenticated = isAuthenticated;
}
private get searchVault(): MenuItemConstructorOptions {
return {
id: 'searchVault',
label: this.localize('searchVault'),
click: () => this.sendMessage('focusSearch'),
accelerator: 'CmdOrCtrl+F',
enabled: this._isAuthenticated,
};
}
private get searchVault(): MenuItemConstructorOptions {
return {
id: "searchVault",
label: this.localize("searchVault"),
click: () => this.sendMessage("focusSearch"),
accelerator: "CmdOrCtrl+F",
enabled: this._isAuthenticated,
};
}
private get separator(): MenuItemConstructorOptions {
return { type: 'separator' };
}
private get separator(): MenuItemConstructorOptions {
return { type: "separator" };
}
private get passwordGenerator(): MenuItemConstructorOptions {
return {
id: 'passwordGenerator',
label: this.localize('passwordGenerator'),
click: () => this.sendMessage('openPasswordGenerator'),
accelerator: 'CmdOrCtrl+G',
enabled: this._isAuthenticated,
};
}
private get passwordGenerator(): MenuItemConstructorOptions {
return {
id: "passwordGenerator",
label: this.localize("passwordGenerator"),
click: () => this.sendMessage("openPasswordGenerator"),
accelerator: "CmdOrCtrl+G",
enabled: this._isAuthenticated,
};
}
private get passwordHistory(): MenuItemConstructorOptions {
return {
id: 'passwordHistory',
label: this.localize('passwordHistory'),
click: () => this.sendMessage('openPasswordHistory'),
enabled: this._isAuthenticated,
};
}
private get passwordHistory(): MenuItemConstructorOptions {
return {
id: "passwordHistory",
label: this.localize("passwordHistory"),
click: () => this.sendMessage("openPasswordHistory"),
enabled: this._isAuthenticated,
};
}
private get zoomIn(): MenuItemConstructorOptions {
return {
id: 'zoomIn',
label: this.localize('zoomIn'),
role: 'zoomIn',
accelerator: 'CmdOrCtrl+=',
};
}
private get zoomIn(): MenuItemConstructorOptions {
return {
id: "zoomIn",
label: this.localize("zoomIn"),
role: "zoomIn",
accelerator: "CmdOrCtrl+=",
};
}
private get zoomOut(): MenuItemConstructorOptions {
return {
id: 'zoomOut',
label: this.localize('zoomOut'),
role: 'zoomOut',
accelerator: 'CmdOrCtrl+-',
};
}
private get zoomOut(): MenuItemConstructorOptions {
return {
id: "zoomOut",
label: this.localize("zoomOut"),
role: "zoomOut",
accelerator: "CmdOrCtrl+-",
};
}
private get resetZoom(): MenuItemConstructorOptions {
return {
id: 'resetZoom',
label: this.localize('resetZoom'),
role: 'resetZoom',
accelerator: 'CmdOrCtrl+0',
};
}
private get resetZoom(): MenuItemConstructorOptions {
return {
id: "resetZoom",
label: this.localize("resetZoom"),
role: "resetZoom",
accelerator: "CmdOrCtrl+0",
};
}
private get toggleFullscreen(): MenuItemConstructorOptions {
return {
id: 'toggleFullScreen',
label: this.localize('toggleFullScreen'),
role: 'togglefullscreen',
};
}
private get toggleFullscreen(): MenuItemConstructorOptions {
return {
id: "toggleFullScreen",
label: this.localize("toggleFullScreen"),
role: "togglefullscreen",
};
}
private get reload(): MenuItemConstructorOptions {
return {
id: 'reload',
label: this.localize('reload'),
role: 'forceReload',
};
}
private get reload(): MenuItemConstructorOptions {
return {
id: "reload",
label: this.localize("reload"),
role: "forceReload",
};
}
private get toggleDevTools(): MenuItemConstructorOptions {
return {
id: 'toggleDevTools',
label: this.localize('toggleDevTools'),
role: 'toggleDevTools',
accelerator: 'F12',
};
}
private get toggleDevTools(): MenuItemConstructorOptions {
return {
id: "toggleDevTools",
label: this.localize("toggleDevTools"),
role: "toggleDevTools",
accelerator: "F12",
};
}
private localize(s: string) {
return this._i18nService.t(s);
}
private localize(s: string) {
return this._i18nService.t(s);
}
private sendMessage(message: string) {
this._messagingService.send(message);
}
private sendMessage(message: string) {
this._messagingService.send(message);
}
}

View File

@@ -1,111 +1,111 @@
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { I18nService } from "jslib-common/abstractions/i18n.service";
import { MessagingService } from "jslib-common/abstractions/messaging.service";
import { isMacAppStore } from 'jslib-electron/utils';
import { WindowMain } from 'jslib-electron/window.main';
import { isMacAppStore } from "jslib-electron/utils";
import { WindowMain } from "jslib-electron/window.main";
import { IMenubarMenu } from './menubar';
import { IMenubarMenu } from "./menubar";
import { MenuItemConstructorOptions } from 'electron';
import { MenuItemConstructorOptions } from "electron";
export class WindowMenu implements IMenubarMenu {
readonly id: string;
readonly id: string;
get label(): string {
return this.localize('window');
}
get label(): string {
return this.localize("window");
}
get items(): MenuItemConstructorOptions[] {
return [
this.minimize,
this.hideToMenu,
this.alwaysOnTop,
this.zoom,
this.separator,
this.bringAllToFront,
this.close,
];
}
get items(): MenuItemConstructorOptions[] {
return [
this.minimize,
this.hideToMenu,
this.alwaysOnTop,
this.zoom,
this.separator,
this.bringAllToFront,
this.close,
];
}
private readonly _i18nService: I18nService;
private readonly _messagingService: MessagingService;
private readonly _window: WindowMain;
private readonly _i18nService: I18nService;
private readonly _messagingService: MessagingService;
private readonly _window: WindowMain;
constructor(
i18nService: I18nService,
messagingService: MessagingService,
windowMain: WindowMain,
) {
this._i18nService = i18nService;
this._messagingService = messagingService;
this._window = windowMain;
}
constructor(
i18nService: I18nService,
messagingService: MessagingService,
windowMain: WindowMain
) {
this._i18nService = i18nService;
this._messagingService = messagingService;
this._window = windowMain;
}
private get minimize(): MenuItemConstructorOptions {
return {
id: 'minimize',
label: this.localize('minimize'),
role: 'minimize',
visible: isMacAppStore(),
};
}
private get minimize(): MenuItemConstructorOptions {
return {
id: "minimize",
label: this.localize("minimize"),
role: "minimize",
visible: isMacAppStore(),
};
}
private get hideToMenu(): MenuItemConstructorOptions {
return {
id: 'hideToMenu',
label: this.localize(isMacAppStore() ? 'hideToMenuBar' : 'hideToTray'),
click: () => this.sendMessage('hideToTray'),
accelerator: 'CmdOrCtrl+Shift+M',
};
}
private get hideToMenu(): MenuItemConstructorOptions {
return {
id: "hideToMenu",
label: this.localize(isMacAppStore() ? "hideToMenuBar" : "hideToTray"),
click: () => this.sendMessage("hideToTray"),
accelerator: "CmdOrCtrl+Shift+M",
};
}
private get alwaysOnTop(): MenuItemConstructorOptions {
return {
id: 'alwaysOnTop',
label: this.localize('alwaysOnTop'),
type: 'checkbox',
checked: this._window.win.isAlwaysOnTop(),
click: () => this._window.toggleAlwaysOnTop(),
accelerator: 'CmdOrCtrl+Shift+T',
};
}
private get alwaysOnTop(): MenuItemConstructorOptions {
return {
id: "alwaysOnTop",
label: this.localize("alwaysOnTop"),
type: "checkbox",
checked: this._window.win.isAlwaysOnTop(),
click: () => this._window.toggleAlwaysOnTop(),
accelerator: "CmdOrCtrl+Shift+T",
};
}
private get zoom(): MenuItemConstructorOptions {
return {
id: 'zoom',
label: this.localize('zoom'),
role: 'zoom',
visible: isMacAppStore(),
};
}
private get zoom(): MenuItemConstructorOptions {
return {
id: "zoom",
label: this.localize("zoom"),
role: "zoom",
visible: isMacAppStore(),
};
}
private get separator(): MenuItemConstructorOptions {
return { type: 'separator' };
}
private get separator(): MenuItemConstructorOptions {
return { type: "separator" };
}
private get bringAllToFront(): MenuItemConstructorOptions {
return {
id: 'bringAllToFront',
label: this.localize('bringAllToFront'),
role: 'front',
visible: isMacAppStore(),
};
}
private get bringAllToFront(): MenuItemConstructorOptions {
return {
id: "bringAllToFront",
label: this.localize("bringAllToFront"),
role: "front",
visible: isMacAppStore(),
};
}
private get close(): MenuItemConstructorOptions {
return {
id: 'close',
label: this.localize('close'),
role: 'close',
visible: isMacAppStore(),
};
}
private get close(): MenuItemConstructorOptions {
return {
id: "close",
label: this.localize("close"),
role: "close",
visible: isMacAppStore(),
};
}
private localize(s: string) {
return this._i18nService.t(s);
}
private localize(s: string) {
return this._i18nService.t(s);
}
private sendMessage(message: string, args?: any) {
this._messagingService.send(message, args);
}
private sendMessage(message: string, args?: any) {
this._messagingService.send(message, args);
}
}

View File

@@ -1,105 +1,90 @@
import {
Menu,
MenuItemConstructorOptions,
} from 'electron';
import { Menu, MenuItemConstructorOptions } from "electron";
import { AboutMenu } from './menu.about';
import { AccountMenu } from './menu.account';
import { BitwardenMenu } from './menu.bitwarden';
import { EditMenu } from './menu.edit';
import { FileMenu } from './menu.file';
import { HelpMenu } from './menu.help';
import { MenuUpdateRequest } from './menu.updater';
import { ViewMenu } from './menu.view';
import { WindowMenu } from './menu.window';
import { AboutMenu } from "./menu.about";
import { AccountMenu } from "./menu.account";
import { BitwardenMenu } from "./menu.bitwarden";
import { EditMenu } from "./menu.edit";
import { FileMenu } from "./menu.file";
import { HelpMenu } from "./menu.help";
import { MenuUpdateRequest } from "./menu.updater";
import { ViewMenu } from "./menu.view";
import { WindowMenu } from "./menu.window";
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { I18nService } from "jslib-common/abstractions/i18n.service";
import { MessagingService } from "jslib-common/abstractions/messaging.service";
import { UpdaterMain } from 'jslib-electron/updater.main';
import { WindowMain } from 'jslib-electron/window.main';
import { UpdaterMain } from "jslib-electron/updater.main";
import { WindowMain } from "jslib-electron/window.main";
export interface IMenubarMenu {
id: string;
label: string;
visible?: boolean; // Assumes true if null
items: MenuItemConstructorOptions[];
id: string;
label: string;
visible?: boolean; // Assumes true if null
items: MenuItemConstructorOptions[];
}
export class Menubar {
private readonly items: IMenubarMenu[];
private readonly items: IMenubarMenu[];
get menu(): Menu {
const template: MenuItemConstructorOptions[] = [];
if (this.items != null) {
this.items.forEach((item: IMenubarMenu) => {
if (item != null) {
template.push({
id: item.id,
label: item.label,
submenu: item.items,
visible: item.visible ?? true,
});
}
});
get menu(): Menu {
const template: MenuItemConstructorOptions[] = [];
if (this.items != null) {
this.items.forEach((item: IMenubarMenu) => {
if (item != null) {
template.push({
id: item.id,
label: item.label,
submenu: item.items,
visible: item.visible ?? true,
});
}
return Menu.buildFromTemplate(template);
});
}
return Menu.buildFromTemplate(template);
}
constructor(
i18nService: I18nService,
messagingService: MessagingService,
updaterMain: UpdaterMain,
windowMain: WindowMain,
webVaultUrl: string,
appVersion: string,
updateRequest?: MenuUpdateRequest,
) {
this.items = [
new BitwardenMenu(
i18nService,
messagingService,
updaterMain,
windowMain.win,
updateRequest?.accounts
),
new FileMenu(
i18nService,
messagingService,
updateRequest?.accounts[updateRequest?.activeUserId]?.isLocked ?? true,
),
new EditMenu(
i18nService,
messagingService,
updateRequest?.accounts[updateRequest?.activeUserId]?.isLocked ?? true,
),
new ViewMenu(
i18nService,
messagingService,
updateRequest?.accounts[updateRequest?.activeUserId]?.isLocked ?? true,
),
new AccountMenu(
i18nService,
messagingService,
webVaultUrl,
windowMain.win,
updateRequest?.accounts[updateRequest?.activeUserId]?.isLocked ?? true,
),
new WindowMenu(
i18nService,
messagingService,
windowMain,
),
new AboutMenu(
i18nService,
appVersion,
windowMain.win,
updaterMain,
),
new HelpMenu(
i18nService,
webVaultUrl,
),
];
}
constructor(
i18nService: I18nService,
messagingService: MessagingService,
updaterMain: UpdaterMain,
windowMain: WindowMain,
webVaultUrl: string,
appVersion: string,
updateRequest?: MenuUpdateRequest
) {
this.items = [
new BitwardenMenu(
i18nService,
messagingService,
updaterMain,
windowMain.win,
updateRequest?.accounts
),
new FileMenu(
i18nService,
messagingService,
updateRequest?.accounts[updateRequest?.activeUserId]?.isLocked ?? true
),
new EditMenu(
i18nService,
messagingService,
updateRequest?.accounts[updateRequest?.activeUserId]?.isLocked ?? true
),
new ViewMenu(
i18nService,
messagingService,
updateRequest?.accounts[updateRequest?.activeUserId]?.isLocked ?? true
),
new AccountMenu(
i18nService,
messagingService,
webVaultUrl,
windowMain.win,
updateRequest?.accounts[updateRequest?.activeUserId]?.isLocked ?? true
),
new WindowMenu(i18nService, messagingService, windowMain),
new AboutMenu(i18nService, appVersion, windowMain.win, updaterMain),
new HelpMenu(i18nService, webVaultUrl),
];
}
}

View File

@@ -1,154 +1,157 @@
import { app, ipcMain } from 'electron';
import * as fs from 'fs';
import * as path from 'path';
import { app, ipcMain } from "electron";
import * as fs from "fs";
import * as path from "path";
import { Main } from '../main';
import { Main } from "../main";
import { StateService } from 'jslib-common/abstractions/state.service';
import { StateService } from "jslib-common/abstractions/state.service";
import { MenuUpdateRequest } from './menu.updater';
import { MenuUpdateRequest } from "./menu.updater";
const SyncInterval = 5 * 60 * 1000; // 5 minutes
export class MessagingMain {
private syncTimeout: NodeJS.Timer;
private syncTimeout: NodeJS.Timer;
constructor(private main: Main, private stateService: StateService) { }
constructor(private main: Main, private stateService: StateService) {}
init() {
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();
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));
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);
}
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;
}
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;
}
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);
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 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]
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')}
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});
}
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 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 linuxStartupFile(): string {
return path.join(app.getPath("home"), ".config", "autostart", "bitwarden.desktop");
}
private setFocus() {
this.main.trayMain.restoreFromTray();
this.main.windowMain.win.focusOnWebView();
}
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,
});
}
private windowIsFocused() {
const windowIsFocused = this.main.windowMain.win.isFocused();
this.main.windowMain.win.webContents.send("messagingService", {
command: "windowIsFocused",
windowIsFocused: windowIsFocused,
});
}
}

View File

@@ -1,263 +1,306 @@
import { existsSync, promises as fs } from 'fs';
import { Socket } from 'net';
import * as ipc from 'node-ipc';
import { homedir, userInfo } from 'os';
import * as path from 'path';
import * as util from 'util';
import { existsSync, promises as fs } from "fs";
import { Socket } from "net";
import * as ipc from "node-ipc";
import { homedir, userInfo } from "os";
import * as path from "path";
import * as util from "util";
import { ipcMain } from 'electron';
import { LogService } from 'jslib-common/abstractions/log.service';
import { WindowMain } from 'jslib-electron/window.main';
import { ipcMain } from "electron";
import { LogService } from "jslib-common/abstractions/log.service";
import { WindowMain } from "jslib-electron/window.main";
export class NativeMessagingMain {
private connected: Socket[] = [];
private socket: any;
private connected: Socket[] = [];
private socket: any;
constructor(private logService: LogService, private windowMain: WindowMain, private userPath: string, private exePath: string) {}
constructor(
private logService: LogService,
private windowMain: WindowMain,
private userPath: string,
private exePath: string
) {}
async listen() {
ipc.config.id = 'bitwarden';
ipc.config.retry = 1500;
if (process.platform === 'darwin') {
if (!existsSync(`${homedir()}/tmp`)) {
await fs.mkdir(`${homedir()}/tmp`);
}
ipc.config.socketRoot = `${homedir()}/tmp/`;
async listen() {
ipc.config.id = "bitwarden";
ipc.config.retry = 1500;
if (process.platform === "darwin") {
if (!existsSync(`${homedir()}/tmp`)) {
await fs.mkdir(`${homedir()}/tmp`);
}
ipc.config.socketRoot = `${homedir()}/tmp/`;
}
ipc.serve(() => {
ipc.server.on("message", (data: any, socket: any) => {
this.socket = socket;
this.windowMain.win.webContents.send("nativeMessaging", data);
});
ipcMain.on("nativeMessagingReply", (event, msg) => {
if (this.socket != null && msg != null) {
this.send(msg, this.socket);
}
});
ipc.server.on("connect", (socket: Socket) => {
this.connected.push(socket);
});
ipc.server.on("socket.disconnected", (socket, destroyedSocketID) => {
const index = this.connected.indexOf(socket);
if (index > -1) {
this.connected.splice(index, 1);
}
ipc.serve(() => {
ipc.server.on('message', (data: any, socket: any) => {
this.socket = socket;
this.windowMain.win.webContents.send('nativeMessaging', data);
});
this.socket = null;
ipc.log("client " + destroyedSocketID + " has disconnected!");
});
});
ipcMain.on('nativeMessagingReply', (event, msg) => {
if (this.socket != null && msg != null) {
this.send(msg, this.socket);
}
});
ipc.server.start();
}
ipc.server.on('connect', (socket: Socket) => {
this.connected.push(socket);
});
stop() {
ipc.server.stop();
// Kill all existing connections
this.connected.forEach((socket) => {
if (!socket.destroyed) {
socket.destroy();
}
});
}
ipc.server.on(
'socket.disconnected',
(socket, destroyedSocketID) => {
const index = this.connected.indexOf(socket);
if (index > -1) {
this.connected.splice(index, 1);
}
send(message: object, socket: any) {
ipc.server.emit(socket, "message", message);
}
this.socket = null;
ipc.log(
'client ' + destroyedSocketID + ' has disconnected!'
);
}
generateManifests() {
const baseJson = {
name: "com.8bit.bitwarden",
description: "Bitwarden desktop <-> browser bridge",
path: this.binaryPath(),
type: "stdio",
};
const firefoxJson = {
...baseJson,
...{ allowed_extensions: ["{446900e4-71c2-419f-a6a7-df9c091e268b}"] },
};
const chromeJson = {
...baseJson,
...{
allowed_origins: [
"chrome-extension://nngceckbapebfimnlniiiahkandclblb/",
"chrome-extension://jbkfoedolllekgbhcbcoahefnbanhhlh/",
"chrome-extension://ccnckbpmaceehanjmeomladnmlffdjgn/",
],
},
};
switch (process.platform) {
case "win32":
const destination = path.join(this.userPath, "browsers");
this.writeManifest(path.join(destination, "firefox.json"), firefoxJson);
this.writeManifest(path.join(destination, "chrome.json"), chromeJson);
this.createWindowsRegistry(
"HKLM\\SOFTWARE\\Mozilla\\Firefox",
"HKCU\\SOFTWARE\\Mozilla\\NativeMessagingHosts\\com.8bit.bitwarden",
path.join(destination, "firefox.json")
);
this.createWindowsRegistry(
"HKCU\\SOFTWARE\\Google\\Chrome",
"HKCU\\SOFTWARE\\Google\\Chrome\\NativeMessagingHosts\\com.8bit.bitwarden",
path.join(destination, "chrome.json")
);
break;
case "darwin":
const nmhs = this.getDarwinNMHS();
for (const [key, value] of Object.entries(nmhs)) {
if (existsSync(value)) {
const p = path.join(value, "NativeMessagingHosts", "com.8bit.bitwarden.json");
let manifest: any = chromeJson;
if (key === "Firefox") {
manifest = firefoxJson;
}
this.writeManifest(p, manifest).catch((e) =>
this.logService.error(`Error writing manifest for ${key}. ${e}`)
);
});
ipc.server.start();
}
stop() {
ipc.server.stop();
// Kill all existing connections
this.connected.forEach(socket => {
if (!socket.destroyed) {
socket.destroy();
}
});
}
send(message: object, socket: any) {
ipc.server.emit(socket, 'message', message);
}
generateManifests() {
const baseJson = {
'name': 'com.8bit.bitwarden',
'description': 'Bitwarden desktop <-> browser bridge',
'path': this.binaryPath(),
'type': 'stdio',
};
const firefoxJson = {...baseJson, ...{ 'allowed_extensions': ['{446900e4-71c2-419f-a6a7-df9c091e268b}']}};
const chromeJson = {...baseJson, ...{
'allowed_origins': [
'chrome-extension://nngceckbapebfimnlniiiahkandclblb/',
'chrome-extension://jbkfoedolllekgbhcbcoahefnbanhhlh/',
'chrome-extension://ccnckbpmaceehanjmeomladnmlffdjgn/',
],
}};
switch (process.platform) {
case 'win32':
const destination = path.join(this.userPath, 'browsers');
this.writeManifest(path.join(destination, 'firefox.json'), firefoxJson);
this.writeManifest(path.join(destination, 'chrome.json'), chromeJson);
this.createWindowsRegistry('HKLM\\SOFTWARE\\Mozilla\\Firefox', 'HKCU\\SOFTWARE\\Mozilla\\NativeMessagingHosts\\com.8bit.bitwarden', path.join(destination, 'firefox.json'));
this.createWindowsRegistry('HKCU\\SOFTWARE\\Google\\Chrome', 'HKCU\\SOFTWARE\\Google\\Chrome\\NativeMessagingHosts\\com.8bit.bitwarden', path.join(destination, 'chrome.json'));
break;
case 'darwin':
const nmhs = this.getDarwinNMHS();
for (const [key, value] of Object.entries(nmhs)) {
if (existsSync(value)) {
const p = path.join(value, 'NativeMessagingHosts', 'com.8bit.bitwarden.json');
let manifest: any = chromeJson;
if (key === 'Firefox') {
manifest = firefoxJson;
}
this.writeManifest(p, manifest).catch(e => this.logService.error(`Error writing manifest for ${key}. ${e}`));
} else {
this.logService.warning(`${key} not found skipping.`);
}
}
break;
case 'linux':
if (existsSync(`${this.homedir()}/.mozilla/`)) {
this.writeManifest(`${this.homedir()}/.mozilla/native-messaging-hosts/com.8bit.bitwarden.json`, firefoxJson);
}
if (existsSync(`${this.homedir()}/.config/google-chrome/`)) {
this.writeManifest(`${this.homedir()}/.config/google-chrome/NativeMessagingHosts/com.8bit.bitwarden.json`, chromeJson);
}
if (existsSync(`${this.homedir()}/.config/microsoft-edge/`)) {
this.writeManifest(`${this.homedir()}/.config/microsoft-edge/NativeMessagingHosts/com.8bit.bitwarden.json`, chromeJson);
}
break;
default:
break;
} else {
this.logService.warning(`${key} not found skipping.`);
}
}
}
removeManifests() {
switch (process.platform) {
case 'win32':
fs.unlink(path.join(this.userPath, 'browsers', 'firefox.json'));
fs.unlink(path.join(this.userPath, 'browsers', 'chrome.json'));
this.deleteWindowsRegistry('HKCU\\SOFTWARE\\Mozilla\\NativeMessagingHosts\\com.8bit.bitwarden');
this.deleteWindowsRegistry('HKCU\\SOFTWARE\\Google\\Chrome\\NativeMessagingHosts\\com.8bit.bitwarden');
break;
case 'darwin':
const nmhs = this.getDarwinNMHS();
for (const [_, value] of Object.entries(nmhs)) {
const p = path.join(value, 'NativeMessagingHosts', 'com.8bit.bitwarden.json');
if (existsSync(p)) {
fs.unlink(p);
}
}
break;
case 'linux':
if (existsSync(`${this.homedir()}/.mozilla/native-messaging-hosts/com.8bit.bitwarden.json`)) {
fs.unlink(`${this.homedir()}/.mozilla/native-messaging-hosts/com.8bit.bitwarden.json`);
}
if (existsSync(`${this.homedir()}/.config/google-chrome/NativeMessagingHosts/com.8bit.bitwarden.json`)) {
fs.unlink(`${this.homedir()}/.config/google-chrome/NativeMessagingHosts/com.8bit.bitwarden.json`);
}
if (existsSync(`${this.homedir()}/.config/microsoft-edge/NativeMessagingHosts/com.8bit.bitwarden.json`)) {
fs.unlink(`${this.homedir()}/.config/microsoft-edge/NativeMessagingHosts/com.8bit.bitwarden.json`);
}
break;
default:
break;
}
}
private getDarwinNMHS() {
return {
'Firefox': `${this.homedir()}/Library/Application\ Support/Mozilla/`,
'Chrome': `${this.homedir()}/Library/Application\ Support/Google/Chrome/`,
'Chrome Beta': `${this.homedir()}/Library/Application\ Support/Google/Chrome\ Beta/`,
'Chrome Dev': `${this.homedir()}/Library/Application\ Support/Google/Chrome\ Dev/`,
'Chrome Canary': `${this.homedir()}/Library/Application\ Support/Google/Chrome\ Canary/`,
'Chromium': `${this.homedir()}/Library/Application\ Support/Chromium/`,
'Microsoft Edge': `${this.homedir()}/Library/Application\ Support/Microsoft\ Edge/`,
'Microsoft Edge Beta': `${this.homedir()}/Library/Application\ Support/Microsoft\ Edge\ Beta/`,
'Microsoft Edge Dev': `${this.homedir()}/Library/Application\ Support/Microsoft\ Edge\ Dev/`,
'Microsoft Edge Canary': `${this.homedir()}/Library/Application\ Support/Microsoft\ Edge\ Canary/`,
'Vivaldi': `${this.homedir()}/Library/Application\ Support/Vivaldi/`,
};
}
private async writeManifest(destination: string, manifest: object) {
if (!existsSync(path.dirname(destination))) {
await fs.mkdir(path.dirname(destination));
}
fs.writeFile(destination, JSON.stringify(manifest, null, 2)).catch(this.logService.error);
}
private binaryPath() {
if (process.platform === 'win32') {
return path.join(path.dirname(this.exePath), 'resources', 'native-messaging.bat');
break;
case "linux":
if (existsSync(`${this.homedir()}/.mozilla/`)) {
this.writeManifest(
`${this.homedir()}/.mozilla/native-messaging-hosts/com.8bit.bitwarden.json`,
firefoxJson
);
}
return this.exePath;
}
private async createWindowsRegistry(check: string, location: string, jsonFile: string) {
const regedit = require('regedit');
regedit.setExternalVBSLocation('resources/regedit/vbs');
const list = util.promisify(regedit.list);
const createKey = util.promisify(regedit.createKey);
const putValue = util.promisify(regedit.putValue);
this.logService.debug(`Adding registry: ${location}`);
// Check installed
try {
await list(check);
} catch {
this.logService.warning(`Not finding registry ${check} skipping.`);
return;
if (existsSync(`${this.homedir()}/.config/google-chrome/`)) {
this.writeManifest(
`${this.homedir()}/.config/google-chrome/NativeMessagingHosts/com.8bit.bitwarden.json`,
chromeJson
);
}
try {
await createKey(location);
// Insert path to manifest
const obj: any = {};
obj[location] = {
'default': {
value: jsonFile,
type: 'REG_DEFAULT',
},
};
return putValue(obj);
} catch (error) {
this.logService.error(error);
if (existsSync(`${this.homedir()}/.config/microsoft-edge/`)) {
this.writeManifest(
`${this.homedir()}/.config/microsoft-edge/NativeMessagingHosts/com.8bit.bitwarden.json`,
chromeJson
);
}
break;
default:
break;
}
}
removeManifests() {
switch (process.platform) {
case "win32":
fs.unlink(path.join(this.userPath, "browsers", "firefox.json"));
fs.unlink(path.join(this.userPath, "browsers", "chrome.json"));
this.deleteWindowsRegistry(
"HKCU\\SOFTWARE\\Mozilla\\NativeMessagingHosts\\com.8bit.bitwarden"
);
this.deleteWindowsRegistry(
"HKCU\\SOFTWARE\\Google\\Chrome\\NativeMessagingHosts\\com.8bit.bitwarden"
);
break;
case "darwin":
const nmhs = this.getDarwinNMHS();
for (const [_, value] of Object.entries(nmhs)) {
const p = path.join(value, "NativeMessagingHosts", "com.8bit.bitwarden.json");
if (existsSync(p)) {
fs.unlink(p);
}
}
break;
case "linux":
if (
existsSync(`${this.homedir()}/.mozilla/native-messaging-hosts/com.8bit.bitwarden.json`)
) {
fs.unlink(`${this.homedir()}/.mozilla/native-messaging-hosts/com.8bit.bitwarden.json`);
}
if (
existsSync(
`${this.homedir()}/.config/google-chrome/NativeMessagingHosts/com.8bit.bitwarden.json`
)
) {
fs.unlink(
`${this.homedir()}/.config/google-chrome/NativeMessagingHosts/com.8bit.bitwarden.json`
);
}
if (
existsSync(
`${this.homedir()}/.config/microsoft-edge/NativeMessagingHosts/com.8bit.bitwarden.json`
)
) {
fs.unlink(
`${this.homedir()}/.config/microsoft-edge/NativeMessagingHosts/com.8bit.bitwarden.json`
);
}
break;
default:
break;
}
}
private getDarwinNMHS() {
return {
Firefox: `${this.homedir()}/Library/Application\ Support/Mozilla/`,
Chrome: `${this.homedir()}/Library/Application\ Support/Google/Chrome/`,
"Chrome Beta": `${this.homedir()}/Library/Application\ Support/Google/Chrome\ Beta/`,
"Chrome Dev": `${this.homedir()}/Library/Application\ Support/Google/Chrome\ Dev/`,
"Chrome Canary": `${this.homedir()}/Library/Application\ Support/Google/Chrome\ Canary/`,
Chromium: `${this.homedir()}/Library/Application\ Support/Chromium/`,
"Microsoft Edge": `${this.homedir()}/Library/Application\ Support/Microsoft\ Edge/`,
"Microsoft Edge Beta": `${this.homedir()}/Library/Application\ Support/Microsoft\ Edge\ Beta/`,
"Microsoft Edge Dev": `${this.homedir()}/Library/Application\ Support/Microsoft\ Edge\ Dev/`,
"Microsoft Edge Canary": `${this.homedir()}/Library/Application\ Support/Microsoft\ Edge\ Canary/`,
Vivaldi: `${this.homedir()}/Library/Application\ Support/Vivaldi/`,
};
}
private async writeManifest(destination: string, manifest: object) {
if (!existsSync(path.dirname(destination))) {
await fs.mkdir(path.dirname(destination));
}
fs.writeFile(destination, JSON.stringify(manifest, null, 2)).catch(this.logService.error);
}
private binaryPath() {
if (process.platform === "win32") {
return path.join(path.dirname(this.exePath), "resources", "native-messaging.bat");
}
private async deleteWindowsRegistry(key: string) {
const regedit = require('regedit');
return this.exePath;
}
const list = util.promisify(regedit.list);
const deleteKey = util.promisify(regedit.deleteKey);
private async createWindowsRegistry(check: string, location: string, jsonFile: string) {
const regedit = require("regedit");
regedit.setExternalVBSLocation("resources/regedit/vbs");
this.logService.debug(`Removing registry: ${key}`);
const list = util.promisify(regedit.list);
const createKey = util.promisify(regedit.createKey);
const putValue = util.promisify(regedit.putValue);
try {
await list(key);
await deleteKey(key);
} catch {
this.logService.error(`Unable to delete registry key: ${key}`);
}
this.logService.debug(`Adding registry: ${location}`);
// Check installed
try {
await list(check);
} catch {
this.logService.warning(`Not finding registry ${check} skipping.`);
return;
}
private homedir() {
if (process.platform === 'darwin') {
return userInfo().homedir;
} else {
return homedir();
}
try {
await createKey(location);
// Insert path to manifest
const obj: any = {};
obj[location] = {
default: {
value: jsonFile,
type: "REG_DEFAULT",
},
};
return putValue(obj);
} catch (error) {
this.logService.error(error);
}
}
private async deleteWindowsRegistry(key: string) {
const regedit = require("regedit");
const list = util.promisify(regedit.list);
const deleteKey = util.promisify(regedit.deleteKey);
this.logService.debug(`Removing registry: ${key}`);
try {
await list(key);
await deleteKey(key);
} catch {
this.logService.error(`Unable to delete registry key: ${key}`);
}
}
private homedir() {
if (process.platform === "darwin") {
return userInfo().homedir;
} else {
return homedir();
}
}
}

View File

@@ -1,65 +1,68 @@
import { powerMonitor } from 'electron';
import { powerMonitor } from "electron";
import { isSnapStore } from 'jslib-electron/utils';
import { isSnapStore } from "jslib-electron/utils";
import { Main } from '../main';
import { Main } from "../main";
// tslint:disable-next-line
const IdleLockSeconds = 5 * 60; // 5 minutes
const IdleCheckInterval = 30 * 1000; // 30 seconds
export class PowerMonitorMain {
private idle: boolean = false;
private idle: boolean = false;
constructor(private main: Main) { }
constructor(private main: Main) {}
init() {
// ref: https://github.com/electron/electron/issues/13767
if (!isSnapStore()) {
// System sleep
powerMonitor.on('suspend', async () => {
const options = await this.getVaultTimeoutOptions();
if (options[0] === -3) {
options[1] === 'logOut' ? this.main.messagingService.send('logout', { expired: false }) :
this.main.messagingService.send('lockVault');
}
});
init() {
// ref: https://github.com/electron/electron/issues/13767
if (!isSnapStore()) {
// System sleep
powerMonitor.on("suspend", async () => {
const options = await this.getVaultTimeoutOptions();
if (options[0] === -3) {
options[1] === "logOut"
? this.main.messagingService.send("logout", { expired: false })
: this.main.messagingService.send("lockVault");
}
if (process.platform !== 'linux') {
// System locked
powerMonitor.on('lock-screen', async () => {
const options = await this.getVaultTimeoutOptions();
if (options[0] === -2) {
options[1] === 'logOut' ? this.main.messagingService.send('logout', { expired: false }) :
this.main.messagingService.send('lockVault');
}
});
}
// System idle
global.setInterval(async () => {
const idleSeconds: number = powerMonitor.getSystemIdleTime();
const idle = idleSeconds >= IdleLockSeconds;
if (idle) {
if (this.idle) {
return;
}
const options = await this.getVaultTimeoutOptions();
if (options[0] === -4) {
options[1] === 'logOut' ? this.main.messagingService.send('logout', { expired: false }) :
this.main.messagingService.send('lockVault');
}
}
this.idle = idle;
}, IdleCheckInterval);
});
}
private async getVaultTimeoutOptions(): Promise<[number, string]> {
const timeout = await this.main.stateService.getVaultTimeout();
const action = await this.main.stateService.getVaultTimeoutAction();
return [timeout, action];
if (process.platform !== "linux") {
// System locked
powerMonitor.on("lock-screen", async () => {
const options = await this.getVaultTimeoutOptions();
if (options[0] === -2) {
options[1] === "logOut"
? this.main.messagingService.send("logout", { expired: false })
: this.main.messagingService.send("lockVault");
}
});
}
// System idle
global.setInterval(async () => {
const idleSeconds: number = powerMonitor.getSystemIdleTime();
const idle = idleSeconds >= IdleLockSeconds;
if (idle) {
if (this.idle) {
return;
}
const options = await this.getVaultTimeoutOptions();
if (options[0] === -4) {
options[1] === "logOut"
? this.main.messagingService.send("logout", { expired: false })
: this.main.messagingService.send("lockVault");
}
}
this.idle = idle;
}, IdleCheckInterval);
}
private async getVaultTimeoutOptions(): Promise<[number, string]> {
const timeout = await this.main.stateService.getVaultTimeout();
const action = await this.main.stateService.getVaultTimeoutAction();
return [timeout, action];
}
}