Home | History | Annotate | Download | only in setup
      1 package com.android.email.activity.setup;
      2 
      3 import android.content.Context;
      4 import android.os.Bundle;
      5 import android.os.Parcelable;
      6 import android.text.Editable;
      7 import android.text.TextUtils;
      8 import android.text.TextWatcher;
      9 import android.util.AttributeSet;
     10 import android.view.LayoutInflater;
     11 import android.view.View;
     12 import android.view.View.OnClickListener;
     13 import android.widget.EditText;
     14 import android.widget.LinearLayout;
     15 import android.widget.TextView;
     16 
     17 import com.android.email.R;
     18 import com.android.email.activity.UiUtilities;
     19 import com.android.emailcommon.VendorPolicyLoader.OAuthProvider;
     20 import com.android.emailcommon.provider.Credential;
     21 import com.android.emailcommon.provider.HostAuth;
     22 import com.google.common.annotations.VisibleForTesting;
     23 
     24 public class AuthenticationView extends LinearLayout implements OnClickListener {
     25 
     26     private final static String SUPER_STATE = "super_state";
     27     private final static String SAVE_PASSWORD = "save_password";
     28     private final static String SAVE_OFFER_OAUTH = "save_offer_oauth";
     29     private final static String SAVE_USE_OAUTH = "save_use_oauth";
     30     private final static String SAVE_OAUTH_PROVIDER = "save_oauth_provider";
     31 
     32     // Views
     33     private TextView mAuthenticationHeader;
     34     private View mPasswordWrapper;
     35     private View mOAuthWrapper;
     36     private View mNoAuthWrapper;
     37     private TextView mPasswordLabel;
     38     private EditText mPasswordEdit;
     39     private TextView mOAuthLabel;
     40     private View mClearPasswordView;
     41     private View mClearOAuthView;
     42     private View mAddAuthenticationView;
     43 
     44     private boolean mOfferOAuth;
     45     private boolean mUseOAuth;
     46     private String mOAuthProvider;
     47 
     48     private boolean mAuthenticationValid;
     49     private AuthenticationCallback mAuthenticationCallback;
     50 
     51     public interface AuthenticationCallback {
     52         public void onValidateStateChanged();
     53 
     54         public void onRequestSignIn();
     55     }
     56 
     57     public AuthenticationView(Context context) {
     58         this(context, null);
     59     }
     60 
     61     public AuthenticationView(Context context, AttributeSet attrs) {
     62         this(context, attrs, 0);
     63     }
     64 
     65     public AuthenticationView(Context context, AttributeSet attrs, int defstyle) {
     66         super(context, attrs, defstyle);
     67         LayoutInflater.from(context).inflate(R.layout.authentication_view, this, true);
     68     }
     69 
     70 
     71     @Override
     72     public void onFinishInflate() {
     73         super.onFinishInflate();
     74         mPasswordWrapper = UiUtilities.getView(this, R.id.password_wrapper);
     75         mOAuthWrapper = UiUtilities.getView(this, R.id.oauth_wrapper);
     76         mPasswordEdit = UiUtilities.getView(this, R.id.password_edit);
     77         mOAuthLabel =  UiUtilities.getView(this, R.id.oauth_label);
     78         mClearPasswordView = UiUtilities.getView(this, R.id.clear_password);
     79         mClearOAuthView = UiUtilities.getView(this, R.id.clear_oauth);
     80         mAddAuthenticationView = UiUtilities.getView(this, R.id.add_authentication);
     81         // Don't use UiUtilities here, in some configurations, these view doesn't exist and
     82         // UiUtilities throws an exception in this case.
     83         mPasswordLabel = (TextView)findViewById(R.id.password_label);
     84         mAuthenticationHeader = (TextView)findViewById(R.id.authentication_header);
     85 
     86         mClearPasswordView.setOnClickListener(this);
     87         mClearOAuthView.setOnClickListener(this);
     88         mAddAuthenticationView.setOnClickListener(this);
     89 
     90         final TextWatcher validationTextWatcher = new PasswordTextWatcher();
     91         mPasswordEdit.addTextChangedListener(validationTextWatcher);
     92     }
     93 
     94     private class PasswordTextWatcher implements TextWatcher {
     95 
     96         @Override
     97         public void afterTextChanged(Editable s) {
     98             validateFields();
     99         }
    100 
    101         @Override
    102         public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
    103         @Override
    104         public void onTextChanged(CharSequence s, int start, int before, int count) { }
    105     }
    106 
    107     public void setAuthenticationCallback(final AuthenticationCallback host) {
    108         mAuthenticationCallback = host;
    109     }
    110 
    111     public boolean getAuthValid() {
    112         if (mOfferOAuth & mUseOAuth) {
    113             return mOAuthProvider != null;
    114         } else {
    115             return !TextUtils.isEmpty(mPasswordEdit.getText());
    116         }
    117     }
    118 
    119     @VisibleForTesting
    120     public void setPassword(final String password) {
    121         mPasswordEdit.setText(password);
    122     }
    123 
    124     public String getPassword() {
    125         return mPasswordEdit.getText().toString();
    126     }
    127 
    128     public String getOAuthProvider() {
    129         return mOAuthProvider;
    130     }
    131 
    132     private void validateFields() {
    133         boolean valid = getAuthValid();
    134         if (valid != mAuthenticationValid) {
    135             mAuthenticationCallback.onValidateStateChanged();
    136             mAuthenticationValid = valid;
    137         }
    138     }
    139 
    140     public void setAuthInfo(final boolean offerOAuth, final HostAuth hostAuth) {
    141         mOfferOAuth = offerOAuth;
    142 
    143         if (mOfferOAuth) {
    144             final Credential cred = hostAuth.getCredential(getContext());
    145             if (cred != null) {
    146                 // We're authenticated with OAuth.
    147                 mUseOAuth = true;
    148                 mOAuthProvider = cred.mProviderId;
    149             } else {
    150                 mUseOAuth = false;
    151             }
    152         } else {
    153             // We're using a POP or Exchange account, which does not offer oAuth.
    154             mUseOAuth = false;
    155         }
    156         mPasswordEdit.setText(hostAuth.mPassword);
    157 
    158         if (mOfferOAuth && mUseOAuth) {
    159             // We're authenticated with OAuth.
    160             final OAuthProvider provider = AccountSettingsUtils.findOAuthProvider(
    161                     getContext(), mOAuthProvider);
    162             mOAuthLabel.setText(getContext().getString(R.string.signed_in_with_service_label,
    163                     provider.label));
    164         }
    165 
    166         updateVisibility();
    167         validateFields();
    168     }
    169 
    170     private void updateVisibility() {
    171         if (mOfferOAuth) {
    172             if (mAuthenticationHeader != null) {
    173                 mAuthenticationHeader.setVisibility(View.VISIBLE);
    174                 mAuthenticationHeader.setText(R.string.authentication_label);
    175             }
    176             if (mUseOAuth) {
    177                 // We're authenticated with OAuth.
    178                 mOAuthWrapper.setVisibility(View.VISIBLE);
    179                 mPasswordWrapper.setVisibility(View.GONE);
    180                 mAddAuthenticationView.setVisibility(View.GONE);
    181                 if (mPasswordLabel != null) {
    182                     mPasswordLabel.setVisibility(View.VISIBLE);
    183                 }
    184             } else if (!TextUtils.isEmpty(getPassword())) {
    185                 // We're authenticated with a password.
    186                 mOAuthWrapper.setVisibility(View.GONE);
    187                 mPasswordWrapper.setVisibility(View.VISIBLE);
    188                 mAddAuthenticationView.setVisibility(View.GONE);
    189                 if (TextUtils.isEmpty(mPasswordEdit.getText())) {
    190                     mPasswordEdit.requestFocus();
    191                 }
    192                 mClearPasswordView.setVisibility(View.VISIBLE);
    193             } else {
    194                 // We have no authentication, we need to allow either password or oauth.
    195                 mOAuthWrapper.setVisibility(View.GONE);
    196                 mPasswordWrapper.setVisibility(View.GONE);
    197                 mAddAuthenticationView.setVisibility(View.VISIBLE);
    198             }
    199         } else {
    200             // We're using a POP or Exchange account, which does not offer oAuth.
    201             if (mAuthenticationHeader != null) {
    202                 mAuthenticationHeader.setVisibility(View.VISIBLE);
    203                 mAuthenticationHeader.setText(R.string.account_setup_incoming_password_label);
    204             }
    205             mOAuthWrapper.setVisibility(View.GONE);
    206             mPasswordWrapper.setVisibility(View.VISIBLE);
    207             mAddAuthenticationView.setVisibility(View.GONE);
    208             mClearPasswordView.setVisibility(View.GONE);
    209             if (TextUtils.isEmpty(mPasswordEdit.getText())) {
    210                 mPasswordEdit.requestFocus();
    211             }
    212             if (mPasswordLabel != null) {
    213                 mPasswordLabel.setVisibility(View.GONE);
    214             }
    215         }
    216     }
    217 
    218     @Override
    219     public Parcelable onSaveInstanceState() {
    220         Bundle bundle = new Bundle();
    221         bundle.putParcelable(SUPER_STATE, super.onSaveInstanceState());
    222         bundle.putBoolean(SAVE_OFFER_OAUTH, mOfferOAuth);
    223         bundle.putBoolean(SAVE_USE_OAUTH, mUseOAuth);
    224         bundle.putString(SAVE_PASSWORD, getPassword());
    225         bundle.putString(SAVE_OAUTH_PROVIDER, mOAuthProvider);
    226         return bundle;
    227     }
    228 
    229     @Override
    230     public void onRestoreInstanceState(Parcelable parcelable) {
    231         if (parcelable instanceof Bundle) {
    232             Bundle bundle = (Bundle)parcelable;
    233             super.onRestoreInstanceState(bundle.getParcelable(SUPER_STATE));
    234             mOfferOAuth = bundle.getBoolean(SAVE_OFFER_OAUTH);
    235             mUseOAuth = bundle.getBoolean(SAVE_USE_OAUTH);
    236             mOAuthProvider = bundle.getString(SAVE_OAUTH_PROVIDER);
    237 
    238             final String password = bundle.getString(SAVE_PASSWORD);
    239             mPasswordEdit.setText(password);
    240             if (!TextUtils.isEmpty(mOAuthProvider)) {
    241                 final OAuthProvider provider = AccountSettingsUtils.findOAuthProvider(
    242                         getContext(), mOAuthProvider);
    243                 if (provider != null) {
    244                     mOAuthLabel.setText(getContext().getString(R.string.signed_in_with_service_label,
    245                             provider.label));
    246                 }
    247             }
    248             updateVisibility();
    249         }
    250     }
    251 
    252     @Override
    253     public void onClick(View view) {
    254         if (view == mClearPasswordView) {
    255             mPasswordEdit.setText(null);
    256             updateVisibility();
    257             validateFields();
    258         } else if (view == mClearOAuthView) {
    259             mUseOAuth = false;
    260             mOAuthProvider = null;
    261             updateVisibility();
    262             validateFields();
    263         } else if (view == mAddAuthenticationView) {
    264             mAuthenticationCallback.onRequestSignIn();
    265         }
    266     }
    267 }
    268