diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 85e9c6d60..db16e029b 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -150,6 +150,11 @@
android:label="@string/oauth_authentication_title">
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/sign_in_fragment.xml b/res/layout/sign_in_fragment.xml
new file mode 100644
index 000000000..81e0a8da7
--- /dev/null
+++ b/res/layout/sign_in_fragment.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6034ebc6d..5fbfeaf5d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -190,8 +190,10 @@
Account setup
-
+
OAuth authentication
+
+ IMAP Authentication
Email account
@@ -200,6 +202,12 @@
Email address
+
+
+ OR
+
+ Sign in with Google
+
Password
diff --git a/src/com/android/email/activity/setup/AccountSettingsUtils.java b/src/com/android/email/activity/setup/AccountSettingsUtils.java
index 607cfb2a2..65afb7c32 100644
--- a/src/com/android/email/activity/setup/AccountSettingsUtils.java
+++ b/src/com/android/email/activity/setup/AccountSettingsUtils.java
@@ -40,6 +40,9 @@ import com.android.emailcommon.utility.Utility;
import com.android.mail.utils.LogUtils;
import com.google.common.annotations.VisibleForTesting;
+import java.util.ArrayList;
+import java.util.List;
+
public class AccountSettingsUtils {
/** Pattern to match any part of a domain */
@@ -145,6 +148,43 @@ public class AccountSettingsUtils {
return findOAuthProvider(context, id, R.xml.oauth);
}
+ public static List getAllOAuthProviders(final Context context) {
+ try {
+ List providers = new ArrayList();
+ final XmlResourceParser xml = context.getResources().getXml(R.xml.oauth);
+ int xmlEventType;
+ OAuthProvider provider = null;
+ while ((xmlEventType = xml.next()) != XmlResourceParser.END_DOCUMENT) {
+ if (xmlEventType == XmlResourceParser.START_TAG
+ && "provider".equals(xml.getName())) {
+ try {
+ provider = new OAuthProvider();
+ provider.id = getXmlAttribute(context, xml, "id");
+ provider.label = getXmlAttribute(context, xml, "label");
+ provider.authEndpoint = getXmlAttribute(context, xml, "auth_endpoint");
+ provider.tokenEndpoint = getXmlAttribute(context, xml, "token_endpoint");
+ provider.refreshEndpoint = getXmlAttribute(context, xml,
+ "refresh_endpoint");
+ provider.responseType = getXmlAttribute(context, xml, "response_type");
+ provider.redirectUri = getXmlAttribute(context, xml, "redirect_uri");
+ provider.scope = getXmlAttribute(context, xml, "scope");
+ provider.state = getXmlAttribute(context, xml, "state");
+ provider.clientId = getXmlAttribute(context, xml, "client_id");
+ provider.clientSecret = getXmlAttribute(context, xml, "client_secret");
+ providers.add(provider);
+ } catch (IllegalArgumentException e) {
+ LogUtils.w(Logging.LOG_TAG, "providers line: " + xml.getLineNumber() +
+ "; Domain contains multiple globals");
+ }
+ }
+ }
+ return providers;
+ } catch (Exception e) {
+ LogUtils.e(Logging.LOG_TAG, "Error while trying to load provider settings.", e);
+ }
+ return null;
+ }
+
/**
* Search for a single resource containing known oauth provider definitions.
*
diff --git a/src/com/android/email/activity/setup/AccountSetupBasics.java b/src/com/android/email/activity/setup/AccountSetupBasics.java
index 803422a67..cb8b2bf21 100644
--- a/src/com/android/email/activity/setup/AccountSetupBasics.java
+++ b/src/com/android/email/activity/setup/AccountSetupBasics.java
@@ -110,10 +110,6 @@ public class AccountSetupBasics extends AccountSetupActivity
public static final int RESULT_OAUTH_USER_CANCELED = -1;
public static final int RESULT_OAUTH_FAILURE = -2;
- public static final String EXTRA_OAUTH_ACCESS_TOKEN = "accessToken";
- public static final String EXTRA_OAUTH_REFRESH_TOKEN = "refreshToken";
- public static final String EXTRA_OAUTH_EXPIRES_IN = "expiresIn";
-
// Support for UI
private Provider mProvider;
private Button mManualButton;
@@ -144,9 +140,12 @@ public class AccountSetupBasics extends AccountSetupActivity
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_OAUTH) {
if (resultCode == RESULT_OAUTH_SUCCESS) {
- final String accessToken = data.getStringExtra(EXTRA_OAUTH_ACCESS_TOKEN);
- final String refreshToken = data.getStringExtra(EXTRA_OAUTH_REFRESH_TOKEN);
- final int expiresInSeconds = data.getIntExtra(EXTRA_OAUTH_EXPIRES_IN, 0);
+ final String accessToken = data.getStringExtra(
+ OAuthAuthenticationActivity.EXTRA_OAUTH_ACCESS_TOKEN);
+ final String refreshToken = data.getStringExtra(
+ OAuthAuthenticationActivity.EXTRA_OAUTH_REFRESH_TOKEN);
+ final int expiresInSeconds = data.getIntExtra(
+ OAuthAuthenticationActivity.EXTRA_OAUTH_EXPIRES_IN, 0);
finishOAuthSetup(accessToken, refreshToken, expiresInSeconds);
} else if (resultCode == RESULT_OAUTH_FAILURE
diff --git a/src/com/android/email/activity/setup/AccountSetupIncomingFragment.java b/src/com/android/email/activity/setup/AccountSetupIncomingFragment.java
index 86e987986..be9ec5f4d 100644
--- a/src/com/android/email/activity/setup/AccountSetupIncomingFragment.java
+++ b/src/com/android/email/activity/setup/AccountSetupIncomingFragment.java
@@ -24,6 +24,7 @@ import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
+import android.text.format.DateUtils;
import android.text.method.DigitsKeyListener;
import android.view.LayoutInflater;
import android.view.View;
@@ -44,6 +45,7 @@ import com.android.email.service.EmailServiceUtils.EmailServiceInfo;
import com.android.email2.ui.MailActivityEmail;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.Account;
+import com.android.emailcommon.provider.Credential;
import com.android.emailcommon.provider.HostAuth;
import com.android.emailcommon.utility.CertificateRequestor;
import com.android.emailcommon.utility.Utility;
@@ -61,6 +63,7 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment
implements AuthenticationCallback {
private static final int CERTIFICATE_REQUEST = 0;
+ private static final int SIGN_IN_REQUEST = 1;
private final static String STATE_KEY_CREDENTIAL = "AccountSetupIncomingFragment.credential";
private final static String STATE_KEY_LOADED = "AccountSetupIncomingFragment.loaded";
@@ -403,11 +406,12 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment
SpinnerOption.setSpinnerOptionValue(mDeletePolicyView, mLoadedDeletePolicy);
int flags = recvAuth.mFlags;
- flags &= ~HostAuth.FLAG_AUTHENTICATE;
if (mServiceInfo.defaultSsl) {
flags |= HostAuth.FLAG_SSL;
}
- SpinnerOption.setSpinnerOptionValue(mSecurityTypeView, flags);
+ // Strip out any flags that are not related to security type.
+ int securityTypeFlags = (flags & (HostAuth.FLAG_SSL | HostAuth.FLAG_TLS | HostAuth.FLAG_NONE));
+ SpinnerOption.setSpinnerOptionValue(mSecurityTypeView, securityTypeFlags);
final String hostname = recvAuth.mAddress;
if (hostname != null) {
@@ -472,6 +476,15 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment
public void saveSettingsAfterEdit() {
final Account account = mSetupData.getAccount();
account.update(mContext, account.toContentValues());
+ final Credential cred = account.mHostAuthRecv.mCredential;
+ if (cred != null) {
+ if (cred.isSaved()) {
+ cred.update(mContext, cred.toContentValues());
+ } else {
+ cred.save(mContext);
+ account.mHostAuthRecv.mCredentialKey = cred.mId;
+ }
+ }
account.mHostAuthRecv.update(mContext, account.mHostAuthRecv.toContentValues());
// Update the backup (side copy) of the accounts
AccountBackupRestore.backup(mContext);
@@ -513,6 +526,10 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment
final String userName = mUsernameView.getText().toString().trim();
final String userPassword = mAuthenticationView.getPassword().toString();
recvAuth.setLogin(userName, userPassword);
+ if (!TextUtils.isEmpty(mAuthenticationView.getOAuthProvider())) {
+ Credential cred = recvAuth.getOrCreateCredential(getActivity());
+ cred.mProviderId = mAuthenticationView.getOAuthProvider();
+ }
final String serverAddress = mServerView.getText().toString().trim();
int serverPort;
@@ -568,6 +585,14 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment
validateFields();
}
+ @Override
+ public void onRequestSignIn() {
+ // Launch the signin activity.
+ // TODO: at some point we should just use the sign in fragment on the main setup activity.
+ final Intent intent = new Intent(getActivity(), SignInActivity.class);
+ intent.putExtra(SignInActivity.EXTRA_EMAIL, mSetupData.getAccount().mEmailAddress);
+ startActivityForResult(intent, SIGN_IN_REQUEST);
+ }
@Override
public void onCertificateRequested() {
@@ -581,6 +606,25 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment
if (requestCode == CERTIFICATE_REQUEST && resultCode == Activity.RESULT_OK) {
final String certAlias = data.getStringExtra(CertificateRequestor.RESULT_ALIAS);
mAuthenticationView.setCertificate(certAlias);
+ } else if (requestCode == SIGN_IN_REQUEST && resultCode == Activity.RESULT_OK) {
+ final Account account = mSetupData.getAccount();
+ final HostAuth recvAuth = account.getOrCreateHostAuthRecv(getActivity());
+ final String password = data.getStringExtra(SignInActivity.EXTRA_PASSWORD);
+ if (!TextUtils.isEmpty(password)) {
+ recvAuth.mPassword = password;
+ recvAuth.removeCredential();
+ } else {
+ Credential cred = recvAuth.getOrCreateCredential(getActivity());
+ cred.mProviderId = data.getStringExtra(SignInActivity.EXTRA_OAUTH_PROVIDER);
+ cred.mAccessToken = data.getStringExtra(SignInActivity.EXTRA_OAUTH_ACCESS_TOKEN);
+ cred.mRefreshToken = data.getStringExtra(SignInActivity.EXTRA_OAUTH_REFRESH_TOKEN);
+ cred.mExpiration = System.currentTimeMillis() +
+ data.getIntExtra(SignInActivity.EXTRA_OAUTH_EXPIRES_IN_SECONDS, 0) *
+ DateUtils.SECOND_IN_MILLIS;
+ recvAuth.mPassword = null;
+ }
+ mAuthenticationView.setAuthInfo(mServiceInfo.offerOAuth, mServiceInfo.offerCerts,
+ recvAuth);
}
}
}
diff --git a/src/com/android/email/activity/setup/AccountSetupOutgoingFragment.java b/src/com/android/email/activity/setup/AccountSetupOutgoingFragment.java
index 22a9139c6..fa6822f98 100644
--- a/src/com/android/email/activity/setup/AccountSetupOutgoingFragment.java
+++ b/src/com/android/email/activity/setup/AccountSetupOutgoingFragment.java
@@ -43,6 +43,7 @@ import com.android.email.provider.AccountBackupRestore;
import com.android.email2.ui.MailActivityEmail;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.Account;
+import com.android.emailcommon.provider.Credential;
import com.android.emailcommon.provider.HostAuth;
import com.android.emailcommon.utility.CertificateRequestor;
import com.android.emailcommon.utility.Utility;
@@ -58,6 +59,7 @@ public class AccountSetupOutgoingFragment extends AccountServerBaseFragment
implements OnCheckedChangeListener, AuthenticationCallback {
private static final int CERTIFICATE_REQUEST = 0;
+ private static final int SIGN_IN_REQUEST = 1;
private final static String STATE_KEY_LOADED = "AccountSetupOutgoingFragment.loaded";
@@ -348,6 +350,15 @@ public class AccountSetupOutgoingFragment extends AccountServerBaseFragment
@Override
public void saveSettingsAfterEdit() {
final Account account = mSetupData.getAccount();
+ final Credential cred = account.mHostAuthRecv.mCredential;
+ if (cred != null) {
+ if (cred.isSaved()) {
+ cred.update(mContext, cred.toContentValues());
+ } else {
+ cred.save(mContext);
+ account.mHostAuthRecv.mCredentialKey = cred.mId;
+ }
+ }
account.mHostAuthSend.update(mContext, account.mHostAuthSend.toContentValues());
// Update the backup (side copy) of the accounts
AccountBackupRestore.backup(mContext);
@@ -402,4 +413,13 @@ public class AccountSetupOutgoingFragment extends AccountServerBaseFragment
public void onCertificateRequested() {
// We don't support certificates on any outgoing protocol.
}
+
+ @Override
+ public void onRequestSignIn() {
+ // Launch the signin activity.
+ // TODO: at some point we should just use the sign in fragment on the main setup activity.
+ final Intent intent = new Intent(getActivity(), SignInActivity.class);
+ intent.putExtra(SignInActivity.EXTRA_EMAIL, mSetupData.getAccount().mEmailAddress);
+ startActivityForResult(intent, SIGN_IN_REQUEST);
+ }
}
diff --git a/src/com/android/email/activity/setup/AuthenticationView.java b/src/com/android/email/activity/setup/AuthenticationView.java
index 0a1bc605e..3d16abd14 100644
--- a/src/com/android/email/activity/setup/AuthenticationView.java
+++ b/src/com/android/email/activity/setup/AuthenticationView.java
@@ -1,9 +1,6 @@
package com.android.email.activity.setup;
-import android.app.Activity;
import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
import android.text.Editable;
@@ -19,14 +16,12 @@ import android.widget.TextView;
import com.android.email.R;
import com.android.email.activity.UiUtilities;
-import com.android.email.service.EmailServiceUtils.EmailServiceInfo;
import com.android.email.view.CertificateSelector;
import com.android.email.view.CertificateSelector.HostCallback;
import com.android.emailcommon.Device;
import com.android.emailcommon.VendorPolicyLoader.OAuthProvider;
import com.android.emailcommon.provider.Credential;
import com.android.emailcommon.provider.HostAuth;
-import com.android.emailcommon.utility.CertificateRequestor;
import java.io.IOException;
@@ -42,8 +37,6 @@ public class AuthenticationView extends LinearLayout implements HostCallback, On
private final static String SAVE_OFFER_CERTS = "save_offer_certs";
private final static String SAVE_USE_OAUTH = "save_use_oauth";
private final static String SAVE_OAUTH_PROVIDER = "save_oauth_provider";
- private final static String SAVE_OAUTH_ACCESS_TOKEN = "save_oauth_access_token";
- private final static String SAVE_OAUTH_REFRESH_TOKEN = "save_oauth_refresh_token";
// Views
private View mImapAuthenticationView;
@@ -66,8 +59,6 @@ public class AuthenticationView extends LinearLayout implements HostCallback, On
private boolean mOfferCerts;
private boolean mUseOAuth;
private String mOAuthProvider;
- private String mOAuthAccessToken;
- private String mOAuthRefreshToken;
private boolean mAuthenticationValid;
private AuthenticationCallback mAuthenticationCallback;
@@ -76,6 +67,8 @@ public class AuthenticationView extends LinearLayout implements HostCallback, On
public void onValidateStateChanged();
public void onCertificateRequested();
+
+ public void onRequestSignIn();
}
public AuthenticationView(Context context) {
@@ -155,7 +148,6 @@ public class AuthenticationView extends LinearLayout implements HostCallback, On
}
public String getOAuthProvider() {
- // FLAG: need to handle this getting updated.
return mOAuthProvider;
}
@@ -188,8 +180,6 @@ public class AuthenticationView extends LinearLayout implements HostCallback, On
// We're authenticated with OAuth.
mUseOAuth = true;
mOAuthProvider = cred.mProviderId;
- mOAuthAccessToken = cred.mAccessToken;
- mOAuthRefreshToken = cred.mRefreshToken;
} else {
mUseOAuth = false;
}
@@ -258,8 +248,6 @@ public class AuthenticationView extends LinearLayout implements HostCallback, On
bundle.putBoolean(SAVE_USE_OAUTH, mUseOAuth);
bundle.putString(SAVE_PASSWORD, getPassword());
bundle.putString(SAVE_OAUTH_PROVIDER, mOAuthProvider);
- bundle.putString(SAVE_OAUTH_ACCESS_TOKEN, mOAuthAccessToken);
- bundle.putString(SAVE_OAUTH_REFRESH_TOKEN, mOAuthRefreshToken);
return bundle;
}
@@ -272,8 +260,6 @@ public class AuthenticationView extends LinearLayout implements HostCallback, On
mOfferCerts = bundle.getBoolean(SAVE_OFFER_CERTS);
mUseOAuth = bundle.getBoolean(SAVE_USE_OAUTH);
mOAuthProvider = bundle.getString(SAVE_OAUTH_PROVIDER);
- mOAuthAccessToken = bundle.getString(SAVE_OAUTH_ACCESS_TOKEN);
- mOAuthRefreshToken = bundle.getString(SAVE_OAUTH_REFRESH_TOKEN);
final String password = bundle.getString(SAVE_PASSWORD);
getPasswordEditText().setText(password);
@@ -318,12 +304,14 @@ public class AuthenticationView extends LinearLayout implements HostCallback, On
if (view == mClearImapPasswordView) {
getPasswordEditText().setText(null);
updateVisibility();
+ validateFields();
} else if (view == mClearOAuthView) {
mUseOAuth = false;
mOAuthProvider = null;
updateVisibility();
+ validateFields();
} else if (view == mAddAuthenticationView) {
- // FLAG Launch the add authentication screen
+ mAuthenticationCallback.onRequestSignIn();
}
}
}
diff --git a/src/com/android/email/activity/setup/OAuthAuthenticationActivity.java b/src/com/android/email/activity/setup/OAuthAuthenticationActivity.java
index 15f2b00b2..87023ec18 100644
--- a/src/com/android/email/activity/setup/OAuthAuthenticationActivity.java
+++ b/src/com/android/email/activity/setup/OAuthAuthenticationActivity.java
@@ -42,6 +42,10 @@ public class OAuthAuthenticationActivity extends Activity implements
public static final int LOADER_ID_OAUTH_TOKEN = 1;
+ public static final String EXTRA_OAUTH_ACCESS_TOKEN = "accessToken";
+ public static final String EXTRA_OAUTH_REFRESH_TOKEN = "refreshToken";
+ public static final String EXTRA_OAUTH_EXPIRES_IN = "expiresIn";
+
private WebView mWv;
private OAuthProvider mProvider;
private String mAuthenticationCode;
@@ -179,12 +183,9 @@ public class OAuthAuthenticationActivity extends Activity implements
} else {
final Intent intent = new Intent();
- intent.putExtra(AccountSetupBasics.EXTRA_OAUTH_ACCESS_TOKEN,
- data.mAccessToken);
- intent.putExtra(AccountSetupBasics.EXTRA_OAUTH_REFRESH_TOKEN,
- data.mRefreshToken);
- intent.putExtra(AccountSetupBasics.EXTRA_OAUTH_EXPIRES_IN,
- data.mExpiresInSeconds);
+ intent.putExtra(EXTRA_OAUTH_ACCESS_TOKEN, data.mAccessToken);
+ intent.putExtra(EXTRA_OAUTH_REFRESH_TOKEN, data.mRefreshToken);
+ intent.putExtra(EXTRA_OAUTH_EXPIRES_IN, data.mExpiresInSeconds);
setResult(AccountSetupBasics.RESULT_OAUTH_SUCCESS, intent);
}
finish();
diff --git a/src/com/android/email/activity/setup/SignInActivity.java b/src/com/android/email/activity/setup/SignInActivity.java
new file mode 100644
index 000000000..fa91e7b5a
--- /dev/null
+++ b/src/com/android/email/activity/setup/SignInActivity.java
@@ -0,0 +1,57 @@
+package com.android.email.activity.setup;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+import com.android.email.R;
+
+public class SignInActivity extends Activity implements SignInFragment.SignInCallback {
+
+ public static final String EXTRA_EMAIL = "email";
+
+ public static final String EXTRA_PASSWORD = "password";
+ public static final String EXTRA_OAUTH_PROVIDER = "provider";
+ public static final String EXTRA_OAUTH_ACCESS_TOKEN = "accessToken";
+ public static final String EXTRA_OAUTH_REFRESH_TOKEN = "refreshToken";
+ public static final String EXTRA_OAUTH_EXPIRES_IN_SECONDS = "expiresInSeconds";
+
+ private SignInFragment mFragment;
+
+ @Override
+ public void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.sign_in_activity);
+ mFragment = (SignInFragment)
+ getFragmentManager().findFragmentById(R.id.sign_in_fragment);
+ mFragment.setEmailAddress(getIntent().getStringExtra(EXTRA_EMAIL));
+ mFragment.setSignInCallback(this);
+ }
+
+ @Override
+ public void onOAuthSignIn(final String providerId, final String accessToken,
+ final String refreshToken, final int expiresInSeconds) {
+ final Intent intent = new Intent();
+ intent.putExtra(EXTRA_OAUTH_PROVIDER, providerId);
+ intent.putExtra(EXTRA_OAUTH_ACCESS_TOKEN, accessToken);
+ intent.putExtra(EXTRA_OAUTH_REFRESH_TOKEN, refreshToken);
+ intent.putExtra(EXTRA_OAUTH_EXPIRES_IN_SECONDS, expiresInSeconds);
+ setResult(RESULT_OK, intent);
+ finish();
+ }
+
+ @Override
+ public void onPasswordSignIn(final String password) {
+ final Intent intent = new Intent();
+ intent.putExtra(EXTRA_PASSWORD, password);
+ setResult(RESULT_OK, intent);
+ finish();
+ }
+
+ @Override
+ public void onCancel() {
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+
+}
diff --git a/src/com/android/email/activity/setup/SignInFragment.java b/src/com/android/email/activity/setup/SignInFragment.java
new file mode 100644
index 000000000..83a93a1b0
--- /dev/null
+++ b/src/com/android/email/activity/setup/SignInFragment.java
@@ -0,0 +1,179 @@
+/*
+ * 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.app.Fragment;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import com.android.email.R;
+import com.android.email.activity.UiUtilities;
+import com.android.emailcommon.Logging;
+import com.android.emailcommon.VendorPolicyLoader.OAuthProvider;
+import com.android.emailcommon.VendorPolicyLoader.Provider;
+import com.android.mail.utils.LogUtils;
+
+import java.util.List;
+
+public class SignInFragment extends Fragment implements OnClickListener {
+
+ public static final int REQUEST_OAUTH = 1;
+
+ public static final int RESULT_OAUTH_SUCCESS = 0;
+ public static final int RESULT_OAUTH_USER_CANCELED = -1;
+ public static final int RESULT_OAUTH_FAILURE = -2;
+
+ private View mNextButton;
+ private View mPreviousButton;
+ private View mOAuthButton;
+ private EditText mPasswordText;
+ private TextWatcher mValidationTextWatcher;
+ private String mEmailAddress;
+ private String mProviderId;
+ private SignInCallback mCallback;
+ private Context mContext;
+
+ public interface SignInCallback {
+ public void onOAuthSignIn(final String providerId, final String accessToken,
+ final String refreshToken, final int expiresInSeconds);
+
+ public void onPasswordSignIn(final String password);
+
+ public void onCancel();
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ final View view = inflater.inflate(R.layout.sign_in_fragment, container, false);
+
+ mNextButton = UiUtilities.getView(view, R.id.next);
+ mPreviousButton = UiUtilities.getView(view, R.id.previous);
+ mOAuthButton = UiUtilities.getView(view, R.id.sign_in_with_google);
+ mPasswordText = UiUtilities.getView(view, R.id.account_password);
+ mNextButton.setOnClickListener(this);
+ mPreviousButton.setOnClickListener(this);
+ mOAuthButton.setOnClickListener(this);
+
+ // After any text edits, call validateFields() which enables or disables the Next button
+ mValidationTextWatcher = new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable s) {
+ validatePassword();
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) { }
+ };
+ mPasswordText.addTextChangedListener(mValidationTextWatcher);
+
+ return view;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ mContext = getActivity();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mPasswordText.removeTextChangedListener(mValidationTextWatcher);
+ mPasswordText = null;
+ }
+
+ public void validatePassword() {
+ enableNextButton(!TextUtils.isEmpty(mPasswordText.getText()));
+ // Warn (but don't prevent) if password has leading/trailing spaces
+ AccountSettingsUtils.checkPasswordSpaces(mContext, mPasswordText);
+ }
+
+ private void enableNextButton(final boolean enabled) {
+ mNextButton.setEnabled(enabled);
+ }
+
+ @Override
+ public void onActivityResult(final int requestCode, final int resultCode,
+ final Intent data) {
+ if (requestCode == REQUEST_OAUTH) {
+ if (resultCode == RESULT_OAUTH_SUCCESS) {
+ final String accessToken = data.getStringExtra(
+ OAuthAuthenticationActivity.EXTRA_OAUTH_ACCESS_TOKEN);
+ final String refreshToken = data.getStringExtra(
+ OAuthAuthenticationActivity.EXTRA_OAUTH_REFRESH_TOKEN);
+ final int expiresInSeconds = data.getIntExtra(
+ OAuthAuthenticationActivity.EXTRA_OAUTH_EXPIRES_IN, 0);
+ mCallback.onOAuthSignIn(mProviderId, accessToken, refreshToken, expiresInSeconds);
+
+ getActivity().finish();
+ } else if (resultCode == RESULT_OAUTH_FAILURE
+ || resultCode == RESULT_OAUTH_USER_CANCELED) {
+ LogUtils.i(Logging.LOG_TAG, "Result from oauth %d", resultCode);
+ } else {
+ LogUtils.wtf(Logging.LOG_TAG, "Unknown result code from OAUTH: %d", resultCode);
+ }
+ } else {
+ LogUtils.e(Logging.LOG_TAG, "Unknown request code for onActivityResult in"
+ + " AccountSetupBasics: %d", requestCode);
+ }
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (view == mNextButton) {
+ mCallback.onPasswordSignIn(mPasswordText.getText().toString());
+ } else if (view == mPreviousButton) {
+ mCallback.onCancel();
+ } else if (view == mOAuthButton) {
+ List oauthProviders = AccountSettingsUtils.getAllOAuthProviders(
+ mContext);
+ // FLAG currently the only oauth provider we support is google.
+ // If we ever have more than 1 oauth provider, then we need to implement some sort
+ // of picker UI. For now, just always take the first oauth provider.
+ if (oauthProviders.size() > 0) {
+ mProviderId = oauthProviders.get(0).id;
+ final Intent i = new Intent(mContext, OAuthAuthenticationActivity.class);
+ i.putExtra(OAuthAuthenticationActivity.EXTRA_EMAIL_ADDRESS, mEmailAddress);
+ i.putExtra(OAuthAuthenticationActivity.EXTRA_PROVIDER, mProviderId);
+ startActivityForResult(i, REQUEST_OAUTH);
+ }
+ }
+ }
+
+ public void setEmailAddress(final String emailAddress) {
+ mEmailAddress = emailAddress;
+ }
+
+ public String getEmailAddress() {
+ return mEmailAddress;
+ }
+
+ public void setSignInCallback(SignInCallback callback) {
+ mCallback = callback;
+ }
+}