| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser.download; | 5 package org.chromium.chrome.browser.download; |
| 6 | 6 |
| 7 import android.Manifest.permission; | 7 import android.Manifest.permission; |
| 8 import android.app.Activity; | 8 import android.app.Activity; |
| 9 import android.app.DownloadManager; | 9 import android.app.DownloadManager; |
| 10 import android.content.Context; | 10 import android.content.Context; |
| 11 import android.content.DialogInterface; | 11 import android.content.DialogInterface; |
| 12 import android.content.pm.PackageManager; | 12 import android.content.pm.PackageManager; |
| 13 import android.net.Uri; | 13 import android.net.Uri; |
| 14 import android.os.AsyncTask; | 14 import android.os.AsyncTask; |
| 15 import android.os.Environment; | 15 import android.os.Environment; |
| 16 import android.support.v7.app.AlertDialog; | 16 import android.support.v7.app.AlertDialog; |
| 17 import android.text.TextUtils; | 17 import android.text.TextUtils; |
| 18 import android.util.Pair; | |
| 19 import android.view.View; | 18 import android.view.View; |
| 20 import android.webkit.MimeTypeMap; | 19 import android.webkit.MimeTypeMap; |
| 21 import android.webkit.URLUtil; | 20 import android.webkit.URLUtil; |
| 22 import android.widget.TextView; | 21 import android.widget.TextView; |
| 23 | 22 |
| 24 import org.chromium.base.Log; | 23 import org.chromium.base.Log; |
| 25 import org.chromium.base.ThreadUtils; | 24 import org.chromium.base.ThreadUtils; |
| 26 import org.chromium.base.annotations.CalledByNative; | 25 import org.chromium.base.annotations.CalledByNative; |
| 27 import org.chromium.chrome.R; | 26 import org.chromium.chrome.R; |
| 28 import org.chromium.chrome.browser.ChromeActivity; | 27 import org.chromium.chrome.browser.ChromeActivity; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 protected void onDownloadStartNoStream(final DownloadInfo downloadInfo) { | 77 protected void onDownloadStartNoStream(final DownloadInfo downloadInfo) { |
| 79 final String fileName = downloadInfo.getFileName(); | 78 final String fileName = downloadInfo.getFileName(); |
| 80 assert !TextUtils.isEmpty(fileName); | 79 assert !TextUtils.isEmpty(fileName); |
| 81 final String newMimeType = | 80 final String newMimeType = |
| 82 remapGenericMimeType(downloadInfo.getMimeType(), downloadInfo.ge
tUrl(), fileName); | 81 remapGenericMimeType(downloadInfo.getMimeType(), downloadInfo.ge
tUrl(), fileName); |
| 83 new AsyncTask<Void, Void, Object[]>() { | 82 new AsyncTask<Void, Void, Object[]>() { |
| 84 @Override | 83 @Override |
| 85 protected Object[] doInBackground(Void... params) { | 84 protected Object[] doInBackground(Void... params) { |
| 86 // Check to see if we have an SDCard. | 85 // Check to see if we have an SDCard. |
| 87 String status = Environment.getExternalStorageState(); | 86 String status = Environment.getExternalStorageState(); |
| 88 Pair<String, String> result = getDownloadDirectoryNameAndFullPat
h(); | 87 File fullDirPath = getDownloadDirectoryFullPath(); |
| 89 String dirName = result.first; | 88 boolean fileExists = checkFileExists(fullDirPath, fileName); |
| 90 String fullDirPath = result.second; | |
| 91 boolean fileExists = doesFileAlreadyExists(fullDirPath, fileName
); | |
| 92 | 89 |
| 93 return new Object[] {status, dirName, fullDirPath, fileExists}; | 90 return new Object[] {status, fullDirPath, fileExists}; |
| 94 } | 91 } |
| 95 | 92 |
| 96 @Override | 93 @Override |
| 97 protected void onPostExecute(Object[] result) { | 94 protected void onPostExecute(Object[] result) { |
| 98 String externalStorageState = (String) result[0]; | 95 String externalStorageState = (String) result[0]; |
| 99 String dirName = (String) result[1]; | 96 File fullDirPath = (File) result[1]; |
| 100 String fullDirPath = (String) result[2]; | 97 Boolean fileExists = (Boolean) result[2]; |
| 101 Boolean fileExists = (Boolean) result[3]; | |
| 102 if (!checkExternalStorageAndNotify( | 98 if (!checkExternalStorageAndNotify( |
| 103 fileName, fullDirPath, externalStorageState)) { | 99 fileName, fullDirPath, externalStorageState)) { |
| 104 return; | 100 return; |
| 105 } | 101 } |
| 106 String url = sanitizeDownloadUrl(downloadInfo); | 102 String url = sanitizeDownloadUrl(downloadInfo); |
| 107 if (url == null) return; | 103 if (url == null) return; |
| 108 DownloadInfo newInfo = DownloadInfo.Builder.fromDownloadInfo(dow
nloadInfo) | 104 DownloadInfo newInfo = DownloadInfo.Builder.fromDownloadInfo(dow
nloadInfo) |
| 109 .setUrl(url) | 105 .setUrl(url) |
| 110 .setMimeType(newMimeType) | 106 .setMimeType(newMimeType) |
| 111 .setDescription(url) | 107 .setDescription(url) |
| 112 .setFileName(fileName) | 108 .setFileName(fileName) |
| 113 .setIsGETRequest(true) | 109 .setIsGETRequest(true) |
| 114 .build(); | 110 .build(); |
| 115 | 111 |
| 116 // TODO(acleung): This is a temp fix to disable auto downloading
if flash files. | 112 // TODO(acleung): This is a temp fix to disable auto downloading
if flash files. |
| 117 // We want to avoid downloading flash files when it is linked as
an iframe. | 113 // We want to avoid downloading flash files when it is linked as
an iframe. |
| 118 // The proper fix would be to let chrome knows which frame origi
nated the request. | 114 // The proper fix would be to let chrome knows which frame origi
nated the request. |
| 119 if ("application/x-shockwave-flash".equals(newInfo.getMimeType()
)) return; | 115 if ("application/x-shockwave-flash".equals(newInfo.getMimeType()
)) return; |
| 120 | 116 |
| 121 // Not a dangerous file, proceed. | 117 // Not a dangerous file, proceed. |
| 122 if (fileExists) { | 118 if (fileExists) { |
| 123 launchDownloadInfoBar(newInfo, dirName, fullDirPath); | 119 launchDownloadInfoBar(newInfo, fullDirPath); |
| 124 } else { | 120 } else { |
| 125 enqueueDownloadManagerRequest(newInfo); | 121 enqueueDownloadManagerRequest(newInfo); |
| 126 } | 122 } |
| 127 } | 123 } |
| 128 }.execute(); | 124 }.execute(); |
| 129 } | 125 } |
| 130 | 126 |
| 131 /** | 127 /** |
| 132 * Sanitize the URL for the download item. | 128 * Sanitize the URL for the download item. |
| 133 * | 129 * |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 builder.create().show(); | 185 builder.create().show(); |
| 190 } else if (!mTab.getWindowAndroid().isPermissionRevokedByPolicy(storageP
ermission)) { | 186 } else if (!mTab.getWindowAndroid().isPermissionRevokedByPolicy(storageP
ermission)) { |
| 191 nativeLaunchPermissionUpdateInfoBar(mTab, storagePermission, callbac
kId); | 187 nativeLaunchPermissionUpdateInfoBar(mTab, storagePermission, callbac
kId); |
| 192 } else { | 188 } else { |
| 193 // TODO(tedchoc): Show toast. | 189 // TODO(tedchoc): Show toast. |
| 194 DownloadController.getInstance().onRequestFileAccessResult(callbackI
d, false); | 190 DownloadController.getInstance().onRequestFileAccessResult(callbackI
d, false); |
| 195 } | 191 } |
| 196 } | 192 } |
| 197 | 193 |
| 198 /** | 194 /** |
| 199 * Return a pair of directory name and its full path. Note that we create th
e directory if | 195 * Return the full path of the download directory. |
| 200 * it does not already exist. | |
| 201 * | 196 * |
| 202 * @return A pair of directory name and its full path. A pair of <null, null
> will be returned | 197 * @return File object containing the path to the download directory. |
| 203 * in case of an error. | |
| 204 */ | 198 */ |
| 205 private static Pair<String, String> getDownloadDirectoryNameAndFullPath() { | 199 private static File getDownloadDirectoryFullPath() { |
| 206 assert !ThreadUtils.runningOnUiThread(); | 200 assert !ThreadUtils.runningOnUiThread(); |
| 207 File dir = Environment.getExternalStoragePublicDirectory(Environment.DIR
ECTORY_DOWNLOADS); | 201 File dir = Environment.getExternalStoragePublicDirectory(Environment.DIR
ECTORY_DOWNLOADS); |
| 208 if (!dir.mkdir() && !dir.isDirectory()) return new Pair<>(null, null); | 202 if (!dir.mkdir() && !dir.isDirectory()) return null; |
| 209 String dirName = dir.getName(); | 203 return dir; |
| 210 String fullDirPath = dir.getPath(); | |
| 211 return new Pair<>(dirName, fullDirPath); | |
| 212 } | 204 } |
| 213 | 205 |
| 214 private static boolean doesFileAlreadyExists(String dirPath, final String fi
leName) { | 206 private static boolean checkFileExists(File dirPath, final String fileName)
{ |
| 215 assert !ThreadUtils.runningOnUiThread(); | 207 assert !ThreadUtils.runningOnUiThread(); |
| 216 final File file = new File(dirPath, fileName); | 208 final File file = new File(dirPath, fileName); |
| 217 return file != null && file.exists(); | 209 return file != null && file.exists(); |
| 218 } | 210 } |
| 219 | 211 |
| 220 private static void deleteFileForOverwrite(DownloadInfo info) { | 212 private static void deleteFileForOverwrite(DownloadInfo info) { |
| 221 assert !ThreadUtils.runningOnUiThread(); | 213 assert !ThreadUtils.runningOnUiThread(); |
| 222 File dir = Environment.getExternalStoragePublicDirectory(Environment.DIR
ECTORY_DOWNLOADS); | 214 File dir = Environment.getExternalStoragePublicDirectory(Environment.DIR
ECTORY_DOWNLOADS); |
| 223 if (!dir.isDirectory()) return; | 215 if (!dir.isDirectory()) return; |
| 224 final File file = new File(dir, info.getFileName()); | 216 final File file = new File(dir, info.getFileName()); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 252 public void onPostExecute(Void args) { | 244 public void onPostExecute(Void args) { |
| 253 enqueueDownloadManagerRequest(downloadInfo); | 245 enqueueDownloadManagerRequest(downloadInfo); |
| 254 } | 246 } |
| 255 }.execute(); | 247 }.execute(); |
| 256 } else { | 248 } else { |
| 257 enqueueDownloadManagerRequest(downloadInfo); | 249 enqueueDownloadManagerRequest(downloadInfo); |
| 258 } | 250 } |
| 259 return closeBlankTab(); | 251 return closeBlankTab(); |
| 260 } | 252 } |
| 261 | 253 |
| 262 private void launchDownloadInfoBar(DownloadInfo info, String dirName, String
fullDirPath) { | 254 private void launchDownloadInfoBar(DownloadInfo info, File fullDirPath) { |
| 263 if (mTab == null) return; | 255 if (mTab == null) return; |
| 264 nativeLaunchDownloadOverwriteInfoBar( | 256 nativeLaunchDuplicateDownloadInfoBar(ChromeDownloadDelegate.this, mTab,
info, |
| 265 ChromeDownloadDelegate.this, mTab, info, info.getFileName(), dir
Name, fullDirPath); | 257 new File(fullDirPath, info.getFileName()).toString(), mTab.isInc
ognito()); |
| 266 } | 258 } |
| 267 | 259 |
| 268 /** | 260 /** |
| 269 * Enqueue a request to download a file using Android DownloadManager. | 261 * Enqueue a request to download a file using Android DownloadManager. |
| 270 * | 262 * |
| 271 * @param info Download information about the download. | 263 * @param info Download information about the download. |
| 272 */ | 264 */ |
| 273 private void enqueueDownloadManagerRequest(final DownloadInfo info) { | 265 private void enqueueDownloadManagerRequest(final DownloadInfo info) { |
| 274 DownloadManagerService.getDownloadManagerService( | 266 DownloadManagerService.getDownloadManagerService( |
| 275 mContext.getApplicationContext()).enqueueDownloadManagerRequest( | 267 mContext.getApplicationContext()).enqueueDownloadManagerRequest( |
| 276 new DownloadItem(true, info), true); | 268 new DownloadItem(true, info), true); |
| 277 closeBlankTab(); | 269 closeBlankTab(); |
| 278 } | 270 } |
| 279 | 271 |
| 280 /** | 272 /** |
| 281 * Check the external storage and notify user on error. | 273 * Check the external storage and notify user on error. |
| 282 * | 274 * |
| 283 * @param fullDirPath The dir path to download a file. Normally this is exte
rnal storage. | 275 * @param fullDirPath The dir path to download a file. Normally this is exte
rnal storage. |
| 284 * @param externalStorageStatus The status of the external storage. | 276 * @param externalStorageStatus The status of the external storage. |
| 285 * @return Whether external storage is ok for downloading. | 277 * @return Whether external storage is ok for downloading. |
| 286 */ | 278 */ |
| 287 private boolean checkExternalStorageAndNotify( | 279 private boolean checkExternalStorageAndNotify( |
| 288 String filename, String fullDirPath, String externalStorageStatus) { | 280 String filename, File fullDirPath, String externalStorageStatus) { |
| 289 if (fullDirPath == null) { | 281 if (fullDirPath == null) { |
| 290 Log.e(TAG, "Download failed: no SD card"); | 282 Log.e(TAG, "Download failed: no SD card"); |
| 291 alertDownloadFailure( | 283 alertDownloadFailure( |
| 292 filename, DownloadManager.ERROR_DEVICE_NOT_FOUND); | 284 filename, DownloadManager.ERROR_DEVICE_NOT_FOUND); |
| 293 return false; | 285 return false; |
| 294 } | 286 } |
| 295 if (!externalStorageStatus.equals(Environment.MEDIA_MOUNTED)) { | 287 if (!externalStorageStatus.equals(Environment.MEDIA_MOUNTED)) { |
| 296 int reason = DownloadManager.ERROR_DEVICE_NOT_FOUND; | 288 int reason = DownloadManager.ERROR_DEVICE_NOT_FOUND; |
| 297 // Check to see if the SDCard is busy, same as the music app | 289 // Check to see if the SDCard is busy, same as the music app |
| 298 if (externalStorageStatus.equals(Environment.MEDIA_SHARED)) { | 290 if (externalStorageStatus.equals(Environment.MEDIA_SHARED)) { |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 return true; | 469 return true; |
| 478 } | 470 } |
| 479 | 471 |
| 480 protected Context getContext() { | 472 protected Context getContext() { |
| 481 return mContext; | 473 return mContext; |
| 482 } | 474 } |
| 483 | 475 |
| 484 private native void nativeInit(WebContents webContents); | 476 private native void nativeInit(WebContents webContents); |
| 485 private static native String nativeGetDownloadWarningText(String filename); | 477 private static native String nativeGetDownloadWarningText(String filename); |
| 486 private static native boolean nativeIsDownloadDangerous(String filename); | 478 private static native boolean nativeIsDownloadDangerous(String filename); |
| 487 private static native void nativeLaunchDownloadOverwriteInfoBar(ChromeDownlo
adDelegate delegate, | 479 private static native void nativeLaunchDuplicateDownloadInfoBar(ChromeDownlo
adDelegate delegate, |
| 488 Tab tab, DownloadInfo downloadInfo, String fileName, String dirName, | 480 Tab tab, DownloadInfo downloadInfo, String filePath, boolean isIncog
nito); |
| 489 String dirFullPath); | |
| 490 private static native void nativeLaunchPermissionUpdateInfoBar( | 481 private static native void nativeLaunchPermissionUpdateInfoBar( |
| 491 Tab tab, String permission, long callbackId); | 482 Tab tab, String permission, long callbackId); |
| 492 } | 483 } |
| OLD | NEW |