// 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.

#include "webkit/quota/quota_manager.h"

#include <algorithm>
#include <deque>
#include <set>

#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/message_loop_proxy.h"
#include "base/metrics/histogram.h"
#include "base/string_number_conversions.h"
#include "base/sys_info.h"
#include "base/time.h"
#include "net/base/net_util.h"
#include "webkit/quota/quota_database.h"
#include "webkit/quota/quota_temporary_storage_evictor.h"
#include "webkit/quota/quota_types.h"
#include "webkit/quota/usage_tracker.h"

#define UMA_HISTOGRAM_MBYTES(name, sample)          \
  UMA_HISTOGRAM_CUSTOM_COUNTS(                      \
      (name), static_cast<int>((sample) / kMBytes), \
      1, 10 * 1024 * 1024 /* 10TB */, 100)

namespace quota {

namespace {

const int64 kMBytes = 1024 * 1024;
const int kMinutesInMilliSeconds = 60 * 1000;

const int64 kIncognitoDefaultTemporaryQuota = 50 * kMBytes;
const int64 kReportHistogramInterval = 60 * 60 * 1000;  // 1 hour
const double kTemporaryQuotaRatioToAvail = 0.5;  // 50%

void CountOriginType(const std::set<GURL>& origins,
                     SpecialStoragePolicy* policy,
                     size_t* protected_origins,
                     size_t* unlimited_origins) {
  DCHECK(protected_origins);
  DCHECK(unlimited_origins);
  *protected_origins = 0;
  *unlimited_origins = 0;
  if (!policy)
    return;
  for (std::set<GURL>::const_iterator itr = origins.begin();
       itr != origins.end();
       ++itr) {
    if (policy->IsStorageProtected(*itr))
      ++*protected_origins;
    if (policy->IsStorageUnlimited(*itr))
      ++*unlimited_origins;
  }
}

}  // anonymous namespace

const int QuotaManager::kPerHostTemporaryPortion = 5;  // 20%

const char QuotaManager::kDatabaseName[] = "QuotaManager";

const int QuotaManager::kThresholdOfErrorsToBeBlacklisted = 3;

const int QuotaManager::kEvictionIntervalInMilliSeconds =
    30 * kMinutesInMilliSeconds;

// Callback translators.
void CallGetUsageAndQuotaCallback(
    const QuotaManager::GetUsageAndQuotaCallback& callback,
    bool unlimited,
    QuotaStatusCode status,
    const QuotaAndUsage& quota_and_usage) {
  int64 usage =
      unlimited ? quota_and_usage.unlimited_usage : quota_and_usage.usage;
  int64 quota = unlimited ? kint64max : quota_and_usage.quota;
  callback.Run(status, usage, quota);
}

void CallQuotaCallback(
    const QuotaCallback& callback,
    StorageType type,
    QuotaStatusCode status,
    const QuotaAndUsage& quota_and_usage) {
  callback.Run(status, type, quota_and_usage.quota);
}

// This class is for posting GetUsage/GetQuota tasks, gathering
// results and dispatching GetAndQuota callbacks.
// This class is self-destructed.
class QuotaManager::UsageAndQuotaDispatcherTask : public QuotaTask {
 public:
  typedef UsageAndQuotaDispatcherCallback Callback;
  typedef std::deque<Callback> CallbackList;

  static UsageAndQuotaDispatcherTask* Create(
      QuotaManager* manager,
      bool global,
      const HostAndType& host_and_type);

  // Returns true if it is the first call for this task; which means
  // the caller needs to call Start().
  bool AddCallback(const Callback& callback) {
    callbacks_.push_back(callback);
    return (callbacks_.size() == 1);
  }

  void DidGetGlobalUsage(StorageType type, int64 usage, int64 unlimited_usage) {
    DCHECK_EQ(this->type(), type);
    DCHECK_GE(usage, unlimited_usage);
    if (quota_status_ == kQuotaStatusUnknown)
      quota_status_ = kQuotaStatusOk;
    global_usage_ = usage;
    global_unlimited_usage_ = unlimited_usage;
    CheckCompleted();
  }

  void DidGetHostUsage(const std::string& host, StorageType type, int64 usage) {
    DCHECK_EQ(this->host(), host);
    DCHECK_EQ(this->type(), type);
    host_usage_ = usage;
    CheckCompleted();
  }

  void DidGetHostQuota(QuotaStatusCode status,
                       const std::string& host,
                       StorageType type,
                       int64 host_quota) {
    DCHECK_EQ(this->host(), host);
    DCHECK_EQ(this->type(), type);
    if (quota_status_ == kQuotaStatusUnknown || quota_status_ == kQuotaStatusOk)
      quota_status_ = status;
    host_quota_ = host_quota;
    CheckCompleted();
  }

  void DidGetAvailableSpace(QuotaStatusCode status, int64 space) {
    DCHECK_GE(space, 0);
    if (quota_status_ == kQuotaStatusUnknown || quota_status_ == kQuotaStatusOk)
      quota_status_ = status;
    available_space_ = space;
    CheckCompleted();
  }

  bool IsStartable() const {
    return !started_ && !callbacks_.empty();
  }

 protected:
  UsageAndQuotaDispatcherTask(
      QuotaManager* manager,
      const HostAndType& host_and_type)
      : QuotaTask(manager),
        host_and_type_(host_and_type),
        started_(false),
        host_quota_(-1),
        global_usage_(-1),
        global_unlimited_usage_(-1),
        host_usage_(-1),
        available_space_(-1),
        quota_status_(kQuotaStatusUnknown),
        waiting_callbacks_(1),
        weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}

  virtual ~UsageAndQuotaDispatcherTask() {}

  // Subclasses must implement them.
  virtual void RunBody() = 0;
  virtual void DispatchCallbacks() = 0;

  virtual void Run() OVERRIDE {
    DCHECK(!started_);
    started_ = true;
    RunBody();
    // We initialize waiting_callbacks to 1 so that we won't run
    // the completion callback until here even some of the callbacks
    // are dispatched synchronously.
    CheckCompleted();
  }

  virtual void Aborted() OVERRIDE {
    CallCallbacksAndClear(kQuotaErrorAbort, 0, 0, 0, 0);
    DeleteSoon();
  }

  virtual void Completed() OVERRIDE {
    DeleteSoon();
  }

  void CallCallbacksAndClear(
      QuotaStatusCode status,
      int64 usage, int64 unlimited_usage, int64 quota,
      int64 available_space) {
    QuotaAndUsage qau = { usage, unlimited_usage, quota, available_space };
    for (CallbackList::iterator iter = callbacks_.begin();
         iter != callbacks_.end(); ++iter) {
      (*iter).Run(status, qau);
    }
    callbacks_.clear();
  }

  QuotaManager* manager() const {
    return static_cast<QuotaManager*>(observer());
  }

  std::string host() const { return host_and_type_.first; }
  virtual StorageType type() const { return host_and_type_.second; }
  int64 host_quota() const { return host_quota_; }
  int64 global_usage() const { return global_usage_; }
  int64 global_unlimited_usage() const { return global_unlimited_usage_; }
  int64 host_usage() const { return host_usage_; }
  int64 available_space() const { return available_space_; }
  QuotaStatusCode quota_status() const { return quota_status_; }
  CallbackList& callbacks() { return callbacks_; }

