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 "headless/public/util/http_url_fetcher.h" | |
6 | |
7 #include "net/base/io_buffer.h" | |
8 #include "net/cert/cert_status_flags.h" | |
9 #include "net/url_request/url_request.h" | |
10 #include "net/url_request/url_request_context.h" | |
11 | |
12 namespace headless { | |
13 | |
14 class HttpUrlFetcher::Delegate : public net::URLRequest::Delegate { | |
15 public: | |
16 Delegate(const GURL& rewritten_url, | |
17 const std::string& method, | |
18 const net::HttpRequestHeaders& request_headers, | |
19 const net::URLRequestContext* url_request_context, | |
20 ResultListener* result_listener); | |
21 ~Delegate() override; | |
22 | |
23 // URLRequest::Delegate methods: | |
24 void OnAuthRequired(net::URLRequest* request, | |
25 net::AuthChallengeInfo* auth_info) override; | |
26 void OnSSLCertificateError(net::URLRequest* request, | |
27 const net::SSLInfo& ssl_info, | |
28 bool is_hsts_ok) override; | |
29 void OnResponseStarted(net::URLRequest* request, int net_error) override; | |
30 void OnReadCompleted(net::URLRequest* request, int num_bytes) override; | |
31 | |
32 private: | |
33 enum { kBufSize = 4096 }; | |
34 | |
35 bool ConsumeBytesRead(net::URLRequest* request, int num_bytes); | |
36 void ReadBody(net::URLRequest* request); | |
37 void OnResponseCompleted(net::URLRequest* request, int net_error); | |
38 | |
39 // Holds the error condition that was hit by the request, or OK. | |
40 int result_code_; | |
41 | |
42 // Buffer that URLRequest writes into. | |
43 scoped_refptr<net::IOBuffer> buf_; | |
44 | |
45 // The HTTP fetch. | |
46 std::unique_ptr<net::URLRequest> request_; | |
47 | |
48 // Holds the bytes read so far. | |
49 std::string bytes_read_so_far_; | |
50 | |
51 // The interface kn which to report any results. | |
52 ResultListener* result_listener_; // NOT OWNED. | |
53 }; | |
54 | |
55 HttpUrlFetcher::Delegate::Delegate( | |
56 const GURL& rewritten_url, | |
57 const std::string& method, | |
58 const net::HttpRequestHeaders& request_headers, | |
59 const net::URLRequestContext* url_request_context, | |
60 ResultListener* result_listener) | |
61 : result_code_(net::OK), | |
62 buf_(new net::IOBuffer(kBufSize)), | |
63 request_(url_request_context->CreateRequest(rewritten_url, | |
64 net::DEFAULT_PRIORITY, | |
65 this)), | |
66 result_listener_(result_listener) { | |
67 request_->set_method(method); | |
68 request_->SetExtraRequestHeaders(request_headers); | |
69 request_->Start(); | |
70 } | |
71 | |
72 HttpUrlFetcher::Delegate::~Delegate() {} | |
73 | |
74 void HttpUrlFetcher::Delegate::OnAuthRequired( | |
75 net::URLRequest* request, | |
76 net::AuthChallengeInfo* auth_info) { | |
77 DCHECK_EQ(request, request_.get()); | |
78 LOG(WARNING) << "Auth required to fetch URL, aborting."; | |
79 result_code_ = net::ERR_NOT_IMPLEMENTED; | |
80 request->CancelAuth(); | |
81 } | |
82 | |
83 void HttpUrlFetcher::Delegate::OnSSLCertificateError( | |
84 net::URLRequest* request, | |
85 const net::SSLInfo& ssl_info, | |
86 bool is_hsts_ok) { | |
Sami
2016/09/23 14:27:29
Do we need to care about is_hsts_ok?
alex clarke (OOO till 29th)
2016/09/23 16:40:26
It turns out this is actually called |fatal| by mo
| |
87 DCHECK_EQ(request, request_.get()); | |
88 | |
89 // Revocation check failures are not fatal. | |
90 if (net::IsCertStatusMinorError(ssl_info.cert_status)) { | |
91 request->ContinueDespiteLastError(); | |
92 return; | |
93 } | |
94 LOG(WARNING) << "SSL certificate error, aborting."; | |
95 | |
96 // Certificate errors are in same space as net errors. | |
97 result_code_ = net::MapCertStatusToNetError(ssl_info.cert_status); | |
98 request->Cancel(); | |
99 } | |
100 | |
101 void HttpUrlFetcher::Delegate::OnResponseStarted(net::URLRequest* request, | |
102 int net_error) { | |
103 DCHECK_EQ(request, request_.get()); | |
104 DCHECK_NE(net::ERR_IO_PENDING, net_error); | |
105 | |
106 if (net_error != net::OK) { | |
107 OnResponseCompleted(request, net_error); | |
108 return; | |
109 } | |
110 | |
111 ReadBody(request); | |
112 } | |
113 | |
114 void HttpUrlFetcher::Delegate::OnReadCompleted(net::URLRequest* request, | |
115 int num_bytes) { | |
116 DCHECK_EQ(request, request_.get()); | |
117 DCHECK_NE(net::ERR_IO_PENDING, num_bytes); | |
118 | |
119 if (ConsumeBytesRead(request, num_bytes)) { | |
120 // Keep reading. | |
121 ReadBody(request); | |
122 } | |
123 } | |
124 | |
125 void HttpUrlFetcher::Delegate::ReadBody(net::URLRequest* request) { | |
126 // Read as many bytes as are available synchronously. | |
127 while (true) { | |
128 int num_bytes = request->Read(buf_.get(), kBufSize); | |
129 if (num_bytes == net::ERR_IO_PENDING) | |
130 return; | |
131 | |
132 if (num_bytes < 0) { | |
133 OnResponseCompleted(request, num_bytes); | |
134 return; | |
135 } | |
136 | |
137 if (!ConsumeBytesRead(request, num_bytes)) | |
138 return; | |
139 } | |
140 } | |
141 | |
142 bool HttpUrlFetcher::Delegate::ConsumeBytesRead(net::URLRequest* request, | |
143 int num_bytes) { | |
144 if (num_bytes <= 0) { | |
145 // Error while reading, or EOF. | |
146 OnResponseCompleted(request, num_bytes); | |
147 return false; | |
148 } | |
149 | |
150 bytes_read_so_far_.append(buf_->data(), num_bytes); | |
151 return true; | |
152 } | |
153 | |
154 void HttpUrlFetcher::Delegate::OnResponseCompleted(net::URLRequest* request, | |
155 int net_error) { | |
156 DCHECK_EQ(request, request_.get()); | |
157 | |
158 if (result_code_ != net::OK) { | |
159 result_listener_->OnFetchStartError(static_cast<net::Error>(result_code_)); | |
160 return; | |
161 } | |
162 | |
163 if (net_error != net::OK) { | |
164 result_listener_->OnFetchStartError(static_cast<net::Error>(net_error)); | |
165 return; | |
166 } | |
167 | |
168 result_listener_->OnFetchCompleteExtractHeaders( | |
169 request->url(), request->GetResponseCode(), bytes_read_so_far_.c_str(), | |
170 bytes_read_so_far_.size()); | |
171 } | |
172 | |
173 HttpUrlFetcher::HttpUrlFetcher( | |
174 const net::URLRequestContext* url_request_context) | |
175 : url_request_context_(url_request_context) {} | |
176 | |
177 HttpUrlFetcher::~HttpUrlFetcher() {} | |
178 | |
179 void HttpUrlFetcher::StartFetch(const GURL& rewritten_url, | |
180 const std::string& method, | |
181 const net::HttpRequestHeaders& request_headers, | |
182 ResultListener* result_listener) { | |
183 delagate_.reset(new Delegate(rewritten_url, method, request_headers, | |
184 url_request_context_, result_listener)); | |
185 } | |
186 | |
187 } // namespace headless | |
OLD | NEW |