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 15namespace safe_browsing { 16 17namespace { 18 19const 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 27const int IncidentReportUploaderImpl::kTestUrlFetcherId = 47; 28 29IncidentReportUploaderImpl::~IncidentReportUploaderImpl() { 30} 31 32// static 33scoped_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 44IncidentReportUploaderImpl::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 63GURL 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 71void 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