// Copyright (c) 2012 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.

#ifndef NET_PROXY_RESOLUTION_MOCK_PROXY_RESOLVER_H_
#define NET_PROXY_RESOLUTION_MOCK_PROXY_RESOLVER_H_

#include <memory>
#include <vector>

#include "base/macros.h"
#include "net/base/completion_once_callback.h"
#include "net/base/net_errors.h"
#include "net/proxy_resolution/proxy_resolver.h"
#include "net/proxy_resolution/proxy_resolver_factory.h"
#include "url/gurl.h"

namespace net {

// Asynchronous mock proxy resolver. All requests complete asynchronously,
// user must call Job::CompleteNow() on a pending request to signal it.
class MockAsyncProxyResolver : public ProxyResolver {
 public:
  class Job {
   public:
    Job(MockAsyncProxyResolver* resolver,
        const GURL& url,
        ProxyInfo* results,
        CompletionOnceCallback callback);

    const GURL& url() const { return url_; }
    ProxyInfo* results() const { return results_; }
    MockAsyncProxyResolver* Resolver() const { return resolver_; }

    void CompleteNow(int rv);

    ~Job();

   private:
    MockAsyncProxyResolver* resolver_;
    const GURL url_;
    ProxyInfo* results_;
    CompletionOnceCallback callback_;
  };

  class RequestImpl : public ProxyResolver::Request {
   public:
    explicit RequestImpl(std::unique_ptr<Job> job);

    ~RequestImpl() override;

    LoadState GetLoadState() override;

   private:
    std::unique_ptr<Job> job_;
  };

  MockAsyncProxyResolver();
  ~MockAsyncProxyResolver() override;

  // ProxyResolver implementation.
  int GetProxyForURL(const GURL& url,
                     ProxyInfo* results,
                     CompletionOnceCallback callback,
                     std::unique_ptr<Request>* request,
                     const NetLogWithSource& /*net_log*/) override;
  const std::vector<Job*>& pending_jobs() const { return pending_jobs_; }

  const std::vector<std::unique_ptr<Job>>& cancelled_jobs() const {
    return cancelled_jobs_;
  }

  void AddCancelledJob(std::unique_ptr<Job> job);
  void RemovePendingJob(Job* job);

 private:
  std::vector<Job*> pending_jobs_;
  std::vector<std::unique_ptr<Job>> cancelled_jobs_;
};

// Asynchronous mock proxy resolver factory . All requests complete
// asynchronously; the user must call Request::CompleteNow() on a pending
// request to signal it.
class MockAsyncProxyResolverFactory : public ProxyResolverFactory {
 public:
  class Request;
  using RequestsList = std::vector<scoped_refptr<Request>>;

  explicit MockAsyncProxyResolverFactory(bool resolvers_expect_pac_bytes);
  ~MockAsyncProxyResolverFactory() override;

  int CreateProxyResolver(
      const scoped_refptr<PacFileData>& pac_script,
      std::unique_ptr<ProxyResolver>* resolver,
      CompletionOnceCallback callback,
      std::unique_ptr<ProxyResolverFactory::Request>* request) override;

  const RequestsList& pending_requests() const { return pending_requests_; }

  const RequestsList& cancelled_requests() const { return cancelled_requests_; }

  void RemovePendingRequest(Request* request);

 private:
  class Job;
  RequestsList pending_requests_;
  RequestsList cancelled_requests_;
};

class MockAsyncProxyResolverFactory::Request
    : public base::RefCounted<Request> {
 public:
  Request(MockAsyncProxyResolverFactory* factory,
          const scoped_refptr<PacFileData>& script_data,
          std::unique_ptr<ProxyResolver>* resolver,
          CompletionOnceCallback callback);

  const scoped_refptr<PacFileData>& script_data() const { return script_data_; }

  // Completes this request. A ForwardingProxyResolver that forwards to
  // |resolver| will be returned to the requester. |resolver| must not be
  // null and must remain as long as the resolver returned by this request
  // remains in use.
  void CompleteNowWithForwarder(int rv, ProxyResolver* resolver);

  void CompleteNow(int rv, std::unique_ptr<ProxyResolver> resolver);

 private:
  friend class base::RefCounted<Request>;
  friend class MockAsyncProxyResolverFactory;
  friend class MockAsyncProxyResolverFactory::Job;

  ~Request();

  void FactoryDestroyed();

  MockAsyncProxyResolverFactory* factory_;
  const scoped_refptr<PacFileData> script_data_;
  std::unique_ptr<ProxyResolver>* resolver_;
  CompletionOnceCallback callback_;
};

// ForwardingProxyResolver forwards all requests to |impl|. |impl| must remain
// so long as this remains in use.
class ForwardingProxyResolver : public ProxyResolver {
 public:
  explicit ForwardingProxyResolver(ProxyResolver* impl);

  // ProxyResolver overrides.
  int GetProxyForURL(const GURL& query_url,
                     ProxyInfo* results,
                     CompletionOnceCallback callback,
                     std::unique_ptr<Request>* request,
                     const NetLogWithSource& net_log) override;

 private:
  ProxyResolver* impl_;

  DISALLOW_COPY_AND_ASSIGN(ForwardingProxyResolver);
};

}  // namespace net

#endif  // NET_PROXY_RESOLUTION_MOCK_PROXY_RESOLVER_H_
