1 // Copyright 2011 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/proxy_resolution/mock_proxy_resolver.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/check.h"
11 #include "base/not_fatal_until.h"
12 #include "base/ranges/algorithm.h"
13
14 namespace net {
15
RequestImpl(std::unique_ptr<Job> job)16 MockAsyncProxyResolver::RequestImpl::RequestImpl(std::unique_ptr<Job> job)
17 : job_(std::move(job)) {
18 DCHECK(job_);
19 }
20
~RequestImpl()21 MockAsyncProxyResolver::RequestImpl::~RequestImpl() {
22 MockAsyncProxyResolver* resolver = job_->Resolver();
23 // AddCancelledJob will check if request is already cancelled
24 resolver->AddCancelledJob(std::move(job_));
25 }
26
GetLoadState()27 LoadState MockAsyncProxyResolver::RequestImpl::GetLoadState() {
28 return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
29 }
30
Job(MockAsyncProxyResolver * resolver,const GURL & url,ProxyInfo * results,CompletionOnceCallback callback)31 MockAsyncProxyResolver::Job::Job(MockAsyncProxyResolver* resolver,
32 const GURL& url,
33 ProxyInfo* results,
34 CompletionOnceCallback callback)
35 : resolver_(resolver),
36 url_(url),
37 results_(results),
38 callback_(std::move(callback)) {}
39
40 MockAsyncProxyResolver::Job::~Job() = default;
41
CompleteNow(int rv)42 void MockAsyncProxyResolver::Job::CompleteNow(int rv) {
43 CompletionOnceCallback callback = std::move(callback_);
44
45 resolver_->RemovePendingJob(this);
46
47 std::move(callback).Run(rv);
48 }
49
50 MockAsyncProxyResolver::~MockAsyncProxyResolver() = default;
51
GetProxyForURL(const GURL & url,const NetworkAnonymizationKey & network_anonymization_key,ProxyInfo * results,CompletionOnceCallback callback,std::unique_ptr<Request> * request,const NetLogWithSource &)52 int MockAsyncProxyResolver::GetProxyForURL(
53 const GURL& url,
54 const NetworkAnonymizationKey& network_anonymization_key,
55 ProxyInfo* results,
56 CompletionOnceCallback callback,
57 std::unique_ptr<Request>* request,
58 const NetLogWithSource& /*net_log*/) {
59 auto job = std::make_unique<Job>(this, url, results, std::move(callback));
60
61 pending_jobs_.push_back(job.get());
62 *request = std::make_unique<RequestImpl>(std::move(job));
63
64 // Test code completes the request by calling job->CompleteNow().
65 return ERR_IO_PENDING;
66 }
67
AddCancelledJob(std::unique_ptr<Job> job)68 void MockAsyncProxyResolver::AddCancelledJob(std::unique_ptr<Job> job) {
69 auto it = base::ranges::find(pending_jobs_, job.get());
70 // Because this is called always when RequestImpl is destructed,
71 // we need to check if it is still in pending jobs.
72 if (it != pending_jobs_.end()) {
73 cancelled_jobs_.push_back(std::move(job));
74 pending_jobs_.erase(it);
75 }
76 }
77
RemovePendingJob(Job * job)78 void MockAsyncProxyResolver::RemovePendingJob(Job* job) {
79 DCHECK(job);
80 auto it = base::ranges::find(pending_jobs_, job);
81 CHECK(it != pending_jobs_.end(), base::NotFatalUntil::M130);
82 pending_jobs_.erase(it);
83 }
84
85 MockAsyncProxyResolver::MockAsyncProxyResolver() = default;
86
Request(MockAsyncProxyResolverFactory * factory,const scoped_refptr<PacFileData> & script_data,std::unique_ptr<ProxyResolver> * resolver,CompletionOnceCallback callback)87 MockAsyncProxyResolverFactory::Request::Request(
88 MockAsyncProxyResolverFactory* factory,
89 const scoped_refptr<PacFileData>& script_data,
90 std::unique_ptr<ProxyResolver>* resolver,
91 CompletionOnceCallback callback)
92 : factory_(factory),
93 script_data_(script_data),
94 resolver_(resolver),
95 callback_(std::move(callback)) {}
96
97 MockAsyncProxyResolverFactory::Request::~Request() = default;
98
CompleteNow(int rv,std::unique_ptr<ProxyResolver> resolver)99 void MockAsyncProxyResolverFactory::Request::CompleteNow(
100 int rv,
101 std::unique_ptr<ProxyResolver> resolver) {
102 *resolver_ = std::move(resolver);
103
104 // RemovePendingRequest may remove the last external reference to |this|.
105 scoped_refptr<MockAsyncProxyResolverFactory::Request> keep_alive(this);
106 factory_->RemovePendingRequest(this);
107 factory_ = nullptr;
108 std::move(callback_).Run(rv);
109 }
110
CompleteNowWithForwarder(int rv,ProxyResolver * resolver)111 void MockAsyncProxyResolverFactory::Request::CompleteNowWithForwarder(
112 int rv,
113 ProxyResolver* resolver) {
114 DCHECK(resolver);
115 CompleteNow(rv, std::make_unique<ForwardingProxyResolver>(resolver));
116 }
117
FactoryDestroyed()118 void MockAsyncProxyResolverFactory::Request::FactoryDestroyed() {
119 factory_ = nullptr;
120 }
121
122 class MockAsyncProxyResolverFactory::Job
123 : public ProxyResolverFactory::Request {
124 public:
Job(const scoped_refptr<MockAsyncProxyResolverFactory::Request> & request)125 explicit Job(
126 const scoped_refptr<MockAsyncProxyResolverFactory::Request>& request)
127 : request_(request) {}
~Job()128 ~Job() override {
129 if (request_->factory_) {
130 request_->factory_->cancelled_requests_.push_back(request_);
131 request_->factory_->RemovePendingRequest(request_.get());
132 }
133 }
134
135 private:
136 scoped_refptr<MockAsyncProxyResolverFactory::Request> request_;
137 };
138
MockAsyncProxyResolverFactory(bool resolvers_expect_pac_bytes)139 MockAsyncProxyResolverFactory::MockAsyncProxyResolverFactory(
140 bool resolvers_expect_pac_bytes)
141 : ProxyResolverFactory(resolvers_expect_pac_bytes) {
142 }
143
CreateProxyResolver(const scoped_refptr<PacFileData> & pac_script,std::unique_ptr<ProxyResolver> * resolver,CompletionOnceCallback callback,std::unique_ptr<ProxyResolverFactory::Request> * request_handle)144 int MockAsyncProxyResolverFactory::CreateProxyResolver(
145 const scoped_refptr<PacFileData>& pac_script,
146 std::unique_ptr<ProxyResolver>* resolver,
147 CompletionOnceCallback callback,
148 std::unique_ptr<ProxyResolverFactory::Request>* request_handle) {
149 auto request = base::MakeRefCounted<Request>(this, pac_script, resolver,
150 std::move(callback));
151 pending_requests_.push_back(request);
152
153 *request_handle = std::make_unique<Job>(request);
154
155 // Test code completes the request by calling request->CompleteNow().
156 return ERR_IO_PENDING;
157 }
158
RemovePendingRequest(Request * request)159 void MockAsyncProxyResolverFactory::RemovePendingRequest(Request* request) {
160 auto it = base::ranges::find(pending_requests_, request);
161 CHECK(it != pending_requests_.end(), base::NotFatalUntil::M130);
162 pending_requests_.erase(it);
163 }
164
~MockAsyncProxyResolverFactory()165 MockAsyncProxyResolverFactory::~MockAsyncProxyResolverFactory() {
166 for (auto& request : pending_requests_) {
167 request->FactoryDestroyed();
168 }
169 }
170
ForwardingProxyResolver(ProxyResolver * impl)171 ForwardingProxyResolver::ForwardingProxyResolver(ProxyResolver* impl)
172 : impl_(impl) {
173 }
174
GetProxyForURL(const GURL & query_url,const NetworkAnonymizationKey & network_anonymization_key,ProxyInfo * results,CompletionOnceCallback callback,std::unique_ptr<Request> * request,const NetLogWithSource & net_log)175 int ForwardingProxyResolver::GetProxyForURL(
176 const GURL& query_url,
177 const NetworkAnonymizationKey& network_anonymization_key,
178 ProxyInfo* results,
179 CompletionOnceCallback callback,
180 std::unique_ptr<Request>* request,
181 const NetLogWithSource& net_log) {
182 return impl_->GetProxyForURL(query_url, network_anonymization_key, results,
183 std::move(callback), request, net_log);
184 }
185
186 } // namespace net
187