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.Intent; | 12 import android.content.Intent; |
13 import android.content.pm.PackageManager; | 13 import android.content.pm.PackageManager; |
14 import android.net.Uri; | 14 import android.net.Uri; |
15 import android.os.AsyncTask; | 15 import android.os.AsyncTask; |
16 import android.os.Environment; | 16 import android.os.Environment; |
17 import android.support.v7.app.AlertDialog; | 17 import android.support.v7.app.AlertDialog; |
18 import android.text.TextUtils; | 18 import android.text.TextUtils; |
19 import android.util.Pair; | 19 import android.util.Pair; |
20 import android.view.View; | 20 import android.view.View; |
21 import android.webkit.MimeTypeMap; | 21 import android.webkit.MimeTypeMap; |
22 import android.webkit.URLUtil; | |
23 import android.widget.TextView; | 22 import android.widget.TextView; |
24 | 23 |
25 import org.chromium.base.Log; | 24 import org.chromium.base.Log; |
26 import org.chromium.base.ThreadUtils; | 25 import org.chromium.base.ThreadUtils; |
27 import org.chromium.base.VisibleForTesting; | |
28 import org.chromium.base.annotations.CalledByNative; | 26 import org.chromium.base.annotations.CalledByNative; |
29 import org.chromium.chrome.R; | 27 import org.chromium.chrome.R; |
30 import org.chromium.chrome.browser.infobar.InfoBarIdentifier; | 28 import org.chromium.chrome.browser.infobar.InfoBarIdentifier; |
31 import org.chromium.chrome.browser.infobar.SimpleConfirmInfoBarBuilder; | 29 import org.chromium.chrome.browser.infobar.SimpleConfirmInfoBarBuilder; |
32 import org.chromium.chrome.browser.tab.EmptyTabObserver; | 30 import org.chromium.chrome.browser.tab.EmptyTabObserver; |
33 import org.chromium.chrome.browser.tab.Tab; | 31 import org.chromium.chrome.browser.tab.Tab; |
34 import org.chromium.chrome.browser.tabmodel.TabModelSelector; | 32 import org.chromium.chrome.browser.tabmodel.TabModelSelector; |
35 import org.chromium.content.browser.ContentViewDownloadDelegate; | 33 import org.chromium.content.browser.ContentViewDownloadDelegate; |
36 import org.chromium.content.browser.DownloadController; | 34 import org.chromium.content.browser.DownloadController; |
37 import org.chromium.content.browser.DownloadInfo; | 35 import org.chromium.content.browser.DownloadInfo; |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 // If the intent is resolved to ourselves, we don't want to attempt
to load the url | 168 // If the intent is resolved to ourselves, we don't want to attempt
to load the url |
171 // only to try and download it again. | 169 // only to try and download it again. |
172 if (DownloadManagerService.openIntent(mContext, intent, false)) { | 170 if (DownloadManagerService.openIntent(mContext, intent, false)) { |
173 return; | 171 return; |
174 } | 172 } |
175 } | 173 } |
176 onDownloadStartNoStream(downloadInfo); | 174 onDownloadStartNoStream(downloadInfo); |
177 } | 175 } |
178 | 176 |
179 /** | 177 /** |
180 * Decide the file name of the final download. The file extension is derived | |
181 * from the MIME type. | |
182 * @param url The full URL to the content that should be downloaded. | |
183 * @param mimeType The MIME type of the content reported by the server. | |
184 * @param contentDisposition Content-Disposition HTTP header, if present. | |
185 * @return The best guess of the file name for the downloaded object. | |
186 */ | |
187 @VisibleForTesting | |
188 public static String fileName(String url, String mimeType, String contentDis
position) { | |
189 // URLUtil#guessFileName will prefer the MIME type extension over | |
190 // the file extension only if the latter is of a known MIME type. | |
191 // Therefore for things like "file.php" with Content-Type PDF, it will | |
192 // still generate file names like "file.php" instead of "file.pdf". | |
193 // If that's the case, rebuild the file extension from the MIME type. | |
194 String fileName = URLUtil.guessFileName(url, contentDisposition, mimeTyp
e); | |
195 int dotIndex = fileName.lastIndexOf('.'); | |
196 if (mimeType != null | |
197 && !mimeType.isEmpty() | |
198 && dotIndex > 1 // at least one char before the '.' | |
199 && dotIndex < fileName.length()) { // '.' should not be the last
char | |
200 MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton(); | |
201 | |
202 String fileRoot = fileName.substring(0, dotIndex); | |
203 String fileExtension = fileName.substring(dotIndex + 1); | |
204 String fileExtensionMimeType = | |
205 mimeTypeMap.getMimeTypeFromExtension(fileExtension); | |
206 | |
207 // If the file extension's official MIME type and {@code mimeType} | |
208 // are the same, simply use the file extension. | |
209 // If not, extension derived from {@code mimeType} is preferred. | |
210 if (mimeType.equals(fileExtensionMimeType)) { | |
211 fileName = fileRoot + "." + fileExtension; | |
212 } else { | |
213 String mimeExtension = | |
214 mimeTypeMap.getExtensionFromMimeType(mimeType); | |
215 | |
216 if (mimeExtension != null && !mimeExtension.equals(fileExtension
)) { | |
217 fileName = fileRoot + "." + mimeExtension; | |
218 } | |
219 } | |
220 } | |
221 return fileName; | |
222 } | |
223 | |
224 /** | |
225 * Notify the host application a download should be done, even if there is a | 178 * Notify the host application a download should be done, even if there is a |
226 * streaming viewer available for this type. | 179 * streaming viewer available for this type. |
227 * | 180 * |
228 * @param downloadInfo Information about the download. | 181 * @param downloadInfo Information about the download. |
229 */ | 182 */ |
230 protected void onDownloadStartNoStream(final DownloadInfo downloadInfo) { | 183 protected void onDownloadStartNoStream(final DownloadInfo downloadInfo) { |
231 final String newMimeType = remapGenericMimeType( | 184 final String fileName = downloadInfo.getFileName(); |
232 downloadInfo.getMimeType(), | 185 assert !TextUtils.isEmpty(fileName); |
233 downloadInfo.getUrl(), | 186 final String newMimeType = |
234 downloadInfo.getFileName()); | 187 remapGenericMimeType(downloadInfo.getMimeType(), downloadInfo.ge
tUrl(), fileName); |
235 final String fileName = TextUtils.isEmpty(downloadInfo.getFileName()) | |
236 ? fileName(downloadInfo.getUrl(), newMimeType, downloadInfo.getC
ontentDisposition()) | |
237 : downloadInfo.getFileName(); | |
238 new AsyncTask<Void, Void, Object[]>() { | 188 new AsyncTask<Void, Void, Object[]>() { |
239 @Override | 189 @Override |
240 protected Object[] doInBackground(Void... params) { | 190 protected Object[] doInBackground(Void... params) { |
241 // Check to see if we have an SDCard. | 191 // Check to see if we have an SDCard. |
242 String status = Environment.getExternalStorageState(); | 192 String status = Environment.getExternalStorageState(); |
243 Pair<String, String> result = getDownloadDirectoryNameAndFullPat
h(); | 193 Pair<String, String> result = getDownloadDirectoryNameAndFullPat
h(); |
244 String dirName = result.first; | 194 String dirName = result.first; |
245 String fullDirPath = result.second; | 195 String fullDirPath = result.second; |
246 boolean fileExists = doesFileAlreadyExists(fullDirPath, fileName
); | 196 boolean fileExists = doesFileAlreadyExists(fullDirPath, fileName
); |
247 | 197 |
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
679 private static native String nativeGetDownloadWarningText(String filename); | 629 private static native String nativeGetDownloadWarningText(String filename); |
680 private static native boolean nativeIsDownloadDangerous(String filename); | 630 private static native boolean nativeIsDownloadDangerous(String filename); |
681 private static native void nativeDangerousDownloadValidated( | 631 private static native void nativeDangerousDownloadValidated( |
682 Object tab, int downloadId, boolean accept); | 632 Object tab, int downloadId, boolean accept); |
683 private static native void nativeLaunchDownloadOverwriteInfoBar(ChromeDownlo
adDelegate delegate, | 633 private static native void nativeLaunchDownloadOverwriteInfoBar(ChromeDownlo
adDelegate delegate, |
684 Tab tab, DownloadInfo downloadInfo, String fileName, String dirName, | 634 Tab tab, DownloadInfo downloadInfo, String fileName, String dirName, |
685 String dirFullPath); | 635 String dirFullPath); |
686 private static native void nativeLaunchPermissionUpdateInfoBar( | 636 private static native void nativeLaunchPermissionUpdateInfoBar( |
687 Tab tab, String permission, long callbackId); | 637 Tab tab, String permission, long callbackId); |
688 } | 638 } |
OLD | NEW |