Don't show multiple wipe warning dialogs

Stacking them on top of each other like that does not count as defence
in depth and we should not do it.

Bug: 32934848
Test: make RunSettingsRoboTests # added one specifically for this
Change-Id: I9490652c05a630e7c3f9164a9144fadfc0f41ea1
This commit is contained in:
Robin Lee
2017-02-06 18:19:40 +00:00
parent 85904ac4e8
commit c1cb8a4c2d
2 changed files with 114 additions and 19 deletions

View File

@@ -14,18 +14,21 @@
* limitations under the License * limitations under the License
*/ */
// TODO (b/35202196): move this class out of the root of the package.
package com.android.settings; package com.android.settings;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.ActivityOptions; import android.app.ActivityOptions;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.FragmentManager;
import android.app.IActivityManager; import android.app.IActivityManager;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager; import android.app.trust.TrustManager;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent; import android.content.Intent;
import android.content.IntentSender; import android.content.IntentSender;
import android.graphics.Point; import android.graphics.Point;
@@ -289,12 +292,13 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends OptionsMenuFra
// Last try // Last try
final String title = getActivity().getString( final String title = getActivity().getString(
R.string.lock_profile_wipe_warning_title); R.string.lock_profile_wipe_warning_title);
final String message = getActivity().getString(getLastTryErrorMessage()); LastTryDialog.show(getFragmentManager(), title, getLastTryErrorMessage(),
showDialog(title, message, android.R.string.ok, false /* dismiss */); android.R.string.ok, false /* dismiss */);
} else if (remainingAttempts <= 0) { } else if (remainingAttempts <= 0) {
// Profile is wiped // Profile is wiped
final String message = getActivity().getString(R.string.lock_profile_wipe_content); LastTryDialog.show(getFragmentManager(), null /* title */,
showDialog(null, message, R.string.lock_profile_wipe_dismiss, true /* dismiss */); R.string.lock_profile_wipe_content, R.string.lock_profile_wipe_dismiss,
true /* dismiss */);
} }
if (mErrorTextView != null) { if (mErrorTextView != null) {
final String message = getActivity().getString(R.string.lock_profile_wipe_attempts, final String message = getActivity().getString(R.string.lock_profile_wipe_attempts,
@@ -328,19 +332,55 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends OptionsMenuFra
showError(getText(msg), timeout); showError(getText(msg), timeout);
} }
private void showDialog(String title, String message, int buttonString, final boolean dismiss) { public static class LastTryDialog extends DialogFragment {
final AlertDialog dialog = new AlertDialog.Builder(getActivity()) private static final String TAG = LastTryDialog.class.getSimpleName();
.setTitle(title)
.setMessage(message) private static final String ARG_TITLE = "title";
.setPositiveButton(buttonString, new OnClickListener() { private static final String ARG_MESSAGE = "message";
private static final String ARG_BUTTON = "button";
private static final String ARG_DISMISS = "dismiss";
static boolean show(FragmentManager from, String title, int message, int button,
boolean dismiss) {
LastTryDialog existent = (LastTryDialog) from.findFragmentByTag(TAG);
if (existent != null && !existent.isRemoving()) {
return false;
}
Bundle args = new Bundle();
args.putString(ARG_TITLE, title);
args.putInt(ARG_MESSAGE, message);
args.putInt(ARG_BUTTON, button);
args.putBoolean(ARG_DISMISS, dismiss);
DialogFragment dialog = new LastTryDialog();
dialog.setArguments(args);
dialog.show(from, TAG);
return true;
}
static void hide(FragmentManager from) {
LastTryDialog dialog = (LastTryDialog) from.findFragmentByTag(TAG);
if (dialog != null) {
dialog.dismissAllowingStateLoss();
from.executePendingTransactions();
}
}
@Override @Override
public void onClick(DialogInterface dialog, int which) { public Dialog onCreateDialog(Bundle savedInstanceState) {
if (dismiss) { return new AlertDialog.Builder(getActivity())
.setTitle(getArguments().getString(ARG_TITLE))
.setMessage(getArguments().getInt(ARG_MESSAGE))
.setPositiveButton(getArguments().getInt(ARG_BUTTON), null)
.create();
}
@Override
public void onDismiss(final DialogInterface dialog) {
super.onDismiss(dialog);
if (getActivity() != null && getArguments().getBoolean(ARG_DISMISS)) {
getActivity().finish(); getActivity().finish();
} }
} }
})
.create();
dialog.show();
} }
} }

View File

@@ -0,0 +1,55 @@
/*
* 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.settings;
import static com.android.settings.ConfirmDeviceCredentialBaseFragment.LastTryDialog;
import static com.google.common.truth.Truth.assertThat;
import android.R;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(
manifest = TestConfig.MANIFEST_PATH,
sdk = TestConfig.SDK_VERSION,
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
})
public class ConfirmCredentialTest {
@Test
public void testLastTryDialogShownExactlyOnce() {
FragmentManager fm = Robolectric.buildActivity(Activity.class).get().getFragmentManager();
// Launch only one instance at a time.
assertThat(LastTryDialog.show(fm, "title", R.string.yes, R.string.ok, false)).isTrue();
assertThat(LastTryDialog.show(fm, "title", R.string.yes, R.string.ok, false)).isFalse();
// After cancelling, the dialog should be re-shown when asked for.
LastTryDialog.hide(fm);
assertThat(LastTryDialog.show(fm, "title", R.string.yes, R.string.ok, false)).isTrue();
}
}