910e62b5创建于 1月15日历史提交
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_MANAGER_H_
#define CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_MANAGER_H_

#include <map>
#include <memory>
#include <string>
#include <vector>

#include "base/dcheck_is_on.h"
#include "base/files/file_path.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
#include "components/services/storage/public/mojom/quota_client.mojom.h"
#include "content/browser/cache_storage/blob_storage_context_wrapper.h"
#include "content/browser/cache_storage/cache_storage.h"
#include "content/browser/cache_storage/cache_storage_cache.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/browser/cache_storage/cache_storage_dispatcher_host.h"
#include "content/browser/cache_storage/cache_storage_handle.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/remote_set.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "url/origin.h"

namespace base {
class SequencedTaskRunner;
}

namespace content {

namespace cache_storage_manager_unittest {
class CacheStorageManagerTest;
}

// Keeps track of a CacheStorage per StorageKey. There is one
// CacheStorageManager per CacheStorageOwner. Created and accessed from a single
// sequence.
// TODO(jkarlin): Remove CacheStorage from memory once they're no
// longer in active use.
class CONTENT_EXPORT CacheStorageManager
    : public base::RefCounted<CacheStorageManager>,
      public base::MemoryPressureListener {
 public:
  static scoped_refptr<CacheStorageManager> Create(
      const base::FilePath& path,
      scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
      scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
      scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
      scoped_refptr<BlobStorageContextWrapper> blob_storage_context,
      base::WeakPtr<CacheStorageDispatcherHost> cache_storage_dispatcher_host);

  // Create a new manager using the underlying configuration of the given
  // manager, but with its own list of storage objects.  This is only used
  // for testing.
  static scoped_refptr<CacheStorageManager> CreateForTesting(
      CacheStorageManager* old_manager);

  CacheStorageManager(const CacheStorageManager&) = delete;
  CacheStorageManager& operator=(const CacheStorageManager&) = delete;

  // Map a database identifier (computed from a BucketLocator) to the path.
  static base::FilePath ConstructBucketPath(
      const base::FilePath& profile_path,
      const storage::BucketLocator& bucket_locator,
      storage::mojom::CacheStorageOwner owner);

  static bool IsValidQuotaStorageKey(const blink::StorageKey& storage_key);

  // Open the CacheStorage for the given bucket_locator and owner. A reference
  // counting handle is returned which can be stored and used similar to a weak
  // pointer.
  CacheStorageHandle OpenCacheStorage(
      const storage::BucketLocator& bucket_locator,
      storage::mojom::CacheStorageOwner owner);

  // QuotaClient support.
  void GetBucketUsage(
      const storage::BucketLocator& bucket_locator,
      storage::mojom::CacheStorageOwner owner,
      storage::mojom::QuotaClient::GetBucketUsageCallback callback);
  void GetStorageKeys(
      storage::mojom::CacheStorageOwner owner,
      storage::mojom::QuotaClient::GetDefaultStorageKeysCallback callback);
  void DeleteOriginData(
      const std::set<url::Origin>& origins,
      storage::mojom::CacheStorageOwner owner,
      storage::mojom::QuotaClient::DeleteBucketDataCallback callback);
  void DeleteBucketData(
      const storage::BucketLocator& bucket_locator,
      storage::mojom::CacheStorageOwner owner,
      storage::mojom::QuotaClient::DeleteBucketDataCallback callback);
  void AddObserver(
      mojo::PendingRemote<storage::mojom::CacheStorageObserver> observer);

  void NotifyCacheListChanged(const storage::BucketLocator& bucket_locator);
  void NotifyCacheContentChanged(const storage::BucketLocator& bucket_locator,
                                 const std::u16string& name);

  base::FilePath profile_path() const { return profile_path_; }

  static base::FilePath ConstructFirstPartyDefaultRootPath(
      const base::FilePath& profile_path);

  static base::FilePath ConstructThirdPartyAndNonDefaultRootPath(
      const base::FilePath& profile_path);

  // This method is called when the last CacheStorageHandle for a particular
  // instance is destroyed and its reference count drops to zero.
  void CacheStorageUnreferenced(CacheStorage* cache_storage,
                                const storage::BucketLocator& bucket_locator,
                                storage::mojom::CacheStorageOwner owner);

 protected:
  friend class base::RefCounted<CacheStorageManager>;

  CacheStorageManager(
      const base::FilePath& path,
      scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
      scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
      scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
      scoped_refptr<BlobStorageContextWrapper> blob_storage_context,
      base::WeakPtr<CacheStorageDispatcherHost> cache_storage_dispatcher_host);
  ~CacheStorageManager() override;

 private:
  friend class cache_storage_manager_unittest::CacheStorageManagerTest;
  friend class CacheStorageContextImpl;

  typedef std::map<
      std::pair<storage::BucketLocator, storage::mojom::CacheStorageOwner>,
      std::unique_ptr<CacheStorage>>
      CacheStorageMap;

  void DeleteOriginsDataGotAllBucketInfo(
      const std::set<url::Origin>& origins,
      storage::mojom::CacheStorageOwner owner,
      base::OnceCallback<void(blink::mojom::QuotaStatusCode)> callback,
      std::vector<storage::BucketLocator> buckets);

  void GetBucketUsageDidGetExists(
      const storage::BucketLocator& bucket_locator,
      storage::mojom::CacheStorageOwner owner,
      storage::mojom::QuotaClient::GetBucketUsageCallback callback,
      bool exists);

  void DeleteBucketDataDidGetExists(
      storage::mojom::CacheStorageOwner owner,
      storage::mojom::QuotaClient::DeleteBucketDataCallback callback,
      storage::BucketLocator bucket_locator,
      bool exists);

  void DeleteBucketDidClose(
      const storage::BucketLocator& bucket_locator,
      storage::mojom::CacheStorageOwner owner,
      storage::mojom::QuotaClient::DeleteBucketDataCallback callback,
      std::unique_ptr<CacheStorage> cache_storage,
      int64_t bucket_size);

  scoped_refptr<base::SequencedTaskRunner> cache_task_runner() const {
    return cache_task_runner_;
  }

  scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner() const {
    return scheduler_task_runner_;
  }

  void ListStorageKeysOnTaskRunner(
      storage::mojom::QuotaClient::GetDefaultStorageKeysCallback callback,
      std::vector<storage::BucketLocator> buckets);

  bool IsMemoryBacked() const { return profile_path_.empty(); }

  // MemoryPressureListener callback
  void OnMemoryPressure(base::MemoryPressureLevel level) override;

#if DCHECK_IS_ON()
  bool CacheStoragePathIsUnique(const base::FilePath& path);
#endif
  bool ConflictingInstanceExistsInMap(
      storage::mojom::CacheStorageOwner owner,
      const storage::BucketLocator& bucket_locator);

  // Stores the storage partition (profile) path unless the CacheStorage should
  // be in-memory only, in which case this is empty.
  const base::FilePath profile_path_;
  const scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
  const scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner_;

  const scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;

  // The map owns the CacheStorages and the CacheStorages are only accessed on
  // |cache_task_runner_|.
  CacheStorageMap cache_storage_map_;

  mojo::RemoteSet<storage::mojom::CacheStorageObserver> observers_;

  const scoped_refptr<BlobStorageContextWrapper> blob_storage_context_;

  const base::WeakPtr<CacheStorageDispatcherHost>
      cache_storage_dispatcher_host_;

  std::unique_ptr<base::AsyncMemoryPressureListenerRegistration>
      memory_pressure_listener_registration_;

  SEQUENCE_CHECKER(sequence_checker_);

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

}  // namespace content

#endif  // CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_MANAGER_H_