diff --git a/src/background/main.background.ts b/src/background/main.background.ts index f3538028db..d7f469a890 100644 --- a/src/background/main.background.ts +++ b/src/background/main.background.ts @@ -71,6 +71,7 @@ import CommandsBackground from './commands.background'; import ContextMenusBackground from './contextMenus.background'; import IdleBackground from './idle.background'; import { NativeMessagingBackground } from './nativeMessaging.background'; +import NotificationBackground from './notification.background'; import RuntimeBackground from './runtime.background'; import TabsBackground from './tabs.background'; import WebRequestBackground from './webRequest.background'; @@ -135,6 +136,7 @@ export default class MainBackground { private tabsBackground: TabsBackground; private webRequestBackground: WebRequestBackground; private windowsBackground: WindowsBackground; + private notificationBackground: NotificationBackground; private sidebarAction: any; private buildingContextMenu: boolean; @@ -237,15 +239,16 @@ export default class MainBackground { opr.sidebarAction : (window as any).chrome.sidebarAction; // Background - this.runtimeBackground = new RuntimeBackground(this, this.autofillService, this.cipherService, + this.runtimeBackground = new RuntimeBackground(this, this.autofillService, this.platformUtilsService as BrowserPlatformUtilsService, this.storageService, this.i18nService, - this.notificationsService, this.systemService, this.vaultTimeoutService, - this.environmentService, this.policyService, this.userService, this.messagingService, this.folderService); + this.notificationsService, this.systemService, this.environmentService, this.messagingService); this.nativeMessagingBackground = new NativeMessagingBackground(this.storageService, this.cryptoService, this.cryptoFunctionService, this.vaultTimeoutService, this.runtimeBackground, this.i18nService, this.userService, this.messagingService, this.appIdService, this.platformUtilsService); this.commandsBackground = new CommandsBackground(this, this.passwordGenerationService, this.platformUtilsService, this.vaultTimeoutService); + this.notificationBackground = new NotificationBackground(this, this.autofillService, this.cipherService, + this.storageService, this.vaultTimeoutService, this.policyService, this.folderService); this.tabsBackground = new TabsBackground(this); this.contextMenusBackground = new ContextMenusBackground(this, this.cipherService, this.passwordGenerationService, @@ -276,6 +279,7 @@ export default class MainBackground { await (this.i18nService as I18nService).init(); await (this.eventService as EventService).init(true); await this.runtimeBackground.init(); + await this.notificationBackground.init(); await this.commandsBackground.init(); await this.tabsBackground.init(); diff --git a/src/background/notification.background.ts b/src/background/notification.background.ts new file mode 100644 index 0000000000..7f1377e008 --- /dev/null +++ b/src/background/notification.background.ts @@ -0,0 +1,379 @@ +import { CipherType } from 'jslib-common/enums/cipherType'; + +import { CipherView } from 'jslib-common/models/view/cipherView'; +import { LoginUriView } from 'jslib-common/models/view/loginUriView'; +import { LoginView } from 'jslib-common/models/view/loginView'; + +import { CipherService } from 'jslib-common/abstractions/cipher.service'; +import { FolderService } from 'jslib-common/abstractions/folder.service'; +import { PolicyService } from 'jslib-common/abstractions/policy.service'; +import { StorageService } from 'jslib-common/abstractions/storage.service'; +import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service'; +import { ConstantsService } from 'jslib-common/services/constants.service'; +import { AutofillService } from '../services/abstractions/autofill.service'; + +import { BrowserApi } from '../browser/browserApi'; + +import MainBackground from './main.background'; + +import { Utils } from 'jslib-common/misc/utils'; + +import { PolicyType } from 'jslib-common/enums/policyType'; + +import AddChangePasswordQueueMessage from './models/addChangePasswordQueueMessage'; +import AddLoginQueueMessage from './models/addLoginQueueMessage'; + +export default class NotificationBackground { + constructor(private main: MainBackground, private autofillService: AutofillService, + private cipherService: CipherService, private storageService: StorageService, + private vaultTimeoutService: VaultTimeoutService, private policyService: PolicyService, + private folderService: FolderService) { + } + + async init() { + if (!chrome.runtime) { + return; + } + + BrowserApi.messageListener('notification.background', async (msg: any, sender: any, sendResponse: any) => { + await this.processMessage(msg, sender, sendResponse); + }); + + this.cleanupNotificationQueue(); + } + + async checkNotificationQueue(tab: any = null): Promise { + if (this.main.notificationQueue.length === 0) { + return; + } + + if (tab != null) { + this.doNotificationQueueCheck(tab); + return; + } + + const currentTab = await BrowserApi.getTabFromCurrentWindow(); + if (currentTab != null) { + this.doNotificationQueueCheck(currentTab); + } + } + + private cleanupNotificationQueue() { + for (let i = this.main.notificationQueue.length - 1; i >= 0; i--) { + if (this.main.notificationQueue[i].expires < new Date()) { + this.main.notificationQueue.splice(i, 1); + } + } + setTimeout(() => this.cleanupNotificationQueue(), 2 * 60 * 1000); // check every 2 minutes + } + + private doNotificationQueueCheck(tab: any) { + if (tab == null) { + return; + } + + const tabDomain = Utils.getDomain(tab.url); + if (tabDomain == null) { + return; + } + + for (let i = 0; i < this.main.notificationQueue.length; i++) { + if (this.main.notificationQueue[i].tabId !== tab.id || this.main.notificationQueue[i].domain !== tabDomain) { + continue; + } + + if (this.main.notificationQueue[i].type === 'addLogin') { + BrowserApi.tabSendMessageData(tab, 'openNotificationBar', { + type: 'add', + typeData: { + isVaultLocked: this.main.notificationQueue[i].wasVaultLocked, + }, + }); + } else if (this.main.notificationQueue[i].type === 'changePassword') { + BrowserApi.tabSendMessageData(tab, 'openNotificationBar', { + type: 'change', + typeData: { + isVaultLocked: this.main.notificationQueue[i].wasVaultLocked, + }, + }); + } + break; + } + } + + private removeTabFromNotificationQueue(tab: any) { + for (let i = this.main.notificationQueue.length - 1; i >= 0; i--) { + if (this.main.notificationQueue[i].tabId === tab.id) { + this.main.notificationQueue.splice(i, 1); + } + } + } + + async processMessage(msg: any, sender: any, sendResponse: any) { + switch (msg.command) { + case 'bgGetDataForTab': + await this.getDataForTab(sender.tab, msg.responseCommand); + break; + case 'bgCloseNotificationBar': + await BrowserApi.tabSendMessageData(sender.tab, 'closeNotificationBar'); + break; + case 'bgAdjustNotificationBar': + await BrowserApi.tabSendMessageData(sender.tab, 'adjustNotificationBar', msg.data); + break; + case 'bgAddLogin': + await this.addLogin(msg.login, sender.tab); + break; + case 'bgChangedPassword': + await this.changedPassword(msg.data, sender.tab); + break; + case 'bgAddClose': + case 'bgChangeClose': + this.removeTabFromNotificationQueue(sender.tab); + break; + case 'bgAddSave': + case 'bgChangeSave': + await this.saveOrUpdateCredentials(sender.tab, msg.folder); + break; + case 'bgNeverSave': + await this.saveNever(sender.tab); + break; + case 'collectPageDetailsResponse': + switch (msg.sender) { + case 'notificationBar': + console.log('collectPageDetailsResponse for notificationBar received', msg.tab) + const forms = this.autofillService.getFormsWithPasswordFields(msg.details); + await BrowserApi.tabSendMessageData(msg.tab, 'notificationBarPageDetails', { + details: msg.details, + forms: forms, + }); + break; + default: + break; + } + break; + default: + break; + } + } + + private async addLogin(loginInfo: any, tab: any) { + const loginDomain = Utils.getDomain(loginInfo.url); + if (loginDomain == null) { + return; + } + + let normalizedUsername = loginInfo.username; + if (normalizedUsername != null) { + normalizedUsername = normalizedUsername.toLowerCase(); + } + + if (await this.vaultTimeoutService.isLocked()) { + this.pushAddLoginToQueue(loginDomain, loginInfo, tab, true); + return; + } + + const ciphers = await this.cipherService.getAllDecryptedForUrl(loginInfo.url); + const usernameMatches = ciphers.filter(c => + c.login.username != null && c.login.username.toLowerCase() === normalizedUsername); + if (usernameMatches.length === 0) { + const disabledAddLogin = await this.storageService.get( + ConstantsService.disableAddLoginNotificationKey); + if (disabledAddLogin) { + return; + } + + if (!(await this.allowPersonalOwnership())) { + return; + } + + this.pushAddLoginToQueue(loginDomain, loginInfo, tab); + + } else if (usernameMatches.length === 1 && usernameMatches[0].login.password !== loginInfo.password) { + const disabledChangePassword = await this.storageService.get( + ConstantsService.disableChangedPasswordNotificationKey); + if (disabledChangePassword) { + return; + } + this.pushChangePasswordToQueue(usernameMatches[0].id, loginDomain, loginInfo.password, tab); + } + } + + private async pushAddLoginToQueue(loginDomain: string, loginInfo: any, tab: any, isVaultLocked: boolean = false) { + // remove any old messages for this tab + this.removeTabFromNotificationQueue(tab); + const message: AddLoginQueueMessage = { + type: 'addLogin', + username: loginInfo.username, + password: loginInfo.password, + domain: loginDomain, + uri: loginInfo.url, + tabId: tab.id, + expires: new Date((new Date()).getTime() + 5 * 60000), // 5 minutes + wasVaultLocked: isVaultLocked, + }; + this.main.notificationQueue.push(message); + await this.checkNotificationQueue(tab); + } + + private async changedPassword(changeData: any, tab: any) { + const loginDomain = Utils.getDomain(changeData.url); + if (loginDomain == null) { + return; + } + + if (await this.vaultTimeoutService.isLocked()) { + this.pushChangePasswordToQueue(null, loginDomain, changeData.newPassword, tab, true); + return; + } + + let id: string = null; + const ciphers = await this.cipherService.getAllDecryptedForUrl(changeData.url); + if (changeData.currentPassword != null) { + const passwordMatches = ciphers.filter(c => c.login.password === changeData.currentPassword); + if (passwordMatches.length === 1) { + id = passwordMatches[0].id; + } + } else if (ciphers.length === 1) { + id = ciphers[0].id; + } + if (id != null) { + this.pushChangePasswordToQueue(id, loginDomain, changeData.newPassword, tab); + } + } + + private async pushChangePasswordToQueue(cipherId: string, loginDomain: string, newPassword: string, tab: any, isVaultLocked: boolean = false) { + // remove any old messages for this tab + this.removeTabFromNotificationQueue(tab); + const message: AddChangePasswordQueueMessage = { + type: 'changePassword', + cipherId: cipherId, + newPassword: newPassword, + domain: loginDomain, + tabId: tab.id, + expires: new Date((new Date()).getTime() + 5 * 60000), // 5 minutes + wasVaultLocked: isVaultLocked, + }; + this.main.notificationQueue.push(message); + await this.checkNotificationQueue(tab); + } + + private async saveOrUpdateCredentials(tab: any, folderId?: string) { + for (let i = this.main.notificationQueue.length - 1; i >= 0; i--) { + const queueMessage = this.main.notificationQueue[i]; + if (queueMessage.tabId !== tab.id || + (queueMessage.type !== 'addLogin' && queueMessage.type !== 'changePassword')) { + continue; + } + + const tabDomain = Utils.getDomain(tab.url); + if (tabDomain != null && tabDomain !== queueMessage.domain) { + continue; + } + + this.main.notificationQueue.splice(i, 1); + BrowserApi.tabSendMessageData(tab, 'closeNotificationBar'); + + if (queueMessage.type === 'changePassword') { + const message = (queueMessage as AddChangePasswordQueueMessage); + const cipher = await this.getDecryptedCipherById(message.cipherId); + if (cipher == null) { + return; + } + await this.updateCipher(cipher, message.newPassword); + return; + } + + if (!queueMessage.wasVaultLocked) { + await this.createNewCipher(queueMessage, folderId); + } + + // If the vault was locked, check if a cipher needs updating instead of creating a new one + if (queueMessage.type === 'addLogin' && queueMessage.wasVaultLocked === true) { + const message = (queueMessage as AddLoginQueueMessage); + const ciphers = await this.cipherService.getAllDecryptedForUrl(message.uri); + const usernameMatches = ciphers.filter(c => c.login.username != null && + c.login.username.toLowerCase() === message.username); + + if (usernameMatches.length >= 1) { + await this.updateCipher(usernameMatches[0], message.password); + return; + } + + await this.createNewCipher(message, folderId); + } + } + } + + private async createNewCipher(queueMessage: AddLoginQueueMessage, folderId: string) { + const loginModel = new LoginView(); + const loginUri = new LoginUriView(); + loginUri.uri = queueMessage.uri; + loginModel.uris = [loginUri]; + loginModel.username = queueMessage.username; + loginModel.password = queueMessage.password; + const model = new CipherView(); + model.name = Utils.getHostname(queueMessage.uri) || queueMessage.domain; + model.name = model.name.replace(/^www\./, ''); + model.type = CipherType.Login; + model.login = loginModel; + + if (!Utils.isNullOrWhitespace(folderId)) { + const folders = await this.folderService.getAllDecrypted(); + if (folders.some(x => x.id === folderId)) { + model.folderId = folderId; + } + } + + const cipher = await this.cipherService.encrypt(model); + await this.cipherService.saveWithServer(cipher); + } + + private async getDecryptedCipherById(cipherId: string) { + const cipher = await this.cipherService.get(cipherId); + if (cipher != null && cipher.type === CipherType.Login) { + return await cipher.decrypt(); + } + return null; + } + + private async updateCipher(cipher: CipherView, newPassword: string) { + if (cipher != null && cipher.type === CipherType.Login) { + cipher.login.password = newPassword; + const newCipher = await this.cipherService.encrypt(cipher); + await this.cipherService.saveWithServer(newCipher); + } + } + + private async saveNever(tab: any) { + for (let i = this.main.notificationQueue.length - 1; i >= 0; i--) { + const queueMessage = this.main.notificationQueue[i]; + if (queueMessage.tabId !== tab.id || queueMessage.type !== 'addLogin') { + continue; + } + + const tabDomain = Utils.getDomain(tab.url); + if (tabDomain != null && tabDomain !== queueMessage.domain) { + continue; + } + + this.main.notificationQueue.splice(i, 1); + BrowserApi.tabSendMessageData(tab, 'closeNotificationBar'); + + const hostname = Utils.getHostname(tab.url); + await this.cipherService.saveNeverDomain(hostname); + } + } + + private async getDataForTab(tab: any, responseCommand: string) { + const responseData: any = {}; + if (responseCommand === 'notificationBarGetFoldersList') { + responseData.folders = await this.folderService.getAllDecrypted(); + } + + await BrowserApi.tabSendMessageData(tab, responseCommand, responseData); + } + + private async allowPersonalOwnership(): Promise { + return !await this.policyService.policyAppliesToUser(PolicyType.PersonalOwnership); + } +} diff --git a/src/background/runtime.background.ts b/src/background/runtime.background.ts index a46d174aac..a68c61cf66 100644 --- a/src/background/runtime.background.ts +++ b/src/background/runtime.background.ts @@ -1,20 +1,9 @@ -import { CipherType } from 'jslib-common/enums/cipherType'; - -import { CipherView } from 'jslib-common/models/view/cipherView'; -import { LoginUriView } from 'jslib-common/models/view/loginUriView'; -import { LoginView } from 'jslib-common/models/view/loginView'; - -import { CipherService } from 'jslib-common/abstractions/cipher.service'; import { EnvironmentService } from 'jslib-common/abstractions/environment.service'; -import { FolderService } from 'jslib-common/abstractions/folder.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { MessagingService } from 'jslib-common/abstractions/messaging.service'; import { NotificationsService } from 'jslib-common/abstractions/notifications.service'; -import { PolicyService } from 'jslib-common/abstractions/policy.service'; import { StorageService } from 'jslib-common/abstractions/storage.service'; import { SystemService } from 'jslib-common/abstractions/system.service'; -import { UserService } from 'jslib-common/abstractions/user.service'; -import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service'; import { ConstantsService } from 'jslib-common/services/constants.service'; import { AutofillService } from '../services/abstractions/autofill.service'; import BrowserPlatformUtilsService from '../services/browserPlatformUtils.service'; @@ -39,13 +28,10 @@ export default class RuntimeBackground { private lockedVaultPendingNotifications: any[] = []; constructor(private main: MainBackground, private autofillService: AutofillService, - private cipherService: CipherService, private platformUtilsService: BrowserPlatformUtilsService, + private platformUtilsService: BrowserPlatformUtilsService, private storageService: StorageService, private i18nService: I18nService, - private notificationsService: NotificationsService, - private systemService: SystemService, private vaultTimeoutService: VaultTimeoutService, - private environmentService: EnvironmentService, private policyService: PolicyService, - private userService: UserService, private messagingService: MessagingService, - private folderService: FolderService) { + private notificationsService: NotificationsService, private systemService: SystemService, + private environmentService: EnvironmentService, private messagingService: MessagingService) { // onInstalled listener must be wired up before anything else, so we do it in the ctor chrome.runtime.onInstalled.addListener((details: any) => { @@ -108,35 +94,9 @@ export default class RuntimeBackground { case 'showDialogResolve': this.platformUtilsService.resolveDialogPromise(msg.dialogId, msg.confirmed); break; - case 'bgGetDataForTab': - await this.getDataForTab(sender.tab, msg.responseCommand); - break; - case 'bgCloseNotificationBar': - await BrowserApi.tabSendMessageData(sender.tab, 'closeNotificationBar'); - break; - case 'bgAdjustNotificationBar': - await BrowserApi.tabSendMessageData(sender.tab, 'adjustNotificationBar', msg.data); - break; case 'bgCollectPageDetails': await this.main.collectPageDetailsForContentScript(sender.tab, msg.sender, sender.frameId); break; - case 'bgAddLogin': - await this.addLogin(msg.login, sender.tab); - break; - case 'bgChangedPassword': - await this.changedPassword(msg.data, sender.tab); - break; - case 'bgAddClose': - case 'bgChangeClose': - this.removeTabFromNotificationQueue(sender.tab); - break; - case 'bgAddSave': - case 'bgChangeSave': - await this.saveOrUpdateCredentials(sender.tab, msg.folder); - break; - case 'bgNeverSave': - await this.saveNever(sender.tab); - break; case 'bgUpdateContextMenu': case 'editedCipher': case 'addedCipher': @@ -148,13 +108,6 @@ export default class RuntimeBackground { break; case 'collectPageDetailsResponse': switch (msg.sender) { - case 'notificationBar': - const forms = this.autofillService.getFormsWithPasswordFields(msg.details); - await BrowserApi.tabSendMessageData(msg.tab, 'notificationBarPageDetails', { - details: msg.details, - forms: forms, - }); - break; case 'autofiller': case 'autofill_cmd': const totpCode = await this.autofillService.doAutoFillActiveTab([{ @@ -237,222 +190,6 @@ export default class RuntimeBackground { this.pageDetailsToAutoFill = []; } - private async saveOrUpdateCredentials(tab: any, folderId?: string) { - for (let i = this.main.notificationQueue.length - 1; i >= 0; i--) { - const queueMessage = this.main.notificationQueue[i]; - if (queueMessage.tabId !== tab.id || - (queueMessage.type !== 'addLogin' && queueMessage.type !== 'changePassword')) { - continue; - } - - const tabDomain = Utils.getDomain(tab.url); - if (tabDomain != null && tabDomain !== queueMessage.domain) { - continue; - } - - this.main.notificationQueue.splice(i, 1); - BrowserApi.tabSendMessageData(tab, 'closeNotificationBar'); - - if (queueMessage.type === 'changePassword') { - const message = (queueMessage as AddChangePasswordQueueMessage); - const cipher = await this.getDecryptedCipherById(message.cipherId); - if (cipher == null) { - return; - } - await this.updateCipher(cipher, message.newPassword); - return; - } - - if (!queueMessage.wasVaultLocked) { - await this.createNewCipher(queueMessage, folderId); - } - - // If the vault was locked, check if a cipher needs updating instead of creating a new one - if (queueMessage.type === 'addLogin' && queueMessage.wasVaultLocked === true) { - const message = (queueMessage as AddLoginQueueMessage); - const ciphers = await this.cipherService.getAllDecryptedForUrl(message.uri); - const usernameMatches = ciphers.filter(c => c.login.username != null && - c.login.username.toLowerCase() === message.username); - - if (usernameMatches.length >= 1) { - await this.updateCipher(usernameMatches[0], message.password); - return; - } - - await this.createNewCipher(message, folderId); - } - } - } - - private async createNewCipher(queueMessage: AddLoginQueueMessage, folderId: string) { - const loginModel = new LoginView(); - const loginUri = new LoginUriView(); - loginUri.uri = queueMessage.uri; - loginModel.uris = [loginUri]; - loginModel.username = queueMessage.username; - loginModel.password = queueMessage.password; - const model = new CipherView(); - model.name = Utils.getHostname(queueMessage.uri) || queueMessage.domain; - model.name = model.name.replace(/^www\./, ''); - model.type = CipherType.Login; - model.login = loginModel; - - if (!Utils.isNullOrWhitespace(folderId)) { - const folders = await this.folderService.getAllDecrypted(); - if (folders.some(x => x.id === folderId)) { - model.folderId = folderId; - } - } - - const cipher = await this.cipherService.encrypt(model); - await this.cipherService.saveWithServer(cipher); - } - - private async getDecryptedCipherById(cipherId: string) { - const cipher = await this.cipherService.get(cipherId); - if (cipher != null && cipher.type === CipherType.Login) { - return await cipher.decrypt(); - } - return null; - } - - private async updateCipher(cipher: CipherView, newPassword: string) { - if (cipher != null && cipher.type === CipherType.Login) { - cipher.login.password = newPassword; - const newCipher = await this.cipherService.encrypt(cipher); - await this.cipherService.saveWithServer(newCipher); - } - } - - private async saveNever(tab: any) { - for (let i = this.main.notificationQueue.length - 1; i >= 0; i--) { - const queueMessage = this.main.notificationQueue[i]; - if (queueMessage.tabId !== tab.id || queueMessage.type !== 'addLogin') { - continue; - } - - const tabDomain = Utils.getDomain(tab.url); - if (tabDomain != null && tabDomain !== queueMessage.domain) { - continue; - } - - this.main.notificationQueue.splice(i, 1); - BrowserApi.tabSendMessageData(tab, 'closeNotificationBar'); - - const hostname = Utils.getHostname(tab.url); - await this.cipherService.saveNeverDomain(hostname); - } - } - - private async addLogin(loginInfo: any, tab: any) { - const loginDomain = Utils.getDomain(loginInfo.url); - if (loginDomain == null) { - return; - } - - let normalizedUsername = loginInfo.username; - if (normalizedUsername != null) { - normalizedUsername = normalizedUsername.toLowerCase(); - } - - if (await this.vaultTimeoutService.isLocked()) { - this.pushAddLoginToQueue(loginDomain, loginInfo, tab, true); - return; - } - - const ciphers = await this.cipherService.getAllDecryptedForUrl(loginInfo.url); - const usernameMatches = ciphers.filter(c => - c.login.username != null && c.login.username.toLowerCase() === normalizedUsername); - if (usernameMatches.length === 0) { - const disabledAddLogin = await this.storageService.get( - ConstantsService.disableAddLoginNotificationKey); - if (disabledAddLogin) { - return; - } - - if (!(await this.allowPersonalOwnership())) { - return; - } - - this.pushAddLoginToQueue(loginDomain, loginInfo, tab); - - } else if (usernameMatches.length === 1 && usernameMatches[0].login.password !== loginInfo.password) { - const disabledChangePassword = await this.storageService.get( - ConstantsService.disableChangedPasswordNotificationKey); - if (disabledChangePassword) { - return; - } - this.pushChangePasswordToQueue(usernameMatches[0].id, loginDomain, loginInfo.password, tab); - } - } - - private async pushAddLoginToQueue(loginDomain: string, loginInfo: any, tab: any, isVaultLocked: boolean = false) { - // remove any old messages for this tab - this.removeTabFromNotificationQueue(tab); - const message: AddLoginQueueMessage = { - type: 'addLogin', - username: loginInfo.username, - password: loginInfo.password, - domain: loginDomain, - uri: loginInfo.url, - tabId: tab.id, - expires: new Date((new Date()).getTime() + 5 * 60000), // 5 minutes - wasVaultLocked: isVaultLocked, - }; - this.main.notificationQueue.push(message); - await this.main.checkNotificationQueue(tab); - } - - private async changedPassword(changeData: any, tab: any) { - const loginDomain = Utils.getDomain(changeData.url); - if (loginDomain == null) { - return; - } - - if (await this.vaultTimeoutService.isLocked()) { - this.pushChangePasswordToQueue(null, loginDomain, changeData.newPassword, tab, true); - return; - } - - let id: string = null; - const ciphers = await this.cipherService.getAllDecryptedForUrl(changeData.url); - if (changeData.currentPassword != null) { - const passwordMatches = ciphers.filter(c => c.login.password === changeData.currentPassword); - if (passwordMatches.length === 1) { - id = passwordMatches[0].id; - } - } else if (ciphers.length === 1) { - id = ciphers[0].id; - } - if (id != null) { - this.pushChangePasswordToQueue(id, loginDomain, changeData.newPassword, tab); - } - } - - private async pushChangePasswordToQueue(cipherId: string, loginDomain: string, newPassword: string, tab: any, isVaultLocked: boolean = false) { - // remove any old messages for this tab - this.removeTabFromNotificationQueue(tab); - const message: AddChangePasswordQueueMessage = { - type: 'changePassword', - cipherId: cipherId, - newPassword: newPassword, - domain: loginDomain, - tabId: tab.id, - expires: new Date((new Date()).getTime() + 5 * 60000), // 5 minutes - wasVaultLocked: isVaultLocked, - }; - this.main.notificationQueue.push(message); - await this.main.checkNotificationQueue(tab); - } - - private removeTabFromNotificationQueue(tab: any) { - for (let i = this.main.notificationQueue.length - 1; i >= 0; i--) { - if (this.main.notificationQueue[i].tabId === tab.id) { - this.main.notificationQueue.splice(i, 1); - } - } - } - private async checkOnInstalled() { setTimeout(async () => { if (this.onInstalledReason != null) { @@ -479,17 +216,4 @@ export default class RuntimeBackground { await this.storageService.save(ConstantsService.vaultTimeoutActionKey, 'lock'); } } - - private async getDataForTab(tab: any, responseCommand: string) { - const responseData: any = {}; - if (responseCommand === 'notificationBarGetFoldersList') { - responseData.folders = await this.folderService.getAllDecrypted(); - } - - await BrowserApi.tabSendMessageData(tab, responseCommand, responseData); - } - - private async allowPersonalOwnership(): Promise { - return !await this.policyService.policyAppliesToUser(PolicyType.PersonalOwnership); - } }