// Copyright (c) 2013 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 CHROME_BROWSER_POLICY_CLOUD_EXTERNAL_POLICY_DATA_UPDATER_H_
#define CHROME_BROWSER_POLICY_CLOUD_EXTERNAL_POLICY_DATA_UPDATER_H_

#include <map>
#include <queue>
#include <string>

#include "base/basictypes.h"
#include "base/callback_forward.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"

namespace base {
class SequencedTaskRunner;
}

namespace policy {

class ExternalPolicyDataFetcher;

// This class downloads external policy data. Given a |Request|, data is fetched
// from the |url|, verified to not exceed |max_size| and to match the expected
// |hash| and then handed to a callback that can do further verification before
// finally deciding whether the fetched data is valid.
// If a fetch is not successful or retrieves invalid data, retries are scheduled
// with exponential backoff.
// The actual fetching is handled by an ExternalPolicyDataFetcher, allowing this
// class to run on a background thread where network I/O is not possible.
class ExternalPolicyDataUpdater {
 public:
  struct Request {
   public:
    Request();
    Request(const std::string& url, const std::string& hash, int64 max_size);

    bool operator==(const Request& other) const;

    std::string url;
    std::string hash;
    int64 max_size;
  };

  // This callback is invoked when a fetch has successfully retrieved |data|
  // that does not exceed |max_size| and matches the expected |hash|. The
  // callback can do further verification to decide whether the fetched data is
  // valid.
  // If the callback returns |true|, the data is accepted and the |Request| is
  // finished. If the callback returns |false|, the data is rejected and the
  // fetch is retried after a long backoff. Note that in this case, the callback
  // may be invoked multiple times as the fetch is repeated. Make sure to not
  // bind base::Passed() scoped_ptrs to the callback in such cases as these
  // become invalid after a callback has been run once. base::Owned() can be
  // used in all cases.
  typedef base::Callback<bool(const std::string&)> FetchSuccessCallback;

  // This class runs on the background thread represented by |task_runner|,
  // which must support file I/O. All network I/O is forwarded to a different
  // thread by the |external_policy_data_fetcher|.
  ExternalPolicyDataUpdater(
      scoped_refptr<base::SequencedTaskRunner> task_runner,
      scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher,
      size_t max_parallel_fetches);
  ~ExternalPolicyDataUpdater();

  // Fetches the external data specified in the |request|. The |key| is an
  // opaque identifier. If another request for the same |key| is still pending,
  // it will be canceled and replaced with the new |request|. The callback will
  // be invoked after a successful fetch. See the documentation of
  // |FetchSuccessCallback| for more details.
  void FetchExternalData(const std::string key,
                         const Request& request,
                         const FetchSuccessCallback& callback);

  // Cancels the pending request identified by |key|. If no such request is
  // pending, does nothing.
  void CancelExternalDataFetch(const std::string& key);

 private:
  class FetchJob;

  // Starts jobs from the |job_queue_| until |max_parallel_jobs_| are running or
  // the queue is depleted.
  void StartNextJobs();

  // Appends |job| to the |job_queue_| and starts it immediately if less than
  // |max_parallel_jobs_| are running.
  void ScheduleJob(FetchJob* job);

  // Callback for jobs that succeeded.
  void OnJobSucceeded(FetchJob* job);

  // Callback for jobs that failed.
  void OnJobFailed(FetchJob* job);

  scoped_refptr<base::SequencedTaskRunner> task_runner_;
  scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher_;

  // The maximum number of jobs to run in parallel.
  size_t max_parallel_jobs_;

  // The number of jobs currently running.
  size_t running_jobs_;

  // Queue of jobs waiting to be run. Jobs are taken off the queue and started
  // by StartNextJobs().
  std::queue<base::WeakPtr<FetchJob> > job_queue_;

  // Map that owns all existing jobs, regardless of whether they are currently
  // queued, running or waiting for a retry.
  std::map<std::string, FetchJob*> job_map_;

  // |True| once the destructor starts. Prevents jobs from being started during
  // shutdown.
  bool shutting_down_;

  DISALLOW_COPY_AND_ASSIGN(ExternalPolicyDataUpdater);
};

}  // namespace policy

#endif  // CHROME_BROWSER_POLICY_CLOUD_EXTERNAL_POLICY_DATA_UPDATER_H_
