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"
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|
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 // At least one of 'name', 'filename' or 'filenae*' 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
,
42 CONTENT_DISPOSITION_HAS_NAME
,
43 CONTENT_DISPOSITION_HAS_FILENAME
,
44 CONTENT_DISPOSITION_HAS_EXT_FILENAME
,
45 CONTENT_DISPOSITION_HAS_NON_ASCII_STRINGS
,
46 CONTENT_DISPOSITION_HAS_PERCENT_ENCODED_STRINGS
,
47 CONTENT_DISPOSITION_HAS_RFC2047_ENCODED_STRINGS
,
49 // Only have the 'name' attribute is present.
50 CONTENT_DISPOSITION_HAS_NAME_ONLY
,
52 CONTENT_DISPOSITION_LAST_ENTRY
55 void RecordContentDispositionCount(ContentDispositionCountTypes type
,
59 UMA_HISTOGRAM_ENUMERATION(
60 "Download.ContentDisposition", type
, CONTENT_DISPOSITION_LAST_ENTRY
);
63 void RecordContentDispositionCountFlag(
64 ContentDispositionCountTypes type
,
66 net::HttpContentDisposition::ParseResultFlags flag
) {
67 RecordContentDispositionCount(type
, (flags_to_test
& flag
) == flag
);
70 // Do not insert, delete, or reorder; this is being histogrammed. Append only.
71 // All of the download_extensions.cc file types should be in this list.
72 const base::FilePath::CharType
* kDangerousFileTypes
[] = {
73 FILE_PATH_LITERAL(".ad"),
74 FILE_PATH_LITERAL(".ade"),
75 FILE_PATH_LITERAL(".adp"),
76 FILE_PATH_LITERAL(".ah"),
77 FILE_PATH_LITERAL(".apk"),
78 FILE_PATH_LITERAL(".app"),
79 FILE_PATH_LITERAL(".application"),
80 FILE_PATH_LITERAL(".asp"),
81 FILE_PATH_LITERAL(".asx"),
82 FILE_PATH_LITERAL(".bas"),
83 FILE_PATH_LITERAL(".bash"),
84 FILE_PATH_LITERAL(".bat"),
85 FILE_PATH_LITERAL(".cfg"),
86 FILE_PATH_LITERAL(".chi"),
87 FILE_PATH_LITERAL(".chm"),
88 FILE_PATH_LITERAL(".class"),
89 FILE_PATH_LITERAL(".cmd"),
90 FILE_PATH_LITERAL(".com"),
91 FILE_PATH_LITERAL(".command"),
92 FILE_PATH_LITERAL(".crt"),
93 FILE_PATH_LITERAL(".crx"),
94 FILE_PATH_LITERAL(".csh"),
95 FILE_PATH_LITERAL(".deb"),
96 FILE_PATH_LITERAL(".dex"),
97 FILE_PATH_LITERAL(".dll"),
98 FILE_PATH_LITERAL(".drv"),
99 FILE_PATH_LITERAL(".exe"),
100 FILE_PATH_LITERAL(".fxp"),
101 FILE_PATH_LITERAL(".grp"),
102 FILE_PATH_LITERAL(".hlp"),
103 FILE_PATH_LITERAL(".hta"),
104 FILE_PATH_LITERAL(".htm"),
105 FILE_PATH_LITERAL(".html"),
106 FILE_PATH_LITERAL(".htt"),
107 FILE_PATH_LITERAL(".inf"),
108 FILE_PATH_LITERAL(".ini"),
109 FILE_PATH_LITERAL(".ins"),
110 FILE_PATH_LITERAL(".isp"),
111 FILE_PATH_LITERAL(".jar"),
112 FILE_PATH_LITERAL(".jnlp"),
113 FILE_PATH_LITERAL(".user.js"),
114 FILE_PATH_LITERAL(".js"),
115 FILE_PATH_LITERAL(".jse"),
116 FILE_PATH_LITERAL(".ksh"),
117 FILE_PATH_LITERAL(".lnk"),
118 FILE_PATH_LITERAL(".local"),
119 FILE_PATH_LITERAL(".mad"),
120 FILE_PATH_LITERAL(".maf"),
121 FILE_PATH_LITERAL(".mag"),
122 FILE_PATH_LITERAL(".mam"),
123 FILE_PATH_LITERAL(".manifest"),
124 FILE_PATH_LITERAL(".maq"),
125 FILE_PATH_LITERAL(".mar"),
126 FILE_PATH_LITERAL(".mas"),
127 FILE_PATH_LITERAL(".mat"),
128 FILE_PATH_LITERAL(".mau"),
129 FILE_PATH_LITERAL(".mav"),
130 FILE_PATH_LITERAL(".maw"),
131 FILE_PATH_LITERAL(".mda"),
132 FILE_PATH_LITERAL(".mdb"),
133 FILE_PATH_LITERAL(".mde"),
134 FILE_PATH_LITERAL(".mdt"),
135 FILE_PATH_LITERAL(".mdw"),
136 FILE_PATH_LITERAL(".mdz"),
137 FILE_PATH_LITERAL(".mht"),
138 FILE_PATH_LITERAL(".mhtml"),
139 FILE_PATH_LITERAL(".mmc"),
140 FILE_PATH_LITERAL(".mof"),
141 FILE_PATH_LITERAL(".msc"),
142 FILE_PATH_LITERAL(".msh"),
143 FILE_PATH_LITERAL(".mshxml"),
144 FILE_PATH_LITERAL(".msi"),
145 FILE_PATH_LITERAL(".msp"),
146 FILE_PATH_LITERAL(".mst"),
147 FILE_PATH_LITERAL(".ocx"),
148 FILE_PATH_LITERAL(".ops"),
149 FILE_PATH_LITERAL(".pcd"),
150 FILE_PATH_LITERAL(".pif"),
151 FILE_PATH_LITERAL(".pkg"),
152 FILE_PATH_LITERAL(".pl"),
153 FILE_PATH_LITERAL(".plg"),
154 FILE_PATH_LITERAL(".prf"),
155 FILE_PATH_LITERAL(".prg"),
156 FILE_PATH_LITERAL(".pst"),
157 FILE_PATH_LITERAL(".py"),
158 FILE_PATH_LITERAL(".pyc"),
159 FILE_PATH_LITERAL(".pyw"),
160 FILE_PATH_LITERAL(".rb"),
161 FILE_PATH_LITERAL(".reg"),
162 FILE_PATH_LITERAL(".rpm"),
163 FILE_PATH_LITERAL(".scf"),
164 FILE_PATH_LITERAL(".scr"),
165 FILE_PATH_LITERAL(".sct"),
166 FILE_PATH_LITERAL(".sh"),
167 FILE_PATH_LITERAL(".shar"),
168 FILE_PATH_LITERAL(".shb"),
169 FILE_PATH_LITERAL(".shs"),
170 FILE_PATH_LITERAL(".shtm"),
171 FILE_PATH_LITERAL(".shtml"),
172 FILE_PATH_LITERAL(".spl"),
173 FILE_PATH_LITERAL(".svg"),
174 FILE_PATH_LITERAL(".swf"),
175 FILE_PATH_LITERAL(".sys"),
176 FILE_PATH_LITERAL(".tcsh"),
177 FILE_PATH_LITERAL(".url"),
178 FILE_PATH_LITERAL(".vb"),
179 FILE_PATH_LITERAL(".vbe"),
180 FILE_PATH_LITERAL(".vbs"),
181 FILE_PATH_LITERAL(".vsd"),
182 FILE_PATH_LITERAL(".vsmacros"),
183 FILE_PATH_LITERAL(".vss"),
184 FILE_PATH_LITERAL(".vst"),
185 FILE_PATH_LITERAL(".vsw"),
186 FILE_PATH_LITERAL(".ws"),
187 FILE_PATH_LITERAL(".wsc"),
188 FILE_PATH_LITERAL(".wsf"),
189 FILE_PATH_LITERAL(".wsh"),
190 FILE_PATH_LITERAL(".xbap"),
191 FILE_PATH_LITERAL(".xht"),
192 FILE_PATH_LITERAL(".xhtm"),
193 FILE_PATH_LITERAL(".xhtml"),
194 FILE_PATH_LITERAL(".xml"),
195 FILE_PATH_LITERAL(".xsl"),
196 FILE_PATH_LITERAL(".xslt")
199 // Maps extensions to their matching UMA histogram int value.
200 int GetDangerousFileType(const base::FilePath
& file_path
) {
201 for (size_t i
= 0; i
< arraysize(kDangerousFileTypes
); ++i
) {
202 if (file_path
.MatchesExtension(kDangerousFileTypes
[i
]))
205 return 0; // Unknown extension.
210 void RecordDownloadCount(DownloadCountTypes type
) {
211 UMA_HISTOGRAM_ENUMERATION(
212 "Download.Counts", type
, DOWNLOAD_COUNT_TYPES_LAST_ENTRY
);
215 void RecordDownloadSource(DownloadSource source
) {
216 UMA_HISTOGRAM_ENUMERATION(
217 "Download.Sources", source
, DOWNLOAD_SOURCE_LAST_ENTRY
);
220 void RecordDownloadCompleted(const base::TimeTicks
& start
, int64 download_len
) {
221 RecordDownloadCount(COMPLETED_COUNT
);
222 UMA_HISTOGRAM_LONG_TIMES("Download.Time", (base::TimeTicks::Now() - start
));
223 int64 max
= 1024 * 1024 * 1024; // One Terabyte.
224 download_len
/= 1024; // In Kilobytes
225 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.DownloadSize",
232 void RecordDownloadInterrupted(DownloadInterruptReason reason
,
235 RecordDownloadCount(INTERRUPTED_COUNT
);
236 UMA_HISTOGRAM_CUSTOM_ENUMERATION(
237 "Download.InterruptedReason",
239 base::CustomHistogram::ArrayToCustomRanges(
240 kAllInterruptReasonCodes
, arraysize(kAllInterruptReasonCodes
)));
242 // The maximum should be 2^kBuckets, to have the logarithmic bucket
243 // boundaries fall on powers of 2.
244 static const int kBuckets
= 30;
245 static const int64 kMaxKb
= 1 << kBuckets
; // One Terabyte, in Kilobytes.
246 int64 delta_bytes
= total
- received
;
247 bool unknown_size
= total
<= 0;
248 int64 received_kb
= received
/ 1024;
249 int64 total_kb
= total
/ 1024;
250 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedReceivedSizeK",
256 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedTotalSizeK",
261 if (delta_bytes
== 0) {
262 RecordDownloadCount(INTERRUPTED_AT_END_COUNT
);
263 UMA_HISTOGRAM_CUSTOM_ENUMERATION(
264 "Download.InterruptedAtEndReason",
266 base::CustomHistogram::ArrayToCustomRanges(
267 kAllInterruptReasonCodes
,
268 arraysize(kAllInterruptReasonCodes
)));
269 } else if (delta_bytes
> 0) {
270 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedOverrunBytes",
276 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedUnderrunBytes",
284 UMA_HISTOGRAM_BOOLEAN("Download.InterruptedUnknownSize", unknown_size
);
287 void RecordMaliciousDownloadClassified(DownloadDangerType danger_type
) {
288 UMA_HISTOGRAM_ENUMERATION("Download.MaliciousDownloadClassified",
290 DOWNLOAD_DANGER_TYPE_MAX
);
293 void RecordDangerousDownloadAccept(DownloadDangerType danger_type
,
294 const base::FilePath
& file_path
) {
295 UMA_HISTOGRAM_ENUMERATION("Download.DangerousDownloadValidated",
297 DOWNLOAD_DANGER_TYPE_MAX
);
298 if (danger_type
== DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
) {
299 UMA_HISTOGRAM_SPARSE_SLOWLY(
300 "Download.DangerousFile.DangerousDownloadValidated",
301 GetDangerousFileType(file_path
));
305 void RecordDangerousDownloadDiscard(DownloadDiscardReason reason
,
306 DownloadDangerType danger_type
,
307 const base::FilePath
& file_path
) {
309 case DOWNLOAD_DISCARD_DUE_TO_USER_ACTION
:
310 UMA_HISTOGRAM_ENUMERATION(
311 "Download.UserDiscard", danger_type
, DOWNLOAD_DANGER_TYPE_MAX
);
312 if (danger_type
== DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
) {
313 UMA_HISTOGRAM_SPARSE_SLOWLY("Download.DangerousFile.UserDiscard",
314 GetDangerousFileType(file_path
));
317 case DOWNLOAD_DISCARD_DUE_TO_SHUTDOWN
:
318 UMA_HISTOGRAM_ENUMERATION(
319 "Download.Discard", danger_type
, DOWNLOAD_DANGER_TYPE_MAX
);
320 if (danger_type
== DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
) {
321 UMA_HISTOGRAM_SPARSE_SLOWLY("Download.DangerousFile.Discard",
322 GetDangerousFileType(file_path
));
330 void RecordDownloadWriteSize(size_t data_len
) {
331 int max
= 1024 * 1024; // One Megabyte.
332 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.WriteSize", data_len
, 1, max
, 256);
335 void RecordDownloadWriteLoopCount(int count
) {
336 UMA_HISTOGRAM_ENUMERATION("Download.WriteLoopCount", count
, 20);
339 void RecordAcceptsRanges(const std::string
& accepts_ranges
,
341 bool has_strong_validator
) {
342 int64 max
= 1024 * 1024 * 1024; // One Terabyte.
343 download_len
/= 1024; // In Kilobytes
344 static const int kBuckets
= 50;
346 if (LowerCaseEqualsASCII(accepts_ranges
, "none")) {
347 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.AcceptRangesNone.KBytes",
352 } else if (LowerCaseEqualsASCII(accepts_ranges
, "bytes")) {
353 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.AcceptRangesBytes.KBytes",
358 if (has_strong_validator
)
359 RecordDownloadCount(STRONG_VALIDATOR_AND_ACCEPTS_RANGES
);
361 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.AcceptRangesMissingOrInvalid.KBytes",
371 enum DownloadContent
{
372 DOWNLOAD_CONTENT_UNRECOGNIZED
= 0,
373 DOWNLOAD_CONTENT_TEXT
= 1,
374 DOWNLOAD_CONTENT_IMAGE
= 2,
375 DOWNLOAD_CONTENT_AUDIO
= 3,
376 DOWNLOAD_CONTENT_VIDEO
= 4,
377 DOWNLOAD_CONTENT_OCTET_STREAM
= 5,
378 DOWNLOAD_CONTENT_PDF
= 6,
379 DOWNLOAD_CONTENT_DOC
= 7,
380 DOWNLOAD_CONTENT_XLS
= 8,
381 DOWNLOAD_CONTENT_PPT
= 9,
382 DOWNLOAD_CONTENT_ARCHIVE
= 10,
383 DOWNLOAD_CONTENT_EXE
= 11,
384 DOWNLOAD_CONTENT_DMG
= 12,
385 DOWNLOAD_CONTENT_CRX
= 13,
386 DOWNLOAD_CONTENT_MAX
= 14,
389 struct MimeTypeToDownloadContent
{
390 const char* mime_type
;
391 DownloadContent download_content
;
394 static MimeTypeToDownloadContent kMapMimeTypeToDownloadContent
[] = {
395 {"application/octet-stream", DOWNLOAD_CONTENT_OCTET_STREAM
},
396 {"binary/octet-stream", DOWNLOAD_CONTENT_OCTET_STREAM
},
397 {"application/pdf", DOWNLOAD_CONTENT_PDF
},
398 {"application/msword", DOWNLOAD_CONTENT_DOC
},
399 {"application/vnd.ms-excel", DOWNLOAD_CONTENT_XLS
},
400 {"application/vns.ms-powerpoint", DOWNLOAD_CONTENT_PPT
},
401 {"application/zip", DOWNLOAD_CONTENT_ARCHIVE
},
402 {"application/x-gzip", DOWNLOAD_CONTENT_ARCHIVE
},
403 {"application/x-rar-compressed", DOWNLOAD_CONTENT_ARCHIVE
},
404 {"application/x-tar", DOWNLOAD_CONTENT_ARCHIVE
},
405 {"application/x-bzip", DOWNLOAD_CONTENT_ARCHIVE
},
406 {"application/x-exe", DOWNLOAD_CONTENT_EXE
},
407 {"application/x-apple-diskimage", DOWNLOAD_CONTENT_DMG
},
408 {"application/x-chrome-extension", DOWNLOAD_CONTENT_CRX
},
412 DOWNLOAD_IMAGE_UNRECOGNIZED
= 0,
413 DOWNLOAD_IMAGE_GIF
= 1,
414 DOWNLOAD_IMAGE_JPEG
= 2,
415 DOWNLOAD_IMAGE_PNG
= 3,
416 DOWNLOAD_IMAGE_TIFF
= 4,
417 DOWNLOAD_IMAGE_ICON
= 5,
418 DOWNLOAD_IMAGE_WEBP
= 6,
419 DOWNLOAD_IMAGE_MAX
= 7,
422 struct MimeTypeToDownloadImage
{
423 const char* mime_type
;
424 DownloadImage download_image
;
427 static MimeTypeToDownloadImage kMapMimeTypeToDownloadImage
[] = {
428 {"image/gif", DOWNLOAD_IMAGE_GIF
},
429 {"image/jpeg", DOWNLOAD_IMAGE_JPEG
},
430 {"image/png", DOWNLOAD_IMAGE_PNG
},
431 {"image/tiff", DOWNLOAD_IMAGE_TIFF
},
432 {"image/vnd.microsoft.icon", DOWNLOAD_IMAGE_ICON
},
433 {"image/webp", DOWNLOAD_IMAGE_WEBP
},
436 void RecordDownloadImageType(const std::string
& mime_type_string
) {
437 DownloadImage download_image
= DOWNLOAD_IMAGE_UNRECOGNIZED
;
439 // Look up exact matches.
440 for (size_t i
= 0; i
< arraysize(kMapMimeTypeToDownloadImage
); ++i
) {
441 const MimeTypeToDownloadImage
& entry
= kMapMimeTypeToDownloadImage
[i
];
442 if (mime_type_string
== entry
.mime_type
) {
443 download_image
= entry
.download_image
;
448 UMA_HISTOGRAM_ENUMERATION("Download.ContentImageType",
455 void RecordDownloadMimeType(const std::string
& mime_type_string
) {
456 DownloadContent download_content
= DOWNLOAD_CONTENT_UNRECOGNIZED
;
458 // Look up exact matches.
459 for (size_t i
= 0; i
< arraysize(kMapMimeTypeToDownloadContent
); ++i
) {
460 const MimeTypeToDownloadContent
& entry
= kMapMimeTypeToDownloadContent
[i
];
461 if (mime_type_string
== entry
.mime_type
) {
462 download_content
= entry
.download_content
;
467 // Do partial matches.
468 if (download_content
== DOWNLOAD_CONTENT_UNRECOGNIZED
) {
469 if (StartsWithASCII(mime_type_string
, "text/", true)) {
470 download_content
= DOWNLOAD_CONTENT_TEXT
;
471 } else if (StartsWithASCII(mime_type_string
, "image/", true)) {
472 download_content
= DOWNLOAD_CONTENT_IMAGE
;
473 RecordDownloadImageType(mime_type_string
);
474 } else if (StartsWithASCII(mime_type_string
, "audio/", true)) {
475 download_content
= DOWNLOAD_CONTENT_AUDIO
;
476 } else if (StartsWithASCII(mime_type_string
, "video/", true)) {
477 download_content
= DOWNLOAD_CONTENT_VIDEO
;
482 UMA_HISTOGRAM_ENUMERATION("Download.ContentType",
484 DOWNLOAD_CONTENT_MAX
);
487 void RecordDownloadContentDisposition(
488 const std::string
& content_disposition_string
) {
489 if (content_disposition_string
.empty())
491 net::HttpContentDisposition
content_disposition(content_disposition_string
,
493 int result
= content_disposition
.parse_result_flags();
495 bool is_valid
= !content_disposition
.filename().empty();
496 RecordContentDispositionCount(CONTENT_DISPOSITION_HEADER_PRESENT
, true);
497 RecordContentDispositionCount(CONTENT_DISPOSITION_IS_VALID
, is_valid
);
501 RecordContentDispositionCountFlag(
502 CONTENT_DISPOSITION_HAS_DISPOSITION_TYPE
, result
,
503 net::HttpContentDisposition::HAS_DISPOSITION_TYPE
);
504 RecordContentDispositionCountFlag(
505 CONTENT_DISPOSITION_HAS_UNKNOWN_TYPE
, result
,
506 net::HttpContentDisposition::HAS_UNKNOWN_DISPOSITION_TYPE
);
507 RecordContentDispositionCountFlag(
508 CONTENT_DISPOSITION_HAS_NAME
, result
,
509 net::HttpContentDisposition::HAS_NAME
);
510 RecordContentDispositionCountFlag(
511 CONTENT_DISPOSITION_HAS_FILENAME
, result
,
512 net::HttpContentDisposition::HAS_FILENAME
);
513 RecordContentDispositionCountFlag(
514 CONTENT_DISPOSITION_HAS_EXT_FILENAME
, result
,
515 net::HttpContentDisposition::HAS_EXT_FILENAME
);
516 RecordContentDispositionCountFlag(
517 CONTENT_DISPOSITION_HAS_NON_ASCII_STRINGS
, result
,
518 net::HttpContentDisposition::HAS_NON_ASCII_STRINGS
);
519 RecordContentDispositionCountFlag(
520 CONTENT_DISPOSITION_HAS_PERCENT_ENCODED_STRINGS
, result
,
521 net::HttpContentDisposition::HAS_PERCENT_ENCODED_STRINGS
);
522 RecordContentDispositionCountFlag(
523 CONTENT_DISPOSITION_HAS_RFC2047_ENCODED_STRINGS
, result
,
524 net::HttpContentDisposition::HAS_RFC2047_ENCODED_STRINGS
);
526 RecordContentDispositionCount(
527 CONTENT_DISPOSITION_HAS_NAME_ONLY
,
528 (result
& (net::HttpContentDisposition::HAS_NAME
|
529 net::HttpContentDisposition::HAS_FILENAME
|
530 net::HttpContentDisposition::HAS_EXT_FILENAME
)) ==
531 net::HttpContentDisposition::HAS_NAME
);
534 void RecordFileThreadReceiveBuffers(size_t num_buffers
) {
535 UMA_HISTOGRAM_CUSTOM_COUNTS(
536 "Download.FileThreadReceiveBuffers", num_buffers
, 1,
540 void RecordBandwidth(double actual_bandwidth
, double potential_bandwidth
) {
541 UMA_HISTOGRAM_CUSTOM_COUNTS(
542 "Download.ActualBandwidth", actual_bandwidth
, 1, 1000000000, 50);
543 UMA_HISTOGRAM_CUSTOM_COUNTS(
544 "Download.PotentialBandwidth", potential_bandwidth
, 1, 1000000000, 50);
545 UMA_HISTOGRAM_PERCENTAGE(
546 "Download.BandwidthUsed",
547 (int) ((actual_bandwidth
* 100)/ potential_bandwidth
));
550 void RecordOpen(const base::Time
& end
, bool first
) {
551 if (!end
.is_null()) {
552 UMA_HISTOGRAM_LONG_TIMES("Download.OpenTime", (base::Time::Now() - end
));
554 UMA_HISTOGRAM_LONG_TIMES("Download.FirstOpenTime",
555 (base::Time::Now() - end
));
560 void RecordClearAllSize(int size
) {
561 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.ClearAllSize",
568 void RecordOpensOutstanding(int size
) {
569 UMA_HISTOGRAM_CUSTOM_COUNTS("Download.OpensOutstanding",
576 void RecordContiguousWriteTime(base::TimeDelta time_blocked
) {
577 UMA_HISTOGRAM_TIMES("Download.FileThreadBlockedTime", time_blocked
);
580 // Record what percentage of the time we have the network flow controlled.
581 void RecordNetworkBlockage(base::TimeDelta resource_handler_lifetime
,
582 base::TimeDelta resource_handler_blocked_time
) {
584 // Avoid division by zero errors.
585 if (resource_handler_blocked_time
!= base::TimeDelta()) {
587 resource_handler_blocked_time
* 100 / resource_handler_lifetime
;
590 UMA_HISTOGRAM_COUNTS_100("Download.ResourceHandlerBlockedPercentage",
594 void RecordFileBandwidth(size_t length
,
595 base::TimeDelta disk_write_time
,
596 base::TimeDelta elapsed_time
) {
597 size_t elapsed_time_ms
= elapsed_time
.InMilliseconds();
598 if (0u == elapsed_time_ms
)
600 size_t disk_write_time_ms
= disk_write_time
.InMilliseconds();
601 if (0u == disk_write_time_ms
)
602 disk_write_time_ms
= 1;
604 UMA_HISTOGRAM_CUSTOM_COUNTS(
605 "Download.BandwidthOverallBytesPerSecond",
606 (1000 * length
/ elapsed_time_ms
), 1, 50000000, 50);
607 UMA_HISTOGRAM_CUSTOM_COUNTS(
608 "Download.BandwidthDiskBytesPerSecond",
609 (1000 * length
/ disk_write_time_ms
), 1, 50000000, 50);
610 UMA_HISTOGRAM_COUNTS_100("Download.DiskBandwidthUsedPercentage",
611 disk_write_time_ms
* 100 / elapsed_time_ms
);
614 void RecordDownloadFileRenameResultAfterRetry(
615 base::TimeDelta time_since_first_failure
,
616 DownloadInterruptReason interrupt_reason
) {
617 if (interrupt_reason
== DOWNLOAD_INTERRUPT_REASON_NONE
) {
618 UMA_HISTOGRAM_TIMES("Download.TimeToRenameSuccessAfterInitialFailure",
619 time_since_first_failure
);
621 UMA_HISTOGRAM_TIMES("Download.TimeToRenameFailureAfterInitialFailure",
622 time_since_first_failure
);
626 void RecordSavePackageEvent(SavePackageEvent event
) {
627 UMA_HISTOGRAM_ENUMERATION("Download.SavePackage",
629 SAVE_PACKAGE_LAST_ENTRY
);
632 void RecordOriginStateOnResumption(bool is_partial
,
635 UMA_HISTOGRAM_ENUMERATION("Download.OriginStateOnPartialResumption", state
,
636 ORIGIN_STATE_ON_RESUMPTION_MAX
);
638 UMA_HISTOGRAM_ENUMERATION("Download.OriginStateOnFullResumption", state
,
639 ORIGIN_STATE_ON_RESUMPTION_MAX
);
642 } // namespace content