From 10407d34de7a0aa466470dd402ee10be6249d800 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 26 Oct 2015 14:40:40 +0100 Subject: decrypt: restart operation if interrupted by fragment recreation --- .../keychain/ui/DecryptListFragment.java | 27 ++++++++++------------ 1 file changed, 12 insertions(+), 15 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java index 22ef52f6d..0abe833c6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java @@ -40,6 +40,7 @@ import android.os.AsyncTask; import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Parcelable; +import android.support.annotation.NonNull; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; @@ -97,7 +98,6 @@ public class DecryptListFragment public static final String ARG_CAN_DELETE = "can_delete"; private static final int REQUEST_CODE_OUTPUT = 0x00007007; - public static final String ARG_CURRENT_URI = "current_uri"; private ArrayList mInputUris; private HashMap mInputDataResults; @@ -113,7 +113,7 @@ public class DecryptListFragment /** * Creates new instance of this fragment */ - public static DecryptListFragment newInstance(ArrayList uris, boolean canDelete) { + public static DecryptListFragment newInstance(@NonNull ArrayList uris, boolean canDelete) { DecryptListFragment frag = new DecryptListFragment(); Bundle args = new Bundle(); @@ -170,9 +170,12 @@ public class DecryptListFragment outState.putParcelable(ARG_RESULTS, new ParcelableHashMap<>(results)); outState.putParcelable(ARG_OUTPUT_URIS, new ParcelableHashMap<>(mInputDataResults)); outState.putParcelableArrayList(ARG_CANCELLED_URIS, mCancelledInputUris); - outState.putParcelable(ARG_CURRENT_URI, mCurrentInputUri); outState.putBoolean(ARG_CAN_DELETE, mCanDelete); + // this does not save mCurrentInputUri - if anything is being + // processed at fragment recreation time, the operation in + // progress will be lost! + } @Override @@ -184,20 +187,19 @@ public class DecryptListFragment ArrayList inputUris = getArguments().getParcelableArrayList(ARG_INPUT_URIS); ArrayList cancelledUris = args.getParcelableArrayList(ARG_CANCELLED_URIS); ParcelableHashMap results = args.getParcelable(ARG_RESULTS); - Uri currentInputUri = args.getParcelable(ARG_CURRENT_URI); mCanDelete = args.getBoolean(ARG_CAN_DELETE, false); - displayInputUris(inputUris, currentInputUri, cancelledUris, + displayInputUris(inputUris, cancelledUris, results != null ? results.getMap() : null ); } - private void displayInputUris(ArrayList inputUris, Uri currentInputUri, - ArrayList cancelledUris, HashMap results) { + private void displayInputUris(ArrayList inputUris, ArrayList cancelledUris, + HashMap results) { mInputUris = inputUris; - mCurrentInputUri = currentInputUri; + mCurrentInputUri = null; mInputDataResults = results != null ? results : new HashMap(inputUris.size()); mCancelledInputUris = cancelledUris != null ? cancelledUris : new ArrayList(); @@ -206,10 +208,6 @@ public class DecryptListFragment for (final Uri uri : inputUris) { mAdapter.add(uri); - if (uri.equals(mCurrentInputUri)) { - continue; - } - if (mCancelledInputUris.contains(uri)) { mAdapter.setCancelled(uri, new OnClickListener() { @Override @@ -227,9 +225,8 @@ public class DecryptListFragment } } - if (mCurrentInputUri == null) { - cryptoOperation(); - } + // check if there are any pending input uris + cryptoOperation(); } @Override -- cgit v1.2.3 From c6ea0b6a07df0c509183e4c664b5749a264954f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 13 Nov 2015 17:36:16 +0100 Subject: Request READ_EXTERNAL_STORAGE for decryption --- .../keychain/ui/DecryptListFragment.java | 102 +++++++++++++++++++-- 1 file changed, 94 insertions(+), 8 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java index 0abe833c6..d4190ea3e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java @@ -22,14 +22,17 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.List; +import android.Manifest; import android.annotation.TargetApi; import android.app.Activity; import android.content.ClipDescription; import android.content.Context; import android.content.Intent; import android.content.pm.LabeledIntent; +import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.graphics.Bitmap; import android.graphics.Point; @@ -37,10 +40,12 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.AsyncTask; +import android.os.Build; import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Parcelable; import android.support.annotation.NonNull; +import android.support.v4.content.ContextCompat; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; @@ -98,6 +103,7 @@ public class DecryptListFragment public static final String ARG_CAN_DELETE = "can_delete"; private static final int REQUEST_CODE_OUTPUT = 0x00007007; + private static final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 12; private ArrayList mInputUris; private HashMap mInputDataResults; @@ -218,10 +224,12 @@ public class DecryptListFragment continue; } - if (results != null && results.containsKey(uri)) { - processResult(uri); - } else { - mPendingInputUris.add(uri); + if (readPermissionGranted(uri)) { + if (results != null && results.containsKey(uri)) { + processResult(uri); + } else { + mPendingInputUris.add(uri); + } } } @@ -229,6 +237,82 @@ public class DecryptListFragment cryptoOperation(); } + /** + * Request READ_EXTERNAL_STORAGE permission on Android >= 6.0 to read content from "file" Uris + * + * see + * https://commonsware.com/blog/2015/10/07/runtime-permissions-files-action-send.html + */ + private boolean readPermissionGranted(Uri uri) { + if (Build.VERSION.SDK_INT < VERSION_CODES.M) { + return true; + } + if (! "file".equals(uri.getScheme())) { + return true; + } + + // Build check due to https://commonsware.com/blog/2015/11/09/you-cannot-hold-nonexistent-permissions.html + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN || + ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) + == PackageManager.PERMISSION_GRANTED) { + return true; + } else { + requestPermissions( + new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, + MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE); + + if (! mCancelledInputUris.contains(uri)) { + mCancelledInputUris.add(uri); + } + return false; + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, + @NonNull int[] grantResults) { + switch (requestCode) { + case MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE: { + if (grantResults.length > 0 + && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + + // permission granted -> retry all cancelled uris! + for (Iterator iterator = mCancelledInputUris.iterator(); iterator.hasNext(); ) { + Uri uri = iterator.next(); + + if ("file".equals(uri.getScheme())) { + iterator.remove(); + mPendingInputUris.add(uri); + mAdapter.setCancelled(uri, null); + } + } + + // check if there are any pending input uris + cryptoOperation(); + } else { + + // permission denied -> cancel all file uris + for (final Uri uri : mInputUris) { + if ("file".equals(uri.getScheme())) { + if (! mCancelledInputUris.contains(uri)) { + mCancelledInputUris.add(uri); + } + mAdapter.setCancelled(uri, new OnClickListener() { + @Override + public void onClick(View v) { + retryUri(uri); + } + }); + } + } + } + } + default: { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + } + } + } + @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { @@ -450,12 +534,14 @@ public class DecryptListFragment } // un-cancel this one - mCancelledInputUris.remove(uri); - mPendingInputUris.add(uri); - mAdapter.setCancelled(uri, null); + if (readPermissionGranted(uri)) { + mCancelledInputUris.remove(uri); + mPendingInputUris.add(uri); + mAdapter.setCancelled(uri, null); + } + // check if there are any pending input uris cryptoOperation(); - } public void displayBottomSheet(final InputDataResult result, final int index) { -- cgit v1.2.3 From 1963ca9c2d88f70fdab1c3a696bc832cfc578aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 13 Nov 2015 23:17:34 +0100 Subject: Move permission check to createOperationInput --- .../keychain/ui/DecryptListFragment.java | 187 +++++++++++---------- 1 file changed, 96 insertions(+), 91 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java index d4190ea3e..dbee564b1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java @@ -224,12 +224,10 @@ public class DecryptListFragment continue; } - if (readPermissionGranted(uri)) { - if (results != null && results.containsKey(uri)) { - processResult(uri); - } else { - mPendingInputUris.add(uri); - } + if (results != null && results.containsKey(uri)) { + processResult(uri); + } else { + mPendingInputUris.add(uri); } } @@ -237,82 +235,6 @@ public class DecryptListFragment cryptoOperation(); } - /** - * Request READ_EXTERNAL_STORAGE permission on Android >= 6.0 to read content from "file" Uris - * - * see - * https://commonsware.com/blog/2015/10/07/runtime-permissions-files-action-send.html - */ - private boolean readPermissionGranted(Uri uri) { - if (Build.VERSION.SDK_INT < VERSION_CODES.M) { - return true; - } - if (! "file".equals(uri.getScheme())) { - return true; - } - - // Build check due to https://commonsware.com/blog/2015/11/09/you-cannot-hold-nonexistent-permissions.html - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN || - ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) - == PackageManager.PERMISSION_GRANTED) { - return true; - } else { - requestPermissions( - new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, - MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE); - - if (! mCancelledInputUris.contains(uri)) { - mCancelledInputUris.add(uri); - } - return false; - } - } - - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, - @NonNull int[] grantResults) { - switch (requestCode) { - case MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE: { - if (grantResults.length > 0 - && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - - // permission granted -> retry all cancelled uris! - for (Iterator iterator = mCancelledInputUris.iterator(); iterator.hasNext(); ) { - Uri uri = iterator.next(); - - if ("file".equals(uri.getScheme())) { - iterator.remove(); - mPendingInputUris.add(uri); - mAdapter.setCancelled(uri, null); - } - } - - // check if there are any pending input uris - cryptoOperation(); - } else { - - // permission denied -> cancel all file uris - for (final Uri uri : mInputUris) { - if ("file".equals(uri.getScheme())) { - if (! mCancelledInputUris.contains(uri)) { - mCancelledInputUris.add(uri); - } - mAdapter.setCancelled(uri, new OnClickListener() { - @Override - public void onClick(View v) { - retryUri(uri); - } - }); - } - } - } - } - default: { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - } - } - } - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { @@ -534,11 +456,9 @@ public class DecryptListFragment } // un-cancel this one - if (readPermissionGranted(uri)) { - mCancelledInputUris.remove(uri); - mPendingInputUris.add(uri); - mAdapter.setCancelled(uri, null); - } + mCancelledInputUris.remove(uri); + mPendingInputUris.add(uri); + mAdapter.setCancelled(uri, null); // check if there are any pending input uris cryptoOperation(); @@ -671,12 +591,97 @@ public class DecryptListFragment mCurrentInputUri = mPendingInputUris.remove(0); } - Log.d(Constants.TAG, "mInputUri=" + mCurrentInputUri); + Log.d(Constants.TAG, "mCurrentInputUri=" + mCurrentInputUri); - PgpDecryptVerifyInputParcel decryptInput = new PgpDecryptVerifyInputParcel() - .setAllowSymmetricDecryption(true); - return new InputDataParcel(mCurrentInputUri, decryptInput); + if (readPermissionGranted(mCurrentInputUri)) { + PgpDecryptVerifyInputParcel decryptInput = new PgpDecryptVerifyInputParcel() + .setAllowSymmetricDecryption(true); + return new InputDataParcel(mCurrentInputUri, decryptInput); + } else { + return null; + } + } + + /** + * Request READ_EXTERNAL_STORAGE permission on Android >= 6.0 to read content from "file" Uris + * + * see + * https://commonsware.com/blog/2015/10/07/runtime-permissions-files-action-send.html + */ + private boolean readPermissionGranted(final Uri uri) { + if (Build.VERSION.SDK_INT < VERSION_CODES.M) { + return true; + } + if (! "file".equals(uri.getScheme())) { + return true; + } + + // Build check due to https://commonsware.com/blog/2015/11/09/you-cannot-hold-nonexistent-permissions.html + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN || + ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) + == PackageManager.PERMISSION_GRANTED) { + return true; + } else { + requestPermissions( + new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, + MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE); + + mCurrentInputUri = null; + mCancelledInputUris.add(uri); + mAdapter.setCancelled(uri, new OnClickListener() { + @Override + public void onClick(View v) { + retryUri(uri); + } + }); + return false; + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, + @NonNull int[] grantResults) { + switch (requestCode) { + case MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE: { + if (grantResults.length > 0 + && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + + // permission granted -> retry all cancelled file uris! + for (Iterator iterator = mCancelledInputUris.iterator(); iterator.hasNext(); ) { + Uri uri = iterator.next(); + if ("file".equals(uri.getScheme())) { + iterator.remove(); + mPendingInputUris.add(uri); + mAdapter.setCancelled(uri, null); + } + } + + // check if there are any pending input uris + cryptoOperation(); + } else { + + // permission denied -> cancel all pending file uris + mCurrentInputUri = null; + for (final Uri uri : mPendingInputUris) { + if ("file".equals(uri.getScheme())) { + if (! mCancelledInputUris.contains(uri)) { + mCancelledInputUris.add(uri); + } + mAdapter.setCancelled(uri, new OnClickListener() { + @Override + public void onClick(View v) { + retryUri(uri); + } + }); + } + } + } + } + default: { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + } + } } @Override -- cgit v1.2.3 From e92bd4bea919b6bf9ce9392133b59d9af4678d74 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 14 Nov 2015 17:43:52 +0100 Subject: decryptlist: some cleanup and streamlining of control flow --- .../keychain/ui/DecryptListFragment.java | 165 +++++++++++---------- 1 file changed, 84 insertions(+), 81 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java index dbee564b1..737a5b3b6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java @@ -22,7 +22,6 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import android.Manifest; @@ -103,7 +102,7 @@ public class DecryptListFragment public static final String ARG_CAN_DELETE = "can_delete"; private static final int REQUEST_CODE_OUTPUT = 0x00007007; - private static final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 12; + private static final int REQUEST_PERMISSION_READ_EXTERNAL_STORAGE = 12; private ArrayList mInputUris; private HashMap mInputDataResults; @@ -215,12 +214,7 @@ public class DecryptListFragment mAdapter.add(uri); if (mCancelledInputUris.contains(uri)) { - mAdapter.setCancelled(uri, new OnClickListener() { - @Override - public void onClick(View v) { - retryUri(uri); - } - }); + mAdapter.setCancelled(uri, true); continue; } @@ -362,12 +356,7 @@ public class DecryptListFragment mCurrentInputUri = null; mCancelledInputUris.add(uri); - mAdapter.setCancelled(uri, new OnClickListener() { - @Override - public void onClick(View v) { - retryUri(uri); - } - }); + mAdapter.setCancelled(uri, true); cryptoOperation(); @@ -458,7 +447,7 @@ public class DecryptListFragment // un-cancel this one mCancelledInputUris.remove(uri); mPendingInputUris.add(uri); - mAdapter.setCancelled(uri, null); + mAdapter.setCancelled(uri, false); // check if there are any pending input uris cryptoOperation(); @@ -582,6 +571,11 @@ public class DecryptListFragment @Override public InputDataParcel createOperationInput() { + Activity activity = getActivity(); + if (activity == null) { + return null; + } + if (mCurrentInputUri == null) { if (mPendingInputUris.isEmpty()) { // nothing left to do @@ -593,95 +587,95 @@ public class DecryptListFragment Log.d(Constants.TAG, "mCurrentInputUri=" + mCurrentInputUri); - if (readPermissionGranted(mCurrentInputUri)) { - PgpDecryptVerifyInputParcel decryptInput = new PgpDecryptVerifyInputParcel() - .setAllowSymmetricDecryption(true); - return new InputDataParcel(mCurrentInputUri, decryptInput); - } else { + if ( ! checkAndRequestReadPermission(activity, mCurrentInputUri)) { return null; } + + PgpDecryptVerifyInputParcel decryptInput = new PgpDecryptVerifyInputParcel() + .setAllowSymmetricDecryption(true); + return new InputDataParcel(mCurrentInputUri, decryptInput); + } /** - * Request READ_EXTERNAL_STORAGE permission on Android >= 6.0 to read content from "file" Uris + * Request READ_EXTERNAL_STORAGE permission on Android >= 6.0 to read content from "file" Uris. + * + * This method returns true on Android < 6, or if permission is already granted. It + * requests the permission and returns false otherwise, taking over responsibility + * for mCurrentInputUri. * - * see - * https://commonsware.com/blog/2015/10/07/runtime-permissions-files-action-send.html + * see https://commonsware.com/blog/2015/10/07/runtime-permissions-files-action-send.html */ - private boolean readPermissionGranted(final Uri uri) { + private boolean checkAndRequestReadPermission(Activity activity, final Uri uri) { + if ( ! "file".equals(uri.getScheme())) { + return true; + } + if (Build.VERSION.SDK_INT < VERSION_CODES.M) { return true; } - if (! "file".equals(uri.getScheme())) { + + // Additional check due to https://commonsware.com/blog/2015/11/09/you-cannot-hold-nonexistent-permissions.html + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { return true; } - // Build check due to https://commonsware.com/blog/2015/11/09/you-cannot-hold-nonexistent-permissions.html - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN || - ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) + if (ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { return true; - } else { - requestPermissions( - new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, - MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE); - - mCurrentInputUri = null; - mCancelledInputUris.add(uri); - mAdapter.setCancelled(uri, new OnClickListener() { - @Override - public void onClick(View v) { - retryUri(uri); - } - }); - return false; } + + requestPermissions( + new String[] { Manifest.permission.READ_EXTERNAL_STORAGE }, + REQUEST_PERMISSION_READ_EXTERNAL_STORAGE); + + return false; + } @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, - @NonNull int[] grantResults) { - switch (requestCode) { - case MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE: { - if (grantResults.length > 0 - && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - - // permission granted -> retry all cancelled file uris! - for (Iterator iterator = mCancelledInputUris.iterator(); iterator.hasNext(); ) { - Uri uri = iterator.next(); - - if ("file".equals(uri.getScheme())) { - iterator.remove(); - mPendingInputUris.add(uri); - mAdapter.setCancelled(uri, null); - } - } + public void onRequestPermissionsResult(int requestCode, + @NonNull String[] permissions, + @NonNull int[] grantResults) { - // check if there are any pending input uris - cryptoOperation(); - } else { + if (requestCode != REQUEST_PERMISSION_READ_EXTERNAL_STORAGE) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + return; + } - // permission denied -> cancel all pending file uris - mCurrentInputUri = null; - for (final Uri uri : mPendingInputUris) { - if ("file".equals(uri.getScheme())) { - if (! mCancelledInputUris.contains(uri)) { - mCancelledInputUris.add(uri); - } - mAdapter.setCancelled(uri, new OnClickListener() { - @Override - public void onClick(View v) { - retryUri(uri); - } - }); - } - } + boolean permissionWasGranted = grantResults.length > 0 + && grantResults[0] == PackageManager.PERMISSION_GRANTED; + + if (permissionWasGranted) { + + // permission granted -> retry all cancelled file uris + for (Uri uri : mCancelledInputUris) { + if ( ! "file".equals(uri.getScheme())) { + continue; } + mCancelledInputUris.remove(uri); + mPendingInputUris.add(uri); + mAdapter.setCancelled(uri, false); } - default: { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); + + } else { + + // permission denied -> cancel current, and all pending file uris + mCurrentInputUri = null; + for (final Uri uri : mPendingInputUris) { + if ( ! "file".equals(uri.getScheme())) { + continue; + } + mPendingInputUris.remove(uri); + mCancelledInputUris.add(uri); + mAdapter.setCancelled(uri, true); } + } + + // hand control flow back + cryptoOperation(); + } @Override @@ -1034,10 +1028,19 @@ public class DecryptListFragment notifyItemChanged(pos); } - public void setCancelled(Uri uri, OnClickListener retryListener) { + public void setCancelled(final Uri uri, boolean isCancelled) { ViewModel newModel = new ViewModel(uri); int pos = mDataset.indexOf(newModel); - mDataset.get(pos).setCancelled(retryListener); + if (isCancelled) { + mDataset.get(pos).setCancelled(new OnClickListener() { + @Override + public void onClick(View v) { + retryUri(uri); + } + }); + } else { + mDataset.get(pos).setCancelled(null); + } notifyItemChanged(pos); } -- cgit v1.2.3 From d263bade92c2161ad7759f471341647b4fe2d580 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sat, 14 Nov 2015 18:28:25 +0100 Subject: decryptlist: minor cleanups and documentation --- .../keychain/ui/DecryptListFragment.java | 37 ++++++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java index 737a5b3b6..7db39af6f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java @@ -91,6 +91,22 @@ import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ParcelableHashMap; +/** Displays a list of decrypted inputs. + * + * This class has a complex control flow to manage its input URIs. Each URI + * which is in mInputUris is also in exactly one of mPendingInputUris, + * mCancelledInputUris, mCurrentInputUri, or a key in mInputDataResults. + * + * Processing of URIs happens using a looping approach: + * - There is always exactly one method running which works on mCurrentInputUri + * - Processing starts in cryptoOperation(), which pops a new mCurrentInputUri + * from the list of mPendingInputUris. + * - Once a mCurrentInputUri is finished processing, it should be set to null and + * control handed back to cryptoOperation() + * - Control flow can move through asynchronous calls, and resume in callbacks + * like onActivityResult() or onPermissionRequestResult(). + * + */ public class DecryptListFragment extends QueueingCryptoOperationFragment implements OnMenuItemClickListener { @@ -200,7 +216,9 @@ public class DecryptListFragment ); } - private void displayInputUris(ArrayList inputUris, ArrayList cancelledUris, + private void displayInputUris( + ArrayList inputUris, + ArrayList cancelledUris, HashMap results) { mInputUris = inputUris; @@ -213,16 +231,19 @@ public class DecryptListFragment for (final Uri uri : inputUris) { mAdapter.add(uri); - if (mCancelledInputUris.contains(uri)) { + boolean uriIsCancelled = mCancelledInputUris.contains(uri); + if (uriIsCancelled) { mAdapter.setCancelled(uri, true); continue; } - if (results != null && results.containsKey(uri)) { + boolean uriHasResult = results != null && results.containsKey(uri); + if (uriHasResult) { processResult(uri); - } else { - mPendingInputUris.add(uri); + continue; } + + mPendingInputUris.add(uri); } // check if there are any pending input uris @@ -791,8 +812,10 @@ public class DecryptListFragment return false; } ViewModel viewModel = (ViewModel) o; - return !(mInputUri != null ? !mInputUri.equals(viewModel.mInputUri) - : viewModel.mInputUri != null); + if (mInputUri == null) { + return viewModel.mInputUri == null; + } + return mInputUri.equals(viewModel.mInputUri); } // Depends on inputUri only -- cgit v1.2.3