1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-12-25 16:59:17 +01:00

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.
This commit is contained in:
Oscar Hinton 2017-10-12 20:48:29 +02:00 committed by Kyle Spearrin
parent 5a6c43e46e
commit a99ce875ca
13 changed files with 109 additions and 3 deletions

View File

@ -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."
}
}

BIN
src/images/fa-globe.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 729 B

View File

@ -7,6 +7,7 @@
'angulartics.google.analytics',
'bit.directives',
'bit.components',
'bit.services',
'bit.global',

View File

@ -0,0 +1,2 @@
angular
.module('bit.components', []);

View File

@ -0,0 +1,26 @@
angular
.module('bit.components')
.component('icon', {
bindings: {
uri: '<'
},
template: '<div class="icon" ng-if="$ctrl.enabled()"><img src="{{$ctrl.url}}"></div>',
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);
}
});

View File

@ -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) {

View File

@ -37,6 +37,7 @@
title="{{i18n.edit}} {{login.name}}">
<i class="fa fa-lg fa-pencil"></i>
</span>
<icon uri="login.uri"></icon>
<span class="text">
{{login.name}}
<i class="fa fa-share-alt text-muted" ng-if="login.organizationId" title="{{i18n.shared}}"></i>

View File

@ -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');
}
});
});
};
});

View File

@ -65,5 +65,17 @@
{{i18n.disableContextMenuItemDesc}}
</div>
</div>
<div class="list-section">
<div class="list-section-items">
<div class="list-section-item list-section-item-checkbox">
<label for="context-menu">{{i18n.disableFavicon}}</label>
<input id="context-menu" type="checkbox" ng-model="disableFavicon"
ng-change="updateDisableFavicon()">
</div>
</div>
<div class="list-section-footer">
{{i18n.disableFaviconDesc}}
</div>
</div>
</div>
</div>

View File

@ -55,6 +55,7 @@
ng-class="{'disabled': !login.uri}">
<i class="fa fa-lg fa-share-square-o"></i>
</span>
<icon uri="login.uri"></icon>
<span class="text">
{{login.name}}
<i class="fa fa-share-alt text-muted" ng-if="login.organizationId" title="{{i18n.shared}}"></i>
@ -87,6 +88,7 @@
ng-class="{'disabled': !login.uri}">
<i class="fa fa-lg fa-share-square-o"></i>
</span>
<icon uri="login.uri"></icon>
<span class="text">
{{login.name}}
<i class="fa fa-share-alt text-muted" ng-if="login.organizationId" title="{{i18n.shared}}"></i>

View File

@ -59,6 +59,9 @@
<script src="app/directives/stopClickDirective.js"></script>
<script src="app/directives/stopPropDirective.js"></script>
<script src="app/components/componentsModule.js"></script>
<script src="app/components/iconComponent.js"></script>
<script src="app/services/servicesModule.js"></script>
<script src="app/services/backgroundService.js"></script>
<script src="app/services/authService.js"></script>

View File

@ -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;

View File

@ -4,6 +4,7 @@ function ConstantsService(i18nService) {
disableGaKey: 'disableGa',
disableAddLoginNotificationKey: 'disableAddLoginNotification',
disableContextMenuItemKey: 'disableContextMenuItem',
disableFaviconKey: 'disableFavicon',
disableAutoTotpCopyKey: 'disableAutoTotpCopy',
enableAutoFillOnPageLoadKey: 'enableAutoFillOnPageLoad',
lockOptionKey: 'lockOption',