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 48 virtual ~DomainReliabilityUploaderImpl() { 49 // Delete any in-flight URLFetchers. 50 STLDeleteContainerPairFirstPointers( 51 upload_callbacks_.begin(), upload_callbacks_.end()); 52 } 53 54 // DomainReliabilityUploader implementation: 55 virtual void UploadReport( 56 const std::string& report_json, 57 const GURL& upload_url, 58 const DomainReliabilityUploader::UploadCallback& callback) OVERRIDE { 59 VLOG(1) << "Uploading report to " << upload_url; 60 VLOG(2) << "Report JSON: " << report_json; 61 62 net::URLFetcher* fetcher = 63 net::URLFetcher::Create(0, upload_url, net::URLFetcher::POST, this); 64 fetcher->SetRequestContext(url_request_context_getter_); 65 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 66 net::LOAD_DO_NOT_SAVE_COOKIES); 67 fetcher->SetUploadData(kJsonMimeType, report_json); 68 fetcher->SetAutomaticallyRetryOn5xx(false); 69 fetcher->SetURLRequestUserData( 70 UploadUserData::kUserDataKey, 71 UploadUserData::CreateCreateDataCallback()); 72 fetcher->Start(); 73 74 upload_callbacks_[fetcher] = callback; 75 } 76 77 // net::URLFetcherDelegate implementation: 78 virtual void OnURLFetchComplete( 79 const net::URLFetcher* fetcher) OVERRIDE { 80 DCHECK(fetcher); 81 82 UploadCallbackMap::iterator callback_it = upload_callbacks_.find(fetcher); 83 DCHECK(callback_it != upload_callbacks_.end()); 84 85 VLOG(1) << "Upload finished with " << fetcher->GetResponseCode(); 86 87 UMA_HISTOGRAM_SPARSE_SLOWLY("DomainReliability.UploadResponseCode", 88 fetcher->GetResponseCode()); 89 90 bool success = fetcher->GetResponseCode() == 200; 91 callback_it->second.Run(success); 92 93 delete callback_it->first; 94 upload_callbacks_.erase(callback_it); 95 } 96 97 private: 98 using DomainReliabilityUploader::UploadCallback; 99 typedef std::map<const net::URLFetcher*, UploadCallback> UploadCallbackMap; 100 101 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; 102 UploadCallbackMap upload_callbacks_; 103 }; 104 105 } // namespace 106 107 DomainReliabilityUploader::DomainReliabilityUploader() {} 108 DomainReliabilityUploader::~DomainReliabilityUploader() {} 109 110 // static 111 scoped_ptr<DomainReliabilityUploader> DomainReliabilityUploader::Create( 112 const scoped_refptr<net::URLRequestContextGetter>& 113 url_request_context_getter) { 114 return scoped_ptr<DomainReliabilityUploader>( 115 new DomainReliabilityUploaderImpl(url_request_context_getter)); 116 } 117 118 // static 119 bool DomainReliabilityUploader::URLRequestIsUpload( 120 const net::URLRequest& request) { 121 return request.GetUserData(UploadUserData::kUserDataKey) != NULL; 122 } 123 124 } // namespace domain_reliability 125