| // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "net/proxy_resolution/mock_proxy_resolver.h" | 
 |  | 
 | #include <utility> | 
 |  | 
 | #include "base/logging.h" | 
 |  | 
 | namespace net { | 
 |  | 
 | MockAsyncProxyResolver::RequestImpl::RequestImpl(std::unique_ptr<Job> job) | 
 |     : job_(std::move(job)) { | 
 |   DCHECK(job_); | 
 | } | 
 |  | 
 | MockAsyncProxyResolver::RequestImpl::~RequestImpl() { | 
 |   MockAsyncProxyResolver* resolver = job_->Resolver(); | 
 |   // AddCancelledJob will check if request is already cancelled | 
 |   resolver->AddCancelledJob(std::move(job_)); | 
 | } | 
 |  | 
 | LoadState MockAsyncProxyResolver::RequestImpl::GetLoadState() { | 
 |   return LOAD_STATE_RESOLVING_PROXY_FOR_URL; | 
 | } | 
 |  | 
 | MockAsyncProxyResolver::Job::Job(MockAsyncProxyResolver* resolver, | 
 |                                  const GURL& url, | 
 |                                  ProxyInfo* results, | 
 |                                  CompletionOnceCallback callback) | 
 |     : resolver_(resolver), | 
 |       url_(url), | 
 |       results_(results), | 
 |       callback_(std::move(callback)) {} | 
 |  | 
 | MockAsyncProxyResolver::Job::~Job() = default; | 
 |  | 
 | void MockAsyncProxyResolver::Job::CompleteNow(int rv) { | 
 |   CompletionOnceCallback callback = std::move(callback_); | 
 |  | 
 |   resolver_->RemovePendingJob(this); | 
 |  | 
 |   std::move(callback).Run(rv); | 
 | } | 
 |  | 
 | MockAsyncProxyResolver::~MockAsyncProxyResolver() = default; | 
 |  | 
 | int MockAsyncProxyResolver::GetProxyForURL( | 
 |     const GURL& url, | 
 |     ProxyInfo* results, | 
 |     CompletionOnceCallback callback, | 
 |     std::unique_ptr<Request>* request, | 
 |     const NetLogWithSource& /*net_log*/) { | 
 |   std::unique_ptr<Job> job(new Job(this, url, results, std::move(callback))); | 
 |  | 
 |   pending_jobs_.push_back(job.get()); | 
 |   request->reset(new RequestImpl(std::move(job))); | 
 |  | 
 |   // Test code completes the request by calling job->CompleteNow(). | 
 |   return ERR_IO_PENDING; | 
 | } | 
 |  | 
 | void MockAsyncProxyResolver::AddCancelledJob(std::unique_ptr<Job> job) { | 
 |   auto it = std::find(pending_jobs_.begin(), pending_jobs_.end(), job.get()); | 
 |   // Because this is called always when RequestImpl is destructed, | 
 |   // we need to check if it is still in pending jobs. | 
 |   if (it != pending_jobs_.end()) { | 
 |     cancelled_jobs_.push_back(std::move(job)); | 
 |     pending_jobs_.erase(it); | 
 |   } | 
 | } | 
 |  | 
 | void MockAsyncProxyResolver::RemovePendingJob(Job* job) { | 
 |   DCHECK(job); | 
 |   auto it = std::find(pending_jobs_.begin(), pending_jobs_.end(), job); | 
 |   DCHECK(it != pending_jobs_.end()); | 
 |   pending_jobs_.erase(it); | 
 | } | 
 |  | 
 | MockAsyncProxyResolver::MockAsyncProxyResolver() = default; | 
 |  | 
 | MockAsyncProxyResolverFactory::Request::Request( | 
 |     MockAsyncProxyResolverFactory* factory, | 
 |     const scoped_refptr<PacFileData>& script_data, | 
 |     std::unique_ptr<ProxyResolver>* resolver, | 
 |     CompletionOnceCallback callback) | 
 |     : factory_(factory), | 
 |       script_data_(script_data), | 
 |       resolver_(resolver), | 
 |       callback_(std::move(callback)) {} | 
 |  | 
 | MockAsyncProxyResolverFactory::Request::~Request() = default; | 
 |  | 
 | void MockAsyncProxyResolverFactory::Request::CompleteNow( | 
 |     int rv, | 
 |     std::unique_ptr<ProxyResolver> resolver) { | 
 |   *resolver_ = std::move(resolver); | 
 |  | 
 |   // RemovePendingRequest may remove the last external reference to |this|. | 
 |   scoped_refptr<MockAsyncProxyResolverFactory::Request> keep_alive(this); | 
 |   factory_->RemovePendingRequest(this); | 
 |   factory_ = nullptr; | 
 |   std::move(callback_).Run(rv); | 
 | } | 
 |  | 
 | void MockAsyncProxyResolverFactory::Request::CompleteNowWithForwarder( | 
 |     int rv, | 
 |     ProxyResolver* resolver) { | 
 |   DCHECK(resolver); | 
 |   CompleteNow(rv, std::make_unique<ForwardingProxyResolver>(resolver)); | 
 | } | 
 |  | 
 | void MockAsyncProxyResolverFactory::Request::FactoryDestroyed() { | 
 |   factory_ = nullptr; | 
 | } | 
 |  | 
 | class MockAsyncProxyResolverFactory::Job | 
 |     : public ProxyResolverFactory::Request { | 
 |  public: | 
 |   explicit Job( | 
 |       const scoped_refptr<MockAsyncProxyResolverFactory::Request>& request) | 
 |       : request_(request) {} | 
 |   ~Job() override { | 
 |     if (request_->factory_) { | 
 |       request_->factory_->cancelled_requests_.push_back(request_); | 
 |       request_->factory_->RemovePendingRequest(request_.get()); | 
 |     } | 
 |   } | 
 |  | 
 |  private: | 
 |   scoped_refptr<MockAsyncProxyResolverFactory::Request> request_; | 
 | }; | 
 |  | 
 | MockAsyncProxyResolverFactory::MockAsyncProxyResolverFactory( | 
 |     bool resolvers_expect_pac_bytes) | 
 |     : ProxyResolverFactory(resolvers_expect_pac_bytes) { | 
 | } | 
 |  | 
 | int MockAsyncProxyResolverFactory::CreateProxyResolver( | 
 |     const scoped_refptr<PacFileData>& pac_script, | 
 |     std::unique_ptr<ProxyResolver>* resolver, | 
 |     CompletionOnceCallback callback, | 
 |     std::unique_ptr<ProxyResolverFactory::Request>* request_handle) { | 
 |   scoped_refptr<Request> request = | 
 |       new Request(this, pac_script, resolver, std::move(callback)); | 
 |   pending_requests_.push_back(request); | 
 |  | 
 |   request_handle->reset(new Job(request)); | 
 |  | 
 |   // Test code completes the request by calling request->CompleteNow(). | 
 |   return ERR_IO_PENDING; | 
 | } | 
 |  | 
 | void MockAsyncProxyResolverFactory::RemovePendingRequest(Request* request) { | 
 |   auto it = | 
 |       std::find(pending_requests_.begin(), pending_requests_.end(), request); | 
 |   DCHECK(it != pending_requests_.end()); | 
 |   pending_requests_.erase(it); | 
 | } | 
 |  | 
 | MockAsyncProxyResolverFactory::~MockAsyncProxyResolverFactory() { | 
 |   for (auto& request : pending_requests_) { | 
 |     request->FactoryDestroyed(); | 
 |   } | 
 | } | 
 |  | 
 | ForwardingProxyResolver::ForwardingProxyResolver(ProxyResolver* impl) | 
 |     : impl_(impl) { | 
 | } | 
 |  | 
 | int ForwardingProxyResolver::GetProxyForURL(const GURL& query_url, | 
 |                                             ProxyInfo* results, | 
 |                                             CompletionOnceCallback callback, | 
 |                                             std::unique_ptr<Request>* request, | 
 |                                             const NetLogWithSource& net_log) { | 
 |   return impl_->GetProxyForURL(query_url, results, std::move(callback), request, | 
 |                                net_log); | 
 | } | 
 |  | 
 | }  // namespace net |