1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-14 07:13:32 +00:00

sweet alert dialog implementation

This commit is contained in:
Kyle Spearrin
2018-04-10 14:20:03 -04:00
parent e4a50cbbb0
commit 98b852287d
12 changed files with 109 additions and 38 deletions

2
jslib

Submodule jslib updated: f8d8ca2253...fa5f6c0906

24
package-lock.json generated
View File

@@ -3637,6 +3637,12 @@
"event-emitter": "0.3.5" "event-emitter": "0.3.5"
} }
}, },
"es6-object-assign": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz",
"integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=",
"dev": true
},
"es6-promise": { "es6-promise": {
"version": "4.2.4", "version": "4.2.4",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz",
@@ -10945,6 +10951,12 @@
"integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
"dev": true "dev": true
}, },
"promise-polyfill": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-6.1.0.tgz",
"integrity": "sha1-36lpQ+qcEh/KTem1hoyznTRy4Fc=",
"dev": true
},
"proto-list": { "proto-list": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
@@ -13009,10 +13021,14 @@
} }
}, },
"sweetalert": { "sweetalert": {
"version": "1.1.3", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/sweetalert/-/sweetalert-1.1.3.tgz", "resolved": "https://registry.npmjs.org/sweetalert/-/sweetalert-2.1.0.tgz",
"integrity": "sha1-0sMepJKyK2qNiHrqFZiaI4/AhK4=", "integrity": "sha512-9YKj0SvjKyBfRWco50UOsIbXVeifYbxzT9Qda7EsqC01eafHGCSG0IR7g942ufjzt7lnwO8ZZBwr6emXv2fQrg==",
"dev": true "dev": true,
"requires": {
"es6-object-assign": "1.1.0",
"promise-polyfill": "6.1.0"
}
}, },
"symbol-observable": { "symbol-observable": {
"version": "1.0.1", "version": "1.0.1",

View File

@@ -79,7 +79,7 @@
"papaparse": "4.3.5", "papaparse": "4.3.5",
"sass-loader": "^6.0.6", "sass-loader": "^6.0.6",
"style-loader": "^0.19.0", "style-loader": "^0.19.0",
"sweetalert": "1.1.3", "sweetalert": "2.1.0",
"tldjs": "2.0.0", "tldjs": "2.0.0",
"ts-loader": "^3.5.0", "ts-loader": "^3.5.0",
"tslint": "^5.9.1", "tslint": "^5.9.1",

View File

@@ -115,9 +115,9 @@ export default class MainBackground {
constructor() { constructor() {
// Services // Services
this.utilsService = new UtilsService(); this.utilsService = new UtilsService();
this.platformUtilsService = new BrowserPlatformUtilsService(); this.messagingService = new BrowserMessagingService();
this.platformUtilsService = new BrowserPlatformUtilsService(this.messagingService);
const delayi18nLoad = this.platformUtilsService.isEdge() || this.platformUtilsService.isSafari() ? 1000 : 0; const delayi18nLoad = this.platformUtilsService.isEdge() || this.platformUtilsService.isSafari() ? 1000 : 0;
this.messagingService = new BrowserMessagingService(this.platformUtilsService);
this.storageService = new BrowserStorageService(this.platformUtilsService, false); this.storageService = new BrowserStorageService(this.platformUtilsService, false);
this.secureStorageService = new BrowserStorageService(this.platformUtilsService, true); this.secureStorageService = new BrowserStorageService(this.platformUtilsService, true);
this.i18nService = i18nService(this.platformUtilsService); this.i18nService = i18nService(this.platformUtilsService);
@@ -161,7 +161,8 @@ export default class MainBackground {
// Background // Background
this.runtimeBackground = new RuntimeBackground(this, this.autofillService, this.cipherService, this.runtimeBackground = new RuntimeBackground(this, this.autofillService, this.cipherService,
this.platformUtilsService, this.storageService, this.i18nService, this.analytics); this.platformUtilsService as BrowserPlatformUtilsService, this.storageService, this.i18nService,
this.analytics);
this.tabsBackground = new TabsBackground(this, this.platformUtilsService); this.tabsBackground = new TabsBackground(this, this.platformUtilsService);
this.commandsBackground = new CommandsBackground(this, this.passwordGenerationService, this.commandsBackground = new CommandsBackground(this, this.passwordGenerationService,
this.platformUtilsService, this.analytics); this.platformUtilsService, this.analytics);

View File

@@ -11,7 +11,6 @@ import { Analytics } from 'jslib/misc';
import { import {
CipherService, CipherService,
PlatformUtilsService,
StorageService, StorageService,
} from 'jslib/abstractions'; } from 'jslib/abstractions';
@@ -20,6 +19,7 @@ import { BrowserApi } from '../browser/browserApi';
import MainBackground from './main.background'; import MainBackground from './main.background';
import { AutofillService } from '../services/abstractions/autofill.service'; import { AutofillService } from '../services/abstractions/autofill.service';
import BrowserPlatformUtilsService from '../services/browserPlatformUtils.service';
export default class RuntimeBackground { export default class RuntimeBackground {
private runtime: any; private runtime: any;
@@ -29,7 +29,7 @@ export default class RuntimeBackground {
private onInstalledReason: string = null; private onInstalledReason: string = null;
constructor(private main: MainBackground, private autofillService: AutofillService, constructor(private main: MainBackground, private autofillService: AutofillService,
private cipherService: CipherService, private platformUtilsService: PlatformUtilsService, private cipherService: CipherService, private platformUtilsService: BrowserPlatformUtilsService,
private storageService: StorageService, private i18nService: any, private analytics: Analytics) { private storageService: StorageService, private i18nService: any, private analytics: Analytics) {
this.isSafari = this.platformUtilsService.isSafari(); this.isSafari = this.platformUtilsService.isSafari();
this.runtime = this.isSafari ? safari.application : chrome.runtime; this.runtime = this.isSafari ? safari.application : chrome.runtime;
@@ -90,6 +90,9 @@ export default class RuntimeBackground {
case 'openPopup': case 'openPopup':
await this.main.openPopup(); await this.main.openPopup();
break; break;
case 'showDialogResolve':
this.platformUtilsService.resolveDialogPromise(msg.dialogId, msg.confirmed);
break;
case 'bgGetDataForTab': case 'bgGetDataForTab':
await this.getDataForTab(sender.tab, msg.responseCommand); await this.getDataForTab(sender.tab, msg.responseCommand);
break; break;

View File

@@ -8,7 +8,7 @@ import { AuthService } from 'jslib/services/auth.service';
import BrowserMessagingService from '../../../services/browserMessaging.service'; import BrowserMessagingService from '../../../services/browserMessaging.service';
const messagingService = new BrowserMessagingService(backgroundServices.platformUtilsService()); const messagingService = new BrowserMessagingService();
const authService = new AuthService(backgroundServices.cryptoService(), backgroundServices.apiService(), const authService = new AuthService(backgroundServices.cryptoService(), backgroundServices.apiService(),
backgroundServices.userService(), backgroundServices.tokenService(), backgroundServices.appIdService(), backgroundServices.userService(), backgroundServices.tokenService(), backgroundServices.appIdService(),
backgroundServices.i18n2Service(), backgroundServices.platformUtilsService(), backgroundServices.i18n2Service(), backgroundServices.platformUtilsService(),

View File

@@ -3,6 +3,7 @@ import {
ToasterContainerComponent, ToasterContainerComponent,
} from 'angular2-toaster'; } from 'angular2-toaster';
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga'; import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
import swal from 'sweetalert';
import { import {
Component, Component,
@@ -23,6 +24,7 @@ import { BroadcasterService } from 'jslib/angular/services/broadcaster.service';
import { AuthService } from 'jslib/abstractions/auth.service'; import { AuthService } from 'jslib/abstractions/auth.service';
import { I18nService } from 'jslib/abstractions/i18n.service'; import { I18nService } from 'jslib/abstractions/i18n.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { StateService } from 'jslib/abstractions/state.service'; import { StateService } from 'jslib/abstractions/state.service';
import { StorageService } from 'jslib/abstractions/storage.service'; import { StorageService } from 'jslib/abstractions/storage.service';
@@ -57,7 +59,7 @@ export class AppComponent implements OnInit {
private toasterService: ToasterService, private storageService: StorageService, private toasterService: ToasterService, private storageService: StorageService,
private broadcasterService: BroadcasterService, private authService: AuthService, private broadcasterService: BroadcasterService, private authService: AuthService,
private i18nService: I18nService, private router: Router, private i18nService: I18nService, private router: Router,
private stateService: StateService) { } private stateService: StateService, private messagingService: MessagingService) { }
ngOnInit() { ngOnInit() {
window.onmousemove = () => this.recordActivity(); window.onmousemove = () => this.recordActivity();
@@ -67,7 +69,7 @@ export class AppComponent implements OnInit {
window.onscroll = () => this.recordActivity(); window.onscroll = () => this.recordActivity();
window.onkeypress = () => this.recordActivity(); window.onkeypress = () => this.recordActivity();
(window as any).bitwardenPopupMainMessageListener = (msg: any, sender: any, sendResponse: any) => { (window as any).bitwardenPopupMainMessageListener = async (msg: any, sender: any, sendResponse: any) => {
if (msg.command === 'doneLoggingOut') { if (msg.command === 'doneLoggingOut') {
this.authService.logOut(() => { this.authService.logOut(() => {
this.analytics.eventTrack.next({ action: 'Logged Out' }); this.analytics.eventTrack.next({ action: 'Logged Out' });
@@ -77,6 +79,22 @@ export class AppComponent implements OnInit {
} }
this.router.navigate(['home']); this.router.navigate(['home']);
}); });
} else if (msg.command === 'showDialog') {
const buttons = [msg.confirmText == null ? this.i18nService.t('ok') : msg.confirmText];
if (msg.cancelText != null) {
buttons.unshift(msg.cancelText);
}
const confirmed = await swal({
title: msg.title,
text: msg.text,
buttons: buttons,
});
this.messagingService.send('showDialogResolve', {
dialogId: msg.dialogId,
confirmed: confirmed,
});
} else { } else {
msg.webExtSender = sender; msg.webExtSender = sender;
this.broadcasterService.send(msg); this.broadcasterService.send(msg);

View File

@@ -51,7 +51,7 @@ function getBgService<T>(service: string) {
} }
export const stateService = new StateService(); export const stateService = new StateService();
export const messagingService = new BrowserMessagingService(getBgService<PlatformUtilsService>('platformUtilsService')()); export const messagingService = new BrowserMessagingService();
export const authService = new AuthService(getBgService<CryptoService>('cryptoService')(), export const authService = new AuthService(getBgService<CryptoService>('cryptoService')(),
getBgService<ApiService>('apiService')(), getBgService<UserService>('userService')(), getBgService<ApiService>('apiService')(), getBgService<UserService>('userService')(),
getBgService<TokenService>('tokenService')(), getBgService<AppIdService>('appIdService')(), getBgService<TokenService>('tokenService')(), getBgService<AppIdService>('appIdService')(),

View File

@@ -87,9 +87,12 @@ export class AddEditComponent extends BaseAddEditComponent implements OnInit {
this.location.back(); this.location.back();
} }
async generatePassword() { async generatePassword(): Promise<boolean> {
await super.generatePassword(); const confirmed = await super.generatePassword();
if (confirmed) {
this.stateService.save('addEditCipher', this.cipher); this.stateService.save('addEditCipher', this.cipher);
this.router.navigate(['generator']); this.router.navigate(['generator']);
} }
return confirmed;
}
} }

View File

@@ -1,18 +1,12 @@
import { BrowserApi } from '../browser/browserApi'; import { BrowserApi } from '../browser/browserApi';
import { import { MessagingService } from 'jslib/abstractions';
MessagingService,
PlatformUtilsService,
} from 'jslib/abstractions';
export default class BrowserMessagingService implements MessagingService { export default class BrowserMessagingService implements MessagingService {
constructor(private platformUtilsService: PlatformUtilsService) {
}
send(subscriber: string, arg: any = {}) { send(subscriber: string, arg: any = {}) {
const message = Object.assign({}, { command: subscriber }, arg); const message = Object.assign({}, { command: subscriber }, arg);
if (this.platformUtilsService.isSafari()) { if (BrowserApi.isSafariApi) {
const bgPage = BrowserApi.getBackgroundPage(); const bgPage = BrowserApi.getBackgroundPage();
bgPage.bitwardenMain.sendInternalRuntimeMessage(message); bgPage.bitwardenMain.sendInternalRuntimeMessage(message);

View File

@@ -48,7 +48,7 @@ describe('Browser Utils Service', () => {
value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36' value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'
}); });
const browserPlatformUtilsService = new BrowserPlatformUtilsService(); const browserPlatformUtilsService = new BrowserPlatformUtilsService(null);
expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.Chrome); expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.Chrome);
}); });
@@ -58,7 +58,7 @@ describe('Browser Utils Service', () => {
value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0' value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0'
}); });
const browserPlatformUtilsService = new BrowserPlatformUtilsService(); const browserPlatformUtilsService = new BrowserPlatformUtilsService(null);
expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.Firefox); expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.Firefox);
}); });
@@ -68,7 +68,7 @@ describe('Browser Utils Service', () => {
value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3175.3 Safari/537.36 OPR/49.0.2695.0 (Edition developer)' value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3175.3 Safari/537.36 OPR/49.0.2695.0 (Edition developer)'
}); });
const browserPlatformUtilsService = new BrowserPlatformUtilsService(); const browserPlatformUtilsService = new BrowserPlatformUtilsService(null);
expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.Opera); expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.Opera);
}); });
@@ -78,7 +78,7 @@ describe('Browser Utils Service', () => {
value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; ServiceUI 9) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063' value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; ServiceUI 9) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063'
}); });
const browserPlatformUtilsService = new BrowserPlatformUtilsService(); const browserPlatformUtilsService = new BrowserPlatformUtilsService(null);
expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.Edge); expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.Edge);
}); });
@@ -88,7 +88,7 @@ describe('Browser Utils Service', () => {
value: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/602.4.8 (KHTML, like Gecko) Version/10.0.3 Safari/602.4.8' value: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/602.4.8 (KHTML, like Gecko) Version/10.0.3 Safari/602.4.8'
}); });
const browserPlatformUtilsService = new BrowserPlatformUtilsService(); const browserPlatformUtilsService = new BrowserPlatformUtilsService(null);
expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.Safari); expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.Safari);
}); });
@@ -98,7 +98,7 @@ describe('Browser Utils Service', () => {
value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.97 Safari/537.36 Vivaldi/1.94.1008.40' value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.97 Safari/537.36 Vivaldi/1.94.1008.40'
}); });
const browserPlatformUtilsService = new BrowserPlatformUtilsService(); const browserPlatformUtilsService = new BrowserPlatformUtilsService(null);
expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.Vivaldi); expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.Vivaldi);
}); });
}); });

