1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.base; 6 7 import android.content.ContentResolver; 8 import android.content.Context; 9 import android.database.Cursor; 10 import android.net.Uri; 11 import android.os.ParcelFileDescriptor; 12 import android.util.Log; 13 14 import java.io.File; 15 16 /** 17 * This class provides methods to access content URI schemes. 18 */ 19 public abstract class ContentUriUtils { 20 private static final String TAG = "ContentUriUtils"; 21 private static FileProviderUtil sFileProviderUtil; 22 23 /** 24 * Provides functionality to translate a file into a content URI for use 25 * with a content provider. 26 */ 27 public interface FileProviderUtil { 28 /** 29 * Generate a content uri from the given file. 30 * @param context Application context. 31 * @param file The file to be translated. 32 */ getContentUriFromFile(Context context, File file)33 public Uri getContentUriFromFile(Context context, File file); 34 } 35 36 // Prevent instantiation. ContentUriUtils()37 private ContentUriUtils() {} 38 setFileProviderUtil(FileProviderUtil util)39 public static void setFileProviderUtil(FileProviderUtil util) { 40 sFileProviderUtil = util; 41 } 42 getContentUriFromFile(Context context, File file)43 public static Uri getContentUriFromFile(Context context, File file) { 44 ThreadUtils.assertOnUiThread(); 45 if (sFileProviderUtil != null) { 46 return sFileProviderUtil.getContentUriFromFile(context, file); 47 } 48 return null; 49 } 50 51 /** 52 * Opens the content URI for reading, and returns the file descriptor to 53 * the caller. The caller is responsible for closing the file desciptor. 54 * 55 * @param context {@link Context} in interest 56 * @param uriString the content URI to open 57 * @returns file desciptor upon sucess, or -1 otherwise. 58 */ 59 @CalledByNative openContentUriForRead(Context context, String uriString)60 public static int openContentUriForRead(Context context, String uriString) { 61 ParcelFileDescriptor pfd = getParcelFileDescriptor(context, uriString); 62 if (pfd != null) { 63 return pfd.detachFd(); 64 } 65 return -1; 66 } 67 68 /** 69 * Check whether a content URI exists. 70 * 71 * @param context {@link Context} in interest. 72 * @param uriString the content URI to query. 73 * @returns true if the uri exists, or false otherwise. 74 */ 75 @CalledByNative contentUriExists(Context context, String uriString)76 public static boolean contentUriExists(Context context, String uriString) { 77 ParcelFileDescriptor pfd = getParcelFileDescriptor(context, uriString); 78 if (pfd == null) { 79 return false; 80 } 81 return true; 82 } 83 84 /** 85 * Helper method to open a content URI and return the ParcelFileDescriptor. 86 * 87 * @param context {@link Context} in interest. 88 * @param uriString the content URI to open. 89 * @returns ParcelFileDescriptor of the content URI, or NULL if the file does not exist. 90 */ getParcelFileDescriptor(Context context, String uriString)91 private static ParcelFileDescriptor getParcelFileDescriptor(Context context, String uriString) { 92 ContentResolver resolver = context.getContentResolver(); 93 Uri uri = Uri.parse(uriString); 94 95 ParcelFileDescriptor pfd = null; 96 try { 97 pfd = resolver.openFileDescriptor(uri, "r"); 98 } catch (java.io.FileNotFoundException e) { 99 Log.w(TAG, "Cannot find content uri: " + uriString, e); 100 } 101 return pfd; 102 } 103 104 /** 105 * Method to resolve the display name of a content URI. 106 * 107 * @param uri the content URI to be resolved. 108 * @param contentResolver the content resolver to query. 109 * @param columnField the column field to query. 110 * @returns the display name of the @code uri if present in the database 111 * or an empty string otherwise. 112 */ getDisplayName( Uri uri, ContentResolver contentResolver, String columnField)113 public static String getDisplayName( 114 Uri uri, ContentResolver contentResolver, String columnField) { 115 if (contentResolver == null || uri == null) return ""; 116 Cursor cursor = null; 117 try { 118 cursor = contentResolver.query(uri, null, null, null, null); 119 120 if (cursor != null && cursor.getCount() >= 1) { 121 cursor.moveToFirst(); 122 int index = cursor.getColumnIndex(columnField); 123 if (index > -1) return cursor.getString(index); 124 } 125 } catch (NullPointerException e) { 126 // Some android models don't handle the provider call correctly. 127 // see crbug.com/345393 128 return ""; 129 } finally { 130 if (cursor != null) cursor.close(); 131 } 132 return ""; 133 } 134 } 135