1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-12 14:34:02 +00:00

feat(notification-processing): [PM-19877] System Notification Implementation - Minor changes to popup logic and removed content in login component.

This commit is contained in:
Patrick Pimentel
2025-07-16 17:31:20 -04:00
parent f16194696a
commit edf9024041
9 changed files with 44 additions and 39 deletions

View File

@@ -1134,7 +1134,7 @@ export default class MainBackground {
const userAgent = navigator.userAgent;
const isChrome =
userAgent.includes("Chrome") && !userAgent.includes("Edge") && !userAgent.includes("OPR");
userAgent.includes("Chrome") || userAgent.includes("Edge") || userAgent.includes("OPR");
const isSafari = userAgent.includes("Safari") && !userAgent.includes("Chrome");
const isFirefox = userAgent.includes("Firefox");
@@ -1158,6 +1158,7 @@ export default class MainBackground {
new SignalRConnectionService(this.apiService, this.logService),
this.authService,
this.webPushConnectionService,
this.actionsService,
);
this.fido2UserInterfaceService = new BrowserFido2UserInterfaceService(this.authService);

View File

@@ -427,8 +427,7 @@ export default class RuntimeBackground {
/**
* Opens the popup.
*
* Migrating to the browser actions service, not deprecating yet.
* @private
* @deprecated Migrating to the browser actions service.
*/
private async openPopup() {
await this.main.openPopup();

View File

@@ -21,6 +21,11 @@ export class BrowserActionsService implements ActionsService {
}
case DeviceType.SafariBrowser:
case DeviceType.SafariExtension:
break;
}
}
openPopupToUrl(url: string): Promise<void> {
return Promise.resolve(undefined);
}
}

View File

