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