Home | History | Annotate | Download | only in incident_reporting
      1 // Copyright 2014 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/incident_reporting/incident_report_uploader_impl.h"
      6 
      7 #include "base/metrics/histogram.h"
      8 #include "chrome/common/safe_browsing/csd.pb.h"
      9 #include "google_apis/google_api_keys.h"
     10 #include "net/base/escape.h"
     11 #include "net/base/load_flags.h"
     12 #include "net/http/http_status_code.h"
     13 #include "net/url_request/url_fetcher.h"
     14 
     15 namespace safe_browsing {
     16 
     17 namespace {
     18 
     19 const char kSbIncidentReportUrl[] =
     20     "https://sb-ssl.google.com/safebrowsing/clientreport/incident";
     21 
     22 }  // namespace
     23 
     24 // This is initialized here rather than in the class definition due to an
     25 // "extension" in MSVC that defies the standard.
     26 // static
     27 const int IncidentReportUploaderImpl::kTestUrlFetcherId = 47;
     28 
     29 IncidentReportUploaderImpl::~IncidentReportUploaderImpl() {
     30 }
     31 
     32 // static
     33 scoped_ptr<IncidentReportUploader> IncidentReportUploaderImpl::UploadReport(
     34     const OnResultCallback& callback,
     35     const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
     36     const ClientIncidentReport& report) {
     37   std::string post_data;
     38   if (!report.SerializeToString(&post_data))
     39     return scoped_ptr<IncidentReportUploader>();
     40   return scoped_ptr<IncidentReportUploader>(new IncidentReportUploaderImpl(
     41       callback, request_context_getter, post_data));
     42 }
     43 
     44 IncidentReportUploaderImpl::IncidentReportUploaderImpl(
     45     const OnResultCallback& callback,
     46     const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
     47     const std::string& post_data)
     48     : IncidentReportUploader(callback),
     49       url_fetcher_(net::URLFetcher::Create(kTestUrlFetcherId,
     50                                            GetIncidentReportUrl(),
     51                                            net::URLFetcher::POST,
     52                                            this)),
     53       time_begin_(base::TimeTicks::Now()) {
     54   UMA_HISTOGRAM_COUNTS("SBIRS.ReportPayloadSize", post_data.size());
     55   url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE);
     56   url_fetcher_->SetAutomaticallyRetryOn5xx(false);
     57   url_fetcher_->SetRequestContext(request_context_getter.get());
     58   url_fetcher_->SetUploadData("application/octet-stream", post_data);
     59   url_fetcher_->Start();
     60 }
     61 
     62 // static
     63 GURL IncidentReportUploaderImpl::GetIncidentReportUrl() {
     64   GURL url(kSbIncidentReportUrl);
     65   std::string api_key(google_apis::GetAPIKey());
     66   if (api_key.empty())
     67     return url;
     68   return url.Resolve("?key=" + net::EscapeQueryParamValue(api_key, true));
     69 }
     70 
     71 void IncidentReportUploaderImpl::OnURLFetchComplete(
     72     const net::URLFetcher* source) {
     73   // Take ownership of the fetcher in this scope (source == url_fetcher_).
     74   scoped_ptr<net::URLFetcher> url_fetcher(url_fetcher_.Pass());
     75 
     76   UMA_HISTOGRAM_TIMES("SBIRS.ReportUploadTime",
     77                       base::TimeTicks::Now() - time_begin_);
     78 
     79   Result result = UPLOAD_REQUEST_FAILED;
     80   scoped_ptr<ClientIncidentResponse> response;
     81 
     82   if (source->GetStatus().is_success() &&
     83       source->GetResponseCode() == net::HTTP_OK) {
     84     std::string data;
     85     source->GetResponseAsString(&data);
     86     response.reset(new ClientIncidentResponse());
     87     if (!response->ParseFromString(data)) {
     88       response.reset();
     89       result = UPLOAD_INVALID_RESPONSE;
     90     } else {
     91       result = UPLOAD_SUCCESS;
     92     }
     93   }
     94   // Callbacks have a tendency to delete the uploader, so no touching anything
     95   // after this.
     96   callback_.Run(result, response.Pass());
     97 }
     98 
     99 }  // namespace safe_browsing
    100