  // The main logic that determines the temporary global quota.
  int64 temporary_global_quota() const {
    DCHECK_EQ(type(), kStorageTypeTemporary);
    DCHECK(manager());
    DCHECK_GE(global_usage(), global_unlimited_usage());
    if (manager()->temporary_quota_override_ > 0) {
      // If the user has specified an explicit temporary quota, use the value.
      return manager()->temporary_quota_override_;
    }
    int64 limited_usage = global_usage() - global_unlimited_usage();
    int64 avail_space = available_space();
    if (avail_space < kint64max - limited_usage) {
      // We basically calculate the temporary quota by
      // [available_space + space_used_for_temp] * kTempQuotaRatio,
      // but make sure we'll have no overflow.
      avail_space += limited_usage;
    }
    return avail_space * kTemporaryQuotaRatioToAvail;
  }

  // Subclasses must call following methods to create a new 'waitable'
  // callback, which decrements waiting_callbacks when it is called.
  GlobalUsageCallback NewWaitableGlobalUsageCallback() {
    ++waiting_callbacks_;
    return base::Bind(&UsageAndQuotaDispatcherTask::DidGetGlobalUsage,
                      weak_factory_.GetWeakPtr());
  }
  HostUsageCallback NewWaitableHostUsageCallback() {
    ++waiting_callbacks_;
    return base::Bind(&UsageAndQuotaDispatcherTask::DidGetHostUsage,
                      weak_factory_.GetWeakPtr());
  }
  HostQuotaCallback NewWaitableHostQuotaCallback() {
    ++waiting_callbacks_;
    return base::Bind(&UsageAndQuotaDispatcherTask::DidGetHostQuota,
                      weak_factory_.GetWeakPtr());
  }
  AvailableSpaceCallback NewWaitableAvailableSpaceCallback() {
    ++waiting_callbacks_;
    return base::Bind(&UsageAndQuotaDispatcherTask::DidGetAvailableSpace,
                      weak_factory_.GetWeakPtr());
  }


 private:
  void CheckCompleted() {
    if (--waiting_callbacks_ <= 0) {
      DispatchCallbacks();
      DCHECK(callbacks_.empty());

      UsageAndQuotaDispatcherTaskMap& dispatcher_map =
          manager()->usage_and_quota_dispatchers_;
      DCHECK(dispatcher_map.find(host_and_type_) != dispatcher_map.end());
      dispatcher_map.erase(host_and_type_);
      CallCompleted();
    }
  }

  const std::string host_;
  const HostAndType host_and_type_;
  bool started_;
  int64 host_quota_;
  int64 global_usage_;
  int64 global_unlimited_usage_;
  int64 host_usage_;
  int64 available_space_;
  QuotaStatusCode quota_status_;
  CallbackList callbacks_;
  int waiting_callbacks_;
  base::WeakPtrFactory<UsageAndQuotaDispatcherTask> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(UsageAndQuotaDispatcherTask);
};

class QuotaManager::GetUsageInfoTask : public QuotaTask {
 private:
  typedef QuotaManager::GetUsageInfoTask self_type;

 public:
  GetUsageInfoTask(
      QuotaManager* manager,
      const GetUsageInfoCallback& callback)
      : QuotaTask(manager),
        callback_(callback),
        weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
  }
 protected:
  virtual void Run() OVERRIDE {
    remaining_trackers_ = 2;
    // This will populate cached hosts and usage info.
    manager()->GetUsageTracker(kStorageTypeTemporary)->GetGlobalUsage(
        base::Bind(&GetUsageInfoTask::DidGetGlobalUsage,
                   weak_factory_.GetWeakPtr()));
    manager()->GetUsageTracker(kStorageTypePersistent)->GetGlobalUsage(
        base::Bind(&GetUsageInfoTask::DidGetGlobalUsage,
                   weak_factory_.GetWeakPtr()));
  }

  virtual void Completed() OVERRIDE {
    callback_.Run(entries_);
    DeleteSoon();
  }

  virtual void Aborted() OVERRIDE {
    callback_.Run(UsageInfoEntries());
    DeleteSoon();
  }

 private:
  void AddEntries(StorageType type, UsageTracker* tracker) {
    std::map<std::string, int64> host_usage;
    tracker->GetCachedHostsUsage(&host_usage);
    for (std::map<std::string, int64>::const_iterator iter = host_usage.begin();
         iter != host_usage.end();
         ++iter) {
      entries_.push_back(UsageInfo(iter->first, type, iter->second));
    }
    if (--remaining_trackers_ == 0)
      CallCompleted();
  }

  void DidGetGlobalUsage(StorageType type, int64, int64) {
    AddEntries(type, manager()->GetUsageTracker(type));
  }

  QuotaManager* manager() const {
    return static_cast<QuotaManager*>(observer());
  }

  GetUsageInfoCallback callback_;
  UsageInfoEntries entries_;
  base::WeakPtrFactory<GetUsageInfoTask> weak_factory_;
  int remaining_trackers_;

  DISALLOW_COPY_AND_ASSIGN(GetUsageInfoTask);
};

class QuotaManager::UsageAndQuotaDispatcherTaskForTemporary
    : public QuotaManager::UsageAndQuotaDispatcherTask {
 public:
  UsageAndQuotaDispatcherTaskForTemporary(
      QuotaManager* manager, const HostAndType& host_and_type)
      : UsageAndQuotaDispatcherTask(manager, host_and_type) {}

 protected:
  virtual void RunBody() OVERRIDE {
    manager()->temporary_usage_tracker_->GetGlobalUsage(
        NewWaitableGlobalUsageCallback());
    manager()->temporary_usage_tracker_->GetHostUsage(
        host(), NewWaitableHostUsageCallback());
    manager()->GetAvailableSpace(NewWaitableAvailableSpaceCallback());
  }

  virtual void DispatchCallbacks() OVERRIDE {
    // Allow an individual host to utilize a fraction of the total
    // pool available for temp storage.
    int64 host_quota = temporary_global_quota() / kPerHostTemporaryPortion;

    // But if total temp usage is over-budget, stop letting new data in
    // until we reclaim space.
    DCHECK_GE(global_usage(), global_unlimited_usage());
    int64 limited_global_usage = global_usage() - global_unlimited_usage();
    if (limited_global_usage > temporary_global_quota())
      host_quota = std::min(host_quota, host_usage());

    CallCallbacksAndClear(quota_status(),
                          host_usage(), host_usage(), host_quota,
                          available_space());
  }
};

class QuotaManager::UsageAndQuotaDispatcherTaskForPersistent
    : public QuotaManager::UsageAndQuotaDispatcherTask {
 public:
  UsageAndQuotaDispatcherTaskForPersistent(
      QuotaManager* manager, const HostAndType& host_and_type)
      : UsageAndQuotaDispatcherTask(manager, host_and_type) {}

 protected:
  virtual void RunBody() OVERRIDE {
    manager()->persistent_usage_tracker_->GetHostUsage(
        host(), NewWaitableHostUsageCallback());
    manager()->GetPersistentHostQuota(
        host(), NewWaitableHostQuotaCallback());
  }

  virtual void DispatchCallbacks() OVERRIDE {
    CallCallbacksAndClear(quota_status(),
                          host_usage(), host_usage(), host_quota(),
                          available_space());
  }
};

