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