| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/download/download_stats.h" |
| |
| #include "base/metrics/histogram.h" |
| #include "base/string_util.h" |
| #include "content/browser/download/interrupt_reasons.h" |
| |
| namespace download_stats { |
| |
| // All possible error codes from the network module. Note that the error codes |
| // are all positive (since histograms expect positive sample values). |
| const int kAllInterruptReasonCodes[] = { |
| #define INTERRUPT_REASON(label, value) (value), |
| #include "content/browser/download/interrupt_reason_values.h" |
| #undef INTERRUPT_REASON |
| }; |
| |
| void RecordDownloadCount(DownloadCountTypes type) { |
| UMA_HISTOGRAM_ENUMERATION( |
| "Download.Counts", type, DOWNLOAD_COUNT_TYPES_LAST_ENTRY); |
| } |
| |
| void RecordDownloadCompleted(const base::TimeTicks& start, int64 download_len) { |
| RecordDownloadCount(COMPLETED_COUNT); |
| UMA_HISTOGRAM_LONG_TIMES("Download.Time", (base::TimeTicks::Now() - start)); |
| int64 max = 1024 * 1024 * 1024; // One Terabyte. |
| download_len /= 1024; // In Kilobytes |
| UMA_HISTOGRAM_CUSTOM_COUNTS("Download.DownloadSize", |
| download_len, |
| 1, |
| max, |
| 256); |
| } |
| |
| void RecordDownloadInterrupted(InterruptReason reason, |
| int64 received, |
| int64 total) { |
| RecordDownloadCount(INTERRUPTED_COUNT); |
| UMA_HISTOGRAM_CUSTOM_ENUMERATION( |
| "Download.InterruptedReason", |
| reason, |
| base::CustomHistogram::ArrayToCustomRanges( |
| kAllInterruptReasonCodes, arraysize(kAllInterruptReasonCodes))); |
| |
| // The maximum should be 2^kBuckets, to have the logarithmic bucket |
| // boundaries fall on powers of 2. |
| static const int kBuckets = 30; |
| static const int64 kMaxKb = 1 << kBuckets; // One Terabyte, in Kilobytes. |
| int64 delta_bytes = total - received; |
| bool unknown_size = total <= 0; |
| int64 received_kb = received / 1024; |
| int64 total_kb = total / 1024; |
| UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedReceivedSizeK", |
| received_kb, |
| 1, |
| kMaxKb, |
| kBuckets); |
| if (!unknown_size) { |
| UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedTotalSizeK", |
| total_kb, |
| 1, |
| kMaxKb, |
| kBuckets); |
| if (delta_bytes == 0) { |
| RecordDownloadCount(INTERRUPTED_AT_END_COUNT); |
| UMA_HISTOGRAM_CUSTOM_ENUMERATION( |
| "Download.InterruptedAtEndReason", |
| reason, |
| base::CustomHistogram::ArrayToCustomRanges( |
| kAllInterruptReasonCodes, |
| arraysize(kAllInterruptReasonCodes))); |
| } else if (delta_bytes > 0) { |
| UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedOverrunBytes", |
| delta_bytes, |
| 1, |
| kMaxKb, |
| kBuckets); |
| } else { |
| UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedUnderrunBytes", |
| -delta_bytes, |
| 1, |
| kMaxKb, |
| kBuckets); |
| } |
| } |
| |
| UMA_HISTOGRAM_BOOLEAN("Download.InterruptedUnknownSize", unknown_size); |
| } |
| |
| void RecordDownloadWriteSize(size_t data_len) { |
| RecordDownloadCount(WRITE_SIZE_COUNT); |
| int max = 1024 * 1024; // One Megabyte. |
| UMA_HISTOGRAM_CUSTOM_COUNTS("Download.WriteSize", data_len, 1, max, 256); |
| } |
| |
| void RecordDownloadWriteLoopCount(int count) { |
| RecordDownloadCount(WRITE_LOOP_COUNT); |
| UMA_HISTOGRAM_ENUMERATION("Download.WriteLoopCount", count, 20); |
| } |
| |
| namespace { |
| |
| enum DownloadContent { |
| DOWNLOAD_CONTENT_UNRECOGNIZED = 0, |
| DOWNLOAD_CONTENT_TEXT = 1, |
| DOWNLOAD_CONTENT_IMAGE = 2, |
| DOWNLOAD_CONTENT_AUDIO = 3, |
| DOWNLOAD_CONTENT_VIDEO = 4, |
| DOWNLOAD_CONTENT_OCTET_STREAM = 5, |
| DOWNLOAD_CONTENT_PDF = 6, |
| DOWNLOAD_CONTENT_DOC = 7, |
| DOWNLOAD_CONTENT_XLS = 8, |
| DOWNLOAD_CONTENT_PPT = 9, |
| DOWNLOAD_CONTENT_ARCHIVE = 10, |
| DOWNLOAD_CONTENT_EXE = 11, |
| DOWNLOAD_CONTENT_DMG = 12, |
| DOWNLOAD_CONTENT_CRX = 13, |
| DOWNLOAD_CONTENT_MAX = 14, |
| }; |
| |
| struct MimeTypeToDownloadContent { |
| const char* mime_type; |
| DownloadContent download_content; |
| }; |
| |
| static MimeTypeToDownloadContent kMapMimeTypeToDownloadContent[] = { |
| {"application/octet-stream", DOWNLOAD_CONTENT_OCTET_STREAM}, |
| {"binary/octet-stream", DOWNLOAD_CONTENT_OCTET_STREAM}, |
| {"application/pdf", DOWNLOAD_CONTENT_PDF}, |
| {"application/msword", DOWNLOAD_CONTENT_DOC}, |
| {"application/vnd.ms-excel", DOWNLOAD_CONTENT_XLS}, |
| {"application/vns.ms-powerpoint", DOWNLOAD_CONTENT_PPT}, |
| {"application/zip", DOWNLOAD_CONTENT_ARCHIVE}, |
| {"application/x-gzip", DOWNLOAD_CONTENT_ARCHIVE}, |
| {"application/x-rar-compressed", DOWNLOAD_CONTENT_ARCHIVE}, |
| {"application/x-tar", DOWNLOAD_CONTENT_ARCHIVE}, |
| {"application/x-bzip", DOWNLOAD_CONTENT_ARCHIVE}, |
| {"application/x-exe", DOWNLOAD_CONTENT_EXE}, |
| {"application/x-apple-diskimage", DOWNLOAD_CONTENT_DMG}, |
| {"application/x-chrome-extension", DOWNLOAD_CONTENT_CRX}, |
| }; |
| |
| } // namespace |
| |
| void RecordDownloadMimeType(const std::string& mime_type_string) { |
| DownloadContent download_content = DOWNLOAD_CONTENT_UNRECOGNIZED; |
| |
| // Look up exact matches. |
| for (size_t i = 0; i < arraysize(kMapMimeTypeToDownloadContent); ++i) { |
| const MimeTypeToDownloadContent& entry = |
| kMapMimeTypeToDownloadContent[i]; |
| if (mime_type_string == entry.mime_type) { |
| download_content = entry.download_content; |
| break; |
| } |
| } |
| |
| // Do partial matches. |
| if (download_content == DOWNLOAD_CONTENT_UNRECOGNIZED) { |
| if (StartsWithASCII(mime_type_string, "text/", true)) { |
| download_content = DOWNLOAD_CONTENT_TEXT; |
| } else if (StartsWithASCII(mime_type_string, "image/", true)) { |
| download_content = DOWNLOAD_CONTENT_IMAGE; |
| } else if (StartsWithASCII(mime_type_string, "audio/", true)) { |
| download_content = DOWNLOAD_CONTENT_AUDIO; |
| } else if (StartsWithASCII(mime_type_string, "video/", true)) { |
| download_content = DOWNLOAD_CONTENT_VIDEO; |
| } |
| } |
| |
| // Record the value. |
| UMA_HISTOGRAM_ENUMERATION("Download.ContentType", |
| download_content, |
| DOWNLOAD_CONTENT_MAX); |
| } |
| |
| void RecordOpen(const base::Time& end, bool first) { |
| if (!end.is_null()) { |
| UMA_HISTOGRAM_LONG_TIMES("Download.OpenTime", (base::Time::Now() - end)); |
| if (first) { |
| UMA_HISTOGRAM_LONG_TIMES("Download.FirstOpenTime", |
| (base::Time::Now() - end)); |
| } |
| } |
| } |
| |
| void RecordHistorySize(int size) { |
| UMA_HISTOGRAM_CUSTOM_COUNTS("Download.HistorySize", |
| size, |
| 0/*min*/, |
| (1 << 10)/*max*/, |
| 32/*num_buckets*/); |
| } |
| |
| void RecordShelfClose(int size, int in_progress, bool autoclose) { |
| static const int kMaxShelfSize = 16; |
| if (autoclose) { |
| UMA_HISTOGRAM_ENUMERATION("Download.ShelfSizeOnAutoClose", |
| size, |
| kMaxShelfSize); |
| UMA_HISTOGRAM_ENUMERATION("Download.ShelfInProgressSizeOnAutoClose", |
| in_progress, |
| kMaxShelfSize); |
| } else { |
| UMA_HISTOGRAM_ENUMERATION("Download.ShelfSizeOnUserClose", |
| size, |
| kMaxShelfSize); |
| UMA_HISTOGRAM_ENUMERATION("Download.ShelfInProgressSizeOnUserClose", |
| in_progress, |
| kMaxShelfSize); |
| } |
| } |
| |
| void RecordClearAllSize(int size) { |
| UMA_HISTOGRAM_CUSTOM_COUNTS("Download.ClearAllSize", |
| size, |
| 0/*min*/, |
| (1 << 10)/*max*/, |
| 32/*num_buckets*/); |
| } |
| |
| void RecordOpensOutstanding(int size) { |
| UMA_HISTOGRAM_CUSTOM_COUNTS("Download.OpensOutstanding", |
| size, |
| 0/*min*/, |
| (1 << 10)/*max*/, |
| 64/*num_buckets*/); |
| } |
| |
| } // namespace download_stats |