blob: eba8cbdea5f90cae9496a3fc1d27ca088f5d98b8 [file] [log] [blame]
// Copyright 2020 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_NATIVE_IO_NATIVE_IO_MANAGER_H_
#define CONTENT_BROWSER_NATIVE_IO_NATIVE_IO_MANAGER_H_
#include <map>
#include <memory>
#include <string>
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/thread_annotations.h"
#include "base/types/pass_key.h"
#include "build/build_config.h"
#include "components/services/storage/public/mojom/quota_client.mojom-forward.h"
#include "content/browser/native_io/native_io_quota_client.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/browser/quota/special_storage_policy.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/native_io/native_io.mojom-forward.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom-forward.h"
namespace content {
class NativeIOHost;
// Implements the NativeIO Web Platform feature for a StoragePartition.
//
// Each StoragePartition owns exactly one instance of this class. This class
// creates and destroys NativeIOHost instances to meet the demands for NativeIO
// from different storage keys.
//
// This class is not thread-safe, and all access to an instance must happen on
// the same sequence.
class CONTENT_EXPORT NativeIOManager {
public:
// `profile_root` is empty for in-memory (Incognito) profiles. Otherwise,
// `profile_root` must point to an existing directory. NativeIO will store its
// data in a subdirectory of the profile root.
//
// `allow_set_length_ipc` gates NativeIOFileHost::SetLength(), which works
// around a sandboxing limitation on macOS < 10.15. This is plumbed as a flag
// all the from NativeIOManager to facilitate testing.
explicit NativeIOManager(
const base::FilePath& profile_root,
#if BUILDFLAG(IS_MAC)
bool allow_set_length_ipc,
#endif // BUILDFLAG(IS_MAC)
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy);
~NativeIOManager();
NativeIOManager(const NativeIOManager&) = delete;
NativeIOManager& operator=(const NativeIOManager&) = delete;
// Binds `receiver` to the NativeIOHost serving `storage_key`.
//
// `receiver` must belong to a frame or worker serving `storage_key`.
void BindReceiver(const blink::StorageKey& storage_key,
mojo::PendingReceiver<blink::mojom::NativeIOHost> receiver,
mojo::ReportBadMessageCallback bad_message_callback);
// Removes an storage key's data and closes any open files.
void DeleteStorageKeyData(
const blink::StorageKey& storage_key,
storage::mojom::QuotaClient::DeleteBucketDataCallback callback);
// Computes all storage keys with data for a given type.
void GetStorageKeysForType(
blink::mojom::StorageType type,
storage::mojom::QuotaClient::GetStorageKeysForTypeCallback callback);
// Computes the amount of bytes for the given storage key.
//
// This method walks the storage key's entire directory and is therefore not
// particularly speedy.
// TODO(rstz): Consider a caching mechanism to improve performance.
void GetStorageKeyUsage(
const blink::StorageKey& storage_key,
blink::mojom::StorageType type,
storage::mojom::QuotaClient::GetBucketUsageCallback callback);
// Computes the amount of bytes for all storage keys.
//
// This method walks the storage key's entire directory and is therefore not
// particularly speedy.
// TODO(rstz): Consider a caching mechanism to improve performance.
void GetStorageKeyUsageMap(
base::OnceCallback<void(const std::map<blink::StorageKey, int64_t>&)>
callback);
// Computes the path to the directory storing an storage key's NativeIO files.
//
// Returns an empty path if the storage key isn't supported for NativeIO.
base::FilePath RootPathForStorageKey(const blink::StorageKey& storage_key);
// Computes the path to the directory storing a profile's NativeIO files.
static base::FilePath GetNativeIORootPath(const base::FilePath& profile_root);
// Transform a base::File::Error into a NativeIOError with default error
// message if none is provided.
static blink::mojom::NativeIOErrorPtr FileErrorToNativeIOError(
base::File::Error file_error,
std::string message = "");
// Called when a receiver is disconnected from a NativeIOHost.
//
// `host` must be owned by this manager. `host` may be deleted.
void OnHostReceiverDisconnect(NativeIOHost* host,
base::PassKey<NativeIOHost>);
// Called when a NativeIOHost finishes processing a data deletion request.
//
// `host` must be owned by this manager. `host` may be deleted.
void DidDeleteHostData(NativeIOHost* host, base::PassKey<NativeIOHost>);
const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy() const {
return quota_manager_proxy_;
}
private:
// Adds and binds receiver on default bucket retrieval to ensure that a bucket
// always exists for the storage key.
void BindReceiverWithBucketInfo(
const blink::StorageKey& storage_key,
mojo::PendingReceiver<blink::mojom::NativeIOHost> receiver,
storage::QuotaErrorOr<storage::BucketInfo> result);
// Deletes the NativeIOHost if it serves no further purpose.
//
// `host` must be owned by this manager.
void MaybeDeleteHost(NativeIOHost* host);
SEQUENCE_CHECKER(sequence_checker_);
// Points to the root directory for NativeIO files.
//
// This path is empty for in-memory (Incognito) profiles.
const base::FilePath root_path_;
#if BUILDFLAG(IS_MAC)
const bool allow_set_length_ipc_;
#endif // BUILDFLAG(IS_MAC)
// Tracks special rights for apps and extensions, may be null.
const scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
const scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
std::map<blink::StorageKey, std::unique_ptr<NativeIOHost>> hosts_
GUARDED_BY_CONTEXT(sequence_checker_);
NativeIOQuotaClient quota_client_ GUARDED_BY_CONTEXT(sequence_checker_);
// Once the QuotaClient receiver is destroyed, the underlying mojo connection
// is closed. Callbacks associated with mojo calls received over this
// connection may only be dropped after the connection is closed. For this
// reason, it's preferable to have the receiver be destroyed as early as
// possible during the NativeIOManager destruction process.
mojo::Receiver<storage::mojom::QuotaClient> quota_client_receiver_
GUARDED_BY_CONTEXT(sequence_checker_);
base::WeakPtrFactory<NativeIOManager> weak_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_NATIVE_IO_NATIVE_IO_MANAGER_H_