View File

@@ -2,11 +2,12 @@ import * as tldjs from 'tldjs';
import { BrowserApi } from '../browser/browserApi'; import { BrowserApi } from '../browser/browserApi';
import { DeviceType } from 'jslib/enums'; import { DeviceType } from 'jslib/enums/deviceType';
import { PlatformUtilsService } from 'jslib/abstractions'; import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { UtilsService } from 'jslib/services'; import { UtilsService } from 'jslib/services/utils.service';
const AnalyticsIds = { const AnalyticsIds = {
[DeviceType.Chrome]: 'UA-81915606-6', [DeviceType.Chrome]: 'UA-81915606-6',
@@ -17,6 +18,8 @@ const AnalyticsIds = {
[DeviceType.Safari]: 'UA-81915606-16', [DeviceType.Safari]: 'UA-81915606-16',
}; };
const DialogPromiseExpiration = 3600000; // 1 hour
export default class BrowserPlatformUtilsService implements PlatformUtilsService { export default class BrowserPlatformUtilsService implements PlatformUtilsService {
static getDomain(uriString: string): string { static getDomain(uriString: string): string {
if (uriString == null) { if (uriString == null) {
@@ -57,9 +60,12 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
identityClientId: string = 'browser'; identityClientId: string = 'browser';
private showDialogResolves = new Map<number, { resolve: (value: boolean) => void, date: Date }>();
private deviceCache: DeviceType = null; private deviceCache: DeviceType = null;
private analyticsIdCache: string = null; private analyticsIdCache: string = null;
constructor(private messagingService: MessagingService) { }
getDevice(): DeviceType { getDevice(): DeviceType {
if (this.deviceCache) { if (this.deviceCache) {
return this.deviceCache; return this.deviceCache;
@@ -169,8 +175,18 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
} }
showDialog(text: string, title?: string, confirmText?: string, cancelText?: string, type?: string) { showDialog(text: string, title?: string, confirmText?: string, cancelText?: string, type?: string) {
// TODO const dialogId = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
return Promise.resolve(true); this.messagingService.send('showDialog', {
text: text,
title: title,
confirmText: confirmText,
cancelText: cancelText,
type: type,
dialogId: dialogId,
});
return new Promise<boolean>((resolve) => {
this.showDialogResolves.set(dialogId, { resolve: resolve, date: new Date() });
});
} }
isDev(): boolean { isDev(): boolean {
@@ -183,6 +199,26 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
UtilsService.copyToClipboard(text, doc); UtilsService.copyToClipboard(text, doc);
} }
resolveDialogPromise(dialogId: number, confirmed: boolean) {
if (this.showDialogResolves.has(dialogId)) {
const resolveObj = this.showDialogResolves.get(dialogId);
resolveObj.resolve(confirmed);
this.showDialogResolves.delete(dialogId);
}
// Clean up old promises
const deleteIds: number[] = [];
this.showDialogResolves.forEach((val, key) => {
const age = new Date().getTime() - val.date.getTime();
if (age > DialogPromiseExpiration) {
deleteIds.push(key);
}
});
deleteIds.forEach((id) => {
this.showDialogResolves.delete(id);
});
}
private sidebarViewName(): string { private sidebarViewName(): string {
if ((window as any).chrome.sidebarAction && this.isFirefox()) { if ((window as any).chrome.sidebarAction && this.isFirefox()) {
return 'sidebar'; return 'sidebar';