mirror of
https://github.com/bitwarden/browser
synced 2025-12-19 09:43:23 +00:00
add dismissable banner to the vault view when the active autofill tab is on the blocked domains list
This commit is contained in:
@@ -2339,6 +2339,12 @@
|
|||||||
"blockedDomainsDesc": {
|
"blockedDomainsDesc": {
|
||||||
"message": "Autofill and other related features will not be offered for these websites. You must refresh the page for changes to take effect."
|
"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."
|
||||||
|
},
|
||||||
|
"autofillBlockedTooltip": {
|
||||||
|
"message": "Autofill is blocked on this website. Review in settings."
|
||||||
|
},
|
||||||
"websiteItemLabel": {
|
"websiteItemLabel": {
|
||||||
"message": "Website $number$ (URI)",
|
"message": "Website $number$ (URI)",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
|
|||||||
@@ -22,6 +22,15 @@
|
|||||||
</bit-no-items>
|
</bit-no-items>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<bit-banner
|
||||||
|
*ngIf="vaultState !== VaultStateEnum.Empty && showScriptInjectionIsBlockedBanner"
|
||||||
|
id="domain-script-injection-blocked-banner"
|
||||||
|
bannerType="info"
|
||||||
|
(onClose)="handleScriptInjectionIsBlockedBannerDismiss()"
|
||||||
|
>
|
||||||
|
{{ "autofillBlockedNotice" | i18n }}
|
||||||
|
</bit-banner>
|
||||||
|
|
||||||
<!-- Show search & filters outside of the scroll area of the page -->
|
<!-- Show search & filters outside of the scroll area of the page -->
|
||||||
<ng-container
|
<ng-container
|
||||||
slot="above-scroll-area"
|
slot="above-scroll-area"
|
||||||
|
|||||||
@@ -3,18 +3,20 @@ import { CommonModule } from "@angular/common";
|
|||||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||||
import { RouterLink } from "@angular/router";
|
import { RouterLink } from "@angular/router";
|
||||||
import { combineLatest, Observable, shareReplay, switchMap } from "rxjs";
|
import { combineLatest, firstValueFrom, Observable, shareReplay, switchMap } from "rxjs";
|
||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
|
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||||
import { CollectionId, OrganizationId } from "@bitwarden/common/types/guid";
|
import { CollectionId, OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||||
import { ButtonModule, Icons, NoItemsModule } from "@bitwarden/components";
|
import { BannerModule, ButtonModule, Icons, NoItemsModule } from "@bitwarden/components";
|
||||||
import { VaultIcons } from "@bitwarden/vault";
|
import { VaultIcons } from "@bitwarden/vault";
|
||||||
|
|
||||||
import { CurrentAccountComponent } from "../../../../auth/popup/account-switching/current-account.component";
|
import { CurrentAccountComponent } from "../../../../auth/popup/account-switching/current-account.component";
|
||||||
import { PopOutComponent } from "../../../../platform/popup/components/pop-out.component";
|
import { PopOutComponent } from "../../../../platform/popup/components/pop-out.component";
|
||||||
import { PopupHeaderComponent } from "../../../../platform/popup/layout/popup-header.component";
|
import { PopupHeaderComponent } from "../../../../platform/popup/layout/popup-header.component";
|
||||||
import { PopupPageComponent } from "../../../../platform/popup/layout/popup-page.component";
|
import { PopupPageComponent } from "../../../../platform/popup/layout/popup-page.component";
|
||||||
|
import { VaultPopupAutofillService } from "../../services/vault-popup-autofill.service";
|
||||||
import { VaultPopupItemsService } from "../../services/vault-popup-items.service";
|
import { VaultPopupItemsService } from "../../services/vault-popup-items.service";
|
||||||
import { VaultPopupListFiltersService } from "../../services/vault-popup-list-filters.service";
|
import { VaultPopupListFiltersService } from "../../services/vault-popup-list-filters.service";
|
||||||
import { VaultUiOnboardingService } from "../../services/vault-ui-onboarding.service";
|
import { VaultUiOnboardingService } from "../../services/vault-ui-onboarding.service";
|
||||||
@@ -45,6 +47,7 @@ enum VaultState {
|
|||||||
CommonModule,
|
CommonModule,
|
||||||
AutofillVaultListItemsComponent,
|
AutofillVaultListItemsComponent,
|
||||||
VaultListItemsContainerComponent,
|
VaultListItemsContainerComponent,
|
||||||
|
BannerModule,
|
||||||
ButtonModule,
|
ButtonModule,
|
||||||
RouterLink,
|
RouterLink,
|
||||||
NewItemDropdownV2Component,
|
NewItemDropdownV2Component,
|
||||||
@@ -59,6 +62,9 @@ export class VaultV2Component implements OnInit, OnDestroy {
|
|||||||
protected favoriteCiphers$ = this.vaultPopupItemsService.favoriteCiphers$;
|
protected favoriteCiphers$ = this.vaultPopupItemsService.favoriteCiphers$;
|
||||||
protected remainingCiphers$ = this.vaultPopupItemsService.remainingCiphers$;
|
protected remainingCiphers$ = this.vaultPopupItemsService.remainingCiphers$;
|
||||||
protected loading$ = this.vaultPopupItemsService.loading$;
|
protected loading$ = this.vaultPopupItemsService.loading$;
|
||||||
|
protected scriptInjectionIsBlocked = false;
|
||||||
|
protected showScriptInjectionIsBlockedBanner = false;
|
||||||
|
protected autofillTabHostname: string = null;
|
||||||
|
|
||||||
protected newItemItemValues$: Observable<NewItemInitialValues> =
|
protected newItemItemValues$: Observable<NewItemInitialValues> =
|
||||||
this.vaultPopupListFiltersService.filters$.pipe(
|
this.vaultPopupListFiltersService.filters$.pipe(
|
||||||
@@ -86,6 +92,8 @@ export class VaultV2Component implements OnInit, OnDestroy {
|
|||||||
constructor(
|
constructor(
|
||||||
private vaultPopupItemsService: VaultPopupItemsService,
|
private vaultPopupItemsService: VaultPopupItemsService,
|
||||||
private vaultPopupListFiltersService: VaultPopupListFiltersService,
|
private vaultPopupListFiltersService: VaultPopupListFiltersService,
|
||||||
|
private domainSettingsService: DomainSettingsService,
|
||||||
|
private vaultPopupAutofillService: VaultPopupAutofillService,
|
||||||
private vaultUiOnboardingService: VaultUiOnboardingService,
|
private vaultUiOnboardingService: VaultUiOnboardingService,
|
||||||
) {
|
) {
|
||||||
combineLatest([
|
combineLatest([
|
||||||
@@ -110,6 +118,27 @@ export class VaultV2Component implements OnInit, OnDestroy {
|
|||||||
this.vaultState = null;
|
this.vaultState = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
combineLatest([
|
||||||
|
this.domainSettingsService.blockedInteractionsUris$,
|
||||||
|
this.vaultPopupAutofillService.currentAutofillTab$,
|
||||||
|
])
|
||||||
|
.pipe(takeUntilDestroyed())
|
||||||
|
.subscribe(([blockedInteractionsUris, currentAutofillTab]) => {
|
||||||
|
if (blockedInteractionsUris && currentAutofillTab?.url?.length) {
|
||||||
|
const autofillTabURL = new URL(currentAutofillTab.url);
|
||||||
|
this.autofillTabHostname = autofillTabURL.hostname;
|
||||||
|
const autofillTabIsBlocked = Object.keys(blockedInteractionsUris).includes(
|
||||||
|
autofillTabURL.hostname,
|
||||||
|
);
|
||||||
|
|
||||||
|
this.scriptInjectionIsBlocked = autofillTabIsBlocked;
|
||||||
|
|
||||||
|
this.showScriptInjectionIsBlockedBanner =
|
||||||
|
autofillTabIsBlocked &&
|
||||||
|
!blockedInteractionsUris[autofillTabURL.hostname]?.bannerIsDismissed;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
@@ -117,4 +146,22 @@ export class VaultV2Component implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {}
|
ngOnDestroy(): void {}
|
||||||
|
|
||||||
|
handleScriptInjectionIsBlockedBannerDismiss() {
|
||||||
|
firstValueFrom(this.domainSettingsService.blockedInteractionsUris$)
|
||||||
|
.then((blockedURIs) => {
|
||||||
|
this.showScriptInjectionIsBlockedBanner = false;
|
||||||
|
this.domainSettingsService
|
||||||
|
.setBlockedInteractionsUris({
|
||||||
|
...blockedURIs,
|
||||||
|
[this.autofillTabHostname]: { bannerIsDismissed: true },
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
/* no-op */
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
/* no-op */
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,5 +21,5 @@ export const UriMatchStrategy = {
|
|||||||
export type UriMatchStrategySetting = (typeof UriMatchStrategy)[keyof typeof UriMatchStrategy];
|
export type UriMatchStrategySetting = (typeof UriMatchStrategy)[keyof typeof UriMatchStrategy];
|
||||||
|
|
||||||
// using uniqueness properties of object shape over Set for ease of state storability
|
// using uniqueness properties of object shape over Set for ease of state storability
|
||||||
export type NeverDomains = { [id: string]: null };
|
export type NeverDomains = { [id: string]: null | { bannerIsDismissed?: boolean } };
|
||||||
export type EquivalentDomains = string[][];
|
export type EquivalentDomains = string[][];
|
||||||
|
|||||||
Reference in New Issue
Block a user