// 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.

#ifndef CONTENT_BROWSER_CODE_CACHE_GENERATED_CODE_CACHE_H_
#define CONTENT_BROWSER_CODE_CACHE_GENERATED_CODE_CACHE_H_

#include <queue>

#include "base/containers/queue.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "net/base/completion_callback.h"
#include "net/base/io_buffer.h"
#include "net/disk_cache/disk_cache.h"
#include "url/origin.h"

namespace content {

// Cache for storing generated code from the renderer on the disk. This cache
// uses |resource_url| + |origin_lock| as a key for storing the generated code.
// |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. This is used to enforce site isolation policy on cached code.
// 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.
//
// The key is generated by concatenating the serialized url and origin lock
// with a separator in between. The separator is non-valid URL characters, to
// prevent any attacks by crafting the URLs. |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.
//
// This uses a simple disk_cache backend. It just stores one data stream and
// stores response_time + generated code as one data blob.
//
// There exists one cache per storage partition and is owned by the storage
// partition. This cache is created, accessed and destroyed on the I/O
// thread.
class CONTENT_EXPORT GeneratedCodeCache {
 public:
  using ReadDataCallback =
      base::RepeatingCallback<void(const base::Time&,
                                   const std::vector<uint8_t>&)>;
  using GetBackendCallback = base::OnceCallback<void(disk_cache::Backend*)>;
  static const int kResponseTimeSizeInBytes = sizeof(int64_t);

  // Cache type. Used for collecting statistics for JS and Wasm in separate
  // buckets.
  enum CodeCacheType { kJavaScript, kWebAssembly };

  // Used for collecting statistics about cache behaviour.
  enum CacheEntryStatus {
    kHit,
    kMiss,
    kClear,
    kUpdate,
    kCreate,
    kError,
    kIncompleteEntry,
    kMaxValue = kIncompleteEntry
  };

  // Returns the resource URL from the key. The key has the format prefix +
  // resource URL + separator + requesting origin. This function extracts and
  // returns resource URL from the key.
  static std::string GetResourceURLFromKey(const std::string& key);

  // Creates a GeneratedCodeCache with the specified path and the maximum size.
  // If |max_size_bytes| is 0, then disk_cache picks a default size based on
  // some heuristics.
  GeneratedCodeCache(const base::FilePath& path,
                     int max_size_bytes,
                     CodeCacheType cache_type);

  ~GeneratedCodeCache();

  // Runs the callback with a raw pointer to the backend. If we could not create
  // the backend then it will return a null. This runs the callback
  // synchronously if the backend is already open or asynchronously on the
  // completion of a pending backend creation.
  void GetBackend(GetBackendCallback callback);

  // Writes data to the cache. If there is an entry corresponding to
  // <|resource_url|, |origin_lock|> this overwrites the existing data. If
  // there is no entry it creates a new one.
  void WriteData(const GURL& resource_url,
                 const GURL& origin_lock,
                 const base::Time& response_time,
                 const std::vector<uint8_t>& data);

  // Fetch entry corresponding to <resource_url, origin_lock> from the cache
  // and return it using the ReadDataCallback.
  void FetchEntry(const GURL& resource_url,
                  const GURL& origin_lock,
                  ReadDataCallback);

  // Delete the entry corresponding to <resource_url, origin_lock>
  void DeleteEntry(const GURL& resource_url, const GURL& origin_lock);

  // Should be only used for tests. Sets the last accessed timestamp of an
  // entry.
  void SetLastUsedTimeForTest(const GURL& resource_url,
                              const GURL& origin_lock,
                              base::Time time,
                              base::RepeatingCallback<void(void)> callback);

  const base::FilePath& path() const { return path_; }

 private:
  class PendingOperation;
  using ScopedBackendPtr = std::unique_ptr<disk_cache::Backend>;

  // State of the backend.
  enum BackendState { kInitializing, kInitialized, kFailed };

  // The operation requested.
  enum Operation { kFetch, kWrite, kDelete, kGetBackend };

  // Data streams corresponding to each entry.
  enum { kDataIndex = 1 };

  // Creates a simple_disk_cache backend.
  void CreateBackend();
  void DidCreateBackend(
      scoped_refptr<base::RefCountedData<ScopedBackendPtr>> backend_ptr,
      int rv);

  // The requests that are received while tha backend is being initialized
  // are recorded in pending operations list. This function issues all pending
  // operations.
  void IssuePendingOperations();

  // Write entry to cache
  void WriteDataImpl(const std::string& key,
                     scoped_refptr<net::IOBufferWithSize> buffer);
  void CompleteForWriteData(
      scoped_refptr<net::IOBufferWithSize> buffer,
      const std::string& key,
      scoped_refptr<base::RefCountedData<disk_cache::EntryWithOpened>>
          entry_struct,
      int rv);
  void WriteDataCompleted(const std::string& key, int rv);

  // Fetch entry from cache
  void FetchEntryImpl(const std::string& key, ReadDataCallback);
  void OpenCompleteForReadData(
      ReadDataCallback callback,
      const std::string& key,
      scoped_refptr<base::RefCountedData<disk_cache::Entry*>> entry,
      int rv);
  void ReadDataComplete(const std::string& key,
                        ReadDataCallback callback,
                        scoped_refptr<net::IOBufferWithSize> buffer,
                        int rv);

  // Delete entry from cache
  void DeleteEntryImpl(const std::string& key);

  // Issues the queued operation at the front of the queue for the given |key|.
  void IssueQueuedOperationForEntry(const std::string& key);
  // Enqueues into the list if there is an in-progress operation. Otherwise
  // creates an entry to indicate there is an active operation.
  bool EnqueueAsPendingOperation(const std::string& key,
                                 std::unique_ptr<PendingOperation> op);
  void IssueOperation(PendingOperation* op);

  void DoPendingGetBackend(GetBackendCallback callback);

  void OpenCompleteForSetLastUsedForTest(
      scoped_refptr<base::RefCountedData<disk_cache::Entry*>> entry,
      base::Time time,
      base::RepeatingCallback<void(void)> callback,
      int rv);

  void CollectStatistics(GeneratedCodeCache::CacheEntryStatus status);

  std::unique_ptr<disk_cache::Backend> backend_;
  BackendState backend_state_;

  std::vector<std::unique_ptr<PendingOperation>> pending_ops_;

  // Map from key to queue ops.
  std::map<std::string, base::queue<std::unique_ptr<PendingOperation>>>
      active_entries_map_;

  base::FilePath path_;
  int max_size_bytes_;
  CodeCacheType cache_type_;

  base::WeakPtrFactory<GeneratedCodeCache> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(GeneratedCodeCache);
};

}  // namespace content

#endif  // CONTENT_BROWSER_CODE_CACHE_GENERATED_CODE_CACHE_H_
