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

#include "storage/browser/quota/quota_manager.h"

#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <functional>
#include <limits>
#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/metrics/histogram.h"
#include "base/profiler/scoped_tracker.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/sys_info.h"
#include "base/task_runner_util.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "net/base/net_util.h"
#include "storage/browser/quota/client_usage_tracker.h"
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/browser/quota/quota_temporary_storage_evictor.h"
#include "storage/browser/quota/storage_monitor.h"
#include "storage/browser/quota/usage_tracker.h"
#include "storage/common/quota/quota_types.h"

// Platform specific includes for GetVolumeInfo().
#if defined(OS_WIN)
#include <windows.h>
#elif defined(OS_POSIX)
#if defined(OS_ANDROID)
#include <sys/vfs.h>
#define statvfs statfs  // Android uses a statvfs-like statfs struct and call.
#else
#include <sys/statvfs.h>
#endif
#endif

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

namespace storage {

namespace {

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

const int64_t kReportHistogramInterval = 60 * 60 * 1000;  // 1 hour
const double kTemporaryQuotaRatioToAvail = 1.0 / 3.0;  // 33%

}  // namespace

// Arbitrary for now, but must be reasonably small so that
// in-memory databases can fit.
// TODO(kinuko): Refer SysInfo::AmountOfPhysicalMemory() to determine this.
const int64_t QuotaManager::kIncognitoDefaultQuotaLimit = 100 * kMBytes;

const int64_t QuotaManager::kNoLimit = INT64_MAX;

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

// Cap size for per-host persistent quota determined by the histogram.
// This is a bit lax value because the histogram says nothing about per-host
// persistent storage usage and we determined by global persistent storage
// usage that is less than 10GB for almost all users.
const int64_t QuotaManager::kPerHostPersistentQuotaLimit = 10 * 1024 * kMBytes;

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

const int QuotaManager::kThresholdOfErrorsToBeBlacklisted = 3;

// Preserve kMinimumPreserveForSystem disk space for system book-keeping
// when returning the quota to unlimited apps/extensions.
// TODO(kinuko): This should be like 10% of the actual disk space.
// For now we simply use a constant as getting the disk size needs
// platform-dependent code. (http://crbug.com/178976)
int64_t QuotaManager::kMinimumPreserveForSystem = 1024 * kMBytes;

const int QuotaManager::kEvictionIntervalInMilliSeconds =
    30 * kMinutesInMilliSeconds;

const char QuotaManager::kTimeBetweenRepeatedOriginEvictionsHistogram[] =
    "Quota.TimeBetweenRepeatedOriginEvictions";
const char QuotaManager::kEvictedOriginAccessedCountHistogram[] =
    "Quota.EvictedOriginAccessCount";
const char QuotaManager::kEvictedOriginTimeSinceAccessHistogram[] =
    "Quota.EvictedOriginTimeSinceAccess";

// Heuristics: assuming average cloud server allows a few Gigs storage
// on the server side and the storage needs to be shared for user data
// and by multiple apps.
int64_t QuotaManager::kSyncableStorageDefaultHostQuota = 500 * kMBytes;

namespace {

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;
  }
}

bool SetTemporaryGlobalOverrideQuotaOnDBThread(int64_t* new_quota,
                                               QuotaDatabase* database) {
  DCHECK(database);
  if (!database->SetQuotaConfigValue(
          QuotaDatabase::kTemporaryQuotaOverrideKey, *new_quota)) {
    *new_quota = -1;
    return false;
  }
  return true;
}

bool GetPersistentHostQuotaOnDBThread(const std::string& host,
                                      int64_t* quota,
                                      QuotaDatabase* database) {
  DCHECK(database);
  database->GetHostQuota(host, kStorageTypePersistent, quota);
  return true;
}

bool SetPersistentHostQuotaOnDBThread(const std::string& host,
                                      int64_t* new_quota,
                                      QuotaDatabase* database) {
  DCHECK(database);
  if (database->SetHostQuota(host, kStorageTypePersistent, *new_quota))
    return true;
  *new_quota = 0;
  return false;
}

bool InitializeOnDBThread(int64_t* temporary_quota_override,
                          int64_t* desired_available_space,
                          QuotaDatabase* database) {
  DCHECK(database);
  database->GetQuotaConfigValue(QuotaDatabase::kTemporaryQuotaOverrideKey,
                                temporary_quota_override);
  database->GetQuotaConfigValue(QuotaDatabase::kDesiredAvailableSpaceKey,
                                desired_available_space);
  return true;
}

bool GetLRUOriginOnDBThread(StorageType type,
                            const std::set<GURL>& exceptions,
                            SpecialStoragePolicy* policy,
                            GURL* url,
                            QuotaDatabase* database) {
  DCHECK(database);
  database->GetLRUOrigin(type, exceptions, policy, url);
  return true;
}

bool DeleteOriginInfoOnDBThread(const GURL& origin,
                                StorageType type,
                                bool is_eviction,
                                QuotaDatabase* database) {
  DCHECK(database);

  base::Time now = base::Time::Now();

  if (is_eviction) {
    QuotaDatabase::OriginInfoTableEntry entry;
    database->GetOriginInfo(origin, type, &entry);
    UMA_HISTOGRAM_COUNTS(QuotaManager::kEvictedOriginAccessedCountHistogram,
                         entry.used_count);
    UMA_HISTOGRAM_LONG_TIMES(
        QuotaManager::kEvictedOriginTimeSinceAccessHistogram,
        now - entry.last_access_time);
  }

  if (!database->DeleteOriginInfo(origin, type))
    return false;

  // If the deletion is not due to an eviction, delete the entry in the eviction
  // table as well due to privacy concerns.
  if (!is_eviction)
    return database->DeleteOriginLastEvictionTime(origin, type);

  base::Time last_eviction_time;
  database->GetOriginLastEvictionTime(origin, type, &last_eviction_time);

  if (last_eviction_time != base::Time()) {
    UMA_HISTOGRAM_LONG_TIMES(
        QuotaManager::kTimeBetweenRepeatedOriginEvictionsHistogram,
        now - last_eviction_time);
  }

  return database->SetOriginLastEvictionTime(origin, type, now);
}