class QuotaManager::UsageAndQuotaDispatcherTaskForTemporaryGlobal
    : public QuotaManager::UsageAndQuotaDispatcherTask {
 public:
  UsageAndQuotaDispatcherTaskForTemporaryGlobal(
      QuotaManager* manager, const HostAndType& host_and_type)
      : UsageAndQuotaDispatcherTask(manager, host_and_type) {}

 protected:
  virtual void RunBody() OVERRIDE {
    manager()->temporary_usage_tracker_->GetGlobalUsage(
        NewWaitableGlobalUsageCallback());
    manager()->GetAvailableSpace(NewWaitableAvailableSpaceCallback());
  }

  virtual void DispatchCallbacks() OVERRIDE {
    CallCallbacksAndClear(quota_status(),
                          global_usage(), global_unlimited_usage(),
                          temporary_global_quota(),
                          available_space());
  }

  virtual StorageType type() const { return kStorageTypeTemporary; }
};

// static
QuotaManager::UsageAndQuotaDispatcherTask*
QuotaManager::UsageAndQuotaDispatcherTask::Create(
    QuotaManager* manager, bool global,
    const QuotaManager::HostAndType& host_and_type) {
  if (global)
    return new UsageAndQuotaDispatcherTaskForTemporaryGlobal(
        manager, host_and_type);
  switch (host_and_type.second) {
    case kStorageTypeTemporary:
      return new UsageAndQuotaDispatcherTaskForTemporary(
          manager, host_and_type);
    case kStorageTypePersistent:
      return new UsageAndQuotaDispatcherTaskForPersistent(
          manager, host_and_type);
    default:
      NOTREACHED();
  }
  return NULL;
}

class QuotaManager::OriginDataDeleter : public QuotaTask {
 public:
  OriginDataDeleter(QuotaManager* manager,
                    const GURL& origin,
                    StorageType type,
                    int quota_client_mask,
                    const StatusCallback& callback)
      : QuotaTask(manager),
        origin_(origin),
        type_(type),
        quota_client_mask_(quota_client_mask),
        error_count_(0),
        remaining_clients_(-1),
        skipped_clients_(0),
        callback_(callback),
        weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}

 protected:
  virtual void Run() OVERRIDE {
    error_count_ = 0;
    remaining_clients_ = manager()->clients_.size();
    for (QuotaClientList::iterator iter = manager()->clients_.begin();
         iter != manager()->clients_.end(); ++iter) {
      if (quota_client_mask_ & (*iter)->id()) {
        (*iter)->DeleteOriginData(
            origin_, type_,
            base::Bind(&OriginDataDeleter::DidDeleteOriginData,
                       weak_factory_.GetWeakPtr()));
      } else {
        ++skipped_clients_;
        if (--remaining_clients_ == 0)
          CallCompleted();
      }
    }
  }

  virtual void Completed() OVERRIDE {
    if (error_count_ == 0) {
      // Only remove the entire origin if we didn't skip any client types.
      if (skipped_clients_ == 0)
        manager()->DeleteOriginFromDatabase(origin_, type_);
      callback_.Run(kQuotaStatusOk);
    } else {
      callback_.Run(kQuotaErrorInvalidModification);
    }
    DeleteSoon();
  }

  virtual void Aborted() OVERRIDE {
    callback_.Run(kQuotaErrorAbort);
    DeleteSoon();
  }

  void DidDeleteOriginData(QuotaStatusCode status) {
    DCHECK_GT(remaining_clients_, 0);

    if (status != kQuotaStatusOk)
      ++error_count_;

    if (--remaining_clients_ == 0)
      CallCompleted();
  }

  QuotaManager* manager() const {
    return static_cast<QuotaManager*>(observer());
  }

  GURL origin_;
  StorageType type_;
  int quota_client_mask_;
  int error_count_;
  int remaining_clients_;
  int skipped_clients_;
  StatusCallback callback_;

  base::WeakPtrFactory<OriginDataDeleter> weak_factory_;
  DISALLOW_COPY_AND_ASSIGN(OriginDataDeleter);
};

class QuotaManager::HostDataDeleter : public QuotaTask {
 public:
  HostDataDeleter(QuotaManager* manager,
                  const std::string& host,
                  StorageType type,
                  int quota_client_mask,
                  const StatusCallback& callback)
      : QuotaTask(manager),
        host_(host),
        type_(type),
        quota_client_mask_(quota_client_mask),
        error_count_(0),
        remaining_clients_(-1),
        remaining_deleters_(-1),
        callback_(callback),
        weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}

 protected:
  virtual void Run() OVERRIDE {
    error_count_ = 0;
    remaining_clients_ = manager()->clients_.size();
    for (QuotaClientList::iterator iter = manager()->clients_.begin();
         iter != manager()->clients_.end(); ++iter) {
      (*iter)->GetOriginsForHost(
          type_, host_,
          base::Bind(&HostDataDeleter::DidGetOriginsForHost,
                     weak_factory_.GetWeakPtr()));
    }
  }

  virtual void Completed() OVERRIDE {
    if (error_count_ == 0) {
      callback_.Run(kQuotaStatusOk);
    } else {
      callback_.Run(kQuotaErrorInvalidModification);
    }
    DeleteSoon();
  }

  virtual void Aborted() OVERRIDE {
    callback_.Run(kQuotaErrorAbort);
    DeleteSoon();
  }

  void DidGetOriginsForHost(const std::set<GURL>& origins, StorageType type) {
    DCHECK_GT(remaining_clients_, 0);

    origins_.insert(origins.begin(), origins.end());

    if (--remaining_clients_ == 0) {
      if (!origins_.empty())
        ScheduleOriginsDeletion();
      else
        CallCompleted();
    }
  }

  void ScheduleOriginsDeletion() {
    remaining_deleters_ = origins_.size();
    for (std::set<GURL>::const_iterator p = origins_.begin();
         p != origins_.end();
         ++p) {
      OriginDataDeleter* deleter =
          new OriginDataDeleter(
              manager(), *p, type_, quota_client_mask_,
              base::Bind(&HostDataDeleter::DidDeleteOriginData,
                         weak_factory_.GetWeakPtr()));
      deleter->Start();
    }
  }

  void DidDeleteOriginData(QuotaStatusCode status) {
    DCHECK_GT(remaining_deleters_, 0);

    if (status != kQuotaStatusOk)
      ++error_count_;

    if (--remaining_deleters_ == 0)
      CallCompleted();
  }

  QuotaManager* manager() const {
    return static_cast<QuotaManager*>(observer());
  }

  std::string host_;
  StorageType type_;
  int quota_client_mask_;
  std::set<GURL> origins_;
  int error_count_;
  int remaining_clients_;
  int remaining_deleters_;
  StatusCallback callback_;

  base::WeakPtrFactory<HostDataDeleter> weak_factory_;
  DISALLOW_COPY_AND_ASSIGN(HostDataDeleter);
};

class QuotaManager::DatabaseTaskBase : public QuotaThreadTask {
 public:
  explicit DatabaseTaskBase(QuotaManager* manager)
      : QuotaThreadTask(manager, manager->db_thread_),
        manager_(manager),
        database_(manager->database_.get()),
        db_disabled_(false) {
    DCHECK(database_);
  }

 protected:
  virtual void DatabaseTaskCompleted() = 0;

  virtual void Completed() OVERRIDE {
    manager_->db_disabled_ = db_disabled_;
    DatabaseTaskCompleted();
  }

  bool db_disabled() const { return db_disabled_; }
  void set_db_disabled(bool db_disabled) {
    db_disabled_ = db_disabled;
  }

