blob: 90fc594048efd4ae44d232dba56865d245a3e431 [file] [log] [blame]
[email protected]bda8e362014-03-24 18:21:031// 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"
[email protected]b5c2b742014-06-14 22:21:428#include "base/callback.h"
[email protected]d9df3b82014-04-08 23:44:009#include "base/metrics/sparse_histogram.h"
[email protected]bda8e362014-03-24 18:21:0310#include "base/stl_util.h"
[email protected]d1acfe02014-04-24 17:15:2911#include "base/supports_user_data.h"
amohammadkhanf76ae112015-09-14 17:34:4312#include "components/data_use_measurement/core/data_use_user_data.h"
ttuttle280a73d2014-11-13 21:38:0413#include "components/domain_reliability/util.h"
[email protected]bda8e362014-03-24 18:21:0314#include "net/base/load_flags.h"
ttuttle128179a2014-10-31 23:25:1915#include "net/base/net_errors.h"
ttuttle280a73d2014-11-13 21:38:0416#include "net/http/http_response_headers.h"
17#include "net/http/http_util.h"
[email protected]bda8e362014-03-24 18:21:0318#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"
21
22namespace domain_reliability {
23
24namespace {
25
thestig3b6a2f12015-09-25 08:17:2026const char kJsonMimeType[] = "application/json; charset=utf-8";
[email protected]0d73f082014-05-07 22:30:2327
[email protected]d1acfe02014-04-24 17:15:2928class UploadUserData : public base::SupportsUserData::Data {
29 public:
30 static net::URLFetcher::CreateDataCallback CreateCreateDataCallback() {
31 return base::Bind(&UploadUserData::CreateUploadUserData);
32 }
33
thestig3b6a2f12015-09-25 08:17:2034 static const void* const kUserDataKey;
[email protected]d1acfe02014-04-24 17:15:2935
36 private:
37 static base::SupportsUserData::Data* CreateUploadUserData() {
38 return new UploadUserData();
39 }
40};
41
thestig3b6a2f12015-09-25 08:17:2042const void* const UploadUserData::kUserDataKey =
43 &UploadUserData::kUserDataKey;
[email protected]d1acfe02014-04-24 17:15:2944
[email protected]bda8e362014-03-24 18:21:0345class DomainReliabilityUploaderImpl
46 : public DomainReliabilityUploader, net::URLFetcherDelegate {
47 public:
ttuttle280a73d2014-11-13 21:38:0448 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),
ttuttlefa8427f92014-08-25 19:38:0354 discard_uploads_(true) {}
[email protected]bda8e362014-03-24 18:21:0355
dcheng00ea022b2014-10-21 11:24:5656 ~DomainReliabilityUploaderImpl() override {
[email protected]bda8e362014-03-24 18:21:0357 // Delete any in-flight URLFetchers.
58 STLDeleteContainerPairFirstPointers(
59 upload_callbacks_.begin(), upload_callbacks_.end());
60 }
61
62 // DomainReliabilityUploader implementation:
dcheng00ea022b2014-10-21 11:24:5663 void UploadReport(
[email protected]bda8e362014-03-24 18:21:0364 const std::string& report_json,
65 const GURL& upload_url,
mostynbfe59f482014-10-06 15:04:4666 const DomainReliabilityUploader::UploadCallback& callback) override {
[email protected]bda8e362014-03-24 18:21:0367 VLOG(1) << "Uploading report to " << upload_url;
68 VLOG(2) << "Report JSON: " << report_json;
69
ttuttlefa8427f92014-08-25 19:38:0370 if (discard_uploads_) {
71 VLOG(1) << "Discarding report instead of uploading.";
ttuttle280a73d2014-11-13 21:38:0472 UploadResult result;
73 result.status = UploadResult::SUCCESS;
74 callback.Run(result);
ttuttlefa8427f92014-08-25 19:38:0375 return;
76 }
77
[email protected]bda8e362014-03-24 18:21:0378 net::URLFetcher* fetcher =
dtapuskadafcf892015-05-01 13:58:2579 net::URLFetcher::Create(0, upload_url, net::URLFetcher::POST, this)
80 .release();
amohammadkhanf76ae112015-09-14 17:34:4381 data_use_measurement::DataUseUserData::AttachToFetcher(
82 fetcher, data_use_measurement::DataUseUserData::DOMAIN_RELIABILITY);
dcheng45252e8e2014-08-26 17:59:5483 fetcher->SetRequestContext(url_request_context_getter_.get());
[email protected]bda8e362014-03-24 18:21:0384 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
85 net::LOAD_DO_NOT_SAVE_COOKIES);
[email protected]0d73f082014-05-07 22:30:2386 fetcher->SetUploadData(kJsonMimeType, report_json);
[email protected]bda8e362014-03-24 18:21:0387 fetcher->SetAutomaticallyRetryOn5xx(false);
[email protected]d1acfe02014-04-24 17:15:2988 fetcher->SetURLRequestUserData(
89 UploadUserData::kUserDataKey,
90 UploadUserData::CreateCreateDataCallback());
[email protected]bda8e362014-03-24 18:21:0391 fetcher->Start();
92
93 upload_callbacks_[fetcher] = callback;
94 }
95
dcheng00ea022b2014-10-21 11:24:5696 void set_discard_uploads(bool discard_uploads) override {
ttuttlefa8427f92014-08-25 19:38:0397 discard_uploads_ = discard_uploads;
98 VLOG(1) << "Setting discard_uploads to " << discard_uploads;
99 }
100
[email protected]bda8e362014-03-24 18:21:03101 // net::URLFetcherDelegate implementation:
dcheng00ea022b2014-10-21 11:24:56102 void OnURLFetchComplete(const net::URLFetcher* fetcher) override {
[email protected]bda8e362014-03-24 18:21:03103 DCHECK(fetcher);
104
105 UploadCallbackMap::iterator callback_it = upload_callbacks_.find(fetcher);
106 DCHECK(callback_it != upload_callbacks_.end());
107
ttuttle280a73d2014-11-13 21:38:04108 int net_error = GetNetErrorFromURLRequestStatus(fetcher->GetStatus());
109 int http_response_code = fetcher->GetResponseCode();
110 base::TimeDelta retry_after;
ttuttle128179a2014-10-31 23:25:19111 {
ttuttle280a73d2014-11-13 21:38:04112 std::string retry_after_string;
ttuttled42b14632014-11-19 00:40:29113 if (fetcher->GetResponseHeaders() &&
ttuttlec72f27d2015-03-17 23:55:59114 fetcher->GetResponseHeaders()->EnumerateHeader(nullptr,
ttuttle280a73d2014-11-13 21:38:04115 "Retry-After",
116 &retry_after_string)) {
117 net::HttpUtil::ParseRetryAfterHeader(retry_after_string,
118 time_->Now(),
119 &retry_after);
ttuttle128179a2014-10-31 23:25:19120 }
121 }
ttuttle128179a2014-10-31 23:25:19122
ttuttle280a73d2014-11-13 21:38:04123 VLOG(1) << "Upload finished with net error " << net_error
124 << ", response code " << http_response_code
125 << ", retry after " << retry_after;
[email protected]bda8e362014-03-24 18:21:03126
[email protected]d9df3b82014-04-08 23:44:00127 UMA_HISTOGRAM_SPARSE_SLOWLY("DomainReliability.UploadResponseCode",
ttuttle128179a2014-10-31 23:25:19128 http_response_code);
129 UMA_HISTOGRAM_SPARSE_SLOWLY("DomainReliability.UploadNetError",
130 -net_error);
[email protected]d9df3b82014-04-08 23:44:00131
ttuttle280a73d2014-11-13 21:38:04132 UploadResult result;
133 GetUploadResultFromResponseDetails(net_error,
134 http_response_code,
135 retry_after,
136 &result);
137 callback_it->second.Run(result);
[email protected]bda8e362014-03-24 18:21:03138
139 delete callback_it->first;
140 upload_callbacks_.erase(callback_it);
141 }
142
143 private:
144 using DomainReliabilityUploader::UploadCallback;
145 typedef std::map<const net::URLFetcher*, UploadCallback> UploadCallbackMap;
146
ttuttle280a73d2014-11-13 21:38:04147 MockableTime* time_;
[email protected]bda8e362014-03-24 18:21:03148 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
149 UploadCallbackMap upload_callbacks_;
ttuttlefa8427f92014-08-25 19:38:03150 bool discard_uploads_;
[email protected]bda8e362014-03-24 18:21:03151};
152
153} // namespace
154
155DomainReliabilityUploader::DomainReliabilityUploader() {}
[email protected]bda8e362014-03-24 18:21:03156DomainReliabilityUploader::~DomainReliabilityUploader() {}
157
158// static
159scoped_ptr<DomainReliabilityUploader> DomainReliabilityUploader::Create(
ttuttle280a73d2014-11-13 21:38:04160 MockableTime* time,
[email protected]84d2a492014-05-09 22:18:50161 const scoped_refptr<net::URLRequestContextGetter>&
162 url_request_context_getter) {
[email protected]bda8e362014-03-24 18:21:03163 return scoped_ptr<DomainReliabilityUploader>(
ttuttle280a73d2014-11-13 21:38:04164 new DomainReliabilityUploaderImpl(time, url_request_context_getter));
[email protected]bda8e362014-03-24 18:21:03165}
166
[email protected]d1acfe02014-04-24 17:15:29167// static
168bool DomainReliabilityUploader::URLRequestIsUpload(
169 const net::URLRequest& request) {
ttuttlec72f27d2015-03-17 23:55:59170 return request.GetUserData(UploadUserData::kUserDataKey) != nullptr;
[email protected]d1acfe02014-04-24 17:15:29171}
172
[email protected]bda8e362014-03-24 18:21:03173} // namespace domain_reliability