mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-02 18:17:46 +01:00
Ps/pm-6636/angular-specific-browser-platform-utils (#8211)
* Remove Unused services * Split platform utils between foreground and background * Respond to clipboard clearing and biometric unlock * Use new browser platform utils * Fix folder name * Fix imports * biometrics is supported only on windows and mac * Reject native messaging with errors We're now going through the runtime background, which expects error objects in message failures
This commit is contained in:
parent
5feb9af051
commit
1f41d7871c
@ -17,8 +17,8 @@ import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
|||||||
import { CipherService } from "@bitwarden/common/vault/services/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/services/cipher.service";
|
||||||
|
|
||||||
import { BrowserApi } from "../../platform/browser/browser-api";
|
import { BrowserApi } from "../../platform/browser/browser-api";
|
||||||
import BrowserPlatformUtilsService from "../../platform/services/browser-platform-utils.service";
|
|
||||||
import { BrowserStateService } from "../../platform/services/browser-state.service";
|
import { BrowserStateService } from "../../platform/services/browser-state.service";
|
||||||
|
import { BrowserPlatformUtilsService } from "../../platform/services/platform-utils/browser-platform-utils.service";
|
||||||
import { AutofillService } from "../services/abstractions/autofill.service";
|
import { AutofillService } from "../services/abstractions/autofill.service";
|
||||||
import {
|
import {
|
||||||
createAutofillPageDetailsMock,
|
createAutofillPageDetailsMock,
|
||||||
|
@ -198,10 +198,11 @@ import { BrowserEnvironmentService } from "../platform/services/browser-environm
|
|||||||
import BrowserLocalStorageService from "../platform/services/browser-local-storage.service";
|
import BrowserLocalStorageService from "../platform/services/browser-local-storage.service";
|
||||||
import BrowserMessagingPrivateModeBackgroundService from "../platform/services/browser-messaging-private-mode-background.service";
|
import BrowserMessagingPrivateModeBackgroundService from "../platform/services/browser-messaging-private-mode-background.service";
|
||||||
import BrowserMessagingService from "../platform/services/browser-messaging.service";
|
import BrowserMessagingService from "../platform/services/browser-messaging.service";
|
||||||
import BrowserPlatformUtilsService from "../platform/services/browser-platform-utils.service";
|
|
||||||
import { BrowserStateService } from "../platform/services/browser-state.service";
|
import { BrowserStateService } from "../platform/services/browser-state.service";
|
||||||
import I18nService from "../platform/services/i18n.service";
|
import I18nService from "../platform/services/i18n.service";
|
||||||
import { LocalBackedSessionStorageService } from "../platform/services/local-backed-session-storage.service";
|
import { LocalBackedSessionStorageService } from "../platform/services/local-backed-session-storage.service";
|
||||||
|
import { BackgroundPlatformUtilsService } from "../platform/services/platform-utils/background-platform-utils.service";
|
||||||
|
import { BrowserPlatformUtilsService } from "../platform/services/platform-utils/browser-platform-utils.service";
|
||||||
import { BackgroundDerivedStateProvider } from "../platform/state/background-derived-state.provider";
|
import { BackgroundDerivedStateProvider } from "../platform/state/background-derived-state.provider";
|
||||||
import { BackgroundMemoryStorageService } from "../platform/storage/background-memory-storage.service";
|
import { BackgroundMemoryStorageService } from "../platform/storage/background-memory-storage.service";
|
||||||
import { BrowserSendService } from "../services/browser-send.service";
|
import { BrowserSendService } from "../services/browser-send.service";
|
||||||
@ -438,28 +439,10 @@ export default class MainBackground {
|
|||||||
migrationRunner,
|
migrationRunner,
|
||||||
);
|
);
|
||||||
this.userNotificationSettingsService = new UserNotificationSettingsService(this.stateProvider);
|
this.userNotificationSettingsService = new UserNotificationSettingsService(this.stateProvider);
|
||||||
this.platformUtilsService = new BrowserPlatformUtilsService(
|
this.platformUtilsService = new BackgroundPlatformUtilsService(
|
||||||
this.messagingService,
|
this.messagingService,
|
||||||
(clipboardValue, clearMs) => {
|
(clipboardValue, clearMs) => this.clearClipboard(clipboardValue, clearMs),
|
||||||
if (this.systemService != null) {
|
async () => this.biometricUnlock(),
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
this.systemService.clearClipboard(clipboardValue, clearMs);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async () => {
|
|
||||||
if (this.nativeMessagingBackground != null) {
|
|
||||||
const promise = this.nativeMessagingBackground.getResponse();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this.nativeMessagingBackground.send({ command: "biometricUnlock" });
|
|
||||||
} catch (e) {
|
|
||||||
return Promise.reject(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return promise.then((result) => result.response === "unlocked");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
self,
|
self,
|
||||||
);
|
);
|
||||||
this.i18nService = new I18nService(BrowserApi.getUILanguage(), this.globalStateProvider);
|
this.i18nService = new I18nService(BrowserApi.getUILanguage(), this.globalStateProvider);
|
||||||
@ -1222,6 +1205,23 @@ export default class MainBackground {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async clearClipboard(clipboardValue: string, clearMs: number) {
|
||||||
|
if (this.systemService != null) {
|
||||||
|
await this.systemService.clearClipboard(clipboardValue, clearMs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async biometricUnlock(): Promise<boolean> {
|
||||||
|
if (this.nativeMessagingBackground == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const responsePromise = this.nativeMessagingBackground.getResponse();
|
||||||
|
await this.nativeMessagingBackground.send({ command: "biometricUnlock" });
|
||||||
|
const response = await responsePromise;
|
||||||
|
return response.response === "unlocked";
|
||||||
|
}
|
||||||
|
|
||||||
private async fullSync(override = false) {
|
private async fullSync(override = false) {
|
||||||
const syncInternal = 6 * 60 * 60 * 1000; // 6 hours
|
const syncInternal = 6 * 60 * 60 * 1000; // 6 hours
|
||||||
const lastSync = await this.syncService.getLastSync();
|
const lastSync = await this.syncService.getLastSync();
|
||||||
|
@ -122,7 +122,7 @@ export class NativeMessagingBackground {
|
|||||||
break;
|
break;
|
||||||
case "disconnected":
|
case "disconnected":
|
||||||
if (this.connecting) {
|
if (this.connecting) {
|
||||||
reject("startDesktop");
|
reject(new Error("startDesktop"));
|
||||||
}
|
}
|
||||||
this.connected = false;
|
this.connected = false;
|
||||||
this.port.disconnect();
|
this.port.disconnect();
|
||||||
@ -203,7 +203,7 @@ export class NativeMessagingBackground {
|
|||||||
this.connected = false;
|
this.connected = false;
|
||||||
|
|
||||||
const reason = error != null ? "desktopIntegrationDisabled" : null;
|
const reason = error != null ? "desktopIntegrationDisabled" : null;
|
||||||
reject(reason);
|
reject(new Error(reason));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ import { AutofillService } from "../autofill/services/abstractions/autofill.serv
|
|||||||
import { BrowserApi } from "../platform/browser/browser-api";
|
import { BrowserApi } from "../platform/browser/browser-api";
|
||||||
import { BrowserStateService } from "../platform/services/abstractions/browser-state.service";
|
import { BrowserStateService } from "../platform/services/abstractions/browser-state.service";
|
||||||
import { BrowserEnvironmentService } from "../platform/services/browser-environment.service";
|
import { BrowserEnvironmentService } from "../platform/services/browser-environment.service";
|
||||||
import BrowserPlatformUtilsService from "../platform/services/browser-platform-utils.service";
|
import { BrowserPlatformUtilsService } from "../platform/services/platform-utils/browser-platform-utils.service";
|
||||||
import { AbortManager } from "../vault/background/abort-manager";
|
import { AbortManager } from "../vault/background/abort-manager";
|
||||||
import { Fido2Service } from "../vault/services/abstractions/fido2.service";
|
import { Fido2Service } from "../vault/services/abstractions/fido2.service";
|
||||||
|
|
||||||
@ -68,6 +68,7 @@ export default class RuntimeBackground {
|
|||||||
"checkFido2FeatureEnabled",
|
"checkFido2FeatureEnabled",
|
||||||
"fido2RegisterCredentialRequest",
|
"fido2RegisterCredentialRequest",
|
||||||
"fido2GetCredentialRequest",
|
"fido2GetCredentialRequest",
|
||||||
|
"biometricUnlock",
|
||||||
];
|
];
|
||||||
|
|
||||||
if (messagesWithResponse.includes(msg.command)) {
|
if (messagesWithResponse.includes(msg.command)) {
|
||||||
@ -305,6 +306,14 @@ export default class RuntimeBackground {
|
|||||||
);
|
);
|
||||||
case "switchAccount": {
|
case "switchAccount": {
|
||||||
await this.main.switchAccount(msg.userId);
|
await this.main.switchAccount(msg.userId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "clearClipboard": {
|
||||||
|
await this.main.clearClipboard(msg.clipboardValue, msg.timeoutMs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "biometricUnlock": {
|
||||||
|
return await this.main.biometricUnlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
|
|
||||||
import BrowserPlatformUtilsService from "../../services/browser-platform-utils.service";
|
import { BackgroundPlatformUtilsService } from "../../services/platform-utils/background-platform-utils.service";
|
||||||
|
|
||||||
import { CachedServices, factory, FactoryOptions } from "./factory-options";
|
import { CachedServices, factory, FactoryOptions } from "./factory-options";
|
||||||
import { MessagingServiceInitOptions, messagingServiceFactory } from "./messaging-service.factory";
|
import { MessagingServiceInitOptions, messagingServiceFactory } from "./messaging-service.factory";
|
||||||
@ -25,7 +25,7 @@ export function platformUtilsServiceFactory(
|
|||||||
"platformUtilsService",
|
"platformUtilsService",
|
||||||
opts,
|
opts,
|
||||||
async () =>
|
async () =>
|
||||||
new BrowserPlatformUtilsService(
|
new BackgroundPlatformUtilsService(
|
||||||
await messagingServiceFactory(cache, opts),
|
await messagingServiceFactory(cache, opts),
|
||||||
opts.platformUtilsServiceOptions.clipboardWriteCallback,
|
opts.platformUtilsServiceOptions.clipboardWriteCallback,
|
||||||
opts.platformUtilsServiceOptions.biometricCallback,
|
opts.platformUtilsServiceOptions.biometricCallback,
|
||||||
|
@ -3,7 +3,7 @@ import { Observable } from "rxjs";
|
|||||||
import { DeviceType } from "@bitwarden/common/enums";
|
import { DeviceType } from "@bitwarden/common/enums";
|
||||||
|
|
||||||
import { TabMessage } from "../../types/tab-messages";
|
import { TabMessage } from "../../types/tab-messages";
|
||||||
import BrowserPlatformUtilsService from "../services/browser-platform-utils.service";
|
import { BrowserPlatformUtilsService } from "../services/platform-utils/browser-platform-utils.service";
|
||||||
|
|
||||||
export class BrowserApi {
|
export class BrowserApi {
|
||||||
static isWebExtensionsApi: boolean = typeof browser !== "undefined";
|
static isWebExtensionsApi: boolean = typeof browser !== "undefined";
|
||||||
|
@ -17,7 +17,7 @@ import { Account } from "../../models/account";
|
|||||||
import IconDetails from "../../vault/background/models/icon-details";
|
import IconDetails from "../../vault/background/models/icon-details";
|
||||||
import { cipherServiceFactory } from "../../vault/background/service_factories/cipher-service.factory";
|
import { cipherServiceFactory } from "../../vault/background/service_factories/cipher-service.factory";
|
||||||
import { BrowserApi } from "../browser/browser-api";
|
import { BrowserApi } from "../browser/browser-api";
|
||||||
import BrowserPlatformUtilsService from "../services/browser-platform-utils.service";
|
import { BrowserPlatformUtilsService } from "../services/platform-utils/browser-platform-utils.service";
|
||||||
|
|
||||||
export type BadgeOptions = {
|
export type BadgeOptions = {
|
||||||
tab?: chrome.tabs.Tab;
|
tab?: chrome.tabs.Tab;
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||||
|
|
||||||
|
import { BrowserPlatformUtilsService } from "./browser-platform-utils.service";
|
||||||
|
|
||||||
|
export class BackgroundPlatformUtilsService extends BrowserPlatformUtilsService {
|
||||||
|
constructor(
|
||||||
|
private messagingService: MessagingService,
|
||||||
|
clipboardWriteCallback: (clipboardValue: string, clearMs: number) => void,
|
||||||
|
biometricCallback: () => Promise<boolean>,
|
||||||
|
win: Window & typeof globalThis,
|
||||||
|
) {
|
||||||
|
super(clipboardWriteCallback, biometricCallback, win);
|
||||||
|
}
|
||||||
|
|
||||||
|
override 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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,26 @@
|
|||||||
import { DeviceType } from "@bitwarden/common/enums";
|
import { DeviceType } from "@bitwarden/common/enums";
|
||||||
|
|
||||||
import { flushPromises } from "../../autofill/spec/testing-utils";
|
import { flushPromises } from "../../../autofill/spec/testing-utils";
|
||||||
import { SafariApp } from "../../browser/safariApp";
|
import { SafariApp } from "../../../browser/safariApp";
|
||||||
import { BrowserApi } from "../browser/browser-api";
|
import { BrowserApi } from "../../browser/browser-api";
|
||||||
|
import BrowserClipboardService from "../browser-clipboard.service";
|
||||||
|
|
||||||
import BrowserClipboardService from "./browser-clipboard.service";
|
import { BrowserPlatformUtilsService } from "./browser-platform-utils.service";
|
||||||
import BrowserPlatformUtilsService from "./browser-platform-utils.service";
|
|
||||||
|
class TestBrowserPlatformUtilsService extends BrowserPlatformUtilsService {
|
||||||
|
constructor(clipboardSpy: jest.Mock, win: Window & typeof globalThis) {
|
||||||
|
super(clipboardSpy, null, win);
|
||||||
|
}
|
||||||
|
|
||||||
|
showToast(
|
||||||
|
type: "error" | "success" | "warning" | "info",
|
||||||
|
title: string,
|
||||||
|
text: string | string[],
|
||||||
|
options?: any,
|
||||||
|
): void {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
describe("Browser Utils Service", () => {
|
describe("Browser Utils Service", () => {
|
||||||
let browserPlatformUtilsService: BrowserPlatformUtilsService;
|
let browserPlatformUtilsService: BrowserPlatformUtilsService;
|
||||||
@ -13,10 +28,8 @@ describe("Browser Utils Service", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
(window as any).matchMedia = jest.fn().mockReturnValueOnce({});
|
(window as any).matchMedia = jest.fn().mockReturnValueOnce({});
|
||||||
browserPlatformUtilsService = new BrowserPlatformUtilsService(
|
browserPlatformUtilsService = new TestBrowserPlatformUtilsService(
|
||||||
null,
|
|
||||||
clipboardWriteCallbackSpy,
|
clipboardWriteCallbackSpy,
|
||||||
null,
|
|
||||||
window,
|
window,
|
||||||
);
|
);
|
||||||
});
|
});
|
@ -1,20 +1,17 @@
|
|||||||
import { ClientType, DeviceType } from "@bitwarden/common/enums";
|
import { ClientType, DeviceType } from "@bitwarden/common/enums";
|
||||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
|
||||||
import {
|
import {
|
||||||
ClipboardOptions,
|
ClipboardOptions,
|
||||||
PlatformUtilsService,
|
PlatformUtilsService,
|
||||||
} from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
} from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
|
|
||||||
import { SafariApp } from "../../browser/safariApp";
|
import { SafariApp } from "../../../browser/safariApp";
|
||||||
import { BrowserApi } from "../browser/browser-api";
|
import { BrowserApi } from "../../browser/browser-api";
|
||||||
|
import BrowserClipboardService from "../browser-clipboard.service";
|
||||||
|
|
||||||
import BrowserClipboardService from "./browser-clipboard.service";
|
export abstract class BrowserPlatformUtilsService implements PlatformUtilsService {
|
||||||
|
|
||||||
export default class BrowserPlatformUtilsService implements PlatformUtilsService {
|
|
||||||
private static deviceCache: DeviceType = null;
|
private static deviceCache: DeviceType = null;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private messagingService: MessagingService,
|
|
||||||
private clipboardWriteCallback: (clipboardValue: string, clearMs: number) => void,
|
private clipboardWriteCallback: (clipboardValue: string, clearMs: number) => void,
|
||||||
private biometricCallback: () => Promise<boolean>,
|
private biometricCallback: () => Promise<boolean>,
|
||||||
private globalContext: Window | ServiceWorkerGlobalScope,
|
private globalContext: Window | ServiceWorkerGlobalScope,
|
||||||
@ -193,19 +190,12 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
showToast(
|
abstract showToast(
|
||||||
type: "error" | "success" | "warning" | "info",
|
type: "error" | "success" | "warning" | "info",
|
||||||
title: string,
|
title: string,
|
||||||
text: string | string[],
|
text: string | string[],
|
||||||
options?: any,
|
options?: any,
|
||||||
): void {
|
): void;
|
||||||
this.messagingService.send("showToast", {
|
|
||||||
text: text,
|
|
||||||
title: title,
|
|
||||||
type: type,
|
|
||||||
options: options,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
isDev(): boolean {
|
isDev(): boolean {
|
||||||
return process.env.ENV === "development";
|
return process.env.ENV === "development";
|
||||||
@ -279,12 +269,11 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
|
|||||||
|
|
||||||
async supportsBiometric() {
|
async supportsBiometric() {
|
||||||
const platformInfo = await BrowserApi.getPlatformInfo();
|
const platformInfo = await BrowserApi.getPlatformInfo();
|
||||||
if (platformInfo.os === "android") {
|
if (platformInfo.os === "mac" || platformInfo.os === "win") {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
authenticateBiometric() {
|
authenticateBiometric() {
|
||||||
return this.biometricCallback();
|
return this.biometricCallback();
|
@ -0,0 +1,40 @@
|
|||||||
|
import { SecurityContext } from "@angular/core";
|
||||||
|
import { DomSanitizer } from "@angular/platform-browser";
|
||||||
|
import { ToastrService } from "ngx-toastr";
|
||||||
|
|
||||||
|
import { BrowserPlatformUtilsService } from "./browser-platform-utils.service";
|
||||||
|
|
||||||
|
export class ForegroundPlatformUtilsService extends BrowserPlatformUtilsService {
|
||||||
|
constructor(
|
||||||
|
private sanitizer: DomSanitizer,
|
||||||
|
private toastrService: ToastrService,
|
||||||
|
clipboardWriteCallback: (clipboardValue: string, clearMs: number) => void,
|
||||||
|
biometricCallback: () => Promise<boolean>,
|
||||||
|
win: Window & typeof globalThis,
|
||||||
|
) {
|
||||||
|
super(clipboardWriteCallback, biometricCallback, win);
|
||||||
|
}
|
||||||
|
|
||||||
|
override showToast(
|
||||||
|
type: "error" | "success" | "warning" | "info",
|
||||||
|
title: string,
|
||||||
|
text: string | string[],
|
||||||
|
options?: any,
|
||||||
|
): void {
|
||||||
|
if (typeof text === "string") {
|
||||||
|
// Already in the correct format
|
||||||
|
} else if (text.length === 1) {
|
||||||
|
text = text[0];
|
||||||
|
} else {
|
||||||
|
let message = "";
|
||||||
|
text.forEach(
|
||||||
|
(t: string) =>
|
||||||
|
(message += "<p>" + this.sanitizer.sanitize(SecurityContext.HTML, t) + "</p>"),
|
||||||
|
);
|
||||||
|
text = message;
|
||||||
|
options.enableHtml = true;
|
||||||
|
}
|
||||||
|
this.toastrService.show(text, title, options, "toast-" + type);
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
}
|
@ -1,26 +1,17 @@
|
|||||||
import {
|
import { ChangeDetectorRef, Component, NgZone, OnDestroy, OnInit } from "@angular/core";
|
||||||
ChangeDetectorRef,
|
|
||||||
Component,
|
|
||||||
NgZone,
|
|
||||||
OnDestroy,
|
|
||||||
OnInit,
|
|
||||||
SecurityContext,
|
|
||||||
} from "@angular/core";
|
|
||||||
import { DomSanitizer } from "@angular/platform-browser";
|
|
||||||
import { NavigationEnd, Router, RouterOutlet } from "@angular/router";
|
import { NavigationEnd, Router, RouterOutlet } from "@angular/router";
|
||||||
import { IndividualConfig, ToastrService } from "ngx-toastr";
|
import { ToastrService } from "ngx-toastr";
|
||||||
import { filter, concatMap, Subject, takeUntil, firstValueFrom } from "rxjs";
|
import { filter, concatMap, Subject, takeUntil, firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
|
||||||
import { DialogService, SimpleDialogOptions } from "@bitwarden/components";
|
import { DialogService, SimpleDialogOptions } from "@bitwarden/components";
|
||||||
|
|
||||||
import { BrowserApi } from "../platform/browser/browser-api";
|
import { BrowserApi } from "../platform/browser/browser-api";
|
||||||
import { ZonedMessageListenerService } from "../platform/browser/zoned-message-listener.service";
|
import { ZonedMessageListenerService } from "../platform/browser/zoned-message-listener.service";
|
||||||
import { BrowserStateService } from "../platform/services/abstractions/browser-state.service";
|
import { BrowserStateService } from "../platform/services/abstractions/browser-state.service";
|
||||||
|
import { ForegroundPlatformUtilsService } from "../platform/services/platform-utils/foreground-platform-utils.service";
|
||||||
|
|
||||||
import { routerTransition } from "./app-routing.animations";
|
import { routerTransition } from "./app-routing.animations";
|
||||||
import { DesktopSyncVerificationDialogComponent } from "./components/desktop-sync-verification-dialog.component";
|
import { DesktopSyncVerificationDialogComponent } from "./components/desktop-sync-verification-dialog.component";
|
||||||
@ -46,11 +37,9 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private stateService: BrowserStateService,
|
private stateService: BrowserStateService,
|
||||||
private messagingService: MessagingService,
|
|
||||||
private changeDetectorRef: ChangeDetectorRef,
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
private ngZone: NgZone,
|
private ngZone: NgZone,
|
||||||
private sanitizer: DomSanitizer,
|
private platformUtilsService: ForegroundPlatformUtilsService,
|
||||||
private platformUtilsService: PlatformUtilsService,
|
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
private browserMessagingApi: ZonedMessageListenerService,
|
private browserMessagingApi: ZonedMessageListenerService,
|
||||||
) {}
|
) {}
|
||||||
@ -217,31 +206,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private showToast(msg: any) {
|
private showToast(msg: any) {
|
||||||
let message = "";
|
this.platformUtilsService.showToast(msg.type, msg.title, msg.text, msg.options);
|
||||||
|
|
||||||
const options: Partial<IndividualConfig> = {};
|
|
||||||
|
|
||||||
if (typeof msg.text === "string") {
|
|
||||||
message = msg.text;
|
|
||||||
} else if (msg.text.length === 1) {
|
|
||||||
message = msg.text[0];
|
|
||||||
} else {
|
|
||||||
msg.text.forEach(
|
|
||||||
(t: string) =>
|
|
||||||
(message += "<p>" + this.sanitizer.sanitize(SecurityContext.HTML, t) + "</p>"),
|
|
||||||
);
|
|
||||||
options.enableHtml = true;
|
|
||||||
}
|
|
||||||
if (msg.options != null) {
|
|
||||||
if (msg.options.trustedHtml === true) {
|
|
||||||
options.enableHtml = true;
|
|
||||||
}
|
|
||||||
if (msg.options.timeout != null && msg.options.timeout > 0) {
|
|
||||||
options.timeOut = msg.options.timeout;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.toastrService.show(message, msg.title, options, "toast-" + msg.type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async showDialog(msg: SimpleDialogOptions) {
|
private async showDialog(msg: SimpleDialogOptions) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { enableProdMode } from "@angular/core";
|
import { enableProdMode } from "@angular/core";
|
||||||
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
|
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
|
||||||
|
|
||||||
import BrowserPlatformUtilsService from "../platform/services/browser-platform-utils.service";
|
import { BrowserPlatformUtilsService } from "../platform/services/platform-utils/browser-platform-utils.service";
|
||||||
|
|
||||||
require("./scss/popup.scss");
|
require("./scss/popup.scss");
|
||||||
require("./scss/tailwind.css");
|
require("./scss/tailwind.css");
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import { APP_INITIALIZER, NgModule, NgZone } from "@angular/core";
|
import { APP_INITIALIZER, NgModule, NgZone } from "@angular/core";
|
||||||
|
import { DomSanitizer } from "@angular/platform-browser";
|
||||||
|
import { ToastrService } from "ngx-toastr";
|
||||||
|
|
||||||
import { UnauthGuard as BaseUnauthGuardService } from "@bitwarden/angular/auth/guards";
|
import { UnauthGuard as BaseUnauthGuardService } from "@bitwarden/angular/auth/guards";
|
||||||
import { ThemingService } from "@bitwarden/angular/platform/services/theming/theming.service";
|
import { ThemingService } from "@bitwarden/angular/platform/services/theming/theming.service";
|
||||||
@ -117,6 +119,7 @@ import BrowserMessagingPrivateModePopupService from "../../platform/services/bro
|
|||||||
import BrowserMessagingService from "../../platform/services/browser-messaging.service";
|
import BrowserMessagingService from "../../platform/services/browser-messaging.service";
|
||||||
import { BrowserStateService } from "../../platform/services/browser-state.service";
|
import { BrowserStateService } from "../../platform/services/browser-state.service";
|
||||||
import I18nService from "../../platform/services/i18n.service";
|
import I18nService from "../../platform/services/i18n.service";
|
||||||
|
import { ForegroundPlatformUtilsService } from "../../platform/services/platform-utils/foreground-platform-utils.service";
|
||||||
import { ForegroundDerivedStateProvider } from "../../platform/state/foreground-derived-state.provider";
|
import { ForegroundDerivedStateProvider } from "../../platform/state/foreground-derived-state.provider";
|
||||||
import { ForegroundMemoryStorageService } from "../../platform/storage/foreground-memory-storage.service";
|
import { ForegroundMemoryStorageService } from "../../platform/storage/foreground-memory-storage.service";
|
||||||
import { BrowserSendService } from "../../services/browser-send.service";
|
import { BrowserSendService } from "../../services/browser-send.service";
|
||||||
@ -290,8 +293,32 @@ function getBgService<T>(service: keyof MainBackground) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: PlatformUtilsService,
|
provide: PlatformUtilsService,
|
||||||
useFactory: getBgService<PlatformUtilsService>("platformUtilsService"),
|
useExisting: ForegroundPlatformUtilsService,
|
||||||
deps: [],
|
},
|
||||||
|
{
|
||||||
|
provide: ForegroundPlatformUtilsService,
|
||||||
|
useClass: ForegroundPlatformUtilsService,
|
||||||
|
useFactory: (sanitizer: DomSanitizer, toastrService: ToastrService) => {
|
||||||
|
return new ForegroundPlatformUtilsService(
|
||||||
|
sanitizer,
|
||||||
|
toastrService,
|
||||||
|
(clipboardValue: string, clearMs: number) => {
|
||||||
|
void BrowserApi.sendMessage("clearClipboard", { clipboardValue, clearMs });
|
||||||
|
},
|
||||||
|
async () => {
|
||||||
|
const response = await BrowserApi.sendMessageWithResponse<{
|
||||||
|
result: boolean;
|
||||||
|
error: string;
|
||||||
|
}>("biometricUnlock");
|
||||||
|
if (!response.result) {
|
||||||
|
throw response.error;
|
||||||
|
}
|
||||||
|
return response.result;
|
||||||
|
},
|
||||||
|
window,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
deps: [DomSanitizer, ToastrService],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: PasswordStrengthServiceAbstraction,
|
provide: PasswordStrengthServiceAbstraction,
|
||||||
|
@ -397,7 +397,7 @@ export class SettingsComponent implements OnInit {
|
|||||||
// Handle connection errors
|
// Handle connection errors
|
||||||
this.form.controls.biometric.setValue(false);
|
this.form.controls.biometric.setValue(false);
|
||||||
|
|
||||||
const error = BiometricErrors[e as BiometricErrorTypes];
|
const error = BiometricErrors[e.message as BiometricErrorTypes];
|
||||||
|
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
Loading…
Reference in New Issue
Block a user