Skip to content

Commit

Permalink
android: hide window contents in app switcher when screen lock is active
Browse files Browse the repository at this point in the history
When the screen lock setting is active, we want to also hide the
window contents in the app switcher, otherwise the contents can be
seen there circumventing the screen lock.

Downside: the same setting also disables screenshots. This is why we
only enable it when screen lock is enabled, and not always.
  • Loading branch information
benma committed Nov 30, 2023
1 parent 240c6a9 commit feff560
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 20 deletions.
6 changes: 6 additions & 0 deletions backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,11 @@ type Environment interface {
SetDarkTheme(bool)
// DetectDarkTheme returns true if the dark theme is enabled at OS level.
DetectDarkTheme() bool
// Auth requests the native environment to trigger authentication.
Auth()
// OnAuthSettingChanged is called when the authentication (screen lock) setting is changed.
// This is also called when the app launches with the current setting.
OnAuthSettingChanged(enabled bool)
}

// Backend ties everything together and is the main starting point to use the BitBox wallet library.
Expand Down Expand Up @@ -572,6 +576,8 @@ func (backend *Backend) Start() <-chan interface{} {

backend.ratesUpdater.StartCurrentRates()
backend.configureHistoryExchangeRates()

backend.environment.OnAuthSettingChanged(backend.config.AppConfig().Backend.Authentication)
return backend.events
}

Expand Down
34 changes: 22 additions & 12 deletions backend/bridgecommon/bridgecommon.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,12 @@ type BackendEnvironment struct {
UsingMobileDataFunc func() bool
// NativeLocaleFunc is used by the backend to query native app layer for user
// preferred UI language.
NativeLocaleFunc func() string
GetSaveFilenameFunc func(string) string
SetDarkThemeFunc func(bool)
DetectDarkThemeFunc func() bool
AuthFunc func()
NativeLocaleFunc func() string
GetSaveFilenameFunc func(string) string
SetDarkThemeFunc func(bool)
DetectDarkThemeFunc func() bool
AuthFunc func()
OnAuthSettingChangedFunc func(bool)
}

// NotifyUser implements backend.Environment.
Expand All @@ -188,13 +189,6 @@ func (env *BackendEnvironment) NotifyUser(text string) {
}
}

// Auth implements backend.Environment.
func (env *BackendEnvironment) Auth() {
if env.AuthFunc != nil {
env.AuthFunc()
}
}

