Fix security exception when setting contact photo from Downloads
Bug: 10842701
Change-Id: I56936ee7a656a6e5418d15082365f4f38b109221
diff --git a/src/com/android/contacts/activities/AttachPhotoActivity.java b/src/com/android/contacts/activities/AttachPhotoActivity.java
index 3239f55..678c1d2 100644
--- a/src/com/android/contacts/activities/AttachPhotoActivity.java
+++ b/src/com/android/contacts/activities/AttachPhotoActivity.java
@@ -20,6 +20,7 @@
import android.content.Intent;
import android.content.Loader;
import android.content.Loader.OnLoadCompleteListener;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -59,8 +60,10 @@
private static final String KEY_CONTACT_URI = "contact_uri";
private static final String KEY_TEMP_PHOTO_URI = "temp_photo_uri";
+ private static final String KEY_CROPPED_PHOTO_URI = "cropped_photo_uri";
private Uri mTempPhotoUri;
+ private Uri mCroppedPhotoUri;
private ContentResolver mContentResolver;
@@ -77,8 +80,10 @@
final String uri = icicle.getString(KEY_CONTACT_URI);
mContactUri = (uri == null) ? null : Uri.parse(uri);
mTempPhotoUri = Uri.parse(icicle.getString(KEY_TEMP_PHOTO_URI));
+ mCroppedPhotoUri = Uri.parse(icicle.getString(KEY_CROPPED_PHOTO_URI));
} else {
mTempPhotoUri = ContactPhotoUtils.generateTempImageUri(this);
+ mCroppedPhotoUri = ContactPhotoUtils.generateTempCroppedImageUri(this);
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType(Contacts.CONTENT_TYPE);
startActivityForResult(intent, REQUEST_PICK_CONTACT);
@@ -110,21 +115,37 @@
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent result) {
- if (resultCode != RESULT_OK) {
- finish();
- return;
- }
-
if (requestCode == REQUEST_PICK_CONTACT) {
+ if (resultCode != RESULT_OK) {
+ finish();
+ return;
+ }
// A contact was picked. Launch the cropper to get face detection, the right size, etc.
// TODO: get these values from constants somewhere
- Intent myIntent = getIntent();
- Intent intent = new Intent("com.android.camera.action.CROP", myIntent.getData());
- if (myIntent.getStringExtra("mimeType") != null) {
- intent.setDataAndType(myIntent.getData(), myIntent.getStringExtra("mimeType"));
+ final Intent myIntent = getIntent();
+ final Uri inputUri = myIntent.getData();
+
+ final int perm = checkUriPermission(inputUri, android.os.Process.myPid(),
+ android.os.Process.myUid(), Intent.FLAG_GRANT_READ_URI_PERMISSION |
+ Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+ final Uri toCrop;
+
+ if (perm == PackageManager.PERMISSION_DENIED) {
+ // Work around to save a read-only URI into a temporary file provider URI so that
+ // we can add the FLAG_GRANT_WRITE_URI_PERMISSION flag to the eventual
+ // crop intent b/10837468
+ ContactPhotoUtils.savePhotoFromUriToUri(this, inputUri, mTempPhotoUri, false);
+ toCrop = mTempPhotoUri;
+ } else {
+ toCrop = inputUri;
}
- ContactPhotoUtils.addPhotoPickerExtras(intent, mTempPhotoUri);
+ final Intent intent = new Intent("com.android.camera.action.CROP", toCrop);
+ if (myIntent.getStringExtra("mimeType") != null) {
+ intent.setDataAndType(toCrop, myIntent.getStringExtra("mimeType"));
+ }
+ ContactPhotoUtils.addPhotoPickerExtras(intent, mCroppedPhotoUri);
ContactPhotoUtils.addCropExtras(intent, mPhotoDim);
startActivityForResult(intent, REQUEST_CROP_PHOTO);
@@ -132,6 +153,13 @@
mContactUri = result.getData();
} else if (requestCode == REQUEST_CROP_PHOTO) {
+ // Delete the temporary photo from cache now that we have a cropped version.
+ // We should do this even if the crop failed and we eventually bail
+ getContentResolver().delete(mTempPhotoUri, null, null);
+ if (resultCode != RESULT_OK) {
+ finish();
+ return;
+ }
loadContact(mContactUri, new Listener() {
@Override
public void onContactLoaded(Contact contact) {
@@ -187,7 +215,7 @@
final int size = ContactsUtils.getThumbnailSize(this);
Bitmap bitmap;
try {
- bitmap = ContactPhotoUtils.getBitmapFromUri(this, mTempPhotoUri);
+ bitmap = ContactPhotoUtils.getBitmapFromUri(this, mCroppedPhotoUri);
} catch (FileNotFoundException e) {
Log.w(TAG, "Could not find bitmap");
return;
@@ -221,7 +249,7 @@
contact.isUserProfile(),
null, null,
raw.getRawContactId(),
- mTempPhotoUri
+ mCroppedPhotoUri
);
startService(intent);
finish();