// 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 "storage/browser/fileapi/file_system_quota_client.h"

#include <algorithm>
#include <memory>

#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/task_runner_util.h"
#include "storage/browser/fileapi/file_system_context.h"
#include "storage/browser/fileapi/file_system_usage_cache.h"
#include "storage/browser/fileapi/sandbox_file_system_backend.h"
#include "storage/common/fileapi/file_system_util.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
#include "url/gurl.h"

using blink::mojom::StorageType;

namespace storage {

namespace {

void GetOriginsForTypeOnFileTaskRunner(FileSystemContext* context,
                                       StorageType storage_type,
                                       std::set<url::Origin>* origins_ptr) {
  FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type);
  DCHECK(type != kFileSystemTypeUnknown);

  FileSystemQuotaUtil* quota_util = context->GetQuotaUtil(type);
  if (!quota_util)
    return;
  std::set<GURL> origins;
  quota_util->GetOriginsForTypeOnFileTaskRunner(type, &origins);
  for (auto origin : origins)
    origins_ptr->insert(url::Origin::Create(origin));
}

void GetOriginsForHostOnFileTaskRunner(FileSystemContext* context,
                                       StorageType storage_type,
                                       const std::string& host,
                                       std::set<url::Origin>* origins_ptr) {
  FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type);
  DCHECK(type != kFileSystemTypeUnknown);

  FileSystemQuotaUtil* quota_util = context->GetQuotaUtil(type);
  if (!quota_util)
    return;
  std::set<GURL> origins;
  quota_util->GetOriginsForHostOnFileTaskRunner(type, host, &origins);
  for (auto origin : origins)
    origins_ptr->insert(url::Origin::Create(origin));
}

void DidGetFileSystemQuotaClientOrigins(
    storage::QuotaClient::GetOriginsCallback callback,
    std::set<url::Origin>* origins_ptr) {
  std::move(callback).Run(*origins_ptr);
}

blink::mojom::QuotaStatusCode DeleteOriginOnFileTaskRunner(
    FileSystemContext* context,
    const url::Origin& origin,
    FileSystemType type) {
  FileSystemBackend* provider = context->GetFileSystemBackend(type);
  if (!provider || !provider->GetQuotaUtil())
    return blink::mojom::QuotaStatusCode::kErrorNotSupported;
  base::File::Error result =
      provider->GetQuotaUtil()->DeleteOriginDataOnFileTaskRunner(
          context, context->quota_manager_proxy(), origin.GetURL(), type);
  if (result == base::File::FILE_OK)
    return blink::mojom::QuotaStatusCode::kOk;
  return blink::mojom::QuotaStatusCode::kErrorInvalidModification;
}

}  // namespace

FileSystemQuotaClient::FileSystemQuotaClient(
    FileSystemContext* file_system_context,
    bool is_incognito)
    : file_system_context_(file_system_context),
      is_incognito_(is_incognito) {
}

FileSystemQuotaClient::~FileSystemQuotaClient() = default;

storage::QuotaClient::ID FileSystemQuotaClient::id() const {
  return storage::QuotaClient::kFileSystem;
}

void FileSystemQuotaClient::OnQuotaManagerDestroyed() {
  delete this;
}

void FileSystemQuotaClient::GetOriginUsage(const url::Origin& origin,
                                           StorageType storage_type,
                                           GetUsageCallback callback) {
  DCHECK(!callback.is_null());

  if (is_incognito_) {
    // We don't support FileSystem in incognito mode yet.
    std::move(callback).Run(0);
    return;
  }

  FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type);
  DCHECK(type != kFileSystemTypeUnknown);

  FileSystemQuotaUtil* quota_util = file_system_context_->GetQuotaUtil(type);
  if (!quota_util) {
    std::move(callback).Run(0);
    return;
  }

  base::PostTaskAndReplyWithResult(
      file_task_runner(), FROM_HERE,
      // It is safe to pass Unretained(quota_util) since context owns it.
      base::BindOnce(&FileSystemQuotaUtil::GetOriginUsageOnFileTaskRunner,
                     base::Unretained(quota_util),
                     base::RetainedRef(file_system_context_), origin.GetURL(),
                     type),
      std::move(callback));
}

void FileSystemQuotaClient::GetOriginsForType(StorageType storage_type,
                                              GetOriginsCallback callback) {
  DCHECK(!callback.is_null());

  if (is_incognito_) {
    // We don't support FileSystem in incognito mode yet.
    std::set<url::Origin> origins;
    std::move(callback).Run(origins);
    return;
  }

  std::set<url::Origin>* origins_ptr = new std::set<url::Origin>();
  file_task_runner()->PostTaskAndReply(
      FROM_HERE,
      base::BindOnce(&GetOriginsForTypeOnFileTaskRunner,
                     base::RetainedRef(file_system_context_), storage_type,
                     base::Unretained(origins_ptr)),
      base::BindOnce(&DidGetFileSystemQuotaClientOrigins, std::move(callback),
                     base::Owned(origins_ptr)));
}

void FileSystemQuotaClient::GetOriginsForHost(StorageType storage_type,
                                              const std::string& host,
                                              GetOriginsCallback callback) {
  DCHECK(!callback.is_null());

  if (is_incognito_) {
    // We don't support FileSystem in incognito mode yet.
    std::set<url::Origin> origins;
    std::move(callback).Run(origins);
    return;
  }

  std::set<url::Origin>* origins_ptr = new std::set<url::Origin>();
  file_task_runner()->PostTaskAndReply(
      FROM_HERE,
      base::BindOnce(&GetOriginsForHostOnFileTaskRunner,
                     base::RetainedRef(file_system_context_), storage_type,
                     host, base::Unretained(origins_ptr)),
      base::BindOnce(&DidGetFileSystemQuotaClientOrigins, std::move(callback),
                     base::Owned(origins_ptr)));
}

void FileSystemQuotaClient::DeleteOriginData(const url::Origin& origin,
                                             StorageType type,
                                             DeletionCallback callback) {
  FileSystemType fs_type = QuotaStorageTypeToFileSystemType(type);
  DCHECK(fs_type != kFileSystemTypeUnknown);

  base::PostTaskAndReplyWithResult(
      file_task_runner(), FROM_HERE,
      base::BindOnce(&DeleteOriginOnFileTaskRunner,
                     base::RetainedRef(file_system_context_), origin, fs_type),
      std::move(callback));
}

bool FileSystemQuotaClient::DoesSupport(StorageType storage_type) const {
  FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type);
  DCHECK(type != kFileSystemTypeUnknown);
  return file_system_context_->IsSandboxFileSystem(type);
}

base::SequencedTaskRunner* FileSystemQuotaClient::file_task_runner() const {
  return file_system_context_->default_file_task_runner();
}

}  // namespace storage