bool InitializeTemporaryOriginsInfoOnDBThread(const std::set<GURL>* origins,
                                              QuotaDatabase* database) {
  DCHECK(database);
  if (database->IsOriginDatabaseBootstrapped())
    return true;

  // Register existing origins with 0 last time access.
  if (database->RegisterInitialOriginInfo(*origins, kStorageTypeTemporary)) {
    database->SetOriginDatabaseBootstrapped(true);
    return true;
  }
  return false;
}

bool UpdateAccessTimeOnDBThread(const GURL& origin,
                                StorageType type,
                                base::Time accessed_time,
                                QuotaDatabase* database) {
  DCHECK(database);
  return database->SetOriginLastAccessTime(origin, type, accessed_time);
}

bool UpdateModifiedTimeOnDBThread(const GURL& origin,
                                  StorageType type,
                                  base::Time modified_time,
                                  QuotaDatabase* database) {
  DCHECK(database);
  return database->SetOriginLastModifiedTime(origin, type, modified_time);
}

int64_t CalculateTemporaryGlobalQuota(int64_t global_limited_usage,
                                      int64_t available_space) {
  DCHECK_GE(global_limited_usage, 0);
  int64_t avail_space = available_space;
  if (avail_space <
      std::numeric_limits<int64_t>::max() - global_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 += global_limited_usage;
  }
  int64_t pool_size = avail_space * kTemporaryQuotaRatioToAvail;
  UMA_HISTOGRAM_MBYTES("Quota.GlobalTemporaryPoolSize", pool_size);
  return pool_size;
}

void DispatchTemporaryGlobalQuotaCallback(
    const QuotaCallback& callback,
    QuotaStatusCode status,
    const UsageAndQuota& usage_and_quota) {
  if (status != kQuotaStatusOk) {
    callback.Run(status, 0);
    return;
  }

  callback.Run(status, CalculateTemporaryGlobalQuota(
      usage_and_quota.global_limited_usage,
      usage_and_quota.available_disk_space));
}

int64_t CalculateQuotaWithDiskSpace(int64_t available_disk_space,
                                    int64_t usage,
                                    int64_t quota) {
  if (available_disk_space < QuotaManager::kMinimumPreserveForSystem) {
    LOG(WARNING)
        << "Running out of disk space for profile."
        << " QuotaManager starts forbidding further quota consumption.";
    return usage;
  }

  if (quota < usage) {
    // No more space; cap the quota to the current usage.
    return usage;
  }

  available_disk_space -= QuotaManager::kMinimumPreserveForSystem;
  if (available_disk_space < quota - usage)
    return available_disk_space + usage;

  return quota;
}

int64_t CalculateTemporaryHostQuota(int64_t host_usage,
                                    int64_t global_quota,
                                    int64_t global_limited_usage) {
  DCHECK_GE(global_limited_usage, 0);
  int64_t host_quota = global_quota / QuotaManager::kPerHostTemporaryPortion;
  if (global_limited_usage > global_quota)
    host_quota = std::min(host_quota, host_usage);
  return host_quota;
}

void DispatchUsageAndQuotaForWebApps(
    StorageType type,
    bool is_incognito,
    bool is_unlimited,
    bool can_query_disk_size,
    const QuotaManager::GetUsageAndQuotaCallback& callback,
    QuotaStatusCode status,
    const UsageAndQuota& usage_and_quota) {
  if (status != kQuotaStatusOk) {
    callback.Run(status, 0, 0);
    return;
  }

  int64_t usage = usage_and_quota.usage;
  int64_t quota = usage_and_quota.quota;

  if (type == kStorageTypeTemporary && !is_unlimited) {
    quota = CalculateTemporaryHostQuota(
        usage, quota, usage_and_quota.global_limited_usage);
  }

  if (is_incognito) {
    quota = std::min(quota, QuotaManager::kIncognitoDefaultQuotaLimit);
    callback.Run(status, usage, quota);
    return;
  }

  // For apps with unlimited permission or can_query_disk_size is true (and not
  // in incognito mode).
  // We assume we can expose the actual disk size for them and cap the quota by
  // the available disk space.
  if (is_unlimited || can_query_disk_size) {
    callback.Run(
        status, usage,
        CalculateQuotaWithDiskSpace(
            usage_and_quota.available_disk_space,
            usage, quota));
    return;
  }

  callback.Run(status, usage, quota);
}

}  // namespace

UsageAndQuota::UsageAndQuota()
    : usage(0),
      global_limited_usage(0),
      quota(0),
      available_disk_space(0) {
}

UsageAndQuota::UsageAndQuota(int64_t usage,
                             int64_t global_limited_usage,
                             int64_t quota,
                             int64_t available_disk_space)
    : usage(usage),
      global_limited_usage(global_limited_usage),
      quota(quota),
      available_disk_space(available_disk_space) {}

