1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-17 00:33:44 +00:00

[PM-4414] Bugfix - On page URL change, display notifications that have not been dismissed nor expired (#6637)

* on page location change, display notifications that have not been dismissed nor expired

* also dismiss notifications when removing them from the queue during cleanup

* cleanup
This commit is contained in:
Jonathan Prusik
2023-11-15 12:05:19 -05:00
committed by GitHub
parent 432b96925a
commit 1cbe67d192
4 changed files with 22 additions and 11 deletions

View File

@@ -23,6 +23,7 @@ import { NotificationQueueMessageType } from "../../background/models/notificati
import { BrowserApi } from "../../platform/browser/browser-api"; import { BrowserApi } from "../../platform/browser/browser-api";
import { BrowserStateService } from "../../platform/services/abstractions/browser-state.service"; import { BrowserStateService } from "../../platform/services/abstractions/browser-state.service";
import { openAddEditVaultItemPopout } from "../../vault/popup/utils/vault-popout-window"; import { openAddEditVaultItemPopout } from "../../vault/popup/utils/vault-popout-window";
import { NOTIFICATION_BAR_LIFESPAN_MS } from "../constants";
import { AutofillService } from "../services/abstractions/autofill.service"; import { AutofillService } from "../services/abstractions/autofill.service";
export default class NotificationBackground { export default class NotificationBackground {
@@ -123,6 +124,9 @@ export default class NotificationBackground {
case "bgUnlockPopoutOpened": case "bgUnlockPopoutOpened":
await this.unlockVault(sender.tab); await this.unlockVault(sender.tab);
break; break;
case "checkNotificationQueue":
await this.checkNotificationQueue(sender.tab);
break;
case "bgReopenUnlockPopout": case "bgReopenUnlockPopout":
await openUnlockPopout(sender.tab); await openUnlockPopout(sender.tab);
break; break;
@@ -150,10 +154,11 @@ export default class NotificationBackground {
private cleanupNotificationQueue() { private cleanupNotificationQueue() {
for (let i = this.notificationQueue.length - 1; i >= 0; i--) { for (let i = this.notificationQueue.length - 1; i >= 0; i--) {
if (this.notificationQueue[i].expires < new Date()) { if (this.notificationQueue[i].expires < new Date()) {
BrowserApi.tabSendMessageData(this.notificationQueue[i].tab, "closeNotificationBar");
this.notificationQueue.splice(i, 1); this.notificationQueue.splice(i, 1);
} }
} }
setTimeout(() => this.cleanupNotificationQueue(), 2 * 60 * 1000); // check every 2 minutes setTimeout(() => this.cleanupNotificationQueue(), 30000); // check every 30 seconds
} }
private async doNotificationQueueCheck(tab: chrome.tabs.Tab): Promise<void> { private async doNotificationQueueCheck(tab: chrome.tabs.Tab): Promise<void> {
@@ -168,7 +173,7 @@ export default class NotificationBackground {
for (let i = 0; i < this.notificationQueue.length; i++) { for (let i = 0; i < this.notificationQueue.length; i++) {
if ( if (
this.notificationQueue[i].tabId !== tab.id || this.notificationQueue[i].tab.id !== tab.id ||
this.notificationQueue[i].domain !== tabDomain this.notificationQueue[i].domain !== tabDomain
) { ) {
continue; continue;
@@ -220,7 +225,7 @@ export default class NotificationBackground {
private removeTabFromNotificationQueue(tab: chrome.tabs.Tab) { private removeTabFromNotificationQueue(tab: chrome.tabs.Tab) {
for (let i = this.notificationQueue.length - 1; i >= 0; i--) { for (let i = this.notificationQueue.length - 1; i >= 0; i--) {
if (this.notificationQueue[i].tabId === tab.id) { if (this.notificationQueue[i].tab.id === tab.id) {
this.notificationQueue.splice(i, 1); this.notificationQueue.splice(i, 1);
} }
} }
@@ -289,8 +294,8 @@ export default class NotificationBackground {
password: loginInfo.password, password: loginInfo.password,
domain: loginDomain, domain: loginDomain,
uri: loginInfo.url, uri: loginInfo.url,
tabId: tab.id, tab: tab,
expires: new Date(new Date().getTime() + 5 * 60000), // 5 minutes expires: new Date(new Date().getTime() + NOTIFICATION_BAR_LIFESPAN_MS),
wasVaultLocked: isVaultLocked, wasVaultLocked: isVaultLocked,
}; };
this.notificationQueue.push(message); this.notificationQueue.push(message);
@@ -353,8 +358,8 @@ export default class NotificationBackground {
cipherId: cipherId, cipherId: cipherId,
newPassword: newPassword, newPassword: newPassword,
domain: loginDomain, domain: loginDomain,
tabId: tab.id, tab: tab,
expires: new Date(new Date().getTime() + 5 * 60000), // 5 minutes expires: new Date(new Date().getTime() + NOTIFICATION_BAR_LIFESPAN_MS),
wasVaultLocked: isVaultLocked, wasVaultLocked: isVaultLocked,
}; };
this.notificationQueue.push(message); this.notificationQueue.push(message);
@@ -366,7 +371,7 @@ export default class NotificationBackground {
const message: AddUnlockVaultQueueMessage = { const message: AddUnlockVaultQueueMessage = {
type: NotificationQueueMessageType.UnlockVault, type: NotificationQueueMessageType.UnlockVault,
domain: loginDomain, domain: loginDomain,
tabId: tab.id, tab: tab,
expires: new Date(new Date().getTime() + 0.5 * 60000), // 30 seconds expires: new Date(new Date().getTime() + 0.5 * 60000), // 30 seconds
wasVaultLocked: true, wasVaultLocked: true,
}; };
@@ -378,7 +383,7 @@ export default class NotificationBackground {
private async saveOrUpdateCredentials(tab: chrome.tabs.Tab, edit: boolean, folderId?: string) { private async saveOrUpdateCredentials(tab: chrome.tabs.Tab, edit: boolean, folderId?: string) {
for (let i = this.notificationQueue.length - 1; i >= 0; i--) { for (let i = this.notificationQueue.length - 1; i >= 0; i--) {
const queueMessage = this.notificationQueue[i]; const queueMessage = this.notificationQueue[i];
if (queueMessage.tabId !== tab.id || !(queueMessage.type in NotificationQueueMessageType)) { if (queueMessage.tab.id !== tab.id || !(queueMessage.type in NotificationQueueMessageType)) {
continue; continue;
} }
@@ -476,7 +481,7 @@ export default class NotificationBackground {
for (let i = this.notificationQueue.length - 1; i >= 0; i--) { for (let i = this.notificationQueue.length - 1; i >= 0; i--) {
const queueMessage = this.notificationQueue[i]; const queueMessage = this.notificationQueue[i];
if ( if (
queueMessage.tabId !== tab.id || queueMessage.tab.id !== tab.id ||
queueMessage.type !== NotificationQueueMessageType.AddLogin queueMessage.type !== NotificationQueueMessageType.AddLogin
) { ) {
continue; continue;

View File

@@ -27,3 +27,5 @@ export const GENERATE_PASSWORD_ID = "generate-password";
export const NOOP_COMMAND_SUFFIX = "noop"; export const NOOP_COMMAND_SUFFIX = "noop";
export const ROOT_ID = "root"; export const ROOT_ID = "root";
export const SEPARATOR_ID = "separator"; export const SEPARATOR_ID = "separator";
export const NOTIFICATION_BAR_LIFESPAN_MS = 150000; // 150 seconds

View File

@@ -325,6 +325,10 @@ async function loadNotificationBar() {
// On first load or page change, start observing the DOM as early as possible // On first load or page change, start observing the DOM as early as possible
// to avoid missing any forms that are added after the page loads // to avoid missing any forms that are added after the page loads
observeDom(); observeDom();
sendPlatformMessage({
command: "checkNotificationQueue",
});
} }
// This is a safeguard in case the observer misses a SPA page change. // This is a safeguard in case the observer misses a SPA page change.

View File

@@ -3,7 +3,7 @@ import { NotificationQueueMessageType } from "./notificationQueueMessageType";
export default class NotificationQueueMessage { export default class NotificationQueueMessage {
type: NotificationQueueMessageType; type: NotificationQueueMessageType;
domain: string; domain: string;
tabId: number; tab: chrome.tabs.Tab;
expires: Date; expires: Date;
wasVaultLocked: boolean; wasVaultLocked: boolean;
} }