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