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/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"
18 namespace domain_reliability
{
22 const char* kJsonMimeType
= "application/json; charset=utf-8";
24 class UploadUserData
: public base::SupportsUserData::Data
{
26 static net::URLFetcher::CreateDataCallback
CreateCreateDataCallback() {
27 return base::Bind(&UploadUserData::CreateUploadUserData
);
30 static const void* kUserDataKey
;
33 static base::SupportsUserData::Data
* CreateUploadUserData() {
34 return new UploadUserData();
38 const void* UploadUserData::kUserDataKey
=
39 static_cast<const void*>(&UploadUserData::kUserDataKey
);
41 class DomainReliabilityUploaderImpl
42 : public DomainReliabilityUploader
, net::URLFetcherDelegate
{
44 DomainReliabilityUploaderImpl(const scoped_refptr
<
45 net::URLRequestContextGetter
>& url_request_context_getter
)
46 : url_request_context_getter_(url_request_context_getter
),
47 discard_uploads_(true) {}
49 virtual ~DomainReliabilityUploaderImpl() {
50 // Delete any in-flight URLFetchers.
51 STLDeleteContainerPairFirstPointers(
52 upload_callbacks_
.begin(), upload_callbacks_
.end());
55 // DomainReliabilityUploader implementation:
56 virtual void UploadReport(
57 const std::string
& report_json
,
58 const GURL
& upload_url
,
59 const DomainReliabilityUploader::UploadCallback
& callback
) OVERRIDE
{
60 VLOG(1) << "Uploading report to " << upload_url
;
61 VLOG(2) << "Report JSON: " << report_json
;
63 if (discard_uploads_
) {
64 VLOG(1) << "Discarding report instead of uploading.";
69 net::URLFetcher
* fetcher
=
70 net::URLFetcher::Create(0, upload_url
, net::URLFetcher::POST
, this);
71 fetcher
->SetRequestContext(url_request_context_getter_
.get());
72 fetcher
->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES
|
73 net::LOAD_DO_NOT_SAVE_COOKIES
);
74 fetcher
->SetUploadData(kJsonMimeType
, report_json
);
75 fetcher
->SetAutomaticallyRetryOn5xx(false);
76 fetcher
->SetURLRequestUserData(
77 UploadUserData::kUserDataKey
,
78 UploadUserData::CreateCreateDataCallback());
81 upload_callbacks_
[fetcher
] = callback
;
84 virtual void set_discard_uploads(bool discard_uploads
) OVERRIDE
{
85 discard_uploads_
= discard_uploads
;
86 VLOG(1) << "Setting discard_uploads to " << discard_uploads
;
89 // net::URLFetcherDelegate implementation:
90 virtual void OnURLFetchComplete(
91 const net::URLFetcher
* fetcher
) OVERRIDE
{
94 UploadCallbackMap::iterator callback_it
= upload_callbacks_
.find(fetcher
);
95 DCHECK(callback_it
!= upload_callbacks_
.end());
97 VLOG(1) << "Upload finished with " << fetcher
->GetResponseCode();
99 UMA_HISTOGRAM_SPARSE_SLOWLY("DomainReliability.UploadResponseCode",
100 fetcher
->GetResponseCode());
102 bool success
= fetcher
->GetResponseCode() == 200;
103 callback_it
->second
.Run(success
);
105 delete callback_it
->first
;
106 upload_callbacks_
.erase(callback_it
);
110 using DomainReliabilityUploader::UploadCallback
;
111 typedef std::map
<const net::URLFetcher
*, UploadCallback
> UploadCallbackMap
;
113 scoped_refptr
<net::URLRequestContextGetter
> url_request_context_getter_
;
114 UploadCallbackMap upload_callbacks_
;
115 bool discard_uploads_
;
120 DomainReliabilityUploader::DomainReliabilityUploader() {}
121 DomainReliabilityUploader::~DomainReliabilityUploader() {}
124 scoped_ptr
<DomainReliabilityUploader
> DomainReliabilityUploader::Create(
125 const scoped_refptr
<net::URLRequestContextGetter
>&
126 url_request_context_getter
) {
127 return scoped_ptr
<DomainReliabilityUploader
>(
128 new DomainReliabilityUploaderImpl(url_request_context_getter
));
132 bool DomainReliabilityUploader::URLRequestIsUpload(
133 const net::URLRequest
& request
) {
134 return request
.GetUserData(UploadUserData::kUserDataKey
) != NULL
;
137 } // namespace domain_reliability