1
0
mirror of https://github.com/bitwarden/browser synced 2026-01-06 10:33:57 +00:00

Platform/pm 19/platform team file moves (#5460)

* Rename service-factory folder

* Move cryptographic service factories

* Move crypto models

* Move crypto services

* Move domain base class

* Platform code owners

* Move desktop log services

* Move log files

* Establish component library ownership

* Move background listeners

* Move background background

* Move localization to Platform

* Move browser alarms to Platform

* Move browser state to Platform

* Move CLI state to Platform

* Move Desktop native concerns to Platform

* Move flag and misc to Platform

* Lint fixes

* Move electron state to platform

* Move web state to Platform

* Move lib state to Platform

* Fix broken tests

* Rename interface to idiomatic TS

* `npm run prettier` 🤖

* Resolve review feedback

* Set platform as owners of web core and shared

* Expand moved services

* Fix test types

---------

Co-authored-by: Hinton <hinton@users.noreply.github.com>
This commit is contained in:
Matt Gibson
2023-06-06 15:34:53 -05:00
committed by GitHub
parent ce4fc31efd
commit 78248db590
869 changed files with 2840 additions and 2746 deletions

View File

@@ -1,66 +0,0 @@
import { CryptoFunctionService } from "@bitwarden/common/abstractions/cryptoFunction.service";
import { EncryptService } from "@bitwarden/common/abstractions/encrypt.service";
import { LogService } from "@bitwarden/common/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { KeySuffixOptions } from "@bitwarden/common/enums";
import { Utils } from "@bitwarden/common/misc/utils";
import { SymmetricCryptoKey } from "@bitwarden/common/models/domain/symmetric-crypto-key";
import { CryptoService } from "@bitwarden/common/services/crypto.service";
import { CsprngString } from "@bitwarden/common/types/csprng";
import { ElectronStateService } from "./electron-state.service.abstraction";
export class ElectronCryptoService extends CryptoService {
constructor(
cryptoFunctionService: CryptoFunctionService,
encryptService: EncryptService,
platformUtilsService: PlatformUtilsService,
logService: LogService,
protected override stateService: ElectronStateService
) {
super(cryptoFunctionService, encryptService, platformUtilsService, logService, stateService);
}
protected override async storeKey(key: SymmetricCryptoKey, userId?: string) {
await super.storeKey(key, userId);
const storeBiometricKey = await this.shouldStoreKey(KeySuffixOptions.Biometric, userId);
if (storeBiometricKey) {
await this.storeBiometricKey(key, userId);
} else {
await this.stateService.setCryptoMasterKeyBiometric(null, { userId: userId });
}
}
protected async storeBiometricKey(key: SymmetricCryptoKey, userId?: string): Promise<void> {
let clientEncKeyHalf: CsprngString = null;
if (await this.stateService.getBiometricRequirePasswordOnStart({ userId })) {
clientEncKeyHalf = await this.getBiometricEncryptionClientKeyHalf(userId);
}
await this.stateService.setCryptoMasterKeyBiometric(
{ key: key.keyB64, clientEncKeyHalf },
{ userId: userId }
);
}
private async getBiometricEncryptionClientKeyHalf(userId?: string): Promise<CsprngString | null> {
try {
let biometricKey = await this.stateService
.getBiometricEncryptionClientKeyHalf({ userId })
.then((result) => result?.decrypt(null /* user encrypted */))
.then((result) => result as CsprngString);
const userKey = await this.getKeyForUserEncryption();
if (biometricKey == null && userKey != null) {
const keyBytes = await this.cryptoFunctionService.randomBytes(32);
biometricKey = Utils.fromBufferToUtf8(keyBytes) as CsprngString;
const encKey = await this.encryptService.encrypt(biometricKey, userKey);
await this.stateService.setBiometricEncryptionClientKeyHalf(encKey);
}
return biometricKey;
} catch {
return null;
}
}
}

View File

@@ -1,9 +0,0 @@
import { ElectronLogService } from "./electron-log.service";
describe("ElectronLogService", () => {
it("sets dev based on electron method", () => {
process.env.ELECTRON_IS_DEV = "1";
const logService = new ElectronLogService();
expect(logService).toEqual(expect.objectContaining({ isDev: true }) as any);
});
});

View File

@@ -1,45 +0,0 @@
import * as path from "path";
import log from "electron-log";
import { LogLevelType } from "@bitwarden/common/enums";
import { ConsoleLogService as BaseLogService } from "@bitwarden/common/services/consoleLog.service";
import { isDev } from "../utils";
export class ElectronLogService extends BaseLogService {
constructor(protected filter: (level: LogLevelType) => boolean = null, logDir: string = null) {
super(isDev(), filter);
if (log.transports == null) {
return;
}
log.transports.file.level = "info";
if (logDir != null) {
log.transports.file.file = path.join(logDir, "app.log");
}
}
write(level: LogLevelType, message: string) {
if (this.filter != null && this.filter(level)) {
return;
}
switch (level) {
case LogLevelType.Debug:
log.debug(message);
break;
case LogLevelType.Info:
log.info(message);
break;
case LogLevelType.Warning:
log.warn(message);
break;
case LogLevelType.Error:
log.error(message);
break;
default:
break;
}
}
}

View File

@@ -2,8 +2,8 @@ import * as path from "path";
import { app, dialog, ipcMain, Menu, MenuItem, nativeTheme, session, Notification } from "electron";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { ThemeType } from "@bitwarden/common/enums";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { WindowMain } from "../main/window.main";
import { RendererMenuItem } from "../utils";

View File

@@ -1,171 +0,0 @@
import { clipboard, ipcRenderer, shell } from "electron";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { StateService } from "@bitwarden/common/abstractions/state.service";
import { ClientType, DeviceType } from "@bitwarden/common/enums";
import { BiometricMessage, BiometricStorageAction } from "../types/biometric-message";
import { isDev, isMacAppStore } from "../utils";
export class ElectronPlatformUtilsService implements PlatformUtilsService {
private deviceCache: DeviceType = null;
constructor(
protected i18nService: I18nService,
private messagingService: MessagingService,
private clientType: ClientType.Desktop | ClientType.DirectoryConnector,
private stateService: StateService
) {}
getDevice(): DeviceType {
if (!this.deviceCache) {
switch (process.platform) {
case "win32":
this.deviceCache = DeviceType.WindowsDesktop;
break;
case "darwin":
this.deviceCache = DeviceType.MacOsDesktop;
break;
case "linux":
default:
this.deviceCache = DeviceType.LinuxDesktop;
break;
}
}
return this.deviceCache;
}
getDeviceString(): string {
const device = DeviceType[this.getDevice()].toLowerCase();
return device.replace("desktop", "");
}
getClientType() {
return this.clientType;
}
isFirefox(): boolean {
return false;
}
isChrome(): boolean {
return true;
}
isEdge(): boolean {
return false;
}
isOpera(): boolean {
return false;
}
isVivaldi(): boolean {
return false;
}
isSafari(): boolean {
return false;
}
isMacAppStore(): boolean {
return isMacAppStore();
}
isViewOpen(): Promise<boolean> {
return Promise.resolve(false);
}
launchUri(uri: string, options?: any): void {
shell.openExternal(uri);
}
getApplicationVersion(): Promise<string> {
return ipcRenderer.invoke("appVersion");
}
async getApplicationVersionNumber(): Promise<string> {
return (await this.getApplicationVersion()).split(/[+|-]/)[0].trim();
}
// Temporarily restricted to only Windows until https://github.com/electron/electron/pull/28349
// has been merged and an updated electron build is available.
supportsWebAuthn(win: Window): boolean {
return process.platform === "win32";
}
supportsDuo(): boolean {
return true;
}
showToast(
type: "error" | "success" | "warning" | "info",
title: string,
text: string | string[],
options?: any
): void {
this.messagingService.send("showToast", {
text: text,
title: title,
type: type,
options: options,
});
}
isDev(): boolean {
return isDev();
}
isSelfHost(): boolean {
return false;
}
copyToClipboard(text: string, options?: any): void {
const type = options ? options.type : null;
const clearing = options ? !!options.clearing : false;
const clearMs: number = options && options.clearMs ? options.clearMs : null;
clipboard.writeText(text, type);
if (!clearing) {
this.messagingService.send("copiedToClipboard", {
clipboardValue: text,
clearMs: clearMs,
type: type,
clearing: clearing,
});
}
}
readFromClipboard(options?: any): Promise<string> {
const type = options ? options.type : null;
return Promise.resolve(clipboard.readText(type));
}
async supportsBiometric(): Promise<boolean> {
return await ipcRenderer.invoke("biometric", {
action: BiometricStorageAction.OsSupported,
} as BiometricMessage);
}
/** This method is used to authenticate the user presence _only_.
* It should not be used in the process to retrieve
* biometric keys, which has a separate authentication mechanism.
* For biometric keys, invoke "keytar" with a biometric key suffix */
async authenticateBiometric(): Promise<boolean> {
const val = await ipcRenderer.invoke("biometric", {
action: "authenticate",
});
return val;
}
supportsSecureStorage(): boolean {
return true;
}
getAutofillKeyboardShortcut(): Promise<string> {
return null;
}
}

View File

@@ -1,26 +0,0 @@
import { ipcRenderer } from "electron";
import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
export class ElectronRendererMessagingService implements MessagingService {
constructor(private broadcasterService: BroadcasterService) {
ipcRenderer.on("messagingService", async (event: any, message: any) => {
if (message.command) {
this.sendMessage(message.command, message, false);
}
});
}
send(subscriber: string, arg: any = {}) {
this.sendMessage(subscriber, arg, true);
}
private sendMessage(subscriber: string, arg: any = {}, toMain: boolean) {
const message = Object.assign({}, { command: subscriber }, arg);
this.broadcasterService.send(message);
if (toMain) {
ipcRenderer.send("messagingService", message);
}
}
}

View File

@@ -1,41 +0,0 @@
import { ipcRenderer } from "electron";
import { AbstractStorageService } from "@bitwarden/common/abstractions/storage.service";
import { StorageOptions } from "@bitwarden/common/models/domain/storage-options";
export class ElectronRendererSecureStorageService implements AbstractStorageService {
async get<T>(key: string, options?: StorageOptions): Promise<T> {
const val = await ipcRenderer.invoke("keytar", {
action: "getPassword",
key: key,
keySuffix: options?.keySuffix ?? "",
});
return val != null ? (JSON.parse(val) as T) : null;
}
async has(key: string, options?: StorageOptions): Promise<boolean> {
const val = await ipcRenderer.invoke("keytar", {
action: "hasPassword",
key: key,
keySuffix: options?.keySuffix ?? "",
});
return !!val;
}
async save(key: string, obj: any, options?: StorageOptions): Promise<any> {
await ipcRenderer.invoke("keytar", {
action: "setPassword",
key: key,
keySuffix: options?.keySuffix ?? "",
value: JSON.stringify(obj),
});
}
async remove(key: string, options?: StorageOptions): Promise<any> {
await ipcRenderer.invoke("keytar", {
action: "deletePassword",
key: key,
keySuffix: options?.keySuffix ?? "",
});
}
}

View File

@@ -1,34 +0,0 @@
import { ipcRenderer } from "electron";
import { AbstractStorageService } from "@bitwarden/common/abstractions/storage.service";
export class ElectronRendererStorageService implements AbstractStorageService {
get<T>(key: string): Promise<T> {
return ipcRenderer.invoke("storageService", {
action: "get",
key: key,
});
}
has(key: string): Promise<boolean> {
return ipcRenderer.invoke("storageService", {
action: "has",
key: key,
});
}
save(key: string, obj: any): Promise<any> {
return ipcRenderer.invoke("storageService", {
action: "save",
key: key,
obj: obj,
});
}
remove(key: string): Promise<any> {
return ipcRenderer.invoke("storageService", {
action: "remove",
key: key,
});
}
}

View File

@@ -1,17 +0,0 @@
import { StateService } from "@bitwarden/common/abstractions/state.service";
import { EncString } from "@bitwarden/common/models/domain/enc-string";
import { StorageOptions } from "@bitwarden/common/models/domain/storage-options";
import { Account } from "../models/account";
export abstract class ElectronStateService extends StateService<Account> {
getBiometricEncryptionClientKeyHalf: (options?: StorageOptions) => Promise<EncString>;
setBiometricEncryptionClientKeyHalf: (
value: EncString,
options?: StorageOptions
) => Promise<void>;
getDismissedBiometricRequirePasswordOnStart: (options?: StorageOptions) => Promise<boolean>;
setDismissedBiometricRequirePasswordOnStart: (options?: StorageOptions) => Promise<void>;
getBiometricRequirePasswordOnStart: (options?: StorageOptions) => Promise<boolean>;
setBiometricRequirePasswordOnStart: (value: boolean, options?: StorageOptions) => Promise<void>;
}

View File

@@ -1,112 +0,0 @@
import { Utils } from "@bitwarden/common/misc/utils";
import { EncString } from "@bitwarden/common/models/domain/enc-string";
import { GlobalState } from "@bitwarden/common/models/domain/global-state";
import { StorageOptions } from "@bitwarden/common/models/domain/storage-options";
import {
DeviceKey,
SymmetricCryptoKey,
} from "@bitwarden/common/models/domain/symmetric-crypto-key";
import { StateService as BaseStateService } from "@bitwarden/common/services/state.service";
import { Account } from "../models/account";
import { ElectronStateService as ElectronStateServiceAbstraction } from "./electron-state.service.abstraction";
export class ElectronStateService
extends BaseStateService<GlobalState, Account>
implements ElectronStateServiceAbstraction
{
private partialKeys = {
deviceKey: "_deviceKey",
};
async addAccount(account: Account) {
// Apply desktop overides to default account values
account = new Account(account);
await super.addAccount(account);
}
async getBiometricEncryptionClientKeyHalf(options?: StorageOptions): Promise<EncString> {
const account = await this.getAccount(
this.reconcileOptions(options, await this.defaultOnDiskOptions())
);
const key = account?.keys?.biometricEncryptionClientKeyHalf;
return key == null ? null : new EncString(key);
}
async setBiometricEncryptionClientKeyHalf(
value: EncString,
options?: StorageOptions
): Promise<void> {
const account = await this.getAccount(
this.reconcileOptions(options, await this.defaultOnDiskOptions())
);
account.keys.biometricEncryptionClientKeyHalf = value?.encryptedString;
await this.saveAccount(
account,
this.reconcileOptions(options, await this.defaultOnDiskOptions())
);
}
async getBiometricRequirePasswordOnStart(options?: StorageOptions): Promise<boolean> {
const account = await this.getAccount(
this.reconcileOptions(options, await this.defaultOnDiskOptions())
);
return account?.settings?.requirePasswordOnStart;
}
async setBiometricRequirePasswordOnStart(
value: boolean,
options?: StorageOptions
): Promise<void> {
const account = await this.getAccount(
this.reconcileOptions(options, await this.defaultOnDiskOptions())
);
account.settings.requirePasswordOnStart = value;
await this.saveAccount(
account,
this.reconcileOptions(options, await this.defaultOnDiskOptions())
);
}
async getDismissedBiometricRequirePasswordOnStart(options?: StorageOptions): Promise<boolean> {
const account = await this.getAccount(
this.reconcileOptions(options, await this.defaultOnDiskOptions())
);
return account?.settings?.dismissedBiometricRequirePasswordOnStartCallout;
}
async setDismissedBiometricRequirePasswordOnStart(options?: StorageOptions): Promise<void> {
const account = await this.getAccount(
this.reconcileOptions(options, await this.defaultOnDiskOptions())
);
account.settings.dismissedBiometricRequirePasswordOnStartCallout = true;
await this.saveAccount(
account,
this.reconcileOptions(options, await this.defaultOnDiskOptions())
);
}
override async getDeviceKey(options?: StorageOptions): Promise<DeviceKey | null> {
options = this.reconcileOptions(options, await this.defaultSecureStorageOptions());
if (options?.userId == null) {
return;
}
const b64DeviceKey = await this.secureStorageService.get<string>(
`${options.userId}${this.partialKeys.deviceKey}`,
options
);
return new SymmetricCryptoKey(Utils.fromB64ToArray(b64DeviceKey).buffer) as DeviceKey;
}
override async setDeviceKey(value: DeviceKey, options?: StorageOptions): Promise<void> {
options = this.reconcileOptions(options, await this.defaultSecureStorageOptions());
if (options?.userId == null) {
return;
}
await this.saveSecureStorageKey(this.partialKeys.deviceKey, value.keyB64, options);
}
}

View File

@@ -1,85 +0,0 @@
import * as fs from "fs";
import { ipcMain } from "electron";
import { AbstractStorageService } from "@bitwarden/common/abstractions/storage.service";
import { NodeUtils } from "@bitwarden/common/misc/nodeUtils";
// See: https://github.com/sindresorhus/electron-store/blob/main/index.d.ts
interface ElectronStoreOptions {
defaults: unknown;
name: string;
}
type ElectronStoreConstructor = new (options: ElectronStoreOptions) => ElectronStore;
// eslint-disable-next-line
const Store: ElectronStoreConstructor = require("electron-store");
interface ElectronStore {
get: (key: string) => unknown;
set: (key: string, obj: unknown) => void;
delete: (key: string) => void;
}
interface BaseOptions<T extends string> {
action: T;
key: string;
}
interface SaveOptions extends BaseOptions<"save"> {
obj: unknown;
}
type Options = BaseOptions<"get"> | BaseOptions<"has"> | SaveOptions | BaseOptions<"remove">;
export class ElectronStorageService implements AbstractStorageService {
private store: ElectronStore;
constructor(dir: string, defaults = {}) {
if (!fs.existsSync(dir)) {
NodeUtils.mkdirpSync(dir, "700");
}
const storeConfig: ElectronStoreOptions = {
defaults: defaults,
name: "data",
};
this.store = new Store(storeConfig);
ipcMain.handle("storageService", (event, options: Options) => {
switch (options.action) {
case "get":
return this.get(options.key);
case "has":
return this.has(options.key);
case "save":
return this.save(options.key, options.obj);
case "remove":
return this.remove(options.key);
}
});
}
get<T>(key: string): Promise<T> {
const val = this.store.get(key) as T;
return Promise.resolve(val != null ? val : null);
}
has(key: string): Promise<boolean> {
const val = this.store.get(key);
return Promise.resolve(val != null);
}
save(key: string, obj: unknown): Promise<void> {
if (obj instanceof Set) {
obj = Array.from(obj);
}
this.store.set(key, obj);
return Promise.resolve();
}
remove(key: string): Promise<void> {
this.store.delete(key);
return Promise.resolve();
}
}

View File

@@ -1,10 +1,10 @@
import { firstValueFrom } from "rxjs";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { PolicyType } from "@bitwarden/common/admin-console/enums";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
@@ -24,8 +24,7 @@ import { GenerateResponse } from "../models/native-messaging/encrypted-message-r
import { MessageResponseData } from "../models/native-messaging/encrypted-message-responses/message-response-data";
import { SuccessStatusResponse } from "../models/native-messaging/encrypted-message-responses/success-status-response";
import { UserStatusErrorResponse } from "../models/native-messaging/encrypted-message-responses/user-status-error-response";
import { ElectronStateService } from "./electron-state.service";
import { ElectronStateService } from "../platform/services/electron-state.service";
export class EncryptedMessageHandlerService {
constructor(

View File

@@ -1,78 +0,0 @@
import * as fs from "fs";
import * as path from "path";
import { I18nService as BaseI18nService } from "@bitwarden/common/services/i18n.service";
export class I18nService extends BaseI18nService {
constructor(systemLanguage: string, localesDirectory: string) {
super(systemLanguage, localesDirectory, (formattedLocale: string) => {
const filePath = path.join(
__dirname,
this.localesDirectory + "/" + formattedLocale + "/messages.json"
);
const localesJson = fs.readFileSync(filePath, "utf8");
const locales = JSON.parse(localesJson.replace(/^\uFEFF/, "")); // strip the BOM
return Promise.resolve(locales);
});
// Please leave 'en' where it is, as it's our fallback language in case no translation can be found
this.supportedTranslationLocales = [
"en",
"af",
"ar",
"az",
"be",
"bg",
"bn",
"bs",
"ca",
"cs",
"da",
"de",
"el",
"en-GB",
"en-IN",
"eo",
"es",
"et",
"eu",
"fa",
"fi",
"fil",
"fr",
"he",
"hi",
"hr",
"hu",
"id",
"it",
"ja",
"ka",
"km",
"kn",
"ko",
"lv",
"me",
"ml",
"nb",
"nl",
"nn",
"pl",
"pt-BR",
"pt-PT",
"ro",
"ru",
"si",
"sk",
"sl",
"sr",
"sv",
"th",
"tr",
"uk",
"vi",
"zh-CN",
"zh-TW",
];
}
}

View File

@@ -2,15 +2,15 @@ import { Injectable } from "@angular/core";
import { ipcRenderer } from "electron";
import Swal from "sweetalert2";
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
import { CryptoFunctionService } from "@bitwarden/common/abstractions/cryptoFunction.service";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { NativeMessagingVersion } from "@bitwarden/common/enums";
import { Utils } from "@bitwarden/common/misc/utils";
import { EncString } from "@bitwarden/common/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/models/domain/symmetric-crypto-key";
import { StateService } from "@bitwarden/common/services/state.service";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { StateService } from "@bitwarden/common/platform/services/state.service";
import { DecryptedCommandData } from "../models/native-messaging/decrypted-command-data";
import { EncryptedMessage } from "../models/native-messaging/encrypted-message";

View File

@@ -3,17 +3,17 @@ import { ipcRenderer } from "electron";
import { firstValueFrom } from "rxjs";
import Swal from "sweetalert2";
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
import { CryptoFunctionService } from "@bitwarden/common/abstractions/cryptoFunction.service";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { StateService } from "@bitwarden/common/abstractions/state.service";
import { KeySuffixOptions } from "@bitwarden/common/enums";
import { Utils } from "@bitwarden/common/misc/utils";
import { EncString } from "@bitwarden/common/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/models/domain/symmetric-crypto-key";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { LegacyMessage } from "../models/native-messaging/legacy-message";
import { LegacyMessageWrapper } from "../models/native-messaging/legacy-message-wrapper";