blob: 9fec9e417105e8eb86753a6acd3242f8a09db47b [file] [log] [blame]
// Copyright 2021 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 "components/safe_browsing/content/browser/download/download_stats.h"
#include "base/files/file_path.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/user_metrics.h"
#include "base/metrics/user_metrics_action.h"
#include "base/time/time.h"
#include "components/download/public/common/download_danger_type.h"
#include "components/safe_browsing/content/common/file_type_policies.h"
namespace {
using safe_browsing::FileTypePolicies;
constexpr char kShownMetricSuffix[] = ".Shown";
constexpr char kBypassedMetricSuffix[] = ".Bypassed";
std::string GetDangerTypeMetricSuffix(
download::DownloadDangerType danger_type) {
switch (danger_type) {
case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
return ".DangerousFileType";
case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE:
case download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_OPENED_DANGEROUS:
return ".Malicious";
case download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
return ".Uncommon";
case download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING:
case download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING:
case download::DOWNLOAD_DANGER_TYPE_BLOCKED_PASSWORD_PROTECTED:
case download::DOWNLOAD_DANGER_TYPE_BLOCKED_TOO_LARGE:
case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_WARNING:
case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_BLOCK:
case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_SAFE:
case download::DOWNLOAD_DANGER_TYPE_BLOCKED_UNSUPPORTED_FILETYPE:
case download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
case download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
case download::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
case download::DOWNLOAD_DANGER_TYPE_ALLOWLISTED_BY_POLICY:
case download::DOWNLOAD_DANGER_TYPE_MAX:
return ".Others";
}
}
void RecordDangerousWarningFileType(download::DownloadDangerType danger_type,
const base::FilePath& file_path,
const std::string& metrics_suffix) {
base::UmaHistogramSparse(
"SBClientDownload.Warning.FileType" +
GetDangerTypeMetricSuffix(danger_type) + metrics_suffix,
FileTypePolicies::GetInstance()->UmaValueForFile(file_path));
}
void RecordDangerousWarningIsHttps(download::DownloadDangerType danger_type,
bool is_https,
const std::string& metrics_suffix) {
base::UmaHistogramBoolean("SBClientDownload.Warning.DownloadIsHttps" +
GetDangerTypeMetricSuffix(danger_type) +
metrics_suffix,
is_https);
}
void RecordDangerousWarningHasUserGesture(
download::DownloadDangerType danger_type,
bool has_user_gesture,
const std::string& metrics_suffix) {
base::UmaHistogramBoolean("SBClientDownload.Warning.DownloadHasUserGesture" +
GetDangerTypeMetricSuffix(danger_type) +
metrics_suffix,
has_user_gesture);
}
} // namespace
namespace safe_browsing {
void RecordDangerousDownloadWarningShown(
download::DownloadDangerType danger_type,
const base::FilePath& file_path,
bool is_https,
bool has_user_gesture) {
RecordDangerousWarningFileType(danger_type, file_path, kShownMetricSuffix);
RecordDangerousWarningIsHttps(danger_type, is_https, kShownMetricSuffix);
RecordDangerousWarningHasUserGesture(danger_type, has_user_gesture,
kShownMetricSuffix);
base::RecordAction(
base::UserMetricsAction("SafeBrowsing.Download.WarningShown"));
}
void RecordDangerousDownloadWarningBypassed(
download::DownloadDangerType danger_type,
const base::FilePath& file_path,
bool is_https,
bool has_user_gesture) {
RecordDangerousWarningFileType(danger_type, file_path, kBypassedMetricSuffix);
RecordDangerousWarningIsHttps(danger_type, is_https, kBypassedMetricSuffix);
RecordDangerousWarningHasUserGesture(danger_type, has_user_gesture,
kBypassedMetricSuffix);
base::RecordAction(
base::UserMetricsAction("SafeBrowsing.Download.WarningBypassed"));
}
void RecordDownloadOpened(download::DownloadDangerType danger_type,
download::DownloadContent download_content,
base::Time download_opened_time,
base::Time download_end_time,
bool show_download_in_folder) {
if (danger_type != download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) {
return;
}
std::string metric_suffix =
show_download_in_folder ? ".ShowInFolder" : ".OpenDirectly";
base::UmaHistogramCustomTimes(
"SBClientDownload.SafeDownloadOpenedLatency2" + metric_suffix,
/* sample */ download_opened_time - download_end_time,
/* min */ base::Seconds(1),
/* max */ base::Days(1), /* buckets */ 50);
RecordDownloadOpenedFileType(download_content, download_opened_time,
download_end_time);
}
void RecordDownloadOpenedFileType(download::DownloadContent download_content,
base::Time download_opened_time,
base::Time download_end_time) {
std::string download_content_str;
switch (download_content) {
case download::DownloadContent::UNRECOGNIZED:
download_content_str = "UNRECOGNIZED";
break;
case download::DownloadContent::TEXT:
download_content_str = "TEXT";
break;
case download::DownloadContent::IMAGE:
download_content_str = "IMAGE";
break;
case download::DownloadContent::AUDIO:
download_content_str = "AUDIO";
break;
case download::DownloadContent::VIDEO:
download_content_str = "VIDEO";
break;
case download::DownloadContent::OCTET_STREAM:
download_content_str = "OCTET_STREAM";
break;
case download::DownloadContent::PDF:
download_content_str = "PDF";
break;
case download::DownloadContent::DOCUMENT:
download_content_str = "DOCUMENT";
break;
case download::DownloadContent::SPREADSHEET:
download_content_str = "SPREADSHEET";
break;
case download::DownloadContent::PRESENTATION:
download_content_str = "PRESENTATION";
break;
case download::DownloadContent::ARCHIVE:
download_content_str = "ARCHIVE";
break;
case download::DownloadContent::EXECUTABLE:
download_content_str = "EXECUTABLE";
break;
case download::DownloadContent::DMG:
download_content_str = "DMG";
break;
case download::DownloadContent::CRX:
download_content_str = "CRX";
break;
case download::DownloadContent::WEB:
download_content_str = "WEB";
break;
case download::DownloadContent::EBOOK:
download_content_str = "EBOOK";
break;
case download::DownloadContent::FONT:
download_content_str = "FONT";
break;
case download::DownloadContent::APK:
download_content_str = "APK";
break;
case download::DownloadContent::MAX:
download_content_str = "MAX";
break;
}
base::UmaHistogramCustomTimes(
"SBClientDownload.SafeDownloadOpenedLatencyByContentType." +
download_content_str,
/* sample */ download_opened_time - download_end_time,
/* min */ base::Seconds(1),
/* max */ base::Days(1), /* buckets */ 50);
}
void RecordDownloadFileTypeAttributes(
DownloadFileType::DangerLevel danger_level,
bool has_user_gesture,
bool visited_referrer_before,
absl::optional<base::Time> last_bypass_time) {
if (danger_level != DownloadFileType::ALLOW_ON_USER_GESTURE) {
return;
}
base::UmaHistogramEnumeration(
"SBClientDownload.UserGestureFileType.Attributes",
UserGestureFileTypeAttributes::TOTAL_TYPE_CHECKED);
if (has_user_gesture) {
base::UmaHistogramEnumeration(
"SBClientDownload.UserGestureFileType.Attributes",
UserGestureFileTypeAttributes::HAS_USER_GESTURE);
}
if (visited_referrer_before) {
base::UmaHistogramEnumeration(
"SBClientDownload.UserGestureFileType.Attributes",
UserGestureFileTypeAttributes::HAS_REFERRER_VISIT);
}
if (has_user_gesture && visited_referrer_before) {
base::UmaHistogramEnumeration(
"SBClientDownload.UserGestureFileType.Attributes",
UserGestureFileTypeAttributes::
HAS_BOTH_USER_GESTURE_AND_REFERRER_VISIT);
}
if (last_bypass_time) {
base::UmaHistogramEnumeration(
"SBClientDownload.UserGestureFileType.Attributes",
UserGestureFileTypeAttributes::HAS_BYPASSED_DOWNLOAD_WARNING);
base::UmaHistogramCustomTimes(
"SBClientDownload.UserGestureFileType.LastBypassDownloadInterval",
/* sample */ base::Time::Now() - last_bypass_time.value(),
/* min */ base::Seconds(1),
/* max */ base::Days(1), /* buckets */ 50);
}
}
} // namespace safe_browsing