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:
@@ -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,
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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',
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user