mirror of
https://github.com/bitwarden/browser
synced 2026-01-20 09:23:23 +00:00
Apply Prettier (#1202)
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user