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.
5 #include "chrome/browser/safe_browsing/ping_manager.h"
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"
20 using content::BrowserThread
;
22 // SafeBrowsingPingManager implementation ----------------------------------
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
);
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());
40 version_
= SafeBrowsingProtocolManagerHelper::Version();
43 SafeBrowsingPingManager::~SafeBrowsingPingManager() {
44 // Delete in-progress safebrowsing reports (hits and details).
45 STLDeleteContainerPointers(safebrowsing_reports_
.begin(),
46 safebrowsing_reports_
.end());
49 // net::URLFetcherDelegate implementation ----------------------------------
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());
57 safebrowsing_reports_
.erase(sit
);
60 // Sends a SafeBrowsing "hit" for UMA users.
61 void SafeBrowsingPingManager::ReportSafeBrowsingHit(
62 const GURL
& malicious_url
,
64 const GURL
& referrer_url
,
66 SBThreatType threat_type
,
67 const std::string
& post_data
) {
68 GURL report_url
= SafeBrowsingHitUrl(malicious_url
, page_url
,
69 referrer_url
, is_subresource
,
71 net::URLFetcher
* report
= net::URLFetcher::Create(
73 post_data
.empty() ? net::URLFetcher::GET
: net::URLFetcher::POST
,
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
);
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);
95 safebrowsing_reports_
.insert(fetcher
);
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";
114 case SB_THREAT_TYPE_URL_PHISHING
:
115 threat_list
= "phishblhit";
117 case SB_THREAT_TYPE_BINARY_MALWARE_URL
:
118 threat_list
= "binurlhit";
120 case SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL
:
121 threat_list
= "phishcsdhit";
123 case SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL
:
124 threat_list
= "malcsdhit";
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(),
137 GURL
SafeBrowsingPingManager::MalwareDetailsUrl() const {
138 std::string url
= base::StringPrintf(
139 "%s/clientreport/malware?client=%s&appver=%s&pver=1.0",
141 client_name_
.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());