155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler/*
255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler * Copyright (C) 2010 The Android Open Source Project
355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler *
455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler * Licensed under the Apache License, Version 2.0 (the "License");
555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler * you may not use this file except in compliance with the License.
655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler * You may obtain a copy of the License at
755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler *
855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler *      http://www.apache.org/licenses/LICENSE-2.0
955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler *
1055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler * Unless required by applicable law or agreed to in writing, software
1155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler * distributed under the License is distributed on an "AS IS" BASIS,
1255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler * See the License for the specific language governing permissions and
1455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler * limitations under the License.
1555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler */
1655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
1755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadlerpackage com.android.email.activity.setup;
1855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
19fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadlerimport android.app.Activity;
2055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadlerimport android.app.AlertDialog;
2155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadlerimport android.app.Dialog;
2255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadlerimport android.app.DialogFragment;
2355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadlerimport android.app.Fragment;
2455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadlerimport android.app.FragmentManager;
2555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadlerimport android.app.ProgressDialog;
2655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadlerimport android.content.Context;
2755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadlerimport android.content.DialogInterface;
2855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadlerimport android.os.AsyncTask;
2955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadlerimport android.os.Bundle;
305a2d7da136f2f0519dabacfe9b5a5e224f8be5e8Ben Komaloimport android.text.TextUtils;
3155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
3235b0e95ca795e17b6dc8dd98c7ab847d65d9aa0cMarc Blankimport com.android.email.R;
3335b0e95ca795e17b6dc8dd98c7ab847d65d9aa0cMarc Blankimport com.android.email.mail.Sender;
3435b0e95ca795e17b6dc8dd98c7ab847d65d9aa0cMarc Blankimport com.android.email.mail.Store;
35e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blankimport com.android.email.service.EmailServiceUtils;
36e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blankimport com.android.email.service.EmailServiceUtils.EmailServiceInfo;
3735b0e95ca795e17b6dc8dd98c7ab847d65d9aa0cMarc Blankimport com.android.emailcommon.Logging;
3835b0e95ca795e17b6dc8dd98c7ab847d65d9aa0cMarc Blankimport com.android.emailcommon.mail.MessagingException;
3935b0e95ca795e17b6dc8dd98c7ab847d65d9aa0cMarc Blankimport com.android.emailcommon.provider.Account;
4035b0e95ca795e17b6dc8dd98c7ab847d65d9aa0cMarc Blankimport com.android.emailcommon.provider.HostAuth;
4135b0e95ca795e17b6dc8dd98c7ab847d65d9aa0cMarc Blankimport com.android.emailcommon.provider.Policy;
4235b0e95ca795e17b6dc8dd98c7ab847d65d9aa0cMarc Blankimport com.android.emailcommon.service.EmailServiceProxy;
4335b0e95ca795e17b6dc8dd98c7ab847d65d9aa0cMarc Blankimport com.android.emailcommon.utility.Utility;
44560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedyimport com.android.mail.utils.LogUtils;
4535b0e95ca795e17b6dc8dd98c7ab847d65d9aa0cMarc Blank
4655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler/**
4755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler * Check incoming or outgoing settings, or perform autodiscovery.
4855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler *
4955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler * There are three components that work together.  1. This fragment is retained and non-displayed,
5055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler * and controls the overall process.  2. An AsyncTask that works with the stores/services to
5155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler * check the accounts settings.  3. A stateless progress dialog (which will be recreated on
5255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler * orientation changes).
5355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler *
5455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler * There are also two lightweight error dialogs which are used for notification of terminal
5555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler * conditions.
5655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler */
5755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadlerpublic class AccountCheckSettingsFragment extends Fragment {
5849518bb3605d6c8e3cc4801c452e4f8f63220f44Makoto Onuki
59fead9986c1ce920e669aadddb0b993ff4cff56b8Martin Hibdon    public final static String TAG = "AccountCheckStgFrag";
6055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
6155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    // State
6255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    private final static int STATE_START = 0;
6355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    private final static int STATE_CHECK_AUTODISCOVER = 1;
6455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    private final static int STATE_CHECK_INCOMING = 2;
6555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    private final static int STATE_CHECK_OUTGOING = 3;
662731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    private final static int STATE_CHECK_OK = 4;                    // terminal
672731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    private final static int STATE_CHECK_SHOW_SECURITY = 5;         // terminal
682731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    private final static int STATE_CHECK_ERROR = 6;                 // terminal
692731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    private final static int STATE_AUTODISCOVER_AUTH_DIALOG = 7;    // terminal
702731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    private final static int STATE_AUTODISCOVER_RESULT = 8;         // terminal
7155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    private int mState = STATE_START;
7226cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler    private SetupData mSetupData;
7355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
7455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    // Support for UI
7555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    private boolean mAttached;
76f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank    private boolean mPaused = false;
7755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    private CheckingDialog mCheckingDialog;
78715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo    private MessagingException mProgressException;
79fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler
8055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    // Support for AsyncTask and account checking
8155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    AccountCheckTask mAccountCheckTask;
822731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler
832731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    // Result codes returned by onCheckSettingsComplete.
842731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    /** Check settings returned successfully */
852731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    public final static int CHECK_SETTINGS_OK = 0;
862731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    /** Check settings failed due to connection, authentication, or other server error */
872731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    public final static int CHECK_SETTINGS_SERVER_ERROR = 1;
882731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    /** Check settings failed due to user refusing to accept security requirements */
892731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    public final static int CHECK_SETTINGS_SECURITY_USER_DENY = 2;
90715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo    /** Check settings failed due to certificate being required - user needs to pick immediately. */
91715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo    public final static int CHECK_SETTINGS_CLIENT_CERTIFICATE_NEEDED = 3;
922731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler
932731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    // Result codes returned by onAutoDiscoverComplete.
942731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    /** AutoDiscover completed successfully with server setup data */
952731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    public final static int AUTODISCOVER_OK = 0;
962731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    /** AutoDiscover completed with no data (no server or AD not supported) */
972731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    public final static int AUTODISCOVER_NO_DATA = 1;
982731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    /** AutoDiscover reported authentication error */
992731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    public final static int AUTODISCOVER_AUTHENTICATION = 2;
1002731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler
10155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    /**
102fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler     * Callback interface for any target or activity doing account check settings
103fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler     */
104fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler    public interface Callbacks {
105fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler        /**
1062731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler         * Called when CheckSettings completed
1072731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler         * @param result check settings result code - success is CHECK_SETTINGS_OK
108fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler         */
10926cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        public void onCheckSettingsComplete(int result, SetupData setupData);
1102731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler
1112731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler        /**
1122731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler         * Called when autodiscovery completes.
1132731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler         * @param result autodiscovery result code - success is AUTODISCOVER_OK
1142731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler         */
11526cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        public void onAutoDiscoverComplete(int result, SetupData setupData);
116fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler    }
1172731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler
1187985b43ab7310f76c170266da346f993d2f86051Paul Westbrook    // Public no-args constructor needed for fragment re-instantiation
1197985b43ab7310f76c170266da346f993d2f86051Paul Westbrook    public AccountCheckSettingsFragment() {}
1207985b43ab7310f76c170266da346f993d2f86051Paul Westbrook
121fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler    /**
12255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * Create a retained, invisible fragment that checks accounts
12355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     *
12455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * @param mode incoming or outgoing
12555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     */
12655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    public static AccountCheckSettingsFragment newInstance(int mode, Fragment parentFragment) {
127ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler        final AccountCheckSettingsFragment f = new AccountCheckSettingsFragment();
12855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        f.setTargetFragment(parentFragment, mode);
12955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        return f;
13055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    }
13155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
13255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    /**
13355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * Fragment initialization.  Because we never implement onCreateView, and call
13455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * setRetainInstance here, this creates an invisible, persistent, "worker" fragment.
13555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     */
13655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    @Override
13755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    public void onCreate(Bundle savedInstanceState) {
13855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        super.onCreate(savedInstanceState);
13955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        setRetainInstance(true);
14055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    }
14155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
14255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    /**
14355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * This is called when the Fragment's Activity is ready to go, after
14455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * its content view has been installed; it is called both after
14555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * the initial fragment creation and after the fragment is re-attached
14655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * to a new activity.
14755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     */
14855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    @Override
14955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    public void onActivityCreated(Bundle savedInstanceState) {
15055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        super.onActivityCreated(savedInstanceState);
15155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        mAttached = true;
15255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
15355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        // If this is the first time, start the AsyncTask
15455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        if (mAccountCheckTask == null) {
155ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler            final int checkMode = getTargetRequestCode();
15626cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler            final SetupData.SetupDataContainer container =
15726cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler                    (SetupData.SetupDataContainer) getActivity();
15826cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler            mSetupData = container.getSetupData();
15926cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler            final Account checkAccount = mSetupData.getAccount();
16055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            mAccountCheckTask = (AccountCheckTask)
1612731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    new AccountCheckTask(checkMode, checkAccount)
162bc2eaadde987044027b57d241e635de014bdb8baMakoto Onuki                    .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
16355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        }
164f946ff001914abce9ea06b1ceecd29cdb7e10ef3Andy Stadler    }
165f946ff001914abce9ea06b1ceecd29cdb7e10ef3Andy Stadler
166f946ff001914abce9ea06b1ceecd29cdb7e10ef3Andy Stadler    /**
167f946ff001914abce9ea06b1ceecd29cdb7e10ef3Andy Stadler     * When resuming, restart the progress/error UI if necessary by re-reporting previous values
168f946ff001914abce9ea06b1ceecd29cdb7e10ef3Andy Stadler     */
169f946ff001914abce9ea06b1ceecd29cdb7e10ef3Andy Stadler    @Override
170f946ff001914abce9ea06b1ceecd29cdb7e10ef3Andy Stadler    public void onResume() {
171f946ff001914abce9ea06b1ceecd29cdb7e10ef3Andy Stadler        super.onResume();
172f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank        mPaused = false;
17355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
17455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        if (mState != STATE_START) {
175715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            reportProgress(mState, mProgressException);
17655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        }
17755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    }
17855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
179f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank    @Override
180f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank    public void onPause() {
181f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank        super.onPause();
182f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank        mPaused = true;
183f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank    }
184f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank
18555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    /**
18655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * This is called when the fragment is going away.  It is NOT called
18755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * when the fragment is being propagated between activity instances.
18855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     */
18955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    @Override
19055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    public void onDestroy() {
19155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        super.onDestroy();
192f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank        if (mAccountCheckTask != null) {
193f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank            Utility.cancelTaskInterrupt(mAccountCheckTask);
194f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank            mAccountCheckTask = null;
195f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank        }
1969460be06aab728e69fc908bb55f26ab19f33aa8cTony Mantler        // Make doubly sure that the dialog isn't pointing at us before we're removed from the
1979460be06aab728e69fc908bb55f26ab19f33aa8cTony Mantler        // fragment manager
1989460be06aab728e69fc908bb55f26ab19f33aa8cTony Mantler        final Fragment f = getFragmentManager().findFragmentByTag(CheckingDialog.TAG);
1999460be06aab728e69fc908bb55f26ab19f33aa8cTony Mantler        if (f != null) {
2009460be06aab728e69fc908bb55f26ab19f33aa8cTony Mantler            f.setTargetFragment(null, 0);
2019460be06aab728e69fc908bb55f26ab19f33aa8cTony Mantler        }
20255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    }
20355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
20455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    /**
20555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * This is called right before the fragment is detached from its current activity instance.
20655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * All reporting and callbacks are halted until we reattach.
20755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     */
20855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    @Override
20955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    public void onDetach() {
21055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        super.onDetach();
21155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        mAttached = false;
21255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    }
21355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
21455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    /**
21555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * The worker (AsyncTask) will call this (in the UI thread) to report progress.  If we are
21655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * attached to an activity, update the progress immediately;  If not, simply hold the
21755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * progress for later.
21855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * @param newState The new progress state being reported
21955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     */
220715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo    private void reportProgress(int newState, MessagingException ex) {
22155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        mState = newState;
222715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo        mProgressException = ex;
22355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
22455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        // If we are attached, create, recover, and/or update the dialog
225f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank        if (mAttached && !mPaused) {
226ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler            final FragmentManager fm = getFragmentManager();
22755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
2282731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler            switch (newState) {
2292731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                case STATE_CHECK_OK:
2302731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    // immediately terminate, clean up, and report back
2312731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    // 1. get rid of progress dialog (if any)
2322731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    recoverAndDismissCheckingDialog();
2332731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    // 2. exit self
2342731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    fm.popBackStack();
2352731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    // 3. report OK back to target fragment or activity
23626cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler                    getCallbackTarget().onCheckSettingsComplete(CHECK_SETTINGS_OK, mSetupData);
2372731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    break;
2382731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                case STATE_CHECK_SHOW_SECURITY:
2392731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    // 1. get rid of progress dialog (if any)
2402731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    recoverAndDismissCheckingDialog();
241f946ff001914abce9ea06b1ceecd29cdb7e10ef3Andy Stadler                    // 2. launch the error dialog, if needed
242f946ff001914abce9ea06b1ceecd29cdb7e10ef3Andy Stadler                    if (fm.findFragmentByTag(SecurityRequiredDialog.TAG) == null) {
243715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                        String message = ex.getMessage();
244715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                        if (message != null) {
245715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                            message = message.trim();
246715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                        }
247f946ff001914abce9ea06b1ceecd29cdb7e10ef3Andy Stadler                        SecurityRequiredDialog securityRequiredDialog =
248715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                                SecurityRequiredDialog.newInstance(this, message);
24931e25767918193217c884db72aaa98e50a4957d3Dianne Hackborn                        fm.beginTransaction()
250f946ff001914abce9ea06b1ceecd29cdb7e10ef3Andy Stadler                                .add(securityRequiredDialog, SecurityRequiredDialog.TAG)
251f946ff001914abce9ea06b1ceecd29cdb7e10ef3Andy Stadler                                .commit();
252f946ff001914abce9ea06b1ceecd29cdb7e10ef3Andy Stadler                    }
2532731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    break;
2542731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                case STATE_CHECK_ERROR:
2552731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                case STATE_AUTODISCOVER_AUTH_DIALOG:
2562731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    // 1. get rid of progress dialog (if any)
2572731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    recoverAndDismissCheckingDialog();
258f946ff001914abce9ea06b1ceecd29cdb7e10ef3Andy Stadler                    // 2. launch the error dialog, if needed
259f946ff001914abce9ea06b1ceecd29cdb7e10ef3Andy Stadler                    if (fm.findFragmentByTag(ErrorDialog.TAG) == null) {
260715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                        ErrorDialog errorDialog = ErrorDialog.newInstance(
261715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                                getActivity(), this, mProgressException);
26231e25767918193217c884db72aaa98e50a4957d3Dianne Hackborn                        fm.beginTransaction()
263f946ff001914abce9ea06b1ceecd29cdb7e10ef3Andy Stadler                                .add(errorDialog, ErrorDialog.TAG)
264f946ff001914abce9ea06b1ceecd29cdb7e10ef3Andy Stadler                                .commit();
265f946ff001914abce9ea06b1ceecd29cdb7e10ef3Andy Stadler                    }
2662731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    break;
2672731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                case STATE_AUTODISCOVER_RESULT:
268ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                    final HostAuth autoDiscoverResult = ((AutoDiscoverResults) ex).mHostAuth;
2692731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    // 1. get rid of progress dialog (if any)
2702731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    recoverAndDismissCheckingDialog();
2712731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    // 2. exit self
2722731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    fm.popBackStack();
2732731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    // 3. report back to target fragment or activity
2742731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    getCallbackTarget().onAutoDiscoverComplete(
27526cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler                            (autoDiscoverResult != null) ? AUTODISCOVER_OK : AUTODISCOVER_NO_DATA,
27626cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler                            mSetupData);
2772731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    break;
2782731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                default:
2792731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    // Display a normal progress message
2802731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    mCheckingDialog = (CheckingDialog) fm.findFragmentByTag(CheckingDialog.TAG);
2812731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler
2822731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    if (mCheckingDialog == null) {
2832731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                        mCheckingDialog = CheckingDialog.newInstance(this, mState);
28431e25767918193217c884db72aaa98e50a4957d3Dianne Hackborn                        fm.beginTransaction()
2852731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                                .add(mCheckingDialog, CheckingDialog.TAG)
2862731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                                .commit();
2872731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    } else {
2882731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                        mCheckingDialog.updateProgress(mState);
2892731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    }
2902731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    break;
29155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            }
29255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        }
29355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    }
29455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
29555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    /**
296fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler     * Find the callback target, either a target fragment or the activity
297fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler     */
298fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler    private Callbacks getCallbackTarget() {
299ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler        final Fragment target = getTargetFragment();
300fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler        if (target instanceof Callbacks) {
301fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler            return (Callbacks) target;
302fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler        }
303fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler        Activity activity = getActivity();
304fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler        if (activity instanceof Callbacks) {
305fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler            return (Callbacks) activity;
306fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler        }
307fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler        throw new IllegalStateException();
3082731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    }
309fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler
310fd14496c494a0d38c35c3788c9cc55f1984592e4Andrew Stadler    /**
31155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * Recover and dismiss the progress dialog fragment
31255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     */
31355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    private void recoverAndDismissCheckingDialog() {
31455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        if (mCheckingDialog == null) {
31555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            mCheckingDialog = (CheckingDialog)
31655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    getFragmentManager().findFragmentByTag(CheckingDialog.TAG);
31755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        }
31855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        if (mCheckingDialog != null) {
3199460be06aab728e69fc908bb55f26ab19f33aa8cTony Mantler            // TODO: dismissAllowingStateLoss() can cause the fragment to return later as a zombie
3209460be06aab728e69fc908bb55f26ab19f33aa8cTony Mantler            // after the fragment manager restores state, if it happens that this call is executed
3219460be06aab728e69fc908bb55f26ab19f33aa8cTony Mantler            // after the state is saved. Figure out a way to clean this up later. b/11435698
322a685d3b0191f472de9902b3d5590fc3e8408400cAndy Stadler            mCheckingDialog.dismissAllowingStateLoss();
32355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            mCheckingDialog = null;
32455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        }
32555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    }
32655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
32755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    /**
32855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * This is called when the user clicks "cancel" on the progress dialog.  Shuts everything
32955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * down and dismisses everything.
33055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * This should cause us to remain in the current screen (not accepting the settings)
33155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     */
33255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    private void onCheckingDialogCancel() {
33355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        // 1. kill the checker
33455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        Utility.cancelTaskInterrupt(mAccountCheckTask);
33555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        mAccountCheckTask = null;
33655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        // 2. kill self with no report - this is "cancel"
3377683a431173d242e55afced34175e1178764e757Ben Komalo        finish();
33855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    }
33955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
340715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo    private void onEditCertificateOk() {
34126cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler        getCallbackTarget().onCheckSettingsComplete(CHECK_SETTINGS_CLIENT_CERTIFICATE_NEEDED,
34226cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler                mSetupData);
343715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo        finish();
344715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo    }
345715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo
34655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    /**
34755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * This is called when the user clicks "edit" from the error dialog.  The error dialog
34855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * should have already dismissed itself.
3492731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler     * Depending on the context, the target will remain in the current activity (e.g. editing
3502731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler     * settings) or return to its own parent (e.g. enter new credentials).
35155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     */
35255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    private void onErrorDialogEditButton() {
3535f830f8608eaea6a512a97983b124fd13836a59fAndy Stadler        // 1. handle "edit" - notify callback that we had a problem with the test
354ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler        final Callbacks callbackTarget = getCallbackTarget();
3552731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler        if (mState == STATE_AUTODISCOVER_AUTH_DIALOG) {
3562731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler            // report auth error to target fragment or activity
3577df98d0a6d0a3c67b467e9ff2066970e645957b8Paul Sliwowski            callbackTarget.onAutoDiscoverComplete(CHECK_SETTINGS_SERVER_ERROR, mSetupData);
3582731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler        } else {
3592731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler            // report check settings failure to target fragment or activity
36026cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler            callbackTarget.onCheckSettingsComplete(CHECK_SETTINGS_SERVER_ERROR, mSetupData);
3612731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler        }
362715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo        finish();
363715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo    }
364715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo
365715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo    /** Kill self if not already killed. */
366715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo    private void finish() {
367ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler        final FragmentManager fm = getFragmentManager();
3685f830f8608eaea6a512a97983b124fd13836a59fAndy Stadler        if (fm != null) {
3695f830f8608eaea6a512a97983b124fd13836a59fAndy Stadler            fm.popBackStack();
3705f830f8608eaea6a512a97983b124fd13836a59fAndy Stadler        }
37155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    }
37255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
37355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    /**
37455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * This is called when the user clicks "ok" or "cancel" on the "security required" dialog.
37555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * Shuts everything down and dismisses everything, and reports the result appropriately.
37655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     */
3772731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    private void onSecurityRequiredDialogResultOk(boolean okPressed) {
3782731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler        // 1. handle OK/cancel - notify that security is OK and we can proceed
379ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler        final Callbacks callbackTarget = getCallbackTarget();
3802731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler        callbackTarget.onCheckSettingsComplete(
38126cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler                okPressed ? CHECK_SETTINGS_OK : CHECK_SETTINGS_SECURITY_USER_DENY, mSetupData);
3822731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler
383d8f1d8f2ff75502b86c8ce7b8a738eddc731a607Andy Stadler        // 2. kill self if not already killed by callback
384ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler        final FragmentManager fm = getFragmentManager();
385d8f1d8f2ff75502b86c8ce7b8a738eddc731a607Andy Stadler        if (fm != null) {
386d8f1d8f2ff75502b86c8ce7b8a738eddc731a607Andy Stadler            fm.popBackStack();
387d8f1d8f2ff75502b86c8ce7b8a738eddc731a607Andy Stadler        }
38855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    }
38955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
39055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    /**
3912731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler     * This exception class is used to report autodiscover results via the reporting mechanism.
3922731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler     */
3932731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    public static class AutoDiscoverResults extends MessagingException {
3942731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler        public final HostAuth mHostAuth;
3952731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler
3962731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler        /**
3972731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler         * @param authenticationError true if auth failure, false for result (or no response)
3982731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler         * @param hostAuth null for "no autodiscover", non-null for server info to return
3992731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler         */
4002731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler        public AutoDiscoverResults(boolean authenticationError, HostAuth hostAuth) {
4012731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler            super(null);
4022731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler            if (authenticationError) {
4032731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                mExceptionType = AUTODISCOVER_AUTHENTICATION_FAILED;
4042731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler            } else {
4052731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                mExceptionType = AUTODISCOVER_AUTHENTICATION_RESULT;
4062731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler            }
4072731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler            mHostAuth = hostAuth;
4082731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler        }
4092731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    }
4102731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler
4112731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler    /**
41255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * This AsyncTask does the actual account checking
41355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     *
41455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * TODO: It would be better to remove the UI complete from here (the exception->string
41555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * conversions).
41655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     */
41755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    private class AccountCheckTask extends AsyncTask<Void, Integer, MessagingException> {
41855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
41955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        final Context mContext;
42055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        final int mMode;
421a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy        final Account mAccount;
42255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        final String mStoreHost;
4232731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler        final String mCheckEmail;
4242731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler        final String mCheckPassword;
42555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
42655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        /**
42755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler         * Create task and parameterize it
42855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler         * @param mode bits request operations
4292731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler         * @param checkAccount account holding values to be checked
43055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler         */
4312731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler        public AccountCheckTask(int mode, Account checkAccount) {
43255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            mContext = getActivity().getApplicationContext();
43355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            mMode = mode;
434a50fc99b0c433f0cde31ba1c7ab87fb9ea86345dTodd Kennedy            mAccount = checkAccount;
4352731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler            mStoreHost = checkAccount.mHostAuthRecv.mAddress;
4362731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler            mCheckEmail = checkAccount.mEmailAddress;
4372731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler            mCheckPassword = checkAccount.mHostAuthRecv.mPassword;
43855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        }
43955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
44055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        @Override
44155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        protected MessagingException doInBackground(Void... params) {
44255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            try {
44355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                if ((mMode & SetupData.CHECK_AUTODISCOVER) != 0) {
44455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    if (isCancelled()) return null;
44555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    publishProgress(STATE_CHECK_AUTODISCOVER);
446560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy                    LogUtils.d(Logging.LOG_TAG, "Begin auto-discover for " + mCheckEmail);
447ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                    final Store store = Store.getInstance(mAccount, mContext);
448ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                    final Bundle result = store.autoDiscover(mContext, mCheckEmail, mCheckPassword);
4492731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    // Result will be one of:
4502731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    //  null: remote exception - proceed to manual setup
4512731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    //  MessagingException.AUTHENTICATION_FAILED: username/password rejected
4522731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    //  Other error: proceed to manual setup
4532731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    //  No error: return autodiscover results
4542731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    if (result == null) {
4552731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                        return new AutoDiscoverResults(false, null);
4562731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    }
4572731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    int errorCode =
4582731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                            result.getInt(EmailServiceProxy.AUTO_DISCOVER_BUNDLE_ERROR_CODE);
459c196e05ee15ba72ed993bf498897c2be121ccad1Marc Blank                    if (errorCode == MessagingException.AUTODISCOVER_AUTHENTICATION_FAILED) {
4602731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                        return new AutoDiscoverResults(true, null);
4612731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    } else if (errorCode != MessagingException.NO_ERROR) {
4622731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                        return new AutoDiscoverResults(false, null);
4632731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    } else {
464ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                        HostAuth serverInfo =
4652731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                            result.getParcelable(EmailServiceProxy.AUTO_DISCOVER_BUNDLE_HOST_AUTH);
4662731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                        return new AutoDiscoverResults(false, serverInfo);
4672731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    }
46855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                }
46955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
47055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                // Check Incoming Settings
47155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                if ((mMode & SetupData.CHECK_INCOMING) != 0) {
47255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    if (isCancelled()) return null;
473560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy                    LogUtils.d(Logging.LOG_TAG, "Begin check of incoming email settings");
47455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    publishProgress(STATE_CHECK_INCOMING);
475ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                    final Store store = Store.getInstance(mAccount, mContext);
476ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                    final Bundle bundle = store.checkSettings();
477ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                    if (bundle == null) {
478ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                        return new MessagingException(MessagingException.UNSPECIFIED_EXCEPTION);
479ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                    }
480ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                    mAccount.mProtocolVersion = bundle.getString(
481ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                            EmailServiceProxy.VALIDATE_BUNDLE_PROTOCOL_VERSION);
482ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                    int resultCode = bundle.getInt(EmailServiceProxy.VALIDATE_BUNDLE_RESULT_CODE);
483ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                    final String redirectAddress = bundle.getString(
484ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                            EmailServiceProxy.VALIDATE_BUNDLE_REDIRECT_ADDRESS, null);
485ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                    if (redirectAddress != null) {
486ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                        mAccount.mHostAuthRecv.mAddress = redirectAddress;
487ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                    }
488ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                    // Only show "policies required" if this is a new account setup
489ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                    if (resultCode == MessagingException.SECURITY_POLICIES_REQUIRED &&
490ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                            mAccount.isSaved()) {
491ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                        resultCode = MessagingException.NO_ERROR;
49255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    }
49355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    if (resultCode == MessagingException.SECURITY_POLICIES_REQUIRED) {
49426cd5e024c6af8ff9c8558325dd0930c9aacb370Tony Mantler                        mSetupData.setPolicy((Policy)bundle.getParcelable(
49555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                                EmailServiceProxy.VALIDATE_BUNDLE_POLICY_SET));
496265530723b8c008f6bc23b1723f4de706a3e9556Marc Blank                        return new MessagingException(resultCode, mStoreHost);
497265530723b8c008f6bc23b1723f4de706a3e9556Marc Blank                    } else if (resultCode == MessagingException.SECURITY_POLICIES_UNSUPPORTED) {
498ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                        final Policy policy = bundle.getParcelable(
499f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank                                EmailServiceProxy.VALIDATE_BUNDLE_POLICY_SET);
500ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                        final String unsupported = policy.mProtocolPoliciesUnsupported;
501ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                        final String[] data =
502ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                                unsupported.split("" + Policy.POLICY_STRING_DELIMITER);
503265530723b8c008f6bc23b1723f4de706a3e9556Marc Blank                        return new MessagingException(resultCode, mStoreHost, data);
504265530723b8c008f6bc23b1723f4de706a3e9556Marc Blank                    } else if (resultCode != MessagingException.NO_ERROR) {
505ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                        final String errorMessage;
506ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                        errorMessage = bundle.getString(
507ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                                EmailServiceProxy.VALIDATE_BUNDLE_ERROR_MESSAGE);
50855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                        return new MessagingException(resultCode, errorMessage);
50955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    }
51055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                }
51155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
512ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                final String protocol = mAccount.mHostAuthRecv.mProtocol;
513ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                final EmailServiceInfo info = EmailServiceUtils.getServiceInfo(mContext, protocol);
514e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank
51555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                // Check Outgoing Settings
516e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank                if (info.usesSmtp && (mMode & SetupData.CHECK_OUTGOING) != 0) {
51755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    if (isCancelled()) return null;
518560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy                    LogUtils.d(Logging.LOG_TAG, "Begin check of outgoing email settings");
51955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    publishProgress(STATE_CHECK_OUTGOING);
520ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                    final Sender sender = Sender.getInstance(mContext, mAccount);
52155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    sender.close();
52255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    sender.open();
52355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    sender.close();
52455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                }
52555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
52655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                // If we reached the end, we completed the check(s) successfully
52755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                return null;
52855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            } catch (final MessagingException me) {
52955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                // Some of the legacy account checkers return errors by throwing MessagingException,
53055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                // which we catch and return here.
53155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                return me;
53255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            }
53355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        }
53455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
53555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        /**
53655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler         * Progress reports (runs in UI thread).  This should be used for real progress only
53755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler         * (not for errors).
53855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler         */
53955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        @Override
54055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        protected void onProgressUpdate(Integer... progress) {
54155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            if (isCancelled()) return;
542715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            reportProgress(progress[0], null);
54355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        }
54455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
54555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        /**
5462731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler         * Result handler (runs in UI thread).
5472731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler         *
5482731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler         * AutoDiscover authentication errors are handled a bit differently than the
5492731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler         * other errors;  If encountered, we display the error dialog, but we return with
5502731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler         * a different callback used only for AutoDiscover.
5512731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler         *
55255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler         * @param result null for a successful check;  exception for various errors
55355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler         */
55455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        @Override
55555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        protected void onPostExecute(MessagingException result) {
55655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            if (isCancelled()) return;
55755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            if (result == null) {
558715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                reportProgress(STATE_CHECK_OK, null);
55955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            } else {
5602731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                int progressState = STATE_CHECK_ERROR;
561ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                final int exceptionType = result.getExceptionType();
5622731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler
56355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                switch (exceptionType) {
5642731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    // NOTE: AutoDiscover reports have their own reporting state, handle differently
5652731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    // from the other exception types
5662731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    case MessagingException.AUTODISCOVER_AUTHENTICATION_FAILED:
5672731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                        progressState = STATE_AUTODISCOVER_AUTH_DIALOG;
5682731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                        break;
5692731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                    case MessagingException.AUTODISCOVER_AUTHENTICATION_RESULT:
5702731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                        progressState = STATE_AUTODISCOVER_RESULT;
5712731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                        break;
57255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    // NOTE: Security policies required has its own report state, handle it a bit
57355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    // differently from the other exception types.
57455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    case MessagingException.SECURITY_POLICIES_REQUIRED:
5752731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                        progressState = STATE_CHECK_SHOW_SECURITY;
5762731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                        break;
57755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                }
578715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                reportProgress(progressState, result);
57955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            }
58055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        }
58155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    }
58255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
583715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo    private static String getErrorString(Context context, MessagingException ex) {
58406e140e4a42c11e60331229963d27548ea35551cTony Mantler        final int id;
585715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo        String message = ex.getMessage();
586715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo        if (message != null) {
587715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            message = message.trim();
588715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo        }
589715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo        switch (ex.getExceptionType()) {
590715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            // The remaining exception types are handled by setting the state to
591715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            // STATE_CHECK_ERROR (above, default) and conversion to specific error strings.
592715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            case MessagingException.CERTIFICATE_VALIDATION_ERROR:
593715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                id = TextUtils.isEmpty(message)
594715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                        ? R.string.account_setup_failed_dlg_certificate_message
595715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                        : R.string.account_setup_failed_dlg_certificate_message_fmt;
596715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                break;
597715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            case MessagingException.AUTHENTICATION_FAILED:
59806e140e4a42c11e60331229963d27548ea35551cTony Mantler                id = R.string.account_setup_failed_dlg_auth_message;
59906e140e4a42c11e60331229963d27548ea35551cTony Mantler                break;
600c196e05ee15ba72ed993bf498897c2be121ccad1Marc Blank            case MessagingException.AUTODISCOVER_AUTHENTICATION_FAILED:
60106e140e4a42c11e60331229963d27548ea35551cTony Mantler                id = R.string.account_setup_autodiscover_dlg_authfail_message;
602715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                break;
603715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            case MessagingException.AUTHENTICATION_FAILED_OR_SERVER_ERROR:
604715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                id = R.string.account_setup_failed_check_credentials_message;
605715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                break;
606715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            case MessagingException.IOERROR:
607715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                id = R.string.account_setup_failed_ioerror;
608715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                break;
609715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            case MessagingException.TLS_REQUIRED:
610715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                id = R.string.account_setup_failed_tls_required;
611715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                break;
612715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            case MessagingException.AUTH_REQUIRED:
613715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                id = R.string.account_setup_failed_auth_required;
614715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                break;
615715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            case MessagingException.SECURITY_POLICIES_UNSUPPORTED:
616715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                id = R.string.account_setup_failed_security_policies_unsupported;
617715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                // Belt and suspenders here; there should always be a non-empty array here
618715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                String[] unsupportedPolicies = (String[]) ex.getExceptionData();
619715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                if (unsupportedPolicies == null) {
620560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy                    LogUtils.w(TAG, "No data for unsupported policies?");
621715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                    break;
622715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                }
623715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                // Build a string, concatenating policies we don't support
624ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler                final StringBuilder sb = new StringBuilder();
625715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                boolean first = true;
626715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                for (String policyName: unsupportedPolicies) {
627715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                    if (first) {
628715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                        first = false;
629715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                    } else {
630715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                        sb.append(", ");
631715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                    }
632715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                    sb.append(policyName);
633715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                }
634715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                message = sb.toString();
635715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                break;
636715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            case MessagingException.ACCESS_DENIED:
637715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                id = R.string.account_setup_failed_access_denied;
638715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                break;
639715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            case MessagingException.PROTOCOL_VERSION_UNSUPPORTED:
640715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                id = R.string.account_setup_failed_protocol_unsupported;
641715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                break;
642715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            case MessagingException.GENERAL_SECURITY:
643715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                id = R.string.account_setup_failed_security;
644715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                break;
645715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            case MessagingException.CLIENT_CERTIFICATE_REQUIRED:
646715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                id = R.string.account_setup_failed_certificate_required;
647715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                break;
648715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            case MessagingException.CLIENT_CERTIFICATE_ERROR:
649715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                id = R.string.account_setup_failed_certificate_inaccessible;
650715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                break;
651715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            default:
652715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                id = TextUtils.isEmpty(message)
653715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                        ? R.string.account_setup_failed_dlg_server_message
654715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                        : R.string.account_setup_failed_dlg_server_message_fmt;
655715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                break;
656715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo        }
657715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo        return TextUtils.isEmpty(message)
658715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                ? context.getString(id)
659715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                : context.getString(id, message);
660715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo    }
661715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo
66255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    /**
66355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * Simple dialog that shows progress as we work through the settings checks.
66455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * This is stateless except for its UI (e.g. current strings) and can be torn down or
66555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * recreated at any time without affecting the account checking progress.
66655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     */
66755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    public static class CheckingDialog extends DialogFragment {
668040ddf60cfef4aaecf4bfe1f897fce3248d777a4Todd Kennedy        @SuppressWarnings("hiding")
66955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        public final static String TAG = "CheckProgressDialog";
67055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
67155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        // Extras for saved instance state
67255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        private final String EXTRA_PROGRESS_STRING = "CheckProgressDialog.Progress";
67355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
67455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        // UI
67555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        private String mProgressString;
67655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
6777985b43ab7310f76c170266da346f993d2f86051Paul Westbrook        // Public no-args constructor needed for fragment re-instantiation
6787985b43ab7310f76c170266da346f993d2f86051Paul Westbrook        public CheckingDialog() {}
6797985b43ab7310f76c170266da346f993d2f86051Paul Westbrook
68055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        /**
68155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler         * Create a dialog that reports progress
68255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler         * @param progress initial progress indication
68355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler         */
68455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        public static CheckingDialog newInstance(AccountCheckSettingsFragment parentFragment,
68555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                int progress) {
686ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler            final CheckingDialog f = new CheckingDialog();
68755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            f.setTargetFragment(parentFragment, progress);
68855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            return f;
68955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        }
69055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
69155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        /**
69255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler         * Update the progress of an existing dialog
69355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler         * @param progress latest progress to be displayed
69455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler         */
69555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        public void updateProgress(int progress) {
69655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            mProgressString = getProgressString(progress);
697ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler            final AlertDialog dialog = (AlertDialog) getDialog();
698258ab6ee842d619588b0f5f3ab48efe74de10b0fMarc Blank            if (dialog != null && mProgressString != null) {
699258ab6ee842d619588b0f5f3ab48efe74de10b0fMarc Blank                dialog.setMessage(mProgressString);
700258ab6ee842d619588b0f5f3ab48efe74de10b0fMarc Blank            }
70155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        }
70255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
70355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        @Override
70455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        public Dialog onCreateDialog(Bundle savedInstanceState) {
705ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler            final Context context = getActivity();
70655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            if (savedInstanceState != null) {
70755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                mProgressString = savedInstanceState.getString(EXTRA_PROGRESS_STRING);
70855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            }
70955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            if (mProgressString == null) {
71055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                mProgressString = getProgressString(getTargetRequestCode());
71155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            }
71255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
713ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler            final ProgressDialog dialog = new ProgressDialog(context);
71455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            dialog.setIndeterminate(true);
71555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            dialog.setMessage(mProgressString);
71655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            dialog.setButton(DialogInterface.BUTTON_NEGATIVE,
71755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    context.getString(R.string.cancel_action),
71855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    new DialogInterface.OnClickListener() {
719f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank                        @Override
72055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                        public void onClick(DialogInterface dialog, int which) {
72155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                            dismiss();
7229460be06aab728e69fc908bb55f26ab19f33aa8cTony Mantler
7239460be06aab728e69fc908bb55f26ab19f33aa8cTony Mantler                            final AccountCheckSettingsFragment target =
7249460be06aab728e69fc908bb55f26ab19f33aa8cTony Mantler                                    (AccountCheckSettingsFragment) getTargetFragment();
7259460be06aab728e69fc908bb55f26ab19f33aa8cTony Mantler                            if (target != null) {
7269460be06aab728e69fc908bb55f26ab19f33aa8cTony Mantler                                target.onCheckingDialogCancel();
7279460be06aab728e69fc908bb55f26ab19f33aa8cTony Mantler                            }
72855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                        }
72955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    });
73055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            return dialog;
73155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        }
73255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
733992b7e7ed34334a622d8ccb1d2f692a83a15360eAndy Stadler        /**
734992b7e7ed34334a622d8ccb1d2f692a83a15360eAndy Stadler         * Listen for cancellation, which can happen from places other than the
735992b7e7ed34334a622d8ccb1d2f692a83a15360eAndy Stadler         * negative button (e.g. touching outside the dialog), and stop the checker
736992b7e7ed34334a622d8ccb1d2f692a83a15360eAndy Stadler         */
737992b7e7ed34334a622d8ccb1d2f692a83a15360eAndy Stadler        @Override
738992b7e7ed34334a622d8ccb1d2f692a83a15360eAndy Stadler        public void onCancel(DialogInterface dialog) {
739ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler            final AccountCheckSettingsFragment target =
740992b7e7ed34334a622d8ccb1d2f692a83a15360eAndy Stadler                (AccountCheckSettingsFragment) getTargetFragment();
7419460be06aab728e69fc908bb55f26ab19f33aa8cTony Mantler            if (target != null) {
7429460be06aab728e69fc908bb55f26ab19f33aa8cTony Mantler                target.onCheckingDialogCancel();
7439460be06aab728e69fc908bb55f26ab19f33aa8cTony Mantler            }
744992b7e7ed34334a622d8ccb1d2f692a83a15360eAndy Stadler            super.onCancel(dialog);
745992b7e7ed34334a622d8ccb1d2f692a83a15360eAndy Stadler        }
746992b7e7ed34334a622d8ccb1d2f692a83a15360eAndy Stadler
74755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        @Override
74855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        public void onSaveInstanceState(Bundle outState) {
74955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            super.onSaveInstanceState(outState);
75055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            outState.putString(EXTRA_PROGRESS_STRING, mProgressString);
75155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        }
75255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
75355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        /**
75455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler         * Convert progress to message
75555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler         */
75655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        private String getProgressString(int progress) {
75755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            int stringId = 0;
75855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            switch (progress) {
75955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                case STATE_CHECK_AUTODISCOVER:
76055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    stringId = R.string.account_setup_check_settings_retr_info_msg;
76155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    break;
76255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                case STATE_CHECK_INCOMING:
76355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    stringId = R.string.account_setup_check_settings_check_incoming_msg;
76455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    break;
76555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                case STATE_CHECK_OUTGOING:
76655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    stringId = R.string.account_setup_check_settings_check_outgoing_msg;
76755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    break;
76855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            }
76955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            return getActivity().getString(stringId);
77055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        }
77155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    }
77255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
77355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    /**
77455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     * The standard error dialog.  Calls back to onErrorDialogButton().
77555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     */
77655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    public static class ErrorDialog extends DialogFragment {
777040ddf60cfef4aaecf4bfe1f897fce3248d777a4Todd Kennedy        @SuppressWarnings("hiding")
77855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        public final static String TAG = "ErrorDialog";
77955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
78055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        // Bundle keys for arguments
781715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo        private final static String ARGS_MESSAGE = "ErrorDialog.Message";
782715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo        private final static String ARGS_EXCEPTION_ID = "ErrorDialog.ExceptionId";
78355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
78492922ea4a4a6226aca0f464542a1b98cde144169Mindy Pereira        /**
78592922ea4a4a6226aca0f464542a1b98cde144169Mindy Pereira         * Use {@link #newInstance} This public constructor is still required so
78692922ea4a4a6226aca0f464542a1b98cde144169Mindy Pereira         * that DialogFragment state can be automatically restored by the
78792922ea4a4a6226aca0f464542a1b98cde144169Mindy Pereira         * framework.
78892922ea4a4a6226aca0f464542a1b98cde144169Mindy Pereira         */
78992922ea4a4a6226aca0f464542a1b98cde144169Mindy Pereira        public ErrorDialog() {
790715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo        }
791715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo
792715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo        public static ErrorDialog newInstance(Context context, AccountCheckSettingsFragment target,
793715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                MessagingException ex) {
794ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler            final ErrorDialog fragment = new ErrorDialog();
795ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler            final Bundle arguments = new Bundle(2);
796715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            arguments.putString(ARGS_MESSAGE, getErrorString(context, ex));
797715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            arguments.putInt(ARGS_EXCEPTION_ID, ex.getExceptionType());
79855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            fragment.setArguments(arguments);
79955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            fragment.setTargetFragment(target, 0);
80055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            return fragment;
80155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        }
80255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
80355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        @Override
80455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        public Dialog onCreateDialog(Bundle savedInstanceState) {
80555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            final Context context = getActivity();
80655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            final Bundle arguments = getArguments();
807715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            final String message = arguments.getString(ARGS_MESSAGE);
808715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            final int exceptionId = arguments.getInt(ARGS_EXCEPTION_ID);
80955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            final AccountCheckSettingsFragment target =
81055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    (AccountCheckSettingsFragment) getTargetFragment();
81155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
812ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler            final AlertDialog.Builder builder = new AlertDialog.Builder(context)
813715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                .setMessage(message)
814715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                .setCancelable(true);
815715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo
81606e140e4a42c11e60331229963d27548ea35551cTony Mantler            // Use a different title when we get
81706e140e4a42c11e60331229963d27548ea35551cTony Mantler            // MessagingException.AUTODISCOVER_AUTHENTICATION_FAILED
81806e140e4a42c11e60331229963d27548ea35551cTony Mantler            if (exceptionId == MessagingException.AUTODISCOVER_AUTHENTICATION_FAILED) {
81906e140e4a42c11e60331229963d27548ea35551cTony Mantler                builder.setTitle(R.string.account_setup_autodiscover_dlg_authfail_title);
82006e140e4a42c11e60331229963d27548ea35551cTony Mantler            } else {
8217df98d0a6d0a3c67b467e9ff2066970e645957b8Paul Sliwowski                builder.setIconAttribute(android.R.attr.alertDialogIcon)
8227df98d0a6d0a3c67b467e9ff2066970e645957b8Paul Sliwowski                    .setTitle(context.getString(R.string.account_setup_failed_dlg_title));
8237df98d0a6d0a3c67b467e9ff2066970e645957b8Paul Sliwowski            }
8247df98d0a6d0a3c67b467e9ff2066970e645957b8Paul Sliwowski
825715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            if (exceptionId == MessagingException.CLIENT_CERTIFICATE_REQUIRED) {
826715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                // Certificate error - show two buttons so the host fragment can auto pop
827715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                // into the appropriate flow.
828715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                builder.setPositiveButton(
829715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                        context.getString(android.R.string.ok),
830715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                        new DialogInterface.OnClickListener() {
831f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank                            @Override
832715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                            public void onClick(DialogInterface dialog, int which) {
833715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                                dismiss();
834715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                                target.onEditCertificateOk();
835715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                            }
836715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                        });
837715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                builder.setNegativeButton(
838715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                        context.getString(android.R.string.cancel),
839715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                        new DialogInterface.OnClickListener() {
840f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank                            @Override
841715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                            public void onClick(DialogInterface dialog, int which) {
842715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                                dismiss();
843715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                                target.onErrorDialogEditButton();
844715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                            }
845715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                        });
846715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo
847715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            } else {
848715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                // "Normal" error - just use a single "Edit details" button.
849715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                builder.setPositiveButton(
85055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                        context.getString(R.string.account_setup_failed_dlg_edit_details_action),
85155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                        new DialogInterface.OnClickListener() {
852f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank                            @Override
85355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                            public void onClick(DialogInterface dialog, int which) {
85455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                                dismiss();
85555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                                target.onErrorDialogEditButton();
85655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                            }
857715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo                        });
858715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            }
859715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo
860715ee4ec4c5a7893b89c28b8569a7a109a5be970Ben Komalo            return builder.create();
86155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        }
86255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
86355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    }
86455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
86555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    /**
8662731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler     * The "security required" error dialog.  This is presented whenever an exchange account
8672731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler     * reports that it will require security policy control, and provide the user with the
8682731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler     * opportunity to accept or deny this.
8692731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler     *
8702731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler     * If the user clicks OK, calls onSecurityRequiredDialogResultOk(true) which reports back
8712731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler     * to the target as if the settings check was "ok".  If the user clicks "cancel", calls
8722731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler     * onSecurityRequiredDialogResultOk(false) which simply closes the checker (this is the
8732731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler     * same as any other failed check.)
87455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler     */
87555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    public static class SecurityRequiredDialog extends DialogFragment {
876040ddf60cfef4aaecf4bfe1f897fce3248d777a4Todd Kennedy        @SuppressWarnings("hiding")
87755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        public final static String TAG = "SecurityRequiredDialog";
87855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
87955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        // Bundle keys for arguments
88055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        private final static String ARGS_HOST_NAME = "SecurityRequiredDialog.HostName";
88155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
8827985b43ab7310f76c170266da346f993d2f86051Paul Westbrook        // Public no-args constructor needed for fragment re-instantiation
8837985b43ab7310f76c170266da346f993d2f86051Paul Westbrook        public SecurityRequiredDialog() {}
8847985b43ab7310f76c170266da346f993d2f86051Paul Westbrook
88555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        public static SecurityRequiredDialog newInstance(AccountCheckSettingsFragment target,
88655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                String hostName) {
887ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler            final SecurityRequiredDialog fragment = new SecurityRequiredDialog();
888ed4accb24facd1324948abc61b0791eb3dc97cc4Tony Mantler            final Bundle arguments = new Bundle(1);
88955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            arguments.putString(ARGS_HOST_NAME, hostName);
89055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            fragment.setArguments(arguments);
89155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            fragment.setTargetFragment(target, 0);
89255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            return fragment;
89355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        }
89455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
89555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        @Override
89655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        public Dialog onCreateDialog(Bundle savedInstanceState) {
89755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            final Context context = getActivity();
89855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            final Bundle arguments = getArguments();
89955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            final String hostName = arguments.getString(ARGS_HOST_NAME);
90055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            final AccountCheckSettingsFragment target =
90155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                    (AccountCheckSettingsFragment) getTargetFragment();
90255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
90355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler            return new AlertDialog.Builder(context)
90449518bb3605d6c8e3cc4801c452e4f8f63220f44Makoto Onuki                .setIconAttribute(android.R.attr.alertDialogIcon)
90555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                .setTitle(context.getString(R.string.account_setup_security_required_title))
90655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                .setMessage(context.getString(
90755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                        R.string.account_setup_security_policies_required_fmt, hostName))
90855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                .setCancelable(true)
90955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                .setPositiveButton(
91055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                        context.getString(R.string.okay_action),
91155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                        new DialogInterface.OnClickListener() {
912f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank                            @Override
91355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                            public void onClick(DialogInterface dialog, int which) {
91455110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                                dismiss();
9152731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                                target.onSecurityRequiredDialogResultOk(true);
91655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                            }
91755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                        })
91855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                .setNegativeButton(
91955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                        context.getString(R.string.cancel_action),
92055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                        new DialogInterface.OnClickListener() {
921f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank                            @Override
92255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                            public void onClick(DialogInterface dialog, int which) {
92355110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                                dismiss();
9242731aef45c6f2f9792ae698ebf7d65ca6338a02cAndrew Stadler                                target.onSecurityRequiredDialogResultOk(false);
92555110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                            }
92655110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                        })
92755110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler                 .create();
92855110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler        }
92955110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
93055110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler    }
93155110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler
93255110ca1ad8ce48a5429f9f351d013691c10b806Andrew Stadler}
933