// 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 "chrome/browser/browsing_data/browsing_data_quota_helper_impl.h"

#include <map>
#include <set>

#include "base/barrier_closure.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/task/post_task.h"
#include "chrome/browser/browsing_data/browsing_data_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "storage/browser/quota/quota_manager.h"

using blink::mojom::StorageType;
using content::BrowserThread;
using content::BrowserContext;

// static
BrowsingDataQuotaHelper* BrowsingDataQuotaHelper::Create(Profile* profile) {
  return new BrowsingDataQuotaHelperImpl(
      BrowserContext::GetDefaultStoragePartition(profile)->GetQuotaManager());
}

void BrowsingDataQuotaHelperImpl::StartFetching(FetchResultCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!callback.is_null());

  base::PostTaskWithTraits(
      FROM_HERE, {BrowserThread::IO},
      base::BindOnce(&BrowsingDataQuotaHelperImpl::FetchQuotaInfoOnIOThread,
                     this, std::move(callback)));
}

void BrowsingDataQuotaHelperImpl::RevokeHostQuota(const std::string& host) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  base::PostTaskWithTraits(
      FROM_HERE, {BrowserThread::IO},
      base::BindOnce(&BrowsingDataQuotaHelperImpl::RevokeHostQuotaOnIOThread,
                     this, host));
}

BrowsingDataQuotaHelperImpl::BrowsingDataQuotaHelperImpl(
    storage::QuotaManager* quota_manager)
    : BrowsingDataQuotaHelper(),
      quota_manager_(quota_manager),
      weak_factory_(this) {
  DCHECK(quota_manager);
}

BrowsingDataQuotaHelperImpl::~BrowsingDataQuotaHelperImpl() {}

void BrowsingDataQuotaHelperImpl::FetchQuotaInfoOnIOThread(
    FetchResultCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  const StorageType types[] = {StorageType::kTemporary,
                               StorageType::kPersistent,
                               StorageType::kSyncable};

  // Query hosts for each storage types. When complete, process the collected
  // hosts.
  PendingHosts* pending_hosts = new PendingHosts();
  base::RepeatingClosure completion = base::BarrierClosure(
      arraysize(types),
      base::BindOnce(&BrowsingDataQuotaHelperImpl::OnGetOriginsComplete,
                     weak_factory_.GetWeakPtr(), std::move(callback),
                     base::Owned(pending_hosts)));

  for (const StorageType& type : types) {
    quota_manager_->GetOriginsModifiedSince(
        type, base::Time(),
        base::BindOnce(&BrowsingDataQuotaHelperImpl::GotOrigins,
                       weak_factory_.GetWeakPtr(), pending_hosts, completion));
  }
}

void BrowsingDataQuotaHelperImpl::GotOrigins(PendingHosts* pending_hosts,
                                             base::OnceClosure completion,
                                             const std::set<GURL>& origins,
                                             StorageType type) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  for (const GURL& url : origins) {
    if (!BrowsingDataHelper::HasWebScheme(url))
      continue;  // Non-websafe state is not considered browsing data.
    pending_hosts->insert(std::make_pair(url.host(), type));
  }
  std::move(completion).Run();
}

void BrowsingDataQuotaHelperImpl::OnGetOriginsComplete(
    FetchResultCallback callback,
    PendingHosts* pending_hosts) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  // Query usage for each (host, type). When complete, process the results.
  QuotaInfoMap* quota_info = new QuotaInfoMap();
  base::RepeatingClosure completion = base::BarrierClosure(
      pending_hosts->size(),
      base::BindOnce(&BrowsingDataQuotaHelperImpl::OnGetHostsUsageComplete,
                     weak_factory_.GetWeakPtr(), std::move(callback),
                     base::Owned(quota_info)));

  for (const auto& itr : *pending_hosts) {
    const std::string& host = itr.first;
    StorageType type = itr.second;
    quota_manager_->GetHostUsage(
        host, type,
        base::BindOnce(&BrowsingDataQuotaHelperImpl::GotHostUsage,
                       weak_factory_.GetWeakPtr(), quota_info, completion, host,
                       type));
  }
}

void BrowsingDataQuotaHelperImpl::GotHostUsage(QuotaInfoMap* quota_info,
                                               base::OnceClosure completion,
                                               const std::string& host,
                                               StorageType type,
                                               int64_t usage) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  switch (type) {
    case StorageType::kTemporary:
      (*quota_info)[host].temporary_usage = usage;
      break;
    case StorageType::kPersistent:
      (*quota_info)[host].persistent_usage = usage;
      break;
    case StorageType::kSyncable:
      (*quota_info)[host].syncable_usage = usage;
      break;
    default:
      NOTREACHED();
  }
  std::move(completion).Run();
}

void BrowsingDataQuotaHelperImpl::OnGetHostsUsageComplete(
    FetchResultCallback callback,
    QuotaInfoMap* quota_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  QuotaInfoArray result;
  for (auto& pair : *quota_info) {
    QuotaInfo& info = pair.second;
    // Skip unused entries
    if (info.temporary_usage <= 0 && info.persistent_usage <= 0 &&
        info.syncable_usage <= 0)
      continue;

    info.host = pair.first;
    result.push_back(info);
  }

  base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
                           base::BindOnce(std::move(callback), result));
}

void BrowsingDataQuotaHelperImpl::RevokeHostQuotaOnIOThread(
    const std::string& host) {
  quota_manager_->SetPersistentHostQuota(
      host, 0,
      base::BindOnce(&BrowsingDataQuotaHelperImpl::DidRevokeHostQuota,
                     weak_factory_.GetWeakPtr()));
}

void BrowsingDataQuotaHelperImpl::DidRevokeHostQuota(
    blink::mojom::QuotaStatusCode /*status*/,
    int64_t /*quota*/) {}
