OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 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 "net/reporting/reporting_uploader.h" | |
6 | |
7 #include "base/callback_helpers.h" | |
8 #include "base/memory/ptr_util.h" | |
9 #include "base/metrics/histogram_macros.h" | |
10 #include "net/base/elements_upload_data_stream.h" | |
11 #include "net/base/load_flags.h" | |
12 #include "net/base/upload_bytes_element_reader.h" | |
13 #include "net/http/http_response_headers.h" | |
14 #include "net/url_request/redirect_info.h" | |
15 #include "net/url_request/url_request_context.h" | |
16 | |
17 namespace net { | |
18 | |
19 namespace { | |
20 | |
21 ReportingUploader::Outcome ResponseCodeToOutcome(int response_code) { | |
22 if (response_code >= 200 && response_code <= 299) | |
23 return ReportingUploader::SUCCESS; | |
24 if (response_code == 410) | |
25 return ReportingUploader::REMOVE_ENDPOINT; | |
26 return ReportingUploader::FAILURE; | |
27 } | |
28 | |
29 class ReportingUploaderImpl : public ReportingUploader, URLRequest::Delegate { | |
shivanisha
2017/03/28 19:57:14
Why is this class definition inside the anonymous
Julia Tuttle
2017/03/28 20:36:34
It could, but I consider it an implementation deta
| |
30 public: | |
31 ReportingUploaderImpl(const URLRequestContext* context) : context_(context) { | |
32 DCHECK(context_); | |
33 } | |
34 | |
35 ~ReportingUploaderImpl() override { | |
36 for (auto& it : uploads_) { | |
37 base::ResetAndReturn(&it.second->second).Run(FAILURE); | |
38 it.second->first->Cancel(); | |
39 } | |
40 uploads_.clear(); | |
41 } | |
42 | |
43 void StartUpload(const GURL& url, | |
44 const std::string& json, | |
45 const Callback& callback) override { | |
46 std::unique_ptr<URLRequest> request = | |
47 context_->CreateRequest(url, IDLE, this); | |
48 | |
49 request->set_method("POST"); | |
50 | |
51 request->SetLoadFlags(LOAD_DISABLE_CACHE | LOAD_DO_NOT_SAVE_COOKIES | | |
52 LOAD_DO_NOT_SEND_COOKIES); | |
53 | |
54 request->SetExtraRequestHeaderByName(HttpRequestHeaders::kContentType, | |
55 kUploadContentType, true); | |
56 | |
57 std::vector<char> json_data(json.begin(), json.end()); | |
58 std::unique_ptr<UploadElementReader> reader( | |
59 new UploadOwnedBytesElementReader(&json_data)); | |
60 request->set_upload( | |
61 ElementsUploadDataStream::CreateWithReader(std::move(reader), 0)); | |
62 | |
63 // This inherently sets mode = "no-cors", but that doesn't matter, because | |
64 // the origins that are included in the upload don't actually get to see | |
65 // the response. | |
66 // | |
67 // This inherently skips Service Worker, too. | |
shivanisha
2017/03/28 19:57:14
This question is for my own understanding: what is
Julia Tuttle
2017/03/28 20:36:34
The Reporting spec requires report delivery reques
| |
68 request->Start(); | |
69 | |
70 // Have to grab the unique_ptr* first to ensure request.get() happens | |
71 // before std::move(request). | |
72 std::unique_ptr<Upload>* upload = &uploads_[request.get()]; | |
73 *upload = base::MakeUnique<Upload>(std::move(request), callback); | |
74 } | |
75 | |
76 // URLRequest::Delegate implementation: | |
shivanisha
2017/03/28 19:57:14
new line after this comment as it applies to all t
Julia Tuttle
2017/03/28 20:36:34
Done.
| |
77 void OnReceivedRedirect(URLRequest* request, | |
78 const RedirectInfo& redirect_info, | |
79 bool* defer_redirect) override { | |
80 if (!redirect_info.new_url.SchemeIsCryptographic()) { | |
81 request->Cancel(); | |
82 return; | |
83 } | |
84 } | |
85 | |
86 void OnAuthRequired(URLRequest* request, | |
87 AuthChallengeInfo* auth_info) override { | |
88 request->Cancel(); | |
89 } | |
90 | |
91 void OnCertificateRequested(URLRequest* request, | |
92 SSLCertRequestInfo* cert_request_info) override { | |
93 request->Cancel(); | |
94 } | |
shivanisha
2017/03/28 19:57:14
Implementation of URLRequest::Delegate::OnSSLCerti
Julia Tuttle
2017/03/28 20:36:34
Done.
| |
95 | |
96 void OnResponseStarted(URLRequest* request, int net_error) override { | |
97 // Grab Upload from map, and hold on to it in a local unique_ptr so it's | |
98 // removed at the end of the method. | |
99 UploadMap::iterator it = uploads_.find(request); | |
100 DCHECK(it != uploads_.end()); | |
101 std::unique_ptr<Upload> upload = std::move(it->second); | |
102 uploads_.erase(it); | |
103 | |
104 // request->GetResponseCode() should work, but doesn't in the cases above | |
105 // where the request was canceled, so get the response code by hand. | |
106 // TODO(juliatuttle): Check if mmenke fixed this yet. | |
107 HttpResponseHeaders* headers = request->response_headers(); | |
108 int response_code = headers ? headers->response_code() : 0; | |
109 Outcome outcome = ResponseCodeToOutcome(response_code); | |
110 | |
111 upload->second.Run(outcome); | |
112 | |
113 request->Cancel(); | |
114 } | |
115 | |
116 void OnReadCompleted(URLRequest* request, int bytes_read) override { | |
117 // Reporting doesn't need anything in the body of the response, so it | |
118 // doesn't read it, so it should never get OnReadCompleted calls. | |
119 NOTREACHED(); | |
120 } | |
121 | |
122 private: | |
123 using Upload = std::pair<std::unique_ptr<URLRequest>, Callback>; | |
124 using UploadMap = std::map<const URLRequest*, std::unique_ptr<Upload>>; | |
125 | |
126 const URLRequestContext* context_; | |
127 UploadMap uploads_; | |
128 }; | |
129 | |
130 } // namespace | |
131 | |
132 // static | |
133 const char ReportingUploader::kUploadContentType[] = "application/report"; | |
134 | |
135 ReportingUploader::~ReportingUploader() {} | |
136 | |
137 // static | |
138 std::unique_ptr<ReportingUploader> ReportingUploader::Create( | |
139 const URLRequestContext* context) { | |
140 return base::MakeUnique<ReportingUploaderImpl>(context); | |
141 } | |
142 | |
143 } // namespace net | |
OLD | NEW |