diff --git a/src/background/commands.background.ts b/src/background/commands.background.ts index 4c85c71eb42..26a3089e879 100644 --- a/src/background/commands.background.ts +++ b/src/background/commands.background.ts @@ -1,4 +1,4 @@ -import BrowserApi from '../browser/browserApi'; +import { BrowserApi } from '../browser/browserApi'; import MainBackground from './main.background'; diff --git a/src/background/contextMenus.background.ts b/src/background/contextMenus.background.ts index d714744681e..b0a37ee9aa8 100644 --- a/src/background/contextMenus.background.ts +++ b/src/background/contextMenus.background.ts @@ -1,4 +1,4 @@ -import BrowserApi from '../browser/browserApi'; +import { BrowserApi } from '../browser/browserApi'; import MainBackground from './main.background'; diff --git a/src/background/main.background.ts b/src/background/main.background.ts index 7588494ad27..7f2acd060b8 100644 --- a/src/background/main.background.ts +++ b/src/background/main.background.ts @@ -43,7 +43,7 @@ import { import Analytics from '../scripts/analytics'; -import BrowserApi from '../browser/browserApi'; +import { BrowserApi } from '../browser/browserApi'; import CommandsBackground from './commands.background'; import ContextMenusBackground from './contextMenus.background'; diff --git a/src/background/runtime.background.ts b/src/background/runtime.background.ts index 17b3c21d094..98ced34d37a 100644 --- a/src/background/runtime.background.ts +++ b/src/background/runtime.background.ts @@ -7,7 +7,7 @@ import { PlatformUtilsService, } from 'jslib/abstractions'; -import BrowserApi from '../browser/browserApi'; +import { BrowserApi } from '../browser/browserApi'; import MainBackground from './main.background'; diff --git a/src/browser/browserApi.ts b/src/browser/browserApi.ts index 198b3eec534..6e5521b0fe5 100644 --- a/src/browser/browserApi.ts +++ b/src/browser/browserApi.ts @@ -1,4 +1,4 @@ -export default class BrowserApi { +class BrowserApi { static isSafariApi: boolean = (typeof safari !== 'undefined'); static isChromeApi: boolean = (typeof chrome !== 'undefined'); @@ -72,4 +72,37 @@ export default class BrowserApi { return null; } } + + static isPopupOpen(): boolean { + if (BrowserApi.isChromeApi) { + return chrome.extension.getViews({ type: 'popup' }).length > 0; + } else if (BrowserApi.isSafariApi) { + return true; // TODO + } else { + return null; + } + } + + static createNewTab(url: string): void { + if (BrowserApi.isChromeApi) { + chrome.tabs.create({ url: url }); + } else if (BrowserApi.isSafariApi) { + return; // TODO + } else { + return; + } + } + + static getAssetUrl(path: string): string { + if (BrowserApi.isChromeApi) { + return chrome.extension.getURL(path); + } else if (BrowserApi.isSafariApi) { + return './' + path; // TODO? + } else { + return null; + } + } } + +export { BrowserApi }; +(window as any).BrowserApi = BrowserApi; diff --git a/src/popup/app/accounts/accountsLoginTwoFactorController.js b/src/popup/app/accounts/accountsLoginTwoFactorController.js index c644ad8de90..b614094f031 100644 --- a/src/popup/app/accounts/accountsLoginTwoFactorController.js +++ b/src/popup/app/accounts/accountsLoginTwoFactorController.js @@ -183,9 +183,8 @@ angular params = providers[constants.twoFactorProvider.email]; $scope.twoFactorEmail = params.Email; - if (chrome.extension.getViews({ type: 'popup' }).length > 0 && - !popupUtilsService.inSidebar($window) && !popupUtilsService.inTab($window) && - !popupUtilsService.inPopout($window)) { + if (BrowserApi.isPopupOpen() && !popupUtilsService.inSidebar($window) && + !popupUtilsService.inTab($window) && !popupUtilsService.inPopout($window)) { SweetAlert.swal({ title: i18nService.twoStepLogin, text: i18nService.popup2faCloseMessage, @@ -194,7 +193,7 @@ angular cancelButtonText: i18nService.no }, function (confirmed) { if (confirmed) { - chrome.tabs.create({ url: '/popup/index.html?uilocation=tab#!/login' }); + BrowserApi.createNewTab('/popup/index.html?uilocation=tab#!/login'); return; } else if (Object.keys(providers).length > 1) { diff --git a/src/popup/app/accounts/accountsTwoFactorMethodsController.js b/src/popup/app/accounts/accountsTwoFactorMethodsController.js index ce3d5288617..09f1cf6e4f8 100644 --- a/src/popup/app/accounts/accountsTwoFactorMethodsController.js +++ b/src/popup/app/accounts/accountsTwoFactorMethodsController.js @@ -52,7 +52,7 @@ angular $scope.recover = function () { $analytics.eventTrack('Selected Recover'); - chrome.tabs.create({ url: 'https://help.bitwarden.com/article/lost-two-step-device/' }); + BrowserApi.createNewTab('https://help.bitwarden.com/article/lost-two-step-device/'); }; function add(type) { diff --git a/src/popup/app/components/action-buttons.component.ts b/src/popup/app/components/action-buttons.component.ts index 0295ae9d666..6d224732625 100644 --- a/src/popup/app/components/action-buttons.component.ts +++ b/src/popup/app/components/action-buttons.component.ts @@ -1,5 +1,7 @@ import * as template from './action-buttons.component.html'; +import { BrowserApi } from '../../../browser/browserApi'; + import { ConstantsService } from 'jslib/services/constants.service'; import PopupUtilsService from '../services/popupUtils.service'; @@ -23,7 +25,7 @@ export class ActionButtonsController implements ng.IController { this.$timeout(() => { if (self.cipher.login.uri.startsWith('http://') || self.cipher.login.uri.startsWith('https://')) { self.$analytics.eventTrack('Launched Website From Listing'); - chrome.tabs.create({ url: self.cipher.login.uri }); + BrowserApi.createNewTab(self.cipher.login.uri); if (PopupUtilsService.inPopup(self.$window)) { self.$window.close(); } diff --git a/src/popup/app/components/icon.component.ts b/src/popup/app/components/icon.component.ts index 6abed57f087..eabbb2c5898 100644 --- a/src/popup/app/components/icon.component.ts +++ b/src/popup/app/components/icon.component.ts @@ -1,5 +1,7 @@ import * as template from './icon.component.html'; +import { BrowserApi } from '../../../browser/browserApi'; + import { CipherType } from 'jslib/enums/cipherType'; import { EnvironmentService } from 'jslib/abstractions/environment.service'; @@ -68,7 +70,7 @@ export class IconController implements ng.IController { try { const url = new URL(hostnameUri); this.image = this.iconsUrl + '/' + url.hostname + '/icon.png'; - this.fallbackImage = chrome.extension.getURL('images/fa-globe.png'); + this.fallbackImage = BrowserApi.getAssetUrl('images/fa-globe.png'); } catch (e) { } } } else { diff --git a/src/popup/app/components/pop-out.component.ts b/src/popup/app/components/pop-out.component.ts index 657d843accf..25f88290985 100644 --- a/src/popup/app/components/pop-out.component.ts +++ b/src/popup/app/components/pop-out.component.ts @@ -23,7 +23,7 @@ export class PopOutController implements ng.IController { } } - if (chrome && chrome.windows && chrome.windows.create) { + if ((typeof chrome !== 'undefined') && chrome.windows && chrome.windows.create) { if (href.indexOf('?uilocation=') > -1) { href = href.replace('uilocation=popup', 'uilocation=popout') .replace('uilocation=tab', 'uilocation=popout') @@ -44,13 +44,15 @@ export class PopOutController implements ng.IController { if (PopupUtilsService.inPopup(this.$window)) { this.$window.close(); } - } else if (chrome && chrome.tabs && chrome.tabs.create) { + } else if ((typeof chrome !== 'undefined') && chrome.tabs && chrome.tabs.create) { href = href.replace('uilocation=popup', 'uilocation=tab') .replace('uilocation=popout', 'uilocation=tab') .replace('uilocation=sidebar', 'uilocation=tab'); chrome.tabs.create({ url: href, }); + } else if ((typeof safari !== 'undefined')) { + // TODO? } } } diff --git a/src/popup/app/config.js b/src/popup/app/config.js index 93397a2083c..e74869350db 100644 --- a/src/popup/app/config.js +++ b/src/popup/app/config.js @@ -15,7 +15,7 @@ angular $urlRouterProvider.otherwise(function ($injector, $location) { var $state = $injector.get('$state'); - if ((typeof chrome !== 'undefined') && !chrome.extension.getBackgroundPage()) { + if (!BrowserApi.getBackgroundPage()) { $state.go('privateMode'); return; } diff --git a/src/popup/app/global/private-mode.controller.ts b/src/popup/app/global/private-mode.controller.ts index 23a0c60fd2c..7ae60b5cf55 100644 --- a/src/popup/app/global/private-mode.controller.ts +++ b/src/popup/app/global/private-mode.controller.ts @@ -1,9 +1,11 @@ +import { BrowserApi } from '../../../browser/browserApi'; + export class PrivateModeController implements ng.IController { constructor($scope: any) { $scope.privateModeMessage = chrome.i18n.getMessage('privateModeMessage'); $scope.learnMoreMessage = chrome.i18n.getMessage('learnMore'); $scope.learnMore = () => { - chrome.tabs.create({ url: 'https://help.bitwarden.com/article/extension-wont-load-in-private-mode/' }); + BrowserApi.createNewTab('https://help.bitwarden.com/article/extension-wont-load-in-private-mode/'); }; } } diff --git a/src/popup/app/services/background.service.ts b/src/popup/app/services/background.service.ts index 48aaae7df38..e135d8a4bf5 100644 --- a/src/popup/app/services/background.service.ts +++ b/src/popup/app/services/background.service.ts @@ -1,4 +1,4 @@ -import BrowserApi from '../../../browser/browserApi'; +import { BrowserApi } from '../../../browser/browserApi'; import { ConstantsService } from 'jslib/services/constants.service'; diff --git a/src/popup/app/settings/about.component.ts b/src/popup/app/settings/about.component.ts index 21c215139be..6956d8ebbd8 100644 --- a/src/popup/app/settings/about.component.ts +++ b/src/popup/app/settings/about.component.ts @@ -1,6 +1,6 @@ import * as template from './about.component.html'; -import BrowserApi from '../../../browser/browserApi'; +import { BrowserApi } from '../../../browser/browserApi'; export class AboutController { version: string; diff --git a/src/popup/app/settings/credits.component.ts b/src/popup/app/settings/credits.component.ts index ec170b17d04..444f997cf5d 100644 --- a/src/popup/app/settings/credits.component.ts +++ b/src/popup/app/settings/credits.component.ts @@ -1,5 +1,7 @@ import * as template from './credits.component.html'; +import { BrowserApi } from '../../../browser/browserApi'; + export class CreditsController { i18n: any; @@ -9,10 +11,7 @@ export class CreditsController { learnMore() { this.$analytics.eventTrack('Contribute Learn More'); - - chrome.tabs.create({ - url: 'https://github.com/bitwarden/browser/blob/master/CONTRIBUTING.md', - }); + BrowserApi.createNewTab('https://github.com/bitwarden/browser/blob/master/CONTRIBUTING.md'); } } diff --git a/src/popup/app/settings/help.component.ts b/src/popup/app/settings/help.component.ts index 10ff4800ee7..5727f5af497 100644 --- a/src/popup/app/settings/help.component.ts +++ b/src/popup/app/settings/help.component.ts @@ -1,5 +1,7 @@ import * as template from './help.component.html'; +import { BrowserApi } from '../../../browser/browserApi'; + export class HelpController { i18n: any; @@ -9,22 +11,22 @@ export class HelpController { email() { this.$analytics.eventTrack('Selected Help Email'); - chrome.tabs.create({ url: 'mailto:hello@bitwarden.com' }); + BrowserApi.createNewTab('mailto:hello@bitwarden.com'); } website() { this.$analytics.eventTrack('Selected Help Website'); - chrome.tabs.create({ url: 'https://bitwarden.com/contact/' }); + BrowserApi.createNewTab('https://bitwarden.com/contact/'); } tutorial() { this.$analytics.eventTrack('Selected Help Tutorial'); - chrome.tabs.create({ url: 'https://bitwarden.com/browser-start/' }); + BrowserApi.createNewTab('https://bitwarden.com/browser-start/'); } bug() { this.$analytics.eventTrack('Selected Help Bug Report'); - chrome.tabs.create({ url: 'https://github.com/bitwarden/browser' }); + BrowserApi.createNewTab('https://github.com/bitwarden/browser'); } } diff --git a/src/popup/app/settings/premium.component.ts b/src/popup/app/settings/premium.component.ts index 7f4371aec4f..7326c085760 100644 --- a/src/popup/app/settings/premium.component.ts +++ b/src/popup/app/settings/premium.component.ts @@ -1,5 +1,7 @@ import * as template from './premium.component.html'; +import { BrowserApi } from '../../../browser/browserApi'; + import { ApiService } from 'jslib/abstractions/api.service'; import { TokenService } from 'jslib/abstractions/token.service'; @@ -35,7 +37,7 @@ export class PremiumController { }, (confirmed: boolean) => { this.$analytics.eventTrack('Clicked Purchase Premium'); if (confirmed) { - chrome.tabs.create({ url: 'https://vault.bitwarden.com/#/?premium=purchase' }); + BrowserApi.createNewTab('https://vault.bitwarden.com/#/?premium=purchase'); } }); } @@ -50,7 +52,7 @@ export class PremiumController { }, (confirmed: boolean) => { this.$analytics.eventTrack('Clicked Manage Membership'); if (confirmed) { - chrome.tabs.create({ url: 'https://vault.bitwarden.com/#/?premium=manage' }); + BrowserApi.createNewTab('https://vault.bitwarden.com/#/?premium=manage'); } }); } diff --git a/src/popup/app/settings/settings.component.ts b/src/popup/app/settings/settings.component.ts index 24a389b5376..bf55eff270a 100644 --- a/src/popup/app/settings/settings.component.ts +++ b/src/popup/app/settings/settings.component.ts @@ -1,6 +1,8 @@ import * as angular from 'angular'; import * as template from './settings.component.html'; +import { BrowserApi } from '../../../browser/browserApi'; + import { DeviceType } from 'jslib/enums/deviceType'; import { ConstantsService } from 'jslib/services/constants.service'; @@ -116,7 +118,7 @@ export class SettingsController { }, (confirmed: boolean) => { this.$analytics.eventTrack('Clicked Change Password'); if (confirmed) { - chrome.tabs.create({ url: 'https://help.bitwarden.com/article/change-your-master-password/' }); + BrowserApi.createNewTab('https://help.bitwarden.com/article/change-your-master-password/'); } }); } @@ -131,7 +133,7 @@ export class SettingsController { }, (confirmed: boolean) => { this.$analytics.eventTrack('Clicked Change Email'); if (confirmed) { - chrome.tabs.create({ url: 'https://help.bitwarden.com/article/change-your-email/' }); + BrowserApi.createNewTab('https://help.bitwarden.com/article/change-your-email/'); } }); } @@ -146,16 +148,14 @@ export class SettingsController { }, (confirmed: boolean) => { this.$analytics.eventTrack('Clicked Two-step Login'); if (confirmed) { - chrome.tabs.create({ url: 'https://help.bitwarden.com/article/setup-two-step-login/' }); + BrowserApi.createNewTab('https://help.bitwarden.com/article/setup-two-step-login/'); } }); } rate() { this.$analytics.eventTrack('Rate Extension'); - chrome.tabs.create({ - url: RateUrls[this.platformUtilsService.getDevice()], - }); + BrowserApi.createNewTab(RateUrls[this.platformUtilsService.getDevice()]); } } diff --git a/src/popup/app/tools/tools.component.ts b/src/popup/app/tools/tools.component.ts index 395c4c6cf65..237ecbdc040 100644 --- a/src/popup/app/tools/tools.component.ts +++ b/src/popup/app/tools/tools.component.ts @@ -1,5 +1,7 @@ import * as template from './tools.component.html'; +import { BrowserApi } from '../../../browser/browserApi'; + import { EnvironmentService } from 'jslib/abstractions/environment.service'; import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; @@ -22,20 +24,18 @@ export class ToolsController { launchWebVault(createOrg: any) { this.$analytics.eventTrack('Launch Web Vault' + (createOrg ? ' For Share' : '')); - chrome.tabs.create({ url: this.webVaultBaseUrl + '/#/' + (createOrg ? '?org=free' : '') }); + BrowserApi.createNewTab(this.webVaultBaseUrl + '/#/' + (createOrg ? '?org=free' : '')); } launchAndroid() { this.$analytics.eventTrack('Launch Android'); - chrome.tabs.create({ url: 'https://play.google.com/store/apps/details?id=com.x8bit.bitwarden' }); + BrowserApi.createNewTab('https://play.google.com/store/apps/details?id=com.x8bit.bitwarden'); } launchiOS() { this.$analytics.eventTrack('Launch iOS'); - chrome.tabs.create({ - url: 'https://itunes.apple.com/us/app/bitwarden-free-password-manager/' + - 'id1137397744?mt=8', - }); + BrowserApi.createNewTab('https://itunes.apple.com/us/app/bitwarden-free-password-manager/' + + 'id1137397744?mt=8'); } launchImport() { @@ -48,7 +48,7 @@ export class ToolsController { }, (confirmed: boolean) => { if (confirmed) { this.$analytics.eventTrack('Launch Web Vault For Import'); - chrome.tabs.create({ url: 'https://help.bitwarden.com/article/import-data/' }); + BrowserApi.createNewTab('https://help.bitwarden.com/article/import-data/'); } }); } diff --git a/src/popup/app/vault/vaultAttachmentsController.js b/src/popup/app/vault/vaultAttachmentsController.js index ad09a25c834..463d262fa25 100644 --- a/src/popup/app/vault/vaultAttachmentsController.js +++ b/src/popup/app/vault/vaultAttachmentsController.js @@ -27,7 +27,7 @@ angular cancelButtonText: i18nService.cancel }, function (confirmed) { if (confirmed) { - chrome.tabs.create({ url: 'https://vault.bitwarden.com/#/?premium=purchase' }); + BrowserApi.createNewTab('https://vault.bitwarden.com/#/?premium=purchase'); } }); return; @@ -44,7 +44,7 @@ angular cancelButtonText: i18nService.cancel }, function (confirmed) { if (confirmed) { - chrome.tabs.create({ url: 'https://help.bitwarden.com/article/update-encryption-key/' }); + BrowserApi.createNewTab('https://help.bitwarden.com/article/update-encryption-key/'); } }); } diff --git a/src/popup/app/vault/vaultController.js b/src/popup/app/vault/vaultController.js index 3b51ac10873..6ad6ab64f81 100644 --- a/src/popup/app/vault/vaultController.js +++ b/src/popup/app/vault/vaultController.js @@ -208,7 +208,7 @@ angular $scope.launchWebsite = function (cipher) { if (cipher.login && cipher.login.uri) { $analytics.eventTrack('Launched Website'); - chrome.tabs.create({ url: cipher.login.uri }); + BrowserApi.createNewTab(cipher.login.uri); } }; diff --git a/src/popup/app/vault/vaultViewCipherController.js b/src/popup/app/vault/vaultViewCipherController.js index 2ef7d44e594..89469960974 100644 --- a/src/popup/app/vault/vaultViewCipherController.js +++ b/src/popup/app/vault/vaultViewCipherController.js @@ -91,7 +91,7 @@ angular $scope.launchWebsite = function (cipher) { if (cipher.showLaunch) { $analytics.eventTrack('Launched Website'); - chrome.tabs.create({ url: cipher.login.uri }); + BrowserApi.createNewTab(cipher.login.uri); } }; @@ -133,7 +133,7 @@ angular cancelButtonText: i18nService.cancel }, function (confirmed) { if (confirmed) { - chrome.tabs.create({ url: 'https://bitwarden.com' }); + BrowserApi.createNewTab('https://bitwarden.com'); } }); return; diff --git a/src/popup/app/vault/vaultViewGroupingController.js b/src/popup/app/vault/vaultViewGroupingController.js index 1cf939a9fa4..33d7f534dfe 100644 --- a/src/popup/app/vault/vaultViewGroupingController.js +++ b/src/popup/app/vault/vaultViewGroupingController.js @@ -216,7 +216,7 @@ angular $scope.launchWebsite = function (cipher) { if (cipher.login && cipher.login.uri) { $analytics.eventTrack('Launched Website'); - chrome.tabs.create({ url: cipher.login.uri }); + BrowserApi.createNewTab(cipher.login.uri); } }; diff --git a/src/scripts/analytics.ts b/src/scripts/analytics.ts index 1b1368bbd8f..c343c6cbbd9 100644 --- a/src/scripts/analytics.ts +++ b/src/scripts/analytics.ts @@ -1,4 +1,4 @@ -import BrowserApi from '../browser/browserApi'; +import { BrowserApi } from '../browser/browserApi'; import { AppIdService } from 'jslib/abstractions/appId.service'; import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';