1 // Copyright 2016 The Chromium Authors
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/test/url_request/url_request_hanging_read_job.h"
6
7 #include <memory>
8 #include <string>
9
10 #include "base/functional/bind.h"
11 #include "base/location.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/task/single_thread_task_runner.h"
14 #include "net/http/http_response_headers.h"
15 #include "net/http/http_util.h"
16 #include "net/url_request/url_request.h"
17 #include "net/url_request/url_request_filter.h"
18
19 namespace net {
20 namespace {
21
22 const char kMockHostname[] = "mock.hanging.read";
23
GetMockUrl(const std::string & scheme,const std::string & hostname)24 GURL GetMockUrl(const std::string& scheme, const std::string& hostname) {
25 return GURL(scheme + "://" + hostname + "/");
26 }
27
28 class MockJobInterceptor : public URLRequestInterceptor {
29 public:
30 MockJobInterceptor() = default;
31
32 MockJobInterceptor(const MockJobInterceptor&) = delete;
33 MockJobInterceptor& operator=(const MockJobInterceptor&) = delete;
34
35 ~MockJobInterceptor() override = default;
36
37 // URLRequestInterceptor implementation
MaybeInterceptRequest(URLRequest * request) const38 std::unique_ptr<URLRequestJob> MaybeInterceptRequest(
39 URLRequest* request) const override {
40 return std::make_unique<URLRequestHangingReadJob>(request);
41 }
42 };
43
44 } // namespace
45
URLRequestHangingReadJob(URLRequest * request)46 URLRequestHangingReadJob::URLRequestHangingReadJob(URLRequest* request)
47 : URLRequestJob(request) {}
48
49 URLRequestHangingReadJob::~URLRequestHangingReadJob() = default;
50
Start()51 void URLRequestHangingReadJob::Start() {
52 // Start reading asynchronously so that all error reporting and data
53 // callbacks happen as they would for network requests.
54 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
55 FROM_HERE, base::BindOnce(&URLRequestHangingReadJob::StartAsync,
56 weak_factory_.GetWeakPtr()));
57 }
58
ReadRawData(IOBuffer * buf,int buf_size)59 int URLRequestHangingReadJob::ReadRawData(IOBuffer* buf, int buf_size) {
60 // Make read hang. It never completes.
61 return ERR_IO_PENDING;
62 }
63
64 // Public virtual version.
GetResponseInfo(HttpResponseInfo * info)65 void URLRequestHangingReadJob::GetResponseInfo(HttpResponseInfo* info) {
66 // Forward to private const version.
67 GetResponseInfoConst(info);
68 }
69
70 // Private const version.
GetResponseInfoConst(HttpResponseInfo * info) const71 void URLRequestHangingReadJob::GetResponseInfoConst(
72 HttpResponseInfo* info) const {
73 // Send back mock headers.
74 std::string raw_headers;
75 raw_headers.append(
76 "HTTP/1.1 200 OK\n"
77 "Content-type: text/plain\n");
78 raw_headers.append(
79 base::StringPrintf("Content-Length: %1d\n", content_length_));
80 info->headers = base::MakeRefCounted<HttpResponseHeaders>(
81 HttpUtil::AssembleRawHeaders(raw_headers));
82 }
83
StartAsync()84 void URLRequestHangingReadJob::StartAsync() {
85 if (is_done())
86 return;
87 set_expected_content_size(content_length_);
88 NotifyHeadersComplete();
89 }
90
91 // static
AddUrlHandler()92 void URLRequestHangingReadJob::AddUrlHandler() {
93 // Add |hostname| to URLRequestFilter for HTTP and HTTPS.
94 URLRequestFilter* filter = URLRequestFilter::GetInstance();
95 filter->AddHostnameInterceptor("http", kMockHostname,
96 std::make_unique<MockJobInterceptor>());
97 filter->AddHostnameInterceptor("https", kMockHostname,
98 std::make_unique<MockJobInterceptor>());
99 }
100
101 // static
GetMockHttpUrl()102 GURL URLRequestHangingReadJob::GetMockHttpUrl() {
103 return GetMockUrl("http", kMockHostname);
104 }
105
106 // static
GetMockHttpsUrl()107 GURL URLRequestHangingReadJob::GetMockHttpsUrl() {
108 return GetMockUrl("https", kMockHostname);
109 }
110
111 } // namespace net
112