summaryrefslogtreecommitdiffstats
path: root/src/com/android/providers/downloads/Helpers.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/providers/downloads/Helpers.java')
-rw-r--r--src/com/android/providers/downloads/Helpers.java214
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) {