Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PM-16804] Add supporting Vault component presentational updates for blocked domains #12720

Merged
merged 16 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions apps/browser/src/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -2339,11 +2339,11 @@
"blockedDomainsDesc": {
"message": "Autofill and other related features will not be offered for these websites. You must refresh the page for changes to take effect."
},
"autofillBlockedNotice": {
"message": "Autofill is blocked for this website. Review or change this in settings."
"autofillBlockedNoticeV2": {
"message": "Autofill is blocked for this website."
},
"autofillBlockedTooltip": {
"message": "Autofill is blocked on this website. Review in settings."
"autofillBlockedNoticeGuidance": {
"message": "Change this in settings"
},
"websiteItemLabel": {
"message": "Website $number$ (URI)",
Expand Down Expand Up @@ -4007,8 +4007,8 @@
"passkeyRemoved": {
"message": "Passkey removed"
},
"autofillSuggestions": {
"message": "Autofill suggestions"
"itemSuggestions": {
"message": "Suggested items"
},
"autofillSuggestionsTip": {
"message": "Save a login item for this site to autofill"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<app-vault-list-items-container
*ngIf="autofillCiphers$ | async as ciphers"
[ciphers]="ciphers"
[title]="'autofillSuggestions' | i18n"
shane-melton marked this conversation as resolved.
Show resolved Hide resolved
[title]="'itemSuggestions' | i18n"
[showRefresh]="showRefresh"
(onRefresh)="refreshCurrentTab()"
[description]="(showEmptyAutofillTip$ | async) ? ('autofillSuggestionsTip' | i18n) : null"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<bit-banner
*ngIf="showCurrentTabIsBlockedBanner$ | async"
bannerType="info"
(onClose)="handleCurrentTabIsBlockedBannerDismiss()"
>
{{ "autofillBlockedNoticeV2" | i18n }}
<a bitLink linkType="secondary" [routerLink]="blockedURISettingsRoute">
{{ "autofillBlockedNoticeGuidance" | i18n }}
</a>
</bit-banner>
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { CommonModule } from "@angular/common";
import { Component, OnInit } from "@angular/core";
import { RouterModule } from "@angular/router";

Check warning on line 3 in apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts#L1-L3

Added lines #L1 - L3 were not covered by tests
import { Observable } from "rxjs";

import { JslibModule } from "@bitwarden/angular/jslib.module";
import {

Check warning on line 7 in apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts#L6-L7

Added lines #L6 - L7 were not covered by tests
BannerModule,
IconButtonModule,
LinkModule,
TypographyModule,
} from "@bitwarden/components";

import { VaultPopupAutofillService } from "../../../services/vault-popup-autofill.service";

Check warning on line 14 in apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts#L14

Added line #L14 was not covered by tests

const blockedURISettingsRoute = "/blocked-domains";

Check warning on line 16 in apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts#L16

Added line #L16 was not covered by tests

@Component({
standalone: true,
imports: [
BannerModule,
CommonModule,
IconButtonModule,
JslibModule,
LinkModule,
RouterModule,
TypographyModule,
],
selector: "blocked-injection-banner",
templateUrl: "blocked-injection-banner.component.html",
})
export class BlockedInjectionBanner implements OnInit {

Check warning on line 32 in apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts#L32

Added line #L32 was not covered by tests
/**
* Flag indicating that the banner should be shown
*/
protected showCurrentTabIsBlockedBanner$: Observable<boolean> =

Check warning on line 36 in apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts#L36

Added line #L36 was not covered by tests
this.vaultPopupAutofillService.showCurrentTabIsBlockedBanner$;

/**
* Hostname for current tab
*/
protected currentTabHostname?: string;

blockedURISettingsRoute: string = blockedURISettingsRoute;

Check warning on line 44 in apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts#L44

Added line #L44 was not covered by tests

constructor(private vaultPopupAutofillService: VaultPopupAutofillService) {}

async ngOnInit() {}

Check warning on line 48 in apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts#L48

Added line #L48 was not covered by tests

async handleCurrentTabIsBlockedBannerDismiss() {
await this.vaultPopupAutofillService.dismissCurrentTabIsBlockedBanner();

Check warning on line 51 in apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts#L51

Added line #L51 was not covered by tests
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,9 @@ <h2 bitTypography="h6">
<button
bit-item-content
type="button"
(click)="primaryActionAutofill ? doAutofill(cipher) : onViewCipher(cipher)"
(click)="primaryActionOnSelect(cipher)"
(dblclick)="launchCipher(cipher)"
[appA11yTitle]="
(primaryActionAutofill ? 'autofillTitle' : 'viewItemTitle') | i18n: cipher.name
"
[appA11yTitle]="cipherItemTitleKey | async | i18n: cipher.name"
class="{{ itemHeightClass }}"
>
<div slot="start" class="tw-justify-start tw-w-7 tw-flex">
Expand All @@ -53,7 +51,7 @@ <h2 bitTypography="h6">
<span slot="secondary">{{ cipher.subTitle }}</span>
</button>
<ng-container slot="end">
<bit-item-action *ngIf="showAutofillButton && !primaryActionAutofill">
<bit-item-action *ngIf="!(hideAutofillButton$ | async)">
<button
type="button"
bitBadge
Expand All @@ -78,7 +76,7 @@ <h2 bitTypography="h6">
<app-item-copy-actions [cipher]="cipher"></app-item-copy-actions>
<app-item-more-options
[cipher]="cipher"
[hideAutofillOptions]="showAutofillButton"
[hideAutofillOptions]="hideAutofillOptions$ | async"
[showViewOption]="primaryActionAutofill"
></app-item-more-options>
</ng-container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
Output,
signal,
} from "@angular/core";
import { Router, RouterLink } from "@angular/router";
import { map } from "rxjs";
import { Router } from "@angular/router";
import { firstValueFrom, Observable, map } from "rxjs";

Check warning on line 16 in apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.ts#L15-L16

Added lines #L15 - L16 were not covered by tests

import { JslibModule } from "@bitwarden/angular/jslib.module";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
Expand Down Expand Up @@ -56,7 +56,6 @@
TypographyModule,
JslibModule,
SectionHeaderComponent,
RouterLink,
ItemCopyActionsComponent,
ItemMoreOptionsComponent,
OrgIconDirective,
Expand Down Expand Up @@ -125,12 +124,41 @@
@Output()
onRefresh = new EventEmitter<void>();

/**
* Flag indicating that the current tab location is blocked
*/
currentURIIsBlocked$: Observable<boolean> =

Check warning on line 130 in apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.ts#L130

Added line #L130 was not covered by tests
this.vaultPopupAutofillService.currentTabIsOnBlocklist$;

/**
* Resolved i18n key to use for suggested cipher items
*/
cipherItemTitleKey = this.currentURIIsBlocked$.pipe(

Check warning on line 136 in apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.ts#L136

Added line #L136 was not covered by tests
map((uriIsBlocked) =>
this.primaryActionAutofill && !uriIsBlocked ? "autofillTitle" : "viewItemTitle",
),
);

/**
* Option to show the autofill button for each item.
*/
@Input({ transform: booleanAttribute })
showAutofillButton: boolean;

/**
* Flag indicating whether the suggested cipher item autofill button should be shown or not
*/
hideAutofillButton$ = this.currentURIIsBlocked$.pipe(

Check warning on line 151 in apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.ts#L151

Added line #L151 was not covered by tests
map((uriIsBlocked) => !this.showAutofillButton || uriIsBlocked || this.primaryActionAutofill),
);

/**
* Flag indicating whether the cipher item autofill options should be shown or not
*/
hideAutofillOptions$: Observable<boolean> = this.currentURIIsBlocked$.pipe(

Check warning on line 158 in apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.ts#L158

Added line #L158 was not covered by tests
map((uriIsBlocked) => uriIsBlocked || this.showAutofillButton),
);

/**
* Option to perform autofill operation as the primary action for autofill suggestions.
*/
Expand Down Expand Up @@ -180,6 +208,14 @@
}
}

async primaryActionOnSelect(cipher: CipherView) {
const isBlocked = await firstValueFrom(this.currentURIIsBlocked$);

Check warning on line 212 in apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.ts#L212

Added line #L212 was not covered by tests

return this.primaryActionAutofill && !isBlocked
? this.doAutofill(cipher)
: this.onViewCipher(cipher);
}

/**
* Launches the login cipher in a new browser tab.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
</bit-no-items>
</div>

<blocked-injection-banner
gbubemismith marked this conversation as resolved.
Show resolved Hide resolved
*ngIf="vaultState !== VaultStateEnum.Empty"
slot="full-width-notice"
></blocked-injection-banner>

<!-- Show search & filters outside of the scroll area of the page -->
<ng-container
slot="above-scroll-area"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import { VaultPopupListFiltersService } from "../../services/vault-popup-list-filters.service";
import { VaultUiOnboardingService } from "../../services/vault-ui-onboarding.service";

import { BlockedInjectionBanner } from "./blocked-injection-banner/blocked-injection-banner.component";

Check warning on line 24 in apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.ts#L24

Added line #L24 was not covered by tests
import {
NewItemDropdownV2Component,
NewItemInitialValues,
Expand All @@ -40,6 +41,7 @@
templateUrl: "vault-v2.component.html",
standalone: true,
imports: [
BlockedInjectionBanner,
PopupPageComponent,
PopupHeaderComponent,
PopOutComponent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { mock } from "jest-mock-extended";
import { BehaviorSubject, of } from "rxjs";

import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
Expand Down Expand Up @@ -42,6 +43,7 @@ describe("VaultPopupAutofillService", () => {

// Create mocks for VaultPopupAutofillService
const mockAutofillService = mock<AutofillService>();
const mockDomainSettingsService = mock<DomainSettingsService>();
const mockI18nService = mock<I18nService>();
const mockToastService = mock<ToastService>();
const mockPlatformUtilsService = mock<PlatformUtilsService>();
Expand Down Expand Up @@ -69,6 +71,7 @@ describe("VaultPopupAutofillService", () => {
testBed = TestBed.configureTestingModule({
providers: [
{ provide: AutofillService, useValue: mockAutofillService },
{ provide: DomainSettingsService, useValue: mockDomainSettingsService },
{ provide: I18nService, useValue: mockI18nService },
{ provide: ToastService, useValue: mockToastService },
{ provide: PlatformUtilsService, useValue: mockPlatformUtilsService },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
} from "rxjs";

import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
Expand Down Expand Up @@ -65,6 +66,72 @@
shareReplay({ refCount: false, bufferSize: 1 }),
);

currentTabIsOnBlocklist$: Observable<boolean> = combineLatest([
this.domainSettingsService.blockedInteractionsUris$,
this.currentAutofillTab$,
]).pipe(
map(([blockedInteractionsUris, currentTab]) => {
if (blockedInteractionsUris && currentTab?.url?.length) {
const tabURL = new URL(currentTab.url);
const tabIsBlocked = Object.keys(blockedInteractionsUris).includes(tabURL.hostname);

if (tabIsBlocked) {

Check warning on line 78 in apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts#L77-L78

Added lines #L77 - L78 were not covered by tests
return true;
}
}

Check warning on line 81 in apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts#L81

Added line #L81 was not covered by tests

return false;
}),
shane-melton marked this conversation as resolved.
Show resolved Hide resolved
shareReplay({ refCount: false, bufferSize: 1 }),

Check warning on line 85 in apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts#L85

Added line #L85 was not covered by tests
);

showCurrentTabIsBlockedBanner$: Observable<boolean> = combineLatest([
this.domainSettingsService.blockedInteractionsUris$,
this.currentAutofillTab$,
]).pipe(
map(([blockedInteractionsUris, currentTab]) => {
if (blockedInteractionsUris && currentTab?.url?.length) {
const tabURL = new URL(currentTab.url);
const tabIsBlocked = Object.keys(blockedInteractionsUris).includes(tabURL.hostname);

const showScriptInjectionIsBlockedBanner =

Check warning on line 97 in apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts#L96-L97

Added lines #L96 - L97 were not covered by tests
tabIsBlocked && !blockedInteractionsUris[tabURL.hostname]?.bannerIsDismissed;

return showScriptInjectionIsBlockedBanner;
}

Check warning on line 102 in apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts#L102

Added line #L102 was not covered by tests
return false;
}),
shane-melton marked this conversation as resolved.
Show resolved Hide resolved
shareReplay({ refCount: false, bufferSize: 1 }),

Check warning on line 105 in apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts#L105

Added line #L105 was not covered by tests
);

async dismissCurrentTabIsBlockedBanner() {
try {
const currentTab = await firstValueFrom(this.currentAutofillTab$);
const currentTabURL = currentTab?.url.length && new URL(currentTab.url);

Check warning on line 112 in apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts#L111-L112

Added lines #L111 - L112 were not covered by tests
const currentTabHostname = currentTabURL && currentTabURL.hostname;

if (!currentTabHostname) {
return;
}

Check warning on line 118 in apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts#L118

Added line #L118 was not covered by tests
const blockedURIs = await firstValueFrom(this.domainSettingsService.blockedInteractionsUris$);
const tabIsBlocked = Object.keys(blockedURIs).includes(currentTabHostname);

if (tabIsBlocked) {

Check warning on line 122 in apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts#L121-L122

Added lines #L121 - L122 were not covered by tests
void this.domainSettingsService.setBlockedInteractionsUris({
...blockedURIs,
[currentTabHostname as string]: { bannerIsDismissed: true },

Check warning on line 125 in apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts#L125

Added line #L125 was not covered by tests
});
}
} catch (e) {
throw new Error(
"There was a problem dismissing the blocked interaction URI notification banner",
);

Check warning on line 131 in apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts#L131

Added line #L131 was not covered by tests
}
}

/**
* Observable that indicates whether autofill is allowed in the current context.
* Autofill is allowed when there is a current tab and the popup is not in a popout window.
Expand Down Expand Up @@ -123,6 +190,7 @@

constructor(
private autofillService: AutofillService,
private domainSettingsService: DomainSettingsService,
private i18nService: I18nService,
private toastService: ToastService,
private platformUtilService: PlatformUtilsService,
Expand Down
Loading