1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef STORAGE_BROWSER_FILEAPI_FILE_SYSTEM_CONTEXT_H_ 6 #define STORAGE_BROWSER_FILEAPI_FILE_SYSTEM_CONTEXT_H_ 7 8 #include <map> 9 #include <string> 10 #include <vector> 11 12 #include "base/callback.h" 13 #include "base/files/file.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "base/memory/scoped_vector.h" 17 #include "base/sequenced_task_runner_helpers.h" 18 #include "storage/browser/fileapi/file_system_url.h" 19 #include "storage/browser/fileapi/open_file_system_mode.h" 20 #include "storage/browser/fileapi/plugin_private_file_system_backend.h" 21 #include "storage/browser/fileapi/sandbox_file_system_backend_delegate.h" 22 #include "storage/browser/fileapi/task_runner_bound_observer_list.h" 23 #include "storage/browser/storage_browser_export.h" 24 #include "storage/common/fileapi/file_system_types.h" 25 26 namespace base { 27 class FilePath; 28 class SequencedTaskRunner; 29 class SingleThreadTaskRunner; 30 } 31 32 namespace chrome { 33 class NativeMediaFileUtilTest; 34 } 35 36 namespace storage { 37 class QuotaManagerProxy; 38 class SpecialStoragePolicy; 39 } 40 41 namespace net { 42 class URLRequest; 43 } 44 45 namespace storage { 46 class BlobURLRequestJobTest; 47 class FileStreamReader; 48 } 49 50 namespace storage { 51 52 class AsyncFileUtil; 53 class CopyOrMoveFileValidatorFactory; 54 class ExternalFileSystemBackend; 55 class ExternalMountPoints; 56 class FileStreamWriter; 57 class FileSystemBackend; 58 class FileSystemFileUtil; 59 class FileSystemOperation; 60 class FileSystemOperationRunner; 61 class FileSystemOptions; 62 class FileSystemQuotaUtil; 63 class FileSystemURL; 64 class IsolatedFileSystemBackend; 65 class MountPoints; 66 class QuotaReservation; 67 class SandboxFileSystemBackend; 68 class WatchManager; 69 70 struct DefaultContextDeleter; 71 struct FileSystemInfo; 72 73 // An auto mount handler will attempt to mount the file system requested in 74 // |url_request|. If the URL is for this auto mount handler, it returns true 75 // and calls |callback| when the attempt is complete. If the auto mounter 76 // does not recognize the URL, it returns false and does not call |callback|. 77 // Called on the IO thread. 78 typedef base::Callback<bool( 79 const net::URLRequest* url_request, 80 const FileSystemURL& filesystem_url, 81 const std::string& storage_domain, 82 const base::Callback<void(base::File::Error result)>& callback)> 83 URLRequestAutoMountHandler; 84 85 // This class keeps and provides a file system context for FileSystem API. 86 // An instance of this class is created and owned by profile. 87 class STORAGE_EXPORT FileSystemContext 88 : public base::RefCountedThreadSafe<FileSystemContext, 89 DefaultContextDeleter> { 90 public: 91 // Returns file permission policy we should apply for the given |type|. 92 // The return value must be bitwise-or'd of FilePermissionPolicy. 93 // 94 // Note: if a part of a filesystem is returned via 'Isolated' mount point, 95 // its per-filesystem permission overrides the underlying filesystem's 96 // permission policy. 97 static int GetPermissionPolicy(FileSystemType type); 98 99 // file_task_runner is used as default TaskRunner. 100 // Unless a FileSystemBackend is overridden in CreateFileSystemOperation, 101 // it is used for all file operations and file related meta operations. 102 // The code assumes that file_task_runner->RunsTasksOnCurrentThread() 103 // returns false if the current task is not running on the thread that allows 104 // blocking file operations (like SequencedWorkerPool implementation does). 105 // 106 // |external_mount_points| contains non-system external mount points available 107 // in the context. If not NULL, it will be used during URL cracking. 108 // |external_mount_points| may be NULL only on platforms different from 109 // ChromeOS (i.e. platforms that don't use external_mount_point_provider). 110 // 111 // |additional_backends| are added to the internal backend map 112 // to serve filesystem requests for non-regular types. 113 // If none is given, this context only handles HTML5 Sandbox FileSystem 114 // and Drag-and-drop Isolated FileSystem requests. 115 // 116 // |auto_mount_handlers| are used to resolve calls to 117 // AttemptAutoMountForURLRequest. Only external filesystems are auto mounted 118 // when a filesystem: URL request is made. 119 FileSystemContext( 120 base::SingleThreadTaskRunner* io_task_runner, 121 base::SequencedTaskRunner* file_task_runner, 122 ExternalMountPoints* external_mount_points, 123 storage::SpecialStoragePolicy* special_storage_policy, 124 storage::QuotaManagerProxy* quota_manager_proxy, 125 ScopedVector<FileSystemBackend> additional_backends, 126 const std::vector<URLRequestAutoMountHandler>& auto_mount_handlers, 127 const base::FilePath& partition_path, 128 const FileSystemOptions& options); 129 130 bool DeleteDataForOriginOnFileTaskRunner(const GURL& origin_url); 131 132 // Creates a new QuotaReservation for the given |origin_url| and |type|. 133 // Returns NULL if |type| does not support quota or reservation fails. 134 // This should be run on |default_file_task_runner_| and the returned value 135 // should be destroyed on the runner. 136 scoped_refptr<QuotaReservation> CreateQuotaReservationOnFileTaskRunner( 137 const GURL& origin_url, 138 FileSystemType type); 139 140 storage::QuotaManagerProxy* quota_manager_proxy() const { 141 return quota_manager_proxy_.get(); 142 } 143 144 // Discards inflight operations in the operation runner. 145 void Shutdown(); 146 147 // Returns a quota util for a given filesystem type. This may 148 // return NULL if the type does not support the usage tracking or 149 // it is not a quota-managed storage. 150 FileSystemQuotaUtil* GetQuotaUtil(FileSystemType type) const; 151 152 // Returns the appropriate AsyncFileUtil instance for the given |type|. 153 AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) const; 154 155 // Returns the appropriate CopyOrMoveFileValidatorFactory for the given 156 // |type|. If |error_code| is File::FILE_OK and the result is NULL, 157 // then no validator is required. 158 CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory( 159 FileSystemType type, base::File::Error* error_code) const; 160 161 // Returns the file system backend instance for the given |type|. 162 // This may return NULL if it is given an invalid or unsupported filesystem 163 // type. 164 FileSystemBackend* GetFileSystemBackend( 165 FileSystemType type) const; 166 167 // Returns the watcher manager for the given |type|. 168 // This may return NULL if the type does not support watching. 169 WatcherManager* GetWatcherManager(FileSystemType type) const; 170 171 // Returns true for sandboxed filesystems. Currently this does 172 // the same as GetQuotaUtil(type) != NULL. (In an assumption that 173 // all sandboxed filesystems must cooperate with QuotaManager so that 174 // they can get deleted) 175 bool IsSandboxFileSystem(FileSystemType type) const; 176 177 // Returns observers for the given filesystem type. 178 const UpdateObserverList* GetUpdateObservers(FileSystemType type) const; 179 const ChangeObserverList* GetChangeObservers(FileSystemType type) const; 180 const AccessObserverList* GetAccessObservers(FileSystemType type) const; 181 182 // Returns all registered filesystem types. 183 void GetFileSystemTypes(std::vector<FileSystemType>* types) const; 184 185 // Returns a FileSystemBackend instance for external filesystem 186 // type, which is used only by chromeos for now. This is equivalent to 187 // calling GetFileSystemBackend(kFileSystemTypeExternal). 188 ExternalFileSystemBackend* external_backend() const; 189 190 // Used for OpenFileSystem. 191 typedef base::Callback<void(const GURL& root, 192 const std::string& name, 193 base::File::Error result)> 194 OpenFileSystemCallback; 195 196 // Used for ResolveURL. 197 enum ResolvedEntryType { 198 RESOLVED_ENTRY_FILE, 199 RESOLVED_ENTRY_DIRECTORY, 200 RESOLVED_ENTRY_NOT_FOUND, 201 }; 202 typedef base::Callback<void(base::File::Error result, 203 const FileSystemInfo& info, 204 const base::FilePath& file_path, 205 ResolvedEntryType type)> ResolveURLCallback; 206 207 // Used for DeleteFileSystem and OpenPluginPrivateFileSystem. 208 typedef base::Callback<void(base::File::Error result)> StatusCallback; 209 210 // Opens the filesystem for the given |origin_url| and |type|, and dispatches 211 // |callback| on completion. 212 // If |create| is true this may actually set up a filesystem instance 213 // (e.g. by creating the root directory or initializing the database 214 // entry etc). 215 void OpenFileSystem( 216 const GURL& origin_url, 217 FileSystemType type, 218 OpenFileSystemMode mode, 219 const OpenFileSystemCallback& callback); 220 221 // Opens the filesystem for the given |url| as read-only, if the filesystem 222 // backend referred by the URL allows opening by resolveURL. Otherwise it 223 // fails with FILE_ERROR_SECURITY. The entry pointed by the URL can be 224 // absent; in that case RESOLVED_ENTRY_NOT_FOUND type is returned to the 225 // callback for indicating the absence. Can be called from any thread with 226 // a message loop. |callback| is invoked on the caller thread. 227 void ResolveURL( 228 const FileSystemURL& url, 229 const ResolveURLCallback& callback); 230 231 // Attempts to mount the filesystem needed to satisfy |url_request| made 232 // from |storage_domain|. If an appropriate file system is not found, 233 // callback will return an error. 234 void AttemptAutoMountForURLRequest(const net::URLRequest* url_request, 235 const std::string& storage_domain, 236 const StatusCallback& callback); 237 238 // Deletes the filesystem for the given |origin_url| and |type|. This should 239 // be called on the IO thread. 240 void DeleteFileSystem( 241 const GURL& origin_url, 242 FileSystemType type, 243 const StatusCallback& callback); 244 245 // Creates new FileStreamReader instance to read a file pointed by the given 246 // filesystem URL |url| starting from |offset|. |expected_modification_time| 247 // specifies the expected last modification if the value is non-null, the 248 // reader will check the underlying file's actual modification time to see if 249 // the file has been modified, and if it does any succeeding read operations 250 // should fail with ERR_UPLOAD_FILE_CHANGED error. 251 // This method internally cracks the |url|, get an appropriate 252 // FileSystemBackend for the URL and call the backend's CreateFileReader. 253 // The resolved FileSystemBackend could perform further specialization 254 // depending on the filesystem type pointed by the |url|. 255 // At most |max_bytes_to_read| can be fetched from the file stream reader. 256 scoped_ptr<storage::FileStreamReader> CreateFileStreamReader( 257 const FileSystemURL& url, 258 int64 offset, 259 int64 max_bytes_to_read, 260 const base::Time& expected_modification_time); 261 262 // Creates new FileStreamWriter instance to write into a file pointed by 263 // |url| from |offset|. 264 scoped_ptr<FileStreamWriter> CreateFileStreamWriter( 265 const FileSystemURL& url, 266 int64 offset); 267 268 // Creates a new FileSystemOperationRunner. 269 scoped_ptr<FileSystemOperationRunner> CreateFileSystemOperationRunner(); 270 271 base::SequencedTaskRunner* default_file_task_runner() { 272 return default_file_task_runner_.get(); 273 } 274 275 FileSystemOperationRunner* operation_runner() { 276 return operation_runner_.get(); 277 } 278 279 const base::FilePath& partition_path() const { return partition_path_; } 280 281 // Same as |CrackFileSystemURL|, but cracks FileSystemURL created from |url|. 282 FileSystemURL CrackURL(const GURL& url) const; 283 // Same as |CrackFileSystemURL|, but cracks FileSystemURL created from method 284 // arguments. 285 FileSystemURL CreateCrackedFileSystemURL(const GURL& origin, 286 FileSystemType type, 287 const base::FilePath& path) const; 288 289 #if defined(OS_CHROMEOS) 290 // Used only on ChromeOS for now. 291 void EnableTemporaryFileSystemInIncognito(); 292 #endif 293 294 SandboxFileSystemBackendDelegate* sandbox_delegate() { 295 return sandbox_delegate_.get(); 296 } 297 298 // Returns true if the requested url is ok to be served. 299 // (E.g. this returns false if the context is created for incognito mode) 300 bool CanServeURLRequest(const FileSystemURL& url) const; 301 302 // Returns true if a file in the file system should be flushed for each write 303 // completion. 304 bool ShouldFlushOnWriteCompletion(FileSystemType type) const; 305 306 // This must be used to open 'plugin private' filesystem. 307 // See "plugin_private_file_system_backend.h" for more details. 308 void OpenPluginPrivateFileSystem( 309 const GURL& origin_url, 310 FileSystemType type, 311 const std::string& filesystem_id, 312 const std::string& plugin_id, 313 OpenFileSystemMode mode, 314 const StatusCallback& callback); 315 316 private: 317 typedef std::map<FileSystemType, FileSystemBackend*> 318 FileSystemBackendMap; 319 320 // For CreateFileSystemOperation. 321 friend class FileSystemOperationRunner; 322 323 // For sandbox_backend(). 324 friend class content::SandboxFileSystemTestHelper; 325 326 // For plugin_private_backend(). 327 friend class content::PluginPrivateFileSystemBackendTest; 328 329 // Deleters. 330 friend struct DefaultContextDeleter; 331 friend class base::DeleteHelper<FileSystemContext>; 332 friend class base::RefCountedThreadSafe<FileSystemContext, 333 DefaultContextDeleter>; 334 ~FileSystemContext(); 335 336 void DeleteOnCorrectThread() const; 337 338 // Creates a new FileSystemOperation instance by getting an appropriate 339 // FileSystemBackend for |url| and calling the backend's corresponding 340 // CreateFileSystemOperation method. 341 // The resolved FileSystemBackend could perform further specialization 342 // depending on the filesystem type pointed by the |url|. 343 // 344 // Called by FileSystemOperationRunner. 345 FileSystemOperation* CreateFileSystemOperation( 346 const FileSystemURL& url, 347 base::File::Error* error_code); 348 349 // For non-cracked isolated and external mount points, returns a FileSystemURL 350 // created by cracking |url|. The url is cracked using MountPoints registered 351 // as |url_crackers_|. If the url cannot be cracked, returns invalid 352 // FileSystemURL. 353 // 354 // If the original url does not point to an isolated or external filesystem, 355 // returns the original url, without attempting to crack it. 356 FileSystemURL CrackFileSystemURL(const FileSystemURL& url) const; 357 358 // For initial backend_map construction. This must be called only from 359 // the constructor. 360 void RegisterBackend(FileSystemBackend* backend); 361 362 void DidOpenFileSystemForResolveURL( 363 const FileSystemURL& url, 364 const ResolveURLCallback& callback, 365 const GURL& filesystem_root, 366 const std::string& filesystem_name, 367 base::File::Error error); 368 369 // Returns a FileSystemBackend, used only by test code. 370 SandboxFileSystemBackend* sandbox_backend() const { 371 return sandbox_backend_.get(); 372 } 373 374 // Used only by test code. 375 PluginPrivateFileSystemBackend* plugin_private_backend() const { 376 return plugin_private_backend_.get(); 377 } 378 379 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; 380 scoped_refptr<base::SequencedTaskRunner> default_file_task_runner_; 381 382 scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_; 383 384 scoped_ptr<SandboxFileSystemBackendDelegate> sandbox_delegate_; 385 386 // Regular file system backends. 387 scoped_ptr<SandboxFileSystemBackend> sandbox_backend_; 388 scoped_ptr<IsolatedFileSystemBackend> isolated_backend_; 389 390 // Additional file system backends. 391 scoped_ptr<PluginPrivateFileSystemBackend> plugin_private_backend_; 392 ScopedVector<FileSystemBackend> additional_backends_; 393 394 std::vector<URLRequestAutoMountHandler> auto_mount_handlers_; 395 396 // Registered file system backends. 397 // The map must be constructed in the constructor since it can be accessed 398 // on multiple threads. 399 // This map itself doesn't retain each backend's ownership; ownerships 400 // of the backends are held by additional_backends_ or other scoped_ptr 401 // backend fields. 402 FileSystemBackendMap backend_map_; 403 404 // External mount points visible in the file system context (excluding system 405 // external mount points). 406 scoped_refptr<ExternalMountPoints> external_mount_points_; 407 408 // MountPoints used to crack FileSystemURLs. The MountPoints are ordered 409 // in order they should try to crack a FileSystemURL. 410 std::vector<MountPoints*> url_crackers_; 411 412 // The base path of the storage partition for this context. 413 const base::FilePath partition_path_; 414 415 bool is_incognito_; 416 417 scoped_ptr<FileSystemOperationRunner> operation_runner_; 418 419 DISALLOW_IMPLICIT_CONSTRUCTORS(FileSystemContext); 420 }; 421 422 struct DefaultContextDeleter { 423 static void Destruct(const FileSystemContext* context) { 424 context->DeleteOnCorrectThread(); 425 } 426 }; 427 428 } // namespace storage 429 430 #endif // STORAGE_BROWSER_FILEAPI_FILE_SYSTEM_CONTEXT_H_ 431