class UsageAndQuotaCallbackDispatcher
    : public QuotaTask,
      public base::SupportsWeakPtr<UsageAndQuotaCallbackDispatcher> {
 public:
  explicit UsageAndQuotaCallbackDispatcher(QuotaManager* manager)
      : QuotaTask(manager),
        has_usage_(false),
        has_global_limited_usage_(false),
        has_quota_(false),
        has_available_disk_space_(false),
        status_(kQuotaStatusUnknown),
        usage_and_quota_(-1, -1, -1, -1),
        waiting_callbacks_(1) {}

  ~UsageAndQuotaCallbackDispatcher() override {}

  void WaitForResults(const QuotaManager::UsageAndQuotaCallback& callback) {
    callback_ = callback;
    Start();
  }

  void set_usage(int64_t usage) {
    usage_and_quota_.usage = usage;
    has_usage_ = true;
  }

  void set_global_limited_usage(int64_t global_limited_usage) {
    usage_and_quota_.global_limited_usage = global_limited_usage;
    has_global_limited_usage_ = true;
  }

  void set_quota(int64_t quota) {
    usage_and_quota_.quota = quota;
    has_quota_ = true;
  }

  void set_available_disk_space(int64_t available_disk_space) {
    usage_and_quota_.available_disk_space = available_disk_space;
    has_available_disk_space_ = true;
  }

  UsageCallback GetHostUsageCallback() {
    ++waiting_callbacks_;
    has_usage_ = true;
    return base::Bind(&UsageAndQuotaCallbackDispatcher::DidGetHostUsage,
                      AsWeakPtr());
  }

  UsageCallback GetGlobalLimitedUsageCallback() {
    ++waiting_callbacks_;
    has_global_limited_usage_ = true;
    return base::Bind(
        &UsageAndQuotaCallbackDispatcher::DidGetGlobalLimitedUsage,
        AsWeakPtr());
  }

  QuotaCallback GetQuotaCallback() {
    ++waiting_callbacks_;
    has_quota_ = true;
    return base::Bind(&UsageAndQuotaCallbackDispatcher::DidGetQuota,
                      AsWeakPtr());
  }

  QuotaCallback GetAvailableSpaceCallback() {
    ++waiting_callbacks_;
    has_available_disk_space_ = true;
    return base::Bind(&UsageAndQuotaCallbackDispatcher::DidGetAvailableSpace,
                      AsWeakPtr());
  }

 private:
  void DidGetHostUsage(int64_t usage) {
    if (status_ == kQuotaStatusUnknown)
      status_ = kQuotaStatusOk;
    usage_and_quota_.usage = usage;
    CheckCompleted();
  }

  void DidGetGlobalLimitedUsage(int64_t limited_usage) {
    if (status_ == kQuotaStatusUnknown)
      status_ = kQuotaStatusOk;
    usage_and_quota_.global_limited_usage = limited_usage;
    CheckCompleted();
  }

  void DidGetQuota(QuotaStatusCode status, int64_t quota) {
    if (status_ == kQuotaStatusUnknown || status_ == kQuotaStatusOk)
      status_ = status;
    usage_and_quota_.quota = quota;
    CheckCompleted();
  }

  void DidGetAvailableSpace(QuotaStatusCode status, int64_t space) {
    // crbug.com/349708
    TRACE_EVENT0(
        "io", "UsageAndQuotaCallbackDispatcher::DidGetAvailableSpace");

    DCHECK_GE(space, 0);
    if (status_ == kQuotaStatusUnknown || status_ == kQuotaStatusOk)
      status_ = status;
    usage_and_quota_.available_disk_space = space;
    CheckCompleted();
  }

  void Run() override {
    // 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();
  }

  void Aborted() override {
    callback_.Run(kQuotaErrorAbort, UsageAndQuota());
    DeleteSoon();
  }

  void Completed() override {
    // crbug.com/349708
    TRACE_EVENT0("io", "UsageAndQuotaCallbackDispatcher::Completed");

    DCHECK(!has_usage_ || usage_and_quota_.usage >= 0);
    DCHECK(!has_global_limited_usage_ ||
           usage_and_quota_.global_limited_usage >= 0);
    DCHECK(!has_quota_ || usage_and_quota_.quota >= 0);
    DCHECK(!has_available_disk_space_ ||
           usage_and_quota_.available_disk_space >= 0);

    callback_.Run(status_, usage_and_quota_);
    DeleteSoon();
  }

  void CheckCompleted() {
    if (--waiting_callbacks_ <= 0)
      CallCompleted();
  }

  // For sanity checks, they're checked only when DCHECK is on.
  bool has_usage_;
  bool has_global_limited_usage_;
  bool has_quota_;
  bool has_available_disk_space_;

  QuotaStatusCode status_;
  UsageAndQuota usage_and_quota_;
  QuotaManager::UsageAndQuotaCallback callback_;
  int waiting_callbacks_;

  DISALLOW_COPY_AND_ASSIGN(UsageAndQuotaCallbackDispatcher);
};

class QuotaManager::GetUsageInfoTask : public QuotaTask {
 public:
  GetUsageInfoTask(
      QuotaManager* manager,
      const GetUsageInfoCallback& callback)
      : QuotaTask(manager),
        callback_(callback),
        weak_factory_(this) {
  }

 protected:
  void Run() override {
    // crbug.com/349708
    TRACE_EVENT0("io", "QuotaManager::GetUsageInfoTask::Run");

    remaining_trackers_ = 3;
    // This will populate cached hosts and usage info.
    manager()->GetUsageTracker(kStorageTypeTemporary)->GetGlobalUsage(
        base::Bind(&GetUsageInfoTask::DidGetGlobalUsage,
                   weak_factory_.GetWeakPtr(),
                   kStorageTypeTemporary));
    manager()->GetUsageTracker(kStorageTypePersistent)->GetGlobalUsage(
        base::Bind(&GetUsageInfoTask::DidGetGlobalUsage,
                   weak_factory_.GetWeakPtr(),
                   kStorageTypePersistent));
    manager()->GetUsageTracker(kStorageTypeSyncable)->GetGlobalUsage(
        base::Bind(&GetUsageInfoTask::DidGetGlobalUsage,
                   weak_factory_.GetWeakPtr(),
                   kStorageTypeSyncable));
  }

  void Completed() override {
    // crbug.com/349708
    TRACE_EVENT0("io", "QuotaManager::GetUsageInfoTask::Completed");

    callback_.Run(entries_);
    DeleteSoon();
  }

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

