Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java

Issue 1717783002: Fix an issue that download filename from content disposition is not sanitized (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: pass localized default download file name Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698