  QuotaManager* manager() const { return manager_; }
  QuotaDatabase* database() const { return database_; }

 private:
  QuotaManager* manager_;
  QuotaDatabase* database_;
  bool db_disabled_;
};

class QuotaManager::InitializeTask : public QuotaManager::DatabaseTaskBase {
 public:
  InitializeTask(QuotaManager* manager)
      : DatabaseTaskBase(manager),
        temporary_quota_override_(-1),
        desired_available_space_(-1) {
  }

 protected:
  virtual void RunOnTargetThread() OVERRIDE {
    // See if we have overriding temporary quota configuration.
    database()->GetQuotaConfigValue(QuotaDatabase::kTemporaryQuotaOverrideKey,
                                    &temporary_quota_override_);
    database()->GetQuotaConfigValue(QuotaDatabase::kDesiredAvailableSpaceKey,
                                    &desired_available_space_);
  }

  virtual void DatabaseTaskCompleted() OVERRIDE {
    manager()->temporary_quota_override_ = temporary_quota_override_;
    manager()->desired_available_space_ = desired_available_space_;
    manager()->temporary_quota_initialized_ = true;
    manager()->DidRunInitializeTask();
  }

 private:
  int64 temporary_quota_override_;
  int64 desired_available_space_;
};

class QuotaManager::UpdateTemporaryQuotaOverrideTask
    : public QuotaManager::DatabaseTaskBase {
 public:
  UpdateTemporaryQuotaOverrideTask(
      QuotaManager* manager,
      int64 new_quota,
      const QuotaCallback& callback)
      : DatabaseTaskBase(manager),
        new_quota_(new_quota),
        callback_(callback) {}

 protected:
  virtual void RunOnTargetThread() OVERRIDE {
    if (!database()->SetQuotaConfigValue(
            QuotaDatabase::kTemporaryQuotaOverrideKey, new_quota_)) {
      set_db_disabled(true);
      new_quota_ = -1;
      return;
    }
  }

  virtual void DatabaseTaskCompleted() OVERRIDE {
    if (!db_disabled()) {
      manager()->temporary_quota_override_ = new_quota_;
      CallCallback(kQuotaStatusOk, kStorageTypeTemporary, new_quota_);
    } else {
      CallCallback(kQuotaErrorInvalidAccess, kStorageTypeTemporary, new_quota_);
    }
  }

 private:
  void CallCallback(QuotaStatusCode status, StorageType type, int64 quota) {
    if (!callback_.is_null()) {
      callback_.Run(status, type, quota);
      callback_.Reset();
    }
  }

  int64 new_quota_;
  QuotaCallback callback_;
};

class QuotaManager::GetPersistentHostQuotaTask
    : public QuotaManager::DatabaseTaskBase {
 public:
  GetPersistentHostQuotaTask(
      QuotaManager* manager,
      const std::string& host,
      const HostQuotaCallback& callback)
      : DatabaseTaskBase(manager),
        host_(host),
        quota_(-1),
        callback_(callback) {
  }
 protected:
  virtual void RunOnTargetThread() OVERRIDE {
    if (!database()->GetHostQuota(host_, kStorageTypePersistent, &quota_))
      quota_ = 0;
  }
  virtual void DatabaseTaskCompleted() OVERRIDE {
    callback_.Run(kQuotaStatusOk,
                  host_, kStorageTypePersistent, quota_);
  }
 private:
  std::string host_;
  int64 quota_;
  HostQuotaCallback callback_;
};

class QuotaManager::UpdatePersistentHostQuotaTask
    : public QuotaManager::DatabaseTaskBase {
 public:
  UpdatePersistentHostQuotaTask(
      QuotaManager* manager,
      const std::string& host,
      int64 new_quota,
      const HostQuotaCallback& callback)
      : DatabaseTaskBase(manager),
        host_(host),
        new_quota_(new_quota),
        callback_(callback) {
    DCHECK_GE(new_quota_, 0);
  }
 protected:
  virtual void RunOnTargetThread() OVERRIDE {
    if (!database()->SetHostQuota(host_, kStorageTypePersistent, new_quota_)) {
      set_db_disabled(true);
      new_quota_ = 0;
    }
  }

  virtual void DatabaseTaskCompleted() OVERRIDE {
    callback_.Run(db_disabled() ? kQuotaErrorInvalidAccess : kQuotaStatusOk,
                  host_, kStorageTypePersistent, new_quota_);
  }

  virtual void Aborted() OVERRIDE {
    callback_.Reset();
  }

 private:
  std::string host_;
  int64 new_quota_;
  HostQuotaCallback callback_;
};

class QuotaManager::GetLRUOriginTask
    : public QuotaManager::DatabaseTaskBase {
 public:
  GetLRUOriginTask(
      QuotaManager* manager,
      StorageType type,
      const std::map<GURL, int>& origins_in_use,
      const std::map<GURL, int>& origins_in_error,
      const GetLRUOriginCallback& callback)
      : DatabaseTaskBase(manager),
        type_(type),
        callback_(callback),
        special_storage_policy_(manager->special_storage_policy_) {
    for (std::map<GURL, int>::const_iterator p = origins_in_use.begin();
         p != origins_in_use.end();
         ++p) {
      if (p->second > 0)
        exceptions_.insert(p->first);
    }
    for (std::map<GURL, int>::const_iterator p = origins_in_error.begin();
         p != origins_in_error.end();
         ++p) {
      if (p->second > QuotaManager::kThresholdOfErrorsToBeBlacklisted)
        exceptions_.insert(p->first);
    }
  }

 protected:
  virtual void RunOnTargetThread() OVERRIDE {
    database()->GetLRUOrigin(
        type_, exceptions_, special_storage_policy_, &url_);
  }

  virtual void DatabaseTaskCompleted() OVERRIDE {
    callback_.Run(url_);
  }

  virtual void Aborted() OVERRIDE {
    callback_.Reset();
  }

 private:
  StorageType type_;
  std::set<GURL> exceptions_;
  GetLRUOriginCallback callback_;
  scoped_refptr<SpecialStoragePolicy> special_storage_policy_;
  GURL url_;
};

class QuotaManager::DeleteOriginInfo
    : public QuotaManager::DatabaseTaskBase {
 public:
  DeleteOriginInfo(
      QuotaManager* manager,
      const GURL& origin,
      StorageType type)
      : DatabaseTaskBase(manager),
        origin_(origin),
        type_(type) {}

 protected:
  virtual void RunOnTargetThread() OVERRIDE {
    if (!database()->DeleteOriginInfo(origin_, type_)) {
      set_db_disabled(true);
    }
  }
  virtual void DatabaseTaskCompleted() OVERRIDE {}

 private:
  GURL origin_;
  StorageType type_;
};

class QuotaManager::InitializeTemporaryOriginsInfoTask
    : public QuotaManager::DatabaseTaskBase {
 public:
  InitializeTemporaryOriginsInfoTask(
      QuotaManager* manager,
      UsageTracker* temporary_usage_tracker)
      : DatabaseTaskBase(manager),
        has_registered_origins_(false) {
    DCHECK(temporary_usage_tracker);
    temporary_usage_tracker->GetCachedOrigins(&origins_);
  }

 protected:
  virtual void RunOnTargetThread() OVERRIDE {
    if (!database()->IsOriginDatabaseBootstrapped()) {
      // Register existing origins with 0 last time access.
      if (!database()->RegisterInitialOriginInfo(
              origins_, kStorageTypeTemporary)) {
        set_db_disabled(true);
      } else {
        has_registered_origins_ = true;
        database()->SetOriginDatabaseBootstrapped(true);
      }
    }
  }
  virtual void DatabaseTaskCompleted() OVERRIDE {
    if (has_registered_origins_)
      manager()->StartEviction();
  }

 private:
  std::set<GURL> origins_;
  bool has_registered_origins_;
};

