From edf9024041571681442009edef3780c0ce754517 Mon Sep 17 00:00:00 2001 From: Patrick Pimentel Date: Wed, 16 Jul 2025 17:31:20 -0400 Subject: [PATCH] feat(notification-processing): [PM-19877] System Notification Implementation - Minor changes to popup logic and removed content in login component. --- .../browser/src/background/main.background.ts | 3 +- .../src/background/runtime.background.ts | 3 +- .../actions/browser-actions.service.ts | 5 +++ .../src/popup/services/services.module.ts | 7 ++++ .../src/services/jslib-services.module.ts | 8 +++++ .../auth/src/angular/login/login.component.ts | 36 +------------------ .../src/platform/actions/actions-service.ts | 12 +++++++ .../actions/unsupported-actions.service.ts | 6 +++- .../internal/default-notifications.service.ts | 3 ++ 9 files changed, 44 insertions(+), 39 deletions(-) diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index 75bf509c468..b913c422f23 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -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); diff --git a/apps/browser/src/background/runtime.background.ts b/apps/browser/src/background/runtime.background.ts index c8762e630aa..1af268da01d 100644 --- a/apps/browser/src/background/runtime.background.ts +++ b/apps/browser/src/background/runtime.background.ts @@ -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(); diff --git a/apps/browser/src/platform/actions/browser-actions.service.ts b/apps/browser/src/platform/actions/browser-actions.service.ts index fcf5a2d9682..20e037b30f9 100644 --- a/apps/browser/src/platform/actions/browser-actions.service.ts +++ b/apps/browser/src/platform/actions/browser-actions.service.ts @@ -21,6 +21,11 @@ export class BrowserActionsService implements ActionsService { } case DeviceType.SafariBrowser: case DeviceType.SafariExtension: + break; } } + + openPopupToUrl(url: string): Promise { + return Promise.resolve(undefined); + } } diff --git a/apps/browser/src/popup/services/services.module.ts b/apps/browser/src/popup/services/services.module.ts index 76da465e4b8..9056856b7f1 100644 --- a/apps/browser/src/popup/services/services.module.ts +++ b/apps/browser/src/popup/services/services.module.ts @@ -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: ( diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts index bbd5292ee76..fd1f3e83ad8 100644 --- a/libs/angular/src/services/jslib-services.module.ts +++ b/libs/angular/src/services/jslib-services.module.ts @@ -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({ diff --git a/libs/auth/src/angular/login/login.component.ts b/libs/auth/src/angular/login/login.component.ts index ab10464bc80..b3509850ac0 100644 --- a/libs/auth/src/angular/login/login.component.ts +++ b/libs/auth/src/angular/login/login.component.ts @@ -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 { // Add popstate listener to listen for browser back button clicks window.addEventListener("popstate", this.handlePopState); diff --git a/libs/common/src/platform/actions/actions-service.ts b/libs/common/src/platform/actions/actions-service.ts index 46e1e87326f..a1317975088 100644 --- a/libs/common/src/platform/actions/actions-service.ts +++ b/libs/common/src/platform/actions/actions-service.ts @@ -1,3 +1,15 @@ export abstract class ActionsService { + /** + * Opens the popup. + */ abstract openPopup(): Promise; + + /** + * Opens the popup and navigates to a url. + * + * Stubbed for now. + * + * @param url + */ + abstract openPopupToUrl(url: string): Promise; } diff --git a/libs/common/src/platform/actions/unsupported-actions.service.ts b/libs/common/src/platform/actions/unsupported-actions.service.ts index 9dc05c3665a..aab25f56324 100644 --- a/libs/common/src/platform/actions/unsupported-actions.service.ts +++ b/libs/common/src/platform/actions/unsupported-actions.service.ts @@ -2,6 +2,10 @@ import { ActionsService } from "./actions-service"; export class UnsupportedActionsService implements ActionsService { openPopup(): Promise { - return Promise.resolve(undefined); + throw new Error("Open Popup unsupported."); + } + + openPopupToUrl(url: string): Promise { + throw new Error("Open Popup to Url unsupported."); } } diff --git a/libs/common/src/platform/notifications/internal/default-notifications.service.ts b/libs/common/src/platform/notifications/internal/default-notifications.service.ts index 7f366318ded..618f9bb6ae7 100644 --- a/libs/common/src/platform/notifications/internal/default-notifications.service.ts +++ b/libs/common/src/platform/notifications/internal/default-notifications.service.ts @@ -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, });