// 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 <map>
#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 "mojo/public/cpp/base/big_buffer.h"
#include "net/base/io_buffer.h"
#include "net/base/network_isolation_key.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::OnceCallback<void(const base::Time&, mojo_base::BigBuffer data)>;
  using GetBackendCallback = base::OnceCallback<void(disk_cache::Backend*)>;

  // Cache type. Used for collecting statistics for JS and Wasm in separate
  // buckets.
  enum CodeCacheType {
    // JavaScript from http(s) pages.
    kJavaScript,

    // WebAssembly from http(s) pages. This cache allows more total size and
    // more size per item than the JavaScript cache, since some
    // WebAssembly programs are very large.
    kWebAssembly,

    // JavaScript from chrome and chrome-untrusted pages. The resource URLs are
    // limited to only those fetched via chrome and chrome-untrusted schemes.
    // The cache size is limited to disk_cache::kMaxWebUICodeCacheSize.
    // Deduplication of very large items is disabled in this cache.
    kWebUIJavaScript,
  };

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

  // 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, or the empty string if key is invalid.
  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 WriteEntry(const GURL& resource_url,
                  const GURL& origin_lock,
                  const net::NetworkIsolationKey& nik,
                  const base::Time& response_time,
                  mojo_base::BigBuffer 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,
                  const net::NetworkIsolationKey& nik,
                  ReadDataCallback);

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

  // Should be only used for tests. Sets the last accessed timestamp of an
  // entry.
  void SetLastUsedTimeForTest(const GURL& resource_url,
                              const GURL& origin_lock,
                              const net::NetworkIsolationKey& nik,
                              base::Time time,
                              base::OnceClosure 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,
    kFetchWithSHAKey,
    kWrite,
    kWriteWithSHAKey,
    kDelete,
    kGetBackend
  };

  // Data streams corresponding to each entry.
  enum { kSmallDataStream = 0, kLargeDataStream = 1 };

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

  // Adds operation to the appropriate queue.
  void EnqueueOperation(std::unique_ptr<PendingOperation> op);

  // Issues ops that were received while the backend was being initialized.
  void IssuePendingOperations();
  void IssueOperation(PendingOperation* op);

  // Writes entry to cache.
  void WriteEntryImpl(PendingOperation* op);
  void OpenCompleteForWrite(PendingOperation* op,
                            disk_cache::EntryResult result);
  void WriteSmallBufferComplete(PendingOperation* op, int rv);
  void WriteLargeBufferComplete(PendingOperation* op, int rv);
  void WriteComplete(PendingOperation* op);

  // Fetches entry from cache.
  void FetchEntryImpl(PendingOperation* op);
  void OpenCompleteForRead(PendingOperation* op,
                           disk_cache::EntryResult result);
  void ReadSmallBufferComplete(PendingOperation* op, int rv);
  void ReadLargeBufferComplete(PendingOperation* op, int rv);
  void ReadComplete(PendingOperation* op);

  // Deletes entry from cache.
  void DeleteEntryImpl(PendingOperation* op);

  void DoomEntry(PendingOperation* op);

  // Issues the next operation on the queue for |key|.
  void IssueNextOperation(const std::string& key);
  // Removes |op| and issues the next operation on its queue.
  void CloseOperationAndIssueNext(PendingOperation* op);

  // Enqueues the operation issues it if there are no pending operations for
  // its key.
  void EnqueueOperationAndIssueIfNext(std::unique_ptr<PendingOperation> op);
  // Dequeues the operation and transfers ownership to caller.
  std::unique_ptr<PendingOperation> DequeueOperation(PendingOperation* op);

  void DoPendingGetBackend(PendingOperation* op);

  void OpenCompleteForSetLastUsedForTest(base::Time time,
                                         base::OnceClosure callback,
                                         disk_cache::EntryResult result);

  void CollectStatistics(GeneratedCodeCache::CacheEntryStatus status);

  // Whether very large cache entries are deduplicated in this cache.
  // Deduplication is disabled in the WebUI code cache, as an additional defense
  // against privilege escalation in case there is a bug in the deduplication
  // logic.
  bool IsDeduplicationEnabled() const;

  bool ShouldDeduplicateEntry(uint32_t data_size) const;

  // Checks that the header data in the small buffer is valid. We may read cache
  // entries that were written by a previous version of Chrome which uses
  // obsolete formats. These reads should fail and be doomed as soon as
  // possible.
  bool IsValidHeader(scoped_refptr<net::IOBufferWithSize> small_buffer) const;

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

  // Queue for operations received while initializing the backend.
  using PendingOperationQueue = base::queue<std::unique_ptr<PendingOperation>>;
  PendingOperationQueue pending_ops_;

  // Map from key to queue of pending operations.
  std::map<std::string, PendingOperationQueue> active_entries_map_;

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

  base::WeakPtrFactory<GeneratedCodeCache> weak_ptr_factory_{this};

  DISALLOW_COPY_AND_ASSIGN(GeneratedCodeCache);
};

}  // namespace content

#endif  // CONTENT_BROWSER_CODE_CACHE_GENERATED_CODE_CACHE_H_
