Home | History | Annotate | Download | only in safe_browsing
      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/safe_browsing/ping_manager.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/stl_util.h"
      9 #include "base/strings/string_util.h"
     10 #include "base/strings/stringprintf.h"
     11 #include "chrome/common/env_vars.h"
     12 #include "content/public/browser/browser_thread.h"
     13 #include "google_apis/google_api_keys.h"
     14 #include "net/base/escape.h"
     15 #include "net/base/load_flags.h"
     16 #include "net/url_request/url_fetcher.h"
     17 #include "net/url_request/url_request_context_getter.h"
     18 #include "net/url_request/url_request_status.h"
     19 
     20 using content::BrowserThread;
     21 
     22 // SafeBrowsingPingManager implementation ----------------------------------
     23 
     24 // static
     25 SafeBrowsingPingManager* SafeBrowsingPingManager::Create(
     26     net::URLRequestContextGetter* request_context_getter,
     27     const SafeBrowsingProtocolConfig& config) {
     28   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     29   return new SafeBrowsingPingManager(request_context_getter, config);
     30 }
     31 
     32 SafeBrowsingPingManager::SafeBrowsingPingManager(
     33     net::URLRequestContextGetter* request_context_getter,
     34     const SafeBrowsingProtocolConfig& config)
     35     : client_name_(config.client_name),
     36       request_context_getter_(request_context_getter),
     37       url_prefix_(config.url_prefix) {
     38   DCHECK(!url_prefix_.empty());
     39 
     40   version_ = SafeBrowsingProtocolManagerHelper::Version();
     41 }
     42 
     43 SafeBrowsingPingManager::~SafeBrowsingPingManager() {
     44   // Delete in-progress safebrowsing reports (hits and details).
     45   STLDeleteContainerPointers(safebrowsing_reports_.begin(),
     46                              safebrowsing_reports_.end());
     47 }
     48 
     49 // net::URLFetcherDelegate implementation ----------------------------------
     50 
     51 // All SafeBrowsing request responses are handled here.
     52 void SafeBrowsingPingManager::OnURLFetchComplete(
     53     const net::URLFetcher* source) {
     54   Reports::iterator sit = safebrowsing_reports_.find(source);
     55   DCHECK(sit != safebrowsing_reports_.end());
     56   delete *sit;
     57   safebrowsing_reports_.erase(sit);
     58 }
     59 
     60 // Sends a SafeBrowsing "hit" for UMA users.
     61 void SafeBrowsingPingManager::ReportSafeBrowsingHit(
     62     const GURL& malicious_url,
     63     const GURL& page_url,
     64     const GURL& referrer_url,
     65     bool is_subresource,
     66     SBThreatType threat_type,
     67     const std::string& post_data) {
     68   GURL report_url = SafeBrowsingHitUrl(malicious_url, page_url,
     69                                        referrer_url, is_subresource,
     70                                        threat_type);
     71   net::URLFetcher* report = net::URLFetcher::Create(
     72       report_url,
     73       post_data.empty() ? net::URLFetcher::GET : net::URLFetcher::POST,
     74       this);
     75   report->SetLoadFlags(net::LOAD_DISABLE_CACHE);
     76   report->SetRequestContext(request_context_getter_.get());
     77   if (!post_data.empty())
     78     report->SetUploadData("text/plain", post_data);
     79   safebrowsing_reports_.insert(report);
     80   report->Start();
     81 }
     82 
     83 // Sends malware details for users who opt-in.
     84 void SafeBrowsingPingManager::ReportMalwareDetails(
     85     const std::string& report) {
     86   GURL report_url = MalwareDetailsUrl();
     87   net::URLFetcher* fetcher = net::URLFetcher::Create(
     88       report_url, net::URLFetcher::POST, this);
     89   fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE);
     90   fetcher->SetRequestContext(request_context_getter_.get());
     91   fetcher->SetUploadData("application/octet-stream", report);
     92   // Don't try too hard to send reports on failures.
     93   fetcher->SetAutomaticallyRetryOn5xx(false);
     94   fetcher->Start();
     95   safebrowsing_reports_.insert(fetcher);
     96 }
     97 
     98 GURL SafeBrowsingPingManager::SafeBrowsingHitUrl(
     99     const GURL& malicious_url, const GURL& page_url,
    100     const GURL& referrer_url, bool is_subresource,
    101     SBThreatType threat_type) const {
    102   DCHECK(threat_type == SB_THREAT_TYPE_URL_MALWARE ||
    103          threat_type == SB_THREAT_TYPE_URL_PHISHING ||
    104          threat_type == SB_THREAT_TYPE_BINARY_MALWARE_URL ||
    105          threat_type == SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL ||
    106          threat_type == SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL);
    107   std::string url = SafeBrowsingProtocolManagerHelper::ComposeUrl(
    108       url_prefix_, "report", client_name_, version_, std::string());
    109   std::string threat_list = "none";
    110   switch (threat_type) {
    111     case SB_THREAT_TYPE_URL_MALWARE:
    112       threat_list = "malblhit";
    113       break;
    114     case SB_THREAT_TYPE_URL_PHISHING:
    115       threat_list = "phishblhit";
    116       break;
    117     case SB_THREAT_TYPE_BINARY_MALWARE_URL:
    118       threat_list = "binurlhit";
    119       break;
    120     case SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL:
    121       threat_list = "phishcsdhit";
    122       break;
    123     case SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL:
    124       threat_list = "malcsdhit";
    125       break;
    126     default:
    127       NOTREACHED();
    128   }
    129   return GURL(base::StringPrintf("%s&evts=%s&evtd=%s&evtr=%s&evhr=%s&evtb=%d",
    130       url.c_str(), threat_list.c_str(),
    131       net::EscapeQueryParamValue(malicious_url.spec(), true).c_str(),
    132       net::EscapeQueryParamValue(page_url.spec(), true).c_str(),
    133       net::EscapeQueryParamValue(referrer_url.spec(), true).c_str(),
    134       is_subresource));
    135 }
    136 
    137 GURL SafeBrowsingPingManager::MalwareDetailsUrl() const {
    138   std::string url = base::StringPrintf(
    139           "%s/clientreport/malware?client=%s&appver=%s&pver=1.0",
    140           url_prefix_.c_str(),
    141           client_name_.c_str(),
    142           version_.c_str());
    143   std::string api_key = google_apis::GetAPIKey();
    144   if (!api_key.empty()) {
    145     base::StringAppendF(&url, "&key=%s",
    146                         net::EscapeQueryParamValue(api_key, true).c_str());
    147   }
    148   return GURL(url);
    149 }
    150