• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 
6 #include "chrome/browser/download/download_safe_browsing_client.h"
7 
8 #include "base/command_line.h"
9 #include "base/logging.h"
10 #include "base/metrics/histogram.h"
11 #include "base/metrics/stats_counters.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/download/download_manager.h"
14 #include "chrome/browser/history/download_create_info.h"
15 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
16 #include "chrome/common/chrome_switches.h"
17 #include "content/browser/browser_thread.h"
18 #include "content/browser/renderer_host/resource_dispatcher_host.h"
19 
20 // TODO(lzheng): Get rid of the AddRef and Release after
21 // SafeBrowsingService::Client is changed to RefCountedThreadSafe<>.
22 
DownloadSBClient(int32 download_id,const std::vector<GURL> & url_chain,const GURL & referrer_url)23 DownloadSBClient::DownloadSBClient(int32 download_id,
24                                    const std::vector<GURL>& url_chain,
25                                    const GURL& referrer_url)
26   : info_(NULL),
27     download_id_(download_id),
28     url_chain_(url_chain),
29     referrer_url_(referrer_url) {
30   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
31   DCHECK(!url_chain.empty());
32   ResourceDispatcherHost* rdh = g_browser_process->resource_dispatcher_host();
33   if (rdh)
34     sb_service_ = rdh->safe_browsing_service();
35 }
36 
~DownloadSBClient()37 DownloadSBClient::~DownloadSBClient() {}
38 
CheckDownloadUrl(DownloadCreateInfo * info,UrlDoneCallback * callback)39 void DownloadSBClient::CheckDownloadUrl(DownloadCreateInfo* info,
40                                         UrlDoneCallback* callback) {
41   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
42   // It is not allowed to call this method twice.
43   CHECK(!url_done_callback_.get() && !hash_done_callback_.get());
44   CHECK(callback);
45   CHECK(info);
46 
47   info_ = info;
48   start_time_ = base::TimeTicks::Now();
49   url_done_callback_.reset(callback);
50   BrowserThread::PostTask(
51       BrowserThread::IO, FROM_HERE,
52       NewRunnableMethod(this,
53                         &DownloadSBClient::CheckDownloadUrlOnIOThread,
54                         info->url_chain));
55 }
56 
CheckDownloadHash(const std::string & hash,HashDoneCallback * callback)57 void DownloadSBClient::CheckDownloadHash(const std::string& hash,
58                                          HashDoneCallback* callback) {
59   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
60   // It is not allowed to call this method twice.
61   CHECK(!url_done_callback_.get() && !hash_done_callback_.get());
62   CHECK(callback);
63 
64   start_time_ = base::TimeTicks::Now();
65   hash_done_callback_.reset(callback);
66   BrowserThread::PostTask(
67       BrowserThread::IO, FROM_HERE,
68       NewRunnableMethod(this,
69                         &DownloadSBClient::CheckDownloadHashOnIOThread,
70                         hash));
71 }
72 
CheckDownloadUrlOnIOThread(const std::vector<GURL> & url_chain)73 void DownloadSBClient::CheckDownloadUrlOnIOThread(
74     const std::vector<GURL>& url_chain) {
75   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
76 
77   // Will be released in OnDownloadUrlCheckResult.
78   AddRef();
79   if (sb_service_.get() && !sb_service_->CheckDownloadUrl(url_chain, this)) {
80     // Wait for SafeBrowsingService to call back OnDownloadUrlCheckResult.
81     return;
82   }
83   OnDownloadUrlCheckResult(url_chain, SafeBrowsingService::SAFE);
84 }
85 
86 // The callback interface for SafeBrowsingService::Client.
87 // Called when the result of checking a download URL is known.
OnDownloadUrlCheckResult(const std::vector<GURL> & url_chain,SafeBrowsingService::UrlCheckResult result)88 void DownloadSBClient::OnDownloadUrlCheckResult(
89     const std::vector<GURL>& url_chain,
90     SafeBrowsingService::UrlCheckResult result) {
91   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
92   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
93       NewRunnableMethod(this,
94                         &DownloadSBClient::SafeBrowsingCheckUrlDone,
95                         result));
96   Release();
97 }
98 
CheckDownloadHashOnIOThread(const std::string & hash)99 void DownloadSBClient::CheckDownloadHashOnIOThread(const std::string& hash) {
100   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
101   // Will be released in OnDownloadUrlCheckResult.
102   AddRef();
103   if (sb_service_.get() && !sb_service_->CheckDownloadHash(hash, this)) {
104     // Wait for SafeBrowsingService to call back OnDownloadUrlCheckResult.
105     return;
106   }
107   OnDownloadHashCheckResult(hash, SafeBrowsingService::SAFE);
108 }
109 
110 // The callback interface for SafeBrowsingService::Client.
111 // Called when the result of checking a download URL is known.
OnDownloadHashCheckResult(const std::string & hash,SafeBrowsingService::UrlCheckResult result)112 void DownloadSBClient::OnDownloadHashCheckResult(
113     const std::string& hash, SafeBrowsingService::UrlCheckResult result) {
114   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
115   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
116       NewRunnableMethod(this,
117                         &DownloadSBClient::SafeBrowsingCheckHashDone,
118                         result));
119   Release();
120 }
121 
SafeBrowsingCheckUrlDone(SafeBrowsingService::UrlCheckResult result)122 void DownloadSBClient::SafeBrowsingCheckUrlDone(
123     SafeBrowsingService::UrlCheckResult result) {
124   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
125   DVLOG(1) << "SafeBrowsingCheckUrlDone with result: " << result;
126 
127   bool is_dangerous = result != SafeBrowsingService::SAFE;
128   url_done_callback_->Run(info_, is_dangerous);
129 
130   if (sb_service_.get() && sb_service_->download_protection_enabled()) {
131     UMA_HISTOGRAM_TIMES("SB2.DownloadUrlCheckDuration",
132                         base::TimeTicks::Now() - start_time_);
133     UpdateDownloadCheckStats(DOWNLOAD_URL_CHECKS_TOTAL);
134     if (is_dangerous) {
135       UpdateDownloadCheckStats(DOWNLOAD_URL_CHECKS_MALWARE);
136       ReportMalware(result);
137     }
138   }
139 }
140 
SafeBrowsingCheckHashDone(SafeBrowsingService::UrlCheckResult result)141 void DownloadSBClient::SafeBrowsingCheckHashDone(
142     SafeBrowsingService::UrlCheckResult result) {
143   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
144   DVLOG(1) << "SafeBrowsingCheckHashDone with result: " << result;
145 
146   bool is_dangerous = result != SafeBrowsingService::SAFE;
147   hash_done_callback_->Run(download_id_, is_dangerous);
148 
149   if (sb_service_.get() && sb_service_->download_protection_enabled()) {
150     UMA_HISTOGRAM_TIMES("SB2.DownloadHashCheckDuration",
151                         base::TimeTicks::Now() - start_time_);
152     UpdateDownloadCheckStats(DOWNLOAD_HASH_CHECKS_TOTAL);
153     if (is_dangerous) {
154       UpdateDownloadCheckStats(DOWNLOAD_HASH_CHECKS_MALWARE);
155       ReportMalware(result);
156     }
157   }
158 }
159 
ReportMalware(SafeBrowsingService::UrlCheckResult result)160 void DownloadSBClient::ReportMalware(
161     SafeBrowsingService::UrlCheckResult result) {
162   std::string post_data;
163   for (size_t i = 0; i < url_chain_.size(); ++i)
164     post_data += url_chain_[i].spec() + "\n";
165 
166   sb_service_->ReportSafeBrowsingHit(url_chain_.back(),  // malicious_url
167                                      url_chain_.front(), // page_url
168                                      referrer_url_,
169                                      true,
170                                      result,
171                                      post_data);
172 }
173 
UpdateDownloadCheckStats(SBStatsType stat_type)174 void DownloadSBClient::UpdateDownloadCheckStats(SBStatsType stat_type) {
175   UMA_HISTOGRAM_ENUMERATION("SB2.DownloadChecks",
176                             stat_type,
177                             DOWNLOAD_CHECKS_MAX);
178 }
179