// Copyright 2020 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 "content/browser/native_io/native_io_manager.h"

#include <memory>
#include <utility>

#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "build/build_config.h"
#include "content/browser/native_io/native_io_host.h"
#include "content/browser/native_io/native_io_quota_client.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "storage/browser/quota/quota_client.h"
#include "storage/browser/quota/quota_client_type.h"
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/browser/quota/special_storage_policy.h"
#include "storage/common/database/database_identifier.h"
#include "third_party/blink/public/common/native_io/native_io_utils.h"
#include "third_party/blink/public/mojom/native_io/native_io.mojom.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h"
#include "url/origin.h"

namespace content {

namespace {

std::vector<url::Origin> DoGetOrigins(const base::FilePath& native_io_root) {
  std::vector<url::Origin> result;
  // If the NativeIO directory wasn't created yet, there's no file to report.
  if (!base::PathExists(native_io_root))
    return result;

  base::FileEnumerator file_enumerator(native_io_root, /*recursive=*/false,
                                       base::FileEnumerator::DIRECTORIES);

  for (base::FilePath file_path = file_enumerator.Next(); !file_path.empty();
       file_path = file_enumerator.Next()) {
    // If the directory name has a non-ASCII character, `file_path` will be the
    // empty string. This indicates corruption as any origin creates an
    // ASCII-only directory name, so those directories are ignored.
    std::string directory_name = file_path.BaseName().MaybeAsASCII();
    if (directory_name == "")
      continue;
    url::Origin origin = storage::GetOriginFromIdentifier(directory_name);
    result.push_back(std::move(origin));
  }
  return result;
}

int64_t DoGetOriginUsage(const base::FilePath& origin_root) {
  // Returns 0 if `origin_root` does not exist.
  return base::ComputeDirectorySize(origin_root);
}

std::map<url::Origin, int64_t> DoGetOriginUsageMap(
    const base::FilePath& native_io_root) {
  std::map<url::Origin, int64_t> result;

  // If the NativeIO directory wasn't created yet, there's no file to report.
  if (!base::PathExists(native_io_root))
    return result;

  base::FileEnumerator file_enumerator(native_io_root, /*recursive=*/false,
                                       base::FileEnumerator::DIRECTORIES);

  for (base::FilePath file_path = file_enumerator.Next(); !file_path.empty();
       file_path = file_enumerator.Next()) {
    // If the directory name has a non-ASCII character, `file_path` will be the
    // empty string. This indicates corruption as any origin creates an
    // ASCII-only directory name, so those directories are ignored.
    std::string directory_name = file_path.BaseName().MaybeAsASCII();
    if (directory_name == "")
      continue;
    url::Origin origin = storage::GetOriginFromIdentifier(directory_name);
    int64_t usage = base::ComputeDirectorySize(file_path);
    auto inserted = result.insert(std::make_pair(origin, usage));
    DCHECK(inserted.second)
        << "Origins in NativeIO's directory should have a unique folder.";
  }
  return result;
}

constexpr base::FilePath::CharType kNativeIODirectoryName[] =
    FILE_PATH_LITERAL("NativeIO");
}  // namespace

NativeIOManager::NativeIOManager(
    const base::FilePath& profile_root,
#if defined(OS_MAC)
    bool allow_set_length_ipc,
#endif  // defined(OS_MAC)
    scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,
    scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy)
    : root_path_(GetNativeIORootPath(profile_root)),
#if defined(OS_MAC)
      allow_set_length_ipc_(allow_set_length_ipc),
#endif  // defined(OS_MAC)
      special_storage_policy_(std::move(special_storage_policy)),
      quota_manager_proxy_(std::move(quota_manager_proxy)),
      // Using a raw pointer is safe since NativeIOManager be owned by
      // NativeIOQuotaClient and is guaranteed to outlive it.
      quota_client_(this),
      quota_client_receiver_(&quota_client_) {
  if (quota_manager_proxy_) {
    // Quota client assumes all backends have registered.
    quota_manager_proxy_->RegisterClient(
        quota_client_receiver_.BindNewPipeAndPassRemote(),
        storage::QuotaClientType::kNativeIO,
        {blink::mojom::StorageType::kTemporary});
  }
}

NativeIOManager::~NativeIOManager() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}

