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 5package org.chromium.base; 6 7import android.content.ContentResolver; 8import android.content.Context; 9import android.database.Cursor; 10import android.net.Uri; 11import android.os.ParcelFileDescriptor; 12import android.util.Log; 13 14import org.chromium.base.annotations.CalledByNative; 15 16import java.io.File; 17import java.io.FileNotFoundException; 18 19/** 20 * This class provides methods to access content URI schemes. 21 */ 22public abstract class ContentUriUtils { 23 private static final String TAG = "ContentUriUtils"; 24 private static FileProviderUtil sFileProviderUtil; 25 26 // Guards access to sFileProviderUtil. 27 private static final Object sLock = new Object(); 28 29 /** 30 * Provides functionality to translate a file into a content URI for use 31 * with a content provider. 32 */ 33 public interface FileProviderUtil { 34 /** 35 * Generate a content URI from the given file. 36 * @param context Application context. 37 * @param file The file to be translated. 38 */ 39 Uri getContentUriFromFile(Context context, File file); 40 } 41 42 // Prevent instantiation. 43 private ContentUriUtils() {} 44 45 public static void setFileProviderUtil(FileProviderUtil util) { 46 synchronized (sLock) { 47 sFileProviderUtil = util; 48 } 49 } 50 51 public static Uri getContentUriFromFile(Context context, File file) { 52 synchronized (sLock) { 53 if (sFileProviderUtil != null) { 54 return sFileProviderUtil.getContentUriFromFile(context, file); 55 } 56 } 57 return null; 58 } 59 60 /** 61 * Opens the content URI for reading, and returns the file descriptor to 62 * the caller. The caller is responsible for closing the file desciptor. 63 * 64 * @param context {@link Context} in interest 65 * @param uriString the content URI to open 66 * @return file desciptor upon success, or -1 otherwise. 67 */ 68 @CalledByNative 69 public static int openContentUriForRead(Context context, String uriString) { 70 ParcelFileDescriptor pfd = getParcelFileDescriptor(context, uriString); 71 if (pfd != null) { 72 return pfd.detachFd(); 73 } 74 return -1; 75 } 76 77 /** 78 * Check whether a content URI exists. 79 * 80 * @param context {@link Context} in interest. 81 * @param uriString the content URI to query. 82 * @return true if the URI exists, or false otherwise. 83 */ 84 @CalledByNative 85 public static boolean contentUriExists(Context context, String uriString) { 86 return getParcelFileDescriptor(context, uriString) != null; 87 } 88 89 /** 90 * Retrieve the MIME type for the content URI. 91 * 92 * @param context {@link Context} in interest. 93 * @param uriString the content URI to look up. 94 * @return MIME type or null if the input params are empty or invalid. 95 */ 96 @CalledByNative 97 public static String getMimeType(Context context, String uriString) { 98 ContentResolver resolver = context.getContentResolver(); 99 if (resolver == null) return null; 100 Uri uri = Uri.parse(uriString); 101 return resolver.getType(uri); 102 } 103 104 /** 105 * Helper method to open a content URI and returns the ParcelFileDescriptor. 106 * 107 * @param context {@link Context} in interest. 108 * @param uriString the content URI to open. 109 * @return ParcelFileDescriptor of the content URI, or NULL if the file does not exist. 110 */ 111 private static ParcelFileDescriptor getParcelFileDescriptor(Context context, String uriString) { 112 ContentResolver resolver = context.getContentResolver(); 113 Uri uri = Uri.parse(uriString); 114 115 ParcelFileDescriptor pfd = null; 116 try { 117 pfd = resolver.openFileDescriptor(uri, "r"); 118 } catch (FileNotFoundException e) { 119 Log.w(TAG, "Cannot find content uri: " + uriString, e); 120 } catch (SecurityException e) { 121 Log.w(TAG, "Cannot open content uri: " + uriString, e); 122 } catch (IllegalArgumentException e) { 123 Log.w(TAG, "Unknown content uri: " + uriString, e); 124 } catch (IllegalStateException e) { 125 Log.w(TAG, "Unknown content uri: " + uriString, e); 126 } 127 return pfd; 128 } 129 130 /** 131 * Method to resolve the display name of a content URI. 132 * 133 * @param uri the content URI to be resolved. 134 * @param contentResolver the content resolver to query. 135 * @param columnField the column field to query. 136 * @return the display name of the @code uri if present in the database 137 * or an empty string otherwise. 138 */ 139 public static String getDisplayName( 140 Uri uri, ContentResolver contentResolver, String columnField) { 141 if (contentResolver == null || uri == null) return ""; 142 Cursor cursor = null; 143 try { 144 cursor = contentResolver.query(uri, null, null, null, null); 145 146 if (cursor != null && cursor.getCount() >= 1) { 147 cursor.moveToFirst(); 148 int index = cursor.getColumnIndex(columnField); 149 if (index > -1) return cursor.getString(index); 150 } 151 } catch (NullPointerException e) { 152 // Some android models don't handle the provider call correctly. 153 // see crbug.com/345393 154 return ""; 155 } finally { 156 if (cursor != null) cursor.close(); 157 } 158 return ""; 159 } 160} 161