1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef STORAGE_BROWSER_FILE_SYSTEM_FILE_SYSTEM_CONTEXT_H_
#define STORAGE_BROWSER_FILE_SYSTEM_FILE_SYSTEM_CONTEXT_H_
#include <stdint.h>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/component_export.h"
#include "base/containers/flat_set.h"
#include "base/files/file.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted_delete_on_sequence.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/sequenced_task_runner_helpers.h"
#include "base/threading/sequence_bound.h"
#include "base/types/pass_key.h"
#include "build/build_config.h"
#include "components/file_access/scoped_file_access_delegate.h"
#include "components/services/storage/public/cpp/quota_error_or.h"
#include "components/services/storage/public/mojom/quota_client.mojom.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "storage/browser/file_system/file_system_request_info.h"
#include "storage/browser/file_system/file_system_url.h"
#include "storage/browser/file_system/open_file_system_mode.h"
#include "storage/browser/file_system/task_runner_bound_observer_list.h"
#include "storage/common/file_system/file_system_types.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace base {
class FilePath;
class SequencedTaskRunner;
class SingleThreadTaskRunner;
} // namespace base
namespace blink {
class StorageKey;
} // namespace blink
namespace leveldb {
class Env;
} // namespace leveldb
namespace storage {
class AsyncFileUtil;
class CopyOrMoveFileValidatorFactory;
class ExternalMountPoints;
class FileStreamReader;
class FileStreamWriter;
class FileSystemBackend;
class FileSystemOperation;
class FileSystemOperationRunner;
class FileSystemOptions;
class FileSystemQuotaClient;
class FileSystemQuotaUtil;
class FileSystemURL;
class IsolatedFileSystemBackend;
class MountPoints;
class QuotaClientCallbackWrapper;
class QuotaManagerProxy;
class QuotaReservation;
class SandboxFileSystemBackend;
class SandboxFileSystemBackendDelegate;
class SpecialStoragePolicy;
class WatcherManager;
enum class OperationType;
struct BucketInfo;
struct FileSystemInfo;
// An auto mount handler will attempt to mount the file system requested in
// `request_info`. If the URL is for this auto mount handler, it returns true
// and calls `callback` when the attempt is complete. If the auto mounter
// does not recognize the URL, it returns false and does not call `callback`.
// Called on the IO thread.
using URLRequestAutoMountHandler = base::RepeatingCallback<bool(
const FileSystemRequestInfo& request_info,
const FileSystemURL& filesystem_url,
base::OnceCallback<void(base::File::Error result)> callback)>;
// This class keeps and provides a file system context for FileSystem API.
// An instance of this class is created and owned by profile.
class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemContext
: public base::RefCountedDeleteOnSequence<FileSystemContext> {
public:
REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
FileSystemContext() = delete;
FileSystemContext(const FileSystemContext&) = delete;
FileSystemContext& operator=(const FileSystemContext&) = delete;
// Returns file permission policy we should apply for the given `type`.
// The return value must be bitwise-or'd of FilePermissionPolicy.
//
// Note: if a part of a filesystem is returned via 'Isolated' mount point,
// its per-filesystem permission overrides the underlying filesystem's
// permission policy.
static int GetPermissionPolicy(FileSystemType type);
// file_task_runner is used as default TaskRunner.
// Unless a FileSystemBackend is overridden in CreateFileSystemOperation,
// it is used for all file operations and file related meta operations.
// The code assumes that file_task_runner->RunsTasksInCurrentSequence()
// returns false if the current task is not running on the sequence that
// allows blocking file operations (like SequencedWorkerPool implementation
// does).
//
// `external_mount_points` contains non-system external mount points available
// in the context. If not nullptr, it will be used during URL cracking.
// `external_mount_points` may be nullptr only on platforms different from
// ChromeOS (i.e. platforms that don't use external_mount_point_provider).
//
// `additional_backends` are added to the internal backend map
// to serve filesystem requests for non-regular types.
// If none is given, this context only handles HTML5 Sandbox FileSystem
// and Drag-and-drop Isolated FileSystem requests.
//
// `auto_mount_handlers` are used to resolve calls to
// AttemptAutoMountForURLRequest. Only external filesystems are auto mounted
// when a filesystem: URL request is made.
static scoped_refptr<FileSystemContext> Create(
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
scoped_refptr<base::SequencedTaskRunner> file_task_runner,
scoped_refptr<ExternalMountPoints> external_mount_points,
scoped_refptr<SpecialStoragePolicy> special_storage_policy,
scoped_refptr<QuotaManagerProxy> quota_manager_proxy,
std::vector<std::unique_ptr<FileSystemBackend>> additional_backends,
const std::vector<URLRequestAutoMountHandler>& auto_mount_handlers,
const base::FilePath& partition_path,
const FileSystemOptions& options);
// Exposed for base::MakeRefCounted(). Instances should be obtained from the
// factory method Create().
FileSystemContext(
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
scoped_refptr<base::SequencedTaskRunner> file_task_runner,
scoped_refptr<ExternalMountPoints> external_mount_points,
scoped_refptr<SpecialStoragePolicy> special_storage_policy,
scoped_refptr<QuotaManagerProxy> quota_manager_proxy,
std::vector<std::unique_ptr<FileSystemBackend>> additional_backends,
const std::vector<URLRequestAutoMountHandler>& auto_mount_handlers,
const base::FilePath& partition_path,
const FileSystemOptions& options,
base::PassKey<FileSystemContext>);
// Creates a new QuotaReservation for the given `storage_key` and `type`.
// Returns nullptr if `type` does not support quota or reservation fails.
// This should be run on `default_file_task_runner_` and the returned value
// should be destroyed on the runner.
scoped_refptr<QuotaReservation> CreateQuotaReservationOnFileTaskRunner(
const blink::StorageKey& storage_key,
FileSystemType type);
const scoped_refptr<QuotaManagerProxy>& quota_manager_proxy() const {
return quota_manager_proxy_;
}
// Discards inflight operations in the operation runner.
void Shutdown();
// Returns a quota util for a given filesystem type. This may
// return nullptr if the type does not support the usage tracking or
// it is not a quota-managed storage.
FileSystemQuotaUtil* GetQuotaUtil(FileSystemType type) const;
// Returns the appropriate AsyncFileUtil instance for the given `type`.
AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) const;
// Returns the appropriate CopyOrMoveFileValidatorFactory for the given
// `type`. If `error_code` is File::FILE_OK and the result is nullptr,
// then no validator is required.
CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory(
FileSystemType type,
base::File::Error* error_code) const;
// Returns the file system backend instance for the given `type`.
// This may return nullptr if it is given an invalid or unsupported filesystem
// type.
FileSystemBackend* GetFileSystemBackend(FileSystemType type) const;
// Returns the watcher manager for the given `type`.
// This may return nullptr if the type does not support watching.
WatcherManager* GetWatcherManager(FileSystemType type) const;
// Returns true for sandboxed filesystems. Currently this does
// the same as GetQuotaUtil(type) != nullptr. (In an assumption that
// all sandboxed filesystems must cooperate with QuotaManager so that
// they can get deleted)
bool IsSandboxFileSystem(FileSystemType type) const;
// Returns observers for the given filesystem type.
const UpdateObserverList* GetUpdateObservers(FileSystemType type) const;
const ChangeObserverList* GetChangeObservers(FileSystemType type) const;
const AccessObserverList* GetAccessObservers(FileSystemType type) const;
// Returns all registered filesystem types.
std::vector<FileSystemType> GetFileSystemTypes() const;
// Used for OpenFileSystem.
using OpenFileSystemCallback =
base::OnceCallback<void(const FileSystemURL& root_url,
const std::string& name,
base::File::Error result)>;
// Used for ResolveURL.
enum ResolvedEntryType {
RESOLVED_ENTRY_FILE,
RESOLVED_ENTRY_DIRECTORY,
RESOLVED_ENTRY_NOT_FOUND,
};
using ResolveURLCallback =
base::OnceCallback<void(base::File::Error result,
const FileSystemInfo& info,
const base::FilePath& file_path,
ResolvedEntryType type)>;
// Used for DeleteFileSystem.
using StatusCallback = base::OnceCallback<void(base::File::Error result)>;
// Opens the filesystem for the given `storage_key` and `type`, and dispatches
// `callback` on completion.
// If `create` is true this may actually set up a filesystem instance
// (e.g. by creating the root directory or initializing the database
// entry etc).
// Provide a non-null BucketLocator to override the default storage bucket
// for the root URL (which will be propagated to child URLs).
void OpenFileSystem(const blink::StorageKey& storage_key,
const std::optional<storage::BucketLocator>& bucket,
FileSystemType type,
OpenFileSystemMode mode,
OpenFileSystemCallback callback);
// Opens the filesystem for the given `url` as read-only, if the filesystem
// backend referred by the URL allows opening by resolveURL. Otherwise it
// fails with FILE_ERROR_SECURITY. The entry pointed by the URL can be
// absent; in that case RESOLVED_ENTRY_NOT_FOUND type is returned to the
// callback for indicating the absence. Can be called from any thread with
// a message loop. `callback` is invoked on the caller thread.
void ResolveURL(const FileSystemURL& url, ResolveURLCallback callback);
// Attempts to mount the filesystem needed to satisfy `request_info` made from
// `request_info.storage_domain_`. If an appropriate file system is not found,
// callback will return an error.
void AttemptAutoMountForURLRequest(const FileSystemRequestInfo& request_info,
StatusCallback callback);
// Deletes the filesystem for the given `storage_key` and `type`. This should
// be called on the IO thread.
void DeleteFileSystem(const blink::StorageKey& storage_key,
FileSystemType type,
StatusCallback callback);
// Creates new FileStreamReader instance to read a file pointed by the given
// filesystem URL `url` starting from `offset`. `expected_modification_time`
// specifies the expected last modification if the value is non-null, the
// reader will check the underlying file's actual modification time to see if
// the file has been modified, and if it does any succeeding read operations
// should fail with ERR_UPLOAD_FILE_CHANGED error.
// This method internally cracks the `url`, get an appropriate
// FileSystemBackend for the URL and call the backend's CreateFileReader.
// The resolved FileSystemBackend could perform further specialization
// depending on the filesystem type pointed by the `url`.
// At most `max_bytes_to_read` can be fetched from the file stream reader.
std::unique_ptr<FileStreamReader> CreateFileStreamReader(
const FileSystemURL& url,
int64_t offset,
int64_t max_bytes_to_read,
const base::Time& expected_modification_time,
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
file_access = base::NullCallback());
// Creates new FileStreamWriter instance to write into a file pointed by
// `url` from `offset`.
std::unique_ptr<FileStreamWriter> CreateFileStreamWriter(
const FileSystemURL& url,
int64_t offset);
// Creates a new FileSystemOperationRunner. Callers have to make sure that
// this FileSystemContext outlives the returned FileSystemOperationRunner.
// This must be called on the IO thread.
std::unique_ptr<FileSystemOperationRunner> CreateFileSystemOperationRunner();
// Similar to above, but this method can be called on any thread.
base::SequenceBound<FileSystemOperationRunner>
CreateSequenceBoundFileSystemOperationRunner();
base::SequencedTaskRunner* default_file_task_runner() {
return default_file_task_runner_.get();
}
FileSystemOperationRunner* operation_runner() {
return operation_runner_.get();
}
const base::FilePath& partition_path() const { return partition_path_; }
// Same as `CrackFileSystemURL`, but cracks FileSystemURL created from `url`
// and `storage_key`.
FileSystemURL CrackURL(const GURL& url,
const blink::StorageKey& storage_key) const;
// Same as `CrackFileSystemURL`, but cracks FileSystemURL created from `url`
// and a blink::StorageKey it derives from `url`. Note: never use this
// function to crack URLs received from web contents. For all web-exposed
// URLs, use the CrackURL function above and pass in the StorageKey of the
// frame or worker that provided the URL.
FileSystemURL CrackURLInFirstPartyContext(const GURL& url) const;
// Same as `CrackFileSystemURL`, but cracks FileSystemURL created from method
// arguments.
FileSystemURL CreateCrackedFileSystemURL(const blink::StorageKey& storage_key,
FileSystemType type,
const base::FilePath& path) const;
SandboxFileSystemBackendDelegate* sandbox_delegate() {
return sandbox_delegate_.get();
}
// Returns true if the requested url is ok to be served.
// (E.g. this returns false if the context is created for incognito mode)
bool CanServeURLRequest(const FileSystemURL& url) const;
bool is_incognito() { return is_incognito_; }
void ResolveURLOnOpenFileSystemForTesting(
const blink::StorageKey& storage_key,
const std::optional<storage::BucketLocator>& bucket,
FileSystemType type,
OpenFileSystemMode mode,
OpenFileSystemCallback callback) {
ResolveURLOnOpenFileSystem(storage_key, bucket, type, mode,
std::move(callback));
}
private:
// For CreateFileSystemOperation.
friend class FileSystemOperationRunner;
// For sandbox_backend().
friend class SandboxFileSystemTestHelper;
// Deleters.
friend class base::DeleteHelper<FileSystemContext>;
friend class base::RefCountedDeleteOnSequence<FileSystemContext>;
~FileSystemContext();
// Must be called after creating the FileSystemContext.
void Initialize();
// Creates a new FileSystemOperation instance by getting an appropriate
// FileSystemBackend for `url` and calling the backend's corresponding
// CreateFileSystemOperation method.
// The resolved FileSystemBackend could perform further specialization
// depending on the filesystem type pointed by the `url`.
//
// Called by FileSystemOperationRunner.
std::unique_ptr<FileSystemOperation> CreateFileSystemOperation(
OperationType type,
const FileSystemURL& url,
base::File::Error* error_code);
// For non-cracked isolated and external mount points, returns a FileSystemURL
// created by cracking `url`. The url is cracked using MountPoints registered
// as `url_crackers_`. If the url cannot be cracked, returns invalid
// FileSystemURL.
//
// If the original url does not point to an isolated or external filesystem,
// returns the original url, without attempting to crack it.
FileSystemURL CrackFileSystemURL(const FileSystemURL& url) const;
// For initial backend_map construction. This must be called only from
// the constructor.
void RegisterBackend(FileSystemBackend* backend);
void DidOpenFileSystemForResolveURL(const FileSystemURL& url,
ResolveURLCallback callback,
const GURL& filesystem_root,
const std::string& filesystem_name,
base::File::Error error);
void OnGetBucketForDeleteFileSystem(FileSystemType type,
StatusCallback callback,
QuotaErrorOr<BucketInfo> result);
// OnGetOrCreateBucket is the callback for calling
// QuotaManagerProxy::GetOrCreateDefault.
void OnGetOrCreateBucket(const blink::StorageKey& storage_key,
FileSystemType type,
OpenFileSystemMode mode,
OpenFileSystemCallback callback,
QuotaErrorOr<BucketInfo> result);
// ResolveURLOnOpenFileSystem is called, either by OnGetOrCreateBucket
// on successful bucket creation, or (tests onlyh) by OpenFileSystem
// directly in the absence of a quota manager.
// `bucket` will be populated if the non-default storage bucket was used.
void ResolveURLOnOpenFileSystem(
const blink::StorageKey& storage_key,
const std::optional<storage::BucketLocator>& bucket,
FileSystemType type,
OpenFileSystemMode mode,
OpenFileSystemCallback callback);
void DidResolveURLOnOpenFileSystem(const FileSystemURL& filesystem_root_url,
OpenFileSystemCallback callback,
const GURL& filesystem_root,
const std::string& filesystem_name,
base::File::Error error);
// Returns a FileSystemBackend, used only by test code.
SandboxFileSystemBackend* sandbox_backend() const {
return sandbox_backend_.get();
}
// Override the default leveldb Env with `env_override_` if set.
std::unique_ptr<leveldb::Env> env_override_;
const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
const scoped_refptr<base::SequencedTaskRunner> default_file_task_runner_;
const scoped_refptr<QuotaManagerProxy> quota_manager_proxy_;
std::unique_ptr<FileSystemQuotaClient> quota_client_;
std::unique_ptr<storage::QuotaClientCallbackWrapper> quota_client_wrapper_;
const std::unique_ptr<SandboxFileSystemBackendDelegate> sandbox_delegate_;
// Regular file system backends.
const std::unique_ptr<SandboxFileSystemBackend> sandbox_backend_;
std::unique_ptr<IsolatedFileSystemBackend> isolated_backend_;
// Additional file system backends.
const std::vector<std::unique_ptr<FileSystemBackend>> additional_backends_;
std::vector<URLRequestAutoMountHandler> auto_mount_handlers_;
// Registered file system backends.
// The map must be constructed in the constructor since it can be accessed
// on multiple threads.
// This map itself doesn't retain each backend's ownership; ownerships
// of the backends are held by additional_backends_ or other scoped_ptr
// backend fields.
std::map<FileSystemType, raw_ptr<FileSystemBackend, CtnExperimental>>
backend_map_;
// External mount points visible in the file system context (excluding system
// external mount points).
const scoped_refptr<ExternalMountPoints> external_mount_points_;
// MountPoints used to crack FileSystemURLs. The MountPoints are ordered
// in order they should try to crack a FileSystemURL.
std::vector<raw_ptr<MountPoints, VectorExperimental>> url_crackers_;
// The base path of the storage partition for this context.
const base::FilePath partition_path_;
const bool is_incognito_;
const std::unique_ptr<FileSystemOperationRunner> operation_runner_;
std::unique_ptr<mojo::Receiver<mojom::QuotaClient>> quota_client_receiver_;
base::WeakPtrFactory<FileSystemContext> weak_factory_{this};
};
} // namespace storage
#endif // STORAGE_BROWSER_FILE_SYSTEM_FILE_SYSTEM_CONTEXT_H_
|