void NativeIOManager::BindReceiver(
    const url::Origin& origin,
    mojo::PendingReceiver<blink::mojom::NativeIOHost> receiver,
    mojo::ReportBadMessageCallback bad_message_callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  auto it = hosts_.find(origin);
  if (it == hosts_.end()) {
    // This feature should only be exposed to potentially trustworthy origins
    // (https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy).
    // Notably this includes the https and chrome-extension schemes, among
    // others.
    if (!network::IsOriginPotentiallyTrustworthy(origin)) {
      std::move(bad_message_callback)
          .Run("Called NativeIO from an insecure context");
      return;
    }

    base::FilePath origin_root_path = RootPathForOrigin(origin);
    DCHECK(origin_root_path.empty() || root_path_.IsParent(origin_root_path))
        << "Per-origin data should be in a sub-directory of NativeIO/ for "
        << "non-incognito mode ";

    bool insert_succeeded;
    std::tie(it, insert_succeeded) = hosts_.emplace(
        origin,
        std::make_unique<NativeIOHost>(origin, std::move(origin_root_path),
#if defined(OS_MAC)
                                       allow_set_length_ipc_,
#endif  // defined(OS_MAC)
                                       this));
    DCHECK(insert_succeeded);
  }

  it->second->BindReceiver(std::move(receiver));
}

void NativeIOManager::OnHostReceiverDisconnect(NativeIOHost* host) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  MaybeDeleteHost(host);
}

void NativeIOManager::MaybeDeleteHost(NativeIOHost* host) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(host != nullptr);
  DCHECK(hosts_.count(host->origin()) > 0);
  DCHECK_EQ(hosts_[host->origin()].get(), host);

  if (!host->has_empty_receiver_set() || host->delete_all_data_in_progress())
    return;

  hosts_.erase(host->origin());
}

void NativeIOManager::OnDeleteOriginDataCompleted(
    storage::QuotaClient::DeleteOriginDataCallback callback,
    base::File::Error result,
    NativeIOHost* host) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  MaybeDeleteHost(host);
  blink::mojom::QuotaStatusCode quota_result =
      result == base::File::FILE_OK ? blink::mojom::QuotaStatusCode::kOk
                                    : blink::mojom::QuotaStatusCode::kUnknown;
  std::move(callback).Run(quota_result);
}

void NativeIOManager::DeleteOriginData(
    const url::Origin& origin,
    storage::QuotaClient::DeleteOriginDataCallback callback) {
  auto it = hosts_.find(origin);
  if (it == hosts_.end()) {
    // TODO(rstz): Consider turning these checks into DCHECKS when NativeIO is
    // no longer bundled with the Filesystem API during data removal.
    if (!network::IsOriginPotentiallyTrustworthy(origin)) {
      std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk);
      return;
    }
    base::FilePath origin_root_path = RootPathForOrigin(origin);
    if (origin_root_path.empty()) {
      // NativeIO is not supported for the origin, no data can be deleted.
      std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk);
      return;
    }

    DCHECK(root_path_.IsParent(origin_root_path))
        << "Per-origin data should be in a sub-directory of NativeIO/";

    bool insert_succeeded;
    // Create a NativeIOHost so that future API calls for the origin are queued
    // behind the data deletion. This should not meaningfully slow down the
    // removal process.
    std::tie(it, insert_succeeded) = hosts_.emplace(
        origin,
        std::make_unique<NativeIOHost>(origin, std::move(origin_root_path),
#if defined(OS_MAC)
                                       allow_set_length_ipc_,
#endif  // defined(OS_MAC)
                                       this));
    DCHECK(insert_succeeded);
  }

  // base::Unretained is safe here because this NativeIOManager owns the
  // NativeIOHost. So, the unretained NativeIOManager is guaranteed to outlive
  // the  NativeIOHost and the closure that it uses.
  it->second->DeleteAllData(
      base::BindOnce(&NativeIOManager::OnDeleteOriginDataCompleted,
                     base::Unretained(this), std::move(callback)));
}

void NativeIOManager::GetOriginsForType(
    blink::mojom::StorageType type,
    storage::QuotaClient::GetOriginsForTypeCallback callback) {
  if (type != blink::mojom::StorageType::kTemporary) {
    std::move(callback).Run({});
    return;
  }
  base::ThreadPool::PostTaskAndReplyWithResult(
      FROM_HERE,
      {
          // Needed for file I/O.
          base::MayBlock(),

          // Reasonable compromise, given that the sitedata UI depends on this
          // functionality.
          base::TaskPriority::USER_VISIBLE,

          // BLOCK_SHUTDOWN is definitely not appropriate. We might be able to
          // move to CONTINUE_ON_SHUTDOWN after very careful analysis.
          base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
      },
      base::BindOnce(&DoGetOrigins, root_path_),
      base::BindOnce(&NativeIOManager::DidGetOriginsForType,
                     weak_factory_.GetWeakPtr(), std::move(callback)));
}
void NativeIOManager::GetOriginsForHost(
    blink::mojom::StorageType type,
    const std::string& host,
    storage::QuotaClient::GetOriginsForHostCallback callback) {
  if (type != blink::mojom::StorageType::kTemporary) {
    std::move(callback).Run({});
    return;
  }

  base::ThreadPool::PostTaskAndReplyWithResult(
      FROM_HERE,
      {
          // Needed for file I/O.
          base::MayBlock(),

          // Reasonable compromise, given that the sitedata UI depends on this
          // functionality.
          base::TaskPriority::USER_VISIBLE,

          // BLOCK_SHUTDOWN is definitely not appropriate. We might be able to
          // move to CONTINUE_ON_SHUTDOWN after very careful analysis.
          base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
      },
      base::BindOnce(&DoGetOrigins, root_path_),
      base::BindOnce(&NativeIOManager::DidGetOriginsForHost,
                     weak_factory_.GetWeakPtr(), std::move(callback),
                     std::move(host)));
}

