mirror of
https://github.com/bitwarden/browser
synced 2025-12-20 10:13:31 +00:00
Add Web Push Support (#11346)
* WIP: PoC with lots of terrible code with web push * fix service worker building * Work on WebPush Tailored to Browser * Clean Up Web And MV2 * Fix Merge Conflicts * Prettier * Use Unsupported for MV2 * Add Doc Comments * Remove Permission Button * Fix Type Test * Write Time In More Readable Format * Add SignalR Logger * `sheduleReconnect` -> `scheduleReconnect` Co-authored-by: Matt Gibson <mgibson@bitwarden.com> * Capture Support Context In Connector * Remove Unneeded CSP Change * Fix Build * Simplify `getOrCreateSubscription` * Add More Docs to Matrix * Update libs/common/src/platform/notifications/internal/worker-webpush-connection.service.ts Co-authored-by: Matt Gibson <mgibson@bitwarden.com> * Move API Service Into Notifications Folder * Allow Connection When Account Is Locked * Add Comments to NotificationsService * Only Change Support Status If Public Key Changes * Move Service Choice Out To Method * Use Named Constant For Disabled Notification Url * Add Test & Cleanup * Flatten * Move Tests into `beforeEach` & `afterEach` * Add Tests * Test `distinctUntilChanged`'s Operators More * Make Helper And Cleanup Chain * Add Back Cast * Add extra safety to incoming config check * Put data through response object * Apply TS Strict Rules * Finish PushTechnology comment * Use `instanceof` check * Do Safer Worker Based Registration for MV3 * Remove TODO * Switch to SignalR on any WebPush Error * Fix Manifest Permissions * Add Back `webNavigation` * Sorry, Remove `webNavigation` * Fixed merge conflicts. --------- Co-authored-by: Matt Gibson <mgibson@bitwarden.com> Co-authored-by: Todd Martin <tmartin@bitwarden.com> Co-authored-by: Todd Martin <106564991+trmartin4@users.noreply.github.com>
This commit is contained in:
@@ -2,11 +2,11 @@
|
||||
// @ts-strict-ignore
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { NotificationsService } from "@bitwarden/common/abstractions/notifications.service";
|
||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
||||
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
|
||||
import { NotificationsService } from "@bitwarden/common/platform/notifications";
|
||||
import { VaultTimeoutStringType } from "@bitwarden/common/types/vault-timeout.type";
|
||||
|
||||
const IdleInterval = 60 * 5; // 5 minutes
|
||||
|
||||
@@ -18,7 +18,6 @@ import { ApiService as ApiServiceAbstraction } from "@bitwarden/common/abstracti
|
||||
import { AuditService as AuditServiceAbstraction } from "@bitwarden/common/abstractions/audit.service";
|
||||
import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||
import { EventUploadService as EventUploadServiceAbstraction } from "@bitwarden/common/abstractions/event/event-upload.service";
|
||||
import { NotificationsService as NotificationsServiceAbstraction } from "@bitwarden/common/abstractions/notifications.service";
|
||||
import { SearchService as SearchServiceAbstraction } from "@bitwarden/common/abstractions/search.service";
|
||||
import { VaultTimeoutSettingsService as VaultTimeoutSettingsServiceAbstraction } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
||||
import { InternalOrganizationServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
@@ -109,6 +108,14 @@ import { clearCaches } from "@bitwarden/common/platform/misc/sequentialize";
|
||||
import { Account } from "@bitwarden/common/platform/models/domain/account";
|
||||
import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import { NotificationsService } from "@bitwarden/common/platform/notifications";
|
||||
import {
|
||||
DefaultNotificationsService,
|
||||
WorkerWebPushConnectionService,
|
||||
SignalRConnectionService,
|
||||
UnsupportedWebPushConnectionService,
|
||||
WebPushNotificationsApiService,
|
||||
} from "@bitwarden/common/platform/notifications/internal";
|
||||
import { ScheduledTaskNames } from "@bitwarden/common/platform/scheduling";
|
||||
import { AppIdService } from "@bitwarden/common/platform/services/app-id.service";
|
||||
import { ConfigApiService } from "@bitwarden/common/platform/services/config/config-api.service";
|
||||
@@ -159,7 +166,6 @@ import { ApiService } from "@bitwarden/common/services/api.service";
|
||||
import { AuditService } from "@bitwarden/common/services/audit.service";
|
||||
import { EventCollectionService } from "@bitwarden/common/services/event/event-collection.service";
|
||||
import { EventUploadService } from "@bitwarden/common/services/event/event-upload.service";
|
||||
import { NotificationsService } from "@bitwarden/common/services/notifications.service";
|
||||
import { SearchService } from "@bitwarden/common/services/search.service";
|
||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/services/vault-timeout/vault-timeout-settings.service";
|
||||
import {
|
||||
@@ -314,7 +320,7 @@ export default class MainBackground {
|
||||
importService: ImportServiceAbstraction;
|
||||
exportService: VaultExportServiceAbstraction;
|
||||
searchService: SearchServiceAbstraction;
|
||||
notificationsService: NotificationsServiceAbstraction;
|
||||
notificationsService: NotificationsService;
|
||||
stateService: StateServiceAbstraction;
|
||||
userNotificationSettingsService: UserNotificationSettingsServiceAbstraction;
|
||||
autofillSettingsService: AutofillSettingsServiceAbstraction;
|
||||
@@ -378,6 +384,8 @@ export default class MainBackground {
|
||||
kdfConfigService: KdfConfigService;
|
||||
offscreenDocumentService: OffscreenDocumentService;
|
||||
syncServiceListener: SyncServiceListener;
|
||||
|
||||
webPushConnectionService: WorkerWebPushConnectionService | UnsupportedWebPushConnectionService;
|
||||
themeStateService: DefaultThemeStateService;
|
||||
autoSubmitLoginBackground: AutoSubmitLoginBackground;
|
||||
sdkService: SdkService;
|
||||
@@ -408,11 +416,6 @@ export default class MainBackground {
|
||||
constructor() {
|
||||
// Services
|
||||
const lockedCallback = async (userId?: string) => {
|
||||
if (this.notificationsService != null) {
|
||||
// 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.notificationsService.updateConnection(false);
|
||||
}
|
||||
await this.refreshBadge();
|
||||
await this.refreshMenu(true);
|
||||
if (this.systemService != null) {
|
||||
@@ -1034,17 +1037,34 @@ export default class MainBackground {
|
||||
this.organizationVaultExportService,
|
||||
);
|
||||
|
||||
this.notificationsService = new NotificationsService(
|
||||
this.logService,
|
||||
if (BrowserApi.isManifestVersion(3)) {
|
||||
const registration = (self as unknown as { registration: ServiceWorkerRegistration })
|
||||
?.registration;
|
||||
|
||||
if (registration != null) {
|
||||
this.webPushConnectionService = new WorkerWebPushConnectionService(
|
||||
this.configService,
|
||||
new WebPushNotificationsApiService(this.apiService, this.appIdService),
|
||||
registration,
|
||||
);
|
||||
} else {
|
||||
this.webPushConnectionService = new UnsupportedWebPushConnectionService();
|
||||
}
|
||||
} else {
|
||||
this.webPushConnectionService = new UnsupportedWebPushConnectionService();
|
||||
}
|
||||
|
||||
this.notificationsService = new DefaultNotificationsService(
|
||||
this.syncService,
|
||||
this.appIdService,
|
||||
this.apiService,
|
||||
this.environmentService,
|
||||
logoutCallback,
|
||||
this.stateService,
|
||||
this.authService,
|
||||
this.messagingService,
|
||||
this.taskSchedulerService,
|
||||
this.accountService,
|
||||
new SignalRConnectionService(this.apiService, this.logService),
|
||||
this.authService,
|
||||
this.webPushConnectionService,
|
||||
this.logService,
|
||||
);
|
||||
|
||||
this.fido2UserInterfaceService = new BrowserFido2UserInterfaceService(this.authService);
|
||||
@@ -1259,6 +1279,9 @@ export default class MainBackground {
|
||||
}
|
||||
|
||||
async bootstrap() {
|
||||
if (this.webPushConnectionService instanceof WorkerWebPushConnectionService) {
|
||||
this.webPushConnectionService.start();
|
||||
}
|
||||
this.containerService.attachToGlobal(self);
|
||||
|
||||
await this.sdkLoadService.load();
|
||||
@@ -1324,12 +1347,7 @@ export default class MainBackground {
|
||||
setTimeout(async () => {
|
||||
await this.refreshBadge();
|
||||
await this.fullSync(false);
|
||||
this.taskSchedulerService.setInterval(
|
||||
ScheduledTaskNames.scheduleNextSyncInterval,
|
||||
5 * 60 * 1000, // check every 5 minutes
|
||||
);
|
||||
setTimeout(() => this.notificationsService.init(), 2500);
|
||||
await this.taskSchedulerService.verifyAlarmsState();
|
||||
this.notificationsService.startListening();
|
||||
resolve();
|
||||
}, 500);
|
||||
});
|
||||
@@ -1408,7 +1426,6 @@ export default class MainBackground {
|
||||
ForceSetPasswordReason.None;
|
||||
|
||||
await this.systemService.clearPendingClipboard();
|
||||
await this.notificationsService.updateConnection(false);
|
||||
|
||||
if (nextAccountStatus === AuthenticationStatus.LoggedOut) {
|
||||
this.messagingService.send("goHome");
|
||||
@@ -1512,7 +1529,6 @@ export default class MainBackground {
|
||||
}
|
||||
await this.refreshBadge();
|
||||
await this.mainContextMenuHandler?.noAccess();
|
||||
await this.notificationsService.updateConnection(false);
|
||||
await this.systemService.clearPendingClipboard();
|
||||
await this.processReloadService.startProcessReload(this.authService);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import { firstValueFrom, map, mergeMap } from "rxjs";
|
||||
|
||||
import { LockService } from "@bitwarden/auth/common";
|
||||
import { NotificationsService } from "@bitwarden/common/abstractions/notifications.service";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { AutofillOverlayVisibility, ExtensionCommand } from "@bitwarden/common/autofill/constants";
|
||||
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
||||
@@ -16,6 +15,7 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag
|
||||
import { MessageListener, isExternalMessage } from "@bitwarden/common/platform/messaging";
|
||||
import { devFlagEnabled } from "@bitwarden/common/platform/misc/flags";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { NotificationsService } from "@bitwarden/common/platform/notifications";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||
import { BiometricsCommands } from "@bitwarden/key-management";
|
||||
|
||||
@@ -240,7 +240,6 @@ export default class RuntimeBackground {
|
||||
await closeUnlockPopout();
|
||||
}
|
||||
|
||||
await this.notificationsService.updateConnection(msg.command === "loggedIn");
|
||||
this.processReloadSerivce.cancelProcessReload();
|
||||
|
||||
if (item) {
|
||||
|
||||
@@ -60,7 +60,8 @@
|
||||
"unlimitedStorage",
|
||||
"webNavigation",
|
||||
"webRequest",
|
||||
"webRequestAuthProvider"
|
||||
"webRequestAuthProvider",
|
||||
"notifications"
|
||||
],
|
||||
"__safari__permissions": [
|
||||
"activeTab",
|
||||
|
||||
Reference in New Issue
Block a user