2014-01-16 17:59:39 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2014 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package com.android.email.activity.setup;
|
|
|
|
|
|
|
|
import android.accounts.AccountAuthenticatorResponse;
|
|
|
|
import android.accounts.AccountManager;
|
2014-09-09 22:59:17 +00:00
|
|
|
import android.app.ActionBar;
|
2014-02-13 21:12:06 +00:00
|
|
|
import android.app.ActivityManager;
|
2014-01-16 17:59:39 +00:00
|
|
|
import android.app.AlertDialog;
|
|
|
|
import android.app.Dialog;
|
|
|
|
import android.app.DialogFragment;
|
|
|
|
import android.app.Fragment;
|
2014-03-12 18:00:24 +00:00
|
|
|
import android.app.FragmentManager;
|
2014-01-16 17:59:39 +00:00
|
|
|
import android.app.FragmentTransaction;
|
|
|
|
import android.app.LoaderManager;
|
|
|
|
import android.app.ProgressDialog;
|
|
|
|
import android.content.Context;
|
2014-02-13 21:12:06 +00:00
|
|
|
import android.content.CursorLoader;
|
2014-01-16 17:59:39 +00:00
|
|
|
import android.content.DialogInterface;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.Loader;
|
2014-02-13 21:12:06 +00:00
|
|
|
import android.database.Cursor;
|
2014-01-16 17:59:39 +00:00
|
|
|
import android.os.Bundle;
|
2014-02-13 21:12:06 +00:00
|
|
|
import android.provider.ContactsContract;
|
2014-08-21 16:46:13 +00:00
|
|
|
import android.support.annotation.NonNull;
|
2014-01-16 17:59:39 +00:00
|
|
|
import android.text.TextUtils;
|
2014-03-28 18:19:49 +00:00
|
|
|
import android.view.View;
|
|
|
|
import android.view.inputmethod.InputMethodManager;
|
2014-02-13 21:12:06 +00:00
|
|
|
import android.widget.Toast;
|
2014-01-16 17:59:39 +00:00
|
|
|
|
|
|
|
import com.android.email.R;
|
2014-09-07 20:36:33 +00:00
|
|
|
import com.android.email.setup.AuthenticatorSetupIntentHelper;
|
2014-01-16 17:59:39 +00:00
|
|
|
import com.android.email.service.EmailServiceUtils;
|
2014-02-13 21:12:06 +00:00
|
|
|
import com.android.emailcommon.VendorPolicyLoader;
|
2014-01-16 17:59:39 +00:00
|
|
|
import com.android.emailcommon.provider.Account;
|
2014-02-13 21:12:06 +00:00
|
|
|
import com.android.emailcommon.provider.HostAuth;
|
2014-03-28 20:05:22 +00:00
|
|
|
import com.android.emailcommon.service.SyncWindow;
|
2014-08-21 16:46:13 +00:00
|
|
|
import com.android.mail.providers.MailAppProvider;
|
|
|
|
import com.android.mail.providers.UIProvider;
|
2014-01-16 17:59:39 +00:00
|
|
|
import com.android.mail.utils.LogUtils;
|
|
|
|
|
2014-02-13 21:12:06 +00:00
|
|
|
import java.net.URISyntaxException;
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.Map;
|
2014-01-16 17:59:39 +00:00
|
|
|
|
2014-02-13 21:12:06 +00:00
|
|
|
public class AccountSetupFinal extends AccountSetupActivity
|
2014-03-17 23:45:47 +00:00
|
|
|
implements AccountFinalizeFragment.Callback,
|
2014-02-13 21:12:06 +00:00
|
|
|
AccountSetupNoteDialogFragment.Callback, AccountCreationFragment.Callback,
|
|
|
|
AccountCheckSettingsFragment.Callback, SecurityRequiredDialogFragment.Callback,
|
|
|
|
CheckSettingsErrorDialogFragment.Callback, CheckSettingsProgressDialogFragment.Callback,
|
|
|
|
AccountSetupTypeFragment.Callback, AccountSetupNamesFragment.Callback,
|
|
|
|
AccountSetupOptionsFragment.Callback, AccountSetupBasicsFragment.Callback,
|
2014-03-19 22:20:39 +00:00
|
|
|
AccountServerBaseFragment.Callback, AccountSetupCredentialsFragment.Callback,
|
2014-03-28 23:07:56 +00:00
|
|
|
DuplicateAccountDialogFragment.Callback, AccountSetupABFragment.Callback {
|
2014-01-16 17:59:39 +00:00
|
|
|
|
2014-02-13 21:12:06 +00:00
|
|
|
/**
|
|
|
|
* Direct access for forcing account creation
|
|
|
|
* For use by continuous automated test system (e.g. in conjunction with monkey tests)
|
|
|
|
*
|
|
|
|
* === Support for automated testing ==
|
2014-07-18 22:11:36 +00:00
|
|
|
* This activity can also be launched directly via INTENT_FORCE_CREATE_ACCOUNT. This is intended
|
2014-02-13 21:12:06 +00:00
|
|
|
* only for use by continuous test systems, and is currently only available when
|
|
|
|
* {@link ActivityManager#isRunningInTestHarness()} is set. To use this mode, you must
|
|
|
|
* construct an intent which contains all necessary information to create the account. No
|
|
|
|
* connection checking is done, so the account may or may not actually work. Here is a sample
|
|
|
|
* command, for a gmail account "test_account" with a password of "test_password".
|
|
|
|
*
|
2014-07-18 22:11:36 +00:00
|
|
|
* $ adb shell am start -a com.android.email.FORCE_CREATE_ACCOUNT \
|
2014-02-13 21:12:06 +00:00
|
|
|
* -e EMAIL test_account@gmail.com \
|
|
|
|
* -e USER "Test Account Name" \
|
|
|
|
* -e INCOMING imap+ssl+://test_account:test_password@imap.gmail.com \
|
|
|
|
* -e OUTGOING smtp+ssl+://test_account:test_password@smtp.gmail.com
|
|
|
|
*
|
|
|
|
* Note: For accounts that require the full email address in the login, encode the @ as %40.
|
|
|
|
* Note: Exchange accounts that require device security policies cannot be created
|
|
|
|
* automatically.
|
2014-03-13 23:07:22 +00:00
|
|
|
*
|
|
|
|
* For accounts that correspond to services in providers.xml you can also use the following form
|
|
|
|
*
|
2014-07-18 22:11:36 +00:00
|
|
|
* $adb shell am start -a com.android.email.FORCE_CREATE_ACCOUNT \
|
2014-03-13 23:07:22 +00:00
|
|
|
* -e EMAIL test_account@gmail.com \
|
|
|
|
* -e PASSWORD test_password
|
|
|
|
*
|
|
|
|
* and the appropriate incoming/outgoing information will be filled in automatically.
|
2014-02-13 21:12:06 +00:00
|
|
|
*/
|
2014-07-18 22:11:36 +00:00
|
|
|
private static String INTENT_FORCE_CREATE_ACCOUNT;
|
2014-02-13 21:12:06 +00:00
|
|
|
private static final String EXTRA_CREATE_ACCOUNT_EMAIL = "EMAIL";
|
|
|
|
private static final String EXTRA_CREATE_ACCOUNT_USER = "USER";
|
2014-03-13 23:07:22 +00:00
|
|
|
private static final String EXTRA_CREATE_ACCOUNT_PASSWORD = "PASSWORD";
|
2014-02-13 21:12:06 +00:00
|
|
|
private static final String EXTRA_CREATE_ACCOUNT_INCOMING = "INCOMING";
|
|
|
|
private static final String EXTRA_CREATE_ACCOUNT_OUTGOING = "OUTGOING";
|
2014-03-28 20:05:22 +00:00
|
|
|
private static final String EXTRA_CREATE_ACCOUNT_SYNC_LOOKBACK = "SYNC_LOOKBACK";
|
|
|
|
|
|
|
|
private static final String CREATE_ACCOUNT_SYNC_ALL_VALUE = "ALL";
|
|
|
|
|
2014-02-13 21:12:06 +00:00
|
|
|
private static final Boolean DEBUG_ALLOW_NON_TEST_HARNESS_CREATION = false;
|
|
|
|
|
|
|
|
protected static final String ACTION_JUMP_TO_INCOMING = "jumpToIncoming";
|
|
|
|
protected static final String ACTION_JUMP_TO_OUTGOING = "jumpToOutgoing";
|
|
|
|
protected static final String ACTION_JUMP_TO_OPTIONS = "jumpToOptions";
|
|
|
|
|
|
|
|
private static final String SAVESTATE_KEY_IS_PROCESSING = "AccountSetupFinal.is_processing";
|
|
|
|
private static final String SAVESTATE_KEY_STATE = "AccountSetupFinal.state";
|
|
|
|
private static final String SAVESTATE_KEY_PROVIDER = "AccountSetupFinal.provider";
|
|
|
|
private static final String SAVESTATE_KEY_AUTHENTICATOR_RESPONSE = "AccountSetupFinal.authResp";
|
|
|
|
private static final String SAVESTATE_KEY_REPORT_AUTHENTICATOR_ERROR =
|
|
|
|
"AccountSetupFinal.authErr";
|
|
|
|
private static final String SAVESTATE_KEY_IS_PRE_CONFIGURED = "AccountSetupFinal.preconfig";
|
|
|
|
private static final String SAVESTATE_KEY_SKIP_AUTO_DISCOVER = "AccountSetupFinal.noAuto";
|
2014-03-12 18:00:24 +00:00
|
|
|
private static final String SAVESTATE_KEY_PASSWORD_FAILED = "AccountSetupFinal.passwordFailed";
|
2014-01-16 17:59:39 +00:00
|
|
|
|
|
|
|
private static final String CONTENT_FRAGMENT_TAG = "AccountSetupContentFragment";
|
2014-03-12 18:00:24 +00:00
|
|
|
private static final String CREDENTIALS_BACKSTACK_TAG = "AccountSetupCredentialsFragment";
|
2014-01-16 17:59:39 +00:00
|
|
|
|
2014-02-13 21:12:06 +00:00
|
|
|
// Collecting initial email and password
|
|
|
|
private static final int STATE_BASICS = 0;
|
2014-03-13 21:11:06 +00:00
|
|
|
// Show the user some interstitial message after email entry
|
|
|
|
private static final int STATE_BASICS_POST = 1;
|
|
|
|
// Account is not pre-configured, query user for account type
|
|
|
|
private static final int STATE_TYPE = 2;
|
2014-03-28 23:07:56 +00:00
|
|
|
// Account is pre-configured, but the user picked a different protocol
|
|
|
|
private static final int STATE_AB = 3;
|
2014-02-13 21:12:06 +00:00
|
|
|
// Collect initial password or oauth token
|
2014-03-28 23:07:56 +00:00
|
|
|
private static final int STATE_CREDENTIALS = 4;
|
2014-02-13 21:12:06 +00:00
|
|
|
// Account is a pre-configured account, run the checker
|
2014-03-28 23:07:56 +00:00
|
|
|
private static final int STATE_CHECKING_PRECONFIGURED = 5;
|
2014-02-13 21:12:06 +00:00
|
|
|
// Auto-discovering exchange account info, possibly other protocols later
|
|
|
|
private static final int STATE_AUTO_DISCOVER = 6;
|
|
|
|
// User is entering incoming settings
|
|
|
|
private static final int STATE_MANUAL_INCOMING = 7;
|
|
|
|
// We're checking incoming settings
|
|
|
|
private static final int STATE_CHECKING_INCOMING = 8;
|
|
|
|
// User is entering outgoing settings
|
|
|
|
private static final int STATE_MANUAL_OUTGOING = 9;
|
|
|
|
// We're checking outgoing settings
|
|
|
|
private static final int STATE_CHECKING_OUTGOING = 10;
|
|
|
|
// User is entering sync options
|
|
|
|
private static final int STATE_OPTIONS = 11;
|
|
|
|
// We're creating the account
|
|
|
|
private static final int STATE_CREATING = 12;
|
|
|
|
// User is entering account name and real name
|
|
|
|
private static final int STATE_NAMES = 13;
|
|
|
|
// we're finalizing the account
|
|
|
|
private static final int STATE_FINALIZE = 14;
|
|
|
|
|
|
|
|
private int mState = STATE_BASICS;
|
2014-01-16 17:59:39 +00:00
|
|
|
|
|
|
|
private boolean mIsProcessing = false;
|
2014-01-28 19:16:55 +00:00
|
|
|
private boolean mForceCreate = false;
|
2014-02-13 21:12:06 +00:00
|
|
|
private boolean mReportAccountAuthenticatorError;
|
|
|
|
private AccountAuthenticatorResponse mAccountAuthenticatorResponse;
|
|
|
|
// True if this provider is found in our providers.xml, set after Basics
|
|
|
|
private boolean mIsPreConfiguredProvider = false;
|
|
|
|
// True if the user selected manual setup
|
|
|
|
private boolean mSkipAutoDiscover = false;
|
|
|
|
// True if validating the pre-configured provider failed and we want manual setup
|
|
|
|
private boolean mPreConfiguredFailed = false;
|
|
|
|
|
|
|
|
private VendorPolicyLoader.Provider mProvider;
|
2014-03-12 18:00:24 +00:00
|
|
|
private boolean mPasswordFailed;
|
2014-02-13 21:12:06 +00:00
|
|
|
|
|
|
|
private static final int OWNER_NAME_LOADER_ID = 0;
|
|
|
|
private String mOwnerName;
|
|
|
|
|
|
|
|
private static final int EXISTING_ACCOUNTS_LOADER_ID = 1;
|
|
|
|
private Map<String, String> mExistingAccountsMap;
|
|
|
|
|
2014-01-16 17:59:39 +00:00
|
|
|
@Override
|
|
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
|
2014-02-13 21:12:06 +00:00
|
|
|
final Intent intent = getIntent();
|
|
|
|
final String action = intent.getAction();
|
|
|
|
|
2014-07-18 22:11:36 +00:00
|
|
|
if (INTENT_FORCE_CREATE_ACCOUNT == null) {
|
|
|
|
INTENT_FORCE_CREATE_ACCOUNT = getString(R.string.intent_force_create_email_account);
|
2014-02-13 21:12:06 +00:00
|
|
|
}
|
|
|
|
|
2014-03-17 23:45:47 +00:00
|
|
|
setContentView(R.layout.account_setup_activity);
|
2014-01-16 17:59:39 +00:00
|
|
|
|
2014-09-09 22:59:17 +00:00
|
|
|
final ActionBar actionBar = getActionBar();
|
|
|
|
if (actionBar != null) {
|
|
|
|
// Hide the app icon.
|
|
|
|
actionBar.setIcon(android.R.color.transparent);
|
|
|
|
actionBar.setDisplayUseLogoEnabled(false);
|
|
|
|
}
|
|
|
|
|
2014-01-16 17:59:39 +00:00
|
|
|
if (savedInstanceState != null) {
|
2014-02-13 21:12:06 +00:00
|
|
|
mIsProcessing = savedInstanceState.getBoolean(SAVESTATE_KEY_IS_PROCESSING, false);
|
|
|
|
mState = savedInstanceState.getInt(SAVESTATE_KEY_STATE, STATE_OPTIONS);
|
|
|
|
mProvider = (VendorPolicyLoader.Provider)
|
|
|
|
savedInstanceState.getSerializable(SAVESTATE_KEY_PROVIDER);
|
|
|
|
mAccountAuthenticatorResponse =
|
|
|
|
savedInstanceState.getParcelable(SAVESTATE_KEY_AUTHENTICATOR_RESPONSE);
|
|
|
|
mReportAccountAuthenticatorError =
|
|
|
|
savedInstanceState.getBoolean(SAVESTATE_KEY_REPORT_AUTHENTICATOR_ERROR);
|
|
|
|
mIsPreConfiguredProvider =
|
|
|
|
savedInstanceState.getBoolean(SAVESTATE_KEY_IS_PRE_CONFIGURED);
|
|
|
|
mSkipAutoDiscover = savedInstanceState.getBoolean(SAVESTATE_KEY_SKIP_AUTO_DISCOVER);
|
2014-03-12 18:00:24 +00:00
|
|
|
mPasswordFailed = savedInstanceState.getBoolean(SAVESTATE_KEY_PASSWORD_FAILED);
|
2014-01-16 17:59:39 +00:00
|
|
|
} else {
|
|
|
|
// If we're not restoring from a previous state, we want to configure the initial screen
|
2014-02-13 21:12:06 +00:00
|
|
|
|
|
|
|
// Set aside incoming AccountAuthenticatorResponse, if there was any
|
|
|
|
mAccountAuthenticatorResponse = getIntent()
|
|
|
|
.getParcelableExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE);
|
|
|
|
if (mAccountAuthenticatorResponse != null) {
|
|
|
|
// When this Activity is called as part of account authentification flow,
|
|
|
|
// we are responsible for eventually reporting the result (success or failure) to
|
|
|
|
// the account manager. Most exit paths represent an failed or abandoned setup,
|
|
|
|
// so the default is to report the error. Success will be reported by the code in
|
|
|
|
// AccountSetupOptions that commits the finally created account.
|
|
|
|
mReportAccountAuthenticatorError = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the SetupDataFragment
|
2014-07-18 22:11:36 +00:00
|
|
|
if (INTENT_FORCE_CREATE_ACCOUNT.equals(action)) {
|
2014-09-07 20:36:33 +00:00
|
|
|
mSetupData.setFlowMode(AuthenticatorSetupIntentHelper.FLOW_MODE_FORCE_CREATE);
|
2014-02-13 21:12:06 +00:00
|
|
|
} else {
|
2014-09-07 20:36:33 +00:00
|
|
|
final int intentFlowMode = intent.getIntExtra(
|
|
|
|
AuthenticatorSetupIntentHelper.EXTRA_FLOW_MODE,
|
|
|
|
AuthenticatorSetupIntentHelper.FLOW_MODE_UNSPECIFIED);
|
|
|
|
final String flowAccountType = intent.getStringExtra(
|
|
|
|
AuthenticatorSetupIntentHelper.EXTRA_FLOW_ACCOUNT_TYPE);
|
2014-03-14 22:48:10 +00:00
|
|
|
mSetupData.setAmProtocol(
|
|
|
|
EmailServiceUtils.getProtocolFromAccountType(this, flowAccountType));
|
2014-02-13 21:12:06 +00:00
|
|
|
mSetupData.setFlowMode(intentFlowMode);
|
|
|
|
}
|
|
|
|
|
|
|
|
mState = STATE_BASICS;
|
|
|
|
// Support unit testing individual screens
|
|
|
|
if (TextUtils.equals(ACTION_JUMP_TO_INCOMING, action)) {
|
|
|
|
mState = STATE_MANUAL_INCOMING;
|
|
|
|
} else if (TextUtils.equals(ACTION_JUMP_TO_OUTGOING, action)) {
|
|
|
|
mState = STATE_MANUAL_OUTGOING;
|
|
|
|
} else if (TextUtils.equals(ACTION_JUMP_TO_OPTIONS, action)) {
|
|
|
|
mState = STATE_OPTIONS;
|
|
|
|
}
|
2014-01-22 18:59:22 +00:00
|
|
|
updateContentFragment(false /* addToBackstack */);
|
2014-03-12 18:00:24 +00:00
|
|
|
mPasswordFailed = false;
|
2014-01-16 17:59:39 +00:00
|
|
|
}
|
|
|
|
|
2014-09-07 20:36:33 +00:00
|
|
|
if (!mIsProcessing && mSetupData.getFlowMode() ==
|
|
|
|
AuthenticatorSetupIntentHelper.FLOW_MODE_FORCE_CREATE) {
|
2014-03-04 17:54:18 +00:00
|
|
|
/**
|
|
|
|
* To support continuous testing, we allow the forced creation of accounts.
|
|
|
|
* This works in a manner fairly similar to automatic setup, in which the complete
|
|
|
|
* server Uri's are available, except that we will also skip checking (as if both
|
|
|
|
* checks were true) and all other UI.
|
|
|
|
*
|
|
|
|
* email: The email address for the new account
|
|
|
|
* user: The user name for the new account
|
|
|
|
* incoming: The URI-style string defining the incoming account
|
|
|
|
* outgoing: The URI-style string defining the outgoing account
|
|
|
|
*/
|
|
|
|
final String email = intent.getStringExtra(EXTRA_CREATE_ACCOUNT_EMAIL);
|
|
|
|
final String user = intent.getStringExtra(EXTRA_CREATE_ACCOUNT_USER);
|
2014-03-13 23:07:22 +00:00
|
|
|
final String password = intent.getStringExtra(EXTRA_CREATE_ACCOUNT_PASSWORD);
|
2014-03-04 17:54:18 +00:00
|
|
|
final String incoming = intent.getStringExtra(EXTRA_CREATE_ACCOUNT_INCOMING);
|
|
|
|
final String outgoing = intent.getStringExtra(EXTRA_CREATE_ACCOUNT_OUTGOING);
|
2014-03-28 20:05:22 +00:00
|
|
|
final String syncLookbackText = intent.getStringExtra(EXTRA_CREATE_ACCOUNT_SYNC_LOOKBACK);
|
|
|
|
final int syncLookback;
|
|
|
|
if (TextUtils.equals(syncLookbackText, CREATE_ACCOUNT_SYNC_ALL_VALUE)) {
|
|
|
|
syncLookback = SyncWindow.SYNC_WINDOW_ALL;
|
|
|
|
} else {
|
|
|
|
syncLookback = -1;
|
|
|
|
}
|
2014-03-13 23:07:22 +00:00
|
|
|
// If we've been explicitly provided with all the details to fill in the account, we
|
|
|
|
// can use them
|
|
|
|
final boolean explicitForm = !(TextUtils.isEmpty(user) ||
|
|
|
|
TextUtils.isEmpty(incoming) || TextUtils.isEmpty(outgoing));
|
|
|
|
// If we haven't been provided the details, but we have the password, we can look up
|
|
|
|
// the info from providers.xml
|
|
|
|
final boolean implicitForm = !TextUtils.isEmpty(password) && !explicitForm;
|
|
|
|
if (TextUtils.isEmpty(email) || !(explicitForm || implicitForm)) {
|
|
|
|
LogUtils.e(LogUtils.TAG, "Force account create requires extras EMAIL, " +
|
|
|
|
"USER, INCOMING, OUTGOING, or EMAIL and PASSWORD");
|
2014-03-04 17:54:18 +00:00
|
|
|
finish();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-03-13 23:07:22 +00:00
|
|
|
if (implicitForm) {
|
|
|
|
final String[] emailParts = email.split("@");
|
|
|
|
final String domain = emailParts[1].trim();
|
|
|
|
mProvider = AccountSettingsUtils.findProviderForDomain(this, domain);
|
|
|
|
if (mProvider == null) {
|
|
|
|
LogUtils.e(LogUtils.TAG, "findProviderForDomain couldn't find provider");
|
|
|
|
finish();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mIsPreConfiguredProvider = true;
|
|
|
|
mSetupData.setEmail(email);
|
|
|
|
boolean autoSetupCompleted = finishAutoSetup();
|
|
|
|
if (!autoSetupCompleted) {
|
|
|
|
LogUtils.e(LogUtils.TAG, "Force create account failed to create account");
|
|
|
|
finish();
|
2014-04-01 22:10:18 +00:00
|
|
|
return;
|
2014-03-13 23:07:22 +00:00
|
|
|
}
|
2014-04-01 22:10:18 +00:00
|
|
|
final Account account = mSetupData.getAccount();
|
|
|
|
final HostAuth recvAuth = account.getOrCreateHostAuthRecv(this);
|
|
|
|
recvAuth.mPassword = password;
|
|
|
|
final HostAuth sendAuth = account.getOrCreateHostAuthSend(this);
|
|
|
|
sendAuth.mPassword = password;
|
2014-03-13 23:07:22 +00:00
|
|
|
} else {
|
|
|
|
final Account account = mSetupData.getAccount();
|
|
|
|
|
|
|
|
try {
|
|
|
|
final HostAuth recvAuth = account.getOrCreateHostAuthRecv(this);
|
|
|
|
recvAuth.setHostAuthFromString(incoming);
|
|
|
|
|
|
|
|
final HostAuth sendAuth = account.getOrCreateHostAuthSend(this);
|
|
|
|
sendAuth.setHostAuthFromString(outgoing);
|
|
|
|
} catch (URISyntaxException e) {
|
|
|
|
// If we can't set up the URL, don't continue
|
|
|
|
Toast.makeText(this, R.string.account_setup_username_password_toast,
|
|
|
|
Toast.LENGTH_LONG)
|
|
|
|
.show();
|
|
|
|
finish();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
populateSetupData(user, email);
|
2014-03-28 20:05:22 +00:00
|
|
|
// We need to do this after calling populateSetupData(), because that will
|
|
|
|
// overwrite it with the default values.
|
|
|
|
if (syncLookback >= SyncWindow.SYNC_WINDOW_ACCOUNT &&
|
|
|
|
syncLookback <= SyncWindow.SYNC_WINDOW_ALL) {
|
|
|
|
account.mSyncLookback = syncLookback;
|
|
|
|
}
|
2014-03-13 23:07:22 +00:00
|
|
|
}
|
2014-03-04 17:54:18 +00:00
|
|
|
|
|
|
|
mState = STATE_OPTIONS;
|
|
|
|
updateContentFragment(false /* addToBackstack */);
|
2014-01-16 17:59:39 +00:00
|
|
|
getFragmentManager().executePendingTransactions();
|
2014-02-13 21:12:06 +00:00
|
|
|
|
|
|
|
if (!DEBUG_ALLOW_NON_TEST_HARNESS_CREATION &&
|
|
|
|
!ActivityManager.isRunningInTestHarness()) {
|
|
|
|
LogUtils.e(LogUtils.TAG,
|
|
|
|
"ERROR: Force account create only allowed while in test harness");
|
|
|
|
finish();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-01-28 19:16:55 +00:00
|
|
|
mForceCreate = true;
|
|
|
|
}
|
2014-02-13 21:12:06 +00:00
|
|
|
|
|
|
|
// Launch a loader to look up the owner name. It should be ready well in advance of
|
|
|
|
// the time the user clicks next or manual.
|
2014-08-21 16:46:13 +00:00
|
|
|
getLoaderManager().initLoader(OWNER_NAME_LOADER_ID, null, new OwnerNameLoaderCallbacks());
|
2014-02-13 21:12:06 +00:00
|
|
|
|
|
|
|
// Launch a loader to cache some info about existing accounts so we can dupe-check against
|
|
|
|
// them.
|
|
|
|
getLoaderManager().initLoader(EXISTING_ACCOUNTS_LOADER_ID, null,
|
2014-08-21 16:46:13 +00:00
|
|
|
new ExistingAccountsLoaderCallbacks());
|
|
|
|
}
|
|
|
|
|
|
|
|
private class OwnerNameLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
|
|
|
|
@Override
|
|
|
|
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
|
|
|
|
return new CursorLoader(AccountSetupFinal.this,
|
|
|
|
ContactsContract.Profile.CONTENT_URI,
|
|
|
|
new String[] {ContactsContract.Profile.DISPLAY_NAME_PRIMARY},
|
|
|
|
null, null, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) {
|
|
|
|
if (data != null && data.moveToFirst()) {
|
|
|
|
mOwnerName = data.getString(data.getColumnIndex(
|
|
|
|
ContactsContract.Profile.DISPLAY_NAME_PRIMARY));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onLoaderReset(final Loader<Cursor> loader) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
private class ExistingAccountsLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
|
|
|
|
@Override
|
|
|
|
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
|
|
|
|
return new CursorLoader(AccountSetupFinal.this, MailAppProvider.getAccountsUri(),
|
|
|
|
new String[] {UIProvider.AccountColumns.ACCOUNT_MANAGER_NAME,
|
|
|
|
UIProvider.AccountColumns.NAME},
|
|
|
|
null, null, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) {
|
|
|
|
if (data == null || !data.moveToFirst()) {
|
|
|
|
mExistingAccountsMap = null;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mExistingAccountsMap = new HashMap<>();
|
|
|
|
|
|
|
|
final int emailColumnIndex = data.getColumnIndex(
|
|
|
|
UIProvider.AccountColumns.ACCOUNT_MANAGER_NAME);
|
|
|
|
final int displayNameColumnIndex =
|
|
|
|
data.getColumnIndex(UIProvider.AccountColumns.NAME);
|
|
|
|
|
|
|
|
do {
|
|
|
|
final String email = data.getString(emailColumnIndex);
|
|
|
|
final String displayName = data.getString(displayNameColumnIndex);
|
|
|
|
mExistingAccountsMap.put(email,
|
|
|
|
TextUtils.isEmpty(displayName) ? email : displayName);
|
|
|
|
} while (data.moveToNext());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onLoaderReset(final Loader<Cursor> loader) {
|
|
|
|
mExistingAccountsMap = null;
|
|
|
|
}
|
2014-01-28 19:16:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onResume() {
|
|
|
|
super.onResume();
|
|
|
|
if (mForceCreate) {
|
2014-03-04 17:54:18 +00:00
|
|
|
mForceCreate = false;
|
2014-02-13 21:12:06 +00:00
|
|
|
|
2014-03-04 17:54:18 +00:00
|
|
|
// We need to do this after onCreate so that we can ensure that the fragment is
|
|
|
|
// fully created before querying it.
|
2014-04-01 22:10:18 +00:00
|
|
|
// This will call initiateAccountCreation() for us
|
|
|
|
proceed();
|
2014-01-16 17:59:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2014-08-21 16:46:13 +00:00
|
|
|
public void onSaveInstanceState(@NonNull Bundle outState) {
|
2014-01-16 17:59:39 +00:00
|
|
|
super.onSaveInstanceState(outState);
|
2014-02-13 21:12:06 +00:00
|
|
|
outState.putBoolean(SAVESTATE_KEY_IS_PROCESSING, mIsProcessing);
|
|
|
|
outState.putInt(SAVESTATE_KEY_STATE, mState);
|
|
|
|
outState.putSerializable(SAVESTATE_KEY_PROVIDER, mProvider);
|
|
|
|
outState.putParcelable(SAVESTATE_KEY_AUTHENTICATOR_RESPONSE, mAccountAuthenticatorResponse);
|
|
|
|
outState.putBoolean(SAVESTATE_KEY_REPORT_AUTHENTICATOR_ERROR,
|
|
|
|
mReportAccountAuthenticatorError);
|
|
|
|
outState.putBoolean(SAVESTATE_KEY_IS_PRE_CONFIGURED, mIsPreConfiguredProvider);
|
2014-03-12 18:00:24 +00:00
|
|
|
outState.putBoolean(SAVESTATE_KEY_PASSWORD_FAILED, mPasswordFailed);
|
2014-01-16 17:59:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Swap in the new fragment according to mState. This pushes the current fragment onto the back
|
|
|
|
* stack, so only call it once per transition.
|
|
|
|
*/
|
2014-01-22 18:59:22 +00:00
|
|
|
private void updateContentFragment(boolean addToBackstack) {
|
2014-02-13 21:12:06 +00:00
|
|
|
final AccountSetupFragment f;
|
2014-03-12 18:00:24 +00:00
|
|
|
String backstackTag = null;
|
|
|
|
|
2014-01-16 17:59:39 +00:00
|
|
|
switch (mState) {
|
2014-02-13 21:12:06 +00:00
|
|
|
case STATE_BASICS:
|
|
|
|
f = AccountSetupBasicsFragment.newInstance();
|
|
|
|
break;
|
2014-03-13 21:11:06 +00:00
|
|
|
case STATE_TYPE:
|
|
|
|
f = AccountSetupTypeFragment.newInstance();
|
|
|
|
break;
|
2014-03-28 23:07:56 +00:00
|
|
|
case STATE_AB:
|
|
|
|
f = AccountSetupABFragment.newInstance(mSetupData.getEmail(),
|
|
|
|
mSetupData.getAmProtocol(), mSetupData.getIncomingProtocol(this));
|
|
|
|
break;
|
2014-02-13 21:12:06 +00:00
|
|
|
case STATE_CREDENTIALS:
|
|
|
|
f = AccountSetupCredentialsFragment.newInstance(mSetupData.getEmail(),
|
2014-03-13 18:30:25 +00:00
|
|
|
mSetupData.getIncomingProtocol(this), mSetupData.getClientCert(this),
|
2014-03-17 23:45:47 +00:00
|
|
|
mPasswordFailed, false /* standalone */);
|
2014-03-12 18:00:24 +00:00
|
|
|
backstackTag = CREDENTIALS_BACKSTACK_TAG;
|
2014-02-13 21:12:06 +00:00
|
|
|
break;
|
|
|
|
case STATE_MANUAL_INCOMING:
|
|
|
|
f = AccountSetupIncomingFragment.newInstance(false);
|
|
|
|
break;
|
|
|
|
case STATE_MANUAL_OUTGOING:
|
|
|
|
f = AccountSetupOutgoingFragment.newInstance(false);
|
|
|
|
break;
|
2014-01-16 17:59:39 +00:00
|
|
|
case STATE_OPTIONS:
|
2014-02-13 21:12:06 +00:00
|
|
|
f = AccountSetupOptionsFragment.newInstance();
|
2014-01-16 17:59:39 +00:00
|
|
|
break;
|
|
|
|
case STATE_NAMES:
|
2014-02-13 21:12:06 +00:00
|
|
|
f = AccountSetupNamesFragment.newInstance();
|
2014-01-16 17:59:39 +00:00
|
|
|
break;
|
|
|
|
default:
|
2014-02-13 21:12:06 +00:00
|
|
|
throw new IllegalStateException("Incorrect state " + mState);
|
2014-01-16 17:59:39 +00:00
|
|
|
}
|
2014-02-13 21:12:06 +00:00
|
|
|
f.setState(mState);
|
2014-01-16 17:59:39 +00:00
|
|
|
final FragmentTransaction ft = getFragmentManager().beginTransaction();
|
2014-04-18 21:54:55 +00:00
|
|
|
ft.setCustomAnimations(R.anim.fade_in, R.anim.fade_out, R.anim.fade_in, R.anim.fade_out);
|
2014-01-16 17:59:39 +00:00
|
|
|
ft.replace(R.id.setup_fragment_container, f, CONTENT_FRAGMENT_TAG);
|
2014-01-22 18:59:22 +00:00
|
|
|
if (addToBackstack) {
|
2014-03-12 18:00:24 +00:00
|
|
|
ft.addToBackStack(backstackTag);
|
2014-01-22 18:59:22 +00:00
|
|
|
}
|
2014-01-16 17:59:39 +00:00
|
|
|
ft.commit();
|
2014-03-28 18:19:49 +00:00
|
|
|
|
|
|
|
final InputMethodManager imm =
|
|
|
|
(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
|
|
final View fragment_container = findViewById(R.id.setup_fragment_container);
|
|
|
|
imm.hideSoftInputFromWindow(fragment_container.getWindowToken(),
|
|
|
|
0 /* flags: always hide */);
|
2014-01-16 17:59:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve the current content fragment
|
|
|
|
* @return The content fragment or null if it wasn't found for some reason
|
|
|
|
*/
|
2014-02-13 21:12:06 +00:00
|
|
|
private AccountSetupFragment getContentFragment() {
|
|
|
|
return (AccountSetupFragment) getFragmentManager().findFragmentByTag(CONTENT_FRAGMENT_TAG);
|
2014-01-16 17:59:39 +00:00
|
|
|
}
|
|
|
|
|
2014-02-28 23:56:25 +00:00
|
|
|
/**
|
|
|
|
* Reads the flow state saved into the current fragment and restores mState to it, also
|
|
|
|
* resetting the headline at the same time.
|
|
|
|
*/
|
|
|
|
private void resetStateFromCurrentFragment() {
|
|
|
|
AccountSetupFragment f = getContentFragment();
|
|
|
|
mState = f.getState();
|
|
|
|
}
|
|
|
|
|
2014-01-16 17:59:39 +00:00
|
|
|
/**
|
|
|
|
* Main choreography function to handle moving forward through scenes. Moving back should be
|
|
|
|
* generally handled for us by the back stack
|
|
|
|
*/
|
|
|
|
protected void proceed() {
|
|
|
|
mIsProcessing = false;
|
2014-03-17 23:45:47 +00:00
|
|
|
final AccountSetupFragment oldContentFragment = getContentFragment();
|
|
|
|
if (oldContentFragment != null) {
|
|
|
|
oldContentFragment.setNextButtonEnabled(true);
|
|
|
|
}
|
2014-01-16 17:59:39 +00:00
|
|
|
|
2014-02-13 21:12:06 +00:00
|
|
|
getFragmentManager().executePendingTransactions();
|
|
|
|
|
2014-01-16 17:59:39 +00:00
|
|
|
switch (mState) {
|
2014-02-13 21:12:06 +00:00
|
|
|
case STATE_BASICS:
|
2014-03-13 21:11:06 +00:00
|
|
|
final boolean advance = onBasicsComplete();
|
|
|
|
if (!advance) {
|
|
|
|
mState = STATE_BASICS_POST;
|
|
|
|
break;
|
|
|
|
} // else fall through
|
|
|
|
case STATE_BASICS_POST:
|
2014-03-05 22:08:06 +00:00
|
|
|
if (shouldDivertToManual()) {
|
|
|
|
mSkipAutoDiscover = true;
|
2014-03-13 21:11:06 +00:00
|
|
|
mIsPreConfiguredProvider = false;
|
2014-03-05 22:08:06 +00:00
|
|
|
mState = STATE_TYPE;
|
|
|
|
} else {
|
|
|
|
mSkipAutoDiscover = false;
|
2014-03-13 21:11:06 +00:00
|
|
|
if (mIsPreConfiguredProvider) {
|
2014-03-31 23:43:14 +00:00
|
|
|
if (!TextUtils.isEmpty(mSetupData.getAmProtocol()) &&
|
|
|
|
!TextUtils.equals(mSetupData.getAmProtocol(),
|
|
|
|
mSetupData.getIncomingProtocol(this))) {
|
2014-03-28 23:07:56 +00:00
|
|
|
mState = STATE_AB;
|
|
|
|
} else {
|
|
|
|
mState = STATE_CREDENTIALS;
|
2014-07-31 17:40:53 +00:00
|
|
|
if (possiblyDivertToGmail()) {
|
|
|
|
return;
|
|
|
|
}
|
2014-03-28 23:07:56 +00:00
|
|
|
}
|
2014-03-13 21:11:06 +00:00
|
|
|
} else {
|
2014-03-14 22:48:10 +00:00
|
|
|
final String amProtocol = mSetupData.getAmProtocol();
|
|
|
|
if (!TextUtils.isEmpty(amProtocol)) {
|
|
|
|
mSetupData.setIncomingProtocol(this, amProtocol);
|
|
|
|
final Account account = mSetupData.getAccount();
|
|
|
|
setDefaultsForProtocol(account);
|
|
|
|
mState = STATE_CREDENTIALS;
|
|
|
|
} else {
|
|
|
|
mState = STATE_TYPE;
|
|
|
|
}
|
2014-03-13 21:11:06 +00:00
|
|
|
}
|
2014-03-05 22:08:06 +00:00
|
|
|
}
|
2014-02-13 21:12:06 +00:00
|
|
|
updateContentFragment(true /* addToBackstack */);
|
|
|
|
break;
|
2014-03-13 21:11:06 +00:00
|
|
|
case STATE_TYPE:
|
|
|
|
// We either got here through "Manual Setup" or because we didn't find the provider
|
|
|
|
mState = STATE_CREDENTIALS;
|
|
|
|
updateContentFragment(true /* addToBackstack */);
|
|
|
|
break;
|
2014-03-28 23:07:56 +00:00
|
|
|
case STATE_AB:
|
2014-07-31 17:40:53 +00:00
|
|
|
if (possiblyDivertToGmail()) {
|
|
|
|
return;
|
|
|
|
}
|
2014-03-28 23:07:56 +00:00
|
|
|
mState = STATE_CREDENTIALS;
|
|
|
|
updateContentFragment(true /* addToBackstack */);
|
|
|
|
break;
|
2014-02-13 21:12:06 +00:00
|
|
|
case STATE_CREDENTIALS:
|
2014-03-13 21:11:06 +00:00
|
|
|
collectCredentials();
|
2014-02-13 21:12:06 +00:00
|
|
|
if (mIsPreConfiguredProvider) {
|
|
|
|
mState = STATE_CHECKING_PRECONFIGURED;
|
|
|
|
initiateCheckSettingsFragment(SetupDataFragment.CHECK_INCOMING
|
|
|
|
| SetupDataFragment.CHECK_OUTGOING);
|
|
|
|
} else {
|
2014-04-02 20:30:51 +00:00
|
|
|
populateHostAuthsFromSetupData();
|
2014-03-13 21:11:06 +00:00
|
|
|
if (mSkipAutoDiscover) {
|
|
|
|
mState = STATE_MANUAL_INCOMING;
|
|
|
|
updateContentFragment(true /* addToBackstack */);
|
|
|
|
} else {
|
|
|
|
mState = STATE_AUTO_DISCOVER;
|
|
|
|
initiateAutoDiscover();
|
|
|
|
}
|
2014-02-13 21:12:06 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATE_CHECKING_PRECONFIGURED:
|
|
|
|
if (mPreConfiguredFailed) {
|
2014-03-13 17:56:24 +00:00
|
|
|
if (mPasswordFailed) {
|
|
|
|
// Get rid of the previous instance of the AccountSetupCredentialsFragment.
|
|
|
|
FragmentManager fm = getFragmentManager();
|
|
|
|
fm.popBackStackImmediate(CREDENTIALS_BACKSTACK_TAG, 0);
|
|
|
|
final AccountSetupCredentialsFragment f = (AccountSetupCredentialsFragment)
|
|
|
|
getContentFragment();
|
|
|
|
f.setPasswordFailed(mPasswordFailed);
|
|
|
|
resetStateFromCurrentFragment();
|
|
|
|
} else {
|
|
|
|
mState = STATE_MANUAL_INCOMING;
|
|
|
|
updateContentFragment(true /* addToBackstack */);
|
|
|
|
}
|
2014-02-13 21:12:06 +00:00
|
|
|
} else {
|
|
|
|
mState = STATE_OPTIONS;
|
|
|
|
updateContentFragment(true /* addToBackstack */);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATE_AUTO_DISCOVER:
|
|
|
|
// TODO: figure out if we can skip past manual setup
|
|
|
|
mState = STATE_MANUAL_INCOMING;
|
|
|
|
updateContentFragment(true);
|
|
|
|
break;
|
|
|
|
case STATE_MANUAL_INCOMING:
|
|
|
|
onIncomingComplete();
|
|
|
|
mState = STATE_CHECKING_INCOMING;
|
|
|
|
initiateCheckSettingsFragment(SetupDataFragment.CHECK_INCOMING);
|
|
|
|
break;
|
|
|
|
case STATE_CHECKING_INCOMING:
|
|
|
|
final EmailServiceUtils.EmailServiceInfo serviceInfo =
|
2014-03-07 19:15:44 +00:00
|
|
|
mSetupData.getIncomingServiceInfo(this);
|
2014-02-13 21:12:06 +00:00
|
|
|
if (serviceInfo.usesSmtp) {
|
|
|
|
mState = STATE_MANUAL_OUTGOING;
|
|
|
|
} else {
|
|
|
|
mState = STATE_OPTIONS;
|
|
|
|
}
|
|
|
|
updateContentFragment(true /* addToBackstack */);
|
|
|
|
break;
|
|
|
|
case STATE_MANUAL_OUTGOING:
|
|
|
|
onOutgoingComplete();
|
|
|
|
mState = STATE_CHECKING_OUTGOING;
|
|
|
|
initiateCheckSettingsFragment(SetupDataFragment.CHECK_OUTGOING);
|
|
|
|
break;
|
|
|
|
case STATE_CHECKING_OUTGOING:
|
|
|
|
mState = STATE_OPTIONS;
|
|
|
|
updateContentFragment(true /* addToBackstack */);
|
|
|
|
break;
|
2014-01-16 17:59:39 +00:00
|
|
|
case STATE_OPTIONS:
|
2014-02-13 21:12:06 +00:00
|
|
|
mState = STATE_CREATING;
|
|
|
|
initiateAccountCreation();
|
|
|
|
break;
|
|
|
|
case STATE_CREATING:
|
2014-01-16 17:59:39 +00:00
|
|
|
mState = STATE_NAMES;
|
2014-01-22 18:59:22 +00:00
|
|
|
updateContentFragment(true /* addToBackstack */);
|
2014-09-07 20:36:33 +00:00
|
|
|
if (mSetupData.getFlowMode() ==
|
|
|
|
AuthenticatorSetupIntentHelper.FLOW_MODE_FORCE_CREATE) {
|
2014-01-16 17:59:39 +00:00
|
|
|
getFragmentManager().executePendingTransactions();
|
|
|
|
initiateAccountFinalize();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATE_NAMES:
|
2014-02-13 21:12:06 +00:00
|
|
|
initiateAccountFinalize();
|
|
|
|
break;
|
|
|
|
case STATE_FINALIZE:
|
|
|
|
finish();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LogUtils.wtf(LogUtils.TAG, "Unknown state %d", mState);
|
2014-01-16 17:59:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-31 17:40:53 +00:00
|
|
|
/**
|
|
|
|
* Check if we should divert to creating a Gmail account instead
|
|
|
|
* @return true if we diverted
|
|
|
|
*/
|
|
|
|
private boolean possiblyDivertToGmail() {
|
|
|
|
// TODO: actually divert here
|
|
|
|
final EmailServiceUtils.EmailServiceInfo info =
|
|
|
|
mSetupData.getIncomingServiceInfo(this);
|
|
|
|
if (TextUtils.equals(info.protocol, "gmail")) {
|
|
|
|
final Bundle options = new Bundle(1);
|
|
|
|
options.putBoolean("allowSkip", false);
|
|
|
|
AccountManager.get(this).addAccount("com.google",
|
|
|
|
"mail" /* authTokenType */,
|
|
|
|
null,
|
|
|
|
options,
|
|
|
|
this, null, null);
|
|
|
|
|
|
|
|
finish();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-01-16 17:59:39 +00:00
|
|
|
/**
|
|
|
|
* Block the back key if we are currently processing the "next" key"
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onBackPressed() {
|
|
|
|
if (mIsProcessing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (mState == STATE_NAMES) {
|
2014-02-13 21:12:06 +00:00
|
|
|
finish();
|
2014-01-16 17:59:39 +00:00
|
|
|
} else {
|
|
|
|
super.onBackPressed();
|
|
|
|
}
|
2014-02-13 21:12:06 +00:00
|
|
|
// After super.onBackPressed() our fragment should be in place, so query the state we
|
|
|
|
// installed it for
|
2014-02-28 23:56:25 +00:00
|
|
|
resetStateFromCurrentFragment();
|
2014-01-16 17:59:39 +00:00
|
|
|
}
|
|
|
|
|
2014-02-13 21:12:06 +00:00
|
|
|
@Override
|
|
|
|
public void setAccount(Account account) {
|
|
|
|
mSetupData.setAccount(account);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void finish() {
|
|
|
|
// If the account manager initiated the creation, and success was not reported,
|
|
|
|
// then we assume that we're giving up (for any reason) - report failure.
|
|
|
|
if (mReportAccountAuthenticatorError) {
|
|
|
|
if (mAccountAuthenticatorResponse != null) {
|
|
|
|
mAccountAuthenticatorResponse
|
|
|
|
.onError(AccountManager.ERROR_CODE_CANCELED, "canceled");
|
|
|
|
mAccountAuthenticatorResponse = null;
|
2014-01-16 17:59:39 +00:00
|
|
|
}
|
|
|
|
}
|
2014-02-13 21:12:06 +00:00
|
|
|
super.finish();
|
2014-01-16 17:59:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2014-03-17 23:45:47 +00:00
|
|
|
public void onNextButton() {
|
|
|
|
// Some states are handled without UI, block double-presses here
|
|
|
|
if (!mIsProcessing) {
|
|
|
|
proceed();
|
2014-01-16 17:59:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-13 21:11:06 +00:00
|
|
|
/**
|
|
|
|
* @return true to proceed, false to remain on the current screen
|
|
|
|
*/
|
|
|
|
private boolean onBasicsComplete() {
|
2014-02-13 21:12:06 +00:00
|
|
|
final AccountSetupBasicsFragment f = (AccountSetupBasicsFragment) getContentFragment();
|
|
|
|
final String email = f.getEmail();
|
2014-03-13 21:11:06 +00:00
|
|
|
|
2014-03-28 23:07:56 +00:00
|
|
|
// Reset the protocol choice in case the user has back-navigated here
|
|
|
|
mSetupData.setIncomingProtocol(this, null);
|
|
|
|
|
2014-03-13 17:56:24 +00:00
|
|
|
if (!TextUtils.equals(email, mSetupData.getEmail())) {
|
|
|
|
// If the user changes their email address, clear the password failed state
|
|
|
|
mPasswordFailed = false;
|
|
|
|
}
|
2014-02-13 21:12:06 +00:00
|
|
|
mSetupData.setEmail(email);
|
|
|
|
|
|
|
|
final String[] emailParts = email.split("@");
|
|
|
|
final String domain = emailParts[1].trim();
|
|
|
|
mProvider = AccountSettingsUtils.findProviderForDomain(this, domain);
|
|
|
|
if (mProvider != null) {
|
|
|
|
mIsPreConfiguredProvider = true;
|
|
|
|
if (mProvider.note != null) {
|
|
|
|
final AccountSetupNoteDialogFragment dialogFragment =
|
|
|
|
AccountSetupNoteDialogFragment.newInstance(mProvider.note);
|
|
|
|
dialogFragment.show(getFragmentManager(), AccountSetupNoteDialogFragment.TAG);
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
return finishAutoSetup();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
mIsPreConfiguredProvider = false;
|
2014-06-23 22:10:11 +00:00
|
|
|
final String existingAccountName =
|
|
|
|
mExistingAccountsMap != null ? mExistingAccountsMap.get(email) : null;
|
2014-02-13 21:12:06 +00:00
|
|
|
if (!TextUtils.isEmpty(existingAccountName)) {
|
2014-03-19 22:20:39 +00:00
|
|
|
showDuplicateAccountDialog(existingAccountName);
|
2014-02-13 21:12:06 +00:00
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
populateSetupData(mOwnerName, email);
|
|
|
|
mSkipAutoDiscover = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-19 22:20:39 +00:00
|
|
|
private void showDuplicateAccountDialog(final String existingAccountName) {
|
|
|
|
final DuplicateAccountDialogFragment dialogFragment =
|
|
|
|
DuplicateAccountDialogFragment.newInstance(existingAccountName);
|
|
|
|
dialogFragment.show(getFragmentManager(), DuplicateAccountDialogFragment.TAG);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onDuplicateAccountDialogDismiss() {
|
|
|
|
resetStateFromCurrentFragment();
|
|
|
|
}
|
|
|
|
|
2014-03-13 21:11:06 +00:00
|
|
|
private boolean shouldDivertToManual() {
|
|
|
|
final AccountSetupBasicsFragment f = (AccountSetupBasicsFragment) getContentFragment();
|
|
|
|
return f.isManualSetup();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onCredentialsComplete(Bundle results) {
|
|
|
|
proceed();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void collectCredentials() {
|
|
|
|
final AccountSetupCredentialsFragment f = (AccountSetupCredentialsFragment)
|
|
|
|
getContentFragment();
|
|
|
|
final Bundle results = f.getCredentialResults();
|
|
|
|
mSetupData.setCredentialResults(results);
|
2014-03-18 23:45:07 +00:00
|
|
|
final Account account = mSetupData.getAccount();
|
|
|
|
final HostAuth recvAuth = account.getOrCreateHostAuthRecv(this);
|
|
|
|
AccountSetupCredentialsFragment.populateHostAuthWithResults(this, recvAuth,
|
|
|
|
mSetupData.getCredentialResults());
|
|
|
|
mSetupData.setIncomingCredLoaded(true);
|
|
|
|
final EmailServiceUtils.EmailServiceInfo info = mSetupData.getIncomingServiceInfo(this);
|
|
|
|
if (info.usesSmtp) {
|
|
|
|
final HostAuth sendAuth = account.getOrCreateHostAuthSend(this);
|
|
|
|
AccountSetupCredentialsFragment.populateHostAuthWithResults(this, sendAuth,
|
|
|
|
mSetupData.getCredentialResults());
|
|
|
|
mSetupData.setOutgoingCredLoaded(true);
|
|
|
|
}
|
2014-03-13 21:11:06 +00:00
|
|
|
}
|
|
|
|
|
2014-02-13 21:12:06 +00:00
|
|
|
@Override
|
|
|
|
public void onNoteDialogComplete() {
|
|
|
|
finishAutoSetup();
|
2014-03-13 21:11:06 +00:00
|
|
|
proceed();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onNoteDialogCancel() {
|
|
|
|
resetStateFromCurrentFragment();
|
2014-02-13 21:12:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Finish the auto setup process, in some cases after showing a warning dialog.
|
|
|
|
* Happens after onBasicsComplete
|
|
|
|
* @return true to proceed, false to remain on the current screen
|
|
|
|
*/
|
|
|
|
private boolean finishAutoSetup() {
|
|
|
|
final String email = mSetupData.getEmail();
|
|
|
|
|
|
|
|
try {
|
|
|
|
mProvider.expandTemplates(email);
|
|
|
|
|
2014-08-15 18:18:10 +00:00
|
|
|
final String primaryProtocol = HostAuth.getProtocolFromString(mProvider.incomingUri);
|
|
|
|
EmailServiceUtils.EmailServiceInfo info =
|
|
|
|
EmailServiceUtils.getServiceInfo(this, primaryProtocol);
|
2014-07-31 17:40:53 +00:00
|
|
|
// If the protocol isn't one we can use, and we're not diverting to gmail, try the alt
|
|
|
|
if (!info.isGmailStub && !EmailServiceUtils.isServiceAvailable(this, info.protocol)) {
|
|
|
|
LogUtils.d(LogUtils.TAG, "Protocol %s not available, using alternate",
|
|
|
|
info.protocol);
|
|
|
|
mProvider.expandAlternateTemplates(email);
|
2014-08-15 18:18:10 +00:00
|
|
|
final String alternateProtocol = HostAuth.getProtocolFromString(
|
|
|
|
mProvider.incomingUri);
|
|
|
|
info = EmailServiceUtils.getServiceInfo(this, alternateProtocol);
|
2014-07-31 17:40:53 +00:00
|
|
|
}
|
2014-08-15 18:18:10 +00:00
|
|
|
final Account account = mSetupData.getAccount();
|
|
|
|
final HostAuth recvAuth = account.getOrCreateHostAuthRecv(this);
|
|
|
|
recvAuth.setHostAuthFromString(mProvider.incomingUri);
|
2014-07-31 17:40:53 +00:00
|
|
|
|
|
|
|
recvAuth.setUserName(mProvider.incomingUsername);
|
2014-02-13 21:12:06 +00:00
|
|
|
recvAuth.mPort =
|
|
|
|
((recvAuth.mFlags & HostAuth.FLAG_SSL) != 0) ? info.portSsl : info.port;
|
|
|
|
|
2014-03-07 19:15:44 +00:00
|
|
|
if (info.usesSmtp) {
|
|
|
|
final HostAuth sendAuth = account.getOrCreateHostAuthSend(this);
|
|
|
|
sendAuth.setHostAuthFromString(mProvider.outgoingUri);
|
|
|
|
sendAuth.setUserName(mProvider.outgoingUsername);
|
|
|
|
}
|
2014-02-13 21:12:06 +00:00
|
|
|
|
|
|
|
// Populate the setup data, assuming that the duplicate account check will succeed
|
|
|
|
populateSetupData(mOwnerName, email);
|
|
|
|
|
|
|
|
final String duplicateAccountName =
|
|
|
|
mExistingAccountsMap != null ? mExistingAccountsMap.get(email) : null;
|
|
|
|
if (duplicateAccountName != null) {
|
2014-03-19 22:20:39 +00:00
|
|
|
showDuplicateAccountDialog(duplicateAccountName);
|
2014-02-13 21:12:06 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} catch (URISyntaxException e) {
|
|
|
|
mSkipAutoDiscover = false;
|
|
|
|
mPreConfiguredFailed = true;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper method to fill in some per-protocol defaults
|
|
|
|
* @param account Account object to fill in
|
|
|
|
*/
|
|
|
|
public void setDefaultsForProtocol(Account account) {
|
2014-03-07 19:15:44 +00:00
|
|
|
final EmailServiceUtils.EmailServiceInfo info = mSetupData.getIncomingServiceInfo(this);
|
|
|
|
if (info == null) return;
|
2014-02-13 21:12:06 +00:00
|
|
|
account.mSyncInterval = info.defaultSyncInterval;
|
|
|
|
account.mSyncLookback = info.defaultLookback;
|
|
|
|
if (info.offerLocalDeletes) {
|
|
|
|
account.setDeletePolicy(info.defaultLocalDeletes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Populate SetupData's account with complete setup info, assumes that the receive auth is
|
|
|
|
* created and its protocol is set
|
|
|
|
*/
|
|
|
|
private void populateSetupData(String senderName, String senderEmail) {
|
|
|
|
final Account account = mSetupData.getAccount();
|
|
|
|
account.setSenderName(senderName);
|
|
|
|
account.setEmailAddress(senderEmail);
|
|
|
|
account.setDisplayName(senderEmail);
|
|
|
|
setDefaultsForProtocol(account);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void onIncomingComplete() {
|
|
|
|
AccountSetupIncomingFragment f = (AccountSetupIncomingFragment) getContentFragment();
|
|
|
|
f.collectUserInput();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void onOutgoingComplete() {
|
|
|
|
AccountSetupOutgoingFragment f = (AccountSetupOutgoingFragment) getContentFragment();
|
|
|
|
f.collectUserInput();
|
|
|
|
}
|
|
|
|
|
|
|
|
// This callback method is only applicable to using Incoming/Outgoing fragments in settings mode
|
|
|
|
@Override
|
|
|
|
public void onAccountServerUIComplete(int checkMode) {}
|
|
|
|
|
|
|
|
// This callback method is only applicable to using Incoming/Outgoing fragments in settings mode
|
|
|
|
@Override
|
|
|
|
public void onAccountServerSaveComplete() {}
|
|
|
|
|
2014-04-02 20:30:51 +00:00
|
|
|
private void populateHostAuthsFromSetupData() {
|
2014-03-07 19:15:44 +00:00
|
|
|
final String email = mSetupData.getEmail();
|
|
|
|
final String[] emailParts = email.split("@");
|
|
|
|
final String domain = emailParts[1];
|
|
|
|
|
|
|
|
final Account account = mSetupData.getAccount();
|
|
|
|
|
|
|
|
final HostAuth recvAuth = account.getOrCreateHostAuthRecv(this);
|
|
|
|
recvAuth.setUserName(email);
|
|
|
|
recvAuth.setConnection(mSetupData.getIncomingProtocol(), domain,
|
|
|
|
HostAuth.PORT_UNKNOWN, HostAuth.FLAG_NONE);
|
|
|
|
AccountSetupCredentialsFragment.populateHostAuthWithResults(this, recvAuth,
|
|
|
|
mSetupData.getCredentialResults());
|
|
|
|
mSetupData.setIncomingCredLoaded(true);
|
|
|
|
|
|
|
|
final EmailServiceUtils.EmailServiceInfo info =
|
|
|
|
mSetupData.getIncomingServiceInfo(this);
|
|
|
|
if (info.usesSmtp) {
|
|
|
|
final HostAuth sendAuth = account.getOrCreateHostAuthSend(this);
|
|
|
|
sendAuth.setUserName(email);
|
|
|
|
sendAuth.setConnection(HostAuth.LEGACY_SCHEME_SMTP, domain,
|
|
|
|
HostAuth.PORT_UNKNOWN, HostAuth.FLAG_NONE);
|
|
|
|
AccountSetupCredentialsFragment.populateHostAuthWithResults(this, sendAuth,
|
|
|
|
mSetupData.getCredentialResults());
|
|
|
|
mSetupData.setOutgoingCredLoaded(true);
|
|
|
|
}
|
2014-04-02 20:30:51 +00:00
|
|
|
}
|
2014-03-07 19:15:44 +00:00
|
|
|
|
2014-04-02 20:30:51 +00:00
|
|
|
private void initiateAutoDiscover() {
|
2014-03-07 19:15:44 +00:00
|
|
|
// Populate the setup data, assuming that the duplicate account check will succeed
|
|
|
|
initiateCheckSettingsFragment(SetupDataFragment.CHECK_AUTODISCOVER);
|
|
|
|
}
|
|
|
|
|
2014-02-13 21:12:06 +00:00
|
|
|
private void initiateCheckSettingsFragment(int checkMode) {
|
|
|
|
final Fragment f = AccountCheckSettingsFragment.newInstance(checkMode);
|
|
|
|
final Fragment d = CheckSettingsProgressDialogFragment.newInstance(checkMode);
|
|
|
|
getFragmentManager().beginTransaction()
|
|
|
|
.add(f, AccountCheckSettingsFragment.TAG)
|
|
|
|
.add(d, CheckSettingsProgressDialogFragment.TAG)
|
|
|
|
.commit();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onCheckSettingsProgressDialogCancel() {
|
|
|
|
dismissCheckSettingsFragment();
|
2014-03-19 22:20:39 +00:00
|
|
|
resetStateFromCurrentFragment();
|
2014-02-13 21:12:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private void dismissCheckSettingsFragment() {
|
|
|
|
final Fragment f = getFragmentManager().findFragmentByTag(AccountCheckSettingsFragment.TAG);
|
|
|
|
final Fragment d =
|
|
|
|
getFragmentManager().findFragmentByTag(CheckSettingsProgressDialogFragment.TAG);
|
|
|
|
getFragmentManager().beginTransaction()
|
|
|
|
.remove(f)
|
|
|
|
.remove(d)
|
|
|
|
.commit();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onCheckSettingsError(int reason, String message) {
|
2014-03-13 17:56:24 +00:00
|
|
|
if (reason == CheckSettingsErrorDialogFragment.REASON_AUTHENTICATION_FAILED ||
|
|
|
|
reason == CheckSettingsErrorDialogFragment.REASON_CERTIFICATE_REQUIRED) {
|
|
|
|
// TODO: possibly split password and cert error conditions
|
|
|
|
mPasswordFailed = true;
|
|
|
|
}
|
2014-02-13 21:12:06 +00:00
|
|
|
dismissCheckSettingsFragment();
|
|
|
|
final DialogFragment f =
|
|
|
|
CheckSettingsErrorDialogFragment.newInstance(reason, message);
|
|
|
|
f.show(getFragmentManager(), CheckSettingsErrorDialogFragment.TAG);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onCheckSettingsErrorDialogEditCertificate() {
|
|
|
|
if (mState == STATE_CHECKING_PRECONFIGURED) {
|
|
|
|
mPreConfiguredFailed = true;
|
|
|
|
proceed();
|
2014-02-28 23:56:25 +00:00
|
|
|
} else {
|
|
|
|
resetStateFromCurrentFragment();
|
2014-02-13 21:12:06 +00:00
|
|
|
}
|
|
|
|
final AccountSetupIncomingFragment f = (AccountSetupIncomingFragment) getContentFragment();
|
|
|
|
f.onCertificateRequested();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onCheckSettingsErrorDialogEditSettings() {
|
2014-03-12 18:00:24 +00:00
|
|
|
// If we're checking pre-configured, set a flag that we failed and navigate forwards to
|
2014-02-13 21:12:06 +00:00
|
|
|
// incoming settings
|
|
|
|
if (mState == STATE_CHECKING_PRECONFIGURED || mState == STATE_AUTO_DISCOVER) {
|
|
|
|
mPreConfiguredFailed = true;
|
|
|
|
proceed();
|
2014-02-28 23:56:25 +00:00
|
|
|
} else {
|
|
|
|
resetStateFromCurrentFragment();
|
2014-02-13 21:12:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onCheckSettingsComplete() {
|
2014-03-12 18:00:24 +00:00
|
|
|
mPreConfiguredFailed = false;
|
|
|
|
mPasswordFailed = false;
|
2014-02-13 21:12:06 +00:00
|
|
|
dismissCheckSettingsFragment();
|
|
|
|
proceed();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onCheckSettingsAutoDiscoverComplete(int result) {
|
|
|
|
dismissCheckSettingsFragment();
|
|
|
|
proceed();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onCheckSettingsSecurityRequired(String hostName) {
|
|
|
|
dismissCheckSettingsFragment();
|
|
|
|
final DialogFragment f = SecurityRequiredDialogFragment.newInstance(hostName);
|
|
|
|
f.show(getFragmentManager(), SecurityRequiredDialogFragment.TAG);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onSecurityRequiredDialogResult(boolean ok) {
|
|
|
|
if (ok) {
|
|
|
|
proceed();
|
2014-02-28 23:56:25 +00:00
|
|
|
} else {
|
|
|
|
resetStateFromCurrentFragment();
|
2014-02-13 21:12:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onChooseProtocol(String protocol) {
|
2014-03-07 19:15:44 +00:00
|
|
|
mSetupData.setIncomingProtocol(this, protocol);
|
2014-02-13 21:12:06 +00:00
|
|
|
final Account account = mSetupData.getAccount();
|
|
|
|
setDefaultsForProtocol(account);
|
|
|
|
proceed();
|
|
|
|
}
|
|
|
|
|
2014-03-28 23:07:56 +00:00
|
|
|
@Override
|
|
|
|
public void onABProtocolDisambiguated(String chosenProtocol) {
|
|
|
|
if (!TextUtils.equals(mSetupData.getIncomingProtocol(this), chosenProtocol)) {
|
|
|
|
mIsPreConfiguredProvider = false;
|
|
|
|
mSetupData.setIncomingProtocol(this, chosenProtocol);
|
|
|
|
final Account account = mSetupData.getAccount();
|
|
|
|
setDefaultsForProtocol(account);
|
|
|
|
}
|
|
|
|
proceed();
|
|
|
|
}
|
|
|
|
|
2014-01-16 17:59:39 +00:00
|
|
|
/**
|
|
|
|
* Ths is called when the user clicks the "done" button.
|
|
|
|
* It collects the data from the UI, updates the setup account record, and launches a fragment
|
|
|
|
* which handles creating the account in the system and database.
|
|
|
|
*/
|
|
|
|
private void initiateAccountCreation() {
|
|
|
|
mIsProcessing = true;
|
2014-03-17 23:45:47 +00:00
|
|
|
getContentFragment().setNextButtonEnabled(false);
|
2014-01-16 17:59:39 +00:00
|
|
|
|
|
|
|
final Account account = mSetupData.getAccount();
|
|
|
|
if (account.mHostAuthRecv == null) {
|
|
|
|
throw new IllegalStateException("in AccountSetupOptions with null mHostAuthRecv");
|
|
|
|
}
|
|
|
|
|
|
|
|
final AccountSetupOptionsFragment fragment = (AccountSetupOptionsFragment)
|
|
|
|
getContentFragment();
|
|
|
|
if (fragment == null) {
|
|
|
|
throw new IllegalStateException("Fragment missing!");
|
|
|
|
}
|
|
|
|
|
|
|
|
account.setDisplayName(account.getEmailAddress());
|
|
|
|
int newFlags = account.getFlags() & ~(Account.FLAGS_BACKGROUND_ATTACHMENTS);
|
|
|
|
final EmailServiceUtils.EmailServiceInfo serviceInfo =
|
2014-03-07 19:15:44 +00:00
|
|
|
mSetupData.getIncomingServiceInfo(this);
|
2014-01-16 17:59:39 +00:00
|
|
|
if (serviceInfo.offerAttachmentPreload && fragment.getBackgroundAttachmentsValue()) {
|
|
|
|
newFlags |= Account.FLAGS_BACKGROUND_ATTACHMENTS;
|
|
|
|
}
|
2014-04-01 21:37:36 +00:00
|
|
|
final HostAuth hostAuth = account.getOrCreateHostAuthRecv(this);
|
|
|
|
if (hostAuth.mProtocol.equals(getString(R.string.protocol_eas))) {
|
|
|
|
try {
|
|
|
|
final double protocolVersionDouble = Double.parseDouble(account.mProtocolVersion);
|
|
|
|
if (protocolVersionDouble >= 12.0) {
|
|
|
|
// If the the account is EAS and the protocol version is above 12.0,
|
|
|
|
// we know that SmartForward is enabled and the various search flags
|
|
|
|
// should be enabled first.
|
|
|
|
// TODO: Move this into protocol specific code in the future.
|
|
|
|
newFlags |= Account.FLAGS_SUPPORTS_SMART_FORWARD |
|
|
|
|
Account.FLAGS_SUPPORTS_GLOBAL_SEARCH | Account.FLAGS_SUPPORTS_SEARCH;
|
|
|
|
}
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
LogUtils.wtf(LogUtils.TAG, e, "Exception thrown parsing the protocol version.");
|
|
|
|
}
|
|
|
|
}
|
2014-01-16 17:59:39 +00:00
|
|
|
account.setFlags(newFlags);
|
|
|
|
account.setSyncInterval(fragment.getCheckFrequencyValue());
|
|
|
|
final Integer syncWindowValue = fragment.getAccountSyncWindowValue();
|
|
|
|
if (syncWindowValue != null) {
|
|
|
|
account.setSyncLookback(syncWindowValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finish setting up the account, and commit it to the database
|
|
|
|
if (mSetupData.getPolicy() != null) {
|
|
|
|
account.mFlags |= Account.FLAGS_SECURITY_HOLD;
|
|
|
|
account.mPolicy = mSetupData.getPolicy();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, write the completed account (for the first time) and then
|
|
|
|
// install it into the Account manager as well. These are done off-thread.
|
|
|
|
// The account manager will report back via the callback, which will take us to
|
|
|
|
// the next operations.
|
|
|
|
final boolean syncEmail = fragment.getSyncEmailValue();
|
|
|
|
final boolean syncCalendar = serviceInfo.syncCalendar && fragment.getSyncCalendarValue();
|
|
|
|
final boolean syncContacts = serviceInfo.syncContacts && fragment.getSyncContactsValue();
|
|
|
|
final boolean enableNotifications = fragment.getNotifyValue();
|
|
|
|
|
|
|
|
final Fragment f = AccountCreationFragment.newInstance(account, syncEmail, syncCalendar,
|
|
|
|
syncContacts, enableNotifications);
|
|
|
|
final FragmentTransaction ft = getFragmentManager().beginTransaction();
|
2014-02-13 21:12:06 +00:00
|
|
|
ft.add(f, AccountCreationFragment.TAG);
|
2014-01-16 17:59:39 +00:00
|
|
|
ft.commit();
|
|
|
|
|
|
|
|
showCreateAccountDialog();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called by the account creation fragment after it has completed.
|
|
|
|
* We do a small amount of work here before moving on to the next state.
|
|
|
|
*/
|
2014-03-11 19:56:51 +00:00
|
|
|
@Override
|
2014-02-13 21:12:06 +00:00
|
|
|
public void onAccountCreationFragmentComplete() {
|
2014-01-16 17:59:39 +00:00
|
|
|
destroyAccountCreationFragment();
|
|
|
|
// If the account manager initiated the creation, and success was not reported,
|
|
|
|
// then we assume that we're giving up (for any reason) - report failure.
|
2014-02-13 21:12:06 +00:00
|
|
|
if (mAccountAuthenticatorResponse != null) {
|
2014-03-07 19:15:44 +00:00
|
|
|
final EmailServiceUtils.EmailServiceInfo info = mSetupData.getIncomingServiceInfo(this);
|
2014-02-13 21:12:06 +00:00
|
|
|
final Bundle b = new Bundle(2);
|
2014-03-07 19:15:44 +00:00
|
|
|
b.putString(AccountManager.KEY_ACCOUNT_NAME, mSetupData.getEmail());
|
2014-02-13 21:12:06 +00:00
|
|
|
b.putString(AccountManager.KEY_ACCOUNT_TYPE, info.accountType);
|
|
|
|
mAccountAuthenticatorResponse.onResult(b);
|
|
|
|
mAccountAuthenticatorResponse = null;
|
|
|
|
mReportAccountAuthenticatorError = false;
|
2014-01-16 17:59:39 +00:00
|
|
|
}
|
2014-02-28 19:33:43 +00:00
|
|
|
setResult(RESULT_OK);
|
2014-01-16 17:59:39 +00:00
|
|
|
proceed();
|
|
|
|
}
|
|
|
|
|
2014-03-11 19:56:51 +00:00
|
|
|
@Override
|
2014-01-16 17:59:39 +00:00
|
|
|
public void destroyAccountCreationFragment() {
|
|
|
|
dismissCreateAccountDialog();
|
|
|
|
|
2014-02-13 21:12:06 +00:00
|
|
|
final Fragment f = getFragmentManager().findFragmentByTag(AccountCreationFragment.TAG);
|
2014-01-16 17:59:39 +00:00
|
|
|
if (f == null) {
|
|
|
|
LogUtils.wtf(LogUtils.TAG, "Couldn't find AccountCreationFragment to destroy");
|
|
|
|
}
|
2014-02-13 21:12:06 +00:00
|
|
|
getFragmentManager().beginTransaction()
|
|
|
|
.remove(f)
|
|
|
|
.commit();
|
2014-01-16 17:59:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static class CreateAccountDialogFragment extends DialogFragment {
|
2014-02-13 21:12:06 +00:00
|
|
|
public static final String TAG = "CreateAccountDialogFragment";
|
2014-01-21 21:58:10 +00:00
|
|
|
public CreateAccountDialogFragment() {}
|
2014-01-16 17:59:39 +00:00
|
|
|
|
2014-02-13 21:12:06 +00:00
|
|
|
public static CreateAccountDialogFragment newInstance() {
|
|
|
|
return new CreateAccountDialogFragment();
|
|
|
|
}
|
|
|
|
|
2014-01-16 17:59:39 +00:00
|
|
|
@Override
|
|
|
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
|
|
|
/// Show "Creating account..." dialog
|
2014-03-19 22:20:39 +00:00
|
|
|
setCancelable(false);
|
2014-01-16 17:59:39 +00:00
|
|
|
final ProgressDialog d = new ProgressDialog(getActivity());
|
|
|
|
d.setIndeterminate(true);
|
|
|
|
d.setMessage(getString(R.string.account_setup_creating_account_msg));
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void showCreateAccountDialog() {
|
2014-02-13 21:12:06 +00:00
|
|
|
CreateAccountDialogFragment.newInstance()
|
|
|
|
.show(getFragmentManager(), CreateAccountDialogFragment.TAG);
|
2014-01-16 17:59:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected void dismissCreateAccountDialog() {
|
|
|
|
final DialogFragment f = (DialogFragment)
|
2014-02-13 21:12:06 +00:00
|
|
|
getFragmentManager().findFragmentByTag(CreateAccountDialogFragment.TAG);
|
2014-01-16 17:59:39 +00:00
|
|
|
if (f != null) {
|
|
|
|
f.dismiss();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static class CreateAccountErrorDialogFragment extends DialogFragment
|
|
|
|
implements DialogInterface.OnClickListener {
|
|
|
|
public CreateAccountErrorDialogFragment() {}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
|
|
|
final String message = getString(R.string.account_setup_failed_dlg_auth_message,
|
|
|
|
R.string.system_account_create_failed);
|
|
|
|
|
2014-03-19 22:20:39 +00:00
|
|
|
setCancelable(false);
|
2014-01-16 17:59:39 +00:00
|
|
|
return new AlertDialog.Builder(getActivity())
|
|
|
|
.setIconAttribute(android.R.attr.alertDialogIcon)
|
2014-03-19 22:20:39 +00:00
|
|
|
.setTitle(R.string.account_setup_failed_dlg_title)
|
2014-01-16 17:59:39 +00:00
|
|
|
.setMessage(message)
|
2014-03-19 22:20:39 +00:00
|
|
|
.setPositiveButton(android.R.string.ok, this)
|
2014-01-16 17:59:39 +00:00
|
|
|
.create();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
|
|
getActivity().finish();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This is called if MailService.setupAccountManagerAccount() fails for some reason
|
|
|
|
*/
|
2014-03-11 19:56:51 +00:00
|
|
|
@Override
|
2014-02-13 21:12:06 +00:00
|
|
|
public void showCreateAccountErrorDialog() {
|
2014-01-16 17:59:39 +00:00
|
|
|
new CreateAccountErrorDialogFragment().show(getFragmentManager(), null);
|
|
|
|
}
|
|
|
|
|
2014-02-13 21:12:06 +00:00
|
|
|
/**
|
|
|
|
* Collect the data from AccountSetupNames and finish up account creation
|
|
|
|
*/
|
2014-01-16 17:59:39 +00:00
|
|
|
private void initiateAccountFinalize() {
|
|
|
|
mIsProcessing = true;
|
2014-03-17 23:45:47 +00:00
|
|
|
getContentFragment().setNextButtonEnabled(false);
|
2014-01-16 17:59:39 +00:00
|
|
|
|
|
|
|
AccountSetupNamesFragment fragment = (AccountSetupNamesFragment) getContentFragment();
|
|
|
|
// Update account object from UI
|
|
|
|
final Account account = mSetupData.getAccount();
|
|
|
|
final String description = fragment.getDescription();
|
|
|
|
if (!TextUtils.isEmpty(description)) {
|
|
|
|
account.setDisplayName(description);
|
|
|
|
}
|
|
|
|
account.setSenderName(fragment.getSenderName());
|
|
|
|
|
|
|
|
final Fragment f = AccountFinalizeFragment.newInstance(account);
|
|
|
|
final FragmentTransaction ft = getFragmentManager().beginTransaction();
|
2014-02-13 21:12:06 +00:00
|
|
|
ft.add(f, AccountFinalizeFragment.TAG);
|
2014-01-16 17:59:39 +00:00
|
|
|
ft.commit();
|
|
|
|
}
|
|
|
|
|
2014-02-13 21:12:06 +00:00
|
|
|
/**
|
|
|
|
* Called when the AccountFinalizeFragment has finished its tasks
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void onAccountFinalizeFragmentComplete() {
|
|
|
|
finish();
|
2014-01-16 17:59:39 +00:00
|
|
|
}
|
|
|
|
}
|