From a99ce875caae5323dbbf3a29c727566fd94d0810 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 12 Oct 2017 20:48:29 +0200 Subject: [PATCH] Website icons (#285) * Initial attempt at adding favicons. * Cache the favicons for 30 days. * Refactor faviconService, remove unused faviconDirective. * Change icon url to icons.bitwarden.com. Update style to support dynamic size of icon. * Use hostname instead of domain. * Fix getFavicon throwing an exception if the uri is not a valid url. * Add enabled property to faviconService to prevent slow calls to storage. Fixed chrome not displaying chrome://favicon properly. * Fix chrome disable favicon not working as expected. * Add default icon. * Fix jshint errors. * Cleanup of faviconService, removed caching related code. Add faviconComponent for handling favicons. * Remove faviconService, moved functionallity into faviconComponent. * Fix faviconComponent not updating when uri changes. * Rename favicon to icon. * Improve whitelist. --- src/_locales/en/messages.json | 6 ++++ src/images/fa-globe.png | Bin 0 -> 729 bytes src/popup/app/app.js | 1 + src/popup/app/components/componentsModule.js | 2 ++ src/popup/app/components/iconComponent.js | 26 ++++++++++++++ src/popup/app/config.js | 11 ++++-- src/popup/app/current/views/current.html | 1 + .../settings/settingsFeaturesController.js | 33 +++++++++++++++++- .../app/settings/views/settingsFeatures.html | 12 +++++++ src/popup/app/vault/views/vault.html | 2 ++ src/popup/index.html | 3 ++ src/popup/less/components.less | 14 ++++++++ src/services/constantsService.js | 1 + 13 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 src/images/fa-globe.png create mode 100644 src/popup/app/components/componentsModule.js create mode 100644 src/popup/app/components/iconComponent.js diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index a404572c2c0..ed722ddfed3 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -780,5 +780,11 @@ }, "popup2faCloseMessage": { "message": "Clicking outside the popup window to check your email for your verification code will cause this popup to close. Do you want to open this popup in a new window so that it does not close?" + }, + "disableFavicon": { + "message": "Disable Website Icons" + }, + "disableFaviconDesc": { + "message": "Website Icons, also known as \"Favicons\", provides an image next to the login vault." } } diff --git a/src/images/fa-globe.png b/src/images/fa-globe.png new file mode 100644 index 0000000000000000000000000000000000000000..c3331f365847c3a001c5a2c879a5af6b34755b7f GIT binary patch literal 729 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H3?x5i&EaHVVAKro32_B-%SQnbA;7(}ZYnUa zl1hU7f*BZ@m|0la*f}`4d3gEw1q4OKB_w6!6cm+J)HJnp^bJj{Z5>@)Jp%%RLStg% zQZh1ga`Q_oTRXe^CQh0@W7eW&tJiMWx_#%aJ^KzGJ#p^*<*V0k-MRPV*~`~&-+%u4 z{pat$&*J{-0&V;2>Eak7AsKp*-JXe&;n>6Pll(4D5S-}SVYF#e>yk4$THpWwlRs4Y zxc&LW<=Uq6Pp2LFrM@lw;SP`2*STUgrtVF&<~ddDP-|f)U^@N94&IX+&#qI{EI9Vm zO?rjorrtoqlC~8FCxbm(R68~%-4bk zd5<$fgM=&GR7F3ml|SA-ZT|wT=m(7Vmo4E5bCRugTe~DWM4fxAH=x literal 0 HcmV?d00001 diff --git a/src/popup/app/app.js b/src/popup/app/app.js index e6e3916fb89..0a9c77db351 100644 --- a/src/popup/app/app.js +++ b/src/popup/app/app.js @@ -7,6 +7,7 @@ 'angulartics.google.analytics', 'bit.directives', + 'bit.components', 'bit.services', 'bit.global', diff --git a/src/popup/app/components/componentsModule.js b/src/popup/app/components/componentsModule.js new file mode 100644 index 00000000000..df72afaf0e0 --- /dev/null +++ b/src/popup/app/components/componentsModule.js @@ -0,0 +1,2 @@ +angular + .module('bit.components', []); diff --git a/src/popup/app/components/iconComponent.js b/src/popup/app/components/iconComponent.js new file mode 100644 index 00000000000..66c587f780e --- /dev/null +++ b/src/popup/app/components/iconComponent.js @@ -0,0 +1,26 @@ +angular + .module('bit.components') + .component('icon', { + bindings: { + uri: '<' + }, + template: '
', + controller: function(stateService) { + this.$onInit = (function() { + this.enabled = function() { + return stateService.getState('faviconEnabled'); + }; + }).bind(this); + + this.$onChanges = (function () { + var hostname; + try { + hostname = new URL(this.uri).hostname; + this.url = 'https://icons.bitwarden.com/' + hostname + '/icon.png'; + } catch (e) { + // Invalid URL. + this.url = chrome.extension.getURL('images/fa-globe.png'); + } + }).bind(this); + } + }); diff --git a/src/popup/app/config.js b/src/popup/app/config.js index e834cdfa11a..611ffed5d04 100644 --- a/src/popup/app/config.js +++ b/src/popup/app/config.js @@ -1,7 +1,9 @@ angular .module('bit') - .config(function ($stateProvider, $urlRouterProvider, toastrConfig) { + .config(function ($stateProvider, $urlRouterProvider, $compileProvider, $sceDelegateProvider, toastrConfig) { + $compileProvider.imgSrcSanitizationWhitelist(/^\s*((https?|ftp|file|blob):|data:image\/|(moz|chrome|ms-browser)-extension)/); + angular.extend(toastrConfig, { closeButton: true, progressBar: true, @@ -256,9 +258,14 @@ }); }) .run(function ($rootScope, userService, $state, constantsService, stateService) { + chrome.storage.local.get(constantsService.disableFaviconKey, function(obj) { + stateService.saveState('faviconEnabled', !obj[constantsService.disableFaviconKey]); + }); + $rootScope.$on('$stateChangeStart', function (event, toState, toParams) { if ($state.current.name.indexOf('tabs.') > -1 && toState.name.indexOf('tabs.') > -1) { - stateService.purgeState(); + stateService.removeState('vault'); + stateService.removeState('viewFolder'); } if (!userService) { diff --git a/src/popup/app/current/views/current.html b/src/popup/app/current/views/current.html index 7ceb109557c..62d7e1900af 100644 --- a/src/popup/app/current/views/current.html +++ b/src/popup/app/current/views/current.html @@ -37,6 +37,7 @@ title="{{i18n.edit}} {{login.name}}"> + {{login.name}} diff --git a/src/popup/app/settings/settingsFeaturesController.js b/src/popup/app/settings/settingsFeaturesController.js index 6c739410228..8fb2b482b80 100644 --- a/src/popup/app/settings/settingsFeaturesController.js +++ b/src/popup/app/settings/settingsFeaturesController.js @@ -2,13 +2,14 @@ .module('bit.settings') .controller('settingsFeaturesController', function ($scope, i18nService, $analytics, constantsService, utilsService, - totpService, $timeout) { + totpService, stateService, $timeout) { $scope.i18n = i18nService; $scope.disableGa = false; $scope.disableAddLoginNotification = false; $scope.disableContextMenuItem = false; $scope.disableAutoTotpCopy = false; $scope.enableAutoFillOnPageLoad = false; + $scope.disableFavicon = false; chrome.storage.local.get(constantsService.enableAutoFillOnPageLoadKey, function (obj) { $timeout(function () { @@ -57,6 +58,12 @@ }); }); + chrome.storage.local.get(constantsService.disableFaviconKey, function (obj) { + $timeout(function () { + $scope.disableFavicon = obj && obj[constantsService.disableFaviconKey] === true; + }); + }); + $scope.updateGa = function () { chrome.storage.local.get(constantsService.disableGaKey, function (obj) { // Default for Firefox is disabled. @@ -176,4 +183,28 @@ }); }); }; + + $scope.updateDisableFavicon = function () { + chrome.storage.local.get(constantsService.disableFaviconKey, function (obj) { + if (obj[constantsService.disableFaviconKey]) { + // enable + obj[constantsService.disableFaviconKey] = false; + } + else { + // disable + $analytics.eventTrack('Disabled Favicon'); + obj[constantsService.disableFaviconKey] = true; + } + + chrome.storage.local.set(obj, function () { + $timeout(function () { + $scope.disableFavicon = obj[constantsService.disableFaviconKey]; + stateService.saveState('faviconEnabled', !$scope.disableFavicon); + }); + if (!obj[constantsService.disableFaviconKey]) { + $analytics.eventTrack('Enabled Favicon'); + } + }); + }); + }; }); diff --git a/src/popup/app/settings/views/settingsFeatures.html b/src/popup/app/settings/views/settingsFeatures.html index 4594fc60a62..18bc5c7a289 100644 --- a/src/popup/app/settings/views/settingsFeatures.html +++ b/src/popup/app/settings/views/settingsFeatures.html @@ -65,5 +65,17 @@ {{i18n.disableContextMenuItemDesc}} +
+
+
+ + +
+
+ +
diff --git a/src/popup/app/vault/views/vault.html b/src/popup/app/vault/views/vault.html index 6a9785b8a4e..d80a218c863 100644 --- a/src/popup/app/vault/views/vault.html +++ b/src/popup/app/vault/views/vault.html @@ -55,6 +55,7 @@ ng-class="{'disabled': !login.uri}">
+ {{login.name}} @@ -87,6 +88,7 @@ ng-class="{'disabled': !login.uri}"> + {{login.name}} diff --git a/src/popup/index.html b/src/popup/index.html index 53fc5d12b9b..bba0d921775 100644 --- a/src/popup/index.html +++ b/src/popup/index.html @@ -59,6 +59,9 @@ + + + diff --git a/src/popup/less/components.less b/src/popup/less/components.less index 3bd4eaf98d4..775f321dfdb 100644 --- a/src/popup/less/components.less +++ b/src/popup/less/components.less @@ -349,6 +349,20 @@ width: ~"calc(100% - 27px)"; } + .icon { + display: flex; + justify-content: center; + align-items: center; + float: left; + height: 36px; + width: 36px; + img { + border-radius: 3px; + max-height: 24px; + max-width: 24px; + } + } + .btn-list { cursor: pointer; float: right; diff --git a/src/services/constantsService.js b/src/services/constantsService.js index 4618609fa84..e8cfce30b36 100644 --- a/src/services/constantsService.js +++ b/src/services/constantsService.js @@ -4,6 +4,7 @@ function ConstantsService(i18nService) { disableGaKey: 'disableGa', disableAddLoginNotificationKey: 'disableAddLoginNotification', disableContextMenuItemKey: 'disableContextMenuItem', + disableFaviconKey: 'disableFavicon', disableAutoTotpCopyKey: 'disableAutoTotpCopy', enableAutoFillOnPageLoadKey: 'enableAutoFillOnPageLoad', lockOptionKey: 'lockOption',