/*
 * Copyright (C) 2011 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.app.AlertDialog;
import android.app.Dialog;
import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.UserInfo;
import android.net.http.SslCertificate;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.security.IKeyChainService;
import android.security.KeyChain;
import android.security.KeyChain.KeyChainConnection;
import android.util.SparseArray;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.BaseExpandableListAdapter;
import android.widget.Button;
import android.widget.ExpandableListView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TabHost;
import android.widget.TextView;

import com.android.internal.logging.MetricsLogger;
import com.android.internal.util.ParcelableString;

import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.HashMap;

public class TrustedCredentialsSettings extends InstrumentedFragment {

    private static final String TAG = "TrustedCredentialsSettings";

    private UserManager mUserManager;

    private static final String USER_ACTION = "com.android.settings.TRUSTED_CREDENTIALS_USER";

    @Override
    protected int getMetricsCategory() {
        return MetricsLogger.TRUSTED_CREDENTIALS;
    }

    private enum Tab {
        SYSTEM("system",
               R.string.trusted_credentials_system_tab,
               R.id.system_tab,
               R.id.system_progress,
               R.id.system_list,
               R.id.system_expandable_list,
               true),
        USER("user",
             R.string.trusted_credentials_user_tab,
             R.id.user_tab,
             R.id.user_progress,
             R.id.user_list,
             R.id.user_expandable_list,
             false);

        private final String mTag;
        private final int mLabel;
        private final int mView;
        private final int mProgress;
        private final int mList;
        private final int mExpandableList;
        private final boolean mSwitch;

        private Tab(String tag, int label, int view, int progress, int list, int expandableList,
                boolean withSwitch) {
            mTag = tag;
            mLabel = label;
            mView = view;
            mProgress = progress;
            mList = list;
            mExpandableList = expandableList;
            mSwitch = withSwitch;
        }

        private List<ParcelableString> getAliases(IKeyChainService service) throws RemoteException {
            switch (this) {
                case SYSTEM: {
                    return service.getSystemCaAliases().getList();
                }
                case USER:
                    return service.getUserCaAliases().getList();
            }
            throw new AssertionError();
        }
        private boolean deleted(IKeyChainService service, String alias) throws RemoteException {
            switch (this) {
                case SYSTEM:
                    return !service.containsCaAlias(alias);
                case USER:
                    return false;
            }
            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) {
            if (ok) {
                if (certHolder.mTab.mSwitch) {
                    certHolder.mDeleted = !certHolder.mDeleted;
                } else {
                    certHolder.mAdapter.remove(certHolder);
                }
                certHolder.mAdapter.notifyDataSetChanged();
            } else {
                // bail, reload to reset to known state
                certHolder.mAdapter.load();
            }
        }
    }

    private TabHost mTabHost;
    private AliasOperation mAliasOperation;
    private HashMap<Tab, AdapterData.AliasLoader>
            mAliasLoaders = new HashMap<Tab, AdapterData.AliasLoader>(2);
    private final SparseArray<KeyChainConnection>
            mKeyChainConnectionByProfileId = new SparseArray<KeyChainConnection>();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mUserManager = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
    }


    @Override public View onCreateView(
            LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
        mTabHost = (TabHost) inflater.inflate(R.layout.trusted_credentials, parent, false);
        mTabHost.setup();
        addTab(Tab.SYSTEM);
        // TODO add Install button on Tab.USER to go to CertInstaller like KeyChainActivity
        addTab(Tab.USER);
        if (getActivity().getIntent() != null &&
                USER_ACTION.equals(getActivity().getIntent().getAction())) {
            mTabHost.setCurrentTabByTag(Tab.USER.mTag);
        }
        return mTabHost;
    }
    @Override
    public void onDestroy() {
        for (AdapterData.AliasLoader aliasLoader : mAliasLoaders.values()) {
            aliasLoader.cancel(true);
        }
        if (mAliasOperation != null) {
            mAliasOperation.cancel(true);
            mAliasOperation = null;
        }
        closeKeyChainConnections();
        super.onDestroy();
    }

    private void closeKeyChainConnections() {
        final int n = mKeyChainConnectionByProfileId.size();
        for (int i = 0; i < n; ++i) {
            mKeyChainConnectionByProfileId.valueAt(i).close();
        }
        mKeyChainConnectionByProfileId.clear();
    }

    private void addTab(Tab tab) {
        TabHost.TabSpec systemSpec = mTabHost.newTabSpec(tab.mTag)
                .setIndicator(getActivity().getString(tab.mLabel))
                .setContent(tab.mView);
        mTabHost.addTab(systemSpec);

        if (mUserManager.getUserProfiles().size() > 1) {
            ExpandableListView lv = (ExpandableListView) mTabHost.findViewById(tab.mExpandableList);
            final TrustedCertificateExpandableAdapter adapter =
                    new TrustedCertificateExpandableAdapter(tab);
            lv.setAdapter(adapter);
            lv.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
                    @Override
                public boolean onChildClick(ExpandableListView parent, View v,
                        int groupPosition, int childPosition, long id) {
                    showCertDialog(adapter.getChild(groupPosition, childPosition));
                    return true;
                }
            });
        } else {
            ListView lv = (ListView) mTabHost.findViewById(tab.mList);
            final TrustedCertificateAdapter adapter = new TrustedCertificateAdapter(tab);
            lv.setAdapter(adapter);
            lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override public void onItemClick(AdapterView<?> parent, View view,
                        int pos, long id) {
                    showCertDialog(adapter.getItem(pos));
                }
            });
        }
    }

    /**
     * Common interface for adapters of both expandable and non-expandable certificate lists.
     */
    private interface TrustedCertificateAdapterCommons {
        /**
         * Remove a certificate from the list.
         * @param certHolder the certificate to be removed.
         */
        void remove(CertHolder certHolder);
        /**
         * Notify the adapter that the underlying data set has changed.
         */
        void notifyDataSetChanged();
        /**
         * Load the certificates.
         */
        void load();
        /**
         * Gets the identifier of the list view the adapter is connected to.
         * @param tab the tab on which the list view resides.
         * @return identifier of the list view.
         */
        int getListViewId(Tab tab);
    }

    /**
     * Adapter for expandable list view of certificates. Groups in the view correspond to profiles
     * whereas children correspond to certificates.
     */
    private class TrustedCertificateExpandableAdapter extends BaseExpandableListAdapter implements
            TrustedCertificateAdapterCommons {
        private AdapterData mData;

        private TrustedCertificateExpandableAdapter(Tab tab) {
            mData = new AdapterData(tab, this);
            load();
        }
        @Override
        public void remove(CertHolder certHolder) {
            mData.remove(certHolder);
        }
        @Override
        public int getGroupCount() {
            return mData.mCertHoldersByUserId.size();
        }
        @Override
        public int getChildrenCount(int groupPosition) {
            List<CertHolder> certHolders = mData.mCertHoldersByUserId.valueAt(groupPosition);
            if (certHolders != null) {
                return certHolders.size();
            }
            return 0;
        }
        @Override
        public UserHandle getGroup(int groupPosition) {
            return new UserHandle(mData.mCertHoldersByUserId.keyAt(groupPosition));
        }
        @Override
        public CertHolder getChild(int groupPosition, int childPosition) {
            return mData.mCertHoldersByUserId.valueAt(groupPosition).get(childPosition);
        }
        @Override
        public long getGroupId(int groupPosition) {
            return mData.mCertHoldersByUserId.keyAt(groupPosition);
        }
        @Override
        public long getChildId(int groupPosition, int childPosition) {
            return childPosition;
        }
        @Override
        public boolean hasStableIds() {
            return false;
        }
        @Override
        public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
                ViewGroup parent) {
            if (convertView == null) {
                LayoutInflater inflater = (LayoutInflater) getActivity()
                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = Utils.inflateCategoryHeader(inflater, parent);
            }

            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
            final UserHandle profile = getGroup(groupPosition);
            final UserInfo userInfo = mUserManager.getUserInfo(profile.getIdentifier());
            if (userInfo.isManagedProfile()) {
                title.setText(R.string.category_work);
            } else {
                title.setText(R.string.category_personal);
            }
            title.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_END);

            return convertView;
        }
        @Override
        public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
                View convertView, ViewGroup parent) {
            return getViewForCertificate(getChild(groupPosition, childPosition), mData.mTab,
                    convertView, parent);
        }
        @Override
        public boolean isChildSelectable(int groupPosition, int childPosition) {
            return true;
        }
        @Override
        public void load() {
            mData.new AliasLoader().execute();
        }
        @Override
        public int getListViewId(Tab tab) {
            return tab.mExpandableList;
        }
    }

    private class TrustedCertificateAdapter extends BaseAdapter implements
            TrustedCertificateAdapterCommons {
        private final AdapterData mData;
        private TrustedCertificateAdapter(Tab tab) {
            mData = new AdapterData(tab, this);
            load();
        }
        @Override
        public void remove(CertHolder certHolder) {
            mData.remove(certHolder);
        }
        @Override
        public int getListViewId(Tab tab) {
            return tab.mList;
        }
        @Override
        public void load() {
            mData.new AliasLoader().execute();
        }
        @Override public int getCount() {
            List<CertHolder> certHolders = mData.mCertHoldersByUserId.valueAt(0);
            if (certHolders != null) {
                return certHolders.size();
            }
            return 0;
        }
        @Override public CertHolder getItem(int position) {
            return mData.mCertHoldersByUserId.valueAt(0).get(position);
        }
        @Override public long getItemId(int position) {
            return position;
        }
        @Override public View getView(int position, View view, ViewGroup parent) {
            return getViewForCertificate(getItem(position), mData.mTab, view, parent);
        }
    }

    private class AdapterData {
        private final SparseArray<List<CertHolder>> mCertHoldersByUserId =
                new SparseArray<List<CertHolder>>();
        private final Tab mTab;
        private final TrustedCertificateAdapterCommons mAdapter;

        private AdapterData(Tab tab, TrustedCertificateAdapterCommons adapter) {
            mAdapter = adapter;
            mTab = tab;
        }

        private class AliasLoader extends AsyncTask<Void, Integer, SparseArray<List<CertHolder>>> {
            private ProgressBar mProgressBar;
            private View mList;
            private Context mContext;

            public AliasLoader() {
                mContext = getActivity();
                mAliasLoaders.put(mTab, this);
            }

            @Override protected void onPreExecute() {
                View content = mTabHost.getTabContentView();
                mProgressBar = (ProgressBar) content.findViewById(mTab.mProgress);
                mList = content.findViewById(mAdapter.getListViewId(mTab));
                mProgressBar.setVisibility(View.VISIBLE);
                mList.setVisibility(View.GONE);
            }
            @Override protected SparseArray<List<CertHolder>> doInBackground(Void... params) {
                SparseArray<List<CertHolder>> certHoldersByProfile =
                        new SparseArray<List<CertHolder>>();
                try {
                    List<UserHandle> profiles = mUserManager.getUserProfiles();
                    final int n = profiles.size();
                    // First we get all aliases for all profiles in order to show progress
                    // correctly. Otherwise this could all be in a single loop.
                    SparseArray<List<ParcelableString>> aliasesByProfileId = new SparseArray<
                            List<ParcelableString>>(n);
                    int max = 0;
                    int progress = 0;
                    for (int i = 0; i < n; ++i) {
                        UserHandle profile = profiles.get(i);
                        int profileId = profile.getIdentifier();
                        KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext,
                                profile);
                        // Saving the connection for later use on the certificate dialog.
                        mKeyChainConnectionByProfileId.put(profileId, keyChainConnection);
                        IKeyChainService service = keyChainConnection.getService();
                        List<ParcelableString> aliases = mTab.getAliases(service);
                        if (isCancelled()) {
                            return new SparseArray<List<CertHolder>>();
                        }
                        max += aliases.size();
                        aliasesByProfileId.put(profileId, aliases);
                    }
                    for (int i = 0; i < n; ++i) {
                        UserHandle profile = profiles.get(i);
                        int profileId = profile.getIdentifier();
                        List<ParcelableString> aliases = aliasesByProfileId.get(profileId);
                        if (isCancelled()) {
                            return new SparseArray<List<CertHolder>>();
                        }
                        IKeyChainService service = mKeyChainConnectionByProfileId.get(profileId)
                                .getService();
                        List<CertHolder> certHolders = new ArrayList<CertHolder>(max);
                        final int aliasMax = aliases.size();
                        for (int j = 0; j < aliasMax; ++j) {
                            String alias = aliases.get(j).string;
                            byte[] encodedCertificate = service.getEncodedCaCertificate(alias,
                                    true);
                            X509Certificate cert = KeyChain.toCertificate(encodedCertificate);
                            certHolders.add(new CertHolder(service, mAdapter,
                                    mTab, alias, cert, profileId));
                            publishProgress(++progress, max);
                        }
                        Collections.sort(certHolders);
                        certHoldersByProfile.put(profileId, certHolders);
                    }
                    return certHoldersByProfile;
                } catch (RemoteException e) {
                    Log.e(TAG, "Remote exception while loading aliases.", e);
                    return new SparseArray<List<CertHolder>>();
                } catch (InterruptedException e) {
                    Log.e(TAG, "InterruptedException while loading aliases.", e);
                    return new SparseArray<List<CertHolder>>();
                }
            }
            @Override protected void onProgressUpdate(Integer... progressAndMax) {
                int progress = progressAndMax[0];
                int max = progressAndMax[1];
                if (max != mProgressBar.getMax()) {
                    mProgressBar.setMax(max);
                }
                mProgressBar.setProgress(progress);
            }
            @Override protected void onPostExecute(SparseArray<List<CertHolder>> certHolders) {
                mCertHoldersByUserId.clear();
                final int n = certHolders.size();
                for (int i = 0; i < n; ++i) {
                    mCertHoldersByUserId.put(certHolders.keyAt(i), certHolders.valueAt(i));
                }
                mAdapter.notifyDataSetChanged();
                mProgressBar.setVisibility(View.GONE);
                mList.setVisibility(View.VISIBLE);
                mProgressBar.setProgress(0);
                mAliasLoaders.remove(mTab);
            }
        }

        public void remove(CertHolder certHolder) {
            if (mCertHoldersByUserId != null) {
                final List<CertHolder> certs = mCertHoldersByUserId.get(certHolder.mProfileId);
                if (certs != null) {
                    certs.remove(certHolder);
                }
            }
        }
    }

    private static class CertHolder implements Comparable<CertHolder> {
        public int mProfileId;
        private final IKeyChainService mService;
        private final TrustedCertificateAdapterCommons mAdapter;
        private final Tab mTab;
        private final String mAlias;
        private final X509Certificate mX509Cert;

        private final SslCertificate mSslCert;
        private final String mSubjectPrimary;
        private final String mSubjectSecondary;
        private boolean mDeleted;

        private CertHolder(IKeyChainService service,
                           TrustedCertificateAdapterCommons adapter,
                           Tab tab,
                           String alias,
                           X509Certificate x509Cert,
                           int profileId) {
            mProfileId = profileId;
            mService = service;
            mAdapter = adapter;
            mTab = tab;
            mAlias = alias;
            mX509Cert = x509Cert;

            mSslCert = new SslCertificate(x509Cert);

            String cn = mSslCert.getIssuedTo().getCName();
            String o = mSslCert.getIssuedTo().getOName();
            String ou = mSslCert.getIssuedTo().getUName();
            // if we have a O, use O as primary subject, secondary prefer CN over OU
            // if we don't have an O, use CN as primary, empty secondary
            // if we don't have O or CN, use DName as primary, empty secondary
            if (!o.isEmpty()) {
                if (!cn.isEmpty()) {
                    mSubjectPrimary = o;
                    mSubjectSecondary = cn;
                } else {
                    mSubjectPrimary = o;
                    mSubjectSecondary = ou;
                }
            } else {
                if (!cn.isEmpty()) {
                    mSubjectPrimary = cn;
                    mSubjectSecondary = "";
                } else {
                    mSubjectPrimary = mSslCert.getIssuedTo().getDName();
                    mSubjectSecondary = "";
                }
            }
            try {
                mDeleted = mTab.deleted(mService, mAlias);
            } catch (RemoteException e) {
                Log.e(TAG, "Remote exception while checking if alias " + mAlias + " is deleted.",
                        e);
                mDeleted = false;
            }
        }
        @Override public int compareTo(CertHolder o) {
            int primary = this.mSubjectPrimary.compareToIgnoreCase(o.mSubjectPrimary);
            if (primary != 0) {
                return primary;
            }
            return this.mSubjectSecondary.compareToIgnoreCase(o.mSubjectSecondary);
        }
        @Override public boolean equals(Object o) {
            if (!(o instanceof CertHolder)) {
                return false;
            }
            CertHolder other = (CertHolder) o;
            return mAlias.equals(other.mAlias);
        }
        @Override public int hashCode() {
            return mAlias.hashCode();
        }
    }

    private View getViewForCertificate(CertHolder certHolder, Tab mTab, View convertView,
            ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            LayoutInflater inflater = LayoutInflater.from(getActivity());
            convertView = inflater.inflate(R.layout.trusted_credential, parent, false);
            holder = new ViewHolder();
            holder.mSubjectPrimaryView = (TextView)
                    convertView.findViewById(R.id.trusted_credential_subject_primary);
            holder.mSubjectSecondaryView = (TextView)
                    convertView.findViewById(R.id.trusted_credential_subject_secondary);
            holder.mSwitch = (Switch) convertView.findViewById(
                    R.id.trusted_credential_status);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.mSubjectPrimaryView.setText(certHolder.mSubjectPrimary);
        holder.mSubjectSecondaryView.setText(certHolder.mSubjectSecondary);
        if (mTab.mSwitch) {
            holder.mSwitch.setChecked(!certHolder.mDeleted);
            holder.mSwitch.setEnabled(!mUserManager.hasUserRestriction(
                    UserManager.DISALLOW_CONFIG_CREDENTIALS,
                    new UserHandle(certHolder.mProfileId)));
            holder.mSwitch.setVisibility(View.VISIBLE);
        }
        return convertView;
    }

    private static class ViewHolder {
        private TextView mSubjectPrimaryView;
        private TextView mSubjectSecondaryView;
        private Switch mSwitch;
    }

    private void showCertDialog(final CertHolder certHolder) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle(com.android.internal.R.string.ssl_certificate);

        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);
        builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
            @Override public void onClick(DialogInterface dialog, int id) {
                dialog.dismiss();
            }
        });
        final Dialog certDialog = builder.create();

        ViewGroup body = (ViewGroup) container.findViewById(com.android.internal.R.id.body);
        LayoutInflater inflater = LayoutInflater.from(getActivity());
        Button removeButton = (Button) inflater.inflate(R.layout.trusted_credential_details,
                                                        body,
                                                        false);
        if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS,
                new UserHandle(certHolder.mProfileId))) {
            body.addView(removeButton);
        }
        removeButton.setText(certHolder.mTab.getButtonLabel(certHolder));
        removeButton.setOnClickListener(new View.OnClickListener() {
            @Override public void onClick(View v) {
                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();
                        certDialog.dismiss();
                    }
                });
                builder.setNegativeButton(
                        android.R.string.no, new DialogInterface.OnClickListener() {
                    @Override public void onClick(DialogInterface dialog, int id) {
                        dialog.cancel();
                    }
                });
                AlertDialog alert = builder.create();
                alert.show();
            }
        });

        certDialog.show();
    }

    private void addCertChain(final CertHolder certHolder,
            final ArrayList<View> views, final ArrayList<String> titles) {

        List<X509Certificate> certificates = null;
        try {
            KeyChainConnection keyChainConnection = mKeyChainConnectionByProfileId.get(
                    certHolder.mProfileId);
            IKeyChainService service = keyChainConnection.getService();
            List<String> chain = service.getCaCertificateChainAliases(certHolder.mAlias, true);
            final int n = chain.size();
            certificates = new ArrayList<X509Certificate>(n);
            for (int i = 0; i < n; ++i) {
                byte[] encodedCertificate = service.getEncodedCaCertificate(chain.get(i), true);
                X509Certificate certificate = KeyChain.toCertificate(encodedCertificate);
                certificates.add(certificate);
            }
        } catch (RemoteException ex) {
            Log.e(TAG, "RemoteException while retrieving certificate chain for root "
                    + certHolder.mAlias, ex);
            return;
        }
        for (X509Certificate certificate : certificates) {
            addCertDetails(certificate, views, titles);
        }
    }

    private void addCertDetails(X509Certificate certificate, final ArrayList<View> views,
            final ArrayList<String> titles) {
        SslCertificate sslCert = new SslCertificate(certificate);
        views.add(sslCert.inflateCertificateView(getActivity()));
        titles.add(sslCert.getIssuedTo().getCName());
    }

    private class AliasOperation extends AsyncTask<Void, Void, Boolean> {
        private final CertHolder mCertHolder;

        private AliasOperation(CertHolder certHolder) {
            mCertHolder = certHolder;
            mAliasOperation = this;
        }

        @Override
        protected Boolean doInBackground(Void... params) {
            try {
                KeyChainConnection keyChainConnection = mKeyChainConnectionByProfileId.get(
                        mCertHolder.mProfileId);
                IKeyChainService service = keyChainConnection.getService();
                if (mCertHolder.mDeleted) {
                    byte[] bytes = mCertHolder.mX509Cert.getEncoded();
                    service.installCaCertificate(bytes);
                    return true;
                } else {
                    return service.deleteCaCertificate(mCertHolder.mAlias);
                }
            } catch (CertificateEncodingException | SecurityException | IllegalStateException
                    | RemoteException e) {
                Log.w(TAG, "Error while toggling alias " + mCertHolder.mAlias,
                        e);
                return false;
            }
        }

        @Override
        protected void onPostExecute(Boolean ok) {
            mCertHolder.mTab.postOperationUpdate(ok, mCertHolder);
            mAliasOperation = null;
        }
    }
}