 private:
  void AddEntries(StorageType type, UsageTracker* tracker) {
    std::map<std::string, int64_t> host_usage;
    tracker->GetCachedHostsUsage(&host_usage);
    for (std::map<std::string, int64_t>::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_t, int64_t) {
    DCHECK(manager()->GetUsageTracker(type));
    AddEntries(type, manager()->GetUsageTracker(type));
  }

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

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

  DISALLOW_COPY_AND_ASSIGN(GetUsageInfoTask);
};

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

 protected:
  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();
      }
    }
  }

  void Completed() override {
    if (error_count_ == 0) {
      // crbug.com/349708
      TRACE_EVENT0("io", "QuotaManager::OriginDataDeleter::Completed Ok");

      // Only remove the entire origin if we didn't skip any client types.
      if (skipped_clients_ == 0)
        manager()->DeleteOriginFromDatabase(origin_, type_, is_eviction_);
      callback_.Run(kQuotaStatusOk);
    } else {
      // crbug.com/349708
      TRACE_EVENT0("io", "QuotaManager::OriginDataDeleter::Completed Error");

      callback_.Run(kQuotaErrorInvalidModification);
    }
    DeleteSoon();
  }

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

 private:
  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_;
  bool is_eviction_;
  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_(this) {}

 protected:
  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()));
    }
  }

  void Completed() override {
    if (error_count_ == 0) {
      // crbug.com/349708
      TRACE_EVENT0("io", "QuotaManager::HostDataDeleter::Completed Ok");

      callback_.Run(kQuotaStatusOk);
    } else {
      // crbug.com/349708
      TRACE_EVENT0("io", "QuotaManager::HostDataDeleter::Completed Error");

      callback_.Run(kQuotaErrorInvalidModification);
    }
    DeleteSoon();
  }

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

 private:
  void DidGetOriginsForHost(const std::set<GURL>& origins) {
    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_, false,
          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::GetModifiedSinceHelper {
 public:
  bool GetModifiedSinceOnDBThread(StorageType type,
                                  base::Time modified_since,
                                  QuotaDatabase* database) {
    DCHECK(database);
    return database->GetOriginsModifiedSince(type, &origins_, modified_since);
  }

  void DidGetModifiedSince(const base::WeakPtr<QuotaManager>& manager,
                           const GetOriginsCallback& callback,
                           StorageType type,
                           bool success) {
    if (!manager) {
      // The operation was aborted.
      callback.Run(std::set<GURL>(), type);
      return;
    }
    manager->DidDatabaseWork(success);
    callback.Run(origins_, type);
  }

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

class QuotaManager::DumpQuotaTableHelper {
 public:
  bool DumpQuotaTableOnDBThread(QuotaDatabase* database) {
    DCHECK(database);
    return database->DumpQuotaTable(
        base::Bind(&DumpQuotaTableHelper::AppendEntry, base::Unretained(this)));
  }

  void DidDumpQuotaTable(const base::WeakPtr<QuotaManager>& manager,
                         const DumpQuotaTableCallback& callback,
                         bool success) {
    if (!manager) {
      // The operation was aborted.
      callback.Run(QuotaTableEntries());
      return;
    }
    manager->DidDatabaseWork(success);
    callback.Run(entries_);
  }

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

  QuotaTableEntries entries_;
};

class QuotaManager::DumpOriginInfoTableHelper {
 public:
  bool DumpOriginInfoTableOnDBThread(QuotaDatabase* database) {
    DCHECK(database);
    return database->DumpOriginInfoTable(
        base::Bind(&DumpOriginInfoTableHelper::AppendEntry,
                   base::Unretained(this)));
  }

  void DidDumpOriginInfoTable(const base::WeakPtr<QuotaManager>& manager,
                              const DumpOriginInfoTableCallback& callback,
                              bool success) {
    if (!manager) {
      // The operation was aborted.
      callback.Run(OriginInfoTableEntries());
      return;
    }
    manager->DidDatabaseWork(success);
    callback.Run(entries_);
  }

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

  OriginInfoTableEntries entries_;
};

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

QuotaManager::QuotaManager(
    bool is_incognito,
    const base::FilePath& profile_path,
    const scoped_refptr<base::SingleThreadTaskRunner>& io_thread,
    const scoped_refptr<base::SequencedTaskRunner>& db_thread,
    const scoped_refptr<SpecialStoragePolicy>& special_storage_policy)
    : is_incognito_(is_incognito),
      profile_path_(profile_path),
      proxy_(new QuotaManagerProxy(this, io_thread)),
      db_disabled_(false),
      eviction_disabled_(false),
      io_thread_(io_thread),
      db_thread_(db_thread),
      is_getting_eviction_origin_(false),
      temporary_quota_initialized_(false),
      temporary_quota_override_(-1),
      desired_available_space_(-1),
      special_storage_policy_(special_storage_policy),
      get_disk_space_fn_(&QuotaManager::CallSystemGetAmountOfFreeDiskSpace),
      storage_monitor_(new StorageMonitor(this)),
      weak_factory_(this) {}

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

void QuotaManager::GetUsageAndQuotaForWebApps(
    const GURL& origin,
    StorageType type,
    const GetUsageAndQuotaCallback& callback) {
  // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed.
  tracked_objects::ScopedTracker tracking_profile(
      FROM_HERE_WITH_EXPLICIT_FUNCTION(
          "477117 QuotaManager::GetUsageAndQuotaForWebApps"));
  if (type != kStorageTypeTemporary &&
      type != kStorageTypePersistent &&
      type != kStorageTypeSyncable) {
    callback.Run(kQuotaErrorNotSupported, 0, 0);
    return;
  }

  DCHECK(origin == origin.GetOrigin());
  LazyInitialize();

  bool unlimited = IsStorageUnlimited(origin, type);
  bool can_query_disk_size = CanQueryDiskSize(origin);

  UsageAndQuotaCallbackDispatcher* dispatcher =
      new UsageAndQuotaCallbackDispatcher(this);

  UsageAndQuota usage_and_quota;
  if (unlimited) {
    dispatcher->set_quota(kNoLimit);
  } else {
    if (type == kStorageTypeTemporary) {
      GetUsageTracker(type)->GetGlobalLimitedUsage(
          dispatcher->GetGlobalLimitedUsageCallback());
      GetTemporaryGlobalQuota(dispatcher->GetQuotaCallback());
    } else if (type == kStorageTypePersistent) {
      GetPersistentHostQuota(net::GetHostOrSpecFromURL(origin),
                             dispatcher->GetQuotaCallback());
    } else {
      dispatcher->set_quota(kSyncableStorageDefaultHostQuota);
    }
  }

  DCHECK(GetUsageTracker(type));
  GetUsageTracker(type)->GetHostUsage(net::GetHostOrSpecFromURL(origin),
                                      dispatcher->GetHostUsageCallback());

  if (!is_incognito_ && (unlimited || can_query_disk_size))
    GetAvailableSpace(dispatcher->GetAvailableSpaceCallback());

  dispatcher->WaitForResults(base::Bind(
      &DispatchUsageAndQuotaForWebApps,
      type, is_incognito_, unlimited, can_query_disk_size,
      callback));
}

void QuotaManager::GetUsageAndQuota(
    const GURL& origin, StorageType type,
    const GetUsageAndQuotaCallback& callback) {
  DCHECK(origin == origin.GetOrigin());

  if (IsStorageUnlimited(origin, type)) {
    callback.Run(kQuotaStatusOk, 0, kNoLimit);
    return;
  }

  GetUsageAndQuotaForWebApps(origin, type, callback);
}

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

void QuotaManager::NotifyStorageModified(QuotaClient::ID client_id,
                                         const GURL& origin,
                                         StorageType type,
                                         int64_t delta) {
  DCHECK(origin == origin.GetOrigin());
  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::SetUsageCacheEnabled(QuotaClient::ID client_id,
                                        const GURL& origin,
                                        StorageType type,
                                        bool enabled) {
  LazyInitialize();
  DCHECK(GetUsageTracker(type));
  GetUsageTracker(type)->SetUsageCacheEnabled(client_id, origin, enabled);
}

void QuotaManager::SetTemporaryStorageEvictionPolicy(
    scoped_ptr<QuotaEvictionPolicy> policy) {
  temporary_storage_eviction_policy_ = std::move(policy);
}

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

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();
}

void QuotaManager::GetAvailableSpace(const AvailableSpaceCallback& callback) {
  if (!available_space_callbacks_.Add(callback))
    return;
  // crbug.com/349708
  TRACE_EVENT0("io", "QuotaManager::GetAvailableSpace");

  PostTaskAndReplyWithResult(db_thread_.get(),
                             FROM_HERE,
                             base::Bind(get_disk_space_fn_, profile_path_),
                             base::Bind(&QuotaManager::DidGetAvailableSpace,
                                        weak_factory_.GetWeakPtr()));
}

void QuotaManager::GetTemporaryGlobalQuota(const QuotaCallback& callback) {
  LazyInitialize();
  if (!temporary_quota_initialized_) {
    db_initialization_callbacks_.Add(base::Bind(
        &QuotaManager::GetTemporaryGlobalQuota,
        weak_factory_.GetWeakPtr(), callback));
    return;
  }

  if (temporary_quota_override_ > 0) {
    callback.Run(kQuotaStatusOk, temporary_quota_override_);
    return;
  }

  UsageAndQuotaCallbackDispatcher* dispatcher =
      new UsageAndQuotaCallbackDispatcher(this);
  GetUsageTracker(kStorageTypeTemporary)->
      GetGlobalLimitedUsage(dispatcher->GetGlobalLimitedUsageCallback());
  GetAvailableSpace(dispatcher->GetAvailableSpaceCallback());
  dispatcher->WaitForResults(
      base::Bind(&DispatchTemporaryGlobalQuotaCallback, callback));
}

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

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

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

  int64_t* new_quota_ptr = new int64_t(new_quota);
  PostTaskAndReplyWithResultForDBThread(
      FROM_HERE,
      base::Bind(&SetTemporaryGlobalOverrideQuotaOnDBThread,
                 base::Unretained(new_quota_ptr)),
      base::Bind(&QuotaManager::DidSetTemporaryGlobalOverrideQuota,
                 weak_factory_.GetWeakPtr(),
                 callback,
                 base::Owned(new_quota_ptr)));
}

void QuotaManager::GetPersistentHostQuota(const std::string& host,
                                          const QuotaCallback& 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, 0);
    return;
  }

  if (!persistent_host_quota_callbacks_.Add(host, callback))
    return;

  int64_t* quota_ptr = new int64_t(0);
  PostTaskAndReplyWithResultForDBThread(
      FROM_HERE,
      base::Bind(&GetPersistentHostQuotaOnDBThread,
                 host,
                 base::Unretained(quota_ptr)),
      base::Bind(&QuotaManager::DidGetPersistentHostQuota,
                 weak_factory_.GetWeakPtr(),
                 host,
                 base::Owned(quota_ptr)));
}