class QuotaManager::AvailableSpaceQueryTask : public QuotaThreadTask {
 public:
  AvailableSpaceQueryTask(
      QuotaManager* manager,
      const AvailableSpaceCallback& callback)
      : QuotaThreadTask(manager, manager->db_thread_),
        profile_path_(manager->profile_path_),
        space_(-1),
        callback_(callback) {
  }
  virtual ~AvailableSpaceQueryTask() {}

 protected:
  virtual void RunOnTargetThread() OVERRIDE {
    space_ = base::SysInfo::AmountOfFreeDiskSpace(profile_path_);
  }

  virtual void Aborted() OVERRIDE {
    callback_.Reset();
  }

  virtual void Completed() OVERRIDE {
    callback_.Run(kQuotaStatusOk, space_);
  }

 private:
  FilePath profile_path_;
  int64 space_;
  AvailableSpaceCallback callback_;
};

class QuotaManager::UpdateAccessTimeTask
    : public QuotaManager::DatabaseTaskBase {
 public:
  UpdateAccessTimeTask(
      QuotaManager* manager,
      const GURL& origin,
      StorageType type,
      base::Time accessed_time)
      : DatabaseTaskBase(manager),
        origin_(origin),
        type_(type),
        accessed_time_(accessed_time) {}

 protected:
  virtual void RunOnTargetThread() OVERRIDE {
    if (!database()->SetOriginLastAccessTime(origin_, type_, accessed_time_)) {
      set_db_disabled(true);
    }
  }
  virtual void DatabaseTaskCompleted() OVERRIDE {}

 private:
  GURL origin_;
  StorageType type_;
  base::Time accessed_time_;
};

class QuotaManager::UpdateModifiedTimeTask
    : public QuotaManager::DatabaseTaskBase {
 public:
  UpdateModifiedTimeTask(
      QuotaManager* manager,
      const GURL& origin,
      StorageType type,
      base::Time modified_time)
      : DatabaseTaskBase(manager),
        origin_(origin),
        type_(type),
        modified_time_(modified_time) {}

 protected:
  virtual void RunOnTargetThread() OVERRIDE {
    if (!database()->SetOriginLastModifiedTime(
            origin_, type_, modified_time_)) {
      set_db_disabled(true);
    }
  }
  virtual void DatabaseTaskCompleted() OVERRIDE {}

 private:
  GURL origin_;
  StorageType type_;
  base::Time modified_time_;
};

class QuotaManager::GetModifiedSinceTask
    : public QuotaManager::DatabaseTaskBase {
 public:
  GetModifiedSinceTask(
      QuotaManager* manager,
      StorageType type,
      base::Time modified_since,
      GetOriginsCallback callback)
      : DatabaseTaskBase(manager),
        type_(type),
        modified_since_(modified_since),
        callback_(callback) {}

 protected:
  virtual void RunOnTargetThread() OVERRIDE {
    if (!database()->GetOriginsModifiedSince(
            type_, &origins_, modified_since_)) {
      set_db_disabled(true);
    }
  }

  virtual void DatabaseTaskCompleted() OVERRIDE {
    callback_.Run(origins_, type_);
  }

  virtual void Aborted() OVERRIDE {
    callback_.Run(std::set<GURL>(), type_);
  }

 private:
  StorageType type_;
  base::Time modified_since_;
  std::set<GURL> origins_;
  GetOriginsCallback callback_;
};

class QuotaManager::DumpQuotaTableTask
    : public QuotaManager::DatabaseTaskBase {
 private:
  typedef QuotaManager::DumpQuotaTableTask self_type;
  typedef QuotaManager::DumpQuotaTableCallback Callback;
  typedef QuotaManager::QuotaTableEntry TableEntry;
  typedef QuotaManager::QuotaTableEntries TableEntries;
  typedef QuotaDatabase::QuotaTableCallback TableCallback;

 public:
  DumpQuotaTableTask(
      QuotaManager* manager,
      const Callback& callback)
      : DatabaseTaskBase(manager),
        callback_(callback) {
  }
 protected:
  virtual void RunOnTargetThread() OVERRIDE {
    if (!database()->DumpQuotaTable(
            new TableCallback(
                base::Bind(&self_type::AppendEntry, this))))
      set_db_disabled(true);
  }

  virtual void Aborted() OVERRIDE {
    callback_.Run(TableEntries());
  }

  virtual void DatabaseTaskCompleted() OVERRIDE {
    callback_.Run(entries_);
  }

 private:
  bool AppendEntry(const TableEntry& entry) {
    entries_.push_back(entry);
    return true;
  }

  Callback callback_;
  TableEntries entries_;
};

class QuotaManager::DumpOriginInfoTableTask
    : public QuotaManager::DatabaseTaskBase {
 private:
  typedef QuotaManager::DumpOriginInfoTableTask self_type;
  typedef QuotaManager::DumpOriginInfoTableCallback Callback;
  typedef QuotaManager::OriginInfoTableEntry TableEntry;
  typedef QuotaManager::OriginInfoTableEntries TableEntries;
  typedef QuotaDatabase::OriginInfoTableCallback TableCallback;

 public:
  DumpOriginInfoTableTask(
      QuotaManager* manager,
      const Callback& callback)
      : DatabaseTaskBase(manager),
        callback_(callback) {
  }
 protected:
  virtual void RunOnTargetThread() OVERRIDE {
    if (!database()->DumpOriginInfoTable(
            new TableCallback(
                base::Bind(&self_type::AppendEntry, this))))
      set_db_disabled(true);
  }

  virtual void Aborted() OVERRIDE {
    callback_.Run(TableEntries());
  }

  virtual void DatabaseTaskCompleted() OVERRIDE {
    callback_.Run(entries_);
  }

 private:
  bool AppendEntry(const TableEntry& entry) {
    entries_.push_back(entry);
    return true;
  }

  Callback callback_;
  TableEntries entries_;
};

// QuotaManager ---------------------------------------------------------------

QuotaManager::QuotaManager(bool is_incognito,
                           const FilePath& profile_path,
                           base::MessageLoopProxy* io_thread,
                           base::MessageLoopProxy* db_thread,
                           SpecialStoragePolicy* special_storage_policy)
  : is_incognito_(is_incognito),
    profile_path_(profile_path),
    proxy_(new QuotaManagerProxy(
        ALLOW_THIS_IN_INITIALIZER_LIST(this), io_thread)),
    db_disabled_(false),
    eviction_disabled_(false),
    io_thread_(io_thread),
    db_thread_(db_thread),
    temporary_quota_initialized_(false),
    temporary_quota_override_(-1),
    desired_available_space_(-1),
    special_storage_policy_(special_storage_policy),
    weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
}

QuotaManager::~QuotaManager() {
  proxy_->manager_ = NULL;
  std::for_each(clients_.begin(), clients_.end(),
                std::mem_fun(&QuotaClient::OnQuotaManagerDestroyed));
  if (database_.get())
    db_thread_->DeleteSoon(FROM_HERE, database_.release());
}

