mirror of
https://github.com/bitwarden/desktop.git
synced 2024-06-26 10:36:19 +02:00
* [dep] Implement new StateService factory parameter from jslib * [bug] Ensure setLastActive uses the correct userId Sometimes, because of how often it fires, setLastActive can cause accounts to override each other. To make sure the correct userId is always used we now subscribe to activeUser in the appComponent and pass that value into any setLastActive calls. * [bug] Show loader when logging out When logging out of a large vault the application can appear to hang. This commit turns on the app component loader while logout is doing work. * [bug] Stop tracking activity without an active user * [style] Ran prettier * [chore] Update jslib
216 lines
7.4 KiB
TypeScript
216 lines
7.4 KiB
TypeScript
import { app } from "electron";
|
|
import * as path from "path";
|
|
|
|
import { I18nService } from "./services/i18n.service";
|
|
|
|
import { MenuMain } from "./main/menu.main";
|
|
import { MessagingMain } from "./main/messaging.main";
|
|
import { PowerMonitorMain } from "./main/powerMonitor.main";
|
|
|
|
import { BiometricMain } from "jslib-common/abstractions/biometric.main";
|
|
|
|
import { KeytarStorageListener } from "jslib-electron/keytarStorageListener";
|
|
|
|
import { ElectronLogService } from "jslib-electron/services/electronLog.service";
|
|
import { ElectronMainMessagingService } from "jslib-electron/services/electronMainMessaging.service";
|
|
import { ElectronStorageService } from "jslib-electron/services/electronStorage.service";
|
|
|
|
import { TrayMain } from "jslib-electron/tray.main";
|
|
import { UpdaterMain } from "jslib-electron/updater.main";
|
|
import { WindowMain } from "jslib-electron/window.main";
|
|
import { NativeMessagingMain } from "./main/nativeMessaging.main";
|
|
|
|
import { StateService } from "jslib-common/services/state.service";
|
|
|
|
import { Account, AccountFactory } from "jslib-common/models/domain/account";
|
|
|
|
export class Main {
|
|
logService: ElectronLogService;
|
|
i18nService: I18nService;
|
|
storageService: ElectronStorageService;
|
|
messagingService: ElectronMainMessagingService;
|
|
stateService: StateService;
|
|
keytarStorageListener: KeytarStorageListener;
|
|
|
|
windowMain: WindowMain;
|
|
messagingMain: MessagingMain;
|
|
updaterMain: UpdaterMain;
|
|
menuMain: MenuMain;
|
|
powerMonitorMain: PowerMonitorMain;
|
|
trayMain: TrayMain;
|
|
biometricMain: BiometricMain;
|
|
nativeMessagingMain: NativeMessagingMain;
|
|
|
|
constructor() {
|
|
// Set paths for portable builds
|
|
let appDataPath = null;
|
|
if (process.env.BITWARDEN_APPDATA_DIR != null) {
|
|
appDataPath = process.env.BITWARDEN_APPDATA_DIR;
|
|
} else if (process.platform === "win32" && process.env.PORTABLE_EXECUTABLE_DIR != null) {
|
|
appDataPath = path.join(process.env.PORTABLE_EXECUTABLE_DIR, "bitwarden-appdata");
|
|
} else if (process.platform === "linux" && process.env.SNAP_USER_DATA != null) {
|
|
appDataPath = path.join(process.env.SNAP_USER_DATA, "appdata");
|
|
}
|
|
|
|
app.on("ready", () => {
|
|
// on ready stuff...
|
|
});
|
|
|
|
if (appDataPath != null) {
|
|
app.setPath("userData", appDataPath);
|
|
}
|
|
app.setPath("logs", path.join(app.getPath("userData"), "logs"));
|
|
|
|
const args = process.argv.slice(1);
|
|
const watch = args.some((val) => val === "--watch");
|
|
|
|
if (watch) {
|
|
// tslint:disable-next-line
|
|
require("electron-reload")(__dirname, {});
|
|
}
|
|
|
|
this.logService = new ElectronLogService(null, app.getPath("userData"));
|
|
this.i18nService = new I18nService("en", "./locales/");
|
|
|
|
const storageDefaults: any = {};
|
|
// Default vault timeout to "on restart", and action to "lock"
|
|
storageDefaults["global.vaultTimeout"] = -1;
|
|
storageDefaults["global.vaultTimeoutAction"] = "lock";
|
|
this.storageService = new ElectronStorageService(app.getPath("userData"), storageDefaults);
|
|
|
|
// TODO: this state service will have access to on disk storage, but not in memory storage.
|
|
// If we could get this to work using the stateService singleton that the rest of the app uses we could save
|
|
// ourselves from some hacks, like having to manually update the app menu vs. the menu subscribing to events.
|
|
this.stateService = new StateService(
|
|
this.storageService,
|
|
null,
|
|
this.logService,
|
|
null,
|
|
new AccountFactory(Account)
|
|
);
|
|
|
|
this.windowMain = new WindowMain(
|
|
this.stateService,
|
|
this.logService,
|
|
true,
|
|
undefined,
|
|
undefined,
|
|
(arg) => this.processDeepLink(arg),
|
|
(win) => this.trayMain.setupWindowListeners(win)
|
|
);
|
|
this.messagingMain = new MessagingMain(this, this.stateService);
|
|
this.updaterMain = new UpdaterMain(
|
|
this.i18nService,
|
|
this.windowMain,
|
|
"desktop",
|
|
null,
|
|
null,
|
|
null,
|
|
"bitwarden"
|
|
);
|
|
this.menuMain = new MenuMain(this);
|
|
this.powerMonitorMain = new PowerMonitorMain(this);
|
|
this.trayMain = new TrayMain(this.windowMain, this.i18nService, this.stateService);
|
|
|
|
this.messagingService = new ElectronMainMessagingService(this.windowMain, (message) => {
|
|
this.messagingMain.onMessage(message);
|
|
});
|
|
|
|
if (process.platform === "win32") {
|
|
const BiometricWindowsMain = require("jslib-electron/biometric.windows.main").default;
|
|
this.biometricMain = new BiometricWindowsMain(
|
|
this.i18nService,
|
|
this.windowMain,
|
|
this.stateService,
|
|
this.logService
|
|
);
|
|
} else if (process.platform === "darwin") {
|
|
const BiometricDarwinMain = require("jslib-electron/biometric.darwin.main").default;
|
|
this.biometricMain = new BiometricDarwinMain(this.i18nService, this.stateService);
|
|
}
|
|
|
|
this.keytarStorageListener = new KeytarStorageListener("Bitwarden", this.biometricMain);
|
|
|
|
this.nativeMessagingMain = new NativeMessagingMain(
|
|
this.logService,
|
|
this.windowMain,
|
|
app.getPath("userData"),
|
|
app.getPath("exe")
|
|
);
|
|
}
|
|
|
|
bootstrap() {
|
|
this.keytarStorageListener.init();
|
|
this.windowMain.init().then(
|
|
async () => {
|
|
const locale = await this.stateService.getLocale();
|
|
await this.i18nService.init(locale != null ? locale : app.getLocale());
|
|
this.messagingMain.init();
|
|
this.menuMain.init();
|
|
await this.trayMain.init("Bitwarden", [
|
|
{
|
|
label: this.i18nService.t("lockNow"),
|
|
enabled: false,
|
|
id: "lockNow",
|
|
click: () => this.messagingService.send("lockVault"),
|
|
},
|
|
]);
|
|
if (await this.stateService.getEnableStartToTray()) {
|
|
this.trayMain.hideToTray();
|
|
}
|
|
this.powerMonitorMain.init();
|
|
await this.updaterMain.init();
|
|
if (this.biometricMain != null) {
|
|
await this.biometricMain.init();
|
|
}
|
|
|
|
if (await this.stateService.getEnableBrowserIntegration()) {
|
|
this.nativeMessagingMain.listen();
|
|
}
|
|
|
|
app.removeAsDefaultProtocolClient("bitwarden");
|
|
if (process.env.NODE_ENV === "development" && process.platform === "win32") {
|
|
// Fix development build on Windows requirering a different protocol client
|
|
app.setAsDefaultProtocolClient("bitwarden", process.execPath, [
|
|
process.argv[1],
|
|
path.resolve(process.argv[2]),
|
|
]);
|
|
} else {
|
|
app.setAsDefaultProtocolClient("bitwarden");
|
|
}
|
|
|
|
// Process protocol for macOS
|
|
app.on("open-url", (event, url) => {
|
|
event.preventDefault();
|
|
this.processDeepLink([url]);
|
|
});
|
|
|
|
// Handle window visibility events
|
|
this.windowMain.win.on("hide", () => {
|
|
this.messagingService.send("windowHidden");
|
|
});
|
|
this.windowMain.win.on("minimize", () => {
|
|
this.messagingService.send("windowHidden");
|
|
});
|
|
},
|
|
(e: any) => {
|
|
// tslint:disable-next-line
|
|
console.error(e);
|
|
}
|
|
);
|
|
}
|
|
|
|
private processDeepLink(argv: string[]): void {
|
|
argv
|
|
.filter((s) => s.indexOf("bitwarden://") === 0)
|
|
.forEach((s) => {
|
|
const url = new URL(s);
|
|
const code = url.searchParams.get("code");
|
|
const receivedState = url.searchParams.get("state");
|
|
if (code != null && receivedState != null) {
|
|
this.messagingService.send("ssoCallback", { code: code, state: receivedState });
|
|
}
|
|
});
|
|
}
|
|
}
|