diff options
Diffstat (limited to 'src/com/android/providers/downloads/Helpers.java')
-rw-r--r-- | src/com/android/providers/downloads/Helpers.java | 214 |
1 files changed, 101 insertions, 113 deletions
diff --git a/src/com/android/providers/downloads/Helpers.java b/src/com/android/providers/downloads/Helpers.java index 0c256a75..794bb062 100644 --- a/src/com/android/providers/downloads/Helpers.java +++ b/src/com/android/providers/downloads/Helpers.java @@ -23,19 +23,16 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.database.Cursor; import android.drm.mobile1.DrmRawContent; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; import android.net.Uri; import android.os.Environment; import android.os.StatFs; import android.os.SystemClock; import android.provider.Downloads; -import android.telephony.TelephonyManager; import android.util.Config; import android.util.Log; import android.webkit.MimeTypeMap; -import java.io.File; +import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.util.Random; @@ -76,6 +73,17 @@ public class Helpers { } /** + * Exception thrown from methods called by generateSaveFile() for any fatal error. + */ + private static class GenerateSaveFileError extends Exception { + int mStatus; + + public GenerateSaveFileError(int status) { + mStatus = status; + } + } + + /** * Creates a filename (where the file should be saved) from a uri. */ public static DownloadFileInfo generateSaveFile( @@ -86,18 +94,82 @@ public class Helpers { String contentLocation, String mimeType, int destination, - int contentLength) throws FileNotFoundException { + long contentLength, + boolean isPublicApi) throws FileNotFoundException { + + if (!canHandleDownload(context, mimeType, destination, isPublicApi)) { + return new DownloadFileInfo(null, null, Downloads.Impl.STATUS_NOT_ACCEPTABLE); + } + + String fullFilename; + try { + if (destination == Downloads.Impl.DESTINATION_FILE_URI) { + fullFilename = getPathForFileUri(hint); + } else { + fullFilename = chooseFullPath(context, url, hint, contentDisposition, + contentLocation, mimeType, destination, + contentLength); + } + } catch (GenerateSaveFileError exc) { + return new DownloadFileInfo(null, null, exc.mStatus); + } + + return new DownloadFileInfo(fullFilename, new FileOutputStream(fullFilename), 0); + } + + private static String getPathForFileUri(String hint) throws GenerateSaveFileError { + String path = Uri.parse(hint).getSchemeSpecificPart(); + if (new File(path).exists()) { + Log.d(Constants.TAG, "File already exists: " + path); + throw new GenerateSaveFileError(Downloads.Impl.STATUS_FILE_ERROR); + } + + return path; + } + + private static String chooseFullPath(Context context, String url, String hint, + String contentDisposition, String contentLocation, + String mimeType, int destination, long contentLength) + throws GenerateSaveFileError { + File base = locateDestinationDirectory(context, mimeType, destination, contentLength); + String filename = chooseFilename(url, hint, contentDisposition, contentLocation, + destination); + + // Split filename between base and extension + // Add an extension if filename does not have one + String extension = null; + int dotIndex = filename.indexOf('.'); + if (dotIndex < 0) { + extension = chooseExtensionFromMimeType(mimeType, true); + } else { + extension = chooseExtensionFromFilename(mimeType, destination, filename, dotIndex); + filename = filename.substring(0, dotIndex); + } + + boolean recoveryDir = Constants.RECOVERY_DIRECTORY.equalsIgnoreCase(filename + extension); + + filename = base.getPath() + File.separator + filename; + + if (Constants.LOGVV) { + Log.v(Constants.TAG, "target file: " + filename + extension); + } + + return chooseUniqueFilename(destination, filename, extension, recoveryDir); + } + + private static boolean canHandleDownload(Context context, String mimeType, int destination, + boolean isPublicApi) { + if (isPublicApi) { + return true; + } - /* - * Don't download files that we won't be able to handle - */ if (destination == Downloads.Impl.DESTINATION_EXTERNAL || destination == Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE) { if (mimeType == null) { if (Config.LOGD) { Log.d(Constants.TAG, "external download with no mime type not allowed"); } - return new DownloadFileInfo(null, null, Downloads.Impl.STATUS_NOT_ACCEPTABLE); + return false; } if (!DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING.equalsIgnoreCase(mimeType)) { // Check to see if we are allowed to download this file. Only files @@ -121,32 +193,19 @@ public class Helpers { if (Config.LOGD) { Log.d(Constants.TAG, "no handler found for type " + mimeType); } - return new DownloadFileInfo(null, null, Downloads.Impl.STATUS_NOT_ACCEPTABLE); + return false; } } } - String filename = chooseFilename( - url, hint, contentDisposition, contentLocation, destination); - - // Split filename between base and extension - // Add an extension if filename does not have one - String extension = null; - int dotIndex = filename.indexOf('.'); - if (dotIndex < 0) { - extension = chooseExtensionFromMimeType(mimeType, true); - } else { - extension = chooseExtensionFromFilename( - mimeType, destination, filename, dotIndex); - filename = filename.substring(0, dotIndex); - } - - /* - * Locate the directory where the file will be saved - */ + return true; + } + private static File locateDestinationDirectory(Context context, String mimeType, + int destination, long contentLength) + throws GenerateSaveFileError { File base = null; StatFs stat = null; - // DRM messages should be temporarily stored internally and then passed to + // DRM messages should be temporarily stored internally and then passed to // the DRM content provider if (destination == Downloads.Impl.DESTINATION_CACHE_PARTITION || destination == Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE @@ -170,8 +229,7 @@ public class Helpers { Log.d(Constants.TAG, "download aborted - not enough free space in internal storage"); } - return new DownloadFileInfo(null, null, - Downloads.Impl.STATUS_INSUFFICIENT_SPACE_ERROR); + throw new GenerateSaveFileError(Downloads.Impl.STATUS_INSUFFICIENT_SPACE_ERROR); } else { // Recalculate available space and try again. stat.restat(base.getPath()); @@ -192,8 +250,7 @@ public class Helpers { if (Config.LOGD) { Log.d(Constants.TAG, "download aborted - not enough free space"); } - return new DownloadFileInfo(null, null, - Downloads.Impl.STATUS_INSUFFICIENT_SPACE_ERROR); + throw new GenerateSaveFileError(Downloads.Impl.STATUS_INSUFFICIENT_SPACE_ERROR); } base = new File(root + Constants.DEFAULT_DL_SUBDIR); @@ -204,35 +261,17 @@ public class Helpers { Log.d(Constants.TAG, "download aborted - can't create base directory " + base.getPath()); } - return new DownloadFileInfo(null, null, Downloads.Impl.STATUS_FILE_ERROR); + throw new GenerateSaveFileError(Downloads.Impl.STATUS_FILE_ERROR); } } else { // No SD card found. if (Config.LOGD) { Log.d(Constants.TAG, "download aborted - no external storage"); } - return new DownloadFileInfo(null, null, - Downloads.Impl.STATUS_DEVICE_NOT_FOUND_ERROR); + throw new GenerateSaveFileError(Downloads.Impl.STATUS_DEVICE_NOT_FOUND_ERROR); } - boolean recoveryDir = Constants.RECOVERY_DIRECTORY.equalsIgnoreCase(filename + extension); - - filename = base.getPath() + File.separator + filename; - - /* - * Generate a unique filename, create the file, return it. - */ - if (Constants.LOGVV) { - Log.v(Constants.TAG, "target file: " + filename + extension); - } - - String fullFilename = chooseUniqueFilename( - destination, filename, extension, recoveryDir); - if (fullFilename != null) { - return new DownloadFileInfo(fullFilename, new FileOutputStream(fullFilename), 0); - } else { - return new DownloadFileInfo(null, null, Downloads.Impl.STATUS_FILE_ERROR); - } + return base; } private static String chooseFilename(String url, String hint, String contentDisposition, @@ -384,7 +423,7 @@ public class Helpers { } private static String chooseUniqueFilename(int destination, String filename, - String extension, boolean recoveryDir) { + String extension, boolean recoveryDir) throws GenerateSaveFileError { String fullFilename = filename + extension; if (!new File(fullFilename).exists() && (!recoveryDir || @@ -421,7 +460,7 @@ public class Helpers { sequence += sRandom.nextInt(magnitude) + 1; } } - return null; + throw new GenerateSaveFileError(Downloads.Impl.STATUS_FILE_ERROR); } /** @@ -473,68 +512,17 @@ public class Helpers { /** * Returns whether the network is available */ - public static boolean isNetworkAvailable(Context context) { - ConnectivityManager connectivity = - (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - if (connectivity == null) { - Log.w(Constants.TAG, "couldn't get connectivity manager"); - } else { - NetworkInfo[] info = connectivity.getAllNetworkInfo(); - if (info != null) { - for (int i = 0; i < info.length; i++) { - if (info[i].getState() == NetworkInfo.State.CONNECTED) { - if (Constants.LOGVV) { - Log.v(Constants.TAG, "network is available"); - } - return true; - } - } - } - } - if (Constants.LOGVV) { - Log.v(Constants.TAG, "network is not available"); - } - return false; - } - - /** - * Returns whether the network is roaming - */ - public static boolean isNetworkRoaming(Context context) { - ConnectivityManager connectivity = - (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - if (connectivity == null) { - Log.w(Constants.TAG, "couldn't get connectivity manager"); - } else { - NetworkInfo info = connectivity.getActiveNetworkInfo(); - if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE) { - if (TelephonyManager.getDefault().isNetworkRoaming()) { - if (Constants.LOGVV) { - Log.v(Constants.TAG, "network is roaming"); - } - return true; - } else { - if (Constants.LOGVV) { - Log.v(Constants.TAG, "network is not roaming"); - } - } - } else { - if (Constants.LOGVV) { - Log.v(Constants.TAG, "not using mobile network"); - } - } - } - return false; + public static boolean isNetworkAvailable(SystemFacade system) { + return system.getActiveNetworkType() != null; } /** * Checks whether the filename looks legitimate */ public static boolean isFilenameValid(String filename) { - File dir = new File(filename).getParentFile(); - return dir.equals(Environment.getDownloadCacheDirectory()) - || dir.equals(new File(Environment.getExternalStorageDirectory() - + Constants.DEFAULT_DL_SUBDIR)); + filename = filename.replaceFirst("/+", "/"); // normalize leading slashes + return filename.startsWith(Environment.getDownloadCacheDirectory().toString()) + || filename.startsWith(Environment.getExternalStorageDirectory().toString()); } /** @@ -781,7 +769,7 @@ public class Helpers { } // anything we don't recognize - throw new IllegalArgumentException("illegal character"); + throw new IllegalArgumentException("illegal character: " + chars[mOffset]); } private static final boolean isIdentifierStart(char c) { |