void QuotaManager::GetUsageInfo(const GetUsageInfoCallback& callback) {
  LazyInitialize();
  GetUsageInfoTask* get_usage_info = new GetUsageInfoTask(this, callback);
  get_usage_info->Start();
}

void QuotaManager::GetUsageAndQuota(
    const GURL& origin, StorageType type,
    const GetUsageAndQuotaCallback& callback) {
  GetUsageAndQuotaInternal(origin, type, false /* global */,
                           base::Bind(&CallGetUsageAndQuotaCallback,
                                      callback, IsStorageUnlimited(origin)));
}

void QuotaManager::GetAvailableSpace(const AvailableSpaceCallback& callback) {
  if (is_incognito_) {
    callback.Run(kQuotaStatusOk, kIncognitoDefaultTemporaryQuota);
    return;
  }
  make_scoped_refptr(new AvailableSpaceQueryTask(this, callback))->Start();
}

void QuotaManager::GetTemporaryGlobalQuota(const QuotaCallback& callback) {
  if (temporary_quota_override_ > 0) {
    callback.Run(kQuotaStatusOk, kStorageTypeTemporary,
                 temporary_quota_override_);
    return;
  }
  GetUsageAndQuotaInternal(
      GURL(), kStorageTypeTemporary, true /* global */,
      base::Bind(&CallQuotaCallback, callback, kStorageTypeTemporary));
}

void QuotaManager::SetTemporaryGlobalOverrideQuota(
    int64 new_quota, const QuotaCallback& callback) {
  LazyInitialize();

  if (new_quota < 0) {
    if (!callback.is_null())
      callback.Run(kQuotaErrorInvalidModification,
                   kStorageTypeTemporary, -1);
    return;
  }

  if (db_disabled_) {
    if (callback.is_null())
      callback.Run(kQuotaErrorInvalidAccess,
                   kStorageTypeTemporary, -1);
    return;
  }

  make_scoped_refptr(new UpdateTemporaryQuotaOverrideTask(
      this, new_quota, callback))->Start();
}

void QuotaManager::GetPersistentHostQuota(const std::string& host,
                                          const HostQuotaCallback& callback) {
  LazyInitialize();
  if (host.empty()) {
    // This could happen if we are called on file:///.
    // TODO(kinuko) We may want to respect --allow-file-access-from-files
    // command line switch.
    callback.Run(kQuotaStatusOk, host, kStorageTypePersistent, 0);
    return;
  }
  scoped_refptr<GetPersistentHostQuotaTask> task(
      new GetPersistentHostQuotaTask(this, host, callback));
  task->Start();
}

void QuotaManager::SetPersistentHostQuota(const std::string& host,
                                          int64 new_quota,
                                          const HostQuotaCallback& callback) {
  LazyInitialize();
  if (host.empty()) {
    // This could happen if we are called on file:///.
    callback.Run(kQuotaErrorNotSupported, host, kStorageTypePersistent, 0);
    return;
  }
  if (new_quota < 0) {
    callback.Run(kQuotaErrorInvalidModification,
                 host, kStorageTypePersistent, -1);
    return;
  }

  if (!db_disabled_) {
    scoped_refptr<UpdatePersistentHostQuotaTask> task(
        new UpdatePersistentHostQuotaTask(
            this, host, new_quota, callback));
    task->Start();
  } else {
    callback.Run(kQuotaErrorInvalidAccess,
                  host, kStorageTypePersistent, -1);
  }
}

void QuotaManager::GetGlobalUsage(StorageType type,
                                  const GlobalUsageCallback& callback) {
  LazyInitialize();
  GetUsageTracker(type)->GetGlobalUsage(callback);
}

void QuotaManager::GetHostUsage(const std::string& host,
                                StorageType type,
                                const HostUsageCallback& callback) {
  LazyInitialize();
  GetUsageTracker(type)->GetHostUsage(host, callback);
}

void QuotaManager::GetStatistics(
    std::map<std::string, std::string>* statistics) {
  DCHECK(statistics);
  if (temporary_storage_evictor_.get()) {
    std::map<std::string, int64> stats;
    temporary_storage_evictor_->GetStatistics(&stats);
    for (std::map<std::string, int64>::iterator p = stats.begin();
         p != stats.end();
         ++p)
      (*statistics)[p->first] = base::Int64ToString(p->second);
  }
}

void QuotaManager::GetOriginsModifiedSince(StorageType type,
                                           base::Time modified_since,
                                           const GetOriginsCallback& callback) {
  LazyInitialize();
  make_scoped_refptr(new GetModifiedSinceTask(
      this, type, modified_since, callback))->Start();
}

void QuotaManager::LazyInitialize() {
  DCHECK(io_thread_->BelongsToCurrentThread());
  if (database_.get()) {
    // Initialization seems to be done already.
    return;
  }

  // Use an empty path to open an in-memory only databse for incognito.
  database_.reset(new QuotaDatabase(is_incognito_ ? FilePath() :
      profile_path_.AppendASCII(kDatabaseName)));

  temporary_usage_tracker_.reset(
      new UsageTracker(clients_, kStorageTypeTemporary,
                       special_storage_policy_));
  persistent_usage_tracker_.reset(
      new UsageTracker(clients_, kStorageTypePersistent,
                       special_storage_policy_));

  make_scoped_refptr(new InitializeTask(this))->Start();
}

void QuotaManager::RegisterClient(QuotaClient* client) {
  DCHECK(!database_.get());
  clients_.push_back(client);
}

void QuotaManager::NotifyStorageAccessed(
    QuotaClient::ID client_id,
    const GURL& origin, StorageType type) {
  NotifyStorageAccessedInternal(client_id, origin, type, base::Time::Now());
}

void QuotaManager::NotifyStorageModified(
    QuotaClient::ID client_id,
    const GURL& origin, StorageType type, int64 delta) {
  NotifyStorageModifiedInternal(client_id, origin, type, delta,
                                base::Time::Now());
}

void QuotaManager::NotifyOriginInUse(const GURL& origin) {
  DCHECK(io_thread_->BelongsToCurrentThread());
  origins_in_use_[origin]++;
}

void QuotaManager::NotifyOriginNoLongerInUse(const GURL& origin) {
  DCHECK(io_thread_->BelongsToCurrentThread());
  DCHECK(IsOriginInUse(origin));
  int& count = origins_in_use_[origin];
  if (--count == 0)
    origins_in_use_.erase(origin);
}

void QuotaManager::DeleteOriginData(
    const GURL& origin, StorageType type, int quota_client_mask,
    const StatusCallback& callback) {
  LazyInitialize();

  if (origin.is_empty() || clients_.empty()) {
    callback.Run(kQuotaStatusOk);
    return;
  }

  OriginDataDeleter* deleter =
      new OriginDataDeleter(this, origin, type, quota_client_mask, callback);
  deleter->Start();
}

void QuotaManager::DeleteHostData(const std::string& host,
                                  StorageType type,
                                  int quota_client_mask,
                                  const StatusCallback& callback) {

  LazyInitialize();

  if (host.empty() || clients_.empty()) {
    callback.Run(kQuotaStatusOk);
    return;
  }

  HostDataDeleter* deleter =
      new HostDataDeleter(this, host, type, quota_client_mask, callback);
  deleter->Start();
}

