Home | History | Annotate | Download | only in domain_reliability
      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 "components/domain_reliability/uploader.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/callback.h"
      9 #include "base/memory/scoped_vector.h"
     10 #include "base/metrics/sparse_histogram.h"
     11 #include "base/stl_util.h"
     12 #include "base/supports_user_data.h"
     13 #include "net/base/load_flags.h"
     14 #include "net/url_request/url_fetcher.h"
     15 #include "net/url_request/url_fetcher_delegate.h"
     16 #include "net/url_request/url_request_context_getter.h"
     17 
     18 namespace domain_reliability {
     19 
     20 namespace {
     21 
     22 const char* kJsonMimeType = "application/json; charset=utf-8";
     23 
     24 class UploadUserData : public base::SupportsUserData::Data {
     25  public:
     26   static net::URLFetcher::CreateDataCallback CreateCreateDataCallback() {
     27     return base::Bind(&UploadUserData::CreateUploadUserData);
     28   }
     29 
     30   static const void* kUserDataKey;
     31 
     32  private:
     33   static base::SupportsUserData::Data* CreateUploadUserData() {
     34     return new UploadUserData();
     35   }
     36 };
     37 
     38 const void* UploadUserData::kUserDataKey =
     39     static_cast<const void*>(&UploadUserData::kUserDataKey);
     40 
     41 class DomainReliabilityUploaderImpl
     42     : public DomainReliabilityUploader, net::URLFetcherDelegate {
     43  public:
     44   DomainReliabilityUploaderImpl(const scoped_refptr<
     45       net::URLRequestContextGetter>& url_request_context_getter)
     46       : url_request_context_getter_(url_request_context_getter),
     47         discard_uploads_(true) {}
     48 
     49   virtual ~DomainReliabilityUploaderImpl() {
     50     // Delete any in-flight URLFetchers.
     51     STLDeleteContainerPairFirstPointers(
     52         upload_callbacks_.begin(), upload_callbacks_.end());
     53   }
     54 
     55   // DomainReliabilityUploader implementation:
     56   virtual void UploadReport(
     57       const std::string& report_json,
     58       const GURL& upload_url,
     59       const DomainReliabilityUploader::UploadCallback& callback) OVERRIDE {
     60     VLOG(1) << "Uploading report to " << upload_url;
     61     VLOG(2) << "Report JSON: " << report_json;
     62 
     63     if (discard_uploads_) {
     64       VLOG(1) << "Discarding report instead of uploading.";
     65       callback.Run(true);
     66       return;
     67     }
     68 
     69     net::URLFetcher* fetcher =
     70         net::URLFetcher::Create(0, upload_url, net::URLFetcher::POST, this);
     71     fetcher->SetRequestContext(url_request_context_getter_.get());
     72     fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
     73                           net::LOAD_DO_NOT_SAVE_COOKIES);
     74     fetcher->SetUploadData(kJsonMimeType, report_json);
     75     fetcher->SetAutomaticallyRetryOn5xx(false);
     76     fetcher->SetURLRequestUserData(
     77         UploadUserData::kUserDataKey,
     78         UploadUserData::CreateCreateDataCallback());
     79     fetcher->Start();
     80 
     81     upload_callbacks_[fetcher] = callback;
     82   }
     83 
     84   virtual void set_discard_uploads(bool discard_uploads) OVERRIDE {
     85     discard_uploads_ = discard_uploads;
     86     VLOG(1) << "Setting discard_uploads to " << discard_uploads;
     87   }
     88 
     89   // net::URLFetcherDelegate implementation:
     90   virtual void OnURLFetchComplete(
     91       const net::URLFetcher* fetcher) OVERRIDE {
     92     DCHECK(fetcher);
     93 
     94     UploadCallbackMap::iterator callback_it = upload_callbacks_.find(fetcher);
     95     DCHECK(callback_it != upload_callbacks_.end());
     96 
     97     VLOG(1) << "Upload finished with " << fetcher->GetResponseCode();
     98 
     99     UMA_HISTOGRAM_SPARSE_SLOWLY("DomainReliability.UploadResponseCode",
    100                                 fetcher->GetResponseCode());
    101 
    102     bool success = fetcher->GetResponseCode() == 200;
    103     callback_it->second.Run(success);
    104 
    105     delete callback_it->first;
    106     upload_callbacks_.erase(callback_it);
    107   }
    108 
    109  private:
    110   using DomainReliabilityUploader::UploadCallback;
    111   typedef std::map<const net::URLFetcher*, UploadCallback> UploadCallbackMap;
    112 
    113   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
    114   UploadCallbackMap upload_callbacks_;
    115   bool discard_uploads_;
    116 };
    117 
    118 }  // namespace
    119 
    120 DomainReliabilityUploader::DomainReliabilityUploader() {}
    121 DomainReliabilityUploader::~DomainReliabilityUploader() {}
    122 
    123 // static
    124 scoped_ptr<DomainReliabilityUploader> DomainReliabilityUploader::Create(
    125     const scoped_refptr<net::URLRequestContextGetter>&
    126         url_request_context_getter) {
    127   return scoped_ptr<DomainReliabilityUploader>(
    128       new DomainReliabilityUploaderImpl(url_request_context_getter));
    129 }
    130 
    131 // static
    132 bool DomainReliabilityUploader::URLRequestIsUpload(
    133     const net::URLRequest& request) {
    134   return request.GetUserData(UploadUserData::kUserDataKey) != NULL;
    135 }
    136 
    137 }  // namespace domain_reliability
    138