// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/safe_browsing/incident_report_uploader_impl.h" #include "base/metrics/histogram.h" #include "chrome/common/safe_browsing/csd.pb.h" #include "google_apis/google_api_keys.h" #include "net/base/escape.h" #include "net/base/load_flags.h" #include "net/http/http_status_code.h" #include "net/url_request/url_fetcher.h" namespace safe_browsing { namespace { const char kSbIncidentReportUrl[] = "https://sb-ssl.google.com/safebrowsing/clientreport/incident"; } // namespace // This is initialized here rather than in the class definition due to an // "extension" in MSVC that defies the standard. // static const int IncidentReportUploaderImpl::kTestUrlFetcherId = 47; IncidentReportUploaderImpl::~IncidentReportUploaderImpl() { } // static scoped_ptr IncidentReportUploaderImpl::UploadReport( const OnResultCallback& callback, const scoped_refptr& request_context_getter, const ClientIncidentReport& report) { std::string post_data; if (!report.SerializeToString(&post_data)) return scoped_ptr(); return scoped_ptr(new IncidentReportUploaderImpl( callback, request_context_getter, post_data)); } IncidentReportUploaderImpl::IncidentReportUploaderImpl( const OnResultCallback& callback, const scoped_refptr& request_context_getter, const std::string& post_data) : IncidentReportUploader(callback), url_fetcher_(net::URLFetcher::Create(kTestUrlFetcherId, GetIncidentReportUrl(), net::URLFetcher::POST, this)), time_begin_(base::TimeTicks::Now()) { UMA_HISTOGRAM_COUNTS("SBIRS.ReportPayloadSize", post_data.size()); url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE); url_fetcher_->SetAutomaticallyRetryOn5xx(false); url_fetcher_->SetRequestContext(request_context_getter.get()); url_fetcher_->SetUploadData("application/octet-stream", post_data); url_fetcher_->Start(); } // static GURL IncidentReportUploaderImpl::GetIncidentReportUrl() { GURL url(kSbIncidentReportUrl); std::string api_key(google_apis::GetAPIKey()); if (api_key.empty()) return url; return url.Resolve("?key=" + net::EscapeQueryParamValue(api_key, true)); } void IncidentReportUploaderImpl::OnURLFetchComplete( const net::URLFetcher* source) { // Take ownership of the fetcher in this scope (source == url_fetcher_). scoped_ptr url_fetcher(url_fetcher_.Pass()); UMA_HISTOGRAM_TIMES("SBIRS.ReportUploadTime", base::TimeTicks::Now() - time_begin_); Result result = UPLOAD_REQUEST_FAILED; scoped_ptr response; if (source->GetStatus().is_success() && source->GetResponseCode() == net::HTTP_OK) { std::string data; source->GetResponseAsString(&data); response.reset(new ClientIncidentResponse()); if (!response->ParseFromString(data)) { response.reset(); result = UPLOAD_INVALID_RESPONSE; } else { result = UPLOAD_SUCCESS; } } // Callbacks have a tendency to delete the uploader, so no touching anything // after this. callback_.Run(result, response.Pass()); } } // namespace safe_browsing