blob: 856e62af9fa63b9d8c839e4e371edec791b2b125 [file] [log] [blame]
// 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