Add sign in Activity
This allows the user to choose which type of authentication
to use for existing IMAP accounts.
Change-Id: Ib44364a1059a2c4b8a7a0fa66b14cd042b28770e
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 85e9c6d..db16e02 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -151,6 +151,11 @@
</activity>
<activity
+ android:name=".activity.setup.SignInActivity"
+ android:label="@string/sign_in_title">
+ </activity>
+
+ <activity
android:name=".activity.EventViewer"
android:label="@string/app_name"
>
diff --git a/emailcommon/src/com/android/emailcommon/provider/HostAuth.java b/emailcommon/src/com/android/emailcommon/provider/HostAuth.java
index 15dde4e..f4cdd1b 100644
--- a/emailcommon/src/com/android/emailcommon/provider/HostAuth.java
+++ b/emailcommon/src/com/android/emailcommon/provider/HostAuth.java
@@ -17,12 +17,16 @@
package com.android.emailcommon.provider;
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
import android.content.ContentValues;
import android.content.Context;
+import android.content.OperationApplicationException;
import android.database.Cursor;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.RemoteException;
import android.text.TextUtils;
import com.android.emailcommon.provider.EmailContent.HostAuthColumns;
@@ -31,6 +35,7 @@
import java.net.URI;
import java.net.URISyntaxException;
+import java.util.ArrayList;
public class HostAuth extends EmailContent implements HostAuthColumns, Parcelable {
public static final String TABLE_NAME = "HostAuth";
@@ -145,6 +150,14 @@
}
/**
+ * Clear the credential object.
+ */
+ public void removeCredential() {
+ mCredential = null;
+ mCredentialKey = -1;
+ }
+
+ /**
* Builds a URI scheme name given the parameters for a {@code HostAuth}. If
* a {@code clientAlias} is provided, this indicates that a secure
* connection must be used.
@@ -491,5 +504,4 @@
public String toString() {
return "[protocol " + mProtocol + "]";
}
-
}
diff --git a/res/layout/sign_in_activity.xml b/res/layout/sign_in_activity.xml
new file mode 100644
index 0000000..dcd4e18
--- /dev/null
+++ b/res/layout/sign_in_activity.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingTop="@dimen/setup_fragment_padding_top"
+ android:paddingLeft="@dimen/setup_fragment_padding_left"
+ android:paddingRight="@dimen/setup_fragment_padding_right" >
+
+ <fragment
+ android:id="@+id/sign_in_fragment"
+ class="com.android.email.activity.setup.SignInFragment"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+</FrameLayout>
diff --git a/res/layout/sign_in_fragment.xml b/res/layout/sign_in_fragment.xml
new file mode 100644
index 0000000..81e0a8d
--- /dev/null
+++ b/res/layout/sign_in_fragment.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:orientation="vertical">
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1" />
+
+ <Button
+ android:id="@+id/sign_in_with_google"
+ android:text="@string/sign_in_with_google"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <TextView
+ android:id="@+id/or_label"
+ android:text="@string/or_label"
+ android:layout_marginTop="24dip"
+ android:layout_marginBottom="24dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <EditText
+ android:id="@+id/account_password"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:hint="@string/account_setup_incoming_password_label"
+ android:inputType="textPassword"
+ android:imeOptions="actionNext"/>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1" />
+
+ <include layout="@layout/account_setup_buttons" />
+
+</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6034ebc..5fbfeaf 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -190,8 +190,10 @@
<!-- Title of screen when setting up new email account [CHAR LIMIT=45] -->
<string name="account_setup_basics_title">Account setup</string>
- <!-- Do Not Translate. Title of screen when trying to get oauth authentication -->
+ <!-- Title of screen when trying to get oauth authentication -->
<string name="oauth_authentication_title" translatable="false">OAuth authentication</string>
+ <!-- Title of screen to choose with authentication to use -->
+ <string name="sign_in_title">IMAP Authentication</string>
<!-- Headline of screen when setting up new email account (large text over divider)
[CHAR LIMIT=none] -->
<string name="account_setup_basics_headline">Email account</string>
@@ -200,6 +202,12 @@
</string>
<!-- On "Set up email" screen, hint for account email address text field -->
<string name="account_setup_basics_email_label">Email address</string>
+
+ <!-- Label between OAuth and password authentication, indicating the user must do one or the other [CHAR LIMIT=40] -->
+ <string name="or_label">OR</string>
+ <!-- Label for signing in with Google using OAuth -->
+ <string name="sign_in_with_google">Sign in with Google</string>
+
<!-- On "Set up email" screen, hint for account email password text field -->
<string name="account_setup_basics_password_label">Password</string>
<!-- On the "Setup up email" screen, label indicating what service we are signed in with [CHAR LIMIT=40] -->
diff --git a/src/com/android/email/activity/setup/AccountSettingsUtils.java b/src/com/android/email/activity/setup/AccountSettingsUtils.java
index 607cfb2..65afb7c 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.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 @@
return findOAuthProvider(context, id, R.xml.oauth);
}
+ public static List<OAuthProvider> getAllOAuthProviders(final Context context) {
+ try {
+ List<OAuthProvider> providers = new ArrayList<OAuthProvider>();
+ 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 00af313..94c7318 100644
--- a/src/com/android/email/activity/setup/AccountSetupBasics.java
+++ b/src/com/android/email/activity/setup/AccountSetupBasics.java
@@ -110,10 +110,6 @@
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 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 86e9879..be9ec5f 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.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.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 @@
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 @@
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 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 @@
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 @@
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 @@
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 22a9139..fa6822f 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.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 @@
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 @@
@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 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 0a1bc60..3d16abd 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 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 @@
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 @@
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 void onValidateStateChanged();
public void onCertificateRequested();
+
+ public void onRequestSignIn();
}
public AuthenticationView(Context context) {
@@ -155,7 +148,6 @@
}
public String getOAuthProvider() {
- // FLAG: need to handle this getting updated.
return mOAuthProvider;
}
@@ -188,8 +180,6 @@
// We're authenticated with OAuth.
mUseOAuth = true;
mOAuthProvider = cred.mProviderId;
- mOAuthAccessToken = cred.mAccessToken;
- mOAuthRefreshToken = cred.mRefreshToken;
} else {
mUseOAuth = false;
}
@@ -258,8 +248,6 @@
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 @@
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 @@
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 15f2b00..87023ec 100644
--- a/src/com/android/email/activity/setup/OAuthAuthenticationActivity.java
+++ b/src/com/android/email/activity/setup/OAuthAuthenticationActivity.java
@@ -42,6 +42,10 @@
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 @@
} 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 0000000..fa91e7b
--- /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 0000000..83a93a1
--- /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<OAuthProvider> 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;
+ }
+}