1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-20 10:13:31 +00:00

Merge branch 'master' into feature-aopl-options

This commit is contained in:
Thomas Rittson
2021-05-14 10:55:14 +10:00
106 changed files with 10337 additions and 10121 deletions

View File

@@ -20,6 +20,7 @@ import {
} from 'jslib/abstractions';
import { EventService } from 'jslib/abstractions/event.service';
import { CipherRepromptType } from 'jslib/enums/cipherRepromptType';
import { EventType } from 'jslib/enums/eventType';
const CardAttributes: string[] = ['autoCompleteType', 'data-stripe', 'htmlName', 'htmlID', 'label-tag',
@@ -258,10 +259,17 @@ export default class AutofillService implements AutofillServiceInterface {
}
}
if (cipher.reprompt !== CipherRepromptType.None) {
return;
}
const copyTotpOnAutoFill = await this.totpService.isAutoCopyOnAutoFillEnabled();
const shouldCopyTotp = fromCommand || copyTotpOnAutoFill;
const totpCode = await this.doAutoFill({
cipher: cipher,
pageDetails: pageDetails,
skipTotp: !fromCommand,
skipTotp: !shouldCopyTotp,
skipLastUsed: !fromCommand,
skipUsernameOnlyFill: !fromCommand,
onlyEmptyFields: !fromCommand,

View File

@@ -6,16 +6,14 @@ import { DeviceType } from 'jslib/enums/deviceType';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { AnalyticsIds } from 'jslib/misc/analytics';
const DialogPromiseExpiration = 600000; // 10 minutes
export default class BrowserPlatformUtilsService implements PlatformUtilsService {
identityClientId: string = 'browser';
private showDialogResolves = new Map<number, { resolve: (value: boolean) => void, date: Date }>();
private passwordDialogResolves = new Map<number, { tryResolve: (canceled: boolean, password: string) => Promise<boolean>, date: Date }>();
private deviceCache: DeviceType = null;
private analyticsIdCache: string = null;
private prefersColorSchemeDark = window.matchMedia('(prefers-color-scheme: dark)');
constructor(private messagingService: MessagingService,
@@ -82,15 +80,6 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
return false;
}
analyticsId(): string {
if (this.analyticsIdCache) {
return this.analyticsIdCache;
}
this.analyticsIdCache = (AnalyticsIds as any)[this.getDevice()];
return this.analyticsIdCache;
}
async isViewOpen(): Promise<boolean> {
if (await BrowserApi.isPopupOpen()) {
return true;
@@ -122,16 +111,12 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
BrowserApi.downloadFile(win, blobData, blobOptions, fileName);
}
getApplicationVersion(): string {
return BrowserApi.getApplicationVersion();
getApplicationVersion(): Promise<string> {
return Promise.resolve(BrowserApi.getApplicationVersion());
}
supportsU2f(win: Window): boolean {
if (win != null && (win as any).u2f != null) {
return true;
}
return this.isChrome() || this.isOpera() || this.isVivaldi() || this.isEdge();
supportsWebAuthn(win: Window): boolean {
return (typeof(PublicKeyCredential) !== 'undefined');
}
supportsDuo(): boolean {
@@ -165,11 +150,30 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
});
}
eventTrack(action: string, label?: string, options?: any) {
this.messagingService.send('analyticsEventTrack', {
action: action,
label: label,
options: options,
async showPasswordDialog(title: string, body: string, passwordValidation: (value: string) => Promise<boolean>) {
const dialogId = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
this.messagingService.send('showPasswordDialog', {
title: title,
body: body,
dialogId: dialogId,
});
return new Promise<boolean>(resolve => {
this.passwordDialogResolves.set(dialogId, {
tryResolve: async (canceled: boolean, password: string) => {
if (canceled) {
resolve(false);
return false;
}
if (await passwordValidation(password)) {
resolve(true);
return true;
}
},
date: new Date(),
});
});
}
@@ -280,21 +284,41 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
}
// 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);
this.showDialogResolves.delete(key);
}
});
deleteIds.forEach(id => {
this.showDialogResolves.delete(id);
});
}
async resolvePasswordDialogPromise(dialogId: number, canceled: boolean, password: string): Promise<boolean> {
let result = false;
if (this.passwordDialogResolves.has(dialogId)) {
const resolveObj = this.passwordDialogResolves.get(dialogId);
if (await resolveObj.tryResolve(canceled, password)) {
this.passwordDialogResolves.delete(dialogId);
result = true;
}
}
// Clean up old promises
this.passwordDialogResolves.forEach((val, key) => {
const age = new Date().getTime() - val.date.getTime();
if (age > DialogPromiseExpiration) {
this.passwordDialogResolves.delete(key);
}
});
return result;
}
async supportsBiometric() {
const isUnsuportedFirefox = this.isFirefox() && parseInt((await browser.runtime.getBrowserInfo()).version.split('.')[0], 10) < 87;
return !isUnsuportedFirefox && !this.isSafari();
if (this.isFirefox()) {
return parseInt((await browser.runtime.getBrowserInfo()).version.split('.')[0], 10) >= 87;
}
return true;
}
authenticateBiometric() {
@@ -315,8 +339,8 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
return false;
}
getDefaultSystemTheme() {
return this.prefersColorSchemeDark.matches ? 'dark' : 'light';
getDefaultSystemTheme(): Promise<'light' | 'dark'> {
return Promise.resolve(this.prefersColorSchemeDark.matches ? 'dark' : 'light');
}
onDefaultSystemThemeChange(callback: ((theme: 'light' | 'dark') => unknown)) {

View File

@@ -22,7 +22,7 @@ export default class BrowserStorageService implements StorageService {
async save(key: string, obj: any): Promise<any> {
if (obj == null) {
// Fix safari not liking null in set
return new Promise(resolve => {
return new Promise<void>(resolve => {
this.chromeStorageApi.remove(key, () => {
resolve();
});
@@ -30,7 +30,7 @@ export default class BrowserStorageService implements StorageService {
}
const keyedObj = { [key]: obj };
return new Promise(resolve => {
return new Promise<void>(resolve => {
this.chromeStorageApi.set(keyedObj, () => {
resolve();
});
@@ -38,7 +38,7 @@ export default class BrowserStorageService implements StorageService {
}
async remove(key: string): Promise<any> {
return new Promise(resolve => {
return new Promise<void>(resolve => {
this.chromeStorageApi.remove(key, () => {
resolve();
});

View File

@@ -9,8 +9,8 @@ export default class I18nService extends BaseI18nService {
});
this.supportedTranslationLocales = [
'en', 'be', 'bg', 'ca', 'cs', 'da', 'de', 'el', 'en-GB', 'es', 'et', 'fa', 'fi', 'fr', 'he', 'hr', 'hu',
'id', 'it', 'ja', 'ko', 'nb', 'nl', 'pl', 'pt-BR', 'pt-PT', 'ro', 'ru', 'sk', 'sr', 'sv', 'th', 'tr', 'uk',
'en', 'be', 'bg', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'en-GB', 'en-IN', 'es', 'et', 'fa', 'fi', 'fr', 'he', 'hr', 'hu',
'id', 'it', 'ja', 'ko', 'lv', 'ml-IN', 'nb', 'nl', 'pl', 'pt-BR', 'pt-PT', 'ro', 'ru', 'sk', 'sr', 'sv', 'th', 'tr', 'uk',
'vi', 'zh-CN', 'zh-TW',
];
}