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