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 "net/test/url_request/url_request_mock_data_job.h"
8 #include "base/location.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/url_util.h"
15 #include "net/http/http_request_headers.h"
16 #include "net/http/http_response_headers.h"
17 #include "net/http/http_util.h"
18 #include "net/url_request/url_request_filter.h"
23 const char kMockHostname
[] = "mock.data";
25 // Gets the data from URL of the form:
26 // scheme://kMockHostname/?data=abc&repeat_count=nnn.
27 std::string
GetDataFromRequest(const URLRequest
& request
) {
29 if (!GetValueForKeyInQuery(request
.url(), "data", &value
))
30 return "default_data";
34 // Gets the numeric repeat count from URL of the form:
35 // scheme://kMockHostname/?data=abc&repeat_count=nnn.
36 int GetRepeatCountFromRequest(const URLRequest
& request
) {
38 if (!GetValueForKeyInQuery(request
.url(), "repeat", &value
))
42 if (!base::StringToInt(value
, &repeat_count
))
45 DCHECK_GT(repeat_count
, 0);
50 GURL
GetMockUrl(const std::string
& scheme
,
51 const std::string
& hostname
,
52 const std::string
& data
,
53 int data_repeat_count
) {
54 DCHECK_GT(data_repeat_count
, 0);
55 std::string
url(scheme
+ "://" + hostname
+ "/");
58 url
.append("&repeat=");
59 url
.append(base::IntToString(data_repeat_count
));
63 class MockJobInterceptor
: public URLRequestInterceptor
{
65 MockJobInterceptor() {}
66 ~MockJobInterceptor() override
{}
68 // URLRequestInterceptor implementation
69 URLRequestJob
* MaybeInterceptRequest(
71 NetworkDelegate
* network_delegate
) const override
{
72 return new URLRequestMockDataJob(request
, network_delegate
,
73 GetDataFromRequest(*request
),
74 GetRepeatCountFromRequest(*request
));
78 DISALLOW_COPY_AND_ASSIGN(MockJobInterceptor
);
83 URLRequestMockDataJob::URLRequestMockDataJob(URLRequest
* request
,
84 NetworkDelegate
* network_delegate
,
85 const std::string
& data
,
86 int data_repeat_count
)
87 : URLRequestJob(request
, network_delegate
),
90 DCHECK_GT(data_repeat_count
, 0);
91 for (int i
= 0; i
< data_repeat_count
; ++i
) {
96 void URLRequestMockDataJob::Start() {
97 // Start reading asynchronously so that all error reporting and data
98 // callbacks happen as they would for network requests.
99 base::ThreadTaskRunnerHandle::Get()->PostTask(
100 FROM_HERE
, base::Bind(&URLRequestMockDataJob::StartAsync
,
101 weak_factory_
.GetWeakPtr()));
104 URLRequestMockDataJob::~URLRequestMockDataJob() {
107 bool URLRequestMockDataJob::ReadRawData(IOBuffer
* buf
,
111 *bytes_read
= static_cast<int>(
112 std::min(static_cast<size_t>(buf_size
), data_
.length() - data_offset_
));
113 memcpy(buf
->data(), data_
.c_str() + data_offset_
, *bytes_read
);
114 data_offset_
+= *bytes_read
;
118 int URLRequestMockDataJob::GetResponseCode() const {
119 HttpResponseInfo info
;
120 GetResponseInfoConst(&info
);
121 return info
.headers
->response_code();
124 // Public virtual version.
125 void URLRequestMockDataJob::GetResponseInfo(HttpResponseInfo
* info
) {
126 // Forward to private const version.
127 GetResponseInfoConst(info
);
130 // Private const version.
131 void URLRequestMockDataJob::GetResponseInfoConst(HttpResponseInfo
* info
) const {
132 // Send back mock headers.
133 std::string raw_headers
;
136 "Content-type: text/plain\n");
137 raw_headers
.append(base::StringPrintf("Content-Length: %1d\n",
138 static_cast<int>(data_
.length())));
139 info
->headers
= new HttpResponseHeaders(HttpUtil::AssembleRawHeaders(
140 raw_headers
.c_str(), static_cast<int>(raw_headers
.length())));
143 void URLRequestMockDataJob::StartAsync() {
147 set_expected_content_size(data_
.length());
148 NotifyHeadersComplete();
152 void URLRequestMockDataJob::AddUrlHandler() {
153 return AddUrlHandlerForHostname(kMockHostname
);
157 void URLRequestMockDataJob::AddUrlHandlerForHostname(
158 const std::string
& hostname
) {
159 // Add |hostname| to URLRequestFilter for HTTP and HTTPS.
160 URLRequestFilter
* filter
= URLRequestFilter::GetInstance();
161 filter
->AddHostnameInterceptor("http", hostname
,
162 make_scoped_ptr(new MockJobInterceptor()));
163 filter
->AddHostnameInterceptor("https", hostname
,
164 make_scoped_ptr(new MockJobInterceptor()));
168 GURL
URLRequestMockDataJob::GetMockHttpUrl(const std::string
& data
,
170 return GetMockHttpUrlForHostname(kMockHostname
, data
, repeat_count
);
174 GURL
URLRequestMockDataJob::GetMockHttpsUrl(const std::string
& data
,
176 return GetMockHttpsUrlForHostname(kMockHostname
, data
, repeat_count
);
180 GURL
URLRequestMockDataJob::GetMockHttpUrlForHostname(
181 const std::string
& hostname
,
182 const std::string
& data
,
184 return GetMockUrl("http", hostname
, data
, repeat_count
);
188 GURL
URLRequestMockDataJob::GetMockHttpsUrlForHostname(
189 const std::string
& hostname
,
190 const std::string
& data
,
192 return GetMockUrl("https", hostname
, data
, repeat_count
);