void QuotaManager::SetPersistentHostQuota(const std::string& host,
                                          int64_t new_quota,
                                          const QuotaCallback& callback) {
  LazyInitialize();
  if (host.empty()) {
    // This could happen if we are called on file:///.
    callback.Run(kQuotaErrorNotSupported, 0);
    return;
  }

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

  if (kPerHostPersistentQuotaLimit < new_quota) {
    // Cap the requested size at the per-host quota limit.
    new_quota = kPerHostPersistentQuotaLimit;
  }

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

  int64_t* new_quota_ptr = new int64_t(new_quota);
  PostTaskAndReplyWithResultForDBThread(
      FROM_HERE,
      base::Bind(&SetPersistentHostQuotaOnDBThread,
                 host,
                 base::Unretained(new_quota_ptr)),
      base::Bind(&QuotaManager::DidSetPersistentHostQuota,
                 weak_factory_.GetWeakPtr(),
                 host,
                 callback,
                 base::Owned(new_quota_ptr)));
}

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

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

void QuotaManager::GetHostUsage(const std::string& host,
                                StorageType type,
                                QuotaClient::ID client_id,
                                const UsageCallback& callback) {
  LazyInitialize();
  DCHECK(GetUsageTracker(type));
  ClientUsageTracker* tracker =
      GetUsageTracker(type)->GetClientTracker(client_id);
  if (!tracker) {
    callback.Run(0);
    return;
  }
  tracker->GetHostUsage(host, callback);
}

