Fix AttachmentProvider to work properly w/ EmailProvider

* Apps trying to open attachments using AttachmentProvider were
  seeing SecurityExceptions due to the fact that internal calls
  from AttachmentProvider to EmailProvider didn't have their
  calling identity saved/restored.
* Updated provider calls so that these calls use the Email
  process' identity.

Bug: 2908737
Change-Id: Ifb71ad834530c6232728e1aad31439991f8ed379
This commit is contained in:
Marc Blank 2010-08-11 17:31:45 -07:00
parent c4de16b4ff
commit 1ec89e6290
1 changed files with 121 additions and 105 deletions

View File

@ -33,6 +33,7 @@ import android.database.MatrixCursor;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.net.Uri; import android.net.Uri;
import android.os.Binder;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.text.TextUtils; import android.text.TextUtils;
import android.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
@ -150,27 +151,31 @@ public class AttachmentProvider extends ContentProvider {
*/ */
@Override @Override
public String getType(Uri uri) { public String getType(Uri uri) {
List<String> segments = uri.getPathSegments(); long callingId = Binder.clearCallingIdentity();
String accountId = segments.get(0); try {
String id = segments.get(1); List<String> segments = uri.getPathSegments();
String format = segments.get(2); String id = segments.get(1);
if (FORMAT_THUMBNAIL.equals(format)) { String format = segments.get(2);
return "image/png"; if (FORMAT_THUMBNAIL.equals(format)) {
} else { return "image/png";
uri = ContentUris.withAppendedId(Attachment.CONTENT_URI, Long.parseLong(id)); } else {
Cursor c = getContext().getContentResolver().query(uri, MIME_TYPE_PROJECTION, uri = ContentUris.withAppendedId(Attachment.CONTENT_URI, Long.parseLong(id));
null, null, null); Cursor c = getContext().getContentResolver().query(uri, MIME_TYPE_PROJECTION,
try { null, null, null);
if (c.moveToFirst()) { try {
String mimeType = c.getString(MIME_TYPE_COLUMN_MIME_TYPE); if (c.moveToFirst()) {
String fileName = c.getString(MIME_TYPE_COLUMN_FILENAME); String mimeType = c.getString(MIME_TYPE_COLUMN_MIME_TYPE);
mimeType = inferMimeType(fileName, mimeType); String fileName = c.getString(MIME_TYPE_COLUMN_FILENAME);
return mimeType; mimeType = inferMimeType(fileName, mimeType);
return mimeType;
}
} finally {
c.close();
} }
} finally { return null;
c.close();
} }
return null; } finally {
Binder.restoreCallingIdentity(callingId);
} }
} }
@ -234,52 +239,58 @@ 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(); long callingId = Binder.clearCallingIdentity();
String accountId = segments.get(0); try {
String id = segments.get(1); List<String> segments = uri.getPathSegments();
String format = segments.get(2); String accountId = segments.get(0);
if (FORMAT_THUMBNAIL.equals(format)) { String id = segments.get(1);
int width = Integer.parseInt(segments.get(3)); String format = segments.get(2);
int height = Integer.parseInt(segments.get(4)); if (FORMAT_THUMBNAIL.equals(format)) {
String filename = "thmb_" + accountId + "_" + id; int width = Integer.parseInt(segments.get(3));
File dir = getContext().getCacheDir(); int height = Integer.parseInt(segments.get(4));
File file = new File(dir, filename); String filename = "thmb_" + accountId + "_" + id;
if (!file.exists()) { File dir = getContext().getCacheDir();
Uri attachmentUri = getAttachmentUri(Long.parseLong(accountId), Long.parseLong(id)); File file = new File(dir, filename);
Cursor c = query(attachmentUri, if (!file.exists()) {
new String[] { AttachmentProviderColumns.DATA }, null, null, null); Uri attachmentUri =
if (c != null) { getAttachmentUri(Long.parseLong(accountId), Long.parseLong(id));
try { Cursor c = query(attachmentUri,
if (c.moveToFirst()) { new String[] { AttachmentProviderColumns.DATA }, null, null, null);
attachmentUri = Uri.parse(c.getString(0)); if (c != null) {
} else { try {
return null; if (c.moveToFirst()) {
attachmentUri = Uri.parse(c.getString(0));
} else {
return null;
}
} finally {
c.close();
} }
} finally { }
c.close(); String type = getContext().getContentResolver().getType(attachmentUri);
try {
InputStream in =
getContext().getContentResolver().openInputStream(attachmentUri);
Bitmap thumbnail = createThumbnail(type, in);
thumbnail = Bitmap.createScaledBitmap(thumbnail, width, height, true);
FileOutputStream out = new FileOutputStream(file);
thumbnail.compress(Bitmap.CompressFormat.PNG, 100, out);
out.close();
in.close();
}
catch (IOException ioe) {
return null;
} }
} }
String type = getContext().getContentResolver().getType(attachmentUri); return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
try {
InputStream in =
getContext().getContentResolver().openInputStream(attachmentUri);
Bitmap thumbnail = createThumbnail(type, in);
thumbnail = Bitmap.createScaledBitmap(thumbnail, width, height, true);
FileOutputStream out = new FileOutputStream(file);
thumbnail.compress(Bitmap.CompressFormat.PNG, 100, out);
out.close();
in.close();
}
catch (IOException ioe) {
return null;
}
} }
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); else {
} return ParcelFileDescriptor.open(
else { new File(getContext().getDatabasePath(accountId + ".db_att"), id),
return ParcelFileDescriptor.open( ParcelFileDescriptor.MODE_READ_ONLY);
new File(getContext().getDatabasePath(accountId + ".db_att"), id), }
ParcelFileDescriptor.MODE_READ_ONLY); } finally {
Binder.restoreCallingIdentity(callingId);
} }
} }
@ -303,56 +314,61 @@ public class AttachmentProvider extends ContentProvider {
@Override @Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) { String sortOrder) {
if (projection == null) { long callingId = Binder.clearCallingIdentity();
projection =
new String[] {
AttachmentProviderColumns._ID,
AttachmentProviderColumns.DATA,
};
}
List<String> segments = uri.getPathSegments();
String accountId = segments.get(0);
String id = segments.get(1);
String format = segments.get(2);
String name = null;
int size = -1;
String contentUri = null;
uri = ContentUris.withAppendedId(Attachment.CONTENT_URI, Long.parseLong(id));
Cursor c = getContext().getContentResolver().query(uri, PROJECTION_QUERY,
null, null, null);
try { try {
if (c.moveToFirst()) { if (projection == null) {
name = c.getString(0); projection =
size = c.getInt(1); new String[] {
contentUri = c.getString(2); AttachmentProviderColumns._ID,
} else { AttachmentProviderColumns.DATA,
return null; };
} }
} finally {
c.close();
}
MatrixCursor ret = new MatrixCursor(projection); List<String> segments = uri.getPathSegments();
Object[] values = new Object[projection.length]; String accountId = segments.get(0);
for (int i = 0, count = projection.length; i < count; i++) { String id = segments.get(1);
String column = projection[i]; String format = segments.get(2);
if (AttachmentProviderColumns._ID.equals(column)) { String name = null;
values[i] = id; int size = -1;
String contentUri = null;
uri = ContentUris.withAppendedId(Attachment.CONTENT_URI, Long.parseLong(id));
Cursor c = getContext().getContentResolver().query(uri, PROJECTION_QUERY,
null, null, null);
try {
if (c.moveToFirst()) {
name = c.getString(0);
size = c.getInt(1);
contentUri = c.getString(2);
} else {
return null;
}
} finally {
c.close();
} }
else if (AttachmentProviderColumns.DATA.equals(column)) {
values[i] = contentUri; MatrixCursor ret = new MatrixCursor(projection);
} Object[] values = new Object[projection.length];
else if (AttachmentProviderColumns.DISPLAY_NAME.equals(column)) { for (int i = 0, count = projection.length; i < count; i++) {
values[i] = name; String column = projection[i];
} if (AttachmentProviderColumns._ID.equals(column)) {
else if (AttachmentProviderColumns.SIZE.equals(column)) { values[i] = id;
values[i] = size; }
else if (AttachmentProviderColumns.DATA.equals(column)) {
values[i] = contentUri;
}
else if (AttachmentProviderColumns.DISPLAY_NAME.equals(column)) {
values[i] = name;
}
else if (AttachmentProviderColumns.SIZE.equals(column)) {
values[i] = size;
}
} }
ret.addRow(values);
return ret;
} finally {
Binder.restoreCallingIdentity(callingId);
} }
ret.addRow(values);
return ret;
} }
@Override @Override