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"
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/domain_reliability/util.h"
13 #include "net/base/load_flags.h"
14 #include "net/base/net_errors.h"
15 #include "net/http/http_response_headers.h"
16 #include "net/http/http_util.h"
17 #include "net/url_request/url_fetcher.h"
18 #include "net/url_request/url_fetcher_delegate.h"
19 #include "net/url_request/url_request_context_getter.h"
21 namespace domain_reliability
{
25 const char* kJsonMimeType
= "application/json; charset=utf-8";
27 class UploadUserData
: public base::SupportsUserData::Data
{
29 static net::URLFetcher::CreateDataCallback
CreateCreateDataCallback() {
30 return base::Bind(&UploadUserData::CreateUploadUserData
);
33 static const void* kUserDataKey
;
36 static base::SupportsUserData::Data
* CreateUploadUserData() {
37 return new UploadUserData();
41 const void* UploadUserData::kUserDataKey
=
42 static_cast<const void*>(&UploadUserData::kUserDataKey
);
44 class DomainReliabilityUploaderImpl
45 : public DomainReliabilityUploader
, net::URLFetcherDelegate
{
47 DomainReliabilityUploaderImpl(
50 net::URLRequestContextGetter
>& url_request_context_getter
)
52 url_request_context_getter_(url_request_context_getter
),
53 discard_uploads_(true) {}
55 ~DomainReliabilityUploaderImpl() override
{
56 // Delete any in-flight URLFetchers.
57 STLDeleteContainerPairFirstPointers(
58 upload_callbacks_
.begin(), upload_callbacks_
.end());
61 // DomainReliabilityUploader implementation:
63 const std::string
& report_json
,
64 const GURL
& upload_url
,
65 const DomainReliabilityUploader::UploadCallback
& callback
) override
{
66 VLOG(1) << "Uploading report to " << upload_url
;
67 VLOG(2) << "Report JSON: " << report_json
;
69 if (discard_uploads_
) {
70 VLOG(1) << "Discarding report instead of uploading.";
72 result
.status
= UploadResult::SUCCESS
;
77 net::URLFetcher
* fetcher
=
78 net::URLFetcher::Create(0, upload_url
, net::URLFetcher::POST
, this)
80 fetcher
->SetRequestContext(url_request_context_getter_
.get());
81 fetcher
->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES
|
82 net::LOAD_DO_NOT_SAVE_COOKIES
);
83 fetcher
->SetUploadData(kJsonMimeType
, report_json
);
84 fetcher
->SetAutomaticallyRetryOn5xx(false);
85 fetcher
->SetURLRequestUserData(
86 UploadUserData::kUserDataKey
,
87 UploadUserData::CreateCreateDataCallback());
90 upload_callbacks_
[fetcher
] = callback
;
93 void set_discard_uploads(bool discard_uploads
) override
{
94 discard_uploads_
= discard_uploads
;
95 VLOG(1) << "Setting discard_uploads to " << discard_uploads
;
98 // net::URLFetcherDelegate implementation:
99 void OnURLFetchComplete(const net::URLFetcher
* fetcher
) override
{
102 UploadCallbackMap::iterator callback_it
= upload_callbacks_
.find(fetcher
);
103 DCHECK(callback_it
!= upload_callbacks_
.end());
105 int net_error
= GetNetErrorFromURLRequestStatus(fetcher
->GetStatus());
106 int http_response_code
= fetcher
->GetResponseCode();
107 base::TimeDelta retry_after
;
109 std::string retry_after_string
;
110 if (fetcher
->GetResponseHeaders() &&
111 fetcher
->GetResponseHeaders()->EnumerateHeader(nullptr,
113 &retry_after_string
)) {
114 net::HttpUtil::ParseRetryAfterHeader(retry_after_string
,
120 VLOG(1) << "Upload finished with net error " << net_error
121 << ", response code " << http_response_code
122 << ", retry after " << retry_after
;
124 UMA_HISTOGRAM_SPARSE_SLOWLY("DomainReliability.UploadResponseCode",
126 UMA_HISTOGRAM_SPARSE_SLOWLY("DomainReliability.UploadNetError",
130 GetUploadResultFromResponseDetails(net_error
,
134 callback_it
->second
.Run(result
);
136 delete callback_it
->first
;
137 upload_callbacks_
.erase(callback_it
);
141 using DomainReliabilityUploader::UploadCallback
;
142 typedef std::map
<const net::URLFetcher
*, UploadCallback
> UploadCallbackMap
;
145 scoped_refptr
<net::URLRequestContextGetter
> url_request_context_getter_
;
146 UploadCallbackMap upload_callbacks_
;
147 bool discard_uploads_
;
152 DomainReliabilityUploader::DomainReliabilityUploader() {}
153 DomainReliabilityUploader::~DomainReliabilityUploader() {}
156 scoped_ptr
<DomainReliabilityUploader
> DomainReliabilityUploader::Create(
158 const scoped_refptr
<net::URLRequestContextGetter
>&
159 url_request_context_getter
) {
160 return scoped_ptr
<DomainReliabilityUploader
>(
161 new DomainReliabilityUploaderImpl(time
, url_request_context_getter
));
165 bool DomainReliabilityUploader::URLRequestIsUpload(
166 const net::URLRequest
& request
) {
167 return request
.GetUserData(UploadUserData::kUserDataKey
) != nullptr;
170 } // namespace domain_reliability