bool QuotaManager::IsTrackingHostUsage(StorageType type,
                                       QuotaClient::ID client_id) const {
  UsageTracker* tracker = GetUsageTracker(type);
  return tracker && tracker->GetClientTracker(client_id);
}

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

bool QuotaManager::IsStorageUnlimited(const GURL& origin,
                                      StorageType type) const {
  // For syncable storage we should always enforce quota (since the
  // quota must be capped by the server limit).
  if (type == kStorageTypeSyncable)
    return false;
  if (type == kStorageTypeQuotaNotManaged)
    return true;
  return special_storage_policy_.get() &&
         special_storage_policy_->IsStorageUnlimited(origin);
}

void QuotaManager::GetOriginsModifiedSince(StorageType type,
                                           base::Time modified_since,
                                           const GetOriginsCallback& callback) {
  LazyInitialize();
  GetModifiedSinceHelper* helper = new GetModifiedSinceHelper;
  PostTaskAndReplyWithResultForDBThread(
      FROM_HERE,
      base::Bind(&GetModifiedSinceHelper::GetModifiedSinceOnDBThread,
                 base::Unretained(helper),
                 type,
                 modified_since),
      base::Bind(&GetModifiedSinceHelper::DidGetModifiedSince,
                 base::Owned(helper),
                 weak_factory_.GetWeakPtr(),
                 callback,
                 type));
}

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

void QuotaManager::AddStorageObserver(
    StorageObserver* observer, const StorageObserver::MonitorParams& params) {
  DCHECK(observer);
  storage_monitor_->AddObserver(observer, params);
}

void QuotaManager::RemoveStorageObserver(StorageObserver* observer) {
  DCHECK(observer);
  storage_monitor_->RemoveObserver(observer);
}

void QuotaManager::RemoveStorageObserverForFilter(
    StorageObserver* observer, const StorageObserver::Filter& filter) {
  DCHECK(observer);
  storage_monitor_->RemoveObserverForFilter(observer, filter);
}

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

QuotaManager::EvictionContext::EvictionContext()
    : evicted_type(kStorageTypeUnknown) {
}

QuotaManager::EvictionContext::~EvictionContext() {
}

void QuotaManager::LazyInitialize() {
  DCHECK(io_thread_->BelongsToCurrentThread());
  if (database_) {
    // 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_ ? base::FilePath() :
      profile_path_.AppendASCII(kDatabaseName)));

  temporary_usage_tracker_.reset(new UsageTracker(
      clients_, kStorageTypeTemporary, special_storage_policy_.get(),
      storage_monitor_.get()));
  persistent_usage_tracker_.reset(new UsageTracker(
      clients_, kStorageTypePersistent, special_storage_policy_.get(),
      storage_monitor_.get()));
  syncable_usage_tracker_.reset(new UsageTracker(
      clients_, kStorageTypeSyncable, special_storage_policy_.get(),
      storage_monitor_.get()));

  int64_t* temporary_quota_override = new int64_t(-1);
  int64_t* desired_available_space = new int64_t(-1);
  PostTaskAndReplyWithResultForDBThread(
      FROM_HERE,
      base::Bind(&InitializeOnDBThread,
                 base::Unretained(temporary_quota_override),
                 base::Unretained(desired_available_space)),
      base::Bind(&QuotaManager::DidInitialize,
                 weak_factory_.GetWeakPtr(),
                 base::Owned(temporary_quota_override),
                 base::Owned(desired_available_space)));
}

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

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

void QuotaManager::GetCachedOrigins(
    StorageType type, std::set<GURL>* origins) {
  DCHECK(origins);
  LazyInitialize();
  DCHECK(GetUsageTracker(type));
  GetUsageTracker(type)->GetCachedOrigins(origins);
}

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

  if (db_disabled_)
    return;
  PostTaskAndReplyWithResultForDBThread(
      FROM_HERE,
      base::Bind(&UpdateAccessTimeOnDBThread, origin, type, accessed_time),
      base::Bind(&QuotaManager::DidDatabaseWork,
                 weak_factory_.GetWeakPtr()));
}

void QuotaManager::NotifyStorageModifiedInternal(QuotaClient::ID client_id,
                                                 const GURL& origin,
                                                 StorageType type,
                                                 int64_t delta,
                                                 base::Time modified_time) {
  LazyInitialize();
  DCHECK(GetUsageTracker(type));
  GetUsageTracker(type)->UpdateUsageCache(client_id, origin, delta);

  PostTaskAndReplyWithResultForDBThread(
      FROM_HERE,
      base::Bind(&UpdateModifiedTimeOnDBThread, origin, type, modified_time),
      base::Bind(&QuotaManager::DidDatabaseWork,
                 weak_factory_.GetWeakPtr()));
}

void QuotaManager::DumpQuotaTable(const DumpQuotaTableCallback& callback) {
  DumpQuotaTableHelper* helper = new DumpQuotaTableHelper;
  PostTaskAndReplyWithResultForDBThread(
      FROM_HERE,
      base::Bind(&DumpQuotaTableHelper::DumpQuotaTableOnDBThread,
                 base::Unretained(helper)),
      base::Bind(&DumpQuotaTableHelper::DidDumpQuotaTable,
                 base::Owned(helper),
                 weak_factory_.GetWeakPtr(),
                 callback));
}