// DeviceInfos implements backend.Environment.
func (env *BackendEnvironment) DeviceInfos() []usb.DeviceInfo {
if env.DeviceInfosFunc != nil {
Expand Down Expand Up @@ -235,19 +229,35 @@ func (env *BackendEnvironment) GetSaveFilename(suggestedFilename string) string
return ""
}

// SetDarkTheme implements backend.Environment.
func (env *BackendEnvironment) SetDarkTheme(isDark bool) {
if env.SetDarkThemeFunc != nil {
env.SetDarkThemeFunc(isDark)
}
}

// DetectDarkTheme implements backend.Environment.
func (env *BackendEnvironment) DetectDarkTheme() bool {
if env.DetectDarkThemeFunc != nil {
return env.DetectDarkThemeFunc()
}
return false
}

// Auth implements backend.Environment.
func (env *BackendEnvironment) Auth() {
if env.AuthFunc != nil {
env.AuthFunc()
}
}

// OnAuthSettingChanged implements backend.Environment.
func (env *BackendEnvironment) OnAuthSettingChanged(enabled bool) {
if env.OnAuthSettingChangedFunc != nil {
env.OnAuthSettingChangedFunc(enabled)
}
}

// Serve serves the BitBox API for use in a native client.
func Serve(
testnet bool,
Expand Down
7 changes: 7 additions & 0 deletions backend/handlers/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ func NewHandlers(
getAPIRouter(apiRouter)("/aopp/choose-account", handlers.postAOPPChooseAccountHandler).Methods("POST")
getAPIRouterNoError(apiRouter)("/cancel-connect-keystore", handlers.postCancelConnectKeystoreHandler).Methods("POST")
getAPIRouterNoError(apiRouter)("/set-watchonly", handlers.postSetWatchonlyHandler).Methods("POST")
getAPIRouterNoError(apiRouter)("/on-auth-setting-changed", handlers.postOnAuthSettingChangedHandler).Methods("POST")

devicesRouter := getAPIRouterNoError(apiRouter.PathPrefix("/devices").Subrouter())
devicesRouter("/registered", handlers.getDevicesRegisteredHandler).Methods("GET")
Expand Down Expand Up @@ -1333,3 +1334,9 @@ func (handlers *Handlers) postSetWatchonlyHandler(r *http.Request) interface{} {
}
return response{Success: true}
}

func (handlers *Handlers) postOnAuthSettingChangedHandler(r *http.Request) interface{} {
handlers.backend.Environment().OnAuthSettingChanged(
handlers.backend.Config().AppConfig().Backend.Authentication)
return nil
}
4 changes: 4 additions & 0 deletions cmd/servewallet/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ func (webdevEnvironment) Auth() {
}
}

// OnAuthSettingChanged implements backend.Environment.
func (webdevEnvironment) OnAuthSettingChanged(enabled bool) {
}

// NativeLocale naively implements backend.Environment.
// This version is unlikely to work on Windows.
func (webdevEnvironment) NativeLocale() string {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,13 @@ public long vendorID() {
}
}

private class GoEnvironment implements GoEnvironmentInterface {
public interface OnAuthSettingChangedAction {
void execute(boolean enabled);
}

public class GoEnvironment implements GoEnvironmentInterface {
private OnAuthSettingChangedAction onAuthSettingChangedAction;

public GoEnvironment() {
}

Expand All @@ -126,6 +132,16 @@ public void auth() {
requestAuth();
}

public void setOnAuthSettingChangedAction(OnAuthSettingChangedAction action) {
this.onAuthSettingChangedAction = action;
}

public void onAuthSettingChanged(boolean enabled) {
if (onAuthSettingChangedAction != null){
onAuthSettingChangedAction.execute(enabled);
}
}

public boolean usingMobileData() {
// Adapted from https://stackoverflow.com/a/53243938

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ public void onChanged(Boolean requestAuth) {
if (!requestAuth) {
return;
}

BiometricAuthHelper.showAuthenticationPrompt(MainActivity.this, new BiometricAuthHelper.AuthCallback() {
@Override
public void onSuccess() {
Expand All @@ -377,22 +378,37 @@ public void onSuccess() {
public void onFailure() {
// Failed
Util.log("Auth failed");
goViewModel.closeAuth();;
goViewModel.closeAuth();
Goserver.authResult(false);
}

@Override
public void onCancel() {
// Canceled
Util.log("Auth canceled");
goViewModel.closeAuth();;
goViewModel.closeAuth();
Goserver.cancelAuth();

}
});
}
});

goViewModel.getGoEnvironment().setOnAuthSettingChangedAction(enabled -> {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (enabled) {
// Treat the content of the window as secure, preventing it from appearing in
// screenshots, the app switcher, or from being viewed on non-secure displays. We
// are really only interested in hiding the app contents from the app switcher -
// screenshots unfortunately also get disabled.
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
}
});
});
}

@Override
Expand Down
8 changes: 5 additions & 3 deletions frontends/android/goserver/goserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ type GoEnvironmentInterface interface {
SetDarkTheme(bool)
DetectDarkTheme() bool
Auth()
OnAuthSettingChanged(bool)
}

// readWriteCloser implements io.ReadWriteCloser, translating from GoReadWriteCloserInterface. All methods
Expand Down Expand Up @@ -185,7 +186,6 @@ func Serve(dataDir string, environment GoEnvironmentInterface, goAPI GoAPIInterf
goAPI,
&bridgecommon.BackendEnvironment{
NotifyUserFunc: environment.NotifyUser,
AuthFunc: environment.Auth,
DeviceInfosFunc: func() []usb.DeviceInfo {
i := environment.DeviceInfo()
if i == nil {
Expand All @@ -200,8 +200,10 @@ func Serve(dataDir string, environment GoEnvironmentInterface, goAPI GoAPIInterf
// On Android, we don't yet support exporting files. Implement this once needed.
return ""
},
SetDarkThemeFunc: environment.SetDarkTheme,
DetectDarkThemeFunc: environment.DetectDarkTheme,
SetDarkThemeFunc: environment.SetDarkTheme,
DetectDarkThemeFunc: environment.DetectDarkTheme,
AuthFunc: environment.Auth,
OnAuthSettingChangedFunc: environment.OnAuthSettingChanged,
},
)
}
Expand Down
1 change: 1 addition & 0 deletions frontends/qt/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ func serve(
log.Info("Qt auth")
authResult(true)
},
OnAuthSettingChangedFunc: func(bool) {},
},
)
}
Expand Down
5 changes: 5 additions & 0 deletions frontends/web/src/api/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ export const cancelConnectKeystore = (): Promise<void> => {
export const setWatchonly = (watchonly: boolean): Promise<ISuccess> => {
return apiPost('set-watchonly', watchonly);
};

export const authenticate = (force: boolean = false): Promise<void> => {
return apiPost('authenticate', force);
};
Expand All @@ -125,3 +126,7 @@ export const subscribeAuth = (
) => (
subscribeEndpoint('auth', cb)
);

export const onAuthSettingChanged = (): Promise<void> => {
return apiPost('on-auth-setting-changed');
};
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { Toggle } from '../../../../components/toggle/toggle';
import { SettingsItem } from '../settingsItem/settingsItem';
import { TBackendConfig, TConfig } from '../../advanced-settings';
import { setConfig } from '../../../../utils/config';
import { TAuthEventObject, subscribeAuth, forceAuth } from '../../../../api/backend';
import { onAuthSettingChanged, TAuthEventObject, subscribeAuth, forceAuth } from '../../../../api/backend';
import { runningInAndroid } from '../../../../utils/env';

type TProps = {
Expand Down Expand Up @@ -52,6 +52,7 @@ export const EnableAuthSetting = ({ backendConfig, onChangeConfig }: TProps) =>
const config = await setConfig({
backend: { authentication: auth },
}) as TConfig;
onAuthSettingChanged();
onChangeConfig(config);
};

Expand Down

0 comments on commit feff560

Please sign in to comment.