Merge "Protect autofill UI against redressing" into oc-dev

This commit is contained in:
Svetoslav Ganov
2017-06-09 20:53:26 +00:00
committed by Android (Google) Code Review
4 changed files with 86 additions and 14 deletions

View File

@@ -61,6 +61,8 @@ public final class AutoFillUI {
private final MetricsLogger mMetricsLogger = new MetricsLogger();
private final @NonNull OverlayControl mOverlayControl;
public interface AutoFillUiCallback {
void authenticate(int requestId, int datasetIndex, @NonNull IntentSender intent,
@Nullable Bundle extras);
@@ -75,6 +77,7 @@ public final class AutoFillUI {
public AutoFillUI(@NonNull Context context) {
mContext = context;
mOverlayControl = new OverlayControl(context);
}
public void setCallback(@NonNull AutoFillUiCallback callback) {
@@ -174,7 +177,7 @@ public final class AutoFillUI {
}
hideAllUiThread(callback);
mFillUi = new FillUi(mContext, response, focusedId,
filterText, new FillUi.Callback() {
filterText, mOverlayControl, new FillUi.Callback() {
@Override
public void onResponsePicked(FillResponse response) {
log.setType(MetricsProto.MetricsEvent.TYPE_DETAIL);
@@ -255,7 +258,7 @@ public final class AutoFillUI {
}
hideAllUiThread(callback);
mSaveUi = new SaveUi(mContext, providerLabel, info,
new SaveUi.OnSaveListener() {
mOverlayControl, new SaveUi.OnSaveListener() {
@Override
public void onSave() {
log.setType(MetricsProto.MetricsEvent.TYPE_ACTION);

View File

@@ -100,7 +100,7 @@ final class FillUi {
FillUi(@NonNull Context context, @NonNull FillResponse response,
@NonNull AutofillId focusedViewId, @NonNull @Nullable String filterText,
@NonNull Callback callback) {
@NonNull OverlayControl overlayControl, @NonNull Callback callback) {
mContext = context;
mCallback = callback;
@@ -146,7 +146,7 @@ final class FillUi {
mContentWidth = content.getMeasuredWidth();
mContentHeight = content.getMeasuredHeight();
mWindow = new AnchoredWindow(decor);
mWindow = new AnchoredWindow(decor, overlayControl);
mCallback.requestShowFillUi(mContentWidth, mContentHeight, mWindowPresenter);
} else {
final int datasetCount = response.getDatasets().size();
@@ -193,7 +193,7 @@ final class FillUi {
}
applyNewFilterText();
mWindow = new AnchoredWindow(decor);
mWindow = new AnchoredWindow(decor, overlayControl);
}
}
@@ -366,6 +366,7 @@ final class FillUi {
}
final class AnchoredWindow implements View.OnTouchListener {
private final @NonNull OverlayControl mOverlayControl;
private final WindowManager mWm;
private final View mContentView;
private boolean mShowing;
@@ -375,9 +376,10 @@ final class FillUi {
*
* @param contentView content of the window
*/
AnchoredWindow(View contentView) {
AnchoredWindow(View contentView, @NonNull OverlayControl overlayControl) {
mWm = contentView.getContext().getSystemService(WindowManager.class);
mContentView = contentView;
mOverlayControl = overlayControl;
}
/**
@@ -391,6 +393,7 @@ final class FillUi {
.getString(R.string.autofill_picker_accessibility_title);
mWm.addView(mContentView, params);
mContentView.setOnTouchListener(this);
mOverlayControl.hideOverlays();
mShowing = true;
} else {
mWm.updateViewLayout(mContentView, params);
@@ -423,6 +426,8 @@ final class FillUi {
// does, it should not crash the system.
Slog.e(TAG, "Exception hiding window ", e);
mCallback.onDestroy();
} finally {
mOverlayControl.showOverlays();
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.autofill.ui;
import android.annotation.NonNull;
import android.app.AppOpsManager;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
/**
* This class controls showing/hiding overlays. We don't
* hide all overlays (toast/system alerts) while sensitive
* autofill UI is up.
*/
class OverlayControl {
private final IBinder mToken = new Binder();
private final @NonNull AppOpsManager mAppOpsManager;
OverlayControl(@NonNull Context context) {
mAppOpsManager = context.getSystemService(AppOpsManager.class);
}
void hideOverlays() {
setOverlayAllowed(false);
}
void showOverlays() {
setOverlayAllowed(true);
}
private void setOverlayAllowed(boolean allowed) {
if (mAppOpsManager != null) {
mAppOpsManager.setUserRestriction(
AppOpsManager.OP_SYSTEM_ALERT_WINDOW, !allowed, mToken);
mAppOpsManager.setUserRestriction(
AppOpsManager.OP_TOAST_WINDOW, !allowed, mToken);
}
}
}

View File

@@ -99,14 +99,17 @@ final class SaveUi {
private final @NonNull OneTimeListener mListener;
private final @NonNull OverlayControl mOverlayControl;
private final CharSequence mTitle;
private final CharSequence mSubTitle;
private boolean mDestroyed;
SaveUi(@NonNull Context context, @NonNull CharSequence providerLabel, @NonNull SaveInfo info,
@NonNull OnSaveListener listener) {
@NonNull OverlayControl overlayControl, @NonNull OnSaveListener listener) {
mListener = new OneTimeListener(listener);
mOverlayControl = overlayControl;
final LayoutInflater inflater = LayoutInflater.from(context);
final View view = inflater.inflate(R.layout.autofill_save, null);
@@ -197,16 +200,21 @@ final class SaveUi {
Slog.i(TAG, "Showing save dialog: " + mTitle);
mDialog.show();
mOverlayControl.hideOverlays();
}
void destroy() {
if (sDebug) Slog.d(TAG, "destroy()");
throwIfDestroyed();
mListener.onDestroy();
mHandler.removeCallbacksAndMessages(mListener);
if (sVerbose) Slog.v(TAG, "destroy(): dismissing dialog");
mDialog.dismiss();
mDestroyed = true;
try {
if (sDebug) Slog.d(TAG, "destroy()");
throwIfDestroyed();
mListener.onDestroy();
mHandler.removeCallbacksAndMessages(mListener);
if (sVerbose) Slog.v(TAG, "destroy(): dismissing dialog");
mDialog.dismiss();
mDestroyed = true;
} finally {
mOverlayControl.showOverlays();
}
}
private void throwIfDestroyed() {