bool QuotaManager::ResetUsageTracker(StorageType type) {
  switch (type) {
    case kStorageTypeTemporary:
      if (temporary_usage_tracker_->IsWorking())
        return false;
      temporary_usage_tracker_.reset(
          new UsageTracker(clients_, kStorageTypeTemporary,
                           special_storage_policy_));
      return true;
    case kStorageTypePersistent:
      if (persistent_usage_tracker_->IsWorking())
        return false;
      persistent_usage_tracker_.reset(
          new UsageTracker(clients_, kStorageTypePersistent,
                           special_storage_policy_));
      return true;
    default:
      NOTREACHED();
  }
  return true;
}

UsageTracker* QuotaManager::GetUsageTracker(StorageType type) const {
  switch (type) {
    case kStorageTypeTemporary:
      return temporary_usage_tracker_.get();
    case kStorageTypePersistent:
      return persistent_usage_tracker_.get();
    default:
      NOTREACHED();
  }
  return NULL;
}

void QuotaManager::GetCachedOrigins(
    StorageType type, std::set<GURL>* origins) {
  DCHECK(origins);
  LazyInitialize();
  switch (type) {
    case kStorageTypeTemporary:
      DCHECK(temporary_usage_tracker_.get());
      temporary_usage_tracker_->GetCachedOrigins(origins);
      return;
    case kStorageTypePersistent:
      DCHECK(persistent_usage_tracker_.get());
      persistent_usage_tracker_->GetCachedOrigins(origins);
      return;
    default:
      NOTREACHED();
  }
}

void QuotaManager::NotifyStorageAccessedInternal(
    QuotaClient::ID client_id,
    const GURL& origin, StorageType type,
    base::Time accessed_time) {
  LazyInitialize();
  if (type == kStorageTypeTemporary && !lru_origin_callback_.is_null()) {
    // Record the accessed origins while GetLRUOrigin task is runing
    // to filter out them from eviction.
    access_notified_origins_.insert(origin);
  }

  if (db_disabled_)
    return;
  make_scoped_refptr(new UpdateAccessTimeTask(
      this, origin, type, accessed_time))->Start();
}

void QuotaManager::NotifyStorageModifiedInternal(
    QuotaClient::ID client_id,
    const GURL& origin,
    StorageType type,
    int64 delta,
    base::Time modified_time) {
  LazyInitialize();
  GetUsageTracker(type)->UpdateUsageCache(client_id, origin, delta);
  make_scoped_refptr(new UpdateModifiedTimeTask(
      this, origin, type, modified_time))->Start();
}

void QuotaManager::GetUsageAndQuotaInternal(
    const GURL& origin, StorageType type, bool global,
    const UsageAndQuotaDispatcherCallback& callback) {
  LazyInitialize();

  StorageType requested_type = type;
  if (type == kStorageTypeUnknown) {
    // Quota only supports temporary/persistent types.
    callback.Run(kQuotaErrorNotSupported, QuotaAndUsage());
    return;
  }

  // Special internal type for querying global usage and quota.
  const int kStorageTypeTemporaryGlobal = kStorageTypeTemporary + 100;
  if (global) {
    DCHECK_EQ(kStorageTypeTemporary, type);
    type = static_cast<StorageType>(kStorageTypeTemporaryGlobal);
  }

  std::string host = net::GetHostOrSpecFromURL(origin);
  HostAndType host_and_type = std::make_pair(host, type);
  UsageAndQuotaDispatcherTaskMap::iterator found =
      usage_and_quota_dispatchers_.find(host_and_type);
  if (found == usage_and_quota_dispatchers_.end()) {
    UsageAndQuotaDispatcherTask* dispatcher =
        UsageAndQuotaDispatcherTask::Create(this, global, host_and_type);
    found = usage_and_quota_dispatchers_.insert(
        std::make_pair(host_and_type, dispatcher)).first;
  }
  // Start the dispatcher if it is the first one and temporary_quota_override
  // is already initialized iff the requested type is temporary.
  // (The first dispatcher task for temporary will be kicked in
  // DidRunInitializeTask if temporary_quota_initialized_ is false here.)
  if (found->second->AddCallback(callback) &&
      (requested_type != kStorageTypeTemporary ||
       temporary_quota_initialized_)) {
    found->second->Start();
  }
}

void QuotaManager::DumpQuotaTable(const DumpQuotaTableCallback& callback) {
  make_scoped_refptr(new DumpQuotaTableTask(this, callback))->Start();
}

void QuotaManager::DumpOriginInfoTable(
    const DumpOriginInfoTableCallback& callback) {
  make_scoped_refptr(new DumpOriginInfoTableTask(this, callback))->Start();
}


void QuotaManager::DeleteOriginFromDatabase(
    const GURL& origin, StorageType type) {
  LazyInitialize();
  if (db_disabled_)
    return;
  scoped_refptr<DeleteOriginInfo> task =
      new DeleteOriginInfo(this, origin, type);
  task->Start();
}

void QuotaManager::GetLRUOrigin(
    StorageType type,
    const GetLRUOriginCallback& callback) {
  LazyInitialize();
  // This must not be called while there's an in-flight task.
  DCHECK(lru_origin_callback_.is_null());
  lru_origin_callback_ = callback;
  if (db_disabled_) {
    lru_origin_callback_.Run(GURL());
    lru_origin_callback_.Reset();
    return;
  }
  scoped_refptr<GetLRUOriginTask> task(new GetLRUOriginTask(
      this, type, origins_in_use_, origins_in_error_,
      base::Bind(&QuotaManager::DidGetDatabaseLRUOrigin,
                 weak_factory_.GetWeakPtr())));
  task->Start();
}

void QuotaManager::DidOriginDataEvicted(QuotaStatusCode status) {
  DCHECK(io_thread_->BelongsToCurrentThread());

  // We only try evict origins that are not in use, so basically
  // deletion attempt for eviction should not fail.  Let's record
  // the origin if we get error and exclude it from future eviction
  // if the error happens consistently (> kThresholdOfErrorsToBeBlacklisted).
  if (status != kQuotaStatusOk)
    origins_in_error_[eviction_context_.evicted_origin]++;

  eviction_context_.evict_origin_data_callback.Run(status);
  eviction_context_.evict_origin_data_callback.Reset();
}

void QuotaManager::EvictOriginData(
    const GURL& origin,
    StorageType type,
    const EvictOriginDataCallback& callback) {
  DCHECK(io_thread_->BelongsToCurrentThread());
  DCHECK_EQ(type, kStorageTypeTemporary);

  eviction_context_.evicted_origin = origin;
  eviction_context_.evicted_type = type;
  eviction_context_.evict_origin_data_callback = callback;

  DeleteOriginData(origin, type, QuotaClient::kAllClientsMask,
      base::Bind(&QuotaManager::DidOriginDataEvicted,
                 weak_factory_.GetWeakPtr()));
}

void QuotaManager::GetUsageAndQuotaForEviction(
    const GetUsageAndQuotaForEvictionCallback& callback) {
  DCHECK(io_thread_->BelongsToCurrentThread());
  GetUsageAndQuotaInternal(
      GURL(), kStorageTypeTemporary, true /* global */, callback);
}

void QuotaManager::StartEviction() {
  DCHECK(!temporary_storage_evictor_.get());
  temporary_storage_evictor_.reset(new QuotaTemporaryStorageEvictor(
      this, kEvictionIntervalInMilliSeconds));
  if (desired_available_space_ >= 0)
    temporary_storage_evictor_->set_min_available_disk_space_to_start_eviction(
        desired_available_space_);
  temporary_storage_evictor_->Start();
}

