Convert AttachmentProvider to use new Provider db.

* Rewrite internals to use EmailProvider instead of raw db access
  * Minor changes to APIs as necessary (and scattered changes to follow)
  * Convert unit tests and check them
This commit is contained in:
Andrew Stadler 2009-07-27 15:52:42 -07:00
parent 63b2ad5bfb
commit 3d25a519ab
7 changed files with 106 additions and 135 deletions

View File

@ -1322,7 +1322,7 @@ public class MessageView extends Activity
String text = MimeUtility.getTextFromPart(part); String text = MimeUtility.getTextFromPart(part);
if (part.getMimeType().equalsIgnoreCase("text/html")) { if (part.getMimeType().equalsIgnoreCase("text/html")) {
text = EmailHtmlUtil.resolveInlineImage( text = EmailHtmlUtil.resolveInlineImage(
getContentResolver(), mAccount, text, mOldMessage, 0); getContentResolver(), mAccount.mId, text, mOldMessage, 0);
} else { } else {
// And also escape special character, such as "<>&", // And also escape special character, such as "<>&",
// to HTML escape sequence. // to HTML escape sequence.

View File

@ -48,7 +48,7 @@ public class EmailHtmlUtil {
* @return html text in which src attribute of img tag may be replaced with content uri * @return html text in which src attribute of img tag may be replaced with content uri
*/ */
public static String resolveInlineImage( public static String resolveInlineImage(
ContentResolver resolver, EmailContent.Account account, String text, Part part, int depth) ContentResolver resolver, long accountId, String text, Part part, int depth)
throws MessagingException { throws MessagingException {
// avoid too deep recursive call. // avoid too deep recursive call.
if (depth >= 10 || text == null) { if (depth >= 10 || text == null) {
@ -60,8 +60,10 @@ public class EmailHtmlUtil {
contentId != null && contentId != null &&
part instanceof LocalAttachmentBodyPart) { part instanceof LocalAttachmentBodyPart) {
LocalAttachmentBodyPart attachment = (LocalAttachmentBodyPart)part; LocalAttachmentBodyPart attachment = (LocalAttachmentBodyPart)part;
Uri contentUri = AttachmentProvider.resolveAttachmentIdToContentUri( Uri attachmentUri =
resolver, AttachmentProvider.getAttachmentUri(account, attachment.getAttachmentId())); AttachmentProvider.getAttachmentUri(accountId, attachment.getAttachmentId());
Uri contentUri =
AttachmentProvider.resolveAttachmentIdToContentUri(resolver, attachmentUri);
// Regexp which matches ' src="cid:contentId"'. // Regexp which matches ' src="cid:contentId"'.
String contentIdRe = "\\s+(?i)src=\"cid(?-i):\\Q" + contentId + "\\E\""; String contentIdRe = "\\s+(?i)src=\"cid(?-i):\\Q" + contentId + "\\E\"";
// Replace all occurrences of src attribute with ' src="content://contentUri"'. // Replace all occurrences of src attribute with ' src="content://contentUri"'.
@ -71,7 +73,7 @@ public class EmailHtmlUtil {
if (part.getBody() instanceof Multipart) { if (part.getBody() instanceof Multipart) {
Multipart mp = (Multipart)part.getBody(); Multipart mp = (Multipart)part.getBody();
for (int i = 0; i < mp.getCount(); i++) { for (int i = 0; i < mp.getCount(); i++) {
text = resolveInlineImage(resolver, account, text, mp.getBodyPart(i), depth + 1); text = resolveInlineImage(resolver, accountId, text, mp.getBodyPart(i), depth + 1);
} }
} }

View File

@ -1375,9 +1375,10 @@ public class LocalStore extends Store implements PersistentDataCallbacks {
if (tempAttachmentFile != null) { if (tempAttachmentFile != null) {
File attachmentFile = new File(mAttachmentsDir, Long.toString(attachmentId)); File attachmentFile = new File(mAttachmentsDir, Long.toString(attachmentId));
tempAttachmentFile.renameTo(attachmentFile); tempAttachmentFile.renameTo(attachmentFile);
contentUri = AttachmentProvider.getAttachmentUri( // Doing this requires knowing the account id
new File(mPath).getName(), // contentUri = AttachmentProvider.getAttachmentUri(
attachmentId); // new File(mPath).getName(),
// attachmentId);
attachment.setBody(new LocalAttachmentBody(contentUri, mContext)); attachment.setBody(new LocalAttachmentBody(contentUri, mContext));
ContentValues cv = new ContentValues(); ContentValues cv = new ContentValues();
cv.put("content_uri", contentUri != null ? contentUri.toString() : null); cv.put("content_uri", contentUri != null ? contentUri.toString() : null);

View File

@ -17,13 +17,15 @@
package com.android.email.provider; package com.android.email.provider;
import com.android.email.mail.internet.MimeUtility; import com.android.email.mail.internet.MimeUtility;
import com.android.email.provider.EmailContent.Attachment;
import com.android.email.provider.EmailContent.AttachmentColumns;
import android.content.ContentProvider; import android.content.ContentProvider;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues; import android.content.ContentValues;
import android.database.Cursor; import android.database.Cursor;
import android.database.MatrixCursor; import android.database.MatrixCursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.net.Uri; import android.net.Uri;
@ -38,6 +40,12 @@ import java.util.List;
/* /*
* A simple ContentProvider that allows file access to Email's attachments. * A simple ContentProvider that allows file access to Email's attachments.
*
* The URI scheme is as follows. For raw file access:
* content://com.android.email.attachmentprovider/acct#/attach#/RAW
*
* And for access to thumbnails:
* content://com.android.email.attachmentprovider/acct#/attach#/THUMBNAIL/width#/height#
*/ */
public class AttachmentProvider extends ContentProvider { public class AttachmentProvider extends ContentProvider {
@ -54,9 +62,13 @@ public class AttachmentProvider extends ContentProvider {
public static final String SIZE = "_size"; public static final String SIZE = "_size";
} }
public static Uri getAttachmentUri(EmailContent.Account account, long id) { private String[] PROJECTION_MIME_TYPE = new String[] { AttachmentColumns.MIME_TYPE };
private String[] PROJECTION_QUERY = new String[] { AttachmentColumns.FILENAME,
AttachmentColumns.SIZE, AttachmentColumns.CONTENT_URI };
public static Uri getAttachmentUri(long accountId, long id) {
return CONTENT_URI.buildUpon() return CONTENT_URI.buildUpon()
.appendPath(account.getUuid() + ".db") .appendPath(Long.toString(accountId))
.appendPath(Long.toString(id)) .appendPath(Long.toString(id))
.appendPath(FORMAT_RAW) .appendPath(FORMAT_RAW)
.build(); .build();
@ -65,7 +77,7 @@ public class AttachmentProvider extends ContentProvider {
public static Uri getAttachmentThumbnailUri(EmailContent.Account account, long id, public static Uri getAttachmentThumbnailUri(EmailContent.Account account, long id,
int width, int height) { int width, int height) {
return CONTENT_URI.buildUpon() return CONTENT_URI.buildUpon()
.appendPath(account.getUuid() + ".db") .appendPath(Long.toString(account.mId))
.appendPath(Long.toString(id)) .appendPath(Long.toString(id))
.appendPath(FORMAT_THUMBNAIL) .appendPath(FORMAT_THUMBNAIL)
.appendPath(Integer.toString(width)) .appendPath(Integer.toString(width))
@ -73,14 +85,6 @@ public class AttachmentProvider extends ContentProvider {
.build(); .build();
} }
public static Uri getAttachmentUri(String db, long id) {
return CONTENT_URI.buildUpon()
.appendPath(db)
.appendPath(Long.toString(id))
.appendPath(FORMAT_RAW)
.build();
}
@Override @Override
public boolean onCreate() { public boolean onCreate() {
/* /*
@ -106,42 +110,23 @@ public class AttachmentProvider extends ContentProvider {
@Override @Override
public String getType(Uri uri) { public String getType(Uri uri) {
List<String> segments = uri.getPathSegments(); List<String> segments = uri.getPathSegments();
String dbName = segments.get(0); String accountId = segments.get(0);
String id = segments.get(1); String id = segments.get(1);
String format = segments.get(2); String format = segments.get(2);
if (FORMAT_THUMBNAIL.equals(format)) { if (FORMAT_THUMBNAIL.equals(format)) {
return "image/png"; return "image/png";
} } else {
else { uri = ContentUris.withAppendedId(Attachment.CONTENT_URI, Long.parseLong(id));
String path = getContext().getDatabasePath(dbName).getAbsolutePath(); Cursor c = getContext().getContentResolver().query(uri, PROJECTION_MIME_TYPE,
SQLiteDatabase db = null; null, null, null);
Cursor cursor = null;
try { try {
db = SQLiteDatabase.openDatabase(path, null, 0); if (c.moveToFirst()) {
cursor = db.query( return c.getString(0);
"attachments",
new String[] { "mime_type" },
"id = ?",
new String[] { id },
null,
null,
null);
cursor.moveToFirst();
String type = cursor.getString(0);
cursor.close();
db.close();
return type;
}
finally {
if (cursor != null) {
cursor.close();
} }
if (db != null) { } finally {
db.close(); c.close();
}
} }
return null;
} }
} }
@ -159,23 +144,25 @@ public class AttachmentProvider extends ContentProvider {
@Override @Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
List<String> segments = uri.getPathSegments(); List<String> segments = uri.getPathSegments();
String dbName = segments.get(0); String accountId = segments.get(0);
String id = segments.get(1); String id = segments.get(1);
String format = segments.get(2); String format = segments.get(2);
if (FORMAT_THUMBNAIL.equals(format)) { if (FORMAT_THUMBNAIL.equals(format)) {
int width = Integer.parseInt(segments.get(3)); int width = Integer.parseInt(segments.get(3));
int height = Integer.parseInt(segments.get(4)); int height = Integer.parseInt(segments.get(4));
String filename = "thmb_" + dbName + "_" + id; String filename = "thmb_" + accountId + "_" + id;
File dir = getContext().getCacheDir(); File dir = getContext().getCacheDir();
File file = new File(dir, filename); File file = new File(dir, filename);
if (!file.exists()) { if (!file.exists()) {
Uri attachmentUri = getAttachmentUri(dbName, Long.parseLong(id)); Uri attachmentUri = getAttachmentUri(Long.parseLong(accountId), Long.parseLong(id));
Cursor c = query(attachmentUri, Cursor c = query(attachmentUri,
new String[] { AttachmentProviderColumns.DATA }, null, null, null); new String[] { AttachmentProviderColumns.DATA }, null, null, null);
if (c != null) { if (c != null) {
try { try {
if (c.moveToFirst()) { if (c.moveToFirst()) {
attachmentUri = Uri.parse(c.getString(0)); attachmentUri = Uri.parse(c.getString(0));
} else {
return null;
} }
} finally { } finally {
c.close(); c.close();
@ -200,7 +187,7 @@ public class AttachmentProvider extends ContentProvider {
} }
else { else {
return ParcelFileDescriptor.open( return ParcelFileDescriptor.open(
new File(getContext().getDatabasePath(dbName + "_att"), id), new File(getContext().getDatabasePath(accountId + ".db_att"), id),
ParcelFileDescriptor.MODE_READ_ONLY); ParcelFileDescriptor.MODE_READ_ONLY);
} }
} }
@ -221,9 +208,6 @@ public class AttachmentProvider extends ContentProvider {
* *
* Supports REST Uri only, for a single row - selection, selection args, and sortOrder are * Supports REST Uri only, for a single row - selection, selection args, and sortOrder are
* ignored (non-null values should probably throw an exception....) * ignored (non-null values should probably throw an exception....)
*
* TODO: Throws an SQLite exception on a missing DB file (e.g. unknown URI) instead of just
* returning null, as it should.
*/ */
@Override @Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
@ -237,39 +221,26 @@ public class AttachmentProvider extends ContentProvider {
} }
List<String> segments = uri.getPathSegments(); List<String> segments = uri.getPathSegments();
String dbName = segments.get(0); String accountId = segments.get(0);
String id = segments.get(1); String id = segments.get(1);
String format = segments.get(2); String format = segments.get(2);
String path = getContext().getDatabasePath(dbName).getAbsolutePath();
String name = null; String name = null;
int size = -1; int size = -1;
String contentUri = null; String contentUri = null;
SQLiteDatabase db = null;
Cursor cursor = null; uri = ContentUris.withAppendedId(Attachment.CONTENT_URI, Long.parseLong(id));
Cursor c = getContext().getContentResolver().query(uri, PROJECTION_QUERY,
null, null, null);
try { try {
db = SQLiteDatabase.openDatabase(path, null, 0); if (c.moveToFirst()) {
cursor = db.query( name = c.getString(0);
"attachments", size = c.getInt(1);
new String[] { "name", "size", "content_uri" }, contentUri = c.getString(2);
"id = ?", } else {
new String[] { id },
null,
null,
null);
if (!cursor.moveToFirst()) {
return null; return null;
} }
name = cursor.getString(0); } finally {
size = cursor.getInt(1); c.close();
contentUri = cursor.getString(2);
}
finally {
if (cursor != null) {
cursor.close();
}
if (db != null) {
db.close();
}
} }
MatrixCursor ret = new MatrixCursor(projection); MatrixCursor ret = new MatrixCursor(projection);

View File

@ -66,7 +66,7 @@ public class MessageTestUtils {
* @return AttachmentProvider content URI * @return AttachmentProvider content URI
*/ */
public static Uri contentUri(long attachmentId, EmailContent.Account account) { public static Uri contentUri(long attachmentId, EmailContent.Account account) {
return AttachmentProvider.getAttachmentUri(account, attachmentId); return AttachmentProvider.getAttachmentUri(account.mId, attachmentId);
} }
/** /**

View File

@ -32,6 +32,12 @@ import android.test.suitebuilder.annotation.MediumTest;
import java.io.IOException; import java.io.IOException;
/**
* Tests of the Email HTML utils.
*
* You can run this entire test case with:
* runtest -c com.android.email.mail.internet.EmailHtmlUtilTest email
*/
@MediumTest @MediumTest
public class EmailHtmlUtilTest extends AndroidTestCase { public class EmailHtmlUtilTest extends AndroidTestCase {
private EmailContent.Account mAccount; private EmailContent.Account mAccount;
@ -74,13 +80,13 @@ public class EmailHtmlUtilTest extends AndroidTestCase {
.build(); .build();
// Simple case. // Simple case.
final String actual1 = EmailHtmlUtil.resolveInlineImage( final String actual1 = EmailHtmlUtil.resolveInlineImage(
getContext().getContentResolver(), mAccount, text1, msg1, 0); getContext().getContentResolver(), mAccount.mId, text1, msg1, 0);
assertEquals("one content id reference is not resolved", assertEquals("one content id reference is not resolved",
expected1, actual1); expected1, actual1);
// Exceed recursive limit. // Exceed recursive limit.
final String actual0 = EmailHtmlUtil.resolveInlineImage( final String actual0 = EmailHtmlUtil.resolveInlineImage(
getContext().getContentResolver(), mAccount, text1, msg1, 10); getContext().getContentResolver(), mAccount.mId, text1, msg1, 10);
assertEquals("recursive call limit may exceeded", assertEquals("recursive call limit may exceeded",
text1, actual0); text1, actual0);
@ -100,7 +106,7 @@ public class EmailHtmlUtilTest extends AndroidTestCase {
.build(); .build();
// cid1 is not replaced // cid1 is not replaced
final String actual2 = EmailHtmlUtil.resolveInlineImage( final String actual2 = EmailHtmlUtil.resolveInlineImage(
getContext().getContentResolver(), mAccount, text1 + text2, msg2, 0); getContext().getContentResolver(), mAccount.mId, text1 + text2, msg2, 0);
assertEquals("only one of two content id is resolved", assertEquals("only one of two content id is resolved",
text1 + expected2, actual2); text1 + expected2, actual2);
@ -114,7 +120,7 @@ public class EmailHtmlUtilTest extends AndroidTestCase {
.build(); .build();
// cid1 and cid2 are replaced // cid1 and cid2 are replaced
final String actual3 = EmailHtmlUtil.resolveInlineImage( final String actual3 = EmailHtmlUtil.resolveInlineImage(
getContext().getContentResolver(), mAccount, text2 + text1, msg3, 0); getContext().getContentResolver(), mAccount.mId, text2 + text1, msg3, 0);
assertEquals("two content ids are resolved correctly", assertEquals("two content ids are resolved correctly",
expected2 + expected1, actual3); expected2 + expected1, actual3);
@ -133,13 +139,13 @@ public class EmailHtmlUtilTest extends AndroidTestCase {
.build(); .build();
// cid1 and cid2 are replaced // cid1 and cid2 are replaced
final String actual4 = EmailHtmlUtil.resolveInlineImage( final String actual4 = EmailHtmlUtil.resolveInlineImage(
getContext().getContentResolver(), mAccount, text2 + text1, msg4, 0); getContext().getContentResolver(), mAccount.mId, text2 + text1, msg4, 0);
assertEquals("two content ids in deep multipart level are resolved", assertEquals("two content ids in deep multipart level are resolved",
expected2 + expected1, actual4); expected2 + expected1, actual4);
// No crash on null text // No crash on null text
final String actual5 = EmailHtmlUtil.resolveInlineImage(getContext().getContentResolver(), final String actual5 = EmailHtmlUtil.resolveInlineImage(getContext().getContentResolver(),
mAccount, null, msg4, 0); mAccount.mId, null, msg4, 0);
assertNull(actual5); assertNull(actual5);
} }

View File

@ -29,7 +29,6 @@ import android.content.Context;
import android.content.res.AssetFileDescriptor; import android.content.res.AssetFileDescriptor;
import android.database.Cursor; import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.net.Uri; import android.net.Uri;
@ -54,7 +53,7 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
* "old" LocalStore model to the "new" provider model. After the transition is complete, * "old" LocalStore model to the "new" provider model. After the transition is complete,
* this flag (and its associated code) can be removed. * this flag (and its associated code) can be removed.
*/ */
private final boolean USE_LOCALSTORE = true; private final boolean USE_LOCALSTORE = false;
LocalStore mLocalStore = null; LocalStore mLocalStore = null;
EmailProvider mEmailProvider; EmailProvider mEmailProvider;
@ -118,18 +117,13 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
// attachment we add will be id=1 and the 2nd will have id=2. This could fail on // attachment we add will be id=1 and the 2nd will have id=2. This could fail on
// a legitimate implementation. Asserts below will catch this and fail the test // a legitimate implementation. Asserts below will catch this and fail the test
// if necessary. // if necessary.
Uri attachment1Uri = AttachmentProvider.getAttachmentUri(account1, attachment1Id); Uri attachment1Uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment1Id);
Uri attachment2Uri = AttachmentProvider.getAttachmentUri(account1, attachment2Id); Uri attachment2Uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment2Id);
Uri attachment3Uri = AttachmentProvider.getAttachmentUri(account1, attachment3Id); Uri attachment3Uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment3Id);
// Test with no attached database - should return null, but throws SQLiteException // Test with no attached database - should return null
Cursor c; Cursor c = mMockResolver.query(attachment1Uri, (String[])null, null, (String[])null, null);
try { assertNull(c);
c = mMockResolver.query(attachment1Uri, (String[])null, null, (String[])null, null);
fail("Should throw an exception on a bad URI");
} catch (SQLiteException sqe) {
// expected
}
// Test with an attached database, but no attachment found - should return null // Test with an attached database, but no attachment found - should return null
setupAttachmentDatabase(account1); setupAttachmentDatabase(account1);
@ -141,26 +135,26 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
Attachment newAttachment1 = ProviderTestUtils.setupAttachment(message1Id, "file1", 100, Attachment newAttachment1 = ProviderTestUtils.setupAttachment(message1Id, "file1", 100,
false, mMockContext); false, mMockContext);
newAttachment1.mContentUri = newAttachment1.mContentUri =
AttachmentProvider.getAttachmentUri(account1, attachment1Id).toString(); AttachmentProvider.getAttachmentUri(account1.mId, attachment1Id).toString();
attachment1Id = addAttachmentToDb(account1, newAttachment1); attachment1Id = addAttachmentToDb(account1, newAttachment1);
assertEquals("Broken test: Unexpected id assignment", 1, attachment1Id); assertEquals("Broken test: Unexpected id assignment", 1, attachment1Id);
Attachment newAttachment2 = ProviderTestUtils.setupAttachment(message1Id, "file2", 200, Attachment newAttachment2 = ProviderTestUtils.setupAttachment(message1Id, "file2", 200,
false, mMockContext); false, mMockContext);
newAttachment2.mContentUri = newAttachment2.mContentUri =
AttachmentProvider.getAttachmentUri(account1, attachment2Id).toString(); AttachmentProvider.getAttachmentUri(account1.mId, attachment2Id).toString();
attachment2Id = addAttachmentToDb(account1, newAttachment2); attachment2Id = addAttachmentToDb(account1, newAttachment2);
assertEquals("Broken test: Unexpected id assignment", 2, attachment2Id); assertEquals("Broken test: Unexpected id assignment", 2, attachment2Id);
Attachment newAttachment3 = ProviderTestUtils.setupAttachment(message1Id, "file3", 300, Attachment newAttachment3 = ProviderTestUtils.setupAttachment(message1Id, "file3", 300,
false, mMockContext); false, mMockContext);
newAttachment3.mContentUri = newAttachment3.mContentUri =
AttachmentProvider.getAttachmentUri(account1, attachment3Id).toString(); AttachmentProvider.getAttachmentUri(account1.mId, attachment3Id).toString();
attachment3Id = addAttachmentToDb(account1, newAttachment3); attachment3Id = addAttachmentToDb(account1, newAttachment3);
assertEquals("Broken test: Unexpected id assignment", 3, attachment3Id); assertEquals("Broken test: Unexpected id assignment", 3, attachment3Id);
// Return a row with all columns specified // Return a row with all columns specified
attachment2Uri = AttachmentProvider.getAttachmentUri(account1, attachment2Id); attachment2Uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment2Id);
c = mMockResolver.query( c = mMockResolver.query(
attachment2Uri, attachment2Uri,
new String[] { AttachmentProviderColumns._ID, AttachmentProviderColumns.DATA, new String[] { AttachmentProviderColumns._ID, AttachmentProviderColumns.DATA,
@ -175,7 +169,7 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
assertEquals(200, c.getInt(3)); // size assertEquals(200, c.getInt(3)); // size
// Return a row with permuted columns // Return a row with permuted columns
attachment3Uri = AttachmentProvider.getAttachmentUri(account1, attachment3Id); attachment3Uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment3Id);
c = mMockResolver.query( c = mMockResolver.query(
attachment3Uri, attachment3Uri,
new String[] { AttachmentProviderColumns.SIZE, new String[] { AttachmentProviderColumns.SIZE,
@ -204,7 +198,7 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
long attachment2Id = 2; long attachment2Id = 2;
long attachment3Id = 3; long attachment3Id = 3;
Uri attachment1Uri = AttachmentProvider.getAttachmentUri(account1, attachment1Id); Uri attachment1Uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment1Id);
// Test with no attached database - should return null // Test with no attached database - should return null
String type = mMockResolver.getType(attachment1Uri); String type = mMockResolver.getType(attachment1Uri);
@ -224,14 +218,14 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
Attachment newAttachment3 = ProviderTestUtils.setupAttachment(message1Id, "file3", 100, Attachment newAttachment3 = ProviderTestUtils.setupAttachment(message1Id, "file3", 100,
false, mMockContext); false, mMockContext);
newAttachment2.mMimeType = "text/plain"; newAttachment3.mMimeType = "text/plain";
attachment3Id = addAttachmentToDb(account1, newAttachment2); attachment3Id = addAttachmentToDb(account1, newAttachment3);
// Check the returned filetypes // Check the returned filetypes
Uri uri = AttachmentProvider.getAttachmentUri(account1, attachment2Id); Uri uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment2Id);
type = mMockResolver.getType(uri); type = mMockResolver.getType(uri);
assertEquals("image/jpg", type); assertEquals("image/jpg", type);
uri = AttachmentProvider.getAttachmentUri(account1, attachment3Id); uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment3Id);
type = mMockResolver.getType(uri); type = mMockResolver.getType(uri);
assertEquals("text/plain", type); assertEquals("text/plain", type);
@ -261,8 +255,8 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
// attachment we add will be id=1 and the 2nd will have id=2. This could fail on // attachment we add will be id=1 and the 2nd will have id=2. This could fail on
// a legitimate implementation. Asserts below will catch this and fail the test // a legitimate implementation. Asserts below will catch this and fail the test
// if necessary. // if necessary.
Uri file1Uri = AttachmentProvider.getAttachmentUri(account1, attachment1Id); Uri file1Uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment1Id);
Uri file2Uri = AttachmentProvider.getAttachmentUri(account1, attachment2Id); Uri file2Uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment2Id);
// Test with no attached database - should throw an exception // Test with no attached database - should throw an exception
AssetFileDescriptor afd; AssetFileDescriptor afd;
@ -302,7 +296,7 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
false, mMockContext); false, mMockContext);
newAttachment2.mContentId = null; newAttachment2.mContentId = null;
newAttachment2.mContentUri = newAttachment2.mContentUri =
AttachmentProvider.getAttachmentUri(account1, attachment2Id).toString(); AttachmentProvider.getAttachmentUri(account1.mId, attachment2Id).toString();
newAttachment2.mMimeType = "image/png"; newAttachment2.mMimeType = "image/png";
attachment2Id = addAttachmentToDb(account1, newAttachment2); attachment2Id = addAttachmentToDb(account1, newAttachment2);
assertEquals("Broken test: Unexpected id assignment", 2, attachment2Id); assertEquals("Broken test: Unexpected id assignment", 2, attachment2Id);
@ -340,17 +334,13 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
Uri thumb2Uri = AttachmentProvider.getAttachmentThumbnailUri(account1, attachment2Id, Uri thumb2Uri = AttachmentProvider.getAttachmentThumbnailUri(account1, attachment2Id,
62, 62); 62, 62);
// Test with no attached database - should throw an exception // Test with no attached database - should return null (used to throw SQLiteException)
try { AssetFileDescriptor afd = mMockResolver.openAssetFileDescriptor(thumb1Uri, "r");
/* AssetFileDescriptor afd = */ mMockResolver.openAssetFileDescriptor(thumb1Uri, "r"); assertNull(afd);
fail("Should throw an exception on a bad URI");
} catch (SQLiteException sqe) {
// expected
}
// Test with an attached database, but no attachment found // Test with an attached database, but no attachment found
setupAttachmentDatabase(account1); setupAttachmentDatabase(account1);
AssetFileDescriptor afd = mMockResolver.openAssetFileDescriptor(thumb1Uri, "r"); afd = mMockResolver.openAssetFileDescriptor(thumb1Uri, "r");
assertNull(afd); assertNull(afd);
// Add an attachment (but no associated file) // Add an attachment (but no associated file)
@ -369,7 +359,7 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
false, mMockContext); false, mMockContext);
newAttachment2.mContentId = null; newAttachment2.mContentId = null;
newAttachment2.mContentUri = newAttachment2.mContentUri =
AttachmentProvider.getAttachmentUri(account1, attachment2Id).toString(); AttachmentProvider.getAttachmentUri(account1.mId, attachment2Id).toString();
newAttachment2.mMimeType = "image/png"; newAttachment2.mMimeType = "image/png";
attachment2Id = addAttachmentToDb(account1, newAttachment2); attachment2Id = addAttachmentToDb(account1, newAttachment2);
assertEquals("Broken test: Unexpected id assignment", 2, attachment2Id); assertEquals("Broken test: Unexpected id assignment", 2, attachment2Id);
@ -397,20 +387,16 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
// attachment we add will be id=1 and the 2nd will have id=2. This could fail on // attachment we add will be id=1 and the 2nd will have id=2. This could fail on
// a legitimate implementation. Asserts below will catch this and fail the test // a legitimate implementation. Asserts below will catch this and fail the test
// if necessary. // if necessary.
Uri attachment1Uri = AttachmentProvider.getAttachmentUri(account1, attachment1Id); Uri attachment1Uri = AttachmentProvider.getAttachmentUri(account1.mId, attachment1Id);
// Test with no attached database - should return null, but throws SQLiteException // Test with no attached database - should return input
try { Uri result = AttachmentProvider.resolveAttachmentIdToContentUri(
Uri result = AttachmentProvider.resolveAttachmentIdToContentUri(
mMockResolver, attachment1Uri); mMockResolver, attachment1Uri);
fail("Expected an exception on a bad URI"); assertEquals(attachment1Uri, result);
} catch (SQLiteException sqe) {
// expected
}
// Test with an attached database, but no attachment found - should return input // Test with an attached database, but no attachment found - should return input
setupAttachmentDatabase(account1); setupAttachmentDatabase(account1);
Uri result = AttachmentProvider.resolveAttachmentIdToContentUri( result = AttachmentProvider.resolveAttachmentIdToContentUri(
mMockResolver, attachment1Uri); mMockResolver, attachment1Uri);
assertEquals(attachment1Uri, result); assertEquals(attachment1Uri, result);
@ -451,7 +437,7 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
String localStoreUri = "local://localhost/" + dbName(forAccount); String localStoreUri = "local://localhost/" + dbName(forAccount);
mLocalStore = (LocalStore) LocalStore.newInstance(localStoreUri, mMockContext, null); mLocalStore = (LocalStore) LocalStore.newInstance(localStoreUri, mMockContext, null);
} else { } else {
throw new java.lang.UnsupportedOperationException(); // Nothing to do - EmailProvider is already available for us
} }
} }
@ -482,7 +468,8 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
} }
} }
} else { } else {
throw new java.lang.UnsupportedOperationException(); newAttachment.save(mMockContext);
attachmentId = newAttachment.mId;
} }
return attachmentId; return attachmentId;
} }
@ -507,7 +494,11 @@ public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvide
return new File(mMockContext.getDatabasePath(forAccount.mCompatibilityUuid + ".db_att"), return new File(mMockContext.getDatabasePath(forAccount.mCompatibilityUuid + ".db_att"),
idString); idString);
} else { } else {
throw new java.lang.UnsupportedOperationException(); File attachmentsDir = mMockContext.getDatabasePath(forAccount.mId + ".db_att");
if (!attachmentsDir.exists()) {
attachmentsDir.mkdirs();
}
return new File(attachmentsDir, idString);
} }
} }
} }