blob: 2a84d438c3a5b6fa599cee2fa6a027c667f90e57 [file] [log] [blame]
// 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/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:
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);
virtual ~CacheStorageManager();
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::MemoryPressureListener::MemoryPressureLevel level);
#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::MemoryPressureListener> memory_pressure_listener_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<CacheStorageManager> weak_ptr_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_MANAGER_H_