void QuotaManager::ReportHistogram() {
  GetGlobalUsage(kStorageTypeTemporary,
                 base::Bind(
                     &QuotaManager::DidGetTemporaryGlobalUsageForHistogram,
                     weak_factory_.GetWeakPtr()));
  GetGlobalUsage(kStorageTypePersistent,
                 base::Bind(
                     &QuotaManager::DidGetPersistentGlobalUsageForHistogram,
                     weak_factory_.GetWeakPtr()));
}

void QuotaManager::DidGetTemporaryGlobalUsageForHistogram(
    StorageType type,
    int64 usage,
    int64 unlimited_usage) {
  UMA_HISTOGRAM_MBYTES("Quota.GlobalUsageOfTemporaryStorage", usage);

  std::set<GURL> origins;
  GetCachedOrigins(type, &origins);

  size_t num_origins = origins.size();
  size_t protected_origins = 0;
  size_t unlimited_origins = 0;
  CountOriginType(origins, special_storage_policy_,
                  &protected_origins, &unlimited_origins);

  UMA_HISTOGRAM_COUNTS("Quota.NumberOfTemporaryStorageOrigins",
                       num_origins);
  UMA_HISTOGRAM_COUNTS("Quota.NumberOfProtectedTemporaryStorageOrigins",
                       protected_origins);
  UMA_HISTOGRAM_COUNTS("Quota.NumberOfUnlimitedTemporaryStorageOrigins",
                       unlimited_origins);
}

void QuotaManager::DidGetPersistentGlobalUsageForHistogram(
    StorageType type,
    int64 usage,
    int64 unlimited_usage) {
  UMA_HISTOGRAM_MBYTES("Quota.GlobalUsageOfPersistentStorage", usage);

  std::set<GURL> origins;
  GetCachedOrigins(type, &origins);

  size_t num_origins = origins.size();
  size_t protected_origins = 0;
  size_t unlimited_origins = 0;
  CountOriginType(origins, special_storage_policy_,
                  &protected_origins, &unlimited_origins);

  UMA_HISTOGRAM_COUNTS("Quota.NumberOfPersistentStorageOrigins",
                       num_origins);
  UMA_HISTOGRAM_COUNTS("Quota.NumberOfProtectedPersistentStorageOrigins",
                       protected_origins);
  UMA_HISTOGRAM_COUNTS("Quota.NumberOfUnlimitedPersistentStorageOrigins",
                       unlimited_origins);
}

void QuotaManager::DidRunInitializeTask() {
  histogram_timer_.Start(FROM_HERE,
                         base::TimeDelta::FromMilliseconds(
                             kReportHistogramInterval),
                         this, &QuotaManager::ReportHistogram);

  DCHECK(temporary_quota_initialized_);

  // Kick the tasks that have been waiting for the
  // temporary_quota_initialized_ to be initialized (if there're any).
  for (UsageAndQuotaDispatcherTaskMap::iterator iter =
           usage_and_quota_dispatchers_.begin();
       iter != usage_and_quota_dispatchers_.end(); ++iter) {
    if (iter->second->IsStartable())
      iter->second->Start();
  }

  // Kick the first GetTemporaryGlobalQuota. This internally fetches (and
  // caches) the usage of all origins and checks the available disk space.
  GetTemporaryGlobalQuota(
      base::Bind(&QuotaManager::DidGetInitialTemporaryGlobalQuota,
                 weak_factory_.GetWeakPtr()));
}

void QuotaManager::DidGetInitialTemporaryGlobalQuota(
    QuotaStatusCode status, StorageType type, int64 quota_unused) {
  DCHECK_EQ(type, kStorageTypeTemporary);

  if (eviction_disabled_)
    return;

  // This will call the StartEviction() when initial origin registration
  // is completed.
  make_scoped_refptr(new InitializeTemporaryOriginsInfoTask(
      this, temporary_usage_tracker_.get()))->Start();
}

void QuotaManager::DidGetDatabaseLRUOrigin(const GURL& origin) {
  // Make sure the returned origin is (still) not in the origin_in_use_ set
  // and has not been accessed since we posted the task.
  if (origins_in_use_.find(origin) != origins_in_use_.end() ||
      access_notified_origins_.find(origin) != access_notified_origins_.end())
    lru_origin_callback_.Run(GURL());
  else
    lru_origin_callback_.Run(origin);
  access_notified_origins_.clear();
  lru_origin_callback_.Reset();
}

void QuotaManager::DeleteOnCorrectThread() const {
  if (!io_thread_->BelongsToCurrentThread() && 
      io_thread_->DeleteSoon(FROM_HERE, this)) {
    return;
  }
  delete this;
}

// QuotaManagerProxy ----------------------------------------------------------

void QuotaManagerProxy::RegisterClient(QuotaClient* client) {
  if (!io_thread_->BelongsToCurrentThread() &&
      io_thread_->PostTask(
          FROM_HERE,
          base::Bind(&QuotaManagerProxy::RegisterClient, this, client))) {
    return;
  }

  if (manager_)
    manager_->RegisterClient(client);
  else
    client->OnQuotaManagerDestroyed();
}

void QuotaManagerProxy::NotifyStorageAccessed(
    QuotaClient::ID client_id,
    const GURL& origin,
    StorageType type) {
  if (!io_thread_->BelongsToCurrentThread()) {
    io_thread_->PostTask(
        FROM_HERE,
        base::Bind(&QuotaManagerProxy::NotifyStorageAccessed, this, client_id,
                   origin, type));
    return;
  }

  if (manager_)
    manager_->NotifyStorageAccessed(client_id, origin, type);
}

void QuotaManagerProxy::NotifyStorageModified(
    QuotaClient::ID client_id,
    const GURL& origin,
    StorageType type,
    int64 delta) {
  if (!io_thread_->BelongsToCurrentThread()) {
    io_thread_->PostTask(
        FROM_HERE,
        base::Bind(&QuotaManagerProxy::NotifyStorageModified, this, client_id,
                   origin, type, delta));
    return;
  }

  if (manager_)
    manager_->NotifyStorageModified(client_id, origin, type, delta);
}

void QuotaManagerProxy::NotifyOriginInUse(
    const GURL& origin) {
  if (!io_thread_->BelongsToCurrentThread()) {
    io_thread_->PostTask(
        FROM_HERE,
        base::Bind(&QuotaManagerProxy::NotifyOriginInUse, this, origin));
    return;
  }

  if (manager_)
    manager_->NotifyOriginInUse(origin);
}

void QuotaManagerProxy::NotifyOriginNoLongerInUse(
    const GURL& origin) {
  if (!io_thread_->BelongsToCurrentThread()) {
    io_thread_->PostTask(
        FROM_HERE,
        base::Bind(&QuotaManagerProxy::NotifyOriginNoLongerInUse, this,
                   origin));
    return;
  }
  if (manager_)
    manager_->NotifyOriginNoLongerInUse(origin);
}

QuotaManager* QuotaManagerProxy::quota_manager() const {
  DCHECK(!io_thread_ || io_thread_->BelongsToCurrentThread());
  return manager_;
}

QuotaManagerProxy::QuotaManagerProxy(
    QuotaManager* manager, base::MessageLoopProxy* io_thread)
    : manager_(manager), io_thread_(io_thread) {
}

QuotaManagerProxy::~QuotaManagerProxy() {
}

}  // namespace quota
