1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 16:23:44 +00:00

[macOS] Don't enable secure input when app is not in focus (#970)

* Don't engage macOS secure input if not focused

* Refactor to use focusInputOnPageLoad

* Fix style and linting

* Refactor to remove focusOnPageLoad

* Update jslib
This commit is contained in:
Thomas Rittson
2021-07-05 08:06:24 +10:00
committed by GitHub
parent 6d8fbf1e43
commit 3aa171a664
5 changed files with 49 additions and 4 deletions

2
jslib

Submodule jslib updated: f568c87289...6f6b5a5503

View File

@@ -8,12 +8,12 @@
<div class="row-main" *ngIf="pinLock"> <div class="row-main" *ngIf="pinLock">
<label for="pin">{{'pin' | i18n}}</label> <label for="pin">{{'pin' | i18n}}</label>
<input id="pin" type="{{showPassword ? 'text' : 'password'}}" name="PIN" class="monospaced" <input id="pin" type="{{showPassword ? 'text' : 'password'}}" name="PIN" class="monospaced"
[(ngModel)]="pin" required appAutofocus> [(ngModel)]="pin" required>
</div> </div>
<div class="row-main" *ngIf="!pinLock"> <div class="row-main" *ngIf="!pinLock">
<label for="masterPassword">{{'masterPass' | i18n}}</label> <label for="masterPassword">{{'masterPass' | i18n}}</label>
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}" name="MasterPassword" <input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}" name="MasterPassword"
class="monospaced" [(ngModel)]="masterPassword" required appAutofocus> class="monospaced" [(ngModel)]="masterPassword" required>
</div> </div>
<div class="action-buttons"> <div class="action-buttons">
<a class="row-btn" href="#" appStopClick appBlurClick role="button" <a class="row-btn" href="#" appStopClick appBlurClick role="button"

View File

@@ -33,6 +33,8 @@ const BroadcasterSubscriptionId = 'LockComponent';
templateUrl: 'lock.component.html', templateUrl: 'lock.component.html',
}) })
export class LockComponent extends BaseLockComponent implements OnDestroy { export class LockComponent extends BaseLockComponent implements OnDestroy {
private deferFocus: boolean = null;
constructor(router: Router, i18nService: I18nService, constructor(router: Router, i18nService: I18nService,
platformUtilsService: PlatformUtilsService, messagingService: MessagingService, platformUtilsService: PlatformUtilsService, messagingService: MessagingService,
userService: UserService, cryptoService: CryptoService, userService: UserService, cryptoService: CryptoService,
@@ -63,10 +65,22 @@ export class LockComponent extends BaseLockComponent implements OnDestroy {
case 'windowHidden': case 'windowHidden':
this.onWindowHidden(); this.onWindowHidden();
break; break;
case 'windowIsFocused':
if (this.deferFocus === null) {
this.deferFocus = !message.windowIsFocused;
if (!this.deferFocus) {
this.focusInput();
}
} else if (this.deferFocus && message.windowIsFocused) {
this.focusInput();
this.deferFocus = false;
}
break;
default: default:
} }
}); });
}); });
this.messagingService.send('getWindowIsFocused');
} }
ngOnDestroy() { ngOnDestroy() {
@@ -76,4 +90,8 @@ export class LockComponent extends BaseLockComponent implements OnDestroy {
onWindowHidden() { onWindowHidden() {
this.showPassword = false; this.showPassword = false;
} }
private focusInput() {
document.getElementById(this.pinLock ? 'pin' : 'masterPassword').focus();
}
} }

View File

@@ -15,6 +15,7 @@ import { AuthService } from 'jslib-common/abstractions/auth.service';
import { CryptoFunctionService } from 'jslib-common/abstractions/cryptoFunction.service'; import { CryptoFunctionService } from 'jslib-common/abstractions/cryptoFunction.service';
import { EnvironmentService } from 'jslib-common/abstractions/environment.service'; import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service'; import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { StateService } from 'jslib-common/abstractions/state.service'; import { StateService } from 'jslib-common/abstractions/state.service';
@@ -37,12 +38,15 @@ export class LoginComponent extends BaseLoginComponent implements OnDestroy {
showingModal = false; showingModal = false;
private deferFocus: boolean = null;
constructor(authService: AuthService, router: Router, i18nService: I18nService, constructor(authService: AuthService, router: Router, i18nService: I18nService,
syncService: SyncService, private componentFactoryResolver: ComponentFactoryResolver, syncService: SyncService, private componentFactoryResolver: ComponentFactoryResolver,
platformUtilsService: PlatformUtilsService, stateService: StateService, platformUtilsService: PlatformUtilsService, stateService: StateService,
environmentService: EnvironmentService, passwordGenerationService: PasswordGenerationService, environmentService: EnvironmentService, passwordGenerationService: PasswordGenerationService,
cryptoFunctionService: CryptoFunctionService, storageService: StorageService, cryptoFunctionService: CryptoFunctionService, storageService: StorageService,
private broadcasterService: BroadcasterService, private ngZone: NgZone) { private broadcasterService: BroadcasterService, private ngZone: NgZone,
private messagingService: MessagingService) {
super(authService, router, platformUtilsService, i18nService, stateService, environmentService, super(authService, router, platformUtilsService, i18nService, stateService, environmentService,
passwordGenerationService, cryptoFunctionService, storageService); passwordGenerationService, cryptoFunctionService, storageService);
super.onSuccessfulLogin = () => { super.onSuccessfulLogin = () => {
@@ -58,10 +62,22 @@ export class LoginComponent extends BaseLoginComponent implements OnDestroy {
case 'windowHidden': case 'windowHidden':
this.onWindowHidden(); this.onWindowHidden();
break; break;
case 'windowIsFocused':
if (this.deferFocus === null) {
this.deferFocus = !message.windowIsFocused;
if (!this.deferFocus) {
this.focusInput();
}
} else if (this.deferFocus && message.windowIsFocused) {
this.focusInput();
this.deferFocus = false;
}
break;
default: default:
} }
}); });
}); });
this.messagingService.send('getWindowIsFocused');
} }
ngOnDestroy() { ngOnDestroy() {

View File

@@ -60,6 +60,9 @@ export class MessagingMain {
case 'setFocus': case 'setFocus':
this.setFocus(); this.setFocus();
break; break;
case 'getWindowIsFocused':
this.windowIsFocused();
break;
case 'enableBrowserIntegration': case 'enableBrowserIntegration':
this.main.nativeMessagingMain.generateManifests(); this.main.nativeMessagingMain.generateManifests();
this.main.nativeMessagingMain.listen(); this.main.nativeMessagingMain.listen();
@@ -139,4 +142,12 @@ Terminal=false`;
this.main.trayMain.restoreFromTray(); this.main.trayMain.restoreFromTray();
this.main.windowMain.win.focusOnWebView(); this.main.windowMain.win.focusOnWebView();
} }
private windowIsFocused() {
const windowIsFocused = this.main.windowMain.win.isFocused();
this.main.windowMain.win.webContents.send('messagingService', {
command: 'windowIsFocused',
windowIsFocused: windowIsFocused,
});
}
} }