diff --git a/src/background/contextMenus.background.ts b/src/background/contextMenus.background.ts index c519f3a07a..fc06216185 100644 --- a/src/background/contextMenus.background.ts +++ b/src/background/contextMenus.background.ts @@ -4,6 +4,7 @@ import MainBackground from './main.background'; import { Analytics } from 'jslib/misc'; +import { TotpService } from 'jslib/abstractions'; import { CipherService } from 'jslib/abstractions/cipher.service'; import { EventService } from 'jslib/abstractions/event.service'; import { LockService } from 'jslib/abstractions/lock.service'; @@ -17,7 +18,7 @@ export default class ContextMenusBackground { constructor(private main: MainBackground, private cipherService: CipherService, private passwordGenerationService: PasswordGenerationService, private analytics: Analytics, private platformUtilsService: PlatformUtilsService, private lockService: LockService, - private eventService: EventService) { + private eventService: EventService, private totpService: TotpService) { this.contextMenus = chrome.contextMenus; } @@ -29,8 +30,10 @@ export default class ContextMenusBackground { this.contextMenus.onClicked.addListener(async (info: any, tab: any) => { if (info.menuItemId === 'generate-password') { await this.generatePasswordToClipboard(); - } else if (info.parentMenuItemId === 'autofill' || info.parentMenuItemId === 'copy-username' || - info.parentMenuItemId === 'copy-password') { + } else if (info.parentMenuItemId === 'autofill' || + info.parentMenuItemId === 'copy-username' || + info.parentMenuItemId === 'copy-password' || + info.parentMenuItemId === 'copy-totp') { await this.cipherAction(info); } }); @@ -86,6 +89,13 @@ export default class ContextMenusBackground { }); this.platformUtilsService.copyToClipboard(cipher.login.password, { window: window }); this.eventService.collect(EventType.Cipher_ClientCopiedPassword, cipher.id); + } else if (info.parentMenuItemId === 'copy-totp') { + this.analytics.ga('send', { + hitType: 'event', + eventAction: 'Copied Totp From Context Menu', + }); + const totpValue = await this.totpService.getCode(cipher.login.totp); + this.platformUtilsService.copyToClipboard(totpValue, { window: window }); } } diff --git a/src/background/main.background.ts b/src/background/main.background.ts index 72a32dc6e2..51f6627373 100644 --- a/src/background/main.background.ts +++ b/src/background/main.background.ts @@ -213,7 +213,7 @@ export default class MainBackground { this.tabsBackground = new TabsBackground(this); this.contextMenusBackground = new ContextMenusBackground(this, this.cipherService, this.passwordGenerationService, this.analytics, this.platformUtilsService, this.lockService, - this.eventService); + this.eventService, this.totpService); this.idleBackground = new IdleBackground(this.lockService, this.storageService, this.notificationsService); this.webRequestBackground = new WebRequestBackground(this.platformUtilsService, this.cipherService, this.lockService); @@ -443,6 +443,14 @@ export default class MainBackground { title: this.i18nService.t('copyPassword'), }); + await this.contextMenusCreate({ + type: 'normal', + id: 'copy-totp', + parentId: 'root', + contexts: ['all'], + title: this.i18nService.t('copyVerificationCode'), + }); + await this.contextMenusCreate({ type: 'separator', parentId: 'root', @@ -575,6 +583,16 @@ export default class MainBackground { title: title, }); } + + if (cipher == null || (cipher.login.totp && cipher.login.totp !== '')) { + await this.contextMenusCreate({ + type: 'normal', + id: 'copy-totp_' + idSuffix, + parentId: 'copy-totp', + contexts: ['all'], + title: title, + }); + } } private cleanupNotificationQueue() {