// 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 "content/browser/appcache/appcache_disk_cache.h"

#include <limits>
#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback_helpers.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "net/base/cache_type.h"
#include "net/base/completion_repeating_callback.h"
#include "net/base/net_errors.h"

namespace content {

// A callback shim that provides storage for the 'backend_ptr' value
// and will delete a resulting ptr if completion occurs after its
// been canceled.
class AppCacheDiskCache::CreateBackendCallbackShim
    : public base::RefCounted<CreateBackendCallbackShim> {
 public:
  explicit CreateBackendCallbackShim(AppCacheDiskCache* object)
      : appcache_diskcache_(object) {
  }

  void Cancel() { appcache_diskcache_ = nullptr; }

  void Callback(int return_value) {
    if (appcache_diskcache_)
      appcache_diskcache_->OnCreateBackendComplete(return_value);
  }

  std::unique_ptr<disk_cache::Backend> backend_ptr_;  // Accessed directly.

 private:
  friend class base::RefCounted<CreateBackendCallbackShim>;

  ~CreateBackendCallbackShim() {
  }

  AppCacheDiskCache* appcache_diskcache_;  // Unowned pointer.
};

AppCacheDiskCacheEntry::AppCacheDiskCacheEntry(
    disk_cache::Entry* disk_cache_entry,
    AppCacheDiskCache* cache)
    : disk_cache_entry_(disk_cache_entry), cache_(cache) {
  DCHECK(disk_cache_entry);
  DCHECK(cache);
  cache_->AddOpenEntry(this);
}

AppCacheDiskCacheEntry::~AppCacheDiskCacheEntry() {
  if (cache_)
    cache_->RemoveOpenEntry(this);
}

int AppCacheDiskCacheEntry::Read(int index,
                                 int64_t offset,
                                 net::IOBuffer* buf,
                                 int buf_len,
                                 net::CompletionOnceCallback callback) {
  if (offset < 0 || offset > std::numeric_limits<int32_t>::max())
    return net::ERR_INVALID_ARGUMENT;
  if (!disk_cache_entry_)
    return net::ERR_ABORTED;
  return disk_cache_entry_->ReadData(index, static_cast<int>(offset), buf,
                                     buf_len, std::move(callback));
}

int AppCacheDiskCacheEntry::Write(int index,
                                  int64_t offset,
                                  net::IOBuffer* buf,
                                  int buf_len,
                                  net::CompletionOnceCallback callback) {
  if (offset < 0 || offset > std::numeric_limits<int32_t>::max())
    return net::ERR_INVALID_ARGUMENT;
  if (!disk_cache_entry_)
    return net::ERR_ABORTED;
  const bool kTruncate = true;
  return disk_cache_entry_->WriteData(index, static_cast<int>(offset), buf,
                                      buf_len, std::move(callback), kTruncate);
}

int64_t AppCacheDiskCacheEntry::GetSize(int index) {
  return disk_cache_entry_ ? disk_cache_entry_->GetDataSize(index) : 0L;
}

void AppCacheDiskCacheEntry::Close() {
  if (disk_cache_entry_)
    disk_cache_entry_->Close();
  delete this;
}

void AppCacheDiskCacheEntry::Abandon() {
  cache_ = nullptr;
  disk_cache_entry_->Close();
  disk_cache_entry_ = nullptr;
}

// Separate object to hold state for each Create, Delete, or Doom call
// while the call is in-flight and to produce an EntryImpl upon completion.
class AppCacheDiskCache::ActiveCall
    : public base::RefCounted<AppCacheDiskCache::ActiveCall> {
 public:
  static net::Error CreateEntry(const base::WeakPtr<AppCacheDiskCache>& owner,
                                int64_t key,
                                AppCacheDiskCacheEntry** entry,
                                net::CompletionOnceCallback callback) {
    scoped_refptr<ActiveCall> active_call(
        new ActiveCall(owner, entry, std::move(callback)));
    net::Error return_value = owner->disk_cache()->CreateEntry(
        base::NumberToString(key), net::HIGHEST, &active_call->entry_ptr_,
        base::BindOnce(&ActiveCall::OnAsyncCompletion, active_call));
    return active_call->HandleImmediateReturnValue(return_value);
  }

  static net::Error OpenEntry(const base::WeakPtr<AppCacheDiskCache>& owner,
                              int64_t key,
                              AppCacheDiskCacheEntry** entry,
                              net::CompletionOnceCallback callback) {
    scoped_refptr<ActiveCall> active_call(
        new ActiveCall(owner, entry, std::move(callback)));
    net::Error return_value = owner->disk_cache()->OpenEntry(
        base::NumberToString(key), net::HIGHEST, &active_call->entry_ptr_,
        base::BindOnce(&ActiveCall::OnAsyncCompletion, active_call));
    return active_call->HandleImmediateReturnValue(return_value);
  }

  static net::Error DoomEntry(const base::WeakPtr<AppCacheDiskCache>& owner,
                              int64_t key,
                              net::CompletionOnceCallback callback) {
    scoped_refptr<ActiveCall> active_call(
        new ActiveCall(owner, nullptr, std::move(callback)));
    net::Error return_value = owner->disk_cache()->DoomEntry(
        base::NumberToString(key), net::HIGHEST,
        base::BindOnce(&ActiveCall::OnAsyncCompletion, active_call));
    return active_call->HandleImmediateReturnValue(return_value);
  }

 private:
  friend class base::RefCounted<AppCacheDiskCache::ActiveCall>;

  ActiveCall(const base::WeakPtr<AppCacheDiskCache>& owner,
             AppCacheDiskCacheEntry** entry,
             net::CompletionOnceCallback callback)
      : owner_(owner),
        entry_(entry),
        callback_(std::move(callback)),
        entry_ptr_(nullptr) {
    DCHECK(owner_);
  }

  ~ActiveCall() {}

  net::Error HandleImmediateReturnValue(net::Error rv) {
    if (rv == net::ERR_IO_PENDING) {
      // OnAsyncCompletion will be called later.
      return rv;
    }

    if (rv == net::OK && entry_) {
      DCHECK(entry_ptr_);
      *entry_ = new AppCacheDiskCacheEntry(entry_ptr_, owner_.get());
    }
    return rv;
  }

  void OnAsyncCompletion(int rv) {
    if (rv == net::OK && entry_) {
      DCHECK(entry_ptr_);
      if (owner_) {
        *entry_ = new AppCacheDiskCacheEntry(entry_ptr_, owner_.get());
      } else {
        entry_ptr_->Close();
        rv = net::ERR_ABORTED;
      }
    }
    std::move(callback_).Run(rv);
  }

  base::WeakPtr<AppCacheDiskCache> owner_;
  AppCacheDiskCacheEntry** entry_;
  net::CompletionOnceCallback callback_;
  disk_cache::Entry* entry_ptr_;
};

AppCacheDiskCache::AppCacheDiskCache()
#if defined(APPCACHE_USE_SIMPLE_CACHE)
    : AppCacheDiskCache("DiskCache.AppCache", true)
#else
    : AppCacheDiskCache("DiskCache.AppCache", false)
#endif
{
}

AppCacheDiskCache::~AppCacheDiskCache() {
  Disable();
}

net::Error AppCacheDiskCache::InitWithDiskBackend(
    const base::FilePath& disk_cache_directory,
    int disk_cache_size,
    bool force,
    base::OnceClosure post_cleanup_callback,
    net::CompletionOnceCallback callback) {
  return Init(net::APP_CACHE, disk_cache_directory, disk_cache_size, force,
              std::move(post_cleanup_callback), std::move(callback));
}

net::Error AppCacheDiskCache::InitWithMemBackend(
    int mem_cache_size,
    net::CompletionOnceCallback callback) {
  return Init(net::MEMORY_CACHE, base::FilePath(), mem_cache_size, false,
              base::OnceClosure(), std::move(callback));
}

void AppCacheDiskCache::Disable() {
  if (is_disabled_)
    return;

  is_disabled_ = true;

  if (create_backend_callback_.get()) {
    create_backend_callback_->Cancel();
    create_backend_callback_ = nullptr;
    OnCreateBackendComplete(net::ERR_ABORTED);
  }

  // We need to close open file handles in order to reinitalize the
  // appcache system on the fly. File handles held in both entries and in
  // the main disk_cache::Backend class need to be released.
  for (AppCacheDiskCacheEntry* entry : open_entries_) {
    entry->Abandon();
  }
  open_entries_.clear();
  disk_cache_.reset();
}

net::Error AppCacheDiskCache::CreateEntry(
    int64_t key,
    AppCacheDiskCacheEntry** entry,
    net::CompletionOnceCallback callback) {
  DCHECK(entry);
  DCHECK(!callback.is_null());
  if (is_disabled_)
    return net::ERR_ABORTED;

  if (is_initializing_or_waiting_to_initialize()) {
    pending_calls_.push_back(
        PendingCall(CREATE, key, entry, std::move(callback)));
    return net::ERR_IO_PENDING;
  }

  if (!disk_cache_)
    return net::ERR_FAILED;

  return ActiveCall::CreateEntry(weak_factory_.GetWeakPtr(), key, entry,
                                 std::move(callback));
}

net::Error AppCacheDiskCache::OpenEntry(int64_t key,
                                        AppCacheDiskCacheEntry** entry,
                                        net::CompletionOnceCallback callback) {
  DCHECK(entry);
  DCHECK(!callback.is_null());
  if (is_disabled_)
    return net::ERR_ABORTED;

  if (is_initializing_or_waiting_to_initialize()) {
    pending_calls_.push_back(
        PendingCall(OPEN, key, entry, std::move(callback)));
    return net::ERR_IO_PENDING;
  }

  if (!disk_cache_)
    return net::ERR_FAILED;

  return ActiveCall::OpenEntry(weak_factory_.GetWeakPtr(), key, entry,
                               std::move(callback));
}

net::Error AppCacheDiskCache::DoomEntry(int64_t key,
                                        net::CompletionOnceCallback callback) {
  DCHECK(!callback.is_null());
  if (is_disabled_)
    return net::ERR_ABORTED;

  if (is_initializing_or_waiting_to_initialize()) {
    pending_calls_.push_back(
        PendingCall(DOOM, key, nullptr, std::move(callback)));
    return net::ERR_IO_PENDING;
  }

  if (!disk_cache_)
    return net::ERR_FAILED;

  return ActiveCall::DoomEntry(weak_factory_.GetWeakPtr(), key,
                               std::move(callback));
}

base::WeakPtr<AppCacheDiskCache> AppCacheDiskCache::GetWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

AppCacheDiskCache::AppCacheDiskCache(const char* uma_name,
                                     bool use_simple_cache)
    : use_simple_cache_(use_simple_cache),
      is_disabled_(false),
      is_waiting_to_initialize_(false),
      uma_name_(uma_name),
      weak_factory_(this) {}

AppCacheDiskCache::PendingCall::PendingCall()
    : call_type(CREATE), key(0), entry(nullptr) {}

AppCacheDiskCache::PendingCall::PendingCall(
    PendingCallType call_type,
    int64_t key,
    AppCacheDiskCacheEntry** entry,
    net::CompletionOnceCallback callback)
    : call_type(call_type),
      key(key),
      entry(entry),
      callback(std::move(callback)) {}

AppCacheDiskCache::PendingCall::PendingCall(PendingCall&& other) = default;

AppCacheDiskCache::PendingCall::~PendingCall() = default;

net::Error AppCacheDiskCache::Init(net::CacheType cache_type,
                                   const base::FilePath& cache_directory,
                                   int cache_size,
                                   bool force,
                                   base::OnceClosure post_cleanup_callback,
                                   net::CompletionOnceCallback callback) {
  DCHECK(!is_initializing_or_waiting_to_initialize() && !disk_cache_.get());
  is_disabled_ = false;
  create_backend_callback_ = new CreateBackendCallbackShim(this);

  net::Error return_value = disk_cache::CreateCacheBackend(
      cache_type,
      use_simple_cache_ ? net::CACHE_BACKEND_SIMPLE
                        : net::CACHE_BACKEND_DEFAULT,
      cache_directory, cache_size, force, nullptr,
      &(create_backend_callback_->backend_ptr_),
      std::move(post_cleanup_callback),
      base::BindOnce(&CreateBackendCallbackShim::Callback,
                     create_backend_callback_));
  if (return_value == net::ERR_IO_PENDING)
    init_callback_ = std::move(callback);
  else
    OnCreateBackendComplete(return_value);
  return return_value;
}

void AppCacheDiskCache::OnCreateBackendComplete(int return_value) {
  if (return_value == net::OK) {
    disk_cache_ = std::move(create_backend_callback_->backend_ptr_);
  }
  create_backend_callback_ = nullptr;

  // Invoke our clients callback function.
  if (!init_callback_.is_null()) {
    std::move(init_callback_).Run(return_value);
  }

  // Service pending calls that were queued up while we were initializing.
  for (auto& call : pending_calls_) {
    // This is safe, because the callback will only be called once.
    net::CompletionRepeatingCallback copyable_callback =
        base::AdaptCallbackForRepeating(std::move(call.callback));
    return_value = net::ERR_FAILED;
    switch (call.call_type) {
      case CREATE:
        return_value = CreateEntry(call.key, call.entry, copyable_callback);
        break;
      case OPEN:
        return_value = OpenEntry(call.key, call.entry, copyable_callback);
        break;
      case DOOM:
        return_value = DoomEntry(call.key, copyable_callback);
        break;
    }
    if (return_value != net::ERR_IO_PENDING)
      copyable_callback.Run(return_value);
  }
  pending_calls_.clear();
}

}  // namespace content
