blob: f2578e4026330608dea58fa53cc456e4d0cf3ea6 [file] [log] [blame]
[email protected]67f92bc32012-01-26 01:56:191// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
initial.commit586acc5fe2008-07-26 22:42:525#include "net/url_request/url_request_test_job.h"
6
[email protected]b9c806b2011-04-30 00:44:487#include <algorithm>
8#include <list>
Bence Béky8f9d7d3952017-10-09 19:58:049#include <memory>
[email protected]b9c806b2011-04-30 00:44:4810
[email protected]098b29112011-12-20 21:12:3411#include "base/bind.h"
[email protected]b9c806b2011-04-30 00:44:4812#include "base/compiler_specific.h"
Hans Wennborg1071fc2a2021-06-30 12:29:3113#include "base/containers/cxx20_erase_list.h"
[email protected]44281e02011-11-09 22:26:0414#include "base/lazy_instance.h"
skyostil4891b25b2015-06-11 11:43:4515#include "base/location.h"
[email protected]4dc3ad4f2013-06-11 07:15:5016#include "base/strings/string_util.h"
Patrick Monette643cdf62021-10-15 19:13:4217#include "base/task/single_thread_task_runner.h"
gabf767595f2016-05-11 18:50:3518#include "base/threading/thread_task_runner_handle.h"
Gabriel Charetted87f10f2022-03-31 00:44:2219#include "base/time/time.h"
[email protected]597cf6e2009-05-29 09:43:2620#include "net/base/io_buffer.h"
initial.commit586acc5fe2008-07-26 22:42:5221#include "net/base/net_errors.h"
[email protected]319d9e6f2009-02-18 19:47:2122#include "net/http/http_response_headers.h"
martijnf96ddc732015-10-28 19:41:1623#include "net/http/http_util.h"
initial.commit586acc5fe2008-07-26 22:42:5224
[email protected]cbe04ef2011-01-11 00:13:2425namespace net {
26
[email protected]44281e02011-11-09 22:26:0427namespace {
28
29typedef std::list<URLRequestTestJob*> URLRequestJobList;
[email protected]67f92bc32012-01-26 01:56:1930base::LazyInstance<URLRequestJobList>::Leaky
[email protected]6de0fd1d2011-11-15 13:31:4931 g_pending_jobs = LAZY_INSTANCE_INITIALIZER;
[email protected]44281e02011-11-09 22:26:0432
33} // namespace
[email protected]27a112c2011-01-06 04:19:3034
initial.commit586acc5fe2008-07-26 22:42:5235// static getters for known URLs
36GURL URLRequestTestJob::test_url_1() {
37 return GURL("test:url1");
38}
mmenkec8b5fe12016-12-09 18:12:0439
initial.commit586acc5fe2008-07-26 22:42:5240GURL URLRequestTestJob::test_url_2() {
41 return GURL("test:url2");
42}
mmenkec8b5fe12016-12-09 18:12:0443
initial.commit586acc5fe2008-07-26 22:42:5244GURL URLRequestTestJob::test_url_3() {
45 return GURL("test:url3");
46}
mmenkec8b5fe12016-12-09 18:12:0447
[email protected]146b8b22013-11-20 03:59:1848GURL URLRequestTestJob::test_url_4() {
49 return GURL("test:url4");
50}
mmenkec8b5fe12016-12-09 18:12:0451
52GURL URLRequestTestJob::test_url_auto_advance_async_reads_1() {
53 return GURL("test:url_auto_advance_async_reads_1");
54}
55
initial.commit586acc5fe2008-07-26 22:42:5256GURL URLRequestTestJob::test_url_error() {
57 return GURL("test:error");
58}
mmenkec8b5fe12016-12-09 18:12:0459
mmenke94f1bd92016-12-07 21:13:0560GURL URLRequestTestJob::test_url_redirect_to_url_1() {
61 return GURL("test:redirect_to_1");
62}
mmenkec8b5fe12016-12-09 18:12:0463
[email protected]146b8b22013-11-20 03:59:1864GURL URLRequestTestJob::test_url_redirect_to_url_2() {
65 return GURL("test:redirect_to_2");
66}
initial.commit586acc5fe2008-07-26 22:42:5267
68// static getters for known URL responses
69std::string URLRequestTestJob::test_data_1() {
70 return std::string("<html><title>Test One</title></html>");
71}
72std::string URLRequestTestJob::test_data_2() {
73 return std::string("<html><title>Test Two Two</title></html>");
74}
75std::string URLRequestTestJob::test_data_3() {
76 return std::string("<html><title>Test Three Three Three</title></html>");
77}
[email protected]146b8b22013-11-20 03:59:1878std::string URLRequestTestJob::test_data_4() {
79 return std::string("<html><title>Test Four Four Four Four</title></html>");
80}
initial.commit586acc5fe2008-07-26 22:42:5281
[email protected]a5c713f2009-04-16 21:05:4782// static getter for simple response headers
83std::string URLRequestTestJob::test_headers() {
[email protected]b9c806b2011-04-30 00:44:4884 static const char kHeaders[] =
martijnf96ddc732015-10-28 19:41:1685 "HTTP/1.1 200 OK\n"
86 "Content-type: text/html\n"
87 "\n";
Daniel Cheng5feb16f2022-02-28 06:52:0788 return std::string(kHeaders, std::size(kHeaders));
[email protected]a5c713f2009-04-16 21:05:4789}
90
91// static getter for redirect response headers
92std::string URLRequestTestJob::test_redirect_headers() {
[email protected]b9c806b2011-04-30 00:44:4893 static const char kHeaders[] =
martijnf96ddc732015-10-28 19:41:1694 "HTTP/1.1 302 MOVED\n"
95 "Location: somewhere\n"
96 "\n";
Daniel Cheng5feb16f2022-02-28 06:52:0797 return std::string(kHeaders, std::size(kHeaders));
[email protected]a5c713f2009-04-16 21:05:4798}
99
[email protected]146b8b22013-11-20 03:59:18100// static getter for redirect response headers
mmenke94f1bd92016-12-07 21:13:05101std::string URLRequestTestJob::test_redirect_to_url_1_headers() {
102 std::string headers = "HTTP/1.1 302 MOVED";
103 headers.push_back('\n');
104 headers += "Location: ";
105 headers += test_url_1().spec();
106 headers.push_back('\n');
107 headers.push_back('\n');
108 return headers;
109}
110
111// static getter for redirect response headers
[email protected]146b8b22013-11-20 03:59:18112std::string URLRequestTestJob::test_redirect_to_url_2_headers() {
113 std::string headers = "HTTP/1.1 302 MOVED";
martijnf96ddc732015-10-28 19:41:16114 headers.push_back('\n');
[email protected]146b8b22013-11-20 03:59:18115 headers += "Location: ";
116 headers += test_url_2().spec();
martijnf96ddc732015-10-28 19:41:16117 headers.push_back('\n');
118 headers.push_back('\n');
[email protected]146b8b22013-11-20 03:59:18119 return headers;
120}
121
[email protected]a5c713f2009-04-16 21:05:47122// static getter for error response headers
123std::string URLRequestTestJob::test_error_headers() {
[email protected]b9c806b2011-04-30 00:44:48124 static const char kHeaders[] =
martijnf96ddc732015-10-28 19:41:16125 "HTTP/1.1 500 BOO HOO\n"
126 "\n";
Daniel Cheng5feb16f2022-02-28 06:52:07127 return std::string(kHeaders, std::size(kHeaders));
[email protected]a5c713f2009-04-16 21:05:47128}
129
Matt Menkefd978852020-09-15 16:00:57130URLRequestTestJob::URLRequestTestJob(URLRequest* request, bool auto_advance)
131 : URLRequestJob(request),
[email protected]a5c713f2009-04-16 21:05:47132 auto_advance_(auto_advance),
Tsuyoshi Horo432981d52022-06-09 09:50:13133 response_headers_length_(0) {}
[email protected]a5c713f2009-04-16 21:05:47134
[email protected]27a112c2011-01-06 04:19:30135URLRequestTestJob::URLRequestTestJob(URLRequest* request,
[email protected]a5c713f2009-04-16 21:05:47136 const std::string& response_headers,
137 const std::string& response_data,
138 bool auto_advance)
Matt Menkefd978852020-09-15 16:00:57139 : URLRequestJob(request),
[email protected]a5c713f2009-04-16 21:05:47140 auto_advance_(auto_advance),
[email protected]a5c713f2009-04-16 21:05:47141 response_data_(response_data),
David Benjamin1384c0402019-04-29 18:55:52142 response_headers_(base::MakeRefCounted<net::HttpResponseHeaders>(
143 net::HttpUtil::AssembleRawHeaders(response_headers))),
Tsuyoshi Horo432981d52022-06-09 09:50:13144 response_headers_length_(response_headers.size()) {}
[email protected]a5c713f2009-04-16 21:05:47145
146URLRequestTestJob::~URLRequestTestJob() {
Eunseok Oh26ee5ee2018-09-08 03:06:08147 base::Erase(g_pending_jobs.Get(), this);
[email protected]a5c713f2009-04-16 21:05:47148}
149
[email protected]60c413c92009-03-09 16:53:31150bool URLRequestTestJob::GetMimeType(std::string* mime_type) const {
initial.commit586acc5fe2008-07-26 22:42:52151 DCHECK(mime_type);
[email protected]90499482013-06-01 00:39:50152 if (!response_headers_.get())
[email protected]a5c713f2009-04-16 21:05:47153 return false;
154 return response_headers_->GetMimeType(mime_type);
initial.commit586acc5fe2008-07-26 22:42:52155}
156
[email protected]5033ab82013-03-22 20:17:46157void URLRequestTestJob::SetPriority(RequestPriority priority) {
158 priority_ = priority;
159}
160
initial.commit586acc5fe2008-07-26 22:42:52161void URLRequestTestJob::Start() {
162 // Start reading asynchronously so that all error reporting and data
163 // callbacks happen as they would for network requests.
skyostil4891b25b2015-06-11 11:43:45164 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49165 FROM_HERE, base::BindOnce(&URLRequestTestJob::StartAsync,
166 weak_factory_.GetWeakPtr()));
initial.commit586acc5fe2008-07-26 22:42:52167}
168
169void URLRequestTestJob::StartAsync() {
[email protected]90499482013-06-01 00:39:50170 if (!response_headers_.get()) {
ricea49369a32016-07-19 03:43:02171 SetResponseHeaders(test_headers());
mmenkec8b5fe12016-12-09 18:12:04172 if (request_->url() == test_url_1()) {
[email protected]a5c713f2009-04-16 21:05:47173 response_data_ = test_data_1();
174 stage_ = DATA_AVAILABLE; // Simulate a synchronous response for this one.
mmenkec8b5fe12016-12-09 18:12:04175 } else if (request_->url() == test_url_2()) {
[email protected]a5c713f2009-04-16 21:05:47176 response_data_ = test_data_2();
mmenkec8b5fe12016-12-09 18:12:04177 } else if (request_->url() == test_url_3()) {
[email protected]a5c713f2009-04-16 21:05:47178 response_data_ = test_data_3();
mmenkec8b5fe12016-12-09 18:12:04179 } else if (request_->url() == test_url_4()) {
[email protected]146b8b22013-11-20 03:59:18180 response_data_ = test_data_4();
mmenkec8b5fe12016-12-09 18:12:04181 } else if (request_->url() == test_url_auto_advance_async_reads_1()) {
182 response_data_ = test_data_1();
183 stage_ = DATA_AVAILABLE; // Data is available immediately.
184 async_reads_ = true; // All reads complete asynchronously.
185 } else if (request_->url() == test_url_redirect_to_url_1()) {
mmenke94f1bd92016-12-07 21:13:05186 SetResponseHeaders(test_redirect_to_url_1_headers());
mmenkec8b5fe12016-12-09 18:12:04187 } else if (request_->url() == test_url_redirect_to_url_2()) {
ricea49369a32016-07-19 03:43:02188 SetResponseHeaders(test_redirect_to_url_2_headers());
[email protected]a5c713f2009-04-16 21:05:47189 } else {
[email protected]b9c806b2011-04-30 00:44:48190 AdvanceJob();
191
Matt Menke2b4d7c8b2020-04-27 23:35:07192 // Return an error on unexpected urls.
193 NotifyStartError(ERR_INVALID_URL);
[email protected]a5c713f2009-04-16 21:05:47194 return;
195 }
initial.commit586acc5fe2008-07-26 22:42:52196 }
197
[email protected]a5c713f2009-04-16 21:05:47198 AdvanceJob();
initial.commit586acc5fe2008-07-26 22:42:52199
200 this->NotifyHeadersComplete();
201}
202
ricea49369a32016-07-19 03:43:02203void URLRequestTestJob::SetResponseHeaders(
204 const std::string& response_headers) {
David Benjamin1384c0402019-04-29 18:55:52205 response_headers_ = base::MakeRefCounted<HttpResponseHeaders>(
206 net::HttpUtil::AssembleRawHeaders(response_headers));
ricea49369a32016-07-19 03:43:02207 response_headers_length_ = response_headers.size();
208}
209
mmenkec8b5fe12016-12-09 18:12:04210int URLRequestTestJob::CopyDataForRead(IOBuffer* buf, int buf_size) {
211 int bytes_read = 0;
212 if (offset_ < static_cast<int>(response_data_.length())) {
213 bytes_read = buf_size;
214 if (bytes_read + offset_ > static_cast<int>(response_data_.length()))
215 bytes_read = static_cast<int>(response_data_.length()) - offset_;
216
217 memcpy(buf->data(), &response_data_.c_str()[offset_], bytes_read);
218 offset_ += bytes_read;
219 }
220 return bytes_read;
221}
222
xunjieli26ede962015-11-23 19:39:13223int URLRequestTestJob::ReadRawData(IOBuffer* buf, int buf_size) {
mmenkec8b5fe12016-12-09 18:12:04224 if (stage_ == WAITING || async_reads_) {
initial.commit586acc5fe2008-07-26 22:42:52225 async_buf_ = buf;
226 async_buf_size_ = buf_size;
mmenkec8b5fe12016-12-09 18:12:04227 if (stage_ != WAITING) {
228 stage_ = WAITING;
229 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49230 FROM_HERE, base::BindOnce(&URLRequestTestJob::ProcessNextOperation,
231 weak_factory_.GetWeakPtr()));
mmenkec8b5fe12016-12-09 18:12:04232 }
xunjieli26ede962015-11-23 19:39:13233 return ERR_IO_PENDING;
initial.commit586acc5fe2008-07-26 22:42:52234 }
235
mmenkec8b5fe12016-12-09 18:12:04236 return CopyDataForRead(buf, buf_size);
initial.commit586acc5fe2008-07-26 22:42:52237}
238
[email protected]27a112c2011-01-06 04:19:30239void URLRequestTestJob::GetResponseInfo(HttpResponseInfo* info) {
[email protected]90499482013-06-01 00:39:50240 if (response_headers_.get())
[email protected]a5c713f2009-04-16 21:05:47241 info->headers = response_headers_;
initial.commit586acc5fe2008-07-26 22:42:52242}
243
[email protected]2bba3252013-04-08 19:50:59244void URLRequestTestJob::GetLoadTimingInfo(
245 LoadTimingInfo* load_timing_info) const {
246 // Preserve the times the URLRequest is responsible for, but overwrite all
247 // the others.
248 base::TimeTicks request_start = load_timing_info->request_start;
249 base::Time request_start_time = load_timing_info->request_start_time;
250 *load_timing_info = load_timing_info_;
251 load_timing_info->request_start = request_start;
252 load_timing_info->request_start_time = request_start_time;
253}
254
ricea49369a32016-07-19 03:43:02255int64_t URLRequestTestJob::GetTotalReceivedBytes() const {
256 return response_headers_length_ + offset_;
257}
258
[email protected]a5c713f2009-04-16 21:05:47259bool URLRequestTestJob::IsRedirectResponse(GURL* location,
Carlos IL0d67fc72018-06-22 17:18:44260 int* http_status_code,
261 bool* insecure_scheme_was_upgraded) {
[email protected]90499482013-06-01 00:39:50262 if (!response_headers_.get())
[email protected]a5c713f2009-04-16 21:05:47263 return false;
264
265 std::string value;
266 if (!response_headers_->IsRedirect(&value))
267 return false;
268
Carlos IL0d67fc72018-06-22 17:18:44269 *insecure_scheme_was_upgraded = false;
[email protected]a5c713f2009-04-16 21:05:47270 *location = request_->url().Resolve(value);
271 *http_status_code = response_headers_->response_code();
272 return true;
273}
274
initial.commit586acc5fe2008-07-26 22:42:52275void URLRequestTestJob::Kill() {
[email protected]083b0a62009-02-06 01:13:22276 stage_ = DONE;
[email protected]27a112c2011-01-06 04:19:30277 URLRequestJob::Kill();
[email protected]098b29112011-12-20 21:12:34278 weak_factory_.InvalidateWeakPtrs();
Eunseok Oh26ee5ee2018-09-08 03:06:08279 base::Erase(g_pending_jobs.Get(), this);
initial.commit586acc5fe2008-07-26 22:42:52280}
281
[email protected]a5c713f2009-04-16 21:05:47282void URLRequestTestJob::ProcessNextOperation() {
initial.commit586acc5fe2008-07-26 22:42:52283 switch (stage_) {
284 case WAITING:
[email protected]b9c806b2011-04-30 00:44:48285 // Must call AdvanceJob() prior to NotifyReadComplete() since that may
286 // delete |this|.
287 AdvanceJob();
initial.commit586acc5fe2008-07-26 22:42:52288 stage_ = DATA_AVAILABLE;
289 // OK if ReadRawData wasn't called yet.
290 if (async_buf_) {
mmenkec8b5fe12016-12-09 18:12:04291 int result = CopyDataForRead(async_buf_, async_buf_size_);
xunjieli26ede962015-11-23 19:39:13292 if (result < 0)
293 NOTREACHED() << "Reads should not fail in DATA_AVAILABLE.";
[email protected]d7db4f622012-06-04 18:20:56294 if (NextReadAsync()) {
295 // Make all future reads return io pending until the next
296 // ProcessNextOperation().
297 stage_ = WAITING;
298 }
xunjieli26ede962015-11-23 19:39:13299 ReadRawDataComplete(result);
initial.commit586acc5fe2008-07-26 22:42:52300 }
301 break;
302 case DATA_AVAILABLE:
[email protected]b9c806b2011-04-30 00:44:48303 AdvanceJob();
initial.commit586acc5fe2008-07-26 22:42:52304 stage_ = ALL_DATA; // done sending data
305 break;
306 case ALL_DATA:
307 stage_ = DONE;
[email protected]a5c713f2009-04-16 21:05:47308 return;
initial.commit586acc5fe2008-07-26 22:42:52309 case DONE:
[email protected]a5c713f2009-04-16 21:05:47310 return;
initial.commit586acc5fe2008-07-26 22:42:52311 default:
312 NOTREACHED() << "Invalid stage";
[email protected]a5c713f2009-04-16 21:05:47313 return;
initial.commit586acc5fe2008-07-26 22:42:52314 }
[email protected]a5c713f2009-04-16 21:05:47315}
316
[email protected]d7db4f622012-06-04 18:20:56317bool URLRequestTestJob::NextReadAsync() {
318 return false;
319}
320
[email protected]a5c713f2009-04-16 21:05:47321void URLRequestTestJob::AdvanceJob() {
322 if (auto_advance_) {
skyostil4891b25b2015-06-11 11:43:45323 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49324 FROM_HERE, base::BindOnce(&URLRequestTestJob::ProcessNextOperation,
325 weak_factory_.GetWeakPtr()));
[email protected]a5c713f2009-04-16 21:05:47326 return;
327 }
[email protected]44281e02011-11-09 22:26:04328 g_pending_jobs.Get().push_back(this);
initial.commit586acc5fe2008-07-26 22:42:52329}
330
331// static
332bool URLRequestTestJob::ProcessOnePendingMessage() {
[email protected]44281e02011-11-09 22:26:04333 if (g_pending_jobs.Get().empty())
initial.commit586acc5fe2008-07-26 22:42:52334 return false;
335
[email protected]44281e02011-11-09 22:26:04336 URLRequestTestJob* next_job(g_pending_jobs.Get().front());
337 g_pending_jobs.Get().pop_front();
initial.commit586acc5fe2008-07-26 22:42:52338
[email protected]a5c713f2009-04-16 21:05:47339 DCHECK(!next_job->auto_advance()); // auto_advance jobs should be in this q
340 next_job->ProcessNextOperation();
initial.commit586acc5fe2008-07-26 22:42:52341 return true;
342}
[email protected]27a112c2011-01-06 04:19:30343
344} // namespace net