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 #include "net/url_request/url_request_job_factory_impl.h" | |
12 | |
13 namespace headless { | |
14 | |
15 class HttpUrlFetcher::Delegate : public net::URLRequest::Delegate { | |
16 public: | |
17 Delegate(const GURL& rewritten_url, | |
18 const net::HttpRequestHeaders& request_headers, | |
19 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 // The Job factory. | |
49 std::unique_ptr<net::URLRequestJobFactory> job_factory_; | |
50 | |
51 // Holds the bytes read so far. | |
52 std::string bytes_read_so_far_; | |
53 | |
54 // The interface kn which to report any results. | |
55 ResultListener* result_listener_; // NOT OWNED. | |
56 }; | |
57 | |
58 HttpUrlFetcher::Delegate::Delegate( | |
59 const GURL& rewritten_url, | |
60 const net::HttpRequestHeaders& request_headers, | |
61 net::URLRequestContext* url_request_context, | |
62 ResultListener* result_listener) | |
63 : result_code_(net::OK), | |
64 buf_(new net::IOBuffer(kBufSize)), | |
65 request_(url_request_context->CreateRequest(rewritten_url, | |
66 net::DEFAULT_PRIORITY, | |
67 this)), | |
68 result_listener_(result_listener) { | |
69 // TODO(alexclarke): Support the other HTTP verbs. | |
70 request_->set_method("GET"); | |
Sami
2016/09/22 12:09:40
Could we add a DCHECK for this somewhere? I think
alex clarke (OOO till 29th)
2016/09/23 13:29:22
I went ahead and added support for the verb.
| |
71 request_->SetExtraRequestHeaders(request_headers); | |
72 request_->Start(); | |
73 } | |
74 | |
75 HttpUrlFetcher::Delegate::~Delegate() {} | |
76 | |
77 void HttpUrlFetcher::Delegate::OnAuthRequired( | |
78 net::URLRequest* request, | |
79 net::AuthChallengeInfo* auth_info) { | |
80 DCHECK_EQ(request, request_.get()); | |
81 LOG(WARNING) << "Auth required to fetch URL, aborting."; | |
82 result_code_ = net::ERR_NOT_IMPLEMENTED; | |
83 request->CancelAuth(); | |
84 } | |
85 | |
86 void HttpUrlFetcher::Delegate::OnSSLCertificateError( | |
87 net::URLRequest* request, | |
88 const net::SSLInfo& ssl_info, | |
89 bool is_hsts_ok) { | |
90 DCHECK_EQ(request, request_.get()); | |
91 | |
92 // Revocation check failures are not fatal. | |
93 if (net::IsCertStatusMinorError(ssl_info.cert_status)) { | |
94 request->ContinueDespiteLastError(); | |
95 return; | |
96 } | |
97 LOG(WARNING) << "SSL certificate error when fetching PAC script, aborting."; | |
Sami
2016/09/22 12:09:40
I'm not sure how this is related to PAC scripts?
alex clarke (OOO till 29th)
2016/09/23 13:29:22
Whoops cut & paste fail.
| |
98 | |
99 // Certificate errors are in same space as net errors. | |
100 result_code_ = net::MapCertStatusToNetError(ssl_info.cert_status); | |
101 request->Cancel(); | |
102 } | |
103 | |
104 void HttpUrlFetcher::Delegate::OnResponseStarted(net::URLRequest* request, | |
105 int net_error) { | |
106 DCHECK_EQ(request, request_.get()); | |
107 DCHECK_NE(net::ERR_IO_PENDING, net_error); | |
108 | |
109 if (net_error != net::OK) { | |
110 OnResponseCompleted(request, net_error); | |
111 return; | |
112 } | |
113 | |
114 ReadBody(request); | |
115 } | |
116 | |
117 void HttpUrlFetcher::Delegate::OnReadCompleted(net::URLRequest* request, | |
118 int num_bytes) { | |
119 DCHECK_EQ(request, request_.get()); | |
120 DCHECK_NE(net::ERR_IO_PENDING, num_bytes); | |
121 | |
122 if (ConsumeBytesRead(request, num_bytes)) { | |
123 // Keep reading. | |
124 ReadBody(request); | |
125 } | |
126 } | |
127 | |
128 void HttpUrlFetcher::Delegate::ReadBody(net::URLRequest* request) { | |
129 // Read as many bytes as are available synchronously. | |
130 while (true) { | |
131 int num_bytes = request->Read(buf_.get(), kBufSize); | |
132 if (num_bytes == net::ERR_IO_PENDING) | |
133 return; | |
134 | |
135 if (num_bytes < 0) { | |
136 OnResponseCompleted(request, num_bytes); | |
137 return; | |
138 } | |
139 | |
140 if (!ConsumeBytesRead(request, num_bytes)) | |
141 return; | |
142 } | |
143 } | |
144 | |
145 bool HttpUrlFetcher::Delegate::ConsumeBytesRead(net::URLRequest* request, | |
146 int num_bytes) { | |
147 if (num_bytes <= 0) { | |
148 // Error while reading, or EOF. | |
149 OnResponseCompleted(request, num_bytes); | |
150 return false; | |
151 } | |
152 | |
153 bytes_read_so_far_.append(buf_->data(), num_bytes); | |
154 return true; | |
155 } | |
156 | |
157 void HttpUrlFetcher::Delegate::OnResponseCompleted(net::URLRequest* request, | |
158 int net_error) { | |
159 DCHECK_EQ(request, request_.get()); | |
160 | |
161 if (result_code_ != net::OK) { | |
162 result_listener_->OnFetchStartError(static_cast<net::Error>(result_code_)); | |
163 return; | |
164 } | |
165 | |
166 if (net_error != net::OK) { | |
167 result_listener_->OnFetchStartError(static_cast<net::Error>(net_error)); | |
168 return; | |
169 } | |
170 | |
171 result_listener_->OnFetchCompleteExtractHeaders( | |
172 request->url(), request->GetResponseCode(), bytes_read_so_far_.c_str(), | |
173 bytes_read_so_far_.size()); | |
174 } | |
175 | |
176 HttpUrlFetcher::HttpUrlFetcher( | |
177 std::unique_ptr<net::URLRequestContext> url_request_context) | |
178 : url_request_context_(std::move(url_request_context)), | |
179 url_request_job_factory_(new net::URLRequestJobFactoryImpl()) { | |
180 url_request_context_->set_job_factory(url_request_job_factory_.get()); | |
181 } | |
182 | |
183 HttpUrlFetcher::~HttpUrlFetcher() {} | |
184 | |
185 void HttpUrlFetcher::StartFetch(const GURL& rewritten_url, | |
186 const net::HttpRequestHeaders& request_headers, | |
187 ResultListener* result_listener) { | |
188 delagate_.reset(new Delegate(rewritten_url, request_headers, | |
189 url_request_context_.get(), result_listener)); | |
190 } | |
191 | |
192 } // namespace headless | |
OLD | NEW |