// Copyright 2018 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/code_cache/generated_code_cache.h"
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "content/public/common/url_constants.h"
#include "net/base/completion_callback.h"
#include "net/base/completion_once_callback.h"
#include "net/base/url_util.h"
#include "url/gurl.h"

namespace content {

namespace {
constexpr char kPrefix[] = "_key";
constexpr char kSeparator[] = " \n";

// We always expect to receive valid URLs that can be used as keys to the code
// cache. The relevant checks (for ex: resource_url is valid, origin_lock is
// not opque etc.,) must be done prior to requesting the code cache.
//
// This function doesn't enforce anything in the production code. It is here
// to make the assumptions explicit and to catch any errors when DCHECKs are
// enabled.
void CheckValidKeys(const GURL& resource_url, const GURL& origin_lock) {
  // If the resource url is invalid don't cache the code.
  DCHECK(resource_url.is_valid() && resource_url.SchemeIsHTTPOrHTTPS());

  // |origin_lock| should be either empty or should have Http/Https/chrome
  // schemes and it should not be a URL with opaque origin. Empty origin_locks
  // are allowed when the renderer is not locked to an origin.
  DCHECK(origin_lock.is_empty() ||
         ((origin_lock.SchemeIsHTTPOrHTTPS() ||
           origin_lock.SchemeIs(content::kChromeUIScheme)) &&
          !url::Origin::Create(origin_lock).opaque()));
}

// Generates the cache key for the given |resource_url| and the |origin_lock|.
//   |resource_url| is the url corresponding to the requested resource.
//   |origin_lock| is the origin that the renderer which requested this
//   resource is locked to.
// For example, if SitePerProcess is enabled and http://script.com/script1.js is
// requested by http://example.com, then http://script.com/script.js is the
// resource_url and http://example.com is the origin_lock.
//
// This returns the key by concatenating the serialized url and origin lock
// with a separator in between. |origin_lock| could be empty when renderer is
// not locked to an origin (ex: SitePerProcess is disabled) and it is safe to
// use only |resource_url| as the key in such cases.
std::string GetCacheKey(const GURL& resource_url, const GURL& origin_lock) {
  CheckValidKeys(resource_url, origin_lock);

  // Add a prefix _ so it can't be parsed as a valid URL.
  std::string key(kPrefix);
  // Remove reference, username and password sections of the URL.
  key.append(net::SimplifyUrlForRequest(resource_url).spec());
  // Add a separator between URL and origin to avoid any possibility of
  // attacks by crafting the URL. URLs do not contain any control ASCII
  // characters, and also space is encoded. So use ' \n' as a seperator.
  key.append(kSeparator);

  if (origin_lock.is_valid())
    key.append(net::SimplifyUrlForRequest(origin_lock).spec());
  return key;
}

}  // namespace

std::string GeneratedCodeCache::GetResourceURLFromKey(const std::string& key) {
  constexpr size_t kPrefixStringLen = base::size(kPrefix) - 1;
  // Only expect valid keys. All valid keys have a prefix and a separator.
  DCHECK_GE(key.length(), kPrefixStringLen);
  DCHECK_NE(key.find(kSeparator), std::string::npos);

  std::string resource_url =
      key.substr(kPrefixStringLen, key.find(kSeparator) - kPrefixStringLen);
  return resource_url;
}

void GeneratedCodeCache::CollectStatistics(
    GeneratedCodeCache::CacheEntryStatus status) {
  switch (cache_type_) {
    case GeneratedCodeCache::CodeCacheType::kJavaScript:
      UMA_HISTOGRAM_ENUMERATION("SiteIsolatedCodeCache.JS.Behaviour", status);
      break;
    case GeneratedCodeCache::CodeCacheType::kWebAssembly:
      UMA_HISTOGRAM_ENUMERATION("SiteIsolatedCodeCache.WASM.Behaviour", status);
      break;
  }
}

// Stores the information about a pending request while disk backend is
// being initialized.
class GeneratedCodeCache::PendingOperation {
 public:
  static std::unique_ptr<PendingOperation> CreateWritePendingOp(
      std::string key,
      scoped_refptr<net::IOBufferWithSize>);
  static std::unique_ptr<PendingOperation> CreateFetchPendingOp(
      std::string key,
      const ReadDataCallback&);
  static std::unique_ptr<PendingOperation> CreateDeletePendingOp(
      std::string key);
  static std::unique_ptr<PendingOperation> CreateGetBackendPendingOp(
      GetBackendCallback callback);

  ~PendingOperation();

