bitwarden-estensione-browser/src/popup/app.component.ts

270 lines
10 KiB
TypeScript
Raw Normal View History

2018-04-14 04:08:24 +02:00
import { BrowserApi } from '../browser/browserApi';
2018-04-04 04:14:54 +02:00
import {
2018-10-03 05:33:56 +02:00
BodyOutputType,
Toast,
2018-04-04 04:14:54 +02:00
ToasterConfig,
ToasterContainerComponent,
2018-10-03 05:33:56 +02:00
ToasterService,
2018-04-04 04:14:54 +02:00
} from 'angular2-toaster';
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
2018-04-10 20:20:03 +02:00
import swal from 'sweetalert';
2018-04-04 04:14:54 +02:00
import {
2018-04-10 23:14:10 +02:00
ChangeDetectorRef,
2018-04-04 04:14:54 +02:00
Component,
2018-04-10 23:14:10 +02:00
NgZone,
2018-04-04 04:14:54 +02:00
OnInit,
2018-10-03 05:33:56 +02:00
SecurityContext,
2018-04-04 04:14:54 +02:00
} from '@angular/core';
2018-10-03 05:33:56 +02:00
import { DomSanitizer } from '@angular/platform-browser';
2018-04-09 15:51:22 +02:00
import {
2018-04-09 20:17:58 +02:00
NavigationEnd,
2018-04-09 15:51:22 +02:00
Router,
RouterOutlet,
} from '@angular/router';
2018-04-04 04:14:54 +02:00
import { Angulartics2 } from 'angulartics2';
2018-04-06 21:33:20 +02:00
import { BroadcasterService } from 'jslib/angular/services/broadcaster.service';
import { AuthService } from 'jslib/abstractions/auth.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
2018-04-10 20:20:03 +02:00
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
2018-04-09 20:17:58 +02:00
import { StateService } from 'jslib/abstractions/state.service';
2018-04-06 21:33:20 +02:00
import { StorageService } from 'jslib/abstractions/storage.service';
import { ConstantsService } from 'jslib/services/constants.service';
2018-04-08 06:30:04 +02:00
import { routerTransition } from './app-routing.animations';
2018-04-04 04:14:54 +02:00
@Component({
selector: 'app-root',
styles: [],
2018-04-08 06:30:04 +02:00
animations: [routerTransition],
2018-04-04 04:14:54 +02:00
template: `
<toaster-container [toasterconfig]="toasterConfig"></toaster-container>
2018-04-08 06:30:04 +02:00
<main [@routerTransition]="getState(o)">
<router-outlet #o="outlet"></router-outlet>
</main>`,
2018-04-04 04:14:54 +02:00
})
2018-04-06 21:33:20 +02:00
export class AppComponent implements OnInit {
2018-04-04 04:14:54 +02:00
toasterConfig: ToasterConfig = new ToasterConfig({
2018-04-10 04:53:46 +02:00
showCloseButton: false,
2018-04-04 04:14:54 +02:00
mouseoverTimerStop: true,
animation: 'slideUp',
limit: 2,
positionClass: 'toast-bottom-full-width',
2018-04-11 05:49:46 +02:00
newestOnTop: false,
2018-04-04 04:14:54 +02:00
});
2018-04-06 21:33:20 +02:00
private lastActivity: number = null;
2018-04-04 04:14:54 +02:00
constructor(private angulartics2GoogleAnalytics: Angulartics2GoogleAnalytics, private analytics: Angulartics2,
2018-04-06 21:33:20 +02:00
private toasterService: ToasterService, private storageService: StorageService,
private broadcasterService: BroadcasterService, private authService: AuthService,
2018-04-09 20:17:58 +02:00
private i18nService: I18nService, private router: Router,
2018-04-10 23:14:10 +02:00
private stateService: StateService, private messagingService: MessagingService,
2018-10-03 05:33:56 +02:00
private changeDetectorRef: ChangeDetectorRef, private ngZone: NgZone,
private sanitizer: DomSanitizer, private platformUtilsService: PlatformUtilsService) { }
2018-04-06 21:33:20 +02:00
ngOnInit() {
2018-04-14 04:08:24 +02:00
if (BrowserApi.getBackgroundPage() == null) {
return;
}
2018-04-12 20:24:42 +02:00
this.ngZone.runOutsideAngular(() => {
window.onmousemove = () => this.recordActivity();
window.onmousedown = () => this.recordActivity();
window.ontouchstart = () => this.recordActivity();
window.onclick = () => this.recordActivity();
window.onscroll = () => this.recordActivity();
window.onkeypress = () => this.recordActivity();
});
2018-04-06 21:33:20 +02:00
2018-04-10 20:20:03 +02:00
(window as any).bitwardenPopupMainMessageListener = async (msg: any, sender: any, sendResponse: any) => {
2018-04-06 21:33:20 +02:00
if (msg.command === 'doneLoggingOut') {
2018-04-10 23:14:10 +02:00
this.ngZone.run(async () => {
this.authService.logOut(() => {
this.analytics.eventTrack.next({ action: 'Logged Out' });
if (msg.expired) {
2018-10-03 05:33:56 +02:00
this.showToast({
type: 'warning',
title: this.i18nService.t('loggedOut'),
text: this.i18nService.t('loginExpired'),
});
2018-04-10 23:14:10 +02:00
}
this.router.navigate(['home']);
2018-04-12 21:56:27 +02:00
this.stateService.purge();
2018-04-10 23:14:10 +02:00
});
this.changeDetectorRef.detectChanges();
2018-04-06 21:33:20 +02:00
});
2019-04-18 16:11:01 +02:00
} else if (msg.command === 'authBlocked') {
this.ngZone.run(() => {
this.router.navigate(['home']);
});
2018-04-12 21:56:27 +02:00
} else if (msg.command === 'locked') {
this.stateService.purge();
this.ngZone.run(() => {
this.router.navigate(['lock']);
});
2018-04-10 20:20:03 +02:00
} else if (msg.command === 'showDialog') {
2018-04-13 05:18:51 +02:00
await this.showDialog(msg);
2018-10-03 05:33:56 +02:00
} else if (msg.command === 'showToast') {
2018-10-03 15:51:14 +02:00
this.ngZone.run(() => {
this.showToast(msg);
2018-10-03 05:33:56 +02:00
});
} else if (msg.command === 'analyticsEventTrack') {
this.analytics.eventTrack.next({
action: msg.action,
properties: { label: msg.label },
});
2019-02-25 22:19:19 +01:00
} else if (msg.command === 'reloadProcess') {
const windowReload = this.platformUtilsService.isSafari() ||
this.platformUtilsService.isFirefox() || this.platformUtilsService.isOpera();
if (windowReload) {
// Wait to make sure background has reloaded first.
window.setTimeout(() => BrowserApi.reloadExtension(window), 2000);
}
} else if (msg.command === 'reloadPopup') {
this.router.navigate(['/']);
2019-03-05 21:05:04 +01:00
} else {
2018-04-06 21:33:20 +02:00
msg.webExtSender = sender;
this.broadcasterService.send(msg);
}
};
BrowserApi.messageListener('app.component', (window as any).bitwardenPopupMainMessageListener);
2018-04-09 20:17:58 +02:00
2018-04-11 05:49:46 +02:00
this.router.events.subscribe((event) => {
2018-04-09 20:17:58 +02:00
if (event instanceof NavigationEnd) {
const url = event.urlAfterRedirects || event.url || '';
if (url.startsWith('/tabs/') && (window as any).previousPopupUrl != null &&
(window as any).previousPopupUrl.startsWith('/tabs/')) {
2018-04-09 20:17:58 +02:00
this.stateService.remove('GroupingsComponent');
this.stateService.remove('CiphersComponent');
}
2018-04-09 23:35:16 +02:00
if (url.startsWith('/tabs/')) {
this.stateService.remove('addEditCipherInfo');
2018-04-09 23:35:16 +02:00
}
(window as any).previousPopupUrl = url;
// Clear route direction after animation (400ms)
if ((window as any).routeDirection != null) {
window.setTimeout(() => {
(window as any).routeDirection = null;
}, 400);
}
2018-04-09 20:17:58 +02:00
}
});
2018-04-06 21:33:20 +02:00
}
2018-04-09 15:51:22 +02:00
getState(outlet: RouterOutlet) {
if (BrowserApi.isEdge18) {
return null;
} else if (outlet.activatedRouteData.state === 'ciphers') {
const routeDirection = (window as any).routeDirection != null ? (window as any).routeDirection : '';
return 'ciphers_direction=' + routeDirection + '_' +
(outlet.activatedRoute.queryParams as any).value.folderId + '_' +
(outlet.activatedRoute.queryParams as any).value.collectionId;
} else {
return outlet.activatedRouteData.state;
}
2018-04-08 06:30:04 +02:00
}
2018-04-06 21:33:20 +02:00
private async recordActivity() {
const now = (new Date()).getTime();
if (this.lastActivity != null && now - this.lastActivity < 250) {
return;
}
this.lastActivity = now;
this.storageService.save(ConstantsService.lastActiveKey, now);
}
2018-04-13 05:18:51 +02:00
2018-10-03 15:51:14 +02:00
private showToast(msg: any) {
2018-10-03 05:33:56 +02:00
const toast: Toast = {
type: msg.type,
title: msg.title,
};
if (typeof (msg.text) === 'string') {
toast.body = msg.text;
} else if (msg.text.length === 1) {
toast.body = msg.text[0];
} else {
let message = '';
msg.text.forEach((t: string) =>
message += ('<p>' + this.sanitizer.sanitize(SecurityContext.HTML, t) + '</p>'));
toast.body = message;
toast.bodyOutputType = BodyOutputType.TrustedHtml;
}
if (msg.options != null) {
if (msg.options.trustedHtml === true) {
toast.bodyOutputType = BodyOutputType.TrustedHtml;
}
if (msg.options.timeout != null && msg.options.timeout > 0) {
toast.timeout = msg.options.timeout;
}
}
this.toasterService.popAsync(toast);
}
2018-04-13 05:18:51 +02:00
private async showDialog(msg: any) {
const buttons = [msg.confirmText == null ? this.i18nService.t('ok') : msg.confirmText];
if (msg.cancelText != null) {
buttons.unshift(msg.cancelText);
}
const contentDiv = document.createElement('div');
if (msg.type != null) {
const icon = document.createElement('i');
icon.classList.add('swal-custom-icon');
switch (msg.type) {
case 'success':
icon.classList.add('fa', 'fa-check', 'text-success');
break;
case 'warning':
icon.classList.add('fa', 'fa-warning', 'text-warning');
break;
case 'error':
icon.classList.add('fa', 'fa-bolt', 'text-danger');
break;
case 'info':
icon.classList.add('fa', 'fa-info-circle', 'text-info');
break;
default:
break;
}
if (icon.classList.contains('fa')) {
contentDiv.appendChild(icon);
}
}
if (msg.title != null) {
const titleDiv = document.createElement('div');
titleDiv.classList.add('swal-title');
titleDiv.appendChild(document.createTextNode(msg.title));
contentDiv.appendChild(titleDiv);
}
if (msg.text != null) {
const textDiv = document.createElement('div');
textDiv.classList.add('swal-text');
textDiv.appendChild(document.createTextNode(msg.text));
contentDiv.appendChild(textDiv);
}
const confirmed = await swal({
content: { element: contentDiv },
buttons: buttons,
2018-04-14 15:39:47 +02:00
timer: 300000, // 5 minute timeout
2018-04-13 05:18:51 +02:00
});
this.messagingService.send('showDialogResolve', {
dialogId: msg.dialogId,
confirmed: confirmed,
});
}
2018-04-04 04:14:54 +02:00
}