From 84e97786691dce5ef9b1003711ed9574a821369c Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Thu, 13 Jun 2024 20:05:05 +0200 Subject: [PATCH 1/8] [PM-4139] Remove approve device logins setting and enable it by default (#9495) * Remove login with device setting and enable it by default * Remove unused i18n message --- .../browser/src/background/main.background.ts | 1 - .../src/app/accounts/settings.component.html | 14 -------- .../src/app/accounts/settings.component.ts | 13 +------- apps/desktop/src/locales/en/messages.json | 6 ---- .../src/vault/app/vault/vault.component.ts | 20 ++++------- .../src/services/jslib-services.module.ts | 1 - .../auth-request.service.abstraction.ts | 14 -------- .../auth-request/auth-request.service.spec.ts | 9 ----- .../auth-request/auth-request.service.ts | 33 ------------------- .../src/services/notifications.service.ts | 14 +++----- 10 files changed, 11 insertions(+), 114 deletions(-) diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index fe797dc8ba1..3aabde40656 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -938,7 +938,6 @@ export default class MainBackground { logoutCallback, this.stateService, this.authService, - this.authRequestService, this.messagingService, ); diff --git a/apps/desktop/src/app/accounts/settings.component.html b/apps/desktop/src/app/accounts/settings.component.html index ae0409cdbc8..9245c51d555 100644 --- a/apps/desktop/src/app/accounts/settings.component.html +++ b/apps/desktop/src/app/accounts/settings.component.html @@ -166,20 +166,6 @@ "recommendedForSecurity" | i18n }} -
-
- -
- {{ "approveLoginRequestDesc" | i18n }} -
diff --git a/apps/desktop/src/app/accounts/settings.component.ts b/apps/desktop/src/app/accounts/settings.component.ts index 6b6a18958f8..2ef5df2c7cb 100644 --- a/apps/desktop/src/app/accounts/settings.component.ts +++ b/apps/desktop/src/app/accounts/settings.component.ts @@ -3,7 +3,7 @@ import { FormBuilder } from "@angular/forms"; import { BehaviorSubject, Observable, Subject, firstValueFrom } from "rxjs"; import { concatMap, debounceTime, filter, map, switchMap, takeUntil, tap } from "rxjs/operators"; -import { AuthRequestServiceAbstraction, PinServiceAbstraction } from "@bitwarden/auth/common"; +import { PinServiceAbstraction } from "@bitwarden/auth/common"; import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyType } from "@bitwarden/common/admin-console/enums"; @@ -90,7 +90,6 @@ export class SettingsComponent implements OnInit { biometric: false, autoPromptBiometrics: false, requirePasswordOnStart: false, - approveLoginRequests: false, // Account Preferences clearClipboard: [null], minimizeOnCopyToClipboard: false, @@ -135,7 +134,6 @@ export class SettingsComponent implements OnInit { private biometricStateService: BiometricStateService, private desktopAutofillSettingsService: DesktopAutofillSettingsService, private pinService: PinServiceAbstraction, - private authRequestService: AuthRequestServiceAbstraction, private logService: LogService, private nativeMessagingManifestService: NativeMessagingManifestService, ) { @@ -275,8 +273,6 @@ export class SettingsComponent implements OnInit { requirePasswordOnStart: await firstValueFrom( this.biometricStateService.requirePasswordOnStart$, ), - approveLoginRequests: - (await this.authRequestService.getAcceptAuthRequests(this.currentUserId)) ?? false, clearClipboard: await firstValueFrom(this.autofillSettingsService.clearClipboardDelay$), minimizeOnCopyToClipboard: await firstValueFrom(this.desktopSettingsService.minimizeOnCopy$), enableFavicons: await firstValueFrom(this.domainSettingsService.showFavicons$), @@ -722,13 +718,6 @@ export class SettingsComponent implements OnInit { ); } - async updateApproveLoginRequests() { - await this.authRequestService.setAcceptAuthRequests( - this.form.value.approveLoginRequests, - this.currentUserId, - ); - } - ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); diff --git a/apps/desktop/src/locales/en/messages.json b/apps/desktop/src/locales/en/messages.json index 82d57c205d4..7846457294e 100644 --- a/apps/desktop/src/locales/en/messages.json +++ b/apps/desktop/src/locales/en/messages.json @@ -2401,9 +2401,6 @@ "denyLogIn": { "message": "Deny login" }, - "approveLoginRequests": { - "message": "Approve login requests" - }, "logInConfirmedForEmailOnDevice": { "message": "Login confirmed for $EMAIL$ on $DEVICE$", "placeholders": { @@ -2438,9 +2435,6 @@ "thisRequestIsNoLongerValid": { "message": "This request is no longer valid." }, - "approveLoginRequestDesc": { - "message": "Use this device to approve login requests made from other devices." - }, "confirmLoginAtemptForMail": { "message": "Confirm login attempt for $EMAIL$", "placeholders": { diff --git a/apps/desktop/src/vault/app/vault/vault.component.ts b/apps/desktop/src/vault/app/vault/vault.component.ts index 37992ecea0e..f8a2bb773e8 100644 --- a/apps/desktop/src/vault/app/vault/vault.component.ts +++ b/apps/desktop/src/vault/app/vault/vault.component.ts @@ -8,7 +8,7 @@ import { ViewContainerRef, } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; -import { firstValueFrom, Subject, takeUntil } from "rxjs"; +import { Subject, takeUntil } from "rxjs"; import { first } from "rxjs/operators"; import { ModalRef } from "@bitwarden/angular/components/modal/modal.ref"; @@ -16,7 +16,6 @@ import { ModalService } from "@bitwarden/angular/services/modal.service"; import { VaultFilter } from "@bitwarden/angular/vault/vault-filter/models/vault-filter.model"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service"; -import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { EventType } from "@bitwarden/common/enums"; import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service"; @@ -32,7 +31,6 @@ import { FolderView } from "@bitwarden/common/vault/models/view/folder.view"; import { DialogService } from "@bitwarden/components"; import { PasswordRepromptService } from "@bitwarden/vault"; -import { AuthRequestServiceAbstraction } from "../../../../../../libs/auth/src/common/abstractions"; import { SearchBarService } from "../../../app/layout/search/search-bar.service"; import { GeneratorComponent } from "../../../app/tools/generator.component"; import { invokeMenu, RendererMenuItem } from "../../../utils"; @@ -107,8 +105,6 @@ export class VaultComponent implements OnInit, OnDestroy { private apiService: ApiService, private dialogService: DialogService, private billingAccountProfileStateService: BillingAccountProfileStateService, - private authRequestService: AuthRequestServiceAbstraction, - private accountService: AccountService, ) {} async ngOnInit() { @@ -226,15 +222,11 @@ export class VaultComponent implements OnInit, OnDestroy { this.searchBarService.setEnabled(true); this.searchBarService.setPlaceholderText(this.i18nService.t("searchVault")); - const userId = (await firstValueFrom(this.accountService.activeAccount$)).id; - const approveLoginRequests = await this.authRequestService.getAcceptAuthRequests(userId); - if (approveLoginRequests) { - const authRequest = await this.apiService.getLastAuthRequest(); - if (authRequest != null) { - this.messagingService.send("openLoginApproval", { - notificationId: authRequest.id, - }); - } + const authRequest = await this.apiService.getLastAuthRequest(); + if (authRequest != null) { + this.messagingService.send("openLoginApproval", { + notificationId: authRequest.id, + }); } } diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts index 8c676bdb9d9..78b2e81672e 100644 --- a/libs/angular/src/services/jslib-services.module.ts +++ b/libs/angular/src/services/jslib-services.module.ts @@ -802,7 +802,6 @@ const safeProviders: SafeProvider[] = [ LOGOUT_CALLBACK, StateServiceAbstraction, AuthServiceAbstraction, - AuthRequestServiceAbstraction, MessagingServiceAbstraction, ], }), diff --git a/libs/auth/src/common/abstractions/auth-request.service.abstraction.ts b/libs/auth/src/common/abstractions/auth-request.service.abstraction.ts index b7ae903eac1..7e82045c5f4 100644 --- a/libs/auth/src/common/abstractions/auth-request.service.abstraction.ts +++ b/libs/auth/src/common/abstractions/auth-request.service.abstraction.ts @@ -10,20 +10,6 @@ export abstract class AuthRequestServiceAbstraction { /** Emits an auth request id when an auth request has been approved. */ authRequestPushNotification$: Observable; - /** - * Returns true if the user has chosen to allow auth requests to show on this client. - * Intended to prevent spamming the user with auth requests. - * @param userId The user id. - * @throws If `userId` is not provided. - */ - abstract getAcceptAuthRequests: (userId: UserId) => Promise; - /** - * Sets whether to allow auth requests to show on this client for this user. - * @param accept Whether to allow auth requests to show on this client. - * @param userId The user id. - * @throws If `userId` is not provided. - */ - abstract setAcceptAuthRequests: (accept: boolean, userId: UserId) => Promise; /** * Returns an admin auth request for the given user if it exists. * @param userId The user id. diff --git a/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts b/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts index 5fa4f26bdd2..a3b4400588b 100644 --- a/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts +++ b/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts @@ -62,15 +62,6 @@ describe("AuthRequestService", () => { }); }); - describe("AcceptAuthRequests", () => { - it("returns an error when userId isn't provided", async () => { - await expect(sut.getAcceptAuthRequests(undefined)).rejects.toThrow("User ID is required"); - await expect(sut.setAcceptAuthRequests(true, undefined)).rejects.toThrow( - "User ID is required", - ); - }); - }); - describe("AdminAuthRequest", () => { it("returns an error when userId isn't provided", async () => { await expect(sut.getAdminAuthRequest(undefined)).rejects.toThrow("User ID is required"); diff --git a/libs/auth/src/common/services/auth-request/auth-request.service.ts b/libs/auth/src/common/services/auth-request/auth-request.service.ts index 6b45bedb21c..028721c5133 100644 --- a/libs/auth/src/common/services/auth-request/auth-request.service.ts +++ b/libs/auth/src/common/services/auth-request/auth-request.service.ts @@ -22,20 +22,6 @@ import { MasterKey, UserKey } from "@bitwarden/common/types/key"; import { AuthRequestServiceAbstraction } from "../../abstractions/auth-request.service.abstraction"; -/** - * Disk-local to maintain consistency between tabs (even though - * approvals are currently only available on desktop). We don't - * want to clear this on logout as it's a user preference. - */ -export const ACCEPT_AUTH_REQUESTS_KEY = new UserKeyDefinition( - AUTH_REQUEST_DISK_LOCAL, - "acceptAuthRequests", - { - deserializer: (value) => value ?? false, - clearOn: [], - }, -); - /** * Disk-local to maintain consistency between tabs. We don't want to * clear this on logout since admin auth requests are long-lived. @@ -64,25 +50,6 @@ export class AuthRequestService implements AuthRequestServiceAbstraction { this.authRequestPushNotification$ = this.authRequestPushNotificationSubject.asObservable(); } - async getAcceptAuthRequests(userId: UserId): Promise { - if (userId == null) { - throw new Error("User ID is required"); - } - - const value = await firstValueFrom( - this.stateProvider.getUser(userId, ACCEPT_AUTH_REQUESTS_KEY).state$, - ); - return value; - } - - async setAcceptAuthRequests(accept: boolean, userId: UserId): Promise { - if (userId == null) { - throw new Error("User ID is required"); - } - - await this.stateProvider.setUserState(ACCEPT_AUTH_REQUESTS_KEY, accept, userId); - } - async getAdminAuthRequest(userId: UserId): Promise { if (userId == null) { throw new Error("User ID is required"); diff --git a/libs/common/src/services/notifications.service.ts b/libs/common/src/services/notifications.service.ts index 51589f52fae..d5c7170e23c 100644 --- a/libs/common/src/services/notifications.service.ts +++ b/libs/common/src/services/notifications.service.ts @@ -4,7 +4,6 @@ import { firstValueFrom } from "rxjs"; import { LogoutReason } from "@bitwarden/auth/common"; -import { AuthRequestServiceAbstraction } from "../../../auth/src/common/abstractions"; import { ApiService } from "../abstractions/api.service"; import { NotificationsService as NotificationsServiceAbstraction } from "../abstractions/notifications.service"; import { AuthService } from "../auth/abstractions/auth.service"; @@ -21,8 +20,7 @@ import { EnvironmentService } from "../platform/abstractions/environment.service import { LogService } from "../platform/abstractions/log.service"; import { MessagingService } from "../platform/abstractions/messaging.service"; import { StateService } from "../platform/abstractions/state.service"; -import { SyncService } from "../platform/sync/sync.service"; -import { UserId } from "../types/guid"; +import { SyncService } from "../vault/abstractions/sync/sync.service.abstraction"; export class NotificationsService implements NotificationsServiceAbstraction { private signalrConnection: signalR.HubConnection; @@ -41,7 +39,6 @@ export class NotificationsService implements NotificationsServiceAbstraction { private logoutCallback: (logoutReason: LogoutReason) => Promise, private stateService: StateService, private authService: AuthService, - private authRequestService: AuthRequestServiceAbstraction, private messagingService: MessagingService, ) { this.environmentService.environment$.subscribe(() => { @@ -205,12 +202,9 @@ export class NotificationsService implements NotificationsServiceAbstraction { break; case NotificationType.AuthRequest: { - const userId = await this.stateService.getUserId(); - if (await this.authRequestService.getAcceptAuthRequests(userId as UserId)) { - this.messagingService.send("openLoginApproval", { - notificationId: notification.payload.id, - }); - } + this.messagingService.send("openLoginApproval", { + notificationId: notification.payload.id, + }); } break; default: From 8be17c28f03825e5f4406989b0d67de27eef8299 Mon Sep 17 00:00:00 2001 From: Thomas Rittson <31796059+eliykat@users.noreply.github.com> Date: Fri, 14 Jun 2024 04:39:44 +1000 Subject: [PATCH 2/8] Improve device-approval command description (#9615) --- .../admin-console/device-approval/device-approval.program.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bitwarden_license/bit-cli/src/admin-console/device-approval/device-approval.program.ts b/bitwarden_license/bit-cli/src/admin-console/device-approval/device-approval.program.ts index 984bd15cde7..181640a5f81 100644 --- a/bitwarden_license/bit-cli/src/admin-console/device-approval/device-approval.program.ts +++ b/bitwarden_license/bit-cli/src/admin-console/device-approval/device-approval.program.ts @@ -26,7 +26,9 @@ export class DeviceApprovalProgram extends BaseProgram { private deviceApprovalCommand() { return new Command("device-approval") - .description("Manage device approvals") + .description( + "Manage device approval requests sent to organizations that use SSO with trusted devices.", + ) .addCommand(this.listCommand()) .addCommand(this.approveCommand()) .addCommand(this.approveAllCommand()) From 2d43a12ce9ed2a43ce91ee8f1c1b635184ca3c59 Mon Sep 17 00:00:00 2001 From: Matt Bishop Date: Thu, 13 Jun 2024 15:08:52 -0400 Subject: [PATCH 3/8] Conditionally use Codecov secret (#9626) --- .github/workflows/test.yml | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7d841ca880e..16238f15308 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,5 +1,4 @@ ---- -name: Run tests +name: Testing on: workflow_dispatch: @@ -8,29 +7,20 @@ on: - "main" - "rc" - "hotfix-rc-*" - pull_request_target: + pull_request: types: [opened, synchronize] -defaults: - run: - shell: bash - jobs: - check-run: - name: Check PR run - uses: bitwarden/gh-actions/.github/workflows/check-run.yml@main - test: name: Run tests runs-on: ubuntu-22.04 - needs: check-run permissions: checks: write contents: read pull-requests: write steps: - - name: Checkout repo + - name: Check out repo uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Get Node Version @@ -75,14 +65,26 @@ jobs: reporter: jest-junit fail-on-error: true + - name: Check for Codecov secret + id: check-codecov-secret + run: | + if [ "${{ secrets.CODECOV_TOKEN }}" != '' ]; then + echo "available=true" >> $GITHUB_OUTPUT; + else + echo "available=false" >> $GITHUB_OUTPUT; + fi + - name: Upload to codecov.io uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # v4.1.0 + if: steps.check-codecov-secret.outputs.available == 'true' env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} rust: - name: rust - ${{ matrix.os }} + name: Run Rust tests on ${{ matrix.os }} runs-on: ${{ matrix.os || 'ubuntu-latest' }} + permissions: + contents: read strategy: matrix: @@ -92,7 +94,7 @@ jobs: - windows-latest steps: - - name: Rust version check + - name: Check Rust version run: rustup --version - name: Install gnome-keyring @@ -101,7 +103,7 @@ jobs: sudo apt-get update sudo apt-get install -y gnome-keyring dbus-x11 - - name: Checkout repo + - name: Check out repo uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Build From 2ff9c3bb766f7bcb37d0084d7dd689e86fda4d27 Mon Sep 17 00:00:00 2001 From: Shane Melton Date: Thu, 13 Jun 2024 13:18:49 -0700 Subject: [PATCH 4/8] [AC-2771] [AC-2772] Provider Restriction Fixes (#9635) * [AC-2771] Do not make API request when restricted provider is not a member of the org * [AC-2771] Fix console errors when switching organizations * [AC-2772] Fix org vault for providers who are members - Show vault filters - Hide header search bar - Show create new item button --- .../vault-collection-row.component.ts | 4 ++-- .../vault-header/vault-header.component.html | 2 +- .../vault-header/vault-header.component.ts | 8 ++++++-- .../src/app/vault/org-vault/vault.component.ts | 16 +++++++++++++++- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/apps/web/src/app/vault/components/vault-items/vault-collection-row.component.ts b/apps/web/src/app/vault/components/vault-items/vault-collection-row.component.ts index 8909c3e8bd9..873bdd3e1a0 100644 --- a/apps/web/src/app/vault/components/vault-items/vault-collection-row.component.ts +++ b/apps/web/src/app/vault/components/vault-items/vault-collection-row.component.ts @@ -69,9 +69,9 @@ export class VaultCollectionRowComponent { if (this.collection instanceof CollectionAdminView) { // Only show AddAccess if unmanaged and allowAdminAccessToAllCollectionItems is disabled return ( - !this.organization.allowAdminAccessToAllCollectionItems && + !this.organization?.allowAdminAccessToAllCollectionItems && this.collection.unmanaged && - this.organization.canEditUnmanagedCollections() + this.organization?.canEditUnmanagedCollections() ); } diff --git a/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.html b/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.html index ee45f5921e5..75ea3fd050b 100644 --- a/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.html +++ b/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.html @@ -93,7 +93,7 @@ (); @@ -352,6 +356,16 @@ export class VaultComponent implements OnInit, OnDestroy { } let ciphers; + // Restricted providers (who are not members) do not have access org cipher endpoint below + // Return early to avoid 404 response + if ( + this.restrictProviderAccessEnabled && + !organization.isMember && + organization.isProviderUser + ) { + return []; + } + if (this.flexibleCollectionsV1Enabled) { // Flexible collections V1 logic. // If the user can edit all ciphers for the organization then fetch them ALL. From d266868dd8a5fdc0ed8ad9989d385831f8c6ea6b Mon Sep 17 00:00:00 2001 From: Bitwarden DevOps <106330231+bitwarden-devops-bot@users.noreply.github.com> Date: Thu, 13 Jun 2024 16:26:52 -0400 Subject: [PATCH 5/8] Bumped client version(s) (#9636) --- apps/web/package.json | 2 +- package-lock.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index 286811dd5c6..b56a3e03d03 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/web-vault", - "version": "2024.6.0", + "version": "2024.6.1", "scripts": { "build:oss": "webpack", "build:bit": "webpack -c ../../bitwarden_license/bit-web/webpack.config.js", diff --git a/package-lock.json b/package-lock.json index ab127c10058..5c5d17352cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -251,7 +251,7 @@ }, "apps/web": { "name": "@bitwarden/web-vault", - "version": "2024.6.0" + "version": "2024.6.1" }, "libs/admin-console": { "name": "@bitwarden/admin-console", From 23330598858114ab632c3560cfcbc65cc38a5da1 Mon Sep 17 00:00:00 2001 From: Shane Melton Date: Thu, 13 Jun 2024 14:11:18 -0700 Subject: [PATCH 6/8] [PM-8831] Hide trashed items from new vault popup lists (#9633) --- .../popup/services/vault-popup-list-filters.service.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.ts b/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.ts index 66e264dd6de..8242637d5de 100644 --- a/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.ts +++ b/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.ts @@ -2,10 +2,10 @@ import { Injectable } from "@angular/core"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { FormBuilder } from "@angular/forms"; import { - Observable, combineLatest, distinctUntilChanged, map, + Observable, startWith, switchMap, tap, @@ -104,6 +104,11 @@ export class VaultPopupListFiltersService { map( (filters) => (ciphers: CipherView[]) => ciphers.filter((cipher) => { + // Vault popup lists never shows deleted ciphers + if (cipher.isDeleted) { + return false; + } + if (filters.cipherType !== null && cipher.type !== filters.cipherType) { return false; } From 2e2061e34ab0c909bb85547eccd6299dcbb3d076 Mon Sep 17 00:00:00 2001 From: Cesar Gonzalez Date: Thu, 13 Jun 2024 21:06:44 -0500 Subject: [PATCH 7/8] [PM-8869] Autofill features broken on Safari --- .../autofill/services/collect-autofill-content.service.ts | 5 +++-- apps/browser/src/autofill/utils/index.ts | 8 ++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/browser/src/autofill/services/collect-autofill-content.service.ts b/apps/browser/src/autofill/services/collect-autofill-content.service.ts index 87470655786..39e75711561 100644 --- a/apps/browser/src/autofill/services/collect-autofill-content.service.ts +++ b/apps/browser/src/autofill/services/collect-autofill-content.service.ts @@ -21,6 +21,7 @@ import { nodeIsFormElement, nodeIsInputElement, sendExtensionMessage, + requestIdleCallbackPolyfill, } from "../utils"; import { AutofillOverlayContentService } from "./abstractions/autofill-overlay-content.service"; @@ -1057,7 +1058,7 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte } if (!this.mutationsQueue.length) { - globalThis.requestIdleCallback(this.processMutations, { timeout: 500 }); + requestIdleCallbackPolyfill(this.processMutations, { timeout: 500 }); } this.mutationsQueue.push(mutations); }; @@ -1194,7 +1195,7 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte continue; } - globalThis.requestIdleCallback( + requestIdleCallbackPolyfill( // We are setting this item to a -1 index because we do not know its position in the DOM. // This value should be updated with the next call to collect page details. () => void this.buildAutofillFieldItem(node as ElementWithOpId, -1), diff --git a/apps/browser/src/autofill/utils/index.ts b/apps/browser/src/autofill/utils/index.ts index cbb0a862e3c..ab01f517e3e 100644 --- a/apps/browser/src/autofill/utils/index.ts +++ b/apps/browser/src/autofill/utils/index.ts @@ -1,6 +1,14 @@ import { AutofillPort } from "../enums/autofill-port.enums"; import { FillableFormFieldElement, FormFieldElement } from "../types"; +export function requestIdleCallbackPolyfill(callback: () => void, options?: Record) { + if ("requestIdleCallback" in globalThis) { + return globalThis.requestIdleCallback(() => callback(), options); + } + + return globalThis.setTimeout(() => callback(), 1); +} + /** * Generates a random string of characters that formatted as a custom element name. */ From 15e4a24b9fabceaa17c305f442e9ed068352538d Mon Sep 17 00:00:00 2001 From: Cesar Gonzalez Date: Thu, 13 Jun 2024 21:07:39 -0500 Subject: [PATCH 8/8] [PM-8869] Autofill features broken on Safari --- apps/browser/src/autofill/utils/index.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/browser/src/autofill/utils/index.ts b/apps/browser/src/autofill/utils/index.ts index ab01f517e3e..e5d20cf9f59 100644 --- a/apps/browser/src/autofill/utils/index.ts +++ b/apps/browser/src/autofill/utils/index.ts @@ -1,6 +1,12 @@ import { AutofillPort } from "../enums/autofill-port.enums"; import { FillableFormFieldElement, FormFieldElement } from "../types"; +/** + * Polyfills the requestIdleCallback API with a setTimeout fallback. + * + * @param callback - The callback function to run when the browser is idle. + * @param options - The options to pass to the requestIdleCallback function. + */ export function requestIdleCallbackPolyfill(callback: () => void, options?: Record) { if ("requestIdleCallback" in globalThis) { return globalThis.requestIdleCallback(() => callback(), options);