Allow database to hold oauth credentials
Change-Id: I127297fd78c7676995f1dcfa59fbbcafe4e72e8e
This commit is contained in:
parent
5632d4449b
commit
0b25179dab
@ -31,11 +31,9 @@ import android.net.Uri;
|
|||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import com.android.emailcommon.provider.EmailContent.AccountColumns;
|
import com.android.emailcommon.provider.EmailContent.AccountColumns;
|
||||||
import com.android.emailcommon.utility.Utility;
|
import com.android.emailcommon.utility.Utility;
|
||||||
import com.android.mail.utils.LogUtils;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -207,9 +205,6 @@ public final class Account extends EmailContent implements AccountColumns, Parce
|
|||||||
MailboxColumns.TYPE + " = " + Mailbox.TYPE_INBOX +
|
MailboxColumns.TYPE + " = " + Mailbox.TYPE_INBOX +
|
||||||
" AND " + MailboxColumns.ACCOUNT_KEY + " =?";
|
" AND " + MailboxColumns.ACCOUNT_KEY + " =?";
|
||||||
|
|
||||||
/**
|
|
||||||
* no public constructor since this is a utility class
|
|
||||||
*/
|
|
||||||
public Account() {
|
public Account() {
|
||||||
mBaseUri = CONTENT_URI;
|
mBaseUri = CONTENT_URI;
|
||||||
|
|
||||||
@ -739,22 +734,55 @@ public final class Account extends EmailContent implements AccountColumns, Parce
|
|||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
int recvIndex = -1;
|
int recvIndex = -1;
|
||||||
|
int recvCredentialsIndex = -1;
|
||||||
int sendIndex = -1;
|
int sendIndex = -1;
|
||||||
|
int sendCredentialsIndex = -1;
|
||||||
|
|
||||||
// Create operations for saving the send and recv hostAuths
|
// Create operations for saving the send and recv hostAuths, and their credentials.
|
||||||
// Also, remember which operation in the array they represent
|
// Also, remember which operation in the array they represent
|
||||||
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
|
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
|
||||||
if (mHostAuthRecv != null) {
|
if (mHostAuthRecv != null) {
|
||||||
|
if (mHostAuthRecv.mCredential != null) {
|
||||||
|
recvCredentialsIndex = index++;
|
||||||
|
ops.add(ContentProviderOperation.newInsert(mHostAuthRecv.mCredential.mBaseUri)
|
||||||
|
.withValues(mHostAuthRecv.mCredential.toContentValues())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
recvIndex = index++;
|
recvIndex = index++;
|
||||||
ops.add(ContentProviderOperation.newInsert(mHostAuthRecv.mBaseUri)
|
final ContentProviderOperation.Builder b = ContentProviderOperation.newInsert(
|
||||||
.withValues(mHostAuthRecv.toContentValues())
|
mHostAuthRecv.mBaseUri);
|
||||||
.build());
|
b.withValues(mHostAuthRecv.toContentValues());
|
||||||
|
if (recvCredentialsIndex >= 0) {
|
||||||
|
final ContentValues cv = new ContentValues();
|
||||||
|
cv.put(HostAuth.CREDENTIAL_KEY, recvCredentialsIndex);
|
||||||
|
b.withValueBackReferences(cv);
|
||||||
|
}
|
||||||
|
ops.add(b.build());
|
||||||
}
|
}
|
||||||
if (mHostAuthSend != null) {
|
if (mHostAuthSend != null) {
|
||||||
|
if (mHostAuthSend.mCredential != null) {
|
||||||
|
if (mHostAuthRecv.mCredential != null &&
|
||||||
|
mHostAuthRecv.mCredential.equals(mHostAuthSend.mCredential)) {
|
||||||
|
// These two credentials are identical, use the same row.
|
||||||
|
sendCredentialsIndex = recvCredentialsIndex;
|
||||||
|
} else {
|
||||||
|
sendCredentialsIndex = index++;
|
||||||
|
ops.add(ContentProviderOperation.newInsert(mHostAuthRecv.mCredential.mBaseUri)
|
||||||
|
.withValues(mHostAuthRecv.mCredential.toContentValues())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
sendIndex = index++;
|
sendIndex = index++;
|
||||||
ops.add(ContentProviderOperation.newInsert(mHostAuthSend.mBaseUri)
|
final ContentProviderOperation.Builder b = ContentProviderOperation.newInsert(
|
||||||
.withValues(mHostAuthSend.toContentValues())
|
mHostAuthSend.mBaseUri);
|
||||||
.build());
|
b.withValues(mHostAuthSend.toContentValues());
|
||||||
|
if (sendCredentialsIndex >= 0) {
|
||||||
|
final ContentValues cv = new ContentValues();
|
||||||
|
cv.put(HostAuth.CREDENTIAL_KEY, sendCredentialsIndex);
|
||||||
|
b.withValueBackReferences(cv);
|
||||||
|
}
|
||||||
|
ops.add(b.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now do the Account
|
// Now do the Account
|
||||||
|
158
emailcommon/src/com/android/emailcommon/provider/Credential.java
Normal file
158
emailcommon/src/com/android/emailcommon/provider/Credential.java
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
package com.android.emailcommon.provider;
|
||||||
|
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import com.android.emailcommon.provider.EmailContent;
|
||||||
|
import com.android.emailcommon.utility.Utility;
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
|
||||||
|
public class Credential extends EmailContent implements Parcelable {
|
||||||
|
|
||||||
|
public static final String TABLE_NAME = "Credential";
|
||||||
|
public static Uri CONTENT_URI;
|
||||||
|
|
||||||
|
public static final Credential EMPTY = new Credential(-1, "", "", 0);
|
||||||
|
|
||||||
|
public static void initCredential() {
|
||||||
|
CONTENT_URI = Uri.parse(EmailContent.CONTENT_URI + "/credential");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String TYPE_OAUTH = "oauth";
|
||||||
|
|
||||||
|
public String mAccessToken;
|
||||||
|
public String mRefreshToken;
|
||||||
|
public long mExpiration;
|
||||||
|
|
||||||
|
// Name of the authentication provider.
|
||||||
|
public static final String PROVIDER_COLUMN = "provider";
|
||||||
|
// Access token.
|
||||||
|
public static final String ACCESS_TOKEN_COLUMN = "accessToken";
|
||||||
|
// Refresh token.
|
||||||
|
public static final String REFRESH_TOKEN_COLUMN = "refreshToken";
|
||||||
|
// Expiration date for these credentials.
|
||||||
|
public static final String EXPIRATION_COLUMN = "expiration";
|
||||||
|
|
||||||
|
|
||||||
|
public interface CredentialQuery {
|
||||||
|
public static final int ID_COLUMN_INDEX = 0;
|
||||||
|
public static final int PROVIDER_COLUMN_INDEX = 1;
|
||||||
|
public static final int ACCESS_TOKEN_COLUMN_INDEX = 2;
|
||||||
|
public static final int REFRESH_TOKEN_COLUMN_INDEX = 3;
|
||||||
|
public static final int EXPIRATION_COLUMN_INDEX = 4;
|
||||||
|
|
||||||
|
public static final String[] PROJECTION = new String[] {
|
||||||
|
RECORD_ID,
|
||||||
|
PROVIDER_COLUMN,
|
||||||
|
ACCESS_TOKEN_COLUMN,
|
||||||
|
REFRESH_TOKEN_COLUMN,
|
||||||
|
EXPIRATION_COLUMN
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Credential() {
|
||||||
|
mBaseUri = CONTENT_URI;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Credential(long id, String accessToken, String refreshToken, long expiration) {
|
||||||
|
mBaseUri = CONTENT_URI;
|
||||||
|
mId = id;
|
||||||
|
mAccessToken = accessToken;
|
||||||
|
mRefreshToken = refreshToken;
|
||||||
|
mExpiration = expiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore a Credential from the database, given its unique id
|
||||||
|
* @param context
|
||||||
|
* @param id
|
||||||
|
* @return the instantiated Credential
|
||||||
|
*/
|
||||||
|
public static Credential restoreCredentialsWithId(Context context, long id) {
|
||||||
|
return EmailContent.restoreContentWithId(context, Credential.class,
|
||||||
|
Credential.CONTENT_URI, CredentialQuery.PROJECTION, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restore(Cursor cursor) {
|
||||||
|
mBaseUri = CONTENT_URI;
|
||||||
|
mId = cursor.getLong(CredentialQuery.ID_COLUMN_INDEX);
|
||||||
|
mAccessToken = cursor.getString(CredentialQuery.ACCESS_TOKEN_COLUMN_INDEX);
|
||||||
|
mRefreshToken = cursor.getString(CredentialQuery.REFRESH_TOKEN_COLUMN_INDEX);
|
||||||
|
mExpiration = cursor.getInt(CredentialQuery.EXPIRATION_COLUMN_INDEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supports Parcelable
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supports Parcelable
|
||||||
|
*/
|
||||||
|
public static final Parcelable.Creator<Credential> CREATOR
|
||||||
|
= new Parcelable.Creator<Credential>() {
|
||||||
|
@Override
|
||||||
|
public Credential createFromParcel(Parcel in) {
|
||||||
|
return new Credential(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Credential[] newArray(int size) {
|
||||||
|
return new Credential[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
// mBaseUri is not parceled
|
||||||
|
dest.writeLong(mId);
|
||||||
|
dest.writeString(mAccessToken);
|
||||||
|
dest.writeString(mRefreshToken);
|
||||||
|
dest.writeLong(mExpiration);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supports Parcelable
|
||||||
|
*/
|
||||||
|
public Credential(Parcel in) {
|
||||||
|
mBaseUri = CONTENT_URI;
|
||||||
|
mId = in.readLong();
|
||||||
|
mAccessToken = in.readString();
|
||||||
|
mRefreshToken = in.readString();
|
||||||
|
mExpiration = in.readLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (!(o instanceof Credential)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Credential that = (Credential)o;
|
||||||
|
return Utility.areStringsEqual(mAccessToken, that.mAccessToken)
|
||||||
|
&& Utility.areStringsEqual(mRefreshToken, that.mRefreshToken)
|
||||||
|
&& mExpiration == that.mExpiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(mAccessToken, mRefreshToken, mExpiration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContentValues toContentValues() {
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put(ACCESS_TOKEN_COLUMN, mAccessToken);
|
||||||
|
values.put(REFRESH_TOKEN_COLUMN, mRefreshToken);
|
||||||
|
values.put(EXPIRATION_COLUMN, mExpiration);
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -27,12 +27,14 @@ import android.content.res.Resources;
|
|||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
|
import android.os.Looper;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
|
||||||
import com.android.emailcommon.utility.TextUtilities;
|
import com.android.emailcommon.utility.TextUtilities;
|
||||||
import com.android.emailcommon.utility.Utility;
|
import com.android.emailcommon.utility.Utility;
|
||||||
|
import com.android.emailcommon.Logging;
|
||||||
import com.android.emailcommon.R;
|
import com.android.emailcommon.R;
|
||||||
import com.android.mail.providers.UIProvider;
|
import com.android.mail.providers.UIProvider;
|
||||||
import com.android.mail.utils.LogUtils;
|
import com.android.mail.utils.LogUtils;
|
||||||
@ -160,6 +162,7 @@ public abstract class EmailContent {
|
|||||||
Mailbox.initMailbox();
|
Mailbox.initMailbox();
|
||||||
QuickResponse.initQuickResponse();
|
QuickResponse.initQuickResponse();
|
||||||
HostAuth.initHostAuth();
|
HostAuth.initHostAuth();
|
||||||
|
Credential.initCredential();
|
||||||
Policy.initPolicy();
|
Policy.initPolicy();
|
||||||
Message.initMessage();
|
Message.initMessage();
|
||||||
MessageMove.init();
|
MessageMove.init();
|
||||||
@ -169,6 +172,14 @@ public abstract class EmailContent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void warnIfUiThread() {
|
||||||
|
if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
|
||||||
|
LogUtils.w(Logging.LOG_TAG, "Method called on the UI thread",
|
||||||
|
new Throwable());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isInitialSyncKey(final String syncKey) {
|
public static boolean isInitialSyncKey(final String syncKey) {
|
||||||
return syncKey == null || syncKey.isEmpty() || syncKey.equals("0");
|
return syncKey == null || syncKey.isEmpty() || syncKey.equals("0");
|
||||||
}
|
}
|
||||||
@ -197,6 +208,7 @@ public abstract class EmailContent {
|
|||||||
*/
|
*/
|
||||||
public static <T extends EmailContent> T restoreContentWithId(Context context,
|
public static <T extends EmailContent> T restoreContentWithId(Context context,
|
||||||
Class<T> klass, Uri contentUri, String[] contentProjection, long id) {
|
Class<T> klass, Uri contentUri, String[] contentProjection, long id) {
|
||||||
|
warnIfUiThread();
|
||||||
Uri u = ContentUris.withAppendedId(contentUri, id);
|
Uri u = ContentUris.withAppendedId(contentUri, id);
|
||||||
Cursor c = context.getContentResolver().query(u, contentProjection, null, null, null);
|
Cursor c = context.getContentResolver().query(u, contentProjection, null, null, null);
|
||||||
if (c == null) throw new ProviderUnavailableException();
|
if (c == null) throw new ProviderUnavailableException();
|
||||||
@ -1718,6 +1730,8 @@ public abstract class EmailContent {
|
|||||||
static final String ACCOUNT_KEY = "accountKey";
|
static final String ACCOUNT_KEY = "accountKey";
|
||||||
// A blob containing an X509 server certificate
|
// A blob containing an X509 server certificate
|
||||||
static final String SERVER_CERT = "serverCert";
|
static final String SERVER_CERT = "serverCert";
|
||||||
|
// The credentials row this hostAuth should use. Currently only set if using OAuth.
|
||||||
|
static final String CREDENTIAL_KEY = "credentialKey";
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface PolicyColumns {
|
public interface PolicyColumns {
|
||||||
|
@ -52,8 +52,9 @@ public final class HostAuth extends EmailContent implements HostAuthColumns, Par
|
|||||||
public static final int FLAG_TLS = 0x02; // Use TLS
|
public static final int FLAG_TLS = 0x02; // Use TLS
|
||||||
public static final int FLAG_AUTHENTICATE = 0x04; // Use name/password for authentication
|
public static final int FLAG_AUTHENTICATE = 0x04; // Use name/password for authentication
|
||||||
public static final int FLAG_TRUST_ALL = 0x08; // Trust all certificates
|
public static final int FLAG_TRUST_ALL = 0x08; // Trust all certificates
|
||||||
|
public static final int FLAG_OAUTH = 0x10; // Use OAuth for authentication
|
||||||
// Mask of settings directly configurable by the user
|
// Mask of settings directly configurable by the user
|
||||||
public static final int USER_CONFIG_MASK = 0x0b;
|
public static final int USER_CONFIG_MASK = 0x1b;
|
||||||
|
|
||||||
public String mProtocol;
|
public String mProtocol;
|
||||||
public String mAddress;
|
public String mAddress;
|
||||||
@ -65,6 +66,9 @@ public final class HostAuth extends EmailContent implements HostAuthColumns, Par
|
|||||||
public String mClientCertAlias = null;
|
public String mClientCertAlias = null;
|
||||||
// NOTE: The server certificate is NEVER automatically retrieved from EmailProvider
|
// NOTE: The server certificate is NEVER automatically retrieved from EmailProvider
|
||||||
public byte[] mServerCert = null;
|
public byte[] mServerCert = null;
|
||||||
|
public long mCredentialKey;
|
||||||
|
|
||||||
|
public transient Credential mCredential;
|
||||||
|
|
||||||
public static final int CONTENT_ID_COLUMN = 0;
|
public static final int CONTENT_ID_COLUMN = 0;
|
||||||
public static final int CONTENT_PROTOCOL_COLUMN = 1;
|
public static final int CONTENT_PROTOCOL_COLUMN = 1;
|
||||||
@ -75,16 +79,15 @@ public final class HostAuth extends EmailContent implements HostAuthColumns, Par
|
|||||||
public static final int CONTENT_PASSWORD_COLUMN = 6;
|
public static final int CONTENT_PASSWORD_COLUMN = 6;
|
||||||
public static final int CONTENT_DOMAIN_COLUMN = 7;
|
public static final int CONTENT_DOMAIN_COLUMN = 7;
|
||||||
public static final int CONTENT_CLIENT_CERT_ALIAS_COLUMN = 8;
|
public static final int CONTENT_CLIENT_CERT_ALIAS_COLUMN = 8;
|
||||||
|
public static final int CONTENT_CREDENTIAL_KEY_COLUMN = 9;
|
||||||
|
|
||||||
public static final String[] CONTENT_PROJECTION = new String[] {
|
public static final String[] CONTENT_PROJECTION = new String[] {
|
||||||
RECORD_ID, HostAuthColumns.PROTOCOL, HostAuthColumns.ADDRESS, HostAuthColumns.PORT,
|
RECORD_ID, HostAuthColumns.PROTOCOL, HostAuthColumns.ADDRESS, HostAuthColumns.PORT,
|
||||||
HostAuthColumns.FLAGS, HostAuthColumns.LOGIN,
|
HostAuthColumns.FLAGS, HostAuthColumns.LOGIN,
|
||||||
HostAuthColumns.PASSWORD, HostAuthColumns.DOMAIN, HostAuthColumns.CLIENT_CERT_ALIAS
|
HostAuthColumns.PASSWORD, HostAuthColumns.DOMAIN, HostAuthColumns.CLIENT_CERT_ALIAS,
|
||||||
|
HostAuthColumns.CREDENTIAL_KEY
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* no public constructor since this is a utility class
|
|
||||||
*/
|
|
||||||
public HostAuth() {
|
public HostAuth() {
|
||||||
mBaseUri = CONTENT_URI;
|
mBaseUri = CONTENT_URI;
|
||||||
|
|
||||||
@ -92,6 +95,41 @@ public final class HostAuth extends EmailContent implements HostAuthColumns, Par
|
|||||||
mPort = PORT_UNKNOWN;
|
mPort = PORT_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getOrCreateCredentials
|
||||||
|
* Return the credential object for this HostAuth, creating it if it does not yet exist.
|
||||||
|
* This should not be called on the main thread.
|
||||||
|
* @param context
|
||||||
|
* @return the credential object for this HostAuth
|
||||||
|
*/
|
||||||
|
public Credential getOrCreateCredentials(Context context) {
|
||||||
|
|
||||||
|
if (mCredential == null) {
|
||||||
|
if (mCredentialKey >= 0) {
|
||||||
|
mCredential = Credential.restoreCredentialsWithId(context, mCredentialKey);
|
||||||
|
} else {
|
||||||
|
mCredential = new Credential();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mCredential;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getCredentials
|
||||||
|
* Return the credential object for this HostAuth, or null if it does not exist.
|
||||||
|
* This should not be called on the main thread.
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Credential getCredentials(Context context) {
|
||||||
|
if (mCredential == null) {
|
||||||
|
if (mCredentialKey >= 0) {
|
||||||
|
mCredential = Credential.restoreCredentialsWithId(context, mCredentialKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mCredential;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore a HostAuth from the database, given its unique id
|
* Restore a HostAuth from the database, given its unique id
|
||||||
* @param context
|
* @param context
|
||||||
@ -181,6 +219,7 @@ public final class HostAuth extends EmailContent implements HostAuthColumns, Par
|
|||||||
mPassword = cursor.getString(CONTENT_PASSWORD_COLUMN);
|
mPassword = cursor.getString(CONTENT_PASSWORD_COLUMN);
|
||||||
mDomain = cursor.getString(CONTENT_DOMAIN_COLUMN);
|
mDomain = cursor.getString(CONTENT_DOMAIN_COLUMN);
|
||||||
mClientCertAlias = cursor.getString(CONTENT_CLIENT_CERT_ALIAS_COLUMN);
|
mClientCertAlias = cursor.getString(CONTENT_CLIENT_CERT_ALIAS_COLUMN);
|
||||||
|
mCredentialKey = cursor.getLong(CONTENT_CREDENTIAL_KEY_COLUMN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -194,6 +233,7 @@ public final class HostAuth extends EmailContent implements HostAuthColumns, Par
|
|||||||
values.put(HostAuthColumns.PASSWORD, mPassword);
|
values.put(HostAuthColumns.PASSWORD, mPassword);
|
||||||
values.put(HostAuthColumns.DOMAIN, mDomain);
|
values.put(HostAuthColumns.DOMAIN, mDomain);
|
||||||
values.put(HostAuthColumns.CLIENT_CERT_ALIAS, mClientCertAlias);
|
values.put(HostAuthColumns.CLIENT_CERT_ALIAS, mClientCertAlias);
|
||||||
|
values.put(HostAuthColumns.CREDENTIAL_KEY, mCredentialKey);
|
||||||
values.put(HostAuthColumns.ACCOUNT_KEY, 0); // Need something to satisfy the DB
|
values.put(HostAuthColumns.ACCOUNT_KEY, 0); // Need something to satisfy the DB
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
@ -330,6 +370,12 @@ public final class HostAuth extends EmailContent implements HostAuthColumns, Par
|
|||||||
dest.writeString(mPassword);
|
dest.writeString(mPassword);
|
||||||
dest.writeString(mDomain);
|
dest.writeString(mDomain);
|
||||||
dest.writeString(mClientCertAlias);
|
dest.writeString(mClientCertAlias);
|
||||||
|
dest.writeLong(mCredentialKey);
|
||||||
|
if (mCredential == null) {
|
||||||
|
Credential.EMPTY.writeToParcel(dest, flags);
|
||||||
|
} else {
|
||||||
|
mCredential.writeToParcel(dest, flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -346,6 +392,11 @@ public final class HostAuth extends EmailContent implements HostAuthColumns, Par
|
|||||||
mPassword = in.readString();
|
mPassword = in.readString();
|
||||||
mDomain = in.readString();
|
mDomain = in.readString();
|
||||||
mClientCertAlias = in.readString();
|
mClientCertAlias = in.readString();
|
||||||
|
mCredentialKey = in.readLong();
|
||||||
|
mCredential = new Credential(in);
|
||||||
|
if (mCredential.equals(Credential.EMPTY)) {
|
||||||
|
mCredential = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -362,7 +413,8 @@ public final class HostAuth extends EmailContent implements HostAuthColumns, Par
|
|||||||
&& Utility.areStringsEqual(mLogin, that.mLogin)
|
&& Utility.areStringsEqual(mLogin, that.mLogin)
|
||||||
&& Utility.areStringsEqual(mPassword, that.mPassword)
|
&& Utility.areStringsEqual(mPassword, that.mPassword)
|
||||||
&& Utility.areStringsEqual(mDomain, that.mDomain)
|
&& Utility.areStringsEqual(mDomain, that.mDomain)
|
||||||
&& Utility.areStringsEqual(mClientCertAlias, that.mClientCertAlias);
|
&& Utility.areStringsEqual(mClientCertAlias, that.mClientCertAlias)
|
||||||
|
&& mCredentialKey == that.mCredentialKey;
|
||||||
// We don't care about the server certificate for equals
|
// We don't care about the server certificate for equals
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ import com.android.email.R;
|
|||||||
import com.android.email2.ui.MailActivityEmail;
|
import com.android.email2.ui.MailActivityEmail;
|
||||||
import com.android.emailcommon.mail.Address;
|
import com.android.emailcommon.mail.Address;
|
||||||
import com.android.emailcommon.provider.Account;
|
import com.android.emailcommon.provider.Account;
|
||||||
|
import com.android.emailcommon.provider.Credential;
|
||||||
import com.android.emailcommon.provider.EmailContent;
|
import com.android.emailcommon.provider.EmailContent;
|
||||||
import com.android.emailcommon.provider.EmailContent.AccountColumns;
|
import com.android.emailcommon.provider.EmailContent.AccountColumns;
|
||||||
import com.android.emailcommon.provider.EmailContent.Attachment;
|
import com.android.emailcommon.provider.EmailContent.Attachment;
|
||||||
@ -94,6 +95,15 @@ public final class DBHelper {
|
|||||||
" where " + EmailContent.RECORD_ID + "=old." + AccountColumns.POLICY_KEY +
|
" where " + EmailContent.RECORD_ID + "=old." + AccountColumns.POLICY_KEY +
|
||||||
"; end";
|
"; end";
|
||||||
|
|
||||||
|
private static final String TRIGGER_HOST_AUTH_DELETE =
|
||||||
|
"create trigger host_auth_delete after delete on " + HostAuth.TABLE_NAME +
|
||||||
|
" begin delete from " + Credential.TABLE_NAME +
|
||||||
|
" where " + Credential.RECORD_ID + "=old." + HostAuth.CREDENTIAL_KEY +
|
||||||
|
" and (select count(*) from " + HostAuth.TABLE_NAME + " where " +
|
||||||
|
HostAuth.CREDENTIAL_KEY + "=old." + HostAuth.CREDENTIAL_KEY + ")=0" +
|
||||||
|
"; end";
|
||||||
|
|
||||||
|
|
||||||
// Any changes to the database format *must* include update-in-place code.
|
// Any changes to the database format *must* include update-in-place code.
|
||||||
// Original version: 3
|
// Original version: 3
|
||||||
// Version 4: Database wipe required; changing AccountManager interface w/Exchange
|
// Version 4: Database wipe required; changing AccountManager interface w/Exchange
|
||||||
@ -163,7 +173,8 @@ public final class DBHelper {
|
|||||||
// Version 122: Need to update Message_Updates and Message_Deletes to match previous.
|
// Version 122: Need to update Message_Updates and Message_Deletes to match previous.
|
||||||
// Version 123: Changed the duplicateMesage deletion trigger to ignore accounts that aren't
|
// Version 123: Changed the duplicateMesage deletion trigger to ignore accounts that aren't
|
||||||
// exchange accounts.
|
// exchange accounts.
|
||||||
public static final int DATABASE_VERSION = 123;
|
// Version 124: Add credentials table for OAuth.
|
||||||
|
public static final int DATABASE_VERSION = 124;
|
||||||
|
|
||||||
// Any changes to the database format *must* include update-in-place code.
|
// Any changes to the database format *must* include update-in-place code.
|
||||||
// Original version: 2
|
// Original version: 2
|
||||||
@ -216,6 +227,17 @@ public final class DBHelper {
|
|||||||
"; end");
|
"; end");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void createCredentialsTable(SQLiteDatabase db) {
|
||||||
|
String s = " (" + Credential.RECORD_ID + " integer primary key autoincrement, "
|
||||||
|
+ Credential.PROVIDER_COLUMN + " text,"
|
||||||
|
+ Credential.ACCESS_TOKEN_COLUMN + " text,"
|
||||||
|
+ Credential.REFRESH_TOKEN_COLUMN + " text,"
|
||||||
|
+ Credential.EXPIRATION_COLUMN + " integer"
|
||||||
|
+ ");";
|
||||||
|
db.execSQL("create table " + Credential.TABLE_NAME + s);
|
||||||
|
db.execSQL(TRIGGER_HOST_AUTH_DELETE);
|
||||||
|
}
|
||||||
|
|
||||||
static void dropDeleteDuplicateMessagesTrigger(final SQLiteDatabase db) {
|
static void dropDeleteDuplicateMessagesTrigger(final SQLiteDatabase db) {
|
||||||
db.execSQL("drop trigger message_delete_duplicates_on_insert");
|
db.execSQL("drop trigger message_delete_duplicates_on_insert");
|
||||||
}
|
}
|
||||||
@ -535,7 +557,8 @@ public final class DBHelper {
|
|||||||
+ HostAuthColumns.DOMAIN + " text, "
|
+ HostAuthColumns.DOMAIN + " text, "
|
||||||
+ HostAuthColumns.ACCOUNT_KEY + " integer,"
|
+ HostAuthColumns.ACCOUNT_KEY + " integer,"
|
||||||
+ HostAuthColumns.CLIENT_CERT_ALIAS + " text,"
|
+ HostAuthColumns.CLIENT_CERT_ALIAS + " text,"
|
||||||
+ HostAuthColumns.SERVER_CERT + " blob"
|
+ HostAuthColumns.SERVER_CERT + " blob,"
|
||||||
|
+ HostAuthColumns.CREDENTIAL_KEY + " integer"
|
||||||
+ ");";
|
+ ");";
|
||||||
db.execSQL("create table " + HostAuth.TABLE_NAME + s);
|
db.execSQL("create table " + HostAuth.TABLE_NAME + s);
|
||||||
}
|
}
|
||||||
@ -733,6 +756,7 @@ public final class DBHelper {
|
|||||||
createMessageStateChangeTable(db);
|
createMessageStateChangeTable(db);
|
||||||
createPolicyTable(db);
|
createPolicyTable(db);
|
||||||
createQuickResponseTable(db);
|
createQuickResponseTable(db);
|
||||||
|
createCredentialsTable(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1317,6 +1341,15 @@ public final class DBHelper {
|
|||||||
}
|
}
|
||||||
createDeleteDuplicateMessagesTrigger(mContext, db);
|
createDeleteDuplicateMessagesTrigger(mContext, db);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oldVersion <= 123) {
|
||||||
|
createCredentialsTable(db);
|
||||||
|
// Add the credentialKey column, and set it to -1 for all pre-existing hostAuths.
|
||||||
|
db.execSQL("alter table " + HostAuth.TABLE_NAME
|
||||||
|
+ " add " + HostAuthColumns.CREDENTIAL_KEY + " integer");
|
||||||
|
db.execSQL("update table " + HostAuth.TABLE_NAME + " set "
|
||||||
|
+ HostAuthColumns.CREDENTIAL_KEY + "=-1");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -72,6 +72,7 @@ import com.android.email2.ui.MailActivityEmail;
|
|||||||
import com.android.emailcommon.Logging;
|
import com.android.emailcommon.Logging;
|
||||||
import com.android.emailcommon.mail.Address;
|
import com.android.emailcommon.mail.Address;
|
||||||
import com.android.emailcommon.provider.Account;
|
import com.android.emailcommon.provider.Account;
|
||||||
|
import com.android.emailcommon.provider.Credential;
|
||||||
import com.android.emailcommon.provider.EmailContent;
|
import com.android.emailcommon.provider.EmailContent;
|
||||||
import com.android.emailcommon.provider.EmailContent.AccountColumns;
|
import com.android.emailcommon.provider.EmailContent.AccountColumns;
|
||||||
import com.android.emailcommon.provider.EmailContent.Attachment;
|
import com.android.emailcommon.provider.EmailContent.Attachment;
|
||||||
@ -261,6 +262,10 @@ public class EmailProvider extends ContentProvider {
|
|||||||
private static final int BODY = BODY_BASE;
|
private static final int BODY = BODY_BASE;
|
||||||
private static final int BODY_ID = BODY_BASE + 1;
|
private static final int BODY_ID = BODY_BASE + 1;
|
||||||
|
|
||||||
|
private static final int CREDENTIAL_BASE = 0xB000;
|
||||||
|
private static final int CREDENTIAL = CREDENTIAL_BASE;
|
||||||
|
private static final int CREDENTIAL_ID = CREDENTIAL_BASE + 1;
|
||||||
|
|
||||||
private static final int BASE_SHIFT = 12; // 12 bits to the base type: 0, 0x1000, 0x2000, etc.
|
private static final int BASE_SHIFT = 12; // 12 bits to the base type: 0, 0x1000, 0x2000, etc.
|
||||||
|
|
||||||
private static final SparseArray<String> TABLE_NAMES;
|
private static final SparseArray<String> TABLE_NAMES;
|
||||||
@ -277,6 +282,7 @@ public class EmailProvider extends ContentProvider {
|
|||||||
array.put(QUICK_RESPONSE_BASE >> BASE_SHIFT, QuickResponse.TABLE_NAME);
|
array.put(QUICK_RESPONSE_BASE >> BASE_SHIFT, QuickResponse.TABLE_NAME);
|
||||||
array.put(UI_BASE >> BASE_SHIFT, null);
|
array.put(UI_BASE >> BASE_SHIFT, null);
|
||||||
array.put(BODY_BASE >> BASE_SHIFT, Body.TABLE_NAME);
|
array.put(BODY_BASE >> BASE_SHIFT, Body.TABLE_NAME);
|
||||||
|
array.put(CREDENTIAL_BASE >> BASE_SHIFT, Credential.TABLE_NAME);
|
||||||
TABLE_NAMES = array;
|
TABLE_NAMES = array;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -645,6 +651,7 @@ public class EmailProvider extends ContentProvider {
|
|||||||
case HOSTAUTH_ID:
|
case HOSTAUTH_ID:
|
||||||
case POLICY_ID:
|
case POLICY_ID:
|
||||||
case QUICK_RESPONSE_ID:
|
case QUICK_RESPONSE_ID:
|
||||||
|
case CREDENTIAL_ID:
|
||||||
id = uri.getPathSegments().get(1);
|
id = uri.getPathSegments().get(1);
|
||||||
if (match == SYNCED_MESSAGE_ID) {
|
if (match == SYNCED_MESSAGE_ID) {
|
||||||
// For synced messages, first copy the old message to the deleted table and
|
// For synced messages, first copy the old message to the deleted table and
|
||||||
@ -822,6 +829,7 @@ public class EmailProvider extends ContentProvider {
|
|||||||
case MAILBOX:
|
case MAILBOX:
|
||||||
case ACCOUNT:
|
case ACCOUNT:
|
||||||
case HOSTAUTH:
|
case HOSTAUTH:
|
||||||
|
case CREDENTIAL:
|
||||||
case POLICY:
|
case POLICY:
|
||||||
case QUICK_RESPONSE:
|
case QUICK_RESPONSE:
|
||||||
longId = db.insert(TABLE_NAMES.valueAt(table), "foo", values);
|
longId = db.insert(TABLE_NAMES.valueAt(table), "foo", values);
|
||||||
@ -1041,6 +1049,11 @@ public class EmailProvider extends ContentProvider {
|
|||||||
// A specific hostauth
|
// A specific hostauth
|
||||||
sURIMatcher.addURI(EmailContent.AUTHORITY, "hostauth/*", HOSTAUTH_ID);
|
sURIMatcher.addURI(EmailContent.AUTHORITY, "hostauth/*", HOSTAUTH_ID);
|
||||||
|
|
||||||
|
// All credential records
|
||||||
|
sURIMatcher.addURI(EmailContent.AUTHORITY, "credential", CREDENTIAL);
|
||||||
|
// A specific credential
|
||||||
|
sURIMatcher.addURI(EmailContent.AUTHORITY, "credential/*", CREDENTIAL_ID);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* THIS URI HAS SPECIAL SEMANTICS
|
* THIS URI HAS SPECIAL SEMANTICS
|
||||||
* ITS USE IS INTENDED FOR THE UI TO MARK CHANGES THAT NEED TO BE SYNCED BACK
|
* ITS USE IS INTENDED FOR THE UI TO MARK CHANGES THAT NEED TO BE SYNCED BACK
|
||||||
@ -1878,6 +1891,7 @@ public class EmailProvider extends ContentProvider {
|
|||||||
case MAILBOX:
|
case MAILBOX:
|
||||||
case ACCOUNT:
|
case ACCOUNT:
|
||||||
case HOSTAUTH:
|
case HOSTAUTH:
|
||||||
|
case CREDENTIAL:
|
||||||
case POLICY:
|
case POLICY:
|
||||||
if (match == ATTACHMENT) {
|
if (match == ATTACHMENT) {
|
||||||
if (values.containsKey(AttachmentColumns.LOCATION) &&
|
if (values.containsKey(AttachmentColumns.LOCATION) &&
|
||||||
|
Loading…
Reference in New Issue
Block a user