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.
4 
5 #include "chrome/browser/download/download_danger_prompt.h"
6 
7 #include "base/macros.h"
8 #include "base/metrics/histogram_functions.h"
9 #include "base/strings/stringprintf.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/safe_browsing/download_protection/download_protection_service.h"
12 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
13 #include "components/download/public/common/download_danger_type.h"
14 #include "components/download/public/common/download_item.h"
15 #include "components/safe_browsing/core/file_type_policies.h"
16 #include "content/public/browser/download_item_utils.h"
17 
18 using safe_browsing::ClientDownloadResponse;
19 using safe_browsing::ClientSafeBrowsingReportRequest;
20 
21 namespace {
22 
23 const char kDownloadDangerPromptPrefix[] = "Download.DownloadDangerPrompt";
24 
25 // Converts DownloadDangerType into their corresponding string.
GetDangerTypeString(const download::DownloadDangerType & danger_type)26 const char* GetDangerTypeString(
27     const download::DownloadDangerType& danger_type) {
28   switch (danger_type) {
29     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
30       return "DangerousFile";
31     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
32       return "DangerousURL";
33     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
34       return "DangerousContent";
35     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
36       return "DangerousHost";
37     case download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
38       return "UncommonContent";
39     case download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
40       return "PotentiallyUnwanted";
41     case download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING:
42       return "AsyncScanning";
43     case download::DOWNLOAD_DANGER_TYPE_BLOCKED_PASSWORD_PROTECTED:
44       return "BlockedPasswordProtected";
45     case download::DOWNLOAD_DANGER_TYPE_BLOCKED_TOO_LARGE:
46       return "BlockedTooLarge";
47     case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_WARNING:
48       return "SensitiveContentWarning";
49     case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_BLOCK:
50       return "SensitiveContentBlock";
51     case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_SAFE:
52       return "DeepScannedSafe";
53     case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_OPENED_DANGEROUS:
54       return "DeepScannedOpenedDangerous";
55     case download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING:
56       return "PromptForScanning";
57     case download::DOWNLOAD_DANGER_TYPE_BLOCKED_UNSUPPORTED_FILETYPE:
58       return "BlockedUnsupportedFiletype";
59     case download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
60     case download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
61     case download::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
62     case download::DOWNLOAD_DANGER_TYPE_WHITELISTED_BY_POLICY:
63     case download::DOWNLOAD_DANGER_TYPE_MAX:
64       break;
65   }
66   NOTREACHED();
67   return nullptr;
68 }
69 
70 }  // namespace
71 
SendSafeBrowsingDownloadReport(ClientSafeBrowsingReportRequest::ReportType report_type,bool did_proceed,const download::DownloadItem & download)72 void DownloadDangerPrompt::SendSafeBrowsingDownloadReport(
73     ClientSafeBrowsingReportRequest::ReportType report_type,
74     bool did_proceed,
75     const download::DownloadItem& download) {
76   safe_browsing::SafeBrowsingService* sb_service =
77       g_browser_process->safe_browsing_service();
78   Profile* profile = Profile::FromBrowserContext(
79       content::DownloadItemUtils::GetBrowserContext(&download));
80   ClientSafeBrowsingReportRequest report;
81   report.set_type(report_type);
82   switch (download.GetDangerType()) {
83     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
84     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
85       report.set_download_verdict(ClientDownloadResponse::DANGEROUS);
86       break;
87     case download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
88       report.set_download_verdict(ClientDownloadResponse::UNCOMMON);
89       break;
90     case download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
91       report.set_download_verdict(ClientDownloadResponse::POTENTIALLY_UNWANTED);
92       break;
93     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
94       report.set_download_verdict(ClientDownloadResponse::DANGEROUS_HOST);
95       break;
96     default:  // Don't send report for any other danger types.
97       return;
98   }
99   report.set_url(download.GetURL().spec());
100   report.set_did_proceed(did_proceed);
101   std::string token =
102     safe_browsing::DownloadProtectionService::GetDownloadPingToken(
103         &download);
104   if (!token.empty())
105     report.set_token(token);
106   std::string serialized_report;
107   if (report.SerializeToString(&serialized_report))
108     sb_service->SendSerializedDownloadReport(profile, serialized_report);
109   else
110     DLOG(ERROR) << "Unable to serialize the threat report.";
111 }
112 
RecordDownloadDangerPrompt(bool did_proceed,const download::DownloadItem & download)113 void DownloadDangerPrompt::RecordDownloadDangerPrompt(
114     bool did_proceed,
115     const download::DownloadItem& download) {
116   int64_t file_type_uma_value =
117       safe_browsing::FileTypePolicies::GetInstance()->UmaValueForFile(
118           download.GetTargetFilePath());
119   download::DownloadDangerType danger_type = download.GetDangerType();
120 
121   base::UmaHistogramSparse(
122       base::StringPrintf("%s.%s.Shown", kDownloadDangerPromptPrefix,
123                          GetDangerTypeString(danger_type)),
124       file_type_uma_value);
125   if (did_proceed) {
126     base::UmaHistogramSparse(
127         base::StringPrintf("%s.%s.Proceed", kDownloadDangerPromptPrefix,
128                            GetDangerTypeString(danger_type)),
129         file_type_uma_value);
130   }
131 }
132