Add sign in Activity

This allows the user to choose which type of authentication
to use for existing IMAP accounts.

Change-Id: Ib44364a1059a2c4b8a7a0fa66b14cd042b28770e
This commit is contained in:
Martin Hibdon 2014-01-30 16:03:00 -08:00
parent cbab7b409d
commit 58fbd2a477
13 changed files with 475 additions and 34 deletions

View File

@ -150,6 +150,11 @@
android:label="@string/oauth_authentication_title">
</activity>
<activity
android:name=".activity.setup.SignInActivity"
android:label="@string/sign_in_title">
</activity>
<activity
android:name=".activity.EventViewer"
android:label="@string/app_name"

View File

@ -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 com.android.emailcommon.utility.Utility;
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";
@ -144,6 +149,14 @@ public class HostAuth extends EmailContent implements HostAuthColumns, Parcelabl
return mCredential;
}
/**
* 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
@ -491,5 +504,4 @@ public class HostAuth extends EmailContent implements HostAuthColumns, Parcelabl
public String toString() {
return "[protocol " + mProtocol + "]";
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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] -->

View File

@ -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<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.
*

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}
}

View File

@ -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();

View File

@ -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();
}
}

View File

@ -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;
}
}