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