CertDialog supports multiple certs
- Allow user to trust multiple certs in chain in one AlertDialog - The animation is similar to GrantPermissionsViewHandlerImpl. - Fadeout current, Slide-in next cert from the right. - Not animate scale as the CustomeView in AlertDialog matchParent - Refactor CertDialogBuilder into a separate class - The change for config multiple cert into the dialog is another CL note: For single cert case when user taps on a system/user cert, no change is visible to user after this change Bug: 18224038 Change-Id: I09ee8f683031c800830af4001582882d61cd4974
This commit is contained in:
342
src/com/android/settings/TrustedCredentialsDialogBuilder.java
Normal file
342
src/com/android/settings/TrustedCredentialsDialogBuilder.java
Normal file
@@ -0,0 +1,342 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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 android.annotation.NonNull;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.admin.DevicePolicyManager;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.net.http.SslCertificate;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.os.UserManager;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.animation.AnimationUtils;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
|
||||||
|
import com.android.settings.TrustedCredentialsSettings.CertHolder;
|
||||||
|
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
class TrustedCredentialsDialogBuilder extends AlertDialog.Builder {
|
||||||
|
public interface DelegateInterface {
|
||||||
|
List<X509Certificate> getX509CertsFromCertHolder(CertHolder certHolder);
|
||||||
|
void removeOrInstallCert(CertHolder certHolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final DialogEventHandler mDialogEventHandler;
|
||||||
|
|
||||||
|
public TrustedCredentialsDialogBuilder(Activity activity, DelegateInterface delegate) {
|
||||||
|
super(activity);
|
||||||
|
mDialogEventHandler = new DialogEventHandler(activity, delegate);
|
||||||
|
|
||||||
|
initDefaultBuilderParams();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrustedCredentialsDialogBuilder setCertHolder(CertHolder certHolder) {
|
||||||
|
return setCertHolders(certHolder == null ? new CertHolder[0]
|
||||||
|
: new CertHolder[]{certHolder});
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrustedCredentialsDialogBuilder setCertHolders(@NonNull CertHolder[] certHolders) {
|
||||||
|
mDialogEventHandler.setCertHolders(certHolders);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AlertDialog create() {
|
||||||
|
AlertDialog dialog = super.create();
|
||||||
|
dialog.setOnShowListener(mDialogEventHandler);
|
||||||
|
mDialogEventHandler.setDialog(dialog);
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initDefaultBuilderParams() {
|
||||||
|
setTitle(com.android.internal.R.string.ssl_certificate);
|
||||||
|
setView(mDialogEventHandler.mRootContainer);
|
||||||
|
|
||||||
|
// Enable buttons here. The actual labels and listeners are configured in nextOrDismiss
|
||||||
|
setPositiveButton(R.string.trusted_credentials_trust_label, null);
|
||||||
|
setNegativeButton(android.R.string.ok, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DialogEventHandler implements DialogInterface.OnShowListener,
|
||||||
|
View.OnClickListener {
|
||||||
|
private static final long OUT_DURATION_MS = 300;
|
||||||
|
private static final long IN_DURATION_MS = 200;
|
||||||
|
|
||||||
|
private final Activity mActivity;
|
||||||
|
private final DevicePolicyManager mDpm;
|
||||||
|
private final UserManager mUserManager;
|
||||||
|
private final DelegateInterface mDelegate;
|
||||||
|
private final LinearLayout mRootContainer;
|
||||||
|
|
||||||
|
private int mCurrentCertIndex = -1;
|
||||||
|
private AlertDialog mDialog;
|
||||||
|
private Button mPositiveButton;
|
||||||
|
private Button mNegativeButton;
|
||||||
|
private boolean mNeedsApproval;
|
||||||
|
private CertHolder[] mCertHolders = new CertHolder[0];
|
||||||
|
private View mCurrentCertLayout = null;
|
||||||
|
|
||||||
|
public DialogEventHandler(Activity activity, DelegateInterface delegate) {
|
||||||
|
mActivity = activity;
|
||||||
|
mDpm = activity.getSystemService(DevicePolicyManager.class);
|
||||||
|
mUserManager = activity.getSystemService(UserManager.class);
|
||||||
|
mDelegate = delegate;
|
||||||
|
|
||||||
|
mRootContainer = new LinearLayout(mActivity);
|
||||||
|
mRootContainer.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDialog(AlertDialog dialog) {
|
||||||
|
mDialog = dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCertHolders(CertHolder[] certHolder) {
|
||||||
|
mCertHolders = certHolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onShow(DialogInterface dialogInterface) {
|
||||||
|
// Config the display content only when the dialog is shown because the
|
||||||
|
// positive/negative buttons don't exist until the dialog is shown
|
||||||
|
nextOrDismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
if (view == mPositiveButton) {
|
||||||
|
if (mNeedsApproval) {
|
||||||
|
onClickTrust();
|
||||||
|
} else {
|
||||||
|
onClickOk();
|
||||||
|
}
|
||||||
|
} else if (view == mNegativeButton) {
|
||||||
|
onClickRemove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickOk() {
|
||||||
|
nextOrDismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickTrust() {
|
||||||
|
CertHolder certHolder = getCurrentCertInfo();
|
||||||
|
mDpm.approveCaCert(certHolder.getAlias(), certHolder.getUserId(), true);
|
||||||
|
nextOrDismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickRemove() {
|
||||||
|
final CertHolder certHolder = getCurrentCertInfo();
|
||||||
|
new AlertDialog.Builder(mActivity)
|
||||||
|
.setMessage(getButtonConfirmation(certHolder))
|
||||||
|
.setPositiveButton(android.R.string.yes,
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
mDelegate.removeOrInstallCert(certHolder);
|
||||||
|
dialog.dismiss();
|
||||||
|
nextOrDismiss();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(android.R.string.no, null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private CertHolder getCurrentCertInfo() {
|
||||||
|
return mCurrentCertIndex < mCertHolders.length ? mCertHolders[mCurrentCertIndex] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void nextOrDismiss() {
|
||||||
|
mCurrentCertIndex++;
|
||||||
|
// find next non-null cert or dismiss
|
||||||
|
while (mCurrentCertIndex < mCertHolders.length && getCurrentCertInfo() == null) {
|
||||||
|
mCurrentCertIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCurrentCertIndex >= mCertHolders.length) {
|
||||||
|
mDialog.dismiss();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateViewContainer();
|
||||||
|
updatePositiveButton();
|
||||||
|
updateNegativeButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePositiveButton() {
|
||||||
|
final CertHolder certHolder = getCurrentCertInfo();
|
||||||
|
mNeedsApproval = !certHolder.isSystemCert() &&
|
||||||
|
!mDpm.isCaCertApproved(certHolder.getAlias(), certHolder.getUserId());
|
||||||
|
|
||||||
|
// The ok button is optional. User can still dismiss the dialog by other means.
|
||||||
|
// Display it only when trust button is not displayed, because we want users to
|
||||||
|
// either remove or trust a CA cert when the cert is installed by DPC app.
|
||||||
|
CharSequence displayText = mActivity.getText(mNeedsApproval
|
||||||
|
? R.string.trusted_credentials_trust_label
|
||||||
|
: android.R.string.ok);
|
||||||
|
mPositiveButton = updateButton(DialogInterface.BUTTON_POSITIVE, displayText);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateNegativeButton() {
|
||||||
|
final CertHolder certHolder = getCurrentCertInfo();
|
||||||
|
final boolean showRemoveButton = !mUserManager.hasUserRestriction(
|
||||||
|
UserManager.DISALLOW_CONFIG_CREDENTIALS,
|
||||||
|
new UserHandle(certHolder.getUserId()));
|
||||||
|
CharSequence displayText = mActivity.getText(getButtonLabel(certHolder));
|
||||||
|
mNegativeButton = updateButton(DialogInterface.BUTTON_NEGATIVE, displayText);
|
||||||
|
mNegativeButton.setVisibility(showRemoveButton ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mDialog.setButton doesn't trigger text refresh since mDialog has been shown.
|
||||||
|
* It's invoked only in case mDialog is refreshed.
|
||||||
|
* setOnClickListener is invoked to avoid dismiss dialog onClick
|
||||||
|
*/
|
||||||
|
private Button updateButton(int buttonType, CharSequence displayText) {
|
||||||
|
mDialog.setButton(buttonType, displayText, (DialogInterface.OnClickListener) null);
|
||||||
|
Button button = mDialog.getButton(buttonType);
|
||||||
|
button.setText(displayText);
|
||||||
|
button.setOnClickListener(this);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void updateViewContainer() {
|
||||||
|
CertHolder certHolder = getCurrentCertInfo();
|
||||||
|
LinearLayout nextCertLayout = getCertLayout(certHolder);
|
||||||
|
|
||||||
|
// Displaying first cert doesn't require animation
|
||||||
|
if (mCurrentCertLayout == null) {
|
||||||
|
mCurrentCertLayout = nextCertLayout;
|
||||||
|
mRootContainer.addView(mCurrentCertLayout);
|
||||||
|
} else {
|
||||||
|
animateViewTransition(nextCertLayout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private LinearLayout getCertLayout(final CertHolder certHolder) {
|
||||||
|
final ArrayList<View> views = new ArrayList<View>();
|
||||||
|
final ArrayList<String> titles = new ArrayList<String>();
|
||||||
|
List<X509Certificate> certificates = mDelegate.getX509CertsFromCertHolder(certHolder);
|
||||||
|
if (certificates != null) {
|
||||||
|
for (X509Certificate certificate : certificates) {
|
||||||
|
SslCertificate sslCert = new SslCertificate(certificate);
|
||||||
|
views.add(sslCert.inflateCertificateView(mActivity));
|
||||||
|
titles.add(sslCert.getIssuedTo().getCName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(mActivity,
|
||||||
|
android.R.layout.simple_spinner_item,
|
||||||
|
titles);
|
||||||
|
arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
Spinner spinner = new Spinner(mActivity);
|
||||||
|
spinner.setAdapter(arrayAdapter);
|
||||||
|
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(AdapterView<?> parent, View view, int position,
|
||||||
|
long id) {
|
||||||
|
for (int i = 0; i < views.size(); i++) {
|
||||||
|
views.get(i).setVisibility(i == position ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected(AdapterView<?> parent) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
LinearLayout certLayout = new LinearLayout(mActivity);
|
||||||
|
certLayout.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
certLayout.addView(spinner);
|
||||||
|
for (int i = 0; i < views.size(); ++i) {
|
||||||
|
View certificateView = views.get(i);
|
||||||
|
// Show first cert by default
|
||||||
|
certificateView.setVisibility(i == 0 ? View.VISIBLE : View.GONE);
|
||||||
|
certLayout.addView(certificateView);
|
||||||
|
}
|
||||||
|
|
||||||
|
return certLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getButtonConfirmation(CertHolder certHolder) {
|
||||||
|
return certHolder.isSystemCert() ? ( certHolder.isDeleted()
|
||||||
|
? R.string.trusted_credentials_enable_confirmation
|
||||||
|
: R.string.trusted_credentials_disable_confirmation )
|
||||||
|
: R.string.trusted_credentials_remove_confirmation;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getButtonLabel(CertHolder certHolder) {
|
||||||
|
return certHolder.isSystemCert() ? ( certHolder.isDeleted()
|
||||||
|
? R.string.trusted_credentials_enable_label
|
||||||
|
: R.string.trusted_credentials_disable_label )
|
||||||
|
: R.string.trusted_credentials_remove_label;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animation code */
|
||||||
|
private void animateViewTransition(final View nextCertView) {
|
||||||
|
animateOldContent(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
addAndAnimateNewContent(nextCertView);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void animateOldContent(Runnable callback) {
|
||||||
|
// Fade out
|
||||||
|
mCurrentCertLayout.animate()
|
||||||
|
.alpha(0)
|
||||||
|
.setDuration(OUT_DURATION_MS)
|
||||||
|
.setInterpolator(AnimationUtils.loadInterpolator(mActivity,
|
||||||
|
android.R.interpolator.fast_out_linear_in))
|
||||||
|
.withEndAction(callback)
|
||||||
|
.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addAndAnimateNewContent(View nextCertLayout) {
|
||||||
|
mCurrentCertLayout = nextCertLayout;
|
||||||
|
mRootContainer.removeAllViews();
|
||||||
|
mRootContainer.addView(nextCertLayout);
|
||||||
|
|
||||||
|
mRootContainer.addOnLayoutChangeListener( new View.OnLayoutChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onLayoutChange(View v, int left, int top, int right, int bottom,
|
||||||
|
int oldLeft, int oldTop, int oldRight, int oldBottom) {
|
||||||
|
mRootContainer.removeOnLayoutChangeListener(this);
|
||||||
|
|
||||||
|
// Animate slide in from the right
|
||||||
|
final int containerWidth = mRootContainer.getWidth();
|
||||||
|
mCurrentCertLayout.setTranslationX(containerWidth);
|
||||||
|
mCurrentCertLayout.animate()
|
||||||
|
.translationX(0)
|
||||||
|
.setInterpolator(AnimationUtils.loadInterpolator(mActivity,
|
||||||
|
android.R.interpolator.linear_out_slow_in))
|
||||||
|
.setDuration(IN_DURATION_MS)
|
||||||
|
.start();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -16,13 +16,9 @@
|
|||||||
|
|
||||||
package com.android.settings;
|
package com.android.settings;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.app.Dialog;
|
|
||||||
import android.app.KeyguardManager;
|
import android.app.KeyguardManager;
|
||||||
import android.app.admin.DevicePolicyManager;
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.pm.UserInfo;
|
import android.content.pm.UserInfo;
|
||||||
@@ -41,16 +37,11 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.AdapterView.OnItemSelectedListener;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.BaseAdapter;
|
import android.widget.BaseAdapter;
|
||||||
import android.widget.BaseExpandableListAdapter;
|
import android.widget.BaseExpandableListAdapter;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.ExpandableListView;
|
import android.widget.ExpandableListView;
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.Spinner;
|
|
||||||
import android.widget.Switch;
|
import android.widget.Switch;
|
||||||
import android.widget.TabHost;
|
import android.widget.TabHost;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
@@ -67,7 +58,8 @@ import java.util.Collections;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class TrustedCredentialsSettings extends OptionsMenuFragment {
|
public class TrustedCredentialsSettings extends OptionsMenuFragment
|
||||||
|
implements TrustedCredentialsDialogBuilder.DelegateInterface {
|
||||||
|
|
||||||
private static final String TAG = "TrustedCredentialsSettings";
|
private static final String TAG = "TrustedCredentialsSettings";
|
||||||
|
|
||||||
@@ -135,30 +127,6 @@ public class TrustedCredentialsSettings extends OptionsMenuFragment {
|
|||||||
}
|
}
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
private int getButtonLabel(CertHolder certHolder) {
|
|
||||||
switch (this) {
|
|
||||||
case SYSTEM:
|
|
||||||
if (certHolder.mDeleted) {
|
|
||||||
return R.string.trusted_credentials_enable_label;
|
|
||||||
}
|
|
||||||
return R.string.trusted_credentials_disable_label;
|
|
||||||
case USER:
|
|
||||||
return R.string.trusted_credentials_remove_label;
|
|
||||||
}
|
|
||||||
throw new AssertionError();
|
|
||||||
}
|
|
||||||
private int getButtonConfirmation(CertHolder certHolder) {
|
|
||||||
switch (this) {
|
|
||||||
case SYSTEM:
|
|
||||||
if (certHolder.mDeleted) {
|
|
||||||
return R.string.trusted_credentials_enable_confirmation;
|
|
||||||
}
|
|
||||||
return R.string.trusted_credentials_disable_confirmation;
|
|
||||||
case USER:
|
|
||||||
return R.string.trusted_credentials_remove_confirmation;
|
|
||||||
}
|
|
||||||
throw new AssertionError();
|
|
||||||
}
|
|
||||||
private void postOperationUpdate(boolean ok, CertHolder certHolder) {
|
private void postOperationUpdate(boolean ok, CertHolder certHolder) {
|
||||||
if (ok) {
|
if (ok) {
|
||||||
if (certHolder.mTab.mSwitch) {
|
if (certHolder.mTab.mSwitch) {
|
||||||
@@ -603,7 +571,7 @@ public class TrustedCredentialsSettings extends OptionsMenuFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class CertHolder implements Comparable<CertHolder> {
|
/* package */ static class CertHolder implements Comparable<CertHolder> {
|
||||||
public int mProfileId;
|
public int mProfileId;
|
||||||
private final IKeyChainService mService;
|
private final IKeyChainService mService;
|
||||||
private final TrustedCertificateAdapterCommons mAdapter;
|
private final TrustedCertificateAdapterCommons mAdapter;
|
||||||
@@ -679,6 +647,22 @@ public class TrustedCredentialsSettings extends OptionsMenuFragment {
|
|||||||
@Override public int hashCode() {
|
@Override public int hashCode() {
|
||||||
return mAlias.hashCode();
|
return mAlias.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getUserId() {
|
||||||
|
return mProfileId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAlias() {
|
||||||
|
return mAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSystemCert() {
|
||||||
|
return mTab == Tab.SYSTEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDeleted() {
|
||||||
|
return mDeleted;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private View getViewForCertificate(CertHolder certHolder, Tab mTab, View convertView,
|
private View getViewForCertificate(CertHolder certHolder, Tab mTab, View convertView,
|
||||||
@@ -717,90 +701,13 @@ public class TrustedCredentialsSettings extends OptionsMenuFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void showCertDialog(final CertHolder certHolder) {
|
private void showCertDialog(final CertHolder certHolder) {
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
new TrustedCredentialsDialogBuilder(getActivity(), this)
|
||||||
builder.setTitle(com.android.internal.R.string.ssl_certificate);
|
.setCertHolder(certHolder)
|
||||||
|
.show();
|
||||||
final DevicePolicyManager dpm = getActivity().getSystemService(DevicePolicyManager.class);
|
|
||||||
final ArrayList<View> views = new ArrayList<View>();
|
|
||||||
final ArrayList<String> titles = new ArrayList<String>();
|
|
||||||
addCertChain(certHolder, views, titles);
|
|
||||||
|
|
||||||
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(getActivity(),
|
|
||||||
android.R.layout.simple_spinner_item,
|
|
||||||
titles);
|
|
||||||
arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
|
||||||
Spinner spinner = new Spinner(getActivity());
|
|
||||||
spinner.setAdapter(arrayAdapter);
|
|
||||||
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
|
|
||||||
@Override
|
|
||||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
|
||||||
for (int i = 0; i < views.size(); i++) {
|
|
||||||
views.get(i).setVisibility(i == position ? View.VISIBLE : View.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNothingSelected(AdapterView<?> parent) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
LinearLayout container = new LinearLayout(getActivity());
|
|
||||||
container.setOrientation(LinearLayout.VERTICAL);
|
|
||||||
container.addView(spinner);
|
|
||||||
for (int i = 0; i < views.size(); ++i) {
|
|
||||||
View certificateView = views.get(i);
|
|
||||||
if (i != 0) {
|
|
||||||
certificateView.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
container.addView(certificateView);
|
|
||||||
}
|
|
||||||
builder.setView(container);
|
|
||||||
|
|
||||||
if (certHolder.mTab == Tab.USER &&
|
|
||||||
!dpm.isCaCertApproved(certHolder.mAlias, certHolder.mProfileId)) {
|
|
||||||
builder.setPositiveButton(R.string.trusted_credentials_trust_label,
|
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
|
||||||
dpm.approveCaCert(certHolder.mAlias, certHolder.mProfileId, true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// The ok button is optional. Display it only when trust button is not displayed.
|
|
||||||
// User can still dismiss the dialog by other means.
|
|
||||||
builder.setPositiveButton(android.R.string.ok, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS,
|
|
||||||
new UserHandle(certHolder.mProfileId))) {
|
|
||||||
builder.setNegativeButton(certHolder.mTab.getButtonLabel(certHolder),
|
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(final DialogInterface parentDialog, int i) {
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
|
||||||
builder.setMessage(certHolder.mTab.getButtonConfirmation(certHolder));
|
|
||||||
builder.setPositiveButton(android.R.string.yes,
|
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
|
||||||
new AliasOperation(certHolder).execute();
|
|
||||||
dialog.dismiss();
|
|
||||||
parentDialog.dismiss();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
builder.setNegativeButton(android.R.string.no, null);
|
|
||||||
AlertDialog alert = builder.create();
|
|
||||||
alert.show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCertChain(final CertHolder certHolder,
|
@Override
|
||||||
final ArrayList<View> views, final ArrayList<String> titles) {
|
public List<X509Certificate> getX509CertsFromCertHolder(CertHolder certHolder) {
|
||||||
|
|
||||||
List<X509Certificate> certificates = null;
|
List<X509Certificate> certificates = null;
|
||||||
try {
|
try {
|
||||||
KeyChainConnection keyChainConnection = mKeyChainConnectionByProfileId.get(
|
KeyChainConnection keyChainConnection = mKeyChainConnectionByProfileId.get(
|
||||||
@@ -817,18 +724,13 @@ public class TrustedCredentialsSettings extends OptionsMenuFragment {
|
|||||||
} catch (RemoteException ex) {
|
} catch (RemoteException ex) {
|
||||||
Log.e(TAG, "RemoteException while retrieving certificate chain for root "
|
Log.e(TAG, "RemoteException while retrieving certificate chain for root "
|
||||||
+ certHolder.mAlias, ex);
|
+ certHolder.mAlias, ex);
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (X509Certificate certificate : certificates) {
|
|
||||||
addCertDetails(certificate, views, titles);
|
|
||||||
}
|
}
|
||||||
|
return certificates;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCertDetails(X509Certificate certificate, final ArrayList<View> views,
|
@Override
|
||||||
final ArrayList<String> titles) {
|
public void removeOrInstallCert(CertHolder certHolder) {
|
||||||
SslCertificate sslCert = new SslCertificate(certificate);
|
new AliasOperation(certHolder).execute();
|
||||||
views.add(sslCert.inflateCertificateView(getActivity()));
|
|
||||||
titles.add(sslCert.getIssuedTo().getCName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AliasOperation extends AsyncTask<Void, Void, Boolean> {
|
private class AliasOperation extends AsyncTask<Void, Void, Boolean> {
|
||||||
@@ -854,8 +756,7 @@ public class TrustedCredentialsSettings extends OptionsMenuFragment {
|
|||||||
}
|
}
|
||||||
} catch (CertificateEncodingException | SecurityException | IllegalStateException
|
} catch (CertificateEncodingException | SecurityException | IllegalStateException
|
||||||
| RemoteException e) {
|
| RemoteException e) {
|
||||||
Log.w(TAG, "Error while toggling alias " + mCertHolder.mAlias,
|
Log.w(TAG, "Error while toggling alias " + mCertHolder.mAlias, e);
|
||||||
e);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user