Skip to content

Commit 6e2e2a7

Browse files
author
Andrei Lazar
committed
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
1 parent a4008cf commit 6e2e2a7

File tree

3 files changed

+81
-15
lines changed

3 files changed

+81
-15
lines changed

mobile/android/base/java/org/mozilla/gecko/IntentHelper.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141

4242
import static org.mozilla.gecko.Tabs.INTENT_EXTRA_SESSION_UUID;
4343
import static org.mozilla.gecko.Tabs.INTENT_EXTRA_TAB_ID;
44-
import static org.mozilla.gecko.util.FileUtils.getFilePathFromUri;
44+
import static org.mozilla.gecko.util.FileUtils.resolveContentUri;
4545

4646
public final class IntentHelper implements BundleEventListener {
4747

@@ -512,8 +512,11 @@ private void openNoHandler(final GeckoBundle msg, final EventCallback callback)
512512
}
513513

514514
if (FileUtils.isContentUri(uri)) {
515-
errorResponse.putString("uri", getFilePathFromUri(getContext(), intent.getData()));
516-
errorResponse.putBoolean("isFallback", true);
515+
final String contentUri = resolveContentUri(getContext(), intent.getData());
516+
if (!TextUtils.isEmpty(contentUri)) {
517+
errorResponse.putString("uri", contentUri);
518+
errorResponse.putBoolean("isFallback", true);
519+
}
517520
callback.sendError(errorResponse);
518521
return;
519522
}

mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ContentUriUtils.java

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@
2424
import android.os.Environment;
2525
import android.provider.DocumentsContract;
2626
import android.provider.MediaStore;
27+
import android.support.annotation.Nullable;
2728
import android.text.TextUtils;
2829

30+
import java.io.File;
31+
2932
/**
3033
* Based on https://github.com/iPaulPro/aFileChooser/blob/48d65e6649d4201407702b0390326ec9d5c9d17c/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java
3134
*/
@@ -42,7 +45,7 @@ public class ContentUriUtils {
4245
* @param uri The Uri to query.
4346
* @author paulburke
4447
*/
45-
public static String getPath(final Context context, final Uri uri) {
48+
public static @Nullable String getOriginalFilePathFromUri(final Context context, final Uri uri) throws IllegalArgumentException {
4649

4750
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
4851

@@ -118,6 +121,30 @@ else if ("file".equalsIgnoreCase(uri.getScheme())) {
118121
return null;
119122
}
120123

124+
/**
125+
* Retrieves file contents via getContentResolver().openInputStream() and stores them in a
126+
* temporary file.
127+
*
128+
* @return The path of the temporary file, or <code>null</code> if there was an error
129+
* retrieving the file.
130+
*/
131+
public static @Nullable String getTempFilePathFromContentUri(Context context, Uri contentUri) {
132+
//copy file and send new file path
133+
final String fileName = FileUtils.getFileNameFromContentUri(context, contentUri);
134+
final File folder = new File(context.getCacheDir(), FileUtils.CONTENT_TEMP_DIRECTORY);
135+
boolean success = true;
136+
if (!folder.exists()) {
137+
success = folder.mkdirs();
138+
}
139+
140+
if (!TextUtils.isEmpty(fileName) && success) {
141+
File copyFile = new File(folder.getPath(), fileName);
142+
FileUtils.copy(context, contentUri, copyFile);
143+
return copyFile.getAbsolutePath();
144+
}
145+
return null;
146+
}
147+
121148
/**
122149
* Get the value of the data column for this Uri. This is useful for
123150
* MediaStore Uris, and other file-based ContentProviders.
@@ -130,24 +157,19 @@ else if ("file".equalsIgnoreCase(uri.getScheme())) {
130157
* @author paulburke
131158
*/
132159
private static String getDataColumn(Context context, Uri uri, String selection,
133-
String[] selectionArgs) {
160+
String[] selectionArgs) throws IllegalArgumentException {
134161

135-
Cursor cursor = null;
136162
final String column = "_data";
137163
final String[] projection = {
138164
column
139165
};
140166

141-
try {
142-
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
143-
null);
167+
try (Cursor cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
168+
null)) {
144169
if (cursor != null && cursor.moveToFirst()) {
145170
final int column_index = cursor.getColumnIndexOrThrow(column);
146171
return cursor.getString(column_index);
147172
}
148-
} finally {
149-
if (cursor != null)
150-
cursor.close();
151173
}
152174
return null;
153175
}

mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/FileUtils.java

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@
44

55
package org.mozilla.gecko.util;
66

7+
import android.content.ContentResolver;
78
import android.content.Context;
9+
import android.database.Cursor;
810
import android.net.Uri;
11+
import android.provider.MediaStore;
12+
import android.text.TextUtils;
913
import android.util.Log;
1014

1115
import java.io.File;
@@ -29,13 +33,15 @@
2933
import org.json.JSONObject;
3034
import org.mozilla.gecko.annotation.RobocopTarget;
3135

32-
import static org.mozilla.gecko.util.ContentUriUtils.getPath;
36+
import static org.mozilla.gecko.util.ContentUriUtils.getOriginalFilePathFromUri;
37+
import static org.mozilla.gecko.util.ContentUriUtils.getTempFilePathFromContentUri;
3338

3439
public class FileUtils {
3540
private static final String LOGTAG = "GeckoFileUtils";
3641
private static final String FILE_SCHEME = "file";
3742
private static final String CONTENT_SCHEME = "content";
3843
private static final String FILE_ABSOLUTE_URI = FILE_SCHEME + "://%s";
44+
public static final String CONTENT_TEMP_DIRECTORY = "contentUri";
3945

4046
/*
4147
* A basic Filter for checking a filename and age.
@@ -287,8 +293,43 @@ public static File createTempDir(File directory, String prefix) {
287293
return result;
288294
}
289295

290-
public static String getFilePathFromUri(final Context context, final Uri uri) {
291-
return String.format(FILE_ABSOLUTE_URI, getPath(context, uri));
296+
public static String resolveContentUri(final Context context, final Uri uri) {
297+
String path;
298+
try {
299+
path = getOriginalFilePathFromUri(context, uri);
300+
} catch (IllegalArgumentException ex) {
301+
// We cannot always successfully guess the original path of the file behind the
302+
// content:// URI, so we need a fallback. This will break local subresources and
303+
// relative links, but unfortunately there's nothing else we can do
304+
// (see https://issuetracker.google.com/issues/77406791).
305+
path = getTempFilePathFromContentUri(context, uri);
306+
}
307+
return !TextUtils.isEmpty(path) ? String.format(FILE_ABSOLUTE_URI, path) : path;
308+
}
309+
310+
public static String getFileNameFromContentUri(Context context, Uri uri) {
311+
final ContentResolver cr = context.getContentResolver();
312+
final String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME};
313+
String fileName = null;
314+
315+
try (Cursor metaCursor = cr.query(uri, projection, null, null, null);) {
316+
if (metaCursor.moveToFirst()) {
317+
fileName = metaCursor.getString(0);
318+
}
319+
} catch (Exception e) {
320+
e.printStackTrace();
321+
}
322+
323+
return fileName;
324+
}
325+
326+
public static void copy(Context context, Uri srcUri, File dstFile) {
327+
try (InputStream inputStream = context.getContentResolver().openInputStream(srcUri);
328+
OutputStream outputStream = new FileOutputStream(dstFile)) {
329+
IOUtils.copy(inputStream, outputStream);
330+
} catch (Exception e) {
331+
e.printStackTrace();
332+
}
292333
}
293334

294335
public static boolean isContentUri(Uri uri) {

0 commit comments

Comments
 (0)