OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // Download utility implementation | 5 // Download utility implementation |
6 | 6 |
7 #include "chrome/browser/download/download_util.h" | 7 #include "chrome/browser/download/download_util.h" |
8 | 8 |
9 #if defined(OS_WIN) | 9 #if defined(OS_WIN) |
10 #include <shobjidl.h> | 10 #include <shobjidl.h> |
11 #endif | 11 #endif |
12 #include <string> | 12 #include <string> |
13 | 13 |
14 #include "base/file_util.h" | 14 #include "base/file_util.h" |
15 #include "base/i18n/rtl.h" | 15 #include "base/i18n/rtl.h" |
16 #include "base/i18n/time_formatting.h" | 16 #include "base/i18n/time_formatting.h" |
17 #include "base/lazy_instance.h" | 17 #include "base/lazy_instance.h" |
18 #include "base/metrics/histogram.h" | |
19 #include "base/path_service.h" | 18 #include "base/path_service.h" |
20 #include "base/string16.h" | 19 #include "base/string16.h" |
21 #include "base/string_number_conversions.h" | 20 #include "base/string_number_conversions.h" |
22 #include "base/stringprintf.h" | 21 #include "base/stringprintf.h" |
23 #include "base/sys_string_conversions.h" | 22 #include "base/sys_string_conversions.h" |
24 #include "base/threading/thread_restrictions.h" | 23 #include "base/threading/thread_restrictions.h" |
25 #include "base/utf_string_conversions.h" | 24 #include "base/utf_string_conversions.h" |
26 #include "base/value_conversions.h" | 25 #include "base/value_conversions.h" |
27 #include "base/values.h" | 26 #include "base/values.h" |
28 #include "base/win/windows_version.h" | 27 #include "base/win/windows_version.h" |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 const std::string& mime_type, | 105 const std::string& mime_type, |
107 FilePath* generated_name) { | 106 FilePath* generated_name) { |
108 string16 default_file_name( | 107 string16 default_file_name( |
109 l10n_util::GetStringUTF16(IDS_DEFAULT_DOWNLOAD_FILENAME)); | 108 l10n_util::GetStringUTF16(IDS_DEFAULT_DOWNLOAD_FILENAME)); |
110 | 109 |
111 *generated_name = net::GenerateFileName(url, content_disposition, | 110 *generated_name = net::GenerateFileName(url, content_disposition, |
112 referrer_charset, suggested_name, | 111 referrer_charset, suggested_name, |
113 mime_type, default_file_name); | 112 mime_type, default_file_name); |
114 } | 113 } |
115 | 114 |
116 // All possible error codes from the network module. Note that the error codes | |
117 // are all positive (since histograms expect positive sample values). | |
118 const int kAllNetErrorCodes[] = { | |
119 #define NET_ERROR(label, value) -(value), | |
120 #include "net/base/net_error_list.h" | |
121 #undef NET_ERROR | |
122 }; | |
123 | |
124 } // namespace | 115 } // namespace |
125 | 116 |
126 // Download temporary file creation -------------------------------------------- | 117 // Download temporary file creation -------------------------------------------- |
127 | 118 |
128 class DefaultDownloadDirectory { | 119 class DefaultDownloadDirectory { |
129 public: | 120 public: |
130 const FilePath& path() const { return path_; } | 121 const FilePath& path() const { return path_; } |
131 private: | 122 private: |
132 DefaultDownloadDirectory() { | 123 DefaultDownloadDirectory() { |
133 if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &path_)) { | 124 if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &path_)) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 | 169 |
179 void GenerateFileNameFromSuggestedName(const GURL& url, | 170 void GenerateFileNameFromSuggestedName(const GURL& url, |
180 const std::string& suggested_name, | 171 const std::string& suggested_name, |
181 const std::string& mime_type, | 172 const std::string& mime_type, |
182 FilePath* generated_name) { | 173 FilePath* generated_name) { |
183 // TODO(asanka): We should pass in a valid referrer_charset here. | 174 // TODO(asanka): We should pass in a valid referrer_charset here. |
184 GenerateFileNameInternal(url, std::string(), std::string(), | 175 GenerateFileNameInternal(url, std::string(), std::string(), |
185 suggested_name, mime_type, generated_name); | 176 suggested_name, mime_type, generated_name); |
186 } | 177 } |
187 | 178 |
188 void RecordDownloadCount(DownloadCountTypes type) { | |
189 UMA_HISTOGRAM_ENUMERATION( | |
190 "Download.Counts", type, DOWNLOAD_COUNT_TYPES_LAST_ENTRY); | |
191 } | |
192 | |
193 void RecordDownloadCompleted(const base::TimeTicks& start) { | |
194 download_util::RecordDownloadCount(download_util::COMPLETED_COUNT); | |
195 UMA_HISTOGRAM_LONG_TIMES("Download.Time", (base::TimeTicks::Now() - start)); | |
196 } | |
197 | |
198 void RecordDownloadInterrupted(int error, int64 received, int64 total) { | |
199 download_util::RecordDownloadCount(download_util::INTERRUPTED_COUNT); | |
200 UMA_HISTOGRAM_CUSTOM_ENUMERATION( | |
201 "Download.InterruptedError", | |
202 -error, | |
203 base::CustomHistogram::ArrayToCustomRanges( | |
204 kAllNetErrorCodes, arraysize(kAllNetErrorCodes))); | |
205 | |
206 // The maximum should be 2^kBuckets, to have the logarithmic bucket | |
207 // boundaries fall on powers of 2. | |
208 static const int kBuckets = 30; | |
209 static const int64 kMaxKb = 1 << kBuckets; // One Terabyte, in Kilobytes. | |
210 int64 delta_bytes = total - received; | |
211 bool unknown_size = total <= 0; | |
212 int64 received_kb = received / 1024; | |
213 int64 total_kb = total / 1024; | |
214 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedReceivedSizeK", | |
215 received_kb, | |
216 1, | |
217 kMaxKb, | |
218 kBuckets); | |
219 if (!unknown_size) { | |
220 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedTotalSizeK", | |
221 total_kb, | |
222 1, | |
223 kMaxKb, | |
224 kBuckets); | |
225 if (delta_bytes >= 0) { | |
226 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedOverrunBytes", | |
227 delta_bytes, | |
228 1, | |
229 kMaxKb, | |
230 kBuckets); | |
231 } else { | |
232 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedUnderrunBytes", | |
233 -delta_bytes, | |
234 1, | |
235 kMaxKb, | |
236 kBuckets); | |
237 } | |
238 } | |
239 | |
240 UMA_HISTOGRAM_BOOLEAN("Download.InterruptedUnknownSize", unknown_size); | |
241 } | |
242 | |
243 namespace { | |
244 | |
245 enum DownloadContent { | |
246 DOWNLOAD_CONTENT_UNRECOGNIZED = 0, | |
247 DOWNLOAD_CONTENT_TEXT = 1, | |
248 DOWNLOAD_CONTENT_IMAGE = 2, | |
249 DOWNLOAD_CONTENT_AUDIO = 3, | |
250 DOWNLOAD_CONTENT_VIDEO = 4, | |
251 DOWNLOAD_CONTENT_OCTET_STREAM = 5, | |
252 DOWNLOAD_CONTENT_PDF = 6, | |
253 DOWNLOAD_CONTENT_DOC = 7, | |
254 DOWNLOAD_CONTENT_XLS = 8, | |
255 DOWNLOAD_CONTENT_PPT = 9, | |
256 DOWNLOAD_CONTENT_ARCHIVE = 10, | |
257 DOWNLOAD_CONTENT_EXE = 11, | |
258 DOWNLOAD_CONTENT_DMG = 12, | |
259 DOWNLOAD_CONTENT_CRX = 13, | |
260 DOWNLOAD_CONTENT_MAX = 14, | |
261 }; | |
262 | |
263 struct MimeTypeToDownloadContent { | |
264 const char* mime_type; | |
265 DownloadContent download_content; | |
266 }; | |
267 | |
268 static MimeTypeToDownloadContent kMapMimeTypeToDownloadContent[] = { | |
269 {"application/octet-stream", DOWNLOAD_CONTENT_OCTET_STREAM}, | |
270 {"binary/octet-stream", DOWNLOAD_CONTENT_OCTET_STREAM}, | |
271 {"application/pdf", DOWNLOAD_CONTENT_PDF}, | |
272 {"application/msword", DOWNLOAD_CONTENT_DOC}, | |
273 {"application/vnd.ms-excel", DOWNLOAD_CONTENT_XLS}, | |
274 {"application/vns.ms-powerpoint", DOWNLOAD_CONTENT_PPT}, | |
275 {"application/zip", DOWNLOAD_CONTENT_ARCHIVE}, | |
276 {"application/x-gzip", DOWNLOAD_CONTENT_ARCHIVE}, | |
277 {"application/x-rar-compressed", DOWNLOAD_CONTENT_ARCHIVE}, | |
278 {"application/x-tar", DOWNLOAD_CONTENT_ARCHIVE}, | |
279 {"application/x-bzip", DOWNLOAD_CONTENT_ARCHIVE}, | |
280 {"application/x-exe", DOWNLOAD_CONTENT_EXE}, | |
281 {"application/x-apple-diskimage", DOWNLOAD_CONTENT_DMG}, | |
282 {"application/x-chrome-extension", DOWNLOAD_CONTENT_CRX}, | |
283 }; | |
284 | |
285 } // namespace | |
286 | |
287 void RecordDownloadMimeType(const std::string& mime_type_string) { | |
288 DownloadContent download_content = DOWNLOAD_CONTENT_UNRECOGNIZED; | |
289 | |
290 // Look up exact matches. | |
291 for (size_t i = 0; i < arraysize(kMapMimeTypeToDownloadContent); ++i) { | |
292 const MimeTypeToDownloadContent& entry = | |
293 kMapMimeTypeToDownloadContent[i]; | |
294 if (mime_type_string == entry.mime_type) { | |
295 download_content = entry.download_content; | |
296 break; | |
297 } | |
298 } | |
299 | |
300 // Do partial matches. | |
301 if (download_content == DOWNLOAD_CONTENT_UNRECOGNIZED) { | |
302 if (StartsWithASCII(mime_type_string, "text/", true)) { | |
303 download_content = DOWNLOAD_CONTENT_TEXT; | |
304 } else if (StartsWithASCII(mime_type_string, "image/", true)) { | |
305 download_content = DOWNLOAD_CONTENT_IMAGE; | |
306 } else if (StartsWithASCII(mime_type_string, "audio/", true)) { | |
307 download_content = DOWNLOAD_CONTENT_AUDIO; | |
308 } else if (StartsWithASCII(mime_type_string, "video/", true)) { | |
309 download_content = DOWNLOAD_CONTENT_VIDEO; | |
310 } | |
311 } | |
312 | |
313 // Record the value. | |
314 UMA_HISTOGRAM_ENUMERATION("Download.ContentType", | |
315 download_content, | |
316 DOWNLOAD_CONTENT_MAX); | |
317 } | |
318 | |
319 // Download progress painting -------------------------------------------------- | 179 // Download progress painting -------------------------------------------------- |
320 | 180 |
321 // Common bitmaps used for download progress animations. We load them once the | 181 // Common bitmaps used for download progress animations. We load them once the |
322 // first time we do a progress paint, then reuse them as they are always the | 182 // first time we do a progress paint, then reuse them as they are always the |
323 // same. | 183 // same. |
324 SkBitmap* g_foreground_16 = NULL; | 184 SkBitmap* g_foreground_16 = NULL; |
325 SkBitmap* g_background_16 = NULL; | 185 SkBitmap* g_background_16 = NULL; |
326 SkBitmap* g_foreground_32 = NULL; | 186 SkBitmap* g_foreground_32 = NULL; |
327 SkBitmap* g_background_32 = NULL; | 187 SkBitmap* g_background_32 = NULL; |
328 | 188 |
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
772 | 632 |
773 rdh->BeginDownload(url, | 633 rdh->BeginDownload(url, |
774 referrer, | 634 referrer, |
775 save_info, | 635 save_info, |
776 true, // Show "Save as" UI. | 636 true, // Show "Save as" UI. |
777 render_process_host_id, | 637 render_process_host_id, |
778 render_view_id, | 638 render_view_id, |
779 *context); | 639 *context); |
780 } | 640 } |
781 | 641 |
782 void NotifyDownloadInitiated(int render_process_id, int render_view_id) { | |
783 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
784 RenderViewHost* rvh = RenderViewHost::FromID(render_process_id, | |
785 render_view_id); | |
786 if (!rvh) | |
787 return; | |
788 | |
789 NotificationService::current()->Notify( | |
790 chrome::NOTIFICATION_DOWNLOAD_INITIATED, Source<RenderViewHost>(rvh), | |
791 NotificationService::NoDetails()); | |
792 } | |
793 | |
794 int GetUniquePathNumberWithCrDownload(const FilePath& path) { | 642 int GetUniquePathNumberWithCrDownload(const FilePath& path) { |
795 if (!file_util::PathExists(path) && | 643 if (!file_util::PathExists(path) && |
796 !file_util::PathExists(GetCrDownloadPath(path))) | 644 !file_util::PathExists(GetCrDownloadPath(path))) |
797 return 0; | 645 return 0; |
798 | 646 |
799 FilePath new_path; | 647 FilePath new_path; |
800 for (int count = 1; count <= kMaxUniqueFiles; ++count) { | 648 for (int count = 1; count <= kMaxUniqueFiles; ++count) { |
801 new_path = FilePath(path); | 649 new_path = FilePath(path); |
802 AppendNumberToPath(&new_path, count); | 650 AppendNumberToPath(&new_path, count); |
803 | 651 |
804 if (!file_util::PathExists(new_path) && | 652 if (!file_util::PathExists(new_path) && |
805 !file_util::PathExists(GetCrDownloadPath(new_path))) | 653 !file_util::PathExists(GetCrDownloadPath(new_path))) |
806 return count; | 654 return count; |
807 } | 655 } |
808 | 656 |
809 return -1; | 657 return -1; |
810 } | 658 } |
811 | 659 |
812 FilePath GetCrDownloadPath(const FilePath& suggested_path) { | 660 FilePath GetCrDownloadPath(const FilePath& suggested_path) { |
813 FilePath::StringType file_name; | 661 FilePath::StringType file_name; |
814 base::SStringPrintf( | 662 base::SStringPrintf( |
815 &file_name, | 663 &file_name, |
816 PRFilePathLiteral FILE_PATH_LITERAL(".crdownload"), | 664 PRFilePathLiteral FILE_PATH_LITERAL(".crdownload"), |
817 suggested_path.value().c_str()); | 665 suggested_path.value().c_str()); |
818 return FilePath(file_name); | 666 return FilePath(file_name); |
819 } | 667 } |
820 | 668 |
821 } // namespace download_util | 669 } // namespace download_util |
OLD | NEW |