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