  Operation operation() const { return op_; }
  const std::string& key() const { return key_; }
  const scoped_refptr<net::IOBufferWithSize> data() const { return data_; }
  ReadDataCallback ReleaseReadCallback() { return std::move(read_callback_); }
  GetBackendCallback ReleaseCallback() { return std::move(callback_); }

 private:
  PendingOperation(Operation op,
                   std::string key,
                   scoped_refptr<net::IOBufferWithSize>,
                   const ReadDataCallback&,
                   GetBackendCallback);

  const Operation op_;
  const std::string key_;
  const scoped_refptr<net::IOBufferWithSize> data_;
  ReadDataCallback read_callback_;
  GetBackendCallback callback_;
};

std::unique_ptr<GeneratedCodeCache::PendingOperation>
GeneratedCodeCache::PendingOperation::CreateWritePendingOp(
    std::string key,
    scoped_refptr<net::IOBufferWithSize> buffer) {
  return base::WrapUnique(
      new PendingOperation(Operation::kWrite, std::move(key), buffer,
                           ReadDataCallback(), GetBackendCallback()));
}

std::unique_ptr<GeneratedCodeCache::PendingOperation>
GeneratedCodeCache::PendingOperation::CreateFetchPendingOp(
    std::string key,
    const ReadDataCallback& read_callback) {
  return base::WrapUnique(new PendingOperation(
      Operation::kFetch, std::move(key), scoped_refptr<net::IOBufferWithSize>(),
      read_callback, GetBackendCallback()));
}

std::unique_ptr<GeneratedCodeCache::PendingOperation>
GeneratedCodeCache::PendingOperation::CreateDeletePendingOp(std::string key) {
  return base::WrapUnique(
      new PendingOperation(Operation::kDelete, std::move(key),
                           scoped_refptr<net::IOBufferWithSize>(),
                           ReadDataCallback(), GetBackendCallback()));
}

std::unique_ptr<GeneratedCodeCache::PendingOperation>
GeneratedCodeCache::PendingOperation::CreateGetBackendPendingOp(
    GetBackendCallback callback) {
  return base::WrapUnique(
      new PendingOperation(Operation::kGetBackend, std::string(),
                           scoped_refptr<net::IOBufferWithSize>(),
                           ReadDataCallback(), std::move(callback)));
}

GeneratedCodeCache::PendingOperation::PendingOperation(
    Operation op,
    std::string key,
    scoped_refptr<net::IOBufferWithSize> buffer,
    const ReadDataCallback& read_callback,
    GetBackendCallback callback)
    : op_(op),
      key_(std::move(key)),
      data_(buffer),
      read_callback_(read_callback),
      callback_(std::move(callback)) {}

GeneratedCodeCache::PendingOperation::~PendingOperation() = default;

GeneratedCodeCache::GeneratedCodeCache(const base::FilePath& path,
                                       int max_size_bytes,
                                       CodeCacheType cache_type)
    : backend_state_(kInitializing),
      path_(path),
      max_size_bytes_(max_size_bytes),
      cache_type_(cache_type),
      weak_ptr_factory_(this) {
  CreateBackend();
}

GeneratedCodeCache::~GeneratedCodeCache() = default;

void GeneratedCodeCache::GetBackend(GetBackendCallback callback) {
  switch (backend_state_) {
    case kFailed:
      std::move(callback).Run(nullptr);
      return;
    case kInitialized:
      std::move(callback).Run(backend_.get());
      return;
    case kInitializing:
      pending_ops_.push_back(
          GeneratedCodeCache::PendingOperation::CreateGetBackendPendingOp(
              std::move(callback)));
      return;
  }
}

void GeneratedCodeCache::WriteData(const GURL& url,
                                   const GURL& origin_lock,
                                   const base::Time& response_time,
                                   const std::vector<uint8_t>& data) {
  // Silently ignore the requests.
  if (backend_state_ == kFailed) {
    CollectStatistics(CacheEntryStatus::kError);
    return;
  }

  // Append the response time to the metadata. Code caches store
  // response_time + generated code as a single entry.
  scoped_refptr<net::IOBufferWithSize> buffer =
      base::MakeRefCounted<net::IOBufferWithSize>(data.size() +
                                                  kResponseTimeSizeInBytes);
  int64_t serialized_time =
      response_time.ToDeltaSinceWindowsEpoch().InMicroseconds();
  memcpy(buffer->data(), &serialized_time, kResponseTimeSizeInBytes);
  if (!data.empty())
    memcpy(buffer->data() + kResponseTimeSizeInBytes, &data.front(),
           data.size());

  std::string key = GetCacheKey(url, origin_lock);
  // If there is an in progress operation corresponding to this key. Enqueue it
  // so we can issue once the in-progress operation finishes.
  if (EnqueueAsPendingOperation(
          key, GeneratedCodeCache::PendingOperation::CreateWritePendingOp(
                   key, buffer))) {
    return;
  }

  if (backend_state_ != kInitialized) {
    // Insert it into the list of pending operations while the backend is
    // still being opened.
    pending_ops_.push_back(
        GeneratedCodeCache::PendingOperation::CreateWritePendingOp(
            std::move(key), buffer));
    return;
  }

  WriteDataImpl(key, buffer);
}

void GeneratedCodeCache::FetchEntry(const GURL& url,
                                    const GURL& origin_lock,
                                    ReadDataCallback read_data_callback) {
  if (backend_state_ == kFailed) {
    CollectStatistics(CacheEntryStatus::kError);
    // Silently ignore the requests.
    std::move(read_data_callback).Run(base::Time(), std::vector<uint8_t>());
    return;
  }

  std::string key = GetCacheKey(url, origin_lock);
  // If there is an in progress operation corresponding to this key. Enqueue it
  // so we can issue once the in-progress operation finishes.
  if (EnqueueAsPendingOperation(
          key, GeneratedCodeCache::PendingOperation::CreateFetchPendingOp(
                   key, read_data_callback))) {
    return;
  }

  if (backend_state_ != kInitialized) {
    // Insert it into the list of pending operations while the backend is
    // still being opened.
    pending_ops_.push_back(
        GeneratedCodeCache::PendingOperation::CreateFetchPendingOp(
            std::move(key), read_data_callback));
    return;
  }

  FetchEntryImpl(key, read_data_callback);
}

void GeneratedCodeCache::DeleteEntry(const GURL& url, const GURL& origin_lock) {
  // Silently ignore the requests.
  if (backend_state_ == kFailed) {
    CollectStatistics(CacheEntryStatus::kError);
    return;
  }

  std::string key = GetCacheKey(url, origin_lock);
  if (backend_state_ != kInitialized) {
    // Insert it into the list of pending operations while the backend is
    // still being opened.
    pending_ops_.push_back(
        GeneratedCodeCache::PendingOperation::CreateDeletePendingOp(
            std::move(key)));
    return;
  }

  DeleteEntryImpl(key);
}

void GeneratedCodeCache::CreateBackend() {
  // Create a new Backend pointer that cleans itself if the GeneratedCodeCache
  // instance is not live when the CreateCacheBackend finishes.
  scoped_refptr<base::RefCountedData<ScopedBackendPtr>> shared_backend_ptr =
      new base::RefCountedData<ScopedBackendPtr>();

  net::CompletionOnceCallback create_backend_complete =
      base::BindOnce(&GeneratedCodeCache::DidCreateBackend,
                     weak_ptr_factory_.GetWeakPtr(), shared_backend_ptr);

  // If the initialization of the existing cache fails, this call would delete
  // all the contents and recreates a new one.
  int rv = disk_cache::CreateCacheBackend(
      net::GENERATED_CODE_CACHE, net::CACHE_BACKEND_SIMPLE, path_,
      max_size_bytes_, true, nullptr, &shared_backend_ptr->data,
      std::move(create_backend_complete));
  if (rv != net::ERR_IO_PENDING) {
    DidCreateBackend(shared_backend_ptr, rv);
  }
}

void GeneratedCodeCache::DidCreateBackend(
    scoped_refptr<base::RefCountedData<ScopedBackendPtr>> backend_ptr,
    int rv) {
  if (rv != net::OK) {
    backend_state_ = kFailed;
    // Process pending operations to process any required callbacks.
    IssuePendingOperations();
    return;
  }

  backend_ = std::move(backend_ptr->data);
  backend_state_ = kInitialized;
  IssuePendingOperations();
}

void GeneratedCodeCache::IssuePendingOperations() {
  DCHECK_EQ(backend_state_, kInitialized);
  // Issue all the pending operations that were received when creating
  // the backend.
  for (auto const& op : pending_ops_) {
    IssueOperation(op.get());
  }
  pending_ops_.clear();
}

void GeneratedCodeCache::IssueOperation(PendingOperation* op) {
  switch (op->operation()) {
    case kFetch:
      FetchEntryImpl(op->key(), op->ReleaseReadCallback());
      break;
    case kWrite:
      WriteDataImpl(op->key(), op->data());
      break;
    case kDelete:
      DeleteEntryImpl(op->key());
      break;
    case kGetBackend:
      DoPendingGetBackend(op->ReleaseCallback());
      break;
  }
}

void GeneratedCodeCache::WriteDataImpl(
    const std::string& key,
    scoped_refptr<net::IOBufferWithSize> buffer) {
  if (backend_state_ != kInitialized) {
    IssueQueuedOperationForEntry(key);
    return;
  }

  scoped_refptr<base::RefCountedData<disk_cache::EntryWithOpened>>
      entry_struct = new base::RefCountedData<disk_cache::EntryWithOpened>();
  net::CompletionOnceCallback callback =
      base::BindOnce(&GeneratedCodeCache::CompleteForWriteData,
                     weak_ptr_factory_.GetWeakPtr(), buffer, key, entry_struct);

  int result = backend_->OpenOrCreateEntry(key, net::LOW, &entry_struct->data,
                                           std::move(callback));
  if (result != net::ERR_IO_PENDING) {
    CompleteForWriteData(buffer, key, entry_struct, result);
  }
}

void GeneratedCodeCache::CompleteForWriteData(
    scoped_refptr<net::IOBufferWithSize> buffer,
    const std::string& key,
    scoped_refptr<base::RefCountedData<disk_cache::EntryWithOpened>>
        entry_struct,
    int rv) {
  if (rv != net::OK) {
    CollectStatistics(CacheEntryStatus::kError);
    IssueQueuedOperationForEntry(key);
    return;
  }

  DCHECK(entry_struct->data.entry);
  int result = net::ERR_FAILED;
  {
    disk_cache::ScopedEntryPtr disk_entry(entry_struct->data.entry);

    if (entry_struct->data.opened) {
      CollectStatistics(CacheEntryStatus::kUpdate);
    } else {
      CollectStatistics(CacheEntryStatus::kCreate);
    }
    // This call will truncate the data. This is safe to do since we read the
    // entire data at the same time currently. If we want to read in parts we
    // have to doom the entry first.
    result = disk_entry->WriteData(
        kDataIndex, 0, buffer.get(), buffer->size(),
        base::BindOnce(&GeneratedCodeCache::WriteDataCompleted,
                       weak_ptr_factory_.GetWeakPtr(), key),
        true);
  }
  if (result != net::ERR_IO_PENDING) {
    WriteDataCompleted(key, result);
  }
}

void GeneratedCodeCache::WriteDataCompleted(const std::string& key, int rv) {
  IssueQueuedOperationForEntry(key);
}

void GeneratedCodeCache::FetchEntryImpl(const std::string& key,
                                        ReadDataCallback read_data_callback) {
  if (backend_state_ != kInitialized) {
    std::move(read_data_callback).Run(base::Time(), std::vector<uint8_t>());
    IssueQueuedOperationForEntry(key);
    return;
  }

  scoped_refptr<base::RefCountedData<disk_cache::Entry*>> entry_ptr =
      new base::RefCountedData<disk_cache::Entry*>();

  net::CompletionOnceCallback callback = base::BindOnce(
      &GeneratedCodeCache::OpenCompleteForReadData,
      weak_ptr_factory_.GetWeakPtr(), read_data_callback, key, entry_ptr);

  // This is a part of loading cycle and hence should run with a high priority.
  int result = backend_->OpenEntry(key, net::HIGHEST, &entry_ptr->data,
                                   std::move(callback));
  if (result != net::ERR_IO_PENDING) {
    OpenCompleteForReadData(read_data_callback, key, entry_ptr, result);
  }
}

void GeneratedCodeCache::OpenCompleteForReadData(
    ReadDataCallback read_data_callback,
    const std::string& key,
    scoped_refptr<base::RefCountedData<disk_cache::Entry*>> entry,
    int rv) {
  if (rv != net::OK) {
    CollectStatistics(CacheEntryStatus::kMiss);
    std::move(read_data_callback).Run(base::Time(), std::vector<uint8_t>());
    IssueQueuedOperationForEntry(key);
    return;
  }

  // There should be a valid entry if the open was successful.
  DCHECK(entry->data);
  int result = net::ERR_FAILED;
  scoped_refptr<net::IOBufferWithSize> buffer;
  {
    disk_cache::ScopedEntryPtr disk_entry(entry->data);
    int size = disk_entry->GetDataSize(kDataIndex);
    buffer = base::MakeRefCounted<net::IOBufferWithSize>(size);
    net::CompletionOnceCallback callback = base::BindOnce(
        &GeneratedCodeCache::ReadDataComplete, weak_ptr_factory_.GetWeakPtr(),
        key, read_data_callback, buffer);
    result = disk_entry->ReadData(kDataIndex, 0, buffer.get(), size,
                                  std::move(callback));
  }
  if (result != net::ERR_IO_PENDING) {
    ReadDataComplete(key, read_data_callback, buffer, result);
  }
}

void GeneratedCodeCache::ReadDataComplete(
    const std::string& key,
    ReadDataCallback callback,
    scoped_refptr<net::IOBufferWithSize> buffer,
    int rv) {
  if (rv != buffer->size()) {
    CollectStatistics(CacheEntryStatus::kMiss);
    std::move(callback).Run(base::Time(), std::vector<uint8_t>());
  } else {
    // DiskCache ensures that the operations that are queued for an entry
    // go in order. Hence, we would either read an empty data or read the full
    // data.
    CollectStatistics(CacheEntryStatus::kHit);
    DCHECK_GE(buffer->size(), kResponseTimeSizeInBytes);
    int64_t raw_response_time = *(reinterpret_cast<int64_t*>(buffer->data()));
    base::Time response_time = base::Time::FromDeltaSinceWindowsEpoch(
        base::TimeDelta::FromMicroseconds(raw_response_time));
    std::vector<uint8_t> data;
    if (buffer->size() > kResponseTimeSizeInBytes) {
      data = std::vector<uint8_t>(buffer->data() + kResponseTimeSizeInBytes,
                                  buffer->data() + buffer->size());
    }
    std::move(callback).Run(response_time, data);
  }
  IssueQueuedOperationForEntry(key);
}

void GeneratedCodeCache::DeleteEntryImpl(const std::string& key) {
  if (backend_state_ != kInitialized)
    return;

  CollectStatistics(CacheEntryStatus::kClear);
  backend_->DoomEntry(key, net::LOWEST, net::CompletionOnceCallback());
}

void GeneratedCodeCache::IssueQueuedOperationForEntry(const std::string& key) {
  auto it = active_entries_map_.find(key);
  DCHECK(it != active_entries_map_.end());

  // If no more queued entries then remove the entry to indicate that there are
  // no in-progress operations for this key.
  if (it->second.empty()) {
    active_entries_map_.erase(it);
    return;
  }

  std::unique_ptr<PendingOperation> op = std::move(it->second.front());
  // Pop it before issuing the operation. Still retain the queue even if it is
  // empty to indicate that there is a in-progress operation.
  it->second.pop();
  IssueOperation(op.get());
}

bool GeneratedCodeCache::EnqueueAsPendingOperation(
    const std::string& key,
    std::unique_ptr<PendingOperation> op) {
  auto it = active_entries_map_.find(key);
  if (it != active_entries_map_.end()) {
    it->second.emplace(std::move(op));
    return true;
  }

  // Create a entry to indicate there is a in-progress operation for this key.
  active_entries_map_[key] = base::queue<std::unique_ptr<PendingOperation>>();
  return false;
}

void GeneratedCodeCache::DoPendingGetBackend(GetBackendCallback user_callback) {
  if (backend_state_ == kInitialized) {
    std::move(user_callback).Run(backend_.get());
    return;
  }

  DCHECK_EQ(backend_state_, kFailed);
  std::move(user_callback).Run(nullptr);
  return;
}

void GeneratedCodeCache::SetLastUsedTimeForTest(
    const GURL& resource_url,
    const GURL& origin_lock,
    base::Time time,
    base::RepeatingCallback<void(void)> user_callback) {
  // This is used only for tests. So reasonable to assume that backend is
  // initialized here. All other operations handle the case when backend was not
  // yet opened.
  DCHECK_EQ(backend_state_, kInitialized);

  scoped_refptr<base::RefCountedData<disk_cache::Entry*>> entry_ptr =
      new base::RefCountedData<disk_cache::Entry*>();

  net::CompletionOnceCallback callback = base::BindOnce(
      &GeneratedCodeCache::OpenCompleteForSetLastUsedForTest,
      weak_ptr_factory_.GetWeakPtr(), entry_ptr, time, user_callback);

  std::string key = GetCacheKey(resource_url, origin_lock);
  int result = backend_->OpenEntry(key, net::LOWEST, &entry_ptr->data,
                                   std::move(callback));
  if (result != net::ERR_IO_PENDING) {
    OpenCompleteForSetLastUsedForTest(entry_ptr, time, user_callback, result);
  }
}

void GeneratedCodeCache::OpenCompleteForSetLastUsedForTest(
    scoped_refptr<base::RefCountedData<disk_cache::Entry*>> entry,
    base::Time time,
    base::RepeatingCallback<void(void)> callback,
    int rv) {
  DCHECK_EQ(rv, net::OK);
  DCHECK(entry->data);
  {
    disk_cache::ScopedEntryPtr disk_entry(entry->data);
    disk_entry->SetLastUsedTimeForTest(time);
  }
  std::move(callback).Run();
}

}  // namespace content