void NativeIOManager::GetOriginUsage(
    const url::Origin& origin,
    blink::mojom::StorageType type,
    storage::QuotaClient::GetOriginUsageCallback callback) {
  if (type != blink::mojom::StorageType::kTemporary) {
    std::move(callback).Run(0);
    return;
  }

  base::FilePath origin_root = RootPathForOrigin(origin);

  base::ThreadPool::PostTaskAndReplyWithResult(
      FROM_HERE,
      {
          // Needed for file I/O.
          base::MayBlock(),

          // Reasonable compromise, given that the sitedata UI depends on this
          // functionality.
          base::TaskPriority::USER_VISIBLE,

          // BLOCK_SHUTDOWN is definitely not appropriate. We might be able to
          // move to CONTINUE_ON_SHUTDOWN after very careful analysis.
          base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
      },
      base::BindOnce(&DoGetOriginUsage, origin_root),
      base::BindOnce(&NativeIOManager::DidGetOriginUsage,
                     weak_factory_.GetWeakPtr(), std::move(callback)));
}

void NativeIOManager::GetOriginUsageMap(
    base::OnceCallback<void(const std::map<url::Origin, int64_t>)> callback) {
  base::ThreadPool::PostTaskAndReplyWithResult(
      FROM_HERE,
      {
          // Needed for file I/O.
          base::MayBlock(),

          // Site data removal has a visible UI.
          base::TaskPriority::USER_VISIBLE,

          // BLOCK_SHUTDOWN is definitely not appropriate. We might be able to
          // move to CONTINUE_ON_SHUTDOWN after very careful analysis.
          base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
      },
      base::BindOnce(&DoGetOriginUsageMap, root_path_),
      base::BindOnce(&NativeIOManager::DidGetOriginUsageMap,
                     weak_factory_.GetWeakPtr(), std::move(callback)));
}

void NativeIOManager::DidGetOriginsForType(
    storage::QuotaClient::GetOriginsForTypeCallback callback,
    std::vector<url::Origin> origins) {
  std::move(callback).Run(origins);
}

void NativeIOManager::DidGetOriginsForHost(
    storage::QuotaClient::GetOriginsForTypeCallback callback,
    const std::string& host,
    std::vector<url::Origin> origins) {
  std::vector<url::Origin> out_origins;
  for (const url::Origin& origin : origins) {
    if (host == origin.host())
      out_origins.push_back(origin);
  }
  std::move(callback).Run(std::move(out_origins));
}

void NativeIOManager::DidGetOriginUsage(
    storage::QuotaClient::GetOriginUsageCallback callback,
    int64_t usage) {
  std::move(callback).Run(usage);
}

void NativeIOManager::DidGetOriginUsageMap(
    base::OnceCallback<void(const std::map<url::Origin, int64_t>)> callback,
    std::map<url::Origin, int64_t> usage_map) {
  std::move(callback).Run(usage_map);
}

base::FilePath NativeIOManager::RootPathForOrigin(const url::Origin& origin) {
  // TODO(pwnall): Implement in-memory files instead of bouncing in incognito.
  if (root_path_.empty())
    return root_path_;

  std::string origin_identifier = storage::GetIdentifierFromOrigin(origin);
  base::FilePath origin_path = root_path_.AppendASCII(origin_identifier);
  DCHECK(root_path_.IsParent(origin_path));
  return origin_path;
}

// static
base::FilePath NativeIOManager::GetNativeIORootPath(
    const base::FilePath& profile_root) {
  if (profile_root.empty())
    return base::FilePath();

  return profile_root.Append(kNativeIODirectoryName);
}

// static
blink::mojom::NativeIOErrorPtr NativeIOManager::FileErrorToNativeIOError(
    base::File::Error file_error,
    std::string message) {
  blink::mojom::NativeIOErrorType native_io_error_type =
      blink::native_io::FileErrorToNativeIOErrorType(file_error);
  std::string final_message =
      message.empty()
          ? blink::native_io::GetDefaultMessage(native_io_error_type)
          : message;
  return blink::mojom::NativeIOError::New(native_io_error_type, final_message);
}

}  // namespace content