@@ -91,6 +91,7 @@ import {
AbstractStorageService,
ObservableStorageService,
} from "@bitwarden/common/platform/abstractions/storage.service";
import { ActionsService } from "@bitwarden/common/platform/actions";
import { Message, MessageListener, MessageSender } from "@bitwarden/common/platform/messaging";
// eslint-disable-next-line no-restricted-imports -- Used for dependency injection
import { SubjectMessageSender } from "@bitwarden/common/platform/messaging/internal";
@@ -158,6 +159,7 @@ import { InlineMenuFieldQualificationService } from "../../autofill/services/inl
import { ForegroundBrowserBiometricsService } from "../../key-management/biometrics/foreground-browser-biometrics";
import { ExtensionLockComponentService } from "../../key-management/lock/services/extension-lock-component.service";
import { ForegroundVaultTimeoutService } from "../../key-management/vault-timeout/foreground-vault-timeout.service";
import { BrowserActionsService } from "../../platform/actions/browser-actions.service";
import { BrowserApi } from "../../platform/browser/browser-api";
import { runInsideAngular } from "../../platform/browser/run-inside-angular.operator";
/* eslint-disable no-restricted-imports */
@@ -252,6 +254,11 @@ const safeProviders: SafeProvider[] = [
},
deps: [GlobalStateProvider],
}),
safeProvider({
provide: ActionsService,
useClass: BrowserActionsService,
deps: [PlatformUtilsServiceAbstraction],
}),
safeProvider({
provide: KeyService,
useFactory: (

View File

@@ -198,6 +198,8 @@ import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.serv
import { StateService as StateServiceAbstraction } from "@bitwarden/common/platform/abstractions/state.service";
import { AbstractStorageService } from "@bitwarden/common/platform/abstractions/storage.service";
import { ValidationService as ValidationServiceAbstraction } from "@bitwarden/common/platform/abstractions/validation.service";
import { ActionsService } from "@bitwarden/common/platform/actions";
import { UnsupportedActionsService } from "@bitwarden/common/platform/actions/unsupported-actions.service";
import { StateFactory } from "@bitwarden/common/platform/factories/state-factory";
import { Message, MessageListener, MessageSender } from "@bitwarden/common/platform/messaging";
// eslint-disable-next-line no-restricted-imports -- Used for dependency injection
@@ -944,6 +946,11 @@ const safeProviders: SafeProvider[] = [
useClass: UnsupportedWebPushConnectionService,
deps: [],
}),
safeProvider({
provide: ActionsService,
useClass: UnsupportedActionsService,
deps: [],
}),
safeProvider({
provide: ServerNotificationsService,
useClass: devFlagEnabled("noopNotifications")
@@ -960,6 +967,7 @@ const safeProviders: SafeProvider[] = [
SignalRConnectionService,
AuthServiceAbstraction,
WebPushConnectionService,
ActionsService,
],
}),
safeProvider({

View File

@@ -1,13 +1,5 @@
import { CommonModule } from "@angular/common";
import {
Component,
ElementRef,
HostListener,
NgZone,
OnDestroy,
OnInit,
ViewChild,
} from "@angular/core";
import { Component, ElementRef, NgZone, OnDestroy, OnInit, ViewChild } from "@angular/core";
import { FormBuilder, FormControl, ReactiveFormsModule, Validators } from "@angular/forms";
import { ActivatedRoute, Router, RouterModule } from "@angular/router";
import { firstValueFrom, Subject, take, takeUntil } from "rxjs";
@@ -38,10 +30,6 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import {
ButtonActions,
SystemNotificationService,
} from "@bitwarden/common/platform/notifications/system-notification-service";
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
import { UserId } from "@bitwarden/common/types/guid";
// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop.
@@ -139,32 +127,10 @@ export class LoginComponent implements OnInit, OnDestroy {
private loginSuccessHandlerService: LoginSuccessHandlerService,
private masterPasswordService: MasterPasswordServiceAbstraction,
private configService: ConfigService,
private systemNotificationService: SystemNotificationService,
) {
this.clientType = this.platformUtilsService.getClientType();
}
@HostListener("document:keydown.control.b", ["$event"])
async onCtrlB(event: KeyboardEvent) {
if (process.env.ENV === "development") {
event.preventDefault();
await this.systemNotificationService.create({
id: Math.random() * 10000000 + "",
type: ButtonActions.AuthRequestNotification,
title: "Test",
body: "Body",
buttons: [],
});
}
// this.systemNotificationService.notificationClicked$.pipe(takeUntilDestroyed()).subscribe((value) => {
// if (value == ButtonActions.AuthRequestNotification)
// });
// this.ngZone.onStable.pipe(take(1), takeUntil(this.destroy$)).subscribe(() => {
// this.masterPasswordInputRef?.nativeElement?.focus();
// });
}
async ngOnInit(): Promise<void> {
// Add popstate listener to listen for browser back button clicks
window.addEventListener("popstate", this.handlePopState);

View File

@@ -1,3 +1,15 @@
export abstract class ActionsService {
/**
* Opens the popup.
*/
abstract openPopup(): Promise<void>;
/**
* Opens the popup and navigates to a url.
*
* Stubbed for now.
*
* @param url
*/
abstract openPopupToUrl(url: string): Promise<void>;
}

View File

@@ -2,6 +2,10 @@ import { ActionsService } from "./actions-service";
export class UnsupportedActionsService implements ActionsService {
openPopup(): Promise<void> {
return Promise.resolve(undefined);
throw new Error("Open Popup unsupported.");
}
openPopupToUrl(url: string): Promise<void> {
throw new Error("Open Popup to Url unsupported.");
}
}

View File

@@ -14,6 +14,7 @@ import {
// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop.
// eslint-disable-next-line no-restricted-imports
import { LogoutReason } from "@bitwarden/auth/common";
import { ActionsService } from "@bitwarden/common/platform/actions";
import { AccountService } from "../../../auth/abstractions/account.service";
import { AuthService } from "../../../auth/abstractions/auth.service";
@@ -55,6 +56,7 @@ export class DefaultNotificationsService implements NotificationsServiceAbstract
private readonly signalRConnectionService: SignalRConnectionService,
private readonly authService: AuthService,
private readonly webPushConnectionService: WebPushConnectionService,
private readonly actionsService: ActionsService,
) {
this.notifications$ = this.accountService.activeAccount$.pipe(
map((account) => account?.id),
@@ -213,6 +215,7 @@ export class DefaultNotificationsService implements NotificationsServiceAbstract
await this.syncService.syncDeleteSend(notification.payload as SyncSendNotification);
break;
case NotificationType.AuthRequest:
await this.actionsService.openPopup();
this.messagingService.send("openLoginApproval", {
notificationId: notification.payload.id,
});