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