void QuotaManager::DumpOriginInfoTable(
    const DumpOriginInfoTableCallback& callback) {
  DumpOriginInfoTableHelper* helper = new DumpOriginInfoTableHelper;
  PostTaskAndReplyWithResultForDBThread(
      FROM_HERE,
      base::Bind(&DumpOriginInfoTableHelper::DumpOriginInfoTableOnDBThread,
                 base::Unretained(helper)),
      base::Bind(&DumpOriginInfoTableHelper::DidDumpOriginInfoTable,
                 base::Owned(helper),
                 weak_factory_.GetWeakPtr(),
                 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::DeleteOriginFromDatabase(const GURL& origin,
                                            StorageType type,
                                            bool is_eviction) {
  LazyInitialize();
  if (db_disabled_)
    return;

  PostTaskAndReplyWithResultForDBThread(
      FROM_HERE,
      base::Bind(&DeleteOriginInfoOnDBThread, origin, type, is_eviction),
      base::Bind(&QuotaManager::DidDatabaseWork, weak_factory_.GetWeakPtr()));
}

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::DeleteOriginDataInternal(const GURL& origin,
                                            StorageType type,
                                            int quota_client_mask,
                                            bool is_eviction,
                                            const StatusCallback& callback) {
  LazyInitialize();

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

  DCHECK(origin == origin.GetOrigin());
  OriginDataDeleter* deleter = new OriginDataDeleter(
      this, origin, type, quota_client_mask, is_eviction, callback);
  deleter->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(
    int64_t usage,
    int64_t unlimited_usage) {
  UMA_HISTOGRAM_MBYTES("Quota.GlobalUsageOfTemporaryStorage", usage);

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

  size_t num_origins = origins.size();
  size_t protected_origins = 0;
  size_t unlimited_origins = 0;
  CountOriginType(origins,
                  special_storage_policy_.get(),
                  &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(
    int64_t usage,
    int64_t unlimited_usage) {
  UMA_HISTOGRAM_MBYTES("Quota.GlobalUsageOfPersistentStorage", usage);

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

  size_t num_origins = origins.size();
  size_t protected_origins = 0;
  size_t unlimited_origins = 0;
  CountOriginType(origins,
                  special_storage_policy_.get(),
                  &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);
}

std::set<GURL> QuotaManager::GetEvictionOriginExceptions(
    const std::set<GURL>& extra_exceptions) {
  std::set<GURL> exceptions = extra_exceptions;
  for (const auto& p : origins_in_use_) {
    if (p.second > 0)
      exceptions.insert(p.first);
  }

  for (const auto& p : origins_in_error_) {
    if (p.second > QuotaManager::kThresholdOfErrorsToBeBlacklisted)
      exceptions.insert(p.first);
  }

  return exceptions;
}

void QuotaManager::DidGetEvictionOrigin(const GetOriginCallback& callback,
                                        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 (ContainsKey(origins_in_use_, origin) ||
      ContainsKey(access_notified_origins_, origin)) {
    callback.Run(GURL());
  } else {
    callback.Run(origin);
  }
  access_notified_origins_.clear();

  is_getting_eviction_origin_ = false;
}

void QuotaManager::GetEvictionOrigin(StorageType type,
                                     const std::set<GURL>& extra_exceptions,
                                     int64_t global_quota,
                                     const GetOriginCallback& callback) {
  LazyInitialize();
  // This must not be called while there's an in-flight task.
  DCHECK(!is_getting_eviction_origin_);
  is_getting_eviction_origin_ = true;

  GetOriginCallback did_get_origin_callback =
      base::Bind(&QuotaManager::DidGetEvictionOrigin,
                 weak_factory_.GetWeakPtr(), callback);

  if (type == kStorageTypeTemporary && temporary_storage_eviction_policy_) {
    std::map<GURL, int64_t> usage_map;
    // The cached origins are populated by the prior call to
    // GetUsageAndQuotaForEviction().
    GetUsageTracker(kStorageTypeTemporary)->GetCachedOriginsUsage(&usage_map);

    temporary_storage_eviction_policy_->GetEvictionOrigin(
        special_storage_policy_, GetEvictionOriginExceptions(extra_exceptions),
        usage_map, global_quota, did_get_origin_callback);

    return;
  }

  // TODO(calamity): convert LRU origin retrieval into a QuotaEvictionPolicy.
  GetLRUOrigin(type, did_get_origin_callback);
}

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;

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

void QuotaManager::GetUsageAndQuotaForEviction(
    const UsageAndQuotaCallback& callback) {
  // crbug.com/349708
  TRACE_EVENT0("io", "QuotaManager::GetUsageAndQuotaForEviction");

  DCHECK(io_thread_->BelongsToCurrentThread());
  LazyInitialize();

  UsageAndQuotaCallbackDispatcher* dispatcher =
      new UsageAndQuotaCallbackDispatcher(this);
  GetUsageTracker(kStorageTypeTemporary)
      ->GetGlobalLimitedUsage(dispatcher->GetGlobalLimitedUsageCallback());
  GetTemporaryGlobalQuota(dispatcher->GetQuotaCallback());
  GetAvailableSpace(dispatcher->GetAvailableSpaceCallback());
  dispatcher->WaitForResults(callback);
}

void QuotaManager::GetLRUOrigin(StorageType type,
                                const GetOriginCallback& 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;
  }

  GURL* url = new GURL;
  PostTaskAndReplyWithResultForDBThread(
      FROM_HERE, base::Bind(&GetLRUOriginOnDBThread, type,
                            GetEvictionOriginExceptions(std::set<GURL>()),
                            special_storage_policy_, base::Unretained(url)),
      base::Bind(&QuotaManager::DidGetLRUOrigin, weak_factory_.GetWeakPtr(),
                 base::Owned(url)));
}

void QuotaManager::DidSetTemporaryGlobalOverrideQuota(
    const QuotaCallback& callback,
    const int64_t* new_quota,
    bool success) {
  QuotaStatusCode status = kQuotaErrorInvalidAccess;
  DidDatabaseWork(success);
  if (success) {
    temporary_quota_override_ = *new_quota;
    status = kQuotaStatusOk;
  }

  if (callback.is_null())
    return;

  callback.Run(status, *new_quota);
}

void QuotaManager::DidGetPersistentHostQuota(const std::string& host,
                                             const int64_t* quota,
                                             bool success) {
  DidDatabaseWork(success);
  persistent_host_quota_callbacks_.Run(host, kQuotaStatusOk, *quota);
}

void QuotaManager::DidSetPersistentHostQuota(const std::string& host,
                                             const QuotaCallback& callback,
                                             const int64_t* new_quota,
                                             bool success) {
  DidDatabaseWork(success);
  callback.Run(success ? kQuotaStatusOk : kQuotaErrorInvalidAccess, *new_quota);
}

void QuotaManager::DidInitialize(int64_t* temporary_quota_override,
                                 int64_t* desired_available_space,
                                 bool success) {
  temporary_quota_override_ = *temporary_quota_override;
  desired_available_space_ = *desired_available_space;
  temporary_quota_initialized_ = true;
  DidDatabaseWork(success);

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

  db_initialization_callbacks_.Run();
  GetTemporaryGlobalQuota(
      base::Bind(&QuotaManager::DidGetInitialTemporaryGlobalQuota,
                 weak_factory_.GetWeakPtr(), base::TimeTicks::Now()));
}

void QuotaManager::DidGetLRUOrigin(const GURL* origin,
                                   bool success) {
  DidDatabaseWork(success);

  lru_origin_callback_.Run(*origin);
  lru_origin_callback_.Reset();
}

void QuotaManager::DidGetInitialTemporaryGlobalQuota(
    base::TimeTicks start_ticks,
    QuotaStatusCode status,
    int64_t quota_unused) {
  UMA_HISTOGRAM_LONG_TIMES(
      "Quota.TimeToInitializeGlobalQuota",
      base::TimeTicks::Now() - start_ticks);

  if (eviction_disabled_)
    return;

  std::set<GURL>* origins = new std::set<GURL>;
  temporary_usage_tracker_->GetCachedOrigins(origins);
  // This will call the StartEviction() when initial origin registration
  // is completed.
  PostTaskAndReplyWithResultForDBThread(
      FROM_HERE,
      base::Bind(&InitializeTemporaryOriginsInfoOnDBThread,
                 base::Owned(origins)),
      base::Bind(&QuotaManager::DidInitializeTemporaryOriginsInfo,
                 weak_factory_.GetWeakPtr()));
}

void QuotaManager::DidInitializeTemporaryOriginsInfo(bool success) {
  DidDatabaseWork(success);
  if (success)
    StartEviction();
}

void QuotaManager::DidGetAvailableSpace(int64_t space) {
  // crbug.com/349708
  TRACE_EVENT1("io", "QuotaManager::DidGetAvailableSpace",
               "n_callbacks", available_space_callbacks_.size());

  available_space_callbacks_.Run(kQuotaStatusOk, space);
}

void QuotaManager::DidDatabaseWork(bool success) {
  db_disabled_ = !success;
}

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

void QuotaManager::PostTaskAndReplyWithResultForDBThread(
    const tracked_objects::Location& from_here,
    const base::Callback<bool(QuotaDatabase*)>& task,
    const base::Callback<void(bool)>& reply) {
  // Deleting manager will post another task to DB thread to delete
  // |database_|, therefore we can be sure that database_ is alive when this
  // task runs.
  base::PostTaskAndReplyWithResult(
      db_thread_.get(),
      from_here,
      base::Bind(task, base::Unretained(database_.get())),
      reply);
}

//static
int64_t QuotaManager::CallSystemGetAmountOfFreeDiskSpace(
    const base::FilePath& profile_path) {
  // crbug.com/349708
  TRACE_EVENT0("io", "CallSystemGetAmountOfFreeDiskSpace");
  if (!base::CreateDirectory(profile_path)) {
    LOG(WARNING) << "Create directory failed for path" << profile_path.value();
    return 0;
  }
  uint64_t available, total;
  if (!QuotaManager::GetVolumeInfo(profile_path, &available, &total)) {
    return 0;
  }
  UMA_HISTOGRAM_MBYTES("Quota.AvailableDiskSpace", available);
  UMA_HISTOGRAM_MBYTES("Quota.TotalDiskSpace", total);
  return static_cast<int64_t>(available);
}

//static
bool QuotaManager::GetVolumeInfo(const base::FilePath& path,
                                 uint64_t* available_space,
                                 uint64_t* total_size) {
  // Inspired by similar code in the base::SysInfo class.
  base::ThreadRestrictions::AssertIOAllowed();
#if defined(OS_WIN)
  ULARGE_INTEGER available, total, free;
  if (!GetDiskFreeSpaceExW(path.value().c_str(), &available, &total, &free))
    return false;
  *available_space = static_cast<uint64_t>(available.QuadPart);
  *total_size = static_cast<uint64_t>(total.QuadPart);
#elif defined(OS_POSIX)
  struct statvfs stats;
  if (HANDLE_EINTR(statvfs(path.value().c_str(), &stats)) != 0)
    return false;
  *available_space = static_cast<uint64_t>(stats.f_bavail) * stats.f_frsize;
  *total_size = static_cast<uint64_t>(stats.f_blocks) * stats.f_frsize;
#else
#error Not implemented
#endif
  return true;
}

}  // namespace storage
