Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / content / browser / download / download_stats.cc
blob45772ede2c3e5d119e0a2327bc68d890efc15f29
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/download/download_stats.h"
7 #include "base/metrics/histogram.h"
8 #include "base/metrics/sparse_histogram.h"
9 #include "base/strings/string_util.h"
10 #include "content/browser/download/download_resource_handler.h"
11 #include "content/public/browser/download_interrupt_reasons.h"
12 #include "net/http/http_content_disposition.h"
14 namespace content {
16 namespace {
18 // All possible error codes from the network module. Note that the error codes
19 // are all positive (since histograms expect positive sample values).
20 const int kAllInterruptReasonCodes[] = {
21 #define INTERRUPT_REASON(label, value) (value),
22 #include "content/public/browser/download_interrupt_reason_values.h"
23 #undef INTERRUPT_REASON
26 // These values are based on net::HttpContentDisposition::ParseResult values.
27 // Values other than HEADER_PRESENT and IS_VALID are only measured if |IS_VALID|
28 // is true.
29 enum ContentDispositionCountTypes {
30 // Count of downloads which had a Content-Disposition headers. The total
31 // number of downloads is measured by UNTHROTTLED_COUNT.
32 CONTENT_DISPOSITION_HEADER_PRESENT = 0,
34 // Either 'filename' or 'filename*' attributes were valid and
35 // yielded a non-empty filename.
36 CONTENT_DISPOSITION_IS_VALID,
38 // The following enum values correspond to
39 // net::HttpContentDisposition::ParseResult.
40 CONTENT_DISPOSITION_HAS_DISPOSITION_TYPE,
41 CONTENT_DISPOSITION_HAS_UNKNOWN_TYPE,
43 CONTENT_DISPOSITION_HAS_NAME, // Obsolete; kept for UMA compatiblity.
45 CONTENT_DISPOSITION_HAS_FILENAME,
46 CONTENT_DISPOSITION_HAS_EXT_FILENAME,
47 CONTENT_DISPOSITION_HAS_NON_ASCII_STRINGS,
48 CONTENT_DISPOSITION_HAS_PERCENT_ENCODED_STRINGS,
49 CONTENT_DISPOSITION_HAS_RFC2047_ENCODED_STRINGS,
51 CONTENT_DISPOSITION_HAS_NAME_ONLY, // Obsolete; kept for UMA compatiblity.
53 CONTENT_DISPOSITION_LAST_ENTRY
56 void RecordContentDispositionCount(ContentDispositionCountTypes type,
57 bool record) {
58 if (!record)
59 return;
60 UMA_HISTOGRAM_ENUMERATION(
61 "Download.ContentDisposition", type, CONTENT_DISPOSITION_LAST_ENTRY);
64 void RecordContentDispositionCountFlag(
65 ContentDispositionCountTypes type,
66 int flags_to_test,
67 net::HttpContentDisposition::ParseResultFlags flag) {
68 RecordContentDispositionCount(type, (flags_to_test & flag) == flag);
71 // Do not insert, delete, or reorder; this is being histogrammed. Append only.
72 // All of the download_extensions.cc file types should be in this list.
73 // TODO(asanka): This enum and the UMA metrics for dangerous/malicious downloads
74 // should be moved to //chrome/browser/download.
75 const base::FilePath::CharType* kDangerousFileTypes[] = {
76 FILE_PATH_LITERAL(".ad"),
77 FILE_PATH_LITERAL(".ade"),
78 FILE_PATH_LITERAL(".adp"),
79 FILE_PATH_LITERAL(".ah"),
80 FILE_PATH_LITERAL(".apk"),
81 FILE_PATH_LITERAL(".app"),
82 FILE_PATH_LITERAL(".application"),
83 FILE_PATH_LITERAL(".asp"),
84 FILE_PATH_LITERAL(".asx"),
85 FILE_PATH_LITERAL(".bas"),
86 FILE_PATH_LITERAL(".bash"),
87 FILE_PATH_LITERAL(".bat"),
88 FILE_PATH_LITERAL(".cfg"),
89 FILE_PATH_LITERAL(".chi"),
90 FILE_PATH_LITERAL(".chm"),
91 FILE_PATH_LITERAL(".class"),
92 FILE_PATH_LITERAL(".cmd"),
93 FILE_PATH_LITERAL(".com"),
94 FILE_PATH_LITERAL(".command"),
95 FILE_PATH_LITERAL(".crt"),
96 FILE_PATH_LITERAL(".crx"),
97 FILE_PATH_LITERAL(".csh"),
98 FILE_PATH_LITERAL(".deb"),
99 FILE_PATH_LITERAL(".dex"),
100 FILE_PATH_LITERAL(".dll"),
101 FILE_PATH_LITERAL(".drv"),
102 FILE_PATH_LITERAL(".exe"),
103 FILE_PATH_LITERAL(".fxp"),
104 FILE_PATH_LITERAL(".grp"),
105 FILE_PATH_LITERAL(".hlp"),
106 FILE_PATH_LITERAL(".hta"),
107 FILE_PATH_LITERAL(".htm"),
108 FILE_PATH_LITERAL(".html"),
109 FILE_PATH_LITERAL(".htt"),
110 FILE_PATH_LITERAL(".inf"),
111 FILE_PATH_LITERAL(".ini"),
112 FILE_PATH_LITERAL(".ins"),
113 FILE_PATH_LITERAL(".isp"),
114 FILE_PATH_LITERAL(".jar"),
115 FILE_PATH_LITERAL(".jnlp"),
116 FILE_PATH_LITERAL(".user.js"),
117 FILE_PATH_LITERAL(".js"),
118 FILE_PATH_LITERAL(".jse"),
119 FILE_PATH_LITERAL(".ksh"),
120 FILE_PATH_LITERAL(".lnk"),
121 FILE_PATH_LITERAL(".local"),
122 FILE_PATH_LITERAL(".mad"),
123 FILE_PATH_LITERAL(".maf"),
124 FILE_PATH_LITERAL(".mag"),
125 FILE_PATH_LITERAL(".mam"),
126 FILE_PATH_LITERAL(".manifest"),
127 FILE_PATH_LITERAL(".maq"),
128 FILE_PATH_LITERAL(".mar"),
129 FILE_PATH_LITERAL(".mas"),
130 FILE_PATH_LITERAL(".mat"),
131 FILE_PATH_LITERAL(".mau"),
132 FILE_PATH_LITERAL(".mav"),
133 FILE_PATH_LITERAL(".maw"),
134 FILE_PATH_LITERAL(".mda"),
135 FILE_PATH_LITERAL(".mdb"),
136 FILE_PATH_LITERAL(".mde"),
137 FILE_PATH_LITERAL(".mdt"),
138 FILE_PATH_LITERAL(".mdw"),
139 FILE_PATH_LITERAL(".mdz"),
140 FILE_PATH_LITERAL(".mht"),
141 FILE_PATH_LITERAL(".mhtml"),
142 FILE_PATH_LITERAL(".mmc"),
143 FILE_PATH_LITERAL(".mof"),
144 FILE_PATH_LITERAL(".msc"),
145 FILE_PATH_LITERAL(".msh"),
146 FILE_PATH_LITERAL(".mshxml"),
147 FILE_PATH_LITERAL(".msi"),
148 FILE_PATH_LITERAL(".msp"),
149 FILE_PATH_LITERAL(".mst"),
150 FILE_PATH_LITERAL(".ocx"),
151 FILE_PATH_LITERAL(".ops"),
152 FILE_PATH_LITERAL(".pcd"),
153 FILE_PATH_LITERAL(".pif"),
154 FILE_PATH_LITERAL(".pkg"),
155 FILE_PATH_LITERAL(".pl"),
156 FILE_PATH_LITERAL(".plg"),
157 FILE_PATH_LITERAL(".prf"),
158 FILE_PATH_LITERAL(".prg"),
159 FILE_PATH_LITERAL(".pst"),
160 FILE_PATH_LITERAL(".py"),
161 FILE_PATH_LITERAL(".pyc"),
162 FILE_PATH_LITERAL(".pyw"),
163 FILE_PATH_LITERAL(".rb"),
164 FILE_PATH_LITERAL(".reg"),
165 FILE_PATH_LITERAL(".rpm"),
166 FILE_PATH_LITERAL(".scf"),
167 FILE_PATH_LITERAL(".scr"),
168 FILE_PATH_LITERAL(".sct"),
169 FILE_PATH_LITERAL(".sh"),
170 FILE_PATH_LITERAL(".shar"),
171 FILE_PATH_LITERAL(".shb"),
172 FILE_PATH_LITERAL(".shs"),
173 FILE_PATH_LITERAL(".shtm"),
174 FILE_PATH_LITERAL(".shtml"),
175 FILE_PATH_LITERAL(".spl"),
176 FILE_PATH_LITERAL(".svg"),
177 FILE_PATH_LITERAL(".swf"),
178 FILE_PATH_LITERAL(".sys"),
179 FILE_PATH_LITERAL(".tcsh"),
180 FILE_PATH_LITERAL(".url"),
181 FILE_PATH_LITERAL(".vb"),
182 FILE_PATH_LITERAL(".vbe"),
183 FILE_PATH_LITERAL(".vbs"),
184 FILE_PATH_LITERAL(".vsd"),
185 FILE_PATH_LITERAL(".vsmacros"),
186 FILE_PATH_LITERAL(".vss"),
187 FILE_PATH_LITERAL(".vst"),
188 FILE_PATH_LITERAL(".vsw"),
189 FILE_PATH_LITERAL(".ws"),
190 FILE_PATH_LITERAL(".wsc"),
191 FILE_PATH_LITERAL(".wsf"),
192 FILE_PATH_LITERAL(".wsh"),
193 FILE_PATH_LITERAL(".xbap"),
194 FILE_PATH_LITERAL(".xht"),
195 FILE_PATH_LITERAL(".xhtm"),
196 FILE_PATH_LITERAL(".xhtml"),
197 FILE_PATH_LITERAL(".xml"),
198 FILE_PATH_LITERAL(".xsl"),
199 FILE_PATH_LITERAL(".xslt"),
200 FILE_PATH_LITERAL(".website"),
201 FILE_PATH_LITERAL(".msh1"),
202 FILE_PATH_LITERAL(".msh2"),
203 FILE_PATH_LITERAL(".msh1xml"),
204 FILE_PATH_LITERAL(".msh2xml"),
205 FILE_PATH_LITERAL(".ps1"),
206 FILE_PATH_LITERAL(".ps1xml"),
207 FILE_PATH_LITERAL(".ps2"),
208 FILE_PATH_LITERAL(".ps2xml"),
209 FILE_PATH_LITERAL(".psc1"),
210 FILE_PATH_LITERAL(".psc2"),
211 FILE_PATH_LITERAL(".xnk"),
212 FILE_PATH_LITERAL(".appref-ms"),
213 FILE_PATH_LITERAL(".gadget"),
214 FILE_PATH_LITERAL(".efi"),
215 FILE_PATH_LITERAL(".fon"),
218 // Maps extensions to their matching UMA histogram int value.
219 int GetDangerousFileType(const base::FilePath& file_path) {
220 for (size_t i = 0; i < arraysize(kDangerousFileTypes); ++i) {
221 if (file_path.MatchesExtension(kDangerousFileTypes[i]))
222 return i + 1;
224 return 0; // Unknown extension.
227 } // namespace
229 void RecordDownloadCount(DownloadCountTypes type) {
230 UMA_HISTOGRAM_ENUMERATION(
231 "Download.Counts", type, DOWNLOAD_COUNT_TYPES_LAST_ENTRY);
234 void RecordDownloadSource(DownloadSource source) {
235 UMA_HISTOGRAM_ENUMERATION(
236 "Download.Sources", source, DOWNLOAD_SOURCE_LAST_ENTRY);
239 void RecordDownloadCompleted(const base::TimeTicks& start, int64 download_len) {
240 RecordDownloadCount(COMPLETED_COUNT);
241 UMA_HISTOGRAM_LONG_TIMES("Download.Time", (base::TimeTicks::Now() - start));
242 int64 max = 1024 * 1024 * 1024; // One Terabyte.
243 download_len /= 1024; // In Kilobytes
244 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.DownloadSize",
245 download_len,
247 max,
248 256);
251 void RecordDownloadInterrupted(DownloadInterruptReason reason,
252 int64 received,
253 int64 total) {
254 RecordDownloadCount(INTERRUPTED_COUNT);
255 UMA_HISTOGRAM_CUSTOM_ENUMERATION(
256 "Download.InterruptedReason",
257 reason,
258 base::CustomHistogram::ArrayToCustomRanges(
259 kAllInterruptReasonCodes, arraysize(kAllInterruptReasonCodes)));
261 // The maximum should be 2^kBuckets, to have the logarithmic bucket
262 // boundaries fall on powers of 2.
263 static const int kBuckets = 30;
264 static const int64 kMaxKb = 1 << kBuckets; // One Terabyte, in Kilobytes.
265 int64 delta_bytes = total - received;
266 bool unknown_size = total <= 0;
267 int64 received_kb = received / 1024;
268 int64 total_kb = total / 1024;
269 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedReceivedSizeK",
270 received_kb,
272 kMaxKb,
273 kBuckets);
274 if (!unknown_size) {
275 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedTotalSizeK",
276 total_kb,
278 kMaxKb,
279 kBuckets);
280 if (delta_bytes == 0) {
281 RecordDownloadCount(INTERRUPTED_AT_END_COUNT);
282 UMA_HISTOGRAM_CUSTOM_ENUMERATION(
283 "Download.InterruptedAtEndReason",
284 reason,
285 base::CustomHistogram::ArrayToCustomRanges(
286 kAllInterruptReasonCodes,
287 arraysize(kAllInterruptReasonCodes)));
288 } else if (delta_bytes > 0) {
289 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedOverrunBytes",
290 delta_bytes,
292 kMaxKb,
293 kBuckets);
294 } else {
295 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedUnderrunBytes",
296 -delta_bytes,
298 kMaxKb,
299 kBuckets);
303 UMA_HISTOGRAM_BOOLEAN("Download.InterruptedUnknownSize", unknown_size);
306 void RecordMaliciousDownloadClassified(DownloadDangerType danger_type) {
307 UMA_HISTOGRAM_ENUMERATION("Download.MaliciousDownloadClassified",
308 danger_type,
309 DOWNLOAD_DANGER_TYPE_MAX);
312 void RecordDangerousDownloadAccept(DownloadDangerType danger_type,
313 const base::FilePath& file_path) {
314 UMA_HISTOGRAM_ENUMERATION("Download.DangerousDownloadValidated",
315 danger_type,
316 DOWNLOAD_DANGER_TYPE_MAX);
317 if (danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE) {
318 UMA_HISTOGRAM_SPARSE_SLOWLY(
319 "Download.DangerousFile.DangerousDownloadValidated",
320 GetDangerousFileType(file_path));
324 void RecordDangerousDownloadDiscard(DownloadDiscardReason reason,
325 DownloadDangerType danger_type,
326 const base::FilePath& file_path) {
327 switch (reason) {
328 case DOWNLOAD_DISCARD_DUE_TO_USER_ACTION:
329 UMA_HISTOGRAM_ENUMERATION(
330 "Download.UserDiscard", danger_type, DOWNLOAD_DANGER_TYPE_MAX);
331 if (danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE) {
332 UMA_HISTOGRAM_SPARSE_SLOWLY("Download.DangerousFile.UserDiscard",
333 GetDangerousFileType(file_path));
335 break;
336 case DOWNLOAD_DISCARD_DUE_TO_SHUTDOWN:
337 UMA_HISTOGRAM_ENUMERATION(
338 "Download.Discard", danger_type, DOWNLOAD_DANGER_TYPE_MAX);
339 if (danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE) {
340 UMA_HISTOGRAM_SPARSE_SLOWLY("Download.DangerousFile.Discard",
341 GetDangerousFileType(file_path));
343 break;
344 default:
345 NOTREACHED();
349 void RecordDownloadWriteSize(size_t data_len) {
350 int max = 1024 * 1024; // One Megabyte.
351 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.WriteSize", data_len, 1, max, 256);
354 void RecordDownloadWriteLoopCount(int count) {
355 UMA_HISTOGRAM_ENUMERATION("Download.WriteLoopCount", count, 20);
358 void RecordAcceptsRanges(const std::string& accepts_ranges,
359 int64 download_len,
360 bool has_strong_validator) {
361 int64 max = 1024 * 1024 * 1024; // One Terabyte.
362 download_len /= 1024; // In Kilobytes
363 static const int kBuckets = 50;
365 if (base::LowerCaseEqualsASCII(accepts_ranges, "none")) {
366 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.AcceptRangesNone.KBytes",
367 download_len,
369 max,
370 kBuckets);
371 } else if (base::LowerCaseEqualsASCII(accepts_ranges, "bytes")) {
372 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.AcceptRangesBytes.KBytes",
373 download_len,
375 max,
376 kBuckets);
377 if (has_strong_validator)
378 RecordDownloadCount(STRONG_VALIDATOR_AND_ACCEPTS_RANGES);
379 } else {
380 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.AcceptRangesMissingOrInvalid.KBytes",
381 download_len,
383 max,
384 kBuckets);
388 namespace {
390 enum DownloadContent {
391 DOWNLOAD_CONTENT_UNRECOGNIZED = 0,
392 DOWNLOAD_CONTENT_TEXT = 1,
393 DOWNLOAD_CONTENT_IMAGE = 2,
394 DOWNLOAD_CONTENT_AUDIO = 3,
395 DOWNLOAD_CONTENT_VIDEO = 4,
396 DOWNLOAD_CONTENT_OCTET_STREAM = 5,
397 DOWNLOAD_CONTENT_PDF = 6,
398 DOWNLOAD_CONTENT_DOC = 7,
399 DOWNLOAD_CONTENT_XLS = 8,
400 DOWNLOAD_CONTENT_PPT = 9,
401 DOWNLOAD_CONTENT_ARCHIVE = 10,
402 DOWNLOAD_CONTENT_EXE = 11,
403 DOWNLOAD_CONTENT_DMG = 12,
404 DOWNLOAD_CONTENT_CRX = 13,
405 DOWNLOAD_CONTENT_MAX = 14,
408 struct MimeTypeToDownloadContent {
409 const char* mime_type;
410 DownloadContent download_content;
413 static MimeTypeToDownloadContent kMapMimeTypeToDownloadContent[] = {
414 {"application/octet-stream", DOWNLOAD_CONTENT_OCTET_STREAM},
415 {"binary/octet-stream", DOWNLOAD_CONTENT_OCTET_STREAM},
416 {"application/pdf", DOWNLOAD_CONTENT_PDF},
417 {"application/msword", DOWNLOAD_CONTENT_DOC},
418 {"application/vnd.ms-excel", DOWNLOAD_CONTENT_XLS},
419 {"application/vns.ms-powerpoint", DOWNLOAD_CONTENT_PPT},
420 {"application/zip", DOWNLOAD_CONTENT_ARCHIVE},
421 {"application/x-gzip", DOWNLOAD_CONTENT_ARCHIVE},
422 {"application/x-rar-compressed", DOWNLOAD_CONTENT_ARCHIVE},
423 {"application/x-tar", DOWNLOAD_CONTENT_ARCHIVE},
424 {"application/x-bzip", DOWNLOAD_CONTENT_ARCHIVE},
425 {"application/x-exe", DOWNLOAD_CONTENT_EXE},
426 {"application/x-apple-diskimage", DOWNLOAD_CONTENT_DMG},
427 {"application/x-chrome-extension", DOWNLOAD_CONTENT_CRX},
430 enum DownloadImage {
431 DOWNLOAD_IMAGE_UNRECOGNIZED = 0,
432 DOWNLOAD_IMAGE_GIF = 1,
433 DOWNLOAD_IMAGE_JPEG = 2,
434 DOWNLOAD_IMAGE_PNG = 3,
435 DOWNLOAD_IMAGE_TIFF = 4,
436 DOWNLOAD_IMAGE_ICON = 5,
437 DOWNLOAD_IMAGE_WEBP = 6,
438 DOWNLOAD_IMAGE_MAX = 7,
441 struct MimeTypeToDownloadImage {
442 const char* mime_type;
443 DownloadImage download_image;
446 static MimeTypeToDownloadImage kMapMimeTypeToDownloadImage[] = {
447 {"image/gif", DOWNLOAD_IMAGE_GIF},
448 {"image/jpeg", DOWNLOAD_IMAGE_JPEG},
449 {"image/png", DOWNLOAD_IMAGE_PNG},
450 {"image/tiff", DOWNLOAD_IMAGE_TIFF},
451 {"image/vnd.microsoft.icon", DOWNLOAD_IMAGE_ICON},
452 {"image/webp", DOWNLOAD_IMAGE_WEBP},
455 void RecordDownloadImageType(const std::string& mime_type_string) {
456 DownloadImage download_image = DOWNLOAD_IMAGE_UNRECOGNIZED;
458 // Look up exact matches.
459 for (size_t i = 0; i < arraysize(kMapMimeTypeToDownloadImage); ++i) {
460 const MimeTypeToDownloadImage& entry = kMapMimeTypeToDownloadImage[i];
461 if (mime_type_string == entry.mime_type) {
462 download_image = entry.download_image;
463 break;
467 UMA_HISTOGRAM_ENUMERATION("Download.ContentImageType",
468 download_image,
469 DOWNLOAD_IMAGE_MAX);
472 } // namespace
474 void RecordDownloadMimeType(const std::string& mime_type_string) {
475 DownloadContent download_content = DOWNLOAD_CONTENT_UNRECOGNIZED;
477 // Look up exact matches.
478 for (size_t i = 0; i < arraysize(kMapMimeTypeToDownloadContent); ++i) {
479 const MimeTypeToDownloadContent& entry = kMapMimeTypeToDownloadContent[i];
480 if (mime_type_string == entry.mime_type) {
481 download_content = entry.download_content;
482 break;
486 // Do partial matches.
487 if (download_content == DOWNLOAD_CONTENT_UNRECOGNIZED) {
488 if (base::StartsWith(mime_type_string, "text/",
489 base::CompareCase::SENSITIVE)) {
490 download_content = DOWNLOAD_CONTENT_TEXT;
491 } else if (base::StartsWith(mime_type_string, "image/",
492 base::CompareCase::SENSITIVE)) {
493 download_content = DOWNLOAD_CONTENT_IMAGE;
494 RecordDownloadImageType(mime_type_string);
495 } else if (base::StartsWith(mime_type_string, "audio/",
496 base::CompareCase::SENSITIVE)) {
497 download_content = DOWNLOAD_CONTENT_AUDIO;
498 } else if (base::StartsWith(mime_type_string, "video/",
499 base::CompareCase::SENSITIVE)) {
500 download_content = DOWNLOAD_CONTENT_VIDEO;
504 // Record the value.
505 UMA_HISTOGRAM_ENUMERATION("Download.ContentType",
506 download_content,
507 DOWNLOAD_CONTENT_MAX);
510 void RecordDownloadContentDisposition(
511 const std::string& content_disposition_string) {
512 if (content_disposition_string.empty())
513 return;
514 net::HttpContentDisposition content_disposition(content_disposition_string,
515 std::string());
516 int result = content_disposition.parse_result_flags();
518 bool is_valid = !content_disposition.filename().empty();
519 RecordContentDispositionCount(CONTENT_DISPOSITION_HEADER_PRESENT, true);
520 RecordContentDispositionCount(CONTENT_DISPOSITION_IS_VALID, is_valid);
521 if (!is_valid)
522 return;
524 RecordContentDispositionCountFlag(
525 CONTENT_DISPOSITION_HAS_DISPOSITION_TYPE, result,
526 net::HttpContentDisposition::HAS_DISPOSITION_TYPE);
527 RecordContentDispositionCountFlag(
528 CONTENT_DISPOSITION_HAS_UNKNOWN_TYPE, result,
529 net::HttpContentDisposition::HAS_UNKNOWN_DISPOSITION_TYPE);
530 RecordContentDispositionCountFlag(
531 CONTENT_DISPOSITION_HAS_FILENAME, result,
532 net::HttpContentDisposition::HAS_FILENAME);
533 RecordContentDispositionCountFlag(
534 CONTENT_DISPOSITION_HAS_EXT_FILENAME, result,
535 net::HttpContentDisposition::HAS_EXT_FILENAME);
536 RecordContentDispositionCountFlag(
537 CONTENT_DISPOSITION_HAS_NON_ASCII_STRINGS, result,
538 net::HttpContentDisposition::HAS_NON_ASCII_STRINGS);
539 RecordContentDispositionCountFlag(
540 CONTENT_DISPOSITION_HAS_PERCENT_ENCODED_STRINGS, result,
541 net::HttpContentDisposition::HAS_PERCENT_ENCODED_STRINGS);
542 RecordContentDispositionCountFlag(
543 CONTENT_DISPOSITION_HAS_RFC2047_ENCODED_STRINGS, result,
544 net::HttpContentDisposition::HAS_RFC2047_ENCODED_STRINGS);
547 void RecordFileThreadReceiveBuffers(size_t num_buffers) {
548 UMA_HISTOGRAM_CUSTOM_COUNTS(
549 "Download.FileThreadReceiveBuffers", num_buffers, 1,
550 100, 100);
553 void RecordBandwidth(double actual_bandwidth, double potential_bandwidth) {
554 UMA_HISTOGRAM_CUSTOM_COUNTS(
555 "Download.ActualBandwidth", actual_bandwidth, 1, 1000000000, 50);
556 UMA_HISTOGRAM_CUSTOM_COUNTS(
557 "Download.PotentialBandwidth", potential_bandwidth, 1, 1000000000, 50);
558 UMA_HISTOGRAM_PERCENTAGE(
559 "Download.BandwidthUsed",
560 (int) ((actual_bandwidth * 100)/ potential_bandwidth));
563 void RecordOpen(const base::Time& end, bool first) {
564 if (!end.is_null()) {
565 UMA_HISTOGRAM_LONG_TIMES("Download.OpenTime", (base::Time::Now() - end));
566 if (first) {
567 UMA_HISTOGRAM_LONG_TIMES("Download.FirstOpenTime",
568 (base::Time::Now() - end));
573 void RecordClearAllSize(int size) {
574 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.ClearAllSize",
575 size,
576 0/*min*/,
577 (1 << 10)/*max*/,
578 32/*num_buckets*/);
581 void RecordOpensOutstanding(int size) {
582 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.OpensOutstanding",
583 size,
584 0/*min*/,
585 (1 << 10)/*max*/,
586 64/*num_buckets*/);
589 void RecordContiguousWriteTime(base::TimeDelta time_blocked) {
590 UMA_HISTOGRAM_TIMES("Download.FileThreadBlockedTime", time_blocked);
593 // Record what percentage of the time we have the network flow controlled.
594 void RecordNetworkBlockage(base::TimeDelta resource_handler_lifetime,
595 base::TimeDelta resource_handler_blocked_time) {
596 int percentage = 0;
597 // Avoid division by zero errors.
598 if (resource_handler_blocked_time != base::TimeDelta()) {
599 percentage =
600 resource_handler_blocked_time * 100 / resource_handler_lifetime;
603 UMA_HISTOGRAM_COUNTS_100("Download.ResourceHandlerBlockedPercentage",
604 percentage);
607 void RecordFileBandwidth(size_t length,
608 base::TimeDelta disk_write_time,
609 base::TimeDelta elapsed_time) {
610 size_t elapsed_time_ms = elapsed_time.InMilliseconds();
611 if (0u == elapsed_time_ms)
612 elapsed_time_ms = 1;
613 size_t disk_write_time_ms = disk_write_time.InMilliseconds();
614 if (0u == disk_write_time_ms)
615 disk_write_time_ms = 1;
617 UMA_HISTOGRAM_CUSTOM_COUNTS(
618 "Download.BandwidthOverallBytesPerSecond",
619 (1000 * length / elapsed_time_ms), 1, 50000000, 50);
620 UMA_HISTOGRAM_CUSTOM_COUNTS(
621 "Download.BandwidthDiskBytesPerSecond",
622 (1000 * length / disk_write_time_ms), 1, 50000000, 50);
623 UMA_HISTOGRAM_COUNTS_100("Download.DiskBandwidthUsedPercentage",
624 disk_write_time_ms * 100 / elapsed_time_ms);
627 void RecordDownloadFileRenameResultAfterRetry(
628 base::TimeDelta time_since_first_failure,
629 DownloadInterruptReason interrupt_reason) {
630 if (interrupt_reason == DOWNLOAD_INTERRUPT_REASON_NONE) {
631 UMA_HISTOGRAM_TIMES("Download.TimeToRenameSuccessAfterInitialFailure",
632 time_since_first_failure);
633 } else {
634 UMA_HISTOGRAM_TIMES("Download.TimeToRenameFailureAfterInitialFailure",
635 time_since_first_failure);
639 void RecordSavePackageEvent(SavePackageEvent event) {
640 UMA_HISTOGRAM_ENUMERATION("Download.SavePackage",
641 event,
642 SAVE_PACKAGE_LAST_ENTRY);
645 void RecordOriginStateOnResumption(bool is_partial,
646 int state) {
647 if (is_partial)
648 UMA_HISTOGRAM_ENUMERATION("Download.OriginStateOnPartialResumption", state,
649 ORIGIN_STATE_ON_RESUMPTION_MAX);
650 else
651 UMA_HISTOGRAM_ENUMERATION("Download.OriginStateOnFullResumption", state,
652 ORIGIN_STATE_ON_RESUMPTION_MAX);
655 } // namespace content