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:
parent
cbab7b409d
commit
58fbd2a477
@ -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"
|
||||
|
@ -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 + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
31
res/layout/sign_in_activity.xml
Normal file
31
res/layout/sign_in_activity.xml
Normal 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>
|
57
res/layout/sign_in_fragment.xml
Normal file
57
res/layout/sign_in_fragment.xml
Normal 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>
|
@ -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] -->
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
57
src/com/android/email/activity/setup/SignInActivity.java
Normal file
57
src/com/android/email/activity/setup/SignInActivity.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
179
src/com/android/email/activity/setup/SignInFragment.java
Normal file
179
src/com/android/email/activity/setup/SignInFragment.java
Normal 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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user