Bug 1499618 Crash in java.lang.IllegalArgumentException: at android.database.AbstractCursor.getColumnIndexOrThrow(AbstractCursor.java) r=JanH

Added fallback for the cases where trying to obtain a file absolute path from
external storage was throwing an exception.

Differential Revision: https://phabricator.services.mozilla.com/D9248

--HG--
extra : rebase_source : 7f6386e0dd47e503c412e6e9b552e8bf935851c9
extra : source : 3ad6353532ad19cc566c6f44bb47eb514987cc99
This commit is contained in:
Andrei Lazar 2018-11-21 16:33:38 +00:00
Родитель a4008cfe9a
Коммит 6e2e2a7b48
3 изменённых файлов: 81 добавлений и 15 удалений

Просмотреть файл

@ -41,7 +41,7 @@ import java.util.Locale;
import static org.mozilla.gecko.Tabs.INTENT_EXTRA_SESSION_UUID;
import static org.mozilla.gecko.Tabs.INTENT_EXTRA_TAB_ID;
import static org.mozilla.gecko.util.FileUtils.getFilePathFromUri;
import static org.mozilla.gecko.util.FileUtils.resolveContentUri;
public final class IntentHelper implements BundleEventListener {
@ -512,8 +512,11 @@ public final class IntentHelper implements BundleEventListener {
}
if (FileUtils.isContentUri(uri)) {
errorResponse.putString("uri", getFilePathFromUri(getContext(), intent.getData()));
errorResponse.putBoolean("isFallback", true);
final String contentUri = resolveContentUri(getContext(), intent.getData());
if (!TextUtils.isEmpty(contentUri)) {
errorResponse.putString("uri", contentUri);
errorResponse.putBoolean("isFallback", true);
}
callback.sendError(errorResponse);
return;
}

Просмотреть файл

@ -24,8 +24,11 @@ import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import java.io.File;
/**
* Based on https://github.com/iPaulPro/aFileChooser/blob/48d65e6649d4201407702b0390326ec9d5c9d17c/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java
*/
@ -42,7 +45,7 @@ public class ContentUriUtils {
* @param uri The Uri to query.
* @author paulburke
*/
public static String getPath(final Context context, final Uri uri) {
public static @Nullable String getOriginalFilePathFromUri(final Context context, final Uri uri) throws IllegalArgumentException {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
@ -118,6 +121,30 @@ public class ContentUriUtils {
return null;
}
/**
* Retrieves file contents via getContentResolver().openInputStream() and stores them in a
* temporary file.
*
* @return The path of the temporary file, or <code>null</code> if there was an error
* retrieving the file.
*/
public static @Nullable String getTempFilePathFromContentUri(Context context, Uri contentUri) {
//copy file and send new file path
final String fileName = FileUtils.getFileNameFromContentUri(context, contentUri);
final File folder = new File(context.getCacheDir(), FileUtils.CONTENT_TEMP_DIRECTORY);
boolean success = true;
if (!folder.exists()) {
success = folder.mkdirs();
}
if (!TextUtils.isEmpty(fileName) && success) {
File copyFile = new File(folder.getPath(), fileName);
FileUtils.copy(context, contentUri, copyFile);
return copyFile.getAbsolutePath();
}
return null;
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
@ -130,24 +157,19 @@ public class ContentUriUtils {
* @author paulburke
*/
private static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
String[] selectionArgs) throws IllegalArgumentException {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {
column
};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
try (Cursor cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null)) {
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}

Просмотреть файл

@ -4,8 +4,12 @@
package org.mozilla.gecko.util;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;
import java.io.File;
@ -29,13 +33,15 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.gecko.annotation.RobocopTarget;
import static org.mozilla.gecko.util.ContentUriUtils.getPath;
import static org.mozilla.gecko.util.ContentUriUtils.getOriginalFilePathFromUri;
import static org.mozilla.gecko.util.ContentUriUtils.getTempFilePathFromContentUri;
public class FileUtils {
private static final String LOGTAG = "GeckoFileUtils";
private static final String FILE_SCHEME = "file";
private static final String CONTENT_SCHEME = "content";
private static final String FILE_ABSOLUTE_URI = FILE_SCHEME + "://%s";
public static final String CONTENT_TEMP_DIRECTORY = "contentUri";
/*
* A basic Filter for checking a filename and age.
@ -287,8 +293,43 @@ public class FileUtils {
return result;
}
public static String getFilePathFromUri(final Context context, final Uri uri) {
return String.format(FILE_ABSOLUTE_URI, getPath(context, uri));
public static String resolveContentUri(final Context context, final Uri uri) {
String path;
try {
path = getOriginalFilePathFromUri(context, uri);
} catch (IllegalArgumentException ex) {
// We cannot always successfully guess the original path of the file behind the
// content:// URI, so we need a fallback. This will break local subresources and
// relative links, but unfortunately there's nothing else we can do
// (see https://issuetracker.google.com/issues/77406791).
path = getTempFilePathFromContentUri(context, uri);
}
return !TextUtils.isEmpty(path) ? String.format(FILE_ABSOLUTE_URI, path) : path;
}
public static String getFileNameFromContentUri(Context context, Uri uri) {
final ContentResolver cr = context.getContentResolver();
final String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME};
String fileName = null;
try (Cursor metaCursor = cr.query(uri, projection, null, null, null);) {
if (metaCursor.moveToFirst()) {
fileName = metaCursor.getString(0);
}
} catch (Exception e) {
e.printStackTrace();
}
return fileName;
}
public static void copy(Context context, Uri srcUri, File dstFile) {
try (InputStream inputStream = context.getContentResolver().openInputStream(srcUri);
OutputStream outputStream = new FileOutputStream(dstFile)) {
IOUtils.copy(inputStream, outputStream);
} catch (Exception e) {
e.printStackTrace();
}
}
public static boolean isContentUri(Uri uri) {