Report malware sub resources and their containing page to the
SafeBrowsing service for faster malware detection.

Any malware resource that we detect on a page is reported if
the page that contains it is not in the blacklist AND the user
has opted in to reporting stats.

BUG=7607 (http://crbug.com/7607)

Review URL: http://codereview.chromium.org/21474

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10042 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/safe_browsing/protocol_manager.cc b/chrome/browser/safe_browsing/protocol_manager.cc
index df83f8e..eb556c0 100644
--- a/chrome/browser/safe_browsing/protocol_manager.cc
+++ b/chrome/browser/safe_browsing/protocol_manager.cc
@@ -19,6 +19,7 @@
 #include "chrome/common/env_vars.h"
 #include "chrome/common/stl_util-inl.h"
 #include "net/base/base64.h"
+#include "net/base/escape.h"
 #include "net/base/load_flags.h"
 
 using base::Time;
@@ -39,6 +40,10 @@
 static const char* const kSbNewKeyUrl =
     "https://sb-ssl.google.com/safebrowsing/newkey?client=%s&appver=%s&pver=2.2";
 
+// URL for reporting malware pages.
+static const char* const kSbMalwareReportUrl =
+    "http://safebrowsing.clients.google.com/safebrowsing/report?evts=malblhit&evtd=%s&evtr=%s&evhr=%s&client=%s&appver=%s";
+
 #if defined(GOOGLE_CHROME_BUILD)
 static const char* const kSbClientName = "googlechrome";
 #else
@@ -89,6 +94,10 @@
   STLDeleteContainerPairFirstPointers(hash_requests_.begin(),
                                       hash_requests_.end());
   hash_requests_.clear();
+
+  // Delete in-progress malware reports.
+  STLDeleteContainerPointers(malware_reports_.begin(), malware_reports_.end());
+  malware_reports_.clear();
 }
 
 // Public API used by the SafeBrowsingService ----------------------------------
@@ -165,6 +174,16 @@
   bool parsed_ok = true;
   bool must_back_off = false;  // Reduce SafeBrowsing service query frequency.
 
+  // See if this is a malware report fetcher. We don't take any action for
+  // the response to those.
+  std::set<const URLFetcher*>::iterator mit = malware_reports_.find(source);
+  if (mit != malware_reports_.end()) {
+    const URLFetcher* report = *mit;
+    malware_reports_.erase(mit);
+    delete report;
+    return;
+  }
+
   HashRequests::iterator it = hash_requests_.find(source);
   if (it != hash_requests_.end()) {
     // GetHash response.
@@ -555,6 +574,24 @@
   }
 }
 
+void SafeBrowsingProtocolManager::ReportMalware(const GURL& malware_url,
+                                                const GURL& page_url,
+                                                const GURL& referrer_url) {
+  std::string report_str = StringPrintf(
+      kSbMalwareReportUrl,
+      EscapeQueryParamValue(malware_url.spec()).c_str(),
+      EscapeQueryParamValue(page_url.spec()).c_str(),
+      EscapeQueryParamValue(referrer_url.spec()).c_str(),
+      kSbClientName,
+      version_.c_str());
+  GURL report_url(report_str);
+  URLFetcher* report = new URLFetcher(report_url, URLFetcher::GET, this);
+  report->set_load_flags(net::LOAD_DISABLE_CACHE);
+  report->set_request_context(Profile::GetDefaultRequestContext());
+  report->Start();
+  malware_reports_.insert(report);
+}
+
 // static
 std::string SafeBrowsingProtocolManager::FormatList(
     const SBListChunkRanges& list, bool use_mac) {