176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler/*
276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler * Copyright (C) 2014 The Android Open Source Project
376472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler *
476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler * Licensed under the Apache License, Version 2.0 (the "License");
576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler * you may not use this file except in compliance with the License.
676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler * You may obtain a copy of the License at
776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler *
876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler *      http://www.apache.org/licenses/LICENSE-2.0
976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler *
1076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler * Unless required by applicable law or agreed to in writing, software
1176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler * distributed under the License is distributed on an "AS IS" BASIS,
1276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1376472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler * See the License for the specific language governing permissions and
1476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler * limitations under the License.
1576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler */
1676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerpackage com.android.email.activity.setup;
1776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
18658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdonimport android.app.Activity;
1976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport android.content.Context;
2076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport android.content.Intent;
2176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport android.os.Bundle;
2276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport android.text.Editable;
2376472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport android.text.TextUtils;
2476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport android.text.TextWatcher;
2576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport android.text.format.DateUtils;
2676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport android.view.LayoutInflater;
2776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport android.view.View;
2876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport android.view.View.OnClickListener;
2976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport android.view.ViewGroup;
3076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport android.widget.EditText;
31658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdonimport android.widget.TextView;
3276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
3376472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport com.android.email.R;
3476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport com.android.email.activity.UiUtilities;
3576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport com.android.email.service.EmailServiceUtils;
3676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport com.android.email.service.EmailServiceUtils.EmailServiceInfo;
37658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdonimport com.android.email.view.CertificateSelector;
38658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdonimport com.android.email.view.CertificateSelector.HostCallback;
39658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdonimport com.android.emailcommon.Device;
4076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport com.android.emailcommon.VendorPolicyLoader.OAuthProvider;
4176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport com.android.emailcommon.provider.Credential;
4276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport com.android.emailcommon.provider.HostAuth;
43658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdonimport com.android.emailcommon.utility.CertificateRequestor;
4476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport com.android.mail.utils.LogUtils;
4576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
46658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdonimport java.io.IOException;
4776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerimport java.util.List;
4876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
4976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantlerpublic class AccountSetupCredentialsFragment extends AccountSetupFragment
506cbdd5bba0c9c68a3261e54b1cebff48459657d5Tony Mantler        implements OnClickListener, HostCallback {
51658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon
52658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon    private static final int CERTIFICATE_REQUEST = 1000;
53658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon
5476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    private static final String EXTRA_EMAIL = "email";
5576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    private static final String EXTRA_PROTOCOL = "protocol";
5640baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon    private static final String EXTRA_PASSWORD_FAILED = "password_failed";
57ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler    private static final String EXTRA_STANDALONE = "standalone";
5876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
5976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    public static final String EXTRA_PASSWORD = "password";
60f6a945a6cf53327db81be84ef4d16708a864fc18Tony Mantler    public static final String EXTRA_CLIENT_CERT = "certificate";
6176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    public static final String EXTRA_OAUTH_PROVIDER = "provider";
6276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    public static final String EXTRA_OAUTH_ACCESS_TOKEN = "accessToken";
6376472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    public static final String EXTRA_OAUTH_REFRESH_TOKEN = "refreshToken";
6476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    public static final String EXTRA_OAUTH_EXPIRES_IN_SECONDS = "expiresInSeconds";
6576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
6676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    private View mOAuthGroup;
6776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    private View mOAuthButton;
6876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    private EditText mImapPasswordText;
6976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    private EditText mRegularPasswordText;
7076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    private TextWatcher mValidationTextWatcher;
7140baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon    private TextView mPasswordWarningLabel;
7240baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon    private TextView mEmailConfirmationLabel;
7340baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon    private TextView mEmailConfirmation;
74ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler    private CertificateSelector mClientCertificateSelector;
75ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler    private View mDeviceIdSection;
76ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler    private TextView mDeviceId;
77ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler
7876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    private String mEmailAddress;
7976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    private boolean mOfferOAuth;
80658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon    private boolean mOfferCerts;
8176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    private String mProviderId;
829c0463e6b485b3b50d9c6f110a9ece650cd4a692Martin Hibdon    List<OAuthProvider> mOauthProviders;
83ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler
8476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    private Context mAppContext;
85ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler
8676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    private Bundle mResults;
8776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
8876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    public interface Callback extends AccountSetupFragment.Callback {
8976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        void onCredentialsComplete(Bundle results);
9076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    }
9176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
9276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    /**
9376472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler     * Create a new instance of this fragment with the appropriate email and protocol
9476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler     * @param email login address for OAuth purposes
9576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler     * @param protocol protocol of the service we're gathering credentials for
96ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler     * @param clientCert alias of existing client cert
97ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler     * @param passwordFailed true if the password attempt previously failed
98ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler     * @param standalone true if this is not being inserted in the setup flow
9976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler     * @return new fragment instance
10076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler     */
10176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    public static AccountSetupCredentialsFragment newInstance(final String email,
102ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler            final String protocol, final String clientCert, final boolean passwordFailed,
103ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler            final boolean standalone) {
10476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        final AccountSetupCredentialsFragment f = new AccountSetupCredentialsFragment();
105ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler        final Bundle b = new Bundle(5);
10676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        b.putString(EXTRA_EMAIL, email);
10776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        b.putString(EXTRA_PROTOCOL, protocol);
108f6a945a6cf53327db81be84ef4d16708a864fc18Tony Mantler        b.putString(EXTRA_CLIENT_CERT, clientCert);
10940baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon        b.putBoolean(EXTRA_PASSWORD_FAILED, passwordFailed);
110ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler        b.putBoolean(EXTRA_STANDALONE, standalone);
11176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        f.setArguments(b);
11276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        return f;
11376472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    }
11476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
11576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    @Override
11676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
11776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            final Bundle savedInstanceState) {
118ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler        final boolean standalone = getArguments().getBoolean(EXTRA_STANDALONE);
119ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler        final View view;
120ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler        if (standalone) {
121ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler            view = inflater.inflate(R.layout.account_credentials_fragment, container, false);
122ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler            mNextButton = UiUtilities.getView(view, R.id.done);
123ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler            mNextButton.setOnClickListener(this);
124ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler            mPreviousButton = UiUtilities.getView(view, R.id.cancel);
125ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler            mPreviousButton.setOnClickListener(this);
126ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler        } else {
127ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler            // TODO: real headline string instead of sign_in_title
128ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler            view = inflateTemplatedView(inflater, container,
129ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler                    R.layout.account_setup_credentials_fragment, R.string.sign_in_title);
130ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler        }
13176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
13276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        mImapPasswordText = UiUtilities.getView(view, R.id.imap_password);
13376472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        mRegularPasswordText = UiUtilities.getView(view, R.id.regular_password);
13476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        mOAuthGroup = UiUtilities.getView(view, R.id.oauth_group);
135ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler        mOAuthButton = UiUtilities.getView(view, R.id.sign_in_with_oauth);
13676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        mOAuthButton.setOnClickListener(this);
137658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon        mClientCertificateSelector = UiUtilities.getView(view, R.id.client_certificate_selector);
138658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon        mDeviceIdSection = UiUtilities.getView(view, R.id.device_id_section);
139658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon        mDeviceId = UiUtilities.getView(view, R.id.device_id);
14040baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon        mPasswordWarningLabel  = UiUtilities.getView(view, R.id.wrong_password_warning_label);
14140baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon        mEmailConfirmationLabel  = UiUtilities.getView(view, R.id.email_confirmation_label);
14240baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon        mEmailConfirmation  = UiUtilities.getView(view, R.id.email_confirmation);
14340baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon
144f6a945a6cf53327db81be84ef4d16708a864fc18Tony Mantler        mClientCertificateSelector.setHostCallback(this);
145f6a945a6cf53327db81be84ef4d16708a864fc18Tony Mantler        mClientCertificateSelector.setCertificate(getArguments().getString(EXTRA_CLIENT_CERT));
146f6a945a6cf53327db81be84ef4d16708a864fc18Tony Mantler
14776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        // After any text edits, call validateFields() which enables or disables the Next button
14876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        mValidationTextWatcher = new TextWatcher() {
14976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            @Override
15076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            public void afterTextChanged(Editable s) {
15176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                validatePassword();
15276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            }
15376472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
15476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            @Override
15576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
15676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            @Override
15776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            public void onTextChanged(CharSequence s, int start, int before, int count) { }
15876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        };
15976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        mImapPasswordText.addTextChangedListener(mValidationTextWatcher);
16076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        mRegularPasswordText.addTextChangedListener(mValidationTextWatcher);
16176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
16276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        return view;
16376472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    }
16476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
16576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    @Override
16676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    public void onActivityCreated(final Bundle savedInstanceState) {
16776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        super.onActivityCreated(savedInstanceState);
16876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
16976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        mAppContext = getActivity().getApplicationContext();
17076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        mEmailAddress = getArguments().getString(EXTRA_EMAIL);
17176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        final String protocol = getArguments().getString(EXTRA_PROTOCOL);
1729c0463e6b485b3b50d9c6f110a9ece650cd4a692Martin Hibdon        mOauthProviders = AccountSettingsUtils.getAllOAuthProviders(mAppContext);
173658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon        mOfferCerts = true;
17476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        if (protocol != null) {
17576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            final EmailServiceInfo info = EmailServiceUtils.getServiceInfo(mAppContext, protocol);
176658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon            if (info != null) {
1779c0463e6b485b3b50d9c6f110a9ece650cd4a692Martin Hibdon                if (mOauthProviders.size() > 0) {
1789c0463e6b485b3b50d9c6f110a9ece650cd4a692Martin Hibdon                    mOfferOAuth = info.offerOAuth;
1799c0463e6b485b3b50d9c6f110a9ece650cd4a692Martin Hibdon                }
180658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon                mOfferCerts = info.offerCerts;
181658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon            }
1829c0463e6b485b3b50d9c6f110a9ece650cd4a692Martin Hibdon        } else {
1839c0463e6b485b3b50d9c6f110a9ece650cd4a692Martin Hibdon            // For now, we might not know what protocol we're using, so just default to
1849c0463e6b485b3b50d9c6f110a9ece650cd4a692Martin Hibdon            // offering oauth
1859c0463e6b485b3b50d9c6f110a9ece650cd4a692Martin Hibdon            if (mOauthProviders.size() > 0) {
1869c0463e6b485b3b50d9c6f110a9ece650cd4a692Martin Hibdon                mOfferOAuth = true;
1879c0463e6b485b3b50d9c6f110a9ece650cd4a692Martin Hibdon            }
18876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        }
189e96791403e39fa93a73fc285dac537c57ea6ce88Tony Mantler        // We may want to disable OAuth during the new account setup flow, but allow it elsewhere
190e96791403e39fa93a73fc285dac537c57ea6ce88Tony Mantler        final boolean standalone = getArguments().getBoolean(EXTRA_STANDALONE);
191e96791403e39fa93a73fc285dac537c57ea6ce88Tony Mantler        final boolean skipOAuth = !standalone &&
192e96791403e39fa93a73fc285dac537c57ea6ce88Tony Mantler                getActivity().getResources().getBoolean(R.bool.skip_oauth_on_setup);
193e96791403e39fa93a73fc285dac537c57ea6ce88Tony Mantler        mOfferOAuth = mOfferOAuth && !skipOAuth;
194e96791403e39fa93a73fc285dac537c57ea6ce88Tony Mantler
195658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon        mOAuthGroup.setVisibility(mOfferOAuth ? View.VISIBLE : View.GONE);
196658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon        mRegularPasswordText.setVisibility(mOfferOAuth ? View.GONE : View.VISIBLE);
197658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon
198658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon        if (mOfferCerts) {
199658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon            // TODO: Here we always offer certificates for any protocol that allows them (i.e.
200658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon            // Exchange). But they will really only be available if we are using SSL security.
201658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon            // Trouble is, first time through here, we haven't offered the user the choice of
202658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon            // which security type to use.
203658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon            mClientCertificateSelector.setVisibility(mOfferCerts ? View.VISIBLE : View.GONE);
204658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon            mDeviceIdSection.setVisibility(mOfferCerts ? View.VISIBLE : View.GONE);
205658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon            String deviceId = "";
206658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon            try {
207658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon                deviceId = Device.getDeviceId(getActivity());
208658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon            } catch (IOException e) {
209658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon                // Not required
210658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon            }
211658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon            mDeviceId.setText(deviceId);
21276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        }
21340baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon        final boolean passwordFailed = getArguments().getBoolean(EXTRA_PASSWORD_FAILED, false);
21440baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon        setPasswordFailed(passwordFailed);
21576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        validatePassword();
21676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    }
21776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
21876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    @Override
21976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    public void onDestroy() {
22076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        super.onDestroy();
221e8fe78062d5d5ab9df2a75bdf324567ec8b95a65Tony Mantler        if (mImapPasswordText != null) {
222e8fe78062d5d5ab9df2a75bdf324567ec8b95a65Tony Mantler            mImapPasswordText.removeTextChangedListener(mValidationTextWatcher);
223e8fe78062d5d5ab9df2a75bdf324567ec8b95a65Tony Mantler            mImapPasswordText = null;
224e8fe78062d5d5ab9df2a75bdf324567ec8b95a65Tony Mantler        }
225e8fe78062d5d5ab9df2a75bdf324567ec8b95a65Tony Mantler        if (mRegularPasswordText != null) {
226e8fe78062d5d5ab9df2a75bdf324567ec8b95a65Tony Mantler            mRegularPasswordText.removeTextChangedListener(mValidationTextWatcher);
227e8fe78062d5d5ab9df2a75bdf324567ec8b95a65Tony Mantler            mRegularPasswordText = null;
228e8fe78062d5d5ab9df2a75bdf324567ec8b95a65Tony Mantler        }
22976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    }
23076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
23140baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon    public void setPasswordFailed(final boolean failed) {
23240baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon        if (failed) {
23340baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon            mPasswordWarningLabel.setVisibility(View.VISIBLE);
23440baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon            mEmailConfirmationLabel.setVisibility(View.VISIBLE);
23540baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon            mEmailConfirmation.setVisibility(View.VISIBLE);
23640baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon            mEmailConfirmation.setText(mEmailAddress);
23740baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon        } else {
23840baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon            mPasswordWarningLabel.setVisibility(View.GONE);
23940baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon            mEmailConfirmationLabel.setVisibility(View.GONE);
24040baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon            mEmailConfirmation.setVisibility(View.GONE);
24140baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon        }
24240baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon    }
24340baa96c3f5c2a2f50ea243f83bc62c8c65a69b9Martin Hibdon
24476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    public void validatePassword() {
245ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler        setNextButtonEnabled(!TextUtils.isEmpty(getPassword()));
24676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        // Warn (but don't prevent) if password has leading/trailing spaces
24776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        AccountSettingsUtils.checkPasswordSpaces(mAppContext, mImapPasswordText);
24876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        AccountSettingsUtils.checkPasswordSpaces(mAppContext, mRegularPasswordText);
24976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    }
25076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
25176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    @Override
25276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
253658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon        if (requestCode == CERTIFICATE_REQUEST) {
254658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon            if (resultCode == Activity.RESULT_OK) {
255658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon                final String certAlias = data.getStringExtra(CertificateRequestor.RESULT_ALIAS);
256658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon                if (certAlias != null) {
257658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon                    mClientCertificateSelector.setCertificate(certAlias);
258658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon                }
259658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon            } else {
260658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon                LogUtils.e(LogUtils.TAG, "Unknown result from certificate request %d",
261658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon                        resultCode);
262658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon            }
263658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon        } else if (requestCode == OAuthAuthenticationActivity.REQUEST_OAUTH) {
26476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            if (resultCode == OAuthAuthenticationActivity.RESULT_OAUTH_SUCCESS) {
26576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                final String accessToken = data.getStringExtra(
26676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                        OAuthAuthenticationActivity.EXTRA_OAUTH_ACCESS_TOKEN);
26776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                final String refreshToken = data.getStringExtra(
26876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                        OAuthAuthenticationActivity.EXTRA_OAUTH_REFRESH_TOKEN);
26976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                final int expiresInSeconds = data.getIntExtra(
27076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                        OAuthAuthenticationActivity.EXTRA_OAUTH_EXPIRES_IN, 0);
27176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                final Bundle results = new Bundle(4);
27276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                results.putString(EXTRA_OAUTH_PROVIDER, mProviderId);
27376472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                results.putString(EXTRA_OAUTH_ACCESS_TOKEN, accessToken);
27476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                results.putString(EXTRA_OAUTH_REFRESH_TOKEN, refreshToken);
27576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                results.putInt(EXTRA_OAUTH_EXPIRES_IN_SECONDS, expiresInSeconds);
27676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                mResults = results;
27776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                final Callback callback = (Callback) getActivity();
27876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                callback.onCredentialsComplete(results);
27976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            } else if (resultCode == OAuthAuthenticationActivity.RESULT_OAUTH_FAILURE
28076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                    || resultCode == OAuthAuthenticationActivity.RESULT_OAUTH_USER_CANCELED) {
28176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                LogUtils.i(LogUtils.TAG, "Result from oauth %d", resultCode);
28276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            } else {
28376472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                LogUtils.wtf(LogUtils.TAG, "Unknown result code from OAUTH: %d", resultCode);
28476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            }
28576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        } else {
28676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            LogUtils.e(LogUtils.TAG, "Unknown request code for onActivityResult in"
28776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                    + " AccountSetupBasics: %d", requestCode);
28876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        }
28976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    }
29076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
29176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    @Override
29276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    public void onClick(final View view) {
293ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler        final int viewId = view.getId();
294ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler        if (viewId == R.id.sign_in_with_oauth) {
29576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            // TODO currently the only oauth provider we support is google.
29676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            // If we ever have more than 1 oauth provider, then we need to implement some sort
29776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            // of picker UI. For now, just always take the first oauth provider.
2989c0463e6b485b3b50d9c6f110a9ece650cd4a692Martin Hibdon            if (mOauthProviders.size() > 0) {
2999c0463e6b485b3b50d9c6f110a9ece650cd4a692Martin Hibdon                mProviderId = mOauthProviders.get(0).id;
30076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                final Intent i = new Intent(getActivity(), OAuthAuthenticationActivity.class);
30176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                i.putExtra(OAuthAuthenticationActivity.EXTRA_EMAIL_ADDRESS, mEmailAddress);
30276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                i.putExtra(OAuthAuthenticationActivity.EXTRA_PROVIDER, mProviderId);
30376472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                startActivityForResult(i, OAuthAuthenticationActivity.REQUEST_OAUTH);
30476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            }
305ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler        } else if (viewId == R.id.done) {
306ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler            final Callback callback = (Callback) getActivity();
307ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler            callback.onNextButton();
308ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler        } else if (viewId == R.id.cancel) {
309ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler            final Callback callback = (Callback) getActivity();
310ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler            callback.onBackPressed();
311ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler        } else {
312ae980cd685a867b3fecfd38c876fd18d98b7c86bTony Mantler            super.onClick(view);
31376472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        }
31476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    }
31576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
31676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    public String getPassword() {
31776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        if (mOfferOAuth) {
31876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            return mImapPasswordText.getText().toString();
31976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        } else {
32076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            return mRegularPasswordText.getText().toString();
32176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        }
32276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    }
32376472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
32476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    public Bundle getCredentialResults() {
32576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        if (mResults != null) {
32676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            return mResults;
32776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        }
32876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
329f6a945a6cf53327db81be84ef4d16708a864fc18Tony Mantler        final Bundle results = new Bundle(2);
33076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        results.putString(EXTRA_PASSWORD, getPassword());
331f6a945a6cf53327db81be84ef4d16708a864fc18Tony Mantler        results.putString(EXTRA_CLIENT_CERT, getClientCertificate());
33276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        return results;
33376472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    }
33476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler
33576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    public static void populateHostAuthWithResults(final Context context, final HostAuth hostAuth,
33676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            final Bundle results) {
33776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        if (results == null) {
33876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            return;
33976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        }
34076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        final String password = results.getString(AccountSetupCredentialsFragment.EXTRA_PASSWORD);
34176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        if (!TextUtils.isEmpty(password)) {
34276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            hostAuth.mPassword = password;
34376472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            hostAuth.removeCredential();
34476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        } else {
34576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            Credential cred = hostAuth.getOrCreateCredential(context);
34676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            cred.mProviderId = results.getString(
34776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                    AccountSetupCredentialsFragment.EXTRA_OAUTH_PROVIDER);
34876472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            cred.mAccessToken = results.getString(
34976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                    AccountSetupCredentialsFragment.EXTRA_OAUTH_ACCESS_TOKEN);
35076472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            cred.mRefreshToken = results.getString(
35176472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                    AccountSetupCredentialsFragment.EXTRA_OAUTH_REFRESH_TOKEN);
35276472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            cred.mExpiration = System.currentTimeMillis()
35376472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                    + results.getInt(
35476472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                    AccountSetupCredentialsFragment.EXTRA_OAUTH_EXPIRES_IN_SECONDS, 0)
35576472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler                    * DateUtils.SECOND_IN_MILLIS;
35676472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler            hostAuth.mPassword = null;
35776472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler        }
358f6a945a6cf53327db81be84ef4d16708a864fc18Tony Mantler        hostAuth.mClientCertAlias = results.getString(EXTRA_CLIENT_CERT);
35976472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler    }
360658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon
361658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon    public String getClientCertificate() {
362658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon        return mClientCertificateSelector.getCertificate();
363658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon    }
364658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon
365658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon    @Override
366658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon    public void onCertificateRequested() {
367f765f9b976222a8a0e45d4b04883566ecf355937Tony Mantler        final Intent intent = new Intent(getString(R.string.intent_exchange_cert_action));
368f765f9b976222a8a0e45d4b04883566ecf355937Tony Mantler        intent.setData(CertificateRequestor.CERTIFICATE_REQUEST_URI);
369f765f9b976222a8a0e45d4b04883566ecf355937Tony Mantler        // We don't set EXTRA_HOST or EXTRA_PORT here because we don't know the final host/port
370f765f9b976222a8a0e45d4b04883566ecf355937Tony Mantler        // that we're connecting to yet, and autodiscover might point us somewhere else
371658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon        startActivityForResult(intent, CERTIFICATE_REQUEST);
372658231e2070f74f201d1c106cdd55909f2fe1233Martin Hibdon    }
37376472ae40cd55d17edb0420e8fc2a7bae60c50deTony Mantler}
374