blob: 3f7f0687d3ba4cf594c86dfb7bdd6886be080a5e [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
avi12ce31d2016-08-30 16:38:057#include <utility>
8
[email protected]bda8e362014-03-24 18:21:039#include "base/bind.h"
[email protected]b5c2b742014-06-14 22:21:4210#include "base/callback.h"
juliatuttle127604ea2016-12-19 19:13:0411#include "base/logging.h"
avi1ed4a4372017-04-25 05:39:4112#include "base/memory/ptr_util.h"
Ilya Sherman1edb6f182017-12-12 04:00:4213#include "base/metrics/histogram_functions.h"
[email protected]d1acfe02014-04-24 17:15:2914#include "base/supports_user_data.h"
ttuttle280a73d2014-11-13 21:38:0415#include "components/domain_reliability/util.h"
[email protected]bda8e362014-03-24 18:21:0316#include "net/base/load_flags.h"
ttuttle128179a2014-10-31 23:25:1917#include "net/base/net_errors.h"
ttuttle280a73d2014-11-13 21:38:0418#include "net/http/http_response_headers.h"
19#include "net/http/http_util.h"
rhalavati21ac0c12017-04-19 13:25:3220#include "net/traffic_annotation/network_traffic_annotation.h"
[email protected]bda8e362014-03-24 18:21:0321#include "net/url_request/url_fetcher.h"
22#include "net/url_request/url_fetcher_delegate.h"
23#include "net/url_request/url_request_context_getter.h"
24
25namespace domain_reliability {
26
27namespace {
28
thestig3b6a2f12015-09-25 08:17:2029const char kJsonMimeType[] = "application/json; charset=utf-8";
[email protected]0d73f082014-05-07 22:30:2330
[email protected]d1acfe02014-04-24 17:15:2931class UploadUserData : public base::SupportsUserData::Data {
32 public:
ttuttle42144d8a2015-12-01 23:57:3733 static net::URLFetcher::CreateDataCallback CreateCreateDataCallback(
34 int depth) {
35 return base::Bind(&UploadUserData::CreateUploadUserData, depth);
[email protected]d1acfe02014-04-24 17:15:2936 }
37
thestig3b6a2f12015-09-25 08:17:2038 static const void* const kUserDataKey;
[email protected]d1acfe02014-04-24 17:15:2939
ttuttle42144d8a2015-12-01 23:57:3740 int depth() const { return depth_; }
41
[email protected]d1acfe02014-04-24 17:15:2942 private:
ttuttle42144d8a2015-12-01 23:57:3743 UploadUserData(int depth) : depth_(depth) {}
44
avi1ed4a4372017-04-25 05:39:4145 static std::unique_ptr<base::SupportsUserData::Data> CreateUploadUserData(
46 int depth) {
47 return base::WrapUnique(new UploadUserData(depth));
[email protected]d1acfe02014-04-24 17:15:2948 }
ttuttle42144d8a2015-12-01 23:57:3749
50 int depth_;
[email protected]d1acfe02014-04-24 17:15:2951};
52
thestig3b6a2f12015-09-25 08:17:2053const void* const UploadUserData::kUserDataKey =
54 &UploadUserData::kUserDataKey;
[email protected]d1acfe02014-04-24 17:15:2955
[email protected]bda8e362014-03-24 18:21:0356class DomainReliabilityUploaderImpl
57 : public DomainReliabilityUploader, net::URLFetcherDelegate {
58 public:
ttuttle280a73d2014-11-13 21:38:0459 DomainReliabilityUploaderImpl(
60 MockableTime* time,
Julia Tuttle30b169652017-10-16 20:19:0861 const scoped_refptr<net::URLRequestContextGetter>&
62 url_request_context_getter)
ttuttle280a73d2014-11-13 21:38:0463 : time_(time),
64 url_request_context_getter_(url_request_context_getter),
juliatuttle127604ea2016-12-19 19:13:0465 discard_uploads_(true),
Julia Tuttle30b169652017-10-16 20:19:0866 shutdown_(false),
67 discarded_upload_count_(0u) {}
[email protected]bda8e362014-03-24 18:21:0368
juliatuttle127604ea2016-12-19 19:13:0469 ~DomainReliabilityUploaderImpl() override {
70 DCHECK(shutdown_);
71 }
[email protected]bda8e362014-03-24 18:21:0372
73 // DomainReliabilityUploader implementation:
dcheng00ea022b2014-10-21 11:24:5674 void UploadReport(
[email protected]bda8e362014-03-24 18:21:0375 const std::string& report_json,
ttuttle42144d8a2015-12-01 23:57:3776 int max_upload_depth,
[email protected]bda8e362014-03-24 18:21:0377 const GURL& upload_url,
mostynbfe59f482014-10-06 15:04:4678 const DomainReliabilityUploader::UploadCallback& callback) override {
Misha Efimov99c53bcf2018-11-14 20:26:2379 DVLOG(1) << "Uploading report to " << upload_url;
80 DVLOG(2) << "Report JSON: " << report_json;
[email protected]bda8e362014-03-24 18:21:0381
Julia Tuttle30b169652017-10-16 20:19:0882 if (discard_uploads_)
83 discarded_upload_count_++;
84
juliatuttle127604ea2016-12-19 19:13:0485 if (discard_uploads_ || shutdown_) {
Misha Efimov99c53bcf2018-11-14 20:26:2386 DVLOG(1) << "Discarding report instead of uploading.";
ttuttle280a73d2014-11-13 21:38:0487 UploadResult result;
88 result.status = UploadResult::SUCCESS;
89 callback.Run(result);
ttuttlefa8427f92014-08-25 19:38:0390 return;
91 }
92
rhalavati21ac0c12017-04-19 13:25:3293 net::NetworkTrafficAnnotationTag traffic_annotation =
94 net::DefineNetworkTrafficAnnotation("domain_reliability_report_upload",
95 R"(
96 semantics {
97 sender: "Domain Reliability"
98 description:
99 "If Chromium has trouble reaching certain Google sites or "
100 "services, Domain Reliability may report the problems back to "
101 "Google."
102 trigger: "Failure to load certain Google sites or services."
103 data:
104 "Details of the failed request, including the URL, any IP "
105 "addresses the browser tried to connect to, error(s) "
106 "encountered loading the resource, and other connection details."
107 destination: GOOGLE_OWNED_SERVICE
108 }
109 policy {
Ramin Halavati3b979782017-07-21 11:40:26110 cookies_allowed: NO
rhalavati21ac0c12017-04-19 13:25:32111 setting:
112 "Users can enable or disable Domain Reliability on desktop, via "
113 "toggling 'Automatically send usage statistics and crash reports "
114 "to Google' in Chromium's settings under Privacy. On ChromeOS, "
115 "the setting is named 'Automatically send diagnostic and usage "
116 "data to Google'."
117 policy_exception_justification: "Not implemented."
118 })");
119 std::unique_ptr<net::URLFetcher> owned_fetcher = net::URLFetcher::Create(
120 0, upload_url, net::URLFetcher::POST, this, traffic_annotation);
avi12ce31d2016-08-30 16:38:05121 net::URLFetcher* fetcher = owned_fetcher.get();
dcheng45252e8e2014-08-26 17:59:54122 fetcher->SetRequestContext(url_request_context_getter_.get());
[email protected]bda8e362014-03-24 18:21:03123 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
124 net::LOAD_DO_NOT_SAVE_COOKIES);
[email protected]0d73f082014-05-07 22:30:23125 fetcher->SetUploadData(kJsonMimeType, report_json);
[email protected]bda8e362014-03-24 18:21:03126 fetcher->SetAutomaticallyRetryOn5xx(false);
[email protected]d1acfe02014-04-24 17:15:29127 fetcher->SetURLRequestUserData(
128 UploadUserData::kUserDataKey,
ttuttle42144d8a2015-12-01 23:57:37129 UploadUserData::CreateCreateDataCallback(max_upload_depth + 1));
[email protected]bda8e362014-03-24 18:21:03130 fetcher->Start();
131
juliatuttle127604ea2016-12-19 19:13:04132 uploads_[fetcher] = {std::move(owned_fetcher), callback};
[email protected]bda8e362014-03-24 18:21:03133 }
134
Julia Tuttle30b169652017-10-16 20:19:08135 void SetDiscardUploads(bool discard_uploads) override {
ttuttlefa8427f92014-08-25 19:38:03136 discard_uploads_ = discard_uploads;
Misha Efimov99c53bcf2018-11-14 20:26:23137 DVLOG(1) << "Setting discard_uploads to " << discard_uploads;
ttuttlefa8427f92014-08-25 19:38:03138 }
139
juliatuttle127604ea2016-12-19 19:13:04140 void Shutdown() override {
141 DCHECK(!shutdown_);
142 shutdown_ = true;
143 uploads_.clear();
144 }
145
Julia Tuttle30b169652017-10-16 20:19:08146 int GetDiscardedUploadCount() const override {
147 return discarded_upload_count_;
148 }
149
[email protected]bda8e362014-03-24 18:21:03150 // net::URLFetcherDelegate implementation:
dcheng00ea022b2014-10-21 11:24:56151 void OnURLFetchComplete(const net::URLFetcher* fetcher) override {
[email protected]bda8e362014-03-24 18:21:03152 DCHECK(fetcher);
153
juliatuttle127604ea2016-12-19 19:13:04154 auto callback_it = uploads_.find(fetcher);
155 DCHECK(callback_it != uploads_.end());
[email protected]bda8e362014-03-24 18:21:03156
ttuttle280a73d2014-11-13 21:38:04157 int net_error = GetNetErrorFromURLRequestStatus(fetcher->GetStatus());
158 int http_response_code = fetcher->GetResponseCode();
159 base::TimeDelta retry_after;
ttuttle128179a2014-10-31 23:25:19160 {
ttuttle280a73d2014-11-13 21:38:04161 std::string retry_after_string;
ttuttled42b14632014-11-19 00:40:29162 if (fetcher->GetResponseHeaders() &&
ttuttlec72f27d2015-03-17 23:55:59163 fetcher->GetResponseHeaders()->EnumerateHeader(nullptr,
ttuttle280a73d2014-11-13 21:38:04164 "Retry-After",
165 &retry_after_string)) {
166 net::HttpUtil::ParseRetryAfterHeader(retry_after_string,
167 time_->Now(),
168 &retry_after);
ttuttle128179a2014-10-31 23:25:19169 }
170 }
ttuttle128179a2014-10-31 23:25:19171
Misha Efimov99c53bcf2018-11-14 20:26:23172 DVLOG(1) << "Upload finished with net error " << net_error
173 << ", response code " << http_response_code << ", retry after "
174 << retry_after;
[email protected]bda8e362014-03-24 18:21:03175
Ilya Sherman1edb6f182017-12-12 04:00:42176 base::UmaHistogramSparse("DomainReliability.UploadResponseCode",
177 http_response_code);
178 base::UmaHistogramSparse("DomainReliability.UploadNetError", -net_error);
[email protected]d9df3b82014-04-08 23:44:00179
ttuttle280a73d2014-11-13 21:38:04180 UploadResult result;
181 GetUploadResultFromResponseDetails(net_error,
182 http_response_code,
183 retry_after,
184 &result);
avi12ce31d2016-08-30 16:38:05185 callback_it->second.second.Run(result);
[email protected]bda8e362014-03-24 18:21:03186
juliatuttle127604ea2016-12-19 19:13:04187 uploads_.erase(callback_it);
[email protected]bda8e362014-03-24 18:21:03188 }
189
190 private:
191 using DomainReliabilityUploader::UploadCallback;
[email protected]bda8e362014-03-24 18:21:03192
ttuttle280a73d2014-11-13 21:38:04193 MockableTime* time_;
[email protected]bda8e362014-03-24 18:21:03194 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
avi12ce31d2016-08-30 16:38:05195 std::map<const net::URLFetcher*,
196 std::pair<std::unique_ptr<net::URLFetcher>, UploadCallback>>
juliatuttle127604ea2016-12-19 19:13:04197 uploads_;
ttuttlefa8427f92014-08-25 19:38:03198 bool discard_uploads_;
juliatuttle127604ea2016-12-19 19:13:04199 bool shutdown_;
Julia Tuttle30b169652017-10-16 20:19:08200 int discarded_upload_count_;
[email protected]bda8e362014-03-24 18:21:03201};
202
203} // namespace
204
205DomainReliabilityUploader::DomainReliabilityUploader() {}
[email protected]bda8e362014-03-24 18:21:03206DomainReliabilityUploader::~DomainReliabilityUploader() {}
207
208// static
mostynbea64f7c2016-04-03 16:03:44209std::unique_ptr<DomainReliabilityUploader> DomainReliabilityUploader::Create(
ttuttle280a73d2014-11-13 21:38:04210 MockableTime* time,
[email protected]84d2a492014-05-09 22:18:50211 const scoped_refptr<net::URLRequestContextGetter>&
212 url_request_context_getter) {
mostynbea64f7c2016-04-03 16:03:44213 return std::unique_ptr<DomainReliabilityUploader>(
ttuttle280a73d2014-11-13 21:38:04214 new DomainReliabilityUploaderImpl(time, url_request_context_getter));
[email protected]bda8e362014-03-24 18:21:03215}
216
[email protected]d1acfe02014-04-24 17:15:29217// static
ttuttle42144d8a2015-12-01 23:57:37218int DomainReliabilityUploader::GetURLRequestUploadDepth(
[email protected]d1acfe02014-04-24 17:15:29219 const net::URLRequest& request) {
ttuttle42144d8a2015-12-01 23:57:37220 UploadUserData* data = static_cast<UploadUserData*>(
221 request.GetUserData(UploadUserData::kUserDataKey));
222 if (!data)
223 return 0;
224 return data->depth();
[email protected]d1acfe02014-04-24 17:15:29225}
226
juliatuttle127604ea2016-12-19 19:13:04227void DomainReliabilityUploader::Shutdown() {}
228
[email protected]bda8e362014-03-24 18:21:03229} // namespace domain_reliability