Home | History | Annotate | Download | only in 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 
     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 
     37 DownloadSBClient::~DownloadSBClient() {}
     38 
     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 
     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 
     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.
     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 
     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.
    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 
    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 
    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 
    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 
    174 void DownloadSBClient::UpdateDownloadCheckStats(SBStatsType stat_type) {
    175   UMA_HISTOGRAM_ENUMERATION("SB2.DownloadChecks",
    176                             stat_type,
    177                             DOWNLOAD_CHECKS_MAX);
    178 }
    179