From e90476af2bd83934c93a97d673c2bdc32ed7d28e Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Tue, 5 Dec 2017 23:28:31 -0500 Subject: [PATCH] convert background to main.background.ts --- src/background.d.ts | 1 + src/background.js | 975 +------------------ src/background/main.background.ts | 540 +++++++++- src/models/domain/cipher.ts | 2 +- src/models/domain/cipherString.ts | 2 +- src/popup/app/services/background.service.ts | 2 +- src/scripts/analytics.js | 11 +- tsconfig.json | 3 +- 8 files changed, 515 insertions(+), 1021 deletions(-) diff --git a/src/background.d.ts b/src/background.d.ts index a4b6712cd4..414949b486 100644 --- a/src/background.d.ts +++ b/src/background.d.ts @@ -3,3 +3,4 @@ declare function unescape(s: string): string; declare var opr: any; declare var tldjs: any; declare var forge: any; +declare var chrome: any; diff --git a/src/background.js b/src/background.js index f407acd89b..ba585b5796 100644 --- a/src/background.js +++ b/src/background.js @@ -1,971 +1,10 @@ +import MainBackground from './background/main.background'; +import i18nService from './services/i18nService.js'; + window.forge = require('node-forge'); window.tldjs = require('tldjs'); -// Service imports -import ApiService from './services/api.service'; -import AppIdService from './services/appId.service'; -import AutofillService from './services/autofill.service'; -import CipherService from './services/cipher.service'; -import CollectionService from './services/collection.service'; -import ConstantsService from './services/constants.service'; -import CryptoService from './services/crypto.service'; -import EnvironmentService from './services/environment.service'; -import FolderService from './services/folder.service'; -import i18nService from './services/i18nService.js'; -import LockService from './services/lock.service'; -import PasswordGenerationService from './services/passwordGeneration.service'; -import SettingsService from './services/settings.service'; -import SyncService from './services/sync.service'; -import TokenService from './services/token.service'; -import TotpService from './services/totp.service'; -import UserService from './services/user.service'; -import UtilsService from './services/utils.service'; - -// Model imports -import { Attachment } from './models/domain/attachment'; -import { Card } from './models/domain/card'; -import { Cipher } from './models/domain/cipher'; -import { Field } from './models/domain/field'; -import { Folder } from './models/domain/folder'; -import { Identity } from './models/domain/identity'; -import { Login } from './models/domain/login'; -import { SecureNote } from './models/domain/secureNote'; - -import { AttachmentData } from './models/data/attachmentData'; -import { CardData } from './models/data/cardData'; -import { CipherData } from './models/data/cipherData'; -import { FieldData } from './models/data/fieldData'; -import { FolderData } from './models/data/folderData'; -import { IdentityData } from './models/data/identityData'; -import { LoginData } from './models/data/loginData'; -import { SecureNoteData } from './models/data/secureNoteData'; - -import { CipherString } from './models/domain/cipherString'; - -import { CipherRequest } from './models/request/cipherRequest'; -import { DeviceRequest } from './models/request/deviceRequest'; -import { DeviceTokenRequest } from './models/request/deviceTokenRequest'; -import { FolderRequest } from './models/request/folderRequest'; -import { PasswordHintRequest } from './models/request/passwordHintRequest'; -import { RegisterRequest } from './models/request/registerRequest'; -import { TokenRequest } from './models/request/tokenRequest'; -import { TwoFactorEmailRequest } from './models/request/twoFactorEmailRequest'; - -import { AttachmentResponse } from './models/response/attachmentResponse'; -import { CipherResponse } from './models/response/cipherResponse'; -import { DeviceResponse } from './models/response/deviceResponse'; -import { DomainsResponse } from './models/response/domainsResponse'; -import { ErrorResponse } from './models/response/errorResponse'; -import { FolderResponse } from './models/response/folderResponse'; -import { GlobalDomainResponse } from './models/response/globalDomainResponse'; -import { IdentityTokenResponse } from './models/response/identityTokenResponse'; -import { KeysResponse } from './models/response/keysResponse'; -import { ListResponse } from './models/response/listResponse'; -import { ProfileOrganizationResponse } from './models/response/profileOrganizationResponse'; -import { ProfileResponse } from './models/response/profileResponse'; -import { SyncResponse } from './models/response/syncResponse'; - -var bg_isBackground = true, - bg_utilsService, - bg_i18nService, - bg_constantsService, - bg_cryptoService, - bg_tokenService, - bg_appIdService, - bg_apiService, - bg_environmentService, - bg_userService, - bg_settingsService, - bg_cipherService, - bg_folderService, - bg_collectionService, - bg_lockService, - bg_syncService, - bg_passwordGenerationService, - bg_totpService, - bg_autofillService; - -(function () { - var loginToAutoFill = null, - pageDetailsToAutoFill = [], - autofillTimeout = null, - menuOptionsLoaded = [], - pendingAuthRequests = [], - syncTimeout = null, - bg_loginsToAdd = [], - bg_sidebarAction = (typeof opr !== 'undefined') && opr.sidebarAction ? opr.sidebarAction : chrome.sidebarAction; - - // init services - window.bg_utilsService = bg_utilsService = new UtilsService(); - window.bg_i18nService = bg_i18nService = new i18nService(bg_utilsService); - window.bg_constantsService = bg_constantsService = new ConstantsService(bg_i18nService, bg_utilsService); - window.bg_cryptoService = bg_cryptoService = new CryptoService(); - window.bg_tokenService = bg_tokenService = new TokenService(); - window.bg_appIdService = bg_appIdService = new AppIdService(); - window.bg_apiService = bg_apiService = new ApiService(bg_tokenService, logout); - window.bg_environmentService = bg_environmentService = new EnvironmentService(bg_apiService); - window.bg_userService = bg_userService = new UserService(bg_tokenService); - window.bg_settingsService = bg_settingsService = new SettingsService(bg_userService); - window.bg_cipherService = bg_cipherService = new CipherService(bg_cryptoService, bg_userService, bg_settingsService, bg_apiService); - window.bg_folderService = bg_folderService = new FolderService(bg_cryptoService, bg_userService, bg_i18nService, bg_apiService); - window.bg_collectionService = bg_collectionService = new CollectionService(bg_cryptoService, bg_userService); - window.bg_lockService = bg_lockService = new LockService(bg_cipherService, bg_folderService, bg_collectionService, bg_cryptoService, bg_utilsService, setIcon, refreshBadgeAndMenu); - window.bg_syncService = bg_syncService = new SyncService(bg_userService, bg_apiService, bg_settingsService, bg_folderService, bg_cipherService, bg_cryptoService, bg_collectionService, logout); - window.bg_passwordGenerationService = bg_passwordGenerationService = new PasswordGenerationService(bg_cryptoService); - window.bg_totpService = bg_totpService = new TotpService(); - window.bg_autofillService = bg_autofillService = new AutofillService(bg_cipherService, bg_tokenService, bg_totpService, bg_utilsService); - - require('./scripts/analytics.js'); - - if (chrome.commands) { - chrome.commands.onCommand.addListener(function (command) { - if (command === 'generate_password') { - ga('send', { - hitType: 'event', - eventAction: 'Generated Password From Command' - }); - bg_passwordGenerationService.getOptions().then(function (options) { - var password = PasswordGenerationService.generatePassword(options); - bg_utilsService.copyToClipboard(password); - bg_passwordGenerationService.addHistory(password); - }); - } - else if (command === 'autofill_login') { - chrome.tabs.query({ active: true, windowId: chrome.windows.WINDOW_ID_CURRENT }, function (tabs) { - if (tabs.length) { - ga('send', { - hitType: 'event', - eventAction: 'Autofilled From Command' - }); - collectPageDetailsForContentScript(tabs[0], 'autofill_cmd'); - } - }); - } - }); - } - - chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) { - if (msg.command === 'loggedIn' || msg.command === 'unlocked' || msg.command === 'locked') { - setIcon(); - refreshBadgeAndMenu(); - } - else if (msg.command === 'logout') { - logout(msg.expired, function () { }); - } - else if (msg.command === 'syncCompleted' && msg.successfully) { - setTimeout(refreshBadgeAndMenu, 2000); - } - else if (msg.command === 'bgOpenOverlayPopup') { - messageCurrentTab('openOverlayPopup', msg.data); - } - else if (msg.command === 'bgCloseOverlayPopup') { - messageCurrentTab('closeOverlayPopup'); - } - else if (msg.command === 'bgOpenNotificationBar') { - messageTab(sender.tab.id, 'openNotificationBar', msg.data); - } - else if (msg.command === 'bgCloseNotificationBar') { - messageTab(sender.tab.id, 'closeNotificationBar'); - } - else if (msg.command === 'bgAdjustNotificationBar') { - messageTab(sender.tab.id, 'adjustNotificationBar', msg.data); - } - else if (msg.command === 'bgCollectPageDetails') { - collectPageDetailsForContentScript(sender.tab, msg.sender, sender.frameId); - } - else if (msg.command === 'bgAddLogin') { - addLogin(msg.login, sender.tab); - } - else if (msg.command === 'bgAddClose') { - removeAddLogin(sender.tab); - } - else if (msg.command === 'bgAddSave') { - saveAddLogin(sender.tab); - } - else if (msg.command === 'bgNeverSave') { - saveNever(sender.tab); - } - else if (msg.command === 'collectPageDetailsResponse') { - if (msg.sender === 'notificationBar') { - var forms = bg_autofillService.getFormsWithPasswordFields(msg.details); - messageTab(msg.tab.id, 'notificationBarPageDetails', { details: msg.details, forms: forms }); - } - else if (msg.sender === 'autofiller' || msg.sender === 'autofill_cmd') { - bg_autofillService.doAutoFillForLastUsedLogin([{ - frameId: sender.frameId, tab: msg.tab, details: msg.details - }], msg.sender === 'autofill_cmd'); - } - else if (msg.sender === 'contextMenu') { - clearTimeout(autofillTimeout); - pageDetailsToAutoFill.push({ frameId: sender.frameId, tab: msg.tab, details: msg.details }); - autofillTimeout = setTimeout(autofillPage, 300); - } - } else if (msg.command === 'bgUpdateContextMenu') { - refreshBadgeAndMenu(); - } - }); - - if (chrome.runtime.onInstalled) { - chrome.runtime.onInstalled.addListener(function (details) { - ga('send', { - hitType: 'event', - eventAction: 'onInstalled ' + details.reason - }); - - if (details.reason === 'install') { - chrome.tabs.create({ url: 'https://bitwarden.com/browser-start/' }, function (tab) { }); - } - }); - } - - chrome.tabs.onActivated.addListener(function (activeInfo) { - refreshBadgeAndMenu(); - }); - - var onReplacedRan = false; - chrome.tabs.onReplaced.addListener(function (addedTabId, removedTabId) { - if (onReplacedRan) { - return; - } - onReplacedRan = true; - checkbg_loginsToAdd(); - refreshBadgeAndMenu(); - }); - - var onUpdatedRan = false; - chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) { - if (onUpdatedRan) { - return; - } - onUpdatedRan = true; - checkbg_loginsToAdd(); - refreshBadgeAndMenu(); - }); - - if (chrome.windows) { - chrome.windows.onFocusChanged.addListener(function (windowId) { - if (windowId === null || windowId < 0) { - return; - } - - refreshBadgeAndMenu(); - }); - } - - if (chrome.contextMenus) { - chrome.contextMenus.onClicked.addListener(function (info, tab) { - if (info.menuItemId === 'generate-password') { - ga('send', { - hitType: 'event', - eventAction: 'Generated Password From Context Menu' - }); - bg_passwordGenerationService.getOptions().then(function (options) { - var password = PasswordGenerationService.generatePassword(options); - bg_utilsService.copyToClipboard(password); - bg_passwordGenerationService.addHistory(password); - }); - } - else if (info.parentMenuItemId === 'autofill' || info.parentMenuItemId === 'copy-username' || - info.parentMenuItemId === 'copy-password') { - var id = info.menuItemId.split('_')[1]; - if (id === 'noop') { - if (chrome.browserAction.openPopup) { - chrome.browserAction.openPopup(); - } - - return; - } - - bg_cipherService.getAllDecrypted().then(function (ciphers) { - for (var i = 0; i < ciphers.length; i++) { - if (ciphers[i].id === id) { - if (info.parentMenuItemId === 'autofill') { - ga('send', { - hitType: 'event', - eventAction: 'Autofilled From Context Menu' - }); - startAutofillPage(ciphers[i]); - } - else if (info.parentMenuItemId === 'copy-username') { - ga('send', { - hitType: 'event', - eventAction: 'Copied Username From Context Menu' - }); - bg_utilsService.copyToClipboard(ciphers[i].login.username); - } - else if (info.parentMenuItemId === 'copy-password') { - ga('send', { - hitType: 'event', - eventAction: 'Copied Password From Context Menu' - }); - bg_utilsService.copyToClipboard(ciphers[i].login.password); - } - return; - } - } - }, function () { - - }); - } - }); - } - - if (chrome.webRequest && chrome.webRequest.onAuthRequired) { - chrome.webRequest.onAuthRequired.addListener(function (details, callback) { - if (!details.url || pendingAuthRequests.indexOf(details.requestId) != -1) { - if (callback) { - callback(); - } - return; - } - - var domain = bg_utilsService.getDomain(details.url); - if (!domain) { - if (callback) { - callback(); - } - return; - } - - pendingAuthRequests.push(details.requestId); - - if (bg_utilsService.isFirefox()) { - return new Promise(function (resolve, reject) { - bg_cipherService.getAllDecryptedForDomain(domain).then(function (ciphers) { - if (!ciphers || ciphers.length !== 1) { - reject(); - return; - } - - resolve({ - authCredentials: { - username: ciphers[0].login.username, - password: ciphers[0].login.password - } - }); - }, function () { - reject(); - }); - }); - } - else { - bg_cipherService.getAllDecryptedForDomain(domain).then(function (ciphers) { - if (!ciphers || ciphers.length !== 1) { - callback(); - return; - } - - callback({ - authCredentials: { - username: ciphers[0].login.username, - password: ciphers[0].login.password - } - }); - }, function () { - callback(); - }); - } - }, { urls: ['http://*/*', 'https://*/*'] }, [bg_utilsService.isFirefox() ? 'blocking' : 'asyncBlocking']); - - chrome.webRequest.onCompleted.addListener(completeAuthRequest, { urls: ['http://*/*'] }); - chrome.webRequest.onErrorOccurred.addListener(completeAuthRequest, { urls: ['http://*/*'] }); - } - - function completeAuthRequest(details) { - var i = pendingAuthRequests.indexOf(details.requestId); - if (i > -1) { - pendingAuthRequests.splice(i, 1); - } - } - - var buildingContextMenu = false; - function buildContextMenu(callback) { - if (!chrome.contextMenus || buildingContextMenu) { - return; - } - buildingContextMenu = true; - - chrome.contextMenus.removeAll(function () { - chrome.contextMenus.create({ - type: 'normal', - id: 'root', - contexts: ['all'], - title: 'bitwarden' - }, function () { - chrome.contextMenus.create({ - type: 'normal', - id: 'autofill', - parentId: 'root', - contexts: ['all'], - title: bg_i18nService.autoFill - }, function () { - if (bg_utilsService.isFirefox() || bg_utilsService.isEdge()) { - // Firefox & Edge do not support writing to the clipboard from background - buildingContextMenu = false; - if (callback) { - callback(); - } - return; - } - - chrome.contextMenus.create({ - type: 'normal', - id: 'copy-username', - parentId: 'root', - contexts: ['all'], - title: bg_i18nService.copyUsername - }, function () { - chrome.contextMenus.create({ - type: 'normal', - id: 'copy-password', - parentId: 'root', - contexts: ['all'], - title: bg_i18nService.copyPassword - }, function () { - chrome.contextMenus.create({ - type: 'separator', - parentId: 'root' - }); - - chrome.contextMenus.create({ - type: 'normal', - id: 'generate-password', - parentId: 'root', - contexts: ['all'], - title: bg_i18nService.generatePasswordCopied - }, function () { - buildingContextMenu = false; - if (callback) { - callback(); - } - }); - }); - }); - }); - }); - }); - } - - function setIcon() { - if (!chrome.browserAction && !bg_sidebarAction) { - return; - } - - var isAuthenticated; - bg_userService.isAuthenticated().then(function (theIsAuthenticated) { - isAuthenticated = theIsAuthenticated; - return bg_cryptoService.getKey(); - }).then(function (key) { - var suffix = ''; - if (!isAuthenticated) { - suffix = '_gray'; - } - else if (!key) { - suffix = '_locked'; - } - - actionSetIcon(chrome.browserAction, suffix); - actionSetIcon(bg_sidebarAction, suffix); - }); - - function actionSetIcon(theAction, suffix) { - if (theAction && theAction.setIcon) { - theAction.setIcon({ - path: { - '19': 'images/icon19' + suffix + '.png', - '38': 'images/icon38' + suffix + '.png', - } - }); - } - } - } - - function refreshBadgeAndMenu() { - if (!chrome.windows || !chrome.contextMenus) { - return; - } - - chrome.tabs.query({ active: true, windowId: chrome.windows.WINDOW_ID_CURRENT }, function (tabs) { - var tab = null; - if (tabs.length > 0) { - tab = tabs[0]; - } - - if (!tab) { - return; - } - - chrome.storage.local.get(bg_constantsService.disableContextMenuItemKey, function (obj) { - if (!obj[bg_constantsService.disableContextMenuItemKey]) { - buildContextMenu(function () { - contextMenuReady(tab, true); - }); - } - else { - chrome.contextMenus.removeAll(); - contextMenuReady(tab, false); - } - }); - }); - } - - function contextMenuReady(tab, contextMenuEnabled) { - loadMenuAndUpdateBadge(tab.url, tab.id, contextMenuEnabled); - onUpdatedRan = onReplacedRan = false; - } - - function loadMenuAndUpdateBadge(url, tabId, contextMenuEnabled) { - if (!chrome.browserAction && !bg_sidebarAction) { - return; - } - - if (!url) { - return; - } - - var tabDomain = bg_utilsService.getDomain(url); - if (!tabDomain) { - return; - } - - setActionBadgeColor(chrome.browserAction); - setActionBadgeColor(bg_sidebarAction); - - menuOptionsLoaded = []; - bg_cipherService.getAllDecryptedForDomain(tabDomain).then(function (ciphers) { - ciphers.sort(bg_cipherService.sortCiphersByLastUsedThenName); - - if (contextMenuEnabled) { - for (var i = 0; i < ciphers.length; i++) { - loadLoginContextMenuOptions(ciphers[i]); - } - } - - var theText = ''; - if (ciphers.length > 0 && ciphers.length < 9) { - theText = ciphers.length.toString(); - } - else if (ciphers.length > 0) { - theText = '9+'; - } - else { - if (contextMenuEnabled) { - loadNoLoginsContextMenuOptions(bg_i18nService.noMatchingLogins); - } - } - - setBrowserActionText(theText, tabId); - setSidebarActionText(theText, tabId); - }, function () { - if (contextMenuEnabled) { - loadNoLoginsContextMenuOptions(bg_i18nService.vaultLocked); - } - setBrowserActionText('', tabId); - setSidebarActionText('', tabId); - }); - - function setActionBadgeColor(theAction) { - if (theAction && theAction.setBadgeBackgroundColor) { - theAction.setBadgeBackgroundColor({ color: '#294e5f' }); - } - } - - function setBrowserActionText(text, tabId) { - if (chrome.browserAction && chrome.browserAction.setBadgeText) { - chrome.browserAction.setBadgeText({ - text: text, - tabId: tabId - }); - } - } - - function setSidebarActionText(text, tabId) { - if (!bg_sidebarAction) { - return; - } - - if (bg_sidebarAction.setBadgeText) { - bg_sidebarAction.setBadgeText({ - text: text, - tabId: tabId - }); - } - else if (bg_sidebarAction.setTitle) { - var title = 'bitwarden'; - if (text && text !== '') { - title += (' [' + text + ']'); - } - bg_sidebarAction.setTitle({ - title: title, - tabId: tabId - }); - } - } - } - - function messageCurrentTab(command, data) { - chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { - var tabId = null; - if (tabs.length > 0) { - tabId = tabs[0].id; - } - else { - return; - } - - messageTab(tabId, command, data); - }); - } - - function messageTab(tabId, command, data, callback) { - if (!tabId) { - return; - } - - var obj = { - command: command - }; - - if (data) { - obj.data = data; - } - - chrome.tabs.sendMessage(tabId, obj, function () { - if (callback) { - callback(); - } - }); - } - - function collectPageDetailsForContentScript(tab, sender, frameId) { - if (!tab || !tab.id) { - return; - } - - var options = {}; - if (frameId || frameId === 0) { - options.frameId = frameId; - } - - chrome.tabs.sendMessage(tab.id, { - command: 'collectPageDetails', - tab: tab, - sender: sender - }, options, function () { - if (chrome.runtime.lastError) { - return; - } - }); - } - - function addLogin(loginInfo, tab) { - var loginDomain = bg_utilsService.getDomain(loginInfo.url); - if (!loginDomain) { - return; - } - - bg_cipherService.getAllDecryptedForDomain(loginDomain).then(function (ciphers) { - var match = false; - for (var i = 0; i < ciphers.length; i++) { - if (ciphers[i].login.username === loginInfo.username) { - match = true; - break; - } - } - - if (!match) { - // remove any old logins for this tab - removeAddLogin(tab); - - bg_loginsToAdd.push({ - username: loginInfo.username, - password: loginInfo.password, - name: loginDomain, - domain: loginDomain, - uri: loginInfo.url, - tabId: tab.id, - expires: new Date((new Date()).getTime() + 30 * 60000) // 30 minutes - }); - checkbg_loginsToAdd(tab); - } - }); - } - - function cleanupbg_loginsToAdd() { - for (var i = bg_loginsToAdd.length - 1; i >= 0; i--) { - if (bg_loginsToAdd[i].expires < new Date()) { - bg_loginsToAdd.splice(i, 1); - } - } - - setTimeout(cleanupbg_loginsToAdd, 2 * 60 * 1000); // check every 2 minutes - } - - function removeAddLogin(tab) { - for (var i = bg_loginsToAdd.length - 1; i >= 0; i--) { - if (bg_loginsToAdd[i].tabId === tab.id) { - bg_loginsToAdd.splice(i, 1); - } - } - } - - function saveAddLogin(tab) { - for (var i = bg_loginsToAdd.length - 1; i >= 0; i--) { - if (bg_loginsToAdd[i].tabId !== tab.id) { - continue; - } - - var loginInfo = bg_loginsToAdd[i]; - var tabDomain = bg_utilsService.getDomain(tab.url); - if (tabDomain && tabDomain !== loginInfo.domain) { - continue; - } - - bg_loginsToAdd.splice(i, 1); - - /* jshint ignore:start */ - bg_cipherService.encrypt({ - id: null, - folderId: null, - favorite: false, - name: loginInfo.name, - notes: null, - type: bg_constantsService.cipherType.login, - login: { - uri: loginInfo.uri, - username: loginInfo.username, - password: loginInfo.password - } - }).then(function (model) { - var cipher = new Cipher(model, true); - return bg_cipherService.saveWithServer(cipher); - }).then(function (login) { - ga('send', { - hitType: 'event', - eventAction: 'Added Login from Notification Bar' - }); - }); - /* jshint ignore:end */ - - messageTab(tab.id, 'closeNotificationBar'); - } - } - - function saveNever(tab) { - for (var i = bg_loginsToAdd.length - 1; i >= 0; i--) { - if (bg_loginsToAdd[i].tabId !== tab.id) { - continue; - } - - var loginInfo = bg_loginsToAdd[i]; - var tabDomain = bg_utilsService.getDomain(tab.url); - if (tabDomain && tabDomain !== loginInfo.domain) { - continue; - } - - bg_loginsToAdd.splice(i, 1); - var hostname = bg_utilsService.getHostname(tab.url); - bg_cipherService.saveNeverDomain(hostname); - messageTab(tab.id, 'closeNotificationBar'); - } - } - - function checkbg_loginsToAdd(tab) { - if (!bg_loginsToAdd.length) { - return; - } - - if (tab) { - check(); - return; - } - - chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { - if (tabs.length > 0) { - tab = tabs[0]; - check(); - } - }); - - function check() { - if (!tab) { - return; - } - - var tabDomain = bg_utilsService.getDomain(tab.url); - if (!tabDomain) { - return; - } - - for (var i = 0; i < bg_loginsToAdd.length; i++) { - if (bg_loginsToAdd[i].tabId !== tab.id || bg_loginsToAdd[i].domain !== tabDomain) { - continue; - } - - messageTab(tab.id, 'openNotificationBar', { - type: 'add' - }, function () { }); - break; - } - } - } - - function startAutofillPage(cipher) { - loginToAutoFill = cipher; - chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { - var tab = null; - if (tabs.length > 0) { - tab = tabs[0]; - } - else { - return; - } - - if (!tab) { - return; - } - - chrome.tabs.sendMessage(tab.id, { - command: 'collectPageDetails', - tab: tab, - sender: 'contextMenu' - }, function () { }); - }); - } - - function autofillPage() { - bg_autofillService.doAutoFill({ - cipher: loginToAutoFill, - pageDetails: pageDetailsToAutoFill, - fromBackground: true - }); - // reset - loginToAutoFill = null; - pageDetailsToAutoFill = []; - } - - function loadLoginContextMenuOptions(cipher) { - if (!cipher || cipher.type !== bg_constantsService.cipherType.login) { - return; - } - - var title = cipher.name + (cipher.login.username && cipher.login.username !== '' ? - ' (' + cipher.login.username + ')' : ''); - loadContextMenuOptions(title, cipher.id, cipher); - } - - function loadNoLoginsContextMenuOptions(noLoginsMessage) { - loadContextMenuOptions(noLoginsMessage, 'noop', null); - } - - function loadContextMenuOptions(title, idSuffix, cipher) { - if (!chrome.contextMenus || menuOptionsLoaded.indexOf(idSuffix) > -1 || - (cipher && cipher.type !== bg_constantsService.cipherType.login)) { - return; - } - menuOptionsLoaded.push(idSuffix); - - if (!cipher || (cipher.login.password && cipher.login.password !== '')) { - chrome.contextMenus.create({ - type: 'normal', - id: 'autofill_' + idSuffix, - parentId: 'autofill', - contexts: ['all'], - title: title - }, function () { - if (chrome.runtime.lastError) { - return; - } - }); - } - - if (bg_utilsService.isFirefox()) { - // Firefox does not support writing to the clipboard from background - return; - } - - if (!cipher || (cipher.login.username && cipher.login.username !== '')) { - chrome.contextMenus.create({ - type: 'normal', - id: 'copy-username_' + idSuffix, - parentId: 'copy-username', - contexts: ['all'], - title: title - }, function () { - if (chrome.runtime.lastError) { - return; - } - }); - } - - if (!cipher || (cipher.login.password && cipher.login.password !== '')) { - chrome.contextMenus.create({ - type: 'normal', - id: 'copy-password_' + idSuffix, - parentId: 'copy-password', - contexts: ['all'], - title: title - }, function () { - if (chrome.runtime.lastError) { - return; - } - }); - } - } - - function logout(expired, callback) { - bg_userService.getUserId().then(function (userId) { - return Promise.all([ - bg_syncService.setLastSync(new Date(0)), - bg_tokenService.clearToken(), - bg_cryptoService.clearKeys(), - bg_userService.clear(), - bg_settingsService.clear(userId), - bg_cipherService.clear(userId), - bg_folderService.clear(userId), - bg_passwordGenerationService.clear() - ]).then(function () { - chrome.runtime.sendMessage({ - command: 'doneLoggingOut', expired: expired - }); - setIcon(); - refreshBadgeAndMenu(); - if (callback) { - callback(); - } - }); - }); - } - - function fullSync(override) { - override = override || false; - bg_syncService.getLastSync().then(function (lastSync) { - var syncInternal = 6 * 60 * 60 * 1000; // 6 hours - var lastSyncAgo = new Date() - lastSync; - if (override || !lastSync || lastSyncAgo >= syncInternal) { - bg_syncService.fullSync(override || false).then(function () { - scheduleNextSync(); - }); - } - else { - scheduleNextSync(); - } - }); - } - - function scheduleNextSync() { - if (syncTimeout) { - clearTimeout(syncTimeout); - } - - syncTimeout = setTimeout(fullSync, 5 * 60 * 1000); // check every 5 minutes - } - - // Bootstrap - - bg_environmentService.setUrlsFromStorage().then(function () { - setIcon(); - cleanupbg_loginsToAdd(); - fullSync(true); - }); -})(); +window.bg_isBackground = true; +window.bg_main = new MainBackground(new i18nService()); +require('./scripts/analytics.js'); +window.bg_main.bootstrap(); diff --git a/src/background/main.background.ts b/src/background/main.background.ts index c87640c828..ca915e12c2 100644 --- a/src/background/main.background.ts +++ b/src/background/main.background.ts @@ -1,5 +1,7 @@ import { CipherType } from '../enums/cipherType.enum'; +import { Cipher } from '../models/domain/cipher'; + import ApiService from '../services/api.service'; import AppIdService from '../services/appId.service'; import AutofillService from '../services/autofill.service'; @@ -21,7 +23,6 @@ import UtilsService from '../services/utils.service'; export default class MainBackground { utilsService: UtilsService; - i18nService: any; constantsService: ConstantsService; cryptoService: CryptoService; tokenService: TokenService; @@ -46,12 +47,15 @@ export default class MainBackground { private menuOptionsLoaded: any[] = []; private loginToAutoFill: any = null; private pageDetailsToAutoFill: any[] = []; + private loginsToAdd: any[] = []; + private syncTimeout: number; + private autofillTimeout: number; + private pendingAuthRequests: any[] = []; - constructor(window: Window, i18nService: any) { + constructor(public i18nService: any) { // Services - this.i18nService = i18nService; this.utilsService = new UtilsService(); - this.constantsService = new ConstantsService(this.i18nService, this.utilsService); + this.constantsService = new ConstantsService(i18nService, this.utilsService); this.cryptoService = new CryptoService(); this.tokenService = new TokenService(); this.appIdService = new AppIdService(); @@ -59,10 +63,10 @@ export default class MainBackground { this.environmentService = new EnvironmentService(this.apiService); this.userService = new UserService(this.tokenService); this.settingsService = new SettingsService(this.userService); - this.cipherService = new CipherService(this.cryptoService, this.userService, - this.settingsService, this.apiService); - this.folderService = new FolderService(this.cryptoService, this.userService, - this.i18nService, this.apiService); + this.cipherService = new CipherService(this.cryptoService, this.userService, this.settingsService, + this.apiService); + this.folderService = new FolderService(this.cryptoService, this.userService, i18nService, + this.apiService); this.collectionService = new CollectionService(this.cryptoService, this.userService); this.lockService = new LockService(this.cipherService, this.folderService, this.collectionService, this.cryptoService, this.utilsService, this.setIcon, this.refreshBadgeAndMenu); @@ -78,6 +82,261 @@ export default class MainBackground { opr.sidebarAction : (window as any).chrome.sidebarAction; } + bootstrap() { + // Chrome APIs + if (chrome.commands) { + chrome.commands.onCommand.addListener((command: any) => { + if (command === 'generate_password') { + (window as any).ga('send', { + hitType: 'event', + eventAction: 'Generated Password From Command', + }); + this.passwordGenerationService.getOptions().then((options) => { + const password = PasswordGenerationService.generatePassword(options); + UtilsService.copyToClipboard(password); + this.passwordGenerationService.addHistory(password); + }); + } else if (command === 'autofill_login') { + this.tabsQueryFirst({ active: true, windowId: chrome.windows.WINDOW_ID_CURRENT }).then((tab) => { + if (tab != null) { + (window as any).ga('send', { + hitType: 'event', + eventAction: 'Autofilled From Command', + }); + this.collectPageDetailsForContentScript(tab, 'autofill_cmd'); + } + }); + } + }); + } + + chrome.runtime.onMessage.addListener((msg: any, sender: any, sendResponse: any) => { + if (msg.command === 'loggedIn' || msg.command === 'unlocked' || msg.command === 'locked') { + this.setIcon(); + this.refreshBadgeAndMenu(); + } else if (msg.command === 'logout') { + this.logout(msg.expired); + } else if (msg.command === 'syncCompleted' && msg.successfully) { + setTimeout(async () => await this.refreshBadgeAndMenu(), 2000); + } else if (msg.command === 'bgOpenOverlayPopup') { + this.currentTabSendMessage('openOverlayPopup', msg.data); + } else if (msg.command === 'bgCloseOverlayPopup') { + this.currentTabSendMessage('closeOverlayPopup'); + } else if (msg.command === 'bgOpenNotificationBar') { + this.tabSendMessage(sender.tab.id, 'openNotificationBar', msg.data); + } else if (msg.command === 'bgCloseNotificationBar') { + this.tabSendMessage(sender.tab.id, 'closeNotificationBar'); + } else if (msg.command === 'bgAdjustNotificationBar') { + this.tabSendMessage(sender.tab.id, 'adjustNotificationBar', msg.data); + } else if (msg.command === 'bgCollectPageDetails') { + this.collectPageDetailsForContentScript(sender.tab, msg.sender, sender.frameId); + } else if (msg.command === 'bgAddLogin') { + this.addLogin(msg.login, sender.tab); + } else if (msg.command === 'bgAddClose') { + this.removeAddLogin(sender.tab); + } else if (msg.command === 'bgAddSave') { + this.saveAddLogin(sender.tab); + } else if (msg.command === 'bgNeverSave') { + this.saveNever(sender.tab); + } else if (msg.command === 'collectPageDetailsResponse') { + if (msg.sender === 'notificationBar') { + const forms = this.autofillService.getFormsWithPasswordFields(msg.details); + this.tabSendMessage(msg.tab.id, 'notificationBarPageDetails', { + details: msg.details, + forms: forms, + }); + } else if (msg.sender === 'autofiller' || msg.sender === 'autofill_cmd') { + this.autofillService.doAutoFillForLastUsedLogin([{ + frameId: sender.frameId, + tab: msg.tab, + details: msg.details, + }], msg.sender === 'autofill_cmd'); + } else if (msg.sender === 'contextMenu') { + clearTimeout(this.autofillTimeout); + this.pageDetailsToAutoFill.push({ frameId: sender.frameId, tab: msg.tab, details: msg.details }); + this.autofillTimeout = setTimeout(async () => await this.autofillPage(), 300); + } + } else if (msg.command === 'bgUpdateContextMenu') { + this.refreshBadgeAndMenu(); + } + }); + + if (chrome.runtime.onInstalled) { + chrome.runtime.onInstalled.addListener((details: any) => { + (window as any).ga('send', { + hitType: 'event', + eventAction: 'onInstalled ' + details.reason, + }); + + if (details.reason === 'install') { + chrome.tabs.create({ url: 'https://bitwarden.com/browser-start/' }); + } + }); + } + + chrome.tabs.onActivated.addListener((activeInfo: any) => { + this.refreshBadgeAndMenu(); + }); + + chrome.tabs.onReplaced.addListener((addedTabId: any, removedTabId: any) => { + if (this.onReplacedRan) { + return; + } + this.onReplacedRan = true; + this.checkLoginsToAdd(); + this.refreshBadgeAndMenu(); + }); + + chrome.tabs.onUpdated.addListener((tabId: any, changeInfo: any, tab: any) => { + if (this.onUpdatedRan) { + return; + } + this.onUpdatedRan = true; + this.checkLoginsToAdd(); + this.refreshBadgeAndMenu(); + }); + + if (chrome.windows) { + chrome.windows.onFocusChanged.addListener((windowId: any) => { + if (windowId === null || windowId < 0) { + return; + } + + this.refreshBadgeAndMenu(); + }); + } + + if (chrome.contextMenus) { + chrome.contextMenus.onClicked.addListener((info: any, tab: any) => { + if (info.menuItemId === 'generate-password') { + (window as any).ga('send', { + hitType: 'event', + eventAction: 'Generated Password From Context Menu', + }); + this.passwordGenerationService.getOptions().then((options) => { + const password = PasswordGenerationService.generatePassword(options); + UtilsService.copyToClipboard(password); + this.passwordGenerationService.addHistory(password); + }); + } else if (info.parentMenuItemId === 'autofill' || info.parentMenuItemId === 'copy-username' || + info.parentMenuItemId === 'copy-password') { + const id = info.menuItemId.split('_')[1]; + if (id === 'noop') { + if ((window as any).chrome.browserAction.openPopup) { + (window as any).chrome.browserAction.openPopup(); + } + return; + } + + this.cipherService.getAllDecrypted().then((ciphers) => { + for (let i = 0; i < ciphers.length; i++) { + const cipher = ciphers[i]; + if (cipher.id !== id) { + continue; + } + + if (info.parentMenuItemId === 'autofill') { + (window as any).ga('send', { + hitType: 'event', + eventAction: 'Autofilled From Context Menu', + }); + this.startAutofillPage(cipher); + } else if (info.parentMenuItemId === 'copy-username') { + (window as any).ga('send', { + hitType: 'event', + eventAction: 'Copied Username From Context Menu', + }); + UtilsService.copyToClipboard(cipher.login.username); + } else if (info.parentMenuItemId === 'copy-password') { + (window as any).ga('send', { + hitType: 'event', + eventAction: 'Copied Password From Context Menu', + }); + UtilsService.copyToClipboard(cipher.login.password); + } + + break; + } + }); + } + }); + } + + if (chrome.webRequest && chrome.webRequest.onAuthRequired) { + (window as any).chrome.webRequest.onAuthRequired.addListener((details: any, callback: any) => { + if (!details.url || this.pendingAuthRequests.indexOf(details.requestId) !== -1) { + if (callback) { + callback(); + } + return; + } + + const domain = UtilsService.getDomain(details.url); + if (domain == null) { + if (callback) { + callback(); + } + return; + } + + this.pendingAuthRequests.push(details.requestId); + + if (this.utilsService.isFirefox()) { + return new Promise((resolve, reject) => { + this.cipherService.getAllDecryptedForDomain(domain).then((ciphers) => { + if (ciphers == null || ciphers.length !== 1) { + reject(); + return; + } + + resolve({ + authCredentials: { + username: ciphers[0].login.username, + password: ciphers[0].login.password, + }, + }); + }, () => { + reject(); + }); + }); + } else { + this.cipherService.getAllDecryptedForDomain(domain).then((ciphers) => { + if (ciphers == null || ciphers.length !== 1) { + callback(); + return; + } + + callback({ + authCredentials: { + username: ciphers[0].login.username, + password: ciphers[0].login.password, + }, + }); + }, () => { + callback(); + }); + } + }, { urls: ['http://*/*', 'https://*/*'] }, [this.utilsService.isFirefox() ? 'blocking' : 'asyncBlocking']); + + chrome.webRequest.onCompleted.addListener(this.completeAuthRequest, { urls: ['http://*/*'] }); + chrome.webRequest.onErrorOccurred.addListener(this.completeAuthRequest, { urls: ['http://*/*'] }); + } + + // Bootstrap + this.environmentService.setUrlsFromStorage().then(() => { + this.setIcon(); + this.cleanupLoginsToAdd(); + this.fullSync(true); + }); + } + + private completeAuthRequest(details: any) { + const i = this.pendingAuthRequests.indexOf(details.requestId); + if (i > -1) { + this.pendingAuthRequests.splice(i, 1); + } + } + private async buildContextMenu() { if (!chrome.contextMenus || this.buildingContextMenu) { return; @@ -90,7 +349,7 @@ export default class MainBackground { type: 'normal', id: 'root', contexts: ['all'], - title: 'bitwarden' + title: 'bitwarden', }); await this.contextMenusCreate({ @@ -98,7 +357,7 @@ export default class MainBackground { id: 'autofill', parentId: 'root', contexts: ['all'], - title: this.i18nService.autoFill + title: this.i18nService.autoFill, }); // Firefox & Edge do not support writing to the clipboard from background @@ -108,7 +367,7 @@ export default class MainBackground { id: 'copy-username', parentId: 'root', contexts: ['all'], - title: this.i18nService.copyUsername + title: this.i18nService.copyUsername, }); await this.contextMenusCreate({ @@ -116,12 +375,12 @@ export default class MainBackground { id: 'copy-password', parentId: 'root', contexts: ['all'], - title: this.i18nService.copyPassword + title: this.i18nService.copyPassword, }); await this.contextMenusCreate({ type: 'separator', - parentId: 'root' + parentId: 'root', }); await this.contextMenusCreate({ @@ -129,7 +388,7 @@ export default class MainBackground { id: 'generate-password', parentId: 'root', contexts: ['all'], - title: this.i18nService.generatePasswordCopied + title: this.i18nService.generatePasswordCopied, }); } @@ -186,7 +445,7 @@ export default class MainBackground { return; } - var tabDomain = this.utilsService.getDomain(url); + const tabDomain = this.utilsService.getDomain(url); if (tabDomain == null) { return; } @@ -200,12 +459,12 @@ export default class MainBackground { ciphers.sort(this.cipherService.sortCiphersByLastUsedThenName); if (contextMenuEnabled) { - ciphers.forEach((ciphers) => { - this.loadLoginContextMenuOptions(ciphers); + ciphers.forEach((cipher) => { + this.loadLoginContextMenuOptions(cipher); }); } - var theText = ''; + let theText = ''; if (ciphers.length > 0 && ciphers.length < 9) { theText = ciphers.length.toString(); } else if (ciphers.length > 0) { @@ -259,7 +518,7 @@ export default class MainBackground { id: 'autofill_' + idSuffix, parentId: 'autofill', contexts: ['all'], - title: title + title: title, }); } @@ -274,7 +533,7 @@ export default class MainBackground { id: 'copy-username_' + idSuffix, parentId: 'copy-username', contexts: ['all'], - title: title + title: title, }); } @@ -284,7 +543,7 @@ export default class MainBackground { id: 'copy-password_' + idSuffix, parentId: 'copy-password', contexts: ['all'], - title: title + title: title, }); } } @@ -299,15 +558,15 @@ export default class MainBackground { chrome.tabs.sendMessage(tab.id, { command: 'collectPageDetails', tab: tab, - sender: 'contextMenu' - }, function () { }); + sender: 'contextMenu', + }); } private async autofillPage() { await this.autofillService.doAutoFill({ cipher: this.loginToAutoFill, pageDetails: this.pageDetailsToAutoFill, - fromBackground: true + fromBackground: true, }); // reset @@ -315,7 +574,7 @@ export default class MainBackground { this.pageDetailsToAutoFill = []; } - private async logout(expired: boolean, callback: Function) { + private async logout(expired: boolean) { const userId = await this.userService.getUserId(); await Promise.all([ @@ -326,26 +585,215 @@ export default class MainBackground { this.settingsService.clear(userId), this.cipherService.clear(userId), this.folderService.clear(userId), - this.passwordGenerationService.clear() + this.passwordGenerationService.clear(), ]); chrome.runtime.sendMessage({ - command: 'doneLoggingOut', expired: expired + command: 'doneLoggingOut', expired: expired, }); await this.setIcon(); await this.refreshBadgeAndMenu(); + } - if (callback != null) { - callback(); + private collectPageDetailsForContentScript(tab: any, sender: string, frameId: number = null) { + if (tab == null || !tab.id) { + return; + } + + const options: any = {}; + if (frameId != null) { + options.frameId = frameId; + } + + chrome.tabs.sendMessage(tab.id, { + command: 'collectPageDetails', + tab: tab, + sender: sender, + }, options, () => { + if (chrome.runtime.lastError) { + return; + } + }); + } + + private async addLogin(loginInfo: any, tab: any) { + const loginDomain = UtilsService.getDomain(loginInfo.url); + if (loginDomain == null) { + return; + } + + const ciphers = await this.cipherService.getAllDecryptedForDomain(loginDomain); + + let match = false; + for (let i = 0; i < ciphers.length; i++) { + if (ciphers[i].login.username === loginInfo.username) { + match = true; + break; + } + } + + if (!match) { + // remove any old logins for this tab + this.removeAddLogin(tab); + + this.loginsToAdd.push({ + username: loginInfo.username, + password: loginInfo.password, + name: loginDomain, + domain: loginDomain, + uri: loginInfo.url, + tabId: tab.id, + expires: new Date((new Date()).getTime() + 30 * 60000), // 30 minutes + }); + + await this.checkLoginsToAdd(tab); } } - // Browser APIs + private cleanupLoginsToAdd() { + for (let i = this.loginsToAdd.length - 1; i >= 0; i--) { + if (this.loginsToAdd[i].expires < new Date()) { + this.loginsToAdd.splice(i, 1); + } + } + + setTimeout(() => this.cleanupLoginsToAdd(), 2 * 60 * 1000); // check every 2 minutes + } + + private removeAddLogin(tab: any) { + for (let i = this.loginsToAdd.length - 1; i >= 0; i--) { + if (this.loginsToAdd[i].tabId === tab.id) { + this.loginsToAdd.splice(i, 1); + } + } + } + + private async saveAddLogin(tab: any) { + for (let i = this.loginsToAdd.length - 1; i >= 0; i--) { + if (this.loginsToAdd[i].tabId !== tab.id) { + continue; + } + + const loginInfo = this.loginsToAdd[i]; + const tabDomain = UtilsService.getDomain(tab.url); + if (tabDomain != null && tabDomain !== loginInfo.domain) { + continue; + } + + this.loginsToAdd.splice(i, 1); + + const cipher = await this.cipherService.encrypt({ + id: null, + folderId: null, + favorite: false, + name: loginInfo.name, + notes: null, + type: CipherType.Login, + login: { + uri: loginInfo.uri, + username: loginInfo.username, + password: loginInfo.password, + }, + }); + + await this.cipherService.saveWithServer(cipher); + (window as any).ga('send', { + hitType: 'event', + eventAction: 'Added Login from Notification Bar', + }); + + this.tabSendMessage(tab.id, 'closeNotificationBar'); + } + } + + private async checkLoginsToAdd(tab: any = null): Promise { + if (!this.loginsToAdd.length) { + return; + } + + if (tab != null) { + this.doCheck(tab); + return; + } + + const currentTab = await this.tabsQueryFirst({ active: true, currentWindow: true }); + if (currentTab != null) { + this.doCheck(tab); + } + } + + private doCheck(tab: any) { + if (tab == null) { + return; + } + + const tabDomain = UtilsService.getDomain(tab.url); + if (tabDomain == null) { + return; + } + + for (let i = 0; i < this.loginsToAdd.length; i++) { + if (this.loginsToAdd[i].tabId !== tab.id || this.loginsToAdd[i].domain !== tabDomain) { + continue; + } + + this.tabSendMessage(tab.id, 'openNotificationBar', { + type: 'add', + }); + break; + } + } + + private async saveNever(tab: any) { + for (let i = this.loginsToAdd.length - 1; i >= 0; i--) { + if (this.loginsToAdd[i].tabId !== tab.id) { + continue; + } + + const loginInfo = this.loginsToAdd[i]; + const tabDomain = UtilsService.getDomain(tab.url); + if (tabDomain != null && tabDomain !== loginInfo.domain) { + continue; + } + + this.loginsToAdd.splice(i, 1); + const hostname = UtilsService.getHostname(tab.url); + await this.cipherService.saveNeverDomain(hostname); + this.tabSendMessage(tab.id, 'closeNotificationBar'); + } + } + + private async fullSync(override: boolean = false) { + const syncInternal = 6 * 60 * 60 * 1000; // 6 hours + const lastSync = await this.syncService.getLastSync(); + + let lastSyncAgo = syncInternal + 1; + if (lastSync != null) { + lastSyncAgo = new Date().getTime() - lastSync.getTime(); + } + + if (override || lastSyncAgo >= syncInternal) { + await this.syncService.fullSync(override); + this.scheduleNextSync(); + } else { + this.scheduleNextSync(); + } + } + + private scheduleNextSync() { + if (this.syncTimeout) { + clearTimeout(this.syncTimeout); + } + + this.syncTimeout = setTimeout(async () => await this.fullSync(), 5 * 60 * 1000); // check every 5 minutes + } + + // Browser API Helpers private contextMenusRemoveAll() { return new Promise((resolve) => { - chrome.contextMenus.removeAll(function () { + chrome.contextMenus.removeAll(() => { resolve(); if (chrome.runtime.lastError) { return; @@ -356,7 +804,7 @@ export default class MainBackground { private contextMenusCreate(options: any) { return new Promise((resolve) => { - chrome.contextMenus.create(options, function () { + chrome.contextMenus.create(options, () => { resolve(); if (chrome.runtime.lastError) { return; @@ -367,7 +815,7 @@ export default class MainBackground { private tabsQuery(options: any): Promise { return new Promise((resolve) => { - chrome.tabs.query(options, function (tabs: any[]) { + chrome.tabs.query(options, (tabs: any[]) => { resolve(tabs); }); }); @@ -375,7 +823,7 @@ export default class MainBackground { private tabsQueryFirst(options: any): Promise { return new Promise((resolve) => { - chrome.tabs.query(options, function (tabs: any[]) { + chrome.tabs.query(options, (tabs: any[]) => { if (tabs.length > 0) { resolve(tabs[0]); return; @@ -394,10 +842,10 @@ export default class MainBackground { return new Promise((resolve) => { theAction.setIcon({ path: { - '19': 'images/icon19' + suffix + '.png', - '38': 'images/icon38' + suffix + '.png', - } - }, function () { + 19: 'images/icon19' + suffix + '.png', + 38: 'images/icon38' + suffix + '.png', + }, + }, () => { resolve(); }); }); @@ -413,7 +861,7 @@ export default class MainBackground { if (chrome.browserAction && chrome.browserAction.setBadgeText) { chrome.browserAction.setBadgeText({ text: text, - tabId: tabId + tabId: tabId, }); } } @@ -426,7 +874,7 @@ export default class MainBackground { if (this.sidebarAction.setBadgeText) { this.sidebarAction.setBadgeText({ text: text, - tabId: tabId + tabId: tabId, }); } else if (this.sidebarAction.setTitle) { let title = 'bitwarden'; @@ -436,13 +884,13 @@ export default class MainBackground { this.sidebarAction.setTitle({ title: title, - tabId: tabId + tabId: tabId, }); } } - private async currentTabSendMessage(command: string, data: any) { - var tab = await this.tabsQueryFirst({ active: true, currentWindow: true }); + private async currentTabSendMessage(command: string, data: any = null) { + const tab = await this.tabsQueryFirst({ active: true, currentWindow: true }); if (tab == null) { return; } @@ -450,13 +898,13 @@ export default class MainBackground { await this.tabSendMessage(tab.id, command, data); } - private async tabSendMessage(tabId: number, command: string, data: any) { + private async tabSendMessage(tabId: number, command: string, data: any = null) { if (!tabId) { return; } const obj: any = { - command: command + command: command, }; if (data != null) { @@ -464,7 +912,7 @@ export default class MainBackground { } return new Promise((resolve) => { - chrome.tabs.sendMessage(tabId, obj, function () { + chrome.tabs.sendMessage(tabId, obj, () => { resolve(); }); }); diff --git a/src/models/domain/cipher.ts b/src/models/domain/cipher.ts index 1369c9967d..3149f78fd5 100644 --- a/src/models/domain/cipher.ts +++ b/src/models/domain/cipher.ts @@ -120,7 +120,7 @@ class Cipher extends Domain { model.subTitle = model.login.username; if (model.login.uri) { if (this.utilsService == null) { - this.utilsService = chrome.extension.getBackgroundPage().bg_utilsService as UtilsService; + this.utilsService = chrome.extension.getBackgroundPage().bg_main.utilsService as UtilsService; } model.login.domain = this.utilsService.getDomain(model.login.uri); diff --git a/src/models/domain/cipherString.ts b/src/models/domain/cipherString.ts index 26d557e7ec..41fbfc520c 100644 --- a/src/models/domain/cipherString.ts +++ b/src/models/domain/cipherString.ts @@ -95,7 +95,7 @@ class CipherString { const self = this; if (this.cryptoService == null) { - this.cryptoService = chrome.extension.getBackgroundPage().bg_cryptoService as CryptoService; + this.cryptoService = chrome.extension.getBackgroundPage().bg_main.cryptoService as CryptoService; } return this.cryptoService.getOrgKey(orgId).then((orgKey: any) => { diff --git a/src/popup/app/services/background.service.ts b/src/popup/app/services/background.service.ts index 4693bd0566..bf2387dfb8 100644 --- a/src/popup/app/services/background.service.ts +++ b/src/popup/app/services/background.service.ts @@ -4,7 +4,7 @@ import { UtilsService } from '../../../services/abstractions/utils.service'; function getBackgroundService(service: string) { return (): T => { const page = chrome.extension.getBackgroundPage(); - return page ? page['bg_' + service] as T : null; + return page ? page.bg_main[service] as T : null; }; } diff --git a/src/scripts/analytics.js b/src/scripts/analytics.js index b37b917711..559531c824 100644 --- a/src/scripts/analytics.js +++ b/src/scripts/analytics.js @@ -4,9 +4,14 @@ return; } - var gaTrackingId = bgPage.bg_utilsService.analyticsId(); + var bgMain = bgPage.bg_main; + if (!bgMain) { + return; + } + + var gaTrackingId = bgMain.utilsService.analyticsId(); var gaFunc = null; - var isFirefox = bgPage.bg_utilsService.isFirefox(); + var isFirefox = bgMain.utilsService.isFirefox(); window.GoogleAnalyticsObject = 'ga'; window[window.GoogleAnalyticsObject] = function (action, param1, param2, param3, param4) { @@ -47,7 +52,7 @@ return encodeURIComponent(pagePath); } - bgPage.bg_appIdService.getAnonymousAppId().then(function (gaAnonAppId) { + bgMain.appIdService.getAnonymousAppId().then(function (gaAnonAppId) { gaFunc = function (action, param1, param2, param3, param4) { if (action !== 'send' || !param1) { return; diff --git a/tsconfig.json b/tsconfig.json index 3966cd41fc..e65247c974 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,6 +14,7 @@ "dist", "build", "coverage", - "store" + "store", + "src/edge" ] }