AccountSetupIncomingFragment.java revision 76472ae40cd55d17edb0420e8fc2a7bae60c50de
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.email.activity.setup;
18
19import android.app.Activity;
20import android.content.Context;
21import android.content.Intent;
22import android.content.Loader;
23import android.net.Uri;
24import android.os.Bundle;
25import android.text.Editable;
26import android.text.TextUtils;
27import android.text.TextWatcher;
28import android.text.method.DigitsKeyListener;
29import android.view.LayoutInflater;
30import android.view.View;
31import android.view.ViewGroup;
32import android.view.inputmethod.EditorInfo;
33import android.widget.AdapterView;
34import android.widget.ArrayAdapter;
35import android.widget.EditText;
36import android.widget.Spinner;
37import android.widget.TextView;
38
39import com.android.email.R;
40import com.android.email.activity.UiUtilities;
41import com.android.email.activity.setup.AuthenticationView.AuthenticationCallback;
42import com.android.email.provider.AccountBackupRestore;
43import com.android.email.service.EmailServiceUtils;
44import com.android.email.service.EmailServiceUtils.EmailServiceInfo;
45import com.android.email.view.CertificateSelector;
46import com.android.email.view.CertificateSelector.HostCallback;
47import com.android.emailcommon.Device;
48import com.android.emailcommon.provider.Account;
49import com.android.emailcommon.provider.Credential;
50import com.android.emailcommon.provider.HostAuth;
51import com.android.emailcommon.utility.CertificateRequestor;
52import com.android.emailcommon.utility.Utility;
53import com.android.mail.ui.MailAsyncTaskLoader;
54import com.android.mail.utils.LogUtils;
55
56import java.io.IOException;
57import java.util.ArrayList;
58
59/**
60 * Provides UI for IMAP/POP account settings.
61 *
62 * This fragment is used by AccountSetupIncoming (for creating accounts) and by AccountSettingsXL
63 * (for editing existing accounts).
64 */
65public class AccountSetupIncomingFragment extends AccountServerBaseFragment
66        implements HostCallback, AuthenticationCallback {
67
68    private static final int CERTIFICATE_REQUEST = 0;
69    private static final int SIGN_IN_REQUEST = 1;
70
71    private final static String STATE_KEY_CREDENTIAL = "AccountSetupIncomingFragment.credential";
72    private final static String STATE_KEY_LOADED = "AccountSetupIncomingFragment.loaded";
73
74    private EditText mUsernameView;
75    private AuthenticationView mAuthenticationView;
76    private TextView mAuthenticationLabel;
77    private TextView mServerLabelView;
78    private EditText mServerView;
79    private EditText mPortView;
80    private Spinner mSecurityTypeView;
81    private TextView mDeletePolicyLabelView;
82    private Spinner mDeletePolicyView;
83    private CertificateSelector mClientCertificateSelector;
84    private View mDeviceIdSection;
85    private View mImapPathPrefixSectionView;
86    private EditText mImapPathPrefixView;
87    // Delete policy as loaded from the device
88    private int mLoadedDeletePolicy;
89
90    private TextWatcher mValidationTextWatcher;
91
92    // Support for lifecycle
93    private boolean mLoaded;
94    private String mCacheLoginCredential;
95    private EmailServiceInfo mServiceInfo;
96
97    public static AccountSetupIncomingFragment newInstance(boolean settingsMode) {
98        final AccountSetupIncomingFragment f = new AccountSetupIncomingFragment();
99        f.setArguments(getArgs(settingsMode));
100        return f;
101    }
102
103    // Public no-args constructor needed for fragment re-instantiation
104    public AccountSetupIncomingFragment() {}
105
106    /**
107     * Called to do initial creation of a fragment.  This is called after
108     * {@link #onAttach(Activity)} and before {@link #onActivityCreated(Bundle)}.
109     */
110    @Override
111    public void onCreate(Bundle savedInstanceState) {
112        super.onCreate(savedInstanceState);
113
114        if (savedInstanceState != null) {
115            mCacheLoginCredential = savedInstanceState.getString(STATE_KEY_CREDENTIAL);
116            mLoaded = savedInstanceState.getBoolean(STATE_KEY_LOADED, false);
117        }
118    }
119
120    @Override
121    public View onCreateView(LayoutInflater inflater, ViewGroup container,
122            Bundle savedInstanceState) {
123        final int layoutId = mSettingsMode
124                ? R.layout.account_settings_incoming_fragment
125                : R.layout.account_setup_incoming_fragment;
126
127        final View view = inflater.inflate(layoutId, container, false);
128
129        mUsernameView = UiUtilities.getView(view, R.id.account_username);
130        mServerLabelView = UiUtilities.getView(view, R.id.account_server_label);
131        mServerView = UiUtilities.getView(view, R.id.account_server);
132        mPortView = UiUtilities.getView(view, R.id.account_port);
133        mSecurityTypeView = UiUtilities.getView(view, R.id.account_security_type);
134        mDeletePolicyLabelView = UiUtilities.getView(view, R.id.account_delete_policy_label);
135        mDeletePolicyView = UiUtilities.getView(view, R.id.account_delete_policy);
136        mImapPathPrefixSectionView = UiUtilities.getView(view, R.id.imap_path_prefix_section);
137        mImapPathPrefixView = UiUtilities.getView(view, R.id.imap_path_prefix);
138        mAuthenticationView = UiUtilities.getView(view, R.id.authentication_view);
139        mClientCertificateSelector = UiUtilities.getView(view, R.id.client_certificate_selector);
140        mDeviceIdSection = UiUtilities.getView(view, R.id.device_id_section);
141        // Don't use UiUtilities here. In some configurations this view does not exist, and
142        // UiUtilities throws an exception in this case.
143        mAuthenticationLabel = (TextView)view.findViewById(R.id.authentication_label);
144
145        // Updates the port when the user changes the security type. This allows
146        // us to show a reasonable default which the user can change.
147        mSecurityTypeView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
148            @Override
149            public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
150                updatePortFromSecurityType();
151            }
152
153            @Override
154            public void onNothingSelected(AdapterView<?> arg0) { }
155        });
156
157        // After any text edits, call validateFields() which enables or disables the Next button
158        mValidationTextWatcher = new TextWatcher() {
159            @Override
160            public void afterTextChanged(Editable s) {
161                validateFields();
162            }
163
164            @Override
165            public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
166            @Override
167            public void onTextChanged(CharSequence s, int start, int before, int count) { }
168        };
169        // We're editing an existing account; don't allow modification of the user name
170        if (mSettingsMode) {
171            makeTextViewUneditable(mUsernameView,
172                    getString(R.string.account_setup_username_uneditable_error));
173        }
174        mUsernameView.addTextChangedListener(mValidationTextWatcher);
175        mServerView.addTextChangedListener(mValidationTextWatcher);
176        mPortView.addTextChangedListener(mValidationTextWatcher);
177
178        // Only allow digits in the port field.
179        mPortView.setKeyListener(DigitsKeyListener.getInstance("0123456789"));
180
181        // Additional setup only used while in "settings" mode
182        onCreateViewSettingsMode(view);
183
184        mAuthenticationView.setAuthenticationCallback(this);
185
186        return view;
187    }
188
189    @Override
190    public void onActivityCreated(Bundle savedInstanceState) {
191        super.onActivityCreated(savedInstanceState);
192        mClientCertificateSelector.setHostCallback(this);
193
194        final Context context = getActivity();
195        final SetupDataFragment.SetupDataContainer container =
196                (SetupDataFragment.SetupDataContainer) context;
197        mSetupData = container.getSetupData();
198        final Account account = mSetupData.getAccount();
199        final HostAuth recvAuth = account.getOrCreateHostAuthRecv(mAppContext);
200
201        // Pre-fill info as appropriate
202        if (!mSetupData.isIncomingCredLoaded()) {
203            recvAuth.mLogin = mSetupData.getEmail();
204            AccountSetupCredentialsFragment.populateHostAuthWithResults(context, recvAuth,
205                    mSetupData.getCredentialResults());
206            final String[] emailParts = mSetupData.getEmail().split("@");
207            final String domain = emailParts[1];
208            recvAuth.setConnection(recvAuth.mProtocol, domain, HostAuth.PORT_UNKNOWN,
209                    HostAuth.FLAG_NONE);
210            mSetupData.setIncomingCredLoaded(true);
211        }
212
213        mServiceInfo = EmailServiceUtils.getServiceInfo(mAppContext, recvAuth.mProtocol);
214
215        if (mServiceInfo.offerLocalDeletes) {
216            SpinnerOption deletePolicies[] = {
217                    new SpinnerOption(Account.DELETE_POLICY_NEVER,
218                            context.getString(
219                                    R.string.account_setup_incoming_delete_policy_never_label)),
220                    new SpinnerOption(Account.DELETE_POLICY_ON_DELETE,
221                            context.getString(
222                                    R.string.account_setup_incoming_delete_policy_delete_label)),
223            };
224            ArrayAdapter<SpinnerOption> deletePoliciesAdapter =
225                    new ArrayAdapter<SpinnerOption>(context,
226                            android.R.layout.simple_spinner_item, deletePolicies);
227            deletePoliciesAdapter.setDropDownViewResource(
228                    android.R.layout.simple_spinner_dropdown_item);
229            mDeletePolicyView.setAdapter(deletePoliciesAdapter);
230        }
231
232        // Set up security type spinner
233        ArrayList<SpinnerOption> securityTypes = new ArrayList<SpinnerOption>();
234        securityTypes.add(
235                new SpinnerOption(HostAuth.FLAG_NONE, context.getString(
236                        R.string.account_setup_incoming_security_none_label)));
237        securityTypes.add(
238                new SpinnerOption(HostAuth.FLAG_SSL, context.getString(
239                        R.string.account_setup_incoming_security_ssl_label)));
240        securityTypes.add(
241                new SpinnerOption(HostAuth.FLAG_SSL | HostAuth.FLAG_TRUST_ALL, context.getString(
242                        R.string.account_setup_incoming_security_ssl_trust_certificates_label)));
243        if (mServiceInfo.offerTls) {
244            securityTypes.add(
245                    new SpinnerOption(HostAuth.FLAG_TLS, context.getString(
246                            R.string.account_setup_incoming_security_tls_label)));
247            securityTypes.add(new SpinnerOption(HostAuth.FLAG_TLS | HostAuth.FLAG_TRUST_ALL,
248                    context.getString(R.string
249                            .account_setup_incoming_security_tls_trust_certificates_label)));
250        }
251        ArrayAdapter<SpinnerOption> securityTypesAdapter = new ArrayAdapter<SpinnerOption>(
252                context, android.R.layout.simple_spinner_item, securityTypes);
253        securityTypesAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
254        mSecurityTypeView.setAdapter(securityTypesAdapter);
255
256        configureEditor();
257        loadSettings();
258    }
259
260    /**
261     * Called when the fragment is visible to the user and actively running.
262     */
263    @Override
264    public void onResume() {
265        super.onResume();
266        validateFields();
267    }
268
269    @Override
270    public void onDestroyView() {
271        // Make sure we don't get callbacks after the views are supposed to be destroyed
272        // and also don't hold onto them longer than we need
273        if (mUsernameView != null) {
274            mUsernameView.removeTextChangedListener(mValidationTextWatcher);
275        }
276        mUsernameView = null;
277        mServerLabelView = null;
278        if (mServerView != null) {
279            mServerView.removeTextChangedListener(mValidationTextWatcher);
280        }
281        mServerView = null;
282        if (mPortView != null) {
283            mPortView.removeTextChangedListener(mValidationTextWatcher);
284        }
285        mPortView = null;
286        if (mSecurityTypeView != null) {
287            mSecurityTypeView.setOnItemSelectedListener(null);
288        }
289        mSecurityTypeView = null;
290        mDeletePolicyLabelView = null;
291        mDeletePolicyView = null;
292        mImapPathPrefixSectionView = null;
293        mImapPathPrefixView = null;
294        mDeviceIdSection = null;
295        mClientCertificateSelector = null;
296
297        super.onDestroyView();
298    }
299
300    @Override
301    public void onSaveInstanceState(Bundle outState) {
302        super.onSaveInstanceState(outState);
303
304        outState.putString(STATE_KEY_CREDENTIAL, mCacheLoginCredential);
305        outState.putBoolean(STATE_KEY_LOADED, mLoaded);
306    }
307
308    /**
309     * Configure the editor for the account type
310     */
311    private void configureEditor() {
312        final Account account = mSetupData.getAccount();
313        if (account == null || account.mHostAuthRecv == null) {
314            LogUtils.e(LogUtils.TAG,
315                    "null account or host auth. account null: %b host auth null: %b",
316                    account == null, account == null || account.mHostAuthRecv == null);
317            return;
318        }
319        TextView lastView = mImapPathPrefixView;
320        mBaseScheme = account.mHostAuthRecv.mProtocol;
321        mServerLabelView.setText(R.string.account_setup_incoming_server_label);
322        mServerView.setContentDescription(getResources().getText(
323                R.string.account_setup_incoming_server_label));
324        if (!mServiceInfo.offerPrefix) {
325            mImapPathPrefixSectionView.setVisibility(View.GONE);
326            lastView = mPortView;
327        }
328        if (!mServiceInfo.offerLocalDeletes) {
329            mDeletePolicyLabelView.setVisibility(View.GONE);
330            mDeletePolicyView.setVisibility(View.GONE);
331            mPortView.setImeOptions(EditorInfo.IME_ACTION_NEXT);
332        }
333        lastView.setOnEditorActionListener(mDismissImeOnDoneListener);
334    }
335
336    /**
337     * Load the current settings into the UI
338     */
339    private void loadSettings() {
340        if (mLoaded) return;
341
342        final Account account = mSetupData.getAccount();
343        final HostAuth recvAuth = account.getOrCreateHostAuthRecv(mAppContext);
344        mServiceInfo = EmailServiceUtils.getServiceInfo(mAppContext, recvAuth.mProtocol);
345        mAuthenticationView.setAuthInfo(mServiceInfo.offerOAuth, recvAuth);
346        if (mAuthenticationLabel != null) {
347            if (mServiceInfo.offerOAuth) {
348                mAuthenticationLabel.setText(R.string.authentication_label);
349            } else {
350                mAuthenticationLabel.setText(R.string.password_label);
351            }
352        }
353
354        final String username = recvAuth.mLogin;
355        if (username != null) {
356            //*** For eas?
357            // Add a backslash to the start of the username, but only if the username has no
358            // backslash in it.
359            //if (userName.indexOf('\\') < 0) {
360            //    userName = "\\" + userName;
361            //}
362            mUsernameView.setText(username);
363        }
364
365        if (mServiceInfo.offerPrefix) {
366            final String prefix = recvAuth.mDomain;
367            if (prefix != null && prefix.length() > 0) {
368                mImapPathPrefixView.setText(prefix.substring(1));
369            }
370        }
371
372        // The delete policy is set for all legacy accounts. For POP3 accounts, the user sets
373        // the policy explicitly. For IMAP accounts, the policy is set when the Account object
374        // is created. @see AccountSetupBasics#populateSetupData
375        mLoadedDeletePolicy = account.getDeletePolicy();
376        SpinnerOption.setSpinnerOptionValue(mDeletePolicyView, mLoadedDeletePolicy);
377
378        int flags = recvAuth.mFlags;
379        if (mServiceInfo.defaultSsl) {
380            flags |= HostAuth.FLAG_SSL;
381        }
382        // Strip out any flags that are not related to security type.
383        int securityTypeFlags = (flags & HostAuth.FLAG_TRANSPORTSECURITY_MASK);
384        SpinnerOption.setSpinnerOptionValue(mSecurityTypeView, securityTypeFlags);
385
386        final String hostname = recvAuth.mAddress;
387        if (hostname != null) {
388            mServerView.setText(hostname);
389        }
390
391        final int port = recvAuth.mPort;
392        if (port != HostAuth.PORT_UNKNOWN) {
393            mPortView.setText(Integer.toString(port));
394        } else {
395            updatePortFromSecurityType();
396        }
397
398        mLoadedRecvAuth = recvAuth;
399        mLoaded = true;
400        validateFields();
401    }
402
403    /**
404     * Check the values in the fields and decide if it makes sense to enable the "next" button
405     */
406    private void validateFields() {
407        if (!mLoaded) return;
408        enableNextButton(!TextUtils.isEmpty(mUsernameView.getText())
409                && mAuthenticationView.getAuthValid()
410                && Utility.isServerNameValid(mServerView)
411                && Utility.isPortFieldValid(mPortView));
412
413        mCacheLoginCredential = mUsernameView.getText().toString().trim();
414    }
415
416    private int getPortFromSecurityType(boolean useSsl) {
417        final EmailServiceInfo info = EmailServiceUtils.getServiceInfo(mAppContext,
418                mSetupData.getAccount().mHostAuthRecv.mProtocol);
419        return useSsl ? info.portSsl : info.port;
420    }
421
422    private boolean getSslSelected() {
423        final int securityType =
424                (Integer)((SpinnerOption)mSecurityTypeView.getSelectedItem()).value;
425        return ((securityType & HostAuth.FLAG_SSL) != 0);
426    }
427
428    public void onUseSslChanged(boolean useSsl) {
429        if (mServiceInfo.offerCerts) {
430            final int mode = useSsl ? View.VISIBLE : View.GONE;
431            mClientCertificateSelector.setVisibility(mode);
432            String deviceId = "";
433            try {
434                deviceId = Device.getDeviceId(mAppContext);
435            } catch (IOException e) {
436                // Not required
437            }
438            ((TextView) UiUtilities.getView(getView(), R.id.device_id)).setText(deviceId);
439
440            mDeviceIdSection.setVisibility(mode);
441        }
442    }
443
444    private void updatePortFromSecurityType() {
445        final boolean sslSelected = getSslSelected();
446        final int port = getPortFromSecurityType(sslSelected);
447        mPortView.setText(Integer.toString(port));
448        onUseSslChanged(sslSelected);
449    }
450
451    private static class SaveSettingsLoader extends MailAsyncTaskLoader<Boolean> {
452        private final SetupDataFragment mSetupData;
453        private final boolean mSettingsMode;
454
455        private SaveSettingsLoader(Context context, SetupDataFragment setupData,
456                boolean settingsMode) {
457            super(context);
458            mSetupData = setupData;
459            mSettingsMode = settingsMode;
460        }
461
462        @Override
463        public Boolean loadInBackground() {
464            if (mSettingsMode) {
465                saveSettingsAfterEdit(getContext(), mSetupData);
466            } else {
467                saveSettingsAfterSetup(getContext(), mSetupData);
468            }
469            return true;
470        }
471
472        @Override
473        protected void onDiscardResult(Boolean result) {}
474    }
475
476    @Override
477    public Loader<Boolean> getSaveSettingsLoader() {
478        return new SaveSettingsLoader(mAppContext, mSetupData, mSettingsMode);
479    }
480
481    /**
482     * Entry point from Activity after editing settings and verifying them.  Must be FLOW_MODE_EDIT.
483     * Note, we update account here (as well as the account.mHostAuthRecv) because we edit
484     * account's delete policy here.
485     * Blocking - do not call from UI Thread.
486     */
487    public static void saveSettingsAfterEdit(Context context, SetupDataFragment setupData) {
488        final Account account = setupData.getAccount();
489        account.update(context, account.toContentValues());
490        final Credential cred = account.mHostAuthRecv.mCredential;
491        if (cred != null) {
492            if (cred.isSaved()) {
493                cred.update(context, cred.toContentValues());
494            } else {
495                cred.save(context);
496                account.mHostAuthRecv.mCredentialKey = cred.mId;
497            }
498        }
499        account.mHostAuthRecv.update(context, account.mHostAuthRecv.toContentValues());
500        // Update the backup (side copy) of the accounts
501        AccountBackupRestore.backup(context);
502    }
503
504    /**
505     * Entry point from Activity after entering new settings and verifying them.  For setup mode.
506     */
507    public static void saveSettingsAfterSetup(Context context, SetupDataFragment setupData) {
508        final Account account = setupData.getAccount();
509        final HostAuth recvAuth = account.getOrCreateHostAuthRecv(context);
510        final HostAuth sendAuth = account.getOrCreateHostAuthSend(context);
511
512        // Set the username and password for the outgoing settings to the username and
513        // password the user just set for incoming.  Use the verified host address to try and
514        // pick a smarter outgoing address.
515        final String hostName =
516                AccountSettingsUtils.inferServerName(context, recvAuth.mAddress, null, "smtp");
517        sendAuth.setLogin(recvAuth.mLogin, recvAuth.mPassword);
518        sendAuth.setConnection(sendAuth.mProtocol, hostName, sendAuth.mPort, sendAuth.mFlags);
519    }
520
521    /**
522     * Entry point from Activity, when "next" button is clicked
523     */
524    @Override
525    public void collectUserInput() {
526        final Account account = mSetupData.getAccount();
527
528        // Make sure delete policy is an valid option before using it; otherwise, the results are
529        // indeterminate, I suspect...
530        if (mDeletePolicyView.getVisibility() == View.VISIBLE) {
531            account.setDeletePolicy(
532                    (Integer) ((SpinnerOption) mDeletePolicyView.getSelectedItem()).value);
533        }
534
535        final HostAuth recvAuth = account.getOrCreateHostAuthRecv(mAppContext);
536        final String userName = mUsernameView.getText().toString().trim();
537        final String userPassword = mAuthenticationView.getPassword();
538        recvAuth.setLogin(userName, userPassword);
539        if (!TextUtils.isEmpty(mAuthenticationView.getOAuthProvider())) {
540            Credential cred = recvAuth.getOrCreateCredential(getActivity());
541            cred.mProviderId = mAuthenticationView.getOAuthProvider();
542        }
543
544        final String serverAddress = mServerView.getText().toString().trim();
545        int serverPort;
546        try {
547            serverPort = Integer.parseInt(mPortView.getText().toString().trim());
548        } catch (NumberFormatException e) {
549            serverPort = getPortFromSecurityType(getSslSelected());
550            LogUtils.d(LogUtils.TAG, "Non-integer server port; using '" + serverPort + "'");
551        }
552        final int securityType =
553                (Integer) ((SpinnerOption) mSecurityTypeView.getSelectedItem()).value;
554        recvAuth.setConnection(mBaseScheme, serverAddress, serverPort, securityType);
555        if (mServiceInfo.offerPrefix) {
556            final String prefix = mImapPathPrefixView.getText().toString().trim();
557            recvAuth.mDomain = TextUtils.isEmpty(prefix) ? null : ("/" + prefix);
558        } else {
559            recvAuth.mDomain = null;
560        }
561        recvAuth.mClientCertAlias = mClientCertificateSelector.getCertificate();
562
563        final Callback callback = (Callback) getActivity();
564        callback.onAccountServerUIComplete(SetupDataFragment.CHECK_INCOMING);
565    }
566
567    @Override
568    public boolean haveSettingsChanged() {
569        final boolean deletePolicyChanged;
570
571        // Only verify the delete policy if the control is visible (i.e. is a pop3 account)
572        if (mDeletePolicyView != null && mDeletePolicyView.getVisibility() == View.VISIBLE) {
573            int newDeletePolicy =
574                (Integer)((SpinnerOption)mDeletePolicyView.getSelectedItem()).value;
575            deletePolicyChanged = mLoadedDeletePolicy != newDeletePolicy;
576        } else {
577            deletePolicyChanged = false;
578        }
579
580        return deletePolicyChanged || super.haveSettingsChanged();
581    }
582
583    @Override
584    public void onValidateStateChanged() {
585        validateFields();
586    }
587
588    @Override
589    public void onRequestSignIn() {
590        // Launch the credentials activity.
591        final String protocol =
592                mSetupData.getAccount().getOrCreateHostAuthRecv(mAppContext).mProtocol;
593        final Intent intent = AccountCredentials.getAccountCredentialsIntent(getActivity(),
594                mUsernameView.getText().toString(), protocol);
595        startActivityForResult(intent, SIGN_IN_REQUEST);
596    }
597
598    @Override
599    public void onCertificateRequested() {
600        // XXX reimplement
601        final Intent intent = new Intent(CertificateRequestor.ACTION_REQUEST_CERT);
602        intent.setData(Uri.parse("eas://com.android.emailcommon/certrequest"));
603        startActivityForResult(intent, CERTIFICATE_REQUEST);
604    }
605
606    @Override
607    public void onActivityResult(int requestCode, int resultCode, Intent data) {
608        if (requestCode == CERTIFICATE_REQUEST && resultCode == Activity.RESULT_OK) {
609            final String certAlias = data.getStringExtra(CertificateRequestor.RESULT_ALIAS);
610            if (certAlias != null) {
611                mClientCertificateSelector.setCertificate(certAlias);
612            }
613        } else if (requestCode == SIGN_IN_REQUEST && resultCode == Activity.RESULT_OK) {
614            final Account account = mSetupData.getAccount();
615            final HostAuth recvAuth = account.getOrCreateHostAuthRecv(getActivity());
616            AccountSetupCredentialsFragment.populateHostAuthWithResults(mAppContext, recvAuth,
617                    data.getExtras());
618            mAuthenticationView.setAuthInfo(mServiceInfo.offerOAuth, recvAuth);
619        }
620    }
621}
622