Roll src/third_party/WebKit 9f7fb92:f103b33 (svn 202621:202622)
[chromium-blink-merge.git] / components / domain_reliability / uploader.cc
blob90952af3fb2118faba01aaf41ce356eea1d9fb8c
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.
5 #include "components/domain_reliability/uploader.h"
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/metrics/sparse_histogram.h"
10 #include "base/stl_util.h"
11 #include "base/supports_user_data.h"
12 #include "components/data_use_measurement/core/data_use_user_data.h"
13 #include "components/domain_reliability/util.h"
14 #include "net/base/load_flags.h"
15 #include "net/base/net_errors.h"
16 #include "net/http/http_response_headers.h"
17 #include "net/http/http_util.h"
18 #include "net/url_request/url_fetcher.h"
19 #include "net/url_request/url_fetcher_delegate.h"
20 #include "net/url_request/url_request_context_getter.h"
22 namespace domain_reliability {
24 namespace {
26 const char* kJsonMimeType = "application/json; charset=utf-8";
28 class UploadUserData : public base::SupportsUserData::Data {
29 public:
30 static net::URLFetcher::CreateDataCallback CreateCreateDataCallback() {
31 return base::Bind(&UploadUserData::CreateUploadUserData);
34 static const void* kUserDataKey;
36 private:
37 static base::SupportsUserData::Data* CreateUploadUserData() {
38 return new UploadUserData();
42 const void* UploadUserData::kUserDataKey =
43 static_cast<const void*>(&UploadUserData::kUserDataKey);
45 class DomainReliabilityUploaderImpl
46 : public DomainReliabilityUploader, net::URLFetcherDelegate {
47 public:
48 DomainReliabilityUploaderImpl(
49 MockableTime* time,
50 const scoped_refptr<
51 net::URLRequestContextGetter>& url_request_context_getter)
52 : time_(time),
53 url_request_context_getter_(url_request_context_getter),
54 discard_uploads_(true) {}
56 ~DomainReliabilityUploaderImpl() override {
57 // Delete any in-flight URLFetchers.
58 STLDeleteContainerPairFirstPointers(
59 upload_callbacks_.begin(), upload_callbacks_.end());
62 // DomainReliabilityUploader implementation:
63 void UploadReport(
64 const std::string& report_json,
65 const GURL& upload_url,
66 const DomainReliabilityUploader::UploadCallback& callback) override {
67 VLOG(1) << "Uploading report to " << upload_url;
68 VLOG(2) << "Report JSON: " << report_json;
70 if (discard_uploads_) {
71 VLOG(1) << "Discarding report instead of uploading.";
72 UploadResult result;
73 result.status = UploadResult::SUCCESS;
74 callback.Run(result);
75 return;
78 net::URLFetcher* fetcher =
79 net::URLFetcher::Create(0, upload_url, net::URLFetcher::POST, this)
80 .release();
81 data_use_measurement::DataUseUserData::AttachToFetcher(
82 fetcher, data_use_measurement::DataUseUserData::DOMAIN_RELIABILITY);
83 fetcher->SetRequestContext(url_request_context_getter_.get());
84 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
85 net::LOAD_DO_NOT_SAVE_COOKIES);
86 fetcher->SetUploadData(kJsonMimeType, report_json);
87 fetcher->SetAutomaticallyRetryOn5xx(false);
88 fetcher->SetURLRequestUserData(
89 UploadUserData::kUserDataKey,
90 UploadUserData::CreateCreateDataCallback());
91 fetcher->Start();
93 upload_callbacks_[fetcher] = callback;
96 void set_discard_uploads(bool discard_uploads) override {
97 discard_uploads_ = discard_uploads;
98 VLOG(1) << "Setting discard_uploads to " << discard_uploads;
101 // net::URLFetcherDelegate implementation:
102 void OnURLFetchComplete(const net::URLFetcher* fetcher) override {
103 DCHECK(fetcher);
105 UploadCallbackMap::iterator callback_it = upload_callbacks_.find(fetcher);
106 DCHECK(callback_it != upload_callbacks_.end());
108 int net_error = GetNetErrorFromURLRequestStatus(fetcher->GetStatus());
109 int http_response_code = fetcher->GetResponseCode();
110 base::TimeDelta retry_after;
112 std::string retry_after_string;
113 if (fetcher->GetResponseHeaders() &&
114 fetcher->GetResponseHeaders()->EnumerateHeader(nullptr,
115 "Retry-After",
116 &retry_after_string)) {
117 net::HttpUtil::ParseRetryAfterHeader(retry_after_string,
118 time_->Now(),
119 &retry_after);
123 VLOG(1) << "Upload finished with net error " << net_error
124 << ", response code " << http_response_code
125 << ", retry after " << retry_after;
127 UMA_HISTOGRAM_SPARSE_SLOWLY("DomainReliability.UploadResponseCode",
128 http_response_code);
129 UMA_HISTOGRAM_SPARSE_SLOWLY("DomainReliability.UploadNetError",
130 -net_error);
132 UploadResult result;
133 GetUploadResultFromResponseDetails(net_error,
134 http_response_code,
135 retry_after,
136 &result);
137 callback_it->second.Run(result);
139 delete callback_it->first;
140 upload_callbacks_.erase(callback_it);
143 private:
144 using DomainReliabilityUploader::UploadCallback;
145 typedef std::map<const net::URLFetcher*, UploadCallback> UploadCallbackMap;
147 MockableTime* time_;
148 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
149 UploadCallbackMap upload_callbacks_;
150 bool discard_uploads_;
153 } // namespace
155 DomainReliabilityUploader::DomainReliabilityUploader() {}
156 DomainReliabilityUploader::~DomainReliabilityUploader() {}
158 // static
159 scoped_ptr<DomainReliabilityUploader> DomainReliabilityUploader::Create(
160 MockableTime* time,
161 const scoped_refptr<net::URLRequestContextGetter>&
162 url_request_context_getter) {
163 return scoped_ptr<DomainReliabilityUploader>(
164 new DomainReliabilityUploaderImpl(time, url_request_context_getter));
167 // static
168 bool DomainReliabilityUploader::URLRequestIsUpload(
169 const net::URLRequest& request) {
170 return request.GetUserData(UploadUserData::kUserDataKey) != nullptr;
173 } // namespace domain_reliability