Permalink
Browse files

Catch all exceptions from openFile(Artwork)

Instead of making the default implementation of openFile(Artwork) artificially limited to only IOExceptions and SecurityExceptions, have openFile(Artwork) throw any exception (as is common for content:// URIs).

Call onInvalidArtwork whenever a non-IOException is thrown.
  • Loading branch information...
ianhanniballake committed Oct 25, 2018
1 parent de8e298 commit 8e32da664a2ae021441215076e55b81b959ba9cf
@@ -879,7 +879,7 @@ public final ParcelFileDescriptor openFile(
}
if (!isArtworkValid(artwork)) {
onInvalidArtwork(artwork);
throw new SecurityException("Artwork was marked as invalid by the MuzeiArtProvider");
throw new SecurityException("Artwork " + artwork + " was marked as invalid");
}
if (!artwork.getData().exists() && mode.equals("r")) {
// Download the image from the persistent URI for read-only operations
@@ -899,17 +899,17 @@ public final ParcelFileDescriptor openFile(
out.write(buffer, 0, bytesRead);
}
out.flush();
} catch (IOException | SecurityException e) {
Log.e(TAG, "Unable to open artwork " + artwork + " for " + uri, e);
if (e instanceof SecurityException) {
delete(uri, null, null);
} catch (Exception e) {
if (!(e instanceof IOException)) {
Log.e(TAG, "Unable to open artwork " + artwork + " for " + uri, e);
onInvalidArtwork(artwork);
}
// Delete the file in cases of an error so that we will try again from scratch next time.
if (artwork.getData().exists() && !artwork.getData().delete()) {
Log.w(TAG, "Error deleting partially downloaded file after error", e);
}
throw new FileNotFoundException("Could not download artwork " + artwork
+ " for " + uri);
+ " for " + uri + ": " + e.getMessage());
}
}
return ParcelFileDescriptor.open(artwork.getData(), ParcelFileDescriptor.parseMode(mode));
@@ -962,8 +962,8 @@ public boolean isArtworkValid(@NonNull Artwork artwork) {
* <li><code>file:///android_asset/...</code>.</li>
* <li><code>http://...</code> or <code>https://...</code>.</li>
* </ul>
* Throw a {@link SecurityException} if there is a permanent error that causes the artwork to be
* no longer accessible.
* Throwing any exception other than an {@link IOException} will be considered a permanent
* error that will result in a call to {@link #onInvalidArtwork(Artwork)}.
*
* @param artwork The Artwork to open
* @return A valid {@link InputStream} for the artwork's image
@@ -990,17 +990,7 @@ protected InputStream openFile(@NonNull Artwork artwork) throws IOException {
InputStream in = null;
if (ContentResolver.SCHEME_CONTENT.equals(scheme)
|| ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
try {
in = context.getContentResolver().openInputStream(persistentUri);
} catch (IOException e) {
// Rethrow IOExceptions to retry later
throw e;
} catch (SecurityException e) {
throw new SecurityException("No access to " + persistentUri + ": " + e.toString());
} catch (Exception e) {
throw new SecurityException("Unknown error accessing " + persistentUri + ": " +
e.toString());
}
in = context.getContentResolver().openInputStream(persistentUri);
} else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
List<String> segments = persistentUri.getPathSegments();
if (segments != null && segments.size() > 1
@@ -86,11 +86,8 @@ class GalleryArtProvider: MuzeiArtProvider() {
// Assume if we can access the row, we can access the image itself
data?.moveToFirst() == true
}
} catch (e: SecurityException) {
// No access to the underlying image anymore == invalid
false
} catch (e: Exception) {
// Other Exceptions could mean a lot of things.
// An exception could mean a lot of things.
// Delete any cached image and defer to openFile
artwork.data.run {
if (exists()) {
@@ -110,23 +107,15 @@ class GalleryArtProvider: MuzeiArtProvider() {
} catch(e: FileNotFoundException) {
// If the source image was deleted, we won't be able to access it again
throw SecurityException("Source image was deleted: ${e.message}")
} catch (e: IOException) {
// Just rethrow IOExceptions, assuming they are temporary errors
throw e
} catch (e: SecurityException) {
Log.i(TAG, "Unable to load $metadata, deleting the row", e)
Log.i(TAG, "Unable to load artwork, deleting $metadata", e)
context?.let { context ->
GlobalScope.launch {
GalleryDatabase.getInstance(context).chosenPhotoDao().delete(
context, metadata)
}
}
throw SecurityException("No permission to load $metadata")
} catch (e: Exception) {
// ContentProviders can throw a lot of crazy errors
// We'll mark this as an unrecoverable error, but not delete
// our ChosenPhoto record in a hope that it recovers at some point
throw SecurityException("Unknown error reading image: ${e.message}")
throw e
}
}
}

0 comments on commit 8e32da6

Please sign in to comment.