AccountSetupExchange.java revision 8bcb572ccfdac6974c111fe6dfc753a5e0d4e7ca
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.email.activity.setup;
18
19import com.android.email.R;
20import com.android.email.SecurityPolicy.PolicySet;
21import com.android.email.provider.EmailContent.Account;
22import com.android.email.provider.EmailContent.HostAuth;
23import com.android.email.service.EmailServiceProxy;
24
25import android.app.Activity;
26import android.content.Intent;
27import android.os.Bundle;
28import android.os.Parcelable;
29
30/**
31 * Provides generic setup for Exchange accounts.  The following fields are supported:
32 *
33 *  Email Address   (from previous setup screen)
34 *  Server
35 *  Domain
36 *  Requires SSL?
37 *  User (login)
38 *  Password
39 *
40 * There are two primary paths through this activity:
41 *   Edit existing:
42 *     Load existing values from account into fields
43 *     When user clicks 'next':
44 *       Confirm not a duplicate account
45 *       Try new values (check settings)
46 *       If new values are OK:
47 *         Write new values (save to provider)
48 *         finish() (pop to previous)
49 *
50 *   Creating New:
51 *     Try Auto-discover to get details from server
52 *     If Auto-discover reports an authentication failure:
53 *       finish() (pop to previous, to re-enter username & password)
54 *     If Auto-discover succeeds:
55 *       write server's account details into account
56 *     Load values from account into fields
57 *     Confirm not a duplicate account
58 *     Try new values (check settings)
59 *     If new values are OK:
60 *       Write new values (save to provider)
61 *       Proceed to options screen
62 *       finish() (removes self from back stack)
63 *
64 * TODO: The manifest for this activity has it ignore config changes, because
65 * we don't want to restart on every orientation - this would launch autodiscover again.
66 * Do not attempt to define orientation-specific resources, they won't be loaded.
67 * What we really need here is a more "sticky" way to prevent that problem.
68 */
69public class AccountSetupExchange extends AccountSetupActivity
70        implements AccountSetupExchangeFragment.Callback {
71
72    /* package */ AccountSetupExchangeFragment mFragment;
73    private boolean mNextButtonEnabled;
74
75    public static void actionIncomingSettings(Activity fromActivity, int mode, Account acct) {
76        SetupData.init(mode, acct);
77        fromActivity.startActivity(new Intent(fromActivity, AccountSetupExchange.class));
78    }
79
80    public static void actionEditIncomingSettings(Activity fromActivity, int mode, Account acct) {
81        actionIncomingSettings(fromActivity, mode, acct);
82    }
83
84    /**
85     * For now, we'll simply replicate outgoing, for the purpose of satisfying the
86     * account settings flow.
87     */
88    public static void actionEditOutgoingSettings(Activity fromActivity, int mode, Account acct) {
89        actionIncomingSettings(fromActivity, mode, acct);
90    }
91
92    @Override
93    public void onCreate(Bundle savedInstanceState) {
94        super.onCreate(savedInstanceState);
95        setContentView(R.layout.account_setup_exchange);
96
97        mFragment = (AccountSetupExchangeFragment)
98                getFragmentManager().findFragmentById(R.id.setup_fragment);
99        mFragment.setCallback(this);
100
101        startAutoDiscover();
102    }
103
104    /**
105     * If the conditions are right, launch the autodiscover activity.  If it succeeds (even
106     * partially) it will prefill the setup fields and we can proceed as if the user entered them.
107     *
108     * Conditions for skipping:
109     *  Editing existing account
110     *  AutoDiscover blocked (used for unit testing only)
111     *  Username or password not entered yet
112     */
113    private void startAutoDiscover() {
114        if (SetupData.getFlowMode() == SetupData.FLOW_MODE_EDIT
115                || !SetupData.isAllowAutodiscover()) {
116            return;
117        }
118
119        Account account = SetupData.getAccount();
120        // If we've got a username and password and we're NOT editing, try autodiscover
121        String username = account.mHostAuthRecv.mLogin;
122        String password = account.mHostAuthRecv.mPassword;
123        if (username != null && password != null) {
124            AccountSetupCheckSettings.actionAutoDiscover(this, account.mEmailAddress, password);
125        }
126    }
127
128    /**
129     * There are three cases handled here, so we split out into separate sections.
130     * 1.  Validate existing account (edit)
131     * 2.  Validate new account
132     * 3.  Autodiscover for new account
133     *
134     * For each case, there are two or more paths for success or failure.
135     */
136    @Override
137    public void onActivityResult(int requestCode, int resultCode, Intent data) {
138        if (requestCode == AccountSetupCheckSettings.REQUEST_CODE_VALIDATE) {
139            if (SetupData.getFlowMode() == SetupData.FLOW_MODE_EDIT) {
140                doActivityResultValidateExistingAccount(resultCode, data);
141            } else {
142                doActivityResultValidateNewAccount(resultCode, data);
143            }
144        } else if (requestCode == AccountSetupCheckSettings.REQUEST_CODE_AUTO_DISCOVER) {
145            doActivityResultAutoDiscoverNewAccount(resultCode, data);
146        }
147    }
148
149    /**
150     * Process activity result when validating existing account.  If OK, save and finish;
151     * otherwise simply remain in activity for further editing.
152     */
153    private void doActivityResultValidateExistingAccount(int resultCode, Intent data) {
154        if (resultCode == RESULT_OK) {
155            mFragment.saveSettingsAfterEdit();
156            finish();
157        }
158    }
159
160    /**
161     * Process activity result when validating new account
162     */
163    private void doActivityResultValidateNewAccount(int resultCode, Intent data) {
164        if (resultCode == RESULT_OK) {
165            // Go directly to next screen
166            PolicySet ps = null;
167            if ((data != null) && data.hasExtra(EmailServiceProxy.VALIDATE_BUNDLE_POLICY_SET)) {
168                ps = (PolicySet)data.getParcelableExtra(
169                        EmailServiceProxy.VALIDATE_BUNDLE_POLICY_SET);
170            }
171            AccountSetupOptions.actionOptions(this);
172            finish();
173        } else if (resultCode == AccountSetupCheckSettings.RESULT_SECURITY_REQUIRED_USER_CANCEL) {
174            finish();
175        }
176        // else (resultCode not OK) - just return into this activity for further editing
177    }
178
179    /**
180     * Process activity result when provisioning new account via autodiscovery
181     */
182    private void doActivityResultAutoDiscoverNewAccount(int resultCode, Intent data) {
183        // If authentication failed, exit immediately (to re-enter credentials)
184        if (resultCode == AccountSetupCheckSettings.RESULT_AUTO_DISCOVER_AUTH_FAILED) {
185            finish();
186            return;
187        }
188
189        // If data was returned, populate the account & populate the UI fields and validate it
190        if (data != null) {
191            Parcelable p = data.getParcelableExtra("HostAuth");
192            if (p != null) {
193                HostAuth hostAuth = (HostAuth)p;
194                boolean valid = mFragment.setHostAuthFromAutodiscover(hostAuth);
195                if (valid) {
196                    // "click" next to launch server verification
197                    mFragment.onNext();
198                }
199            }
200        }
201        // Otherwise, proceed into this activity for manual setup
202    }
203
204    /**
205     * Implements AccountServerBaseFragment.Callback
206     */
207    public void onEnableProceedButtons(boolean enabled) {
208        boolean wasEnabled = mNextButtonEnabled;
209        mNextButtonEnabled = enabled;
210
211        if (enabled != wasEnabled) {
212            invalidateOptionsMenu();
213        }
214    }
215
216    /**
217     * Implements AccountServerBaseFragment.Callback
218     */
219    public void onProceedNext(int checkMode) {
220        AccountSetupCheckSettings.actionCheckSettings(this, checkMode);
221    }
222}
223