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_OBFUSCATED_FILE_UTIL_H_ 6 #define WEBKIT_BROWSER_FILEAPI_OBFUSCATED_FILE_UTIL_H_ 7 8 #include <map> 9 #include <string> 10 11 #include "base/files/file_path.h" 12 #include "base/files/file_util_proxy.h" 13 #include "base/gtest_prod_util.h" 14 #include "base/memory/scoped_ptr.h" 15 #include "base/platform_file.h" 16 #include "webkit/browser/fileapi/file_system_file_util.h" 17 #include "webkit/browser/fileapi/file_system_url.h" 18 #include "webkit/browser/fileapi/sandbox_directory_database.h" 19 #include "webkit/browser/webkit_storage_browser_export.h" 20 #include "webkit/common/blob/shareable_file_reference.h" 21 #include "webkit/common/fileapi/file_system_types.h" 22 23 namespace base { 24 class SequencedTaskRunner; 25 class TimeTicks; 26 } 27 28 namespace quota { 29 class SpecialStoragePolicy; 30 } 31 32 class GURL; 33 34 namespace fileapi { 35 36 class FileSystemOperationContext; 37 class SandboxOriginDatabaseInterface; 38 class TimedTaskHelper; 39 40 // The overall implementation philosophy of this class is that partial failures 41 // should leave us with an intact database; we'd prefer to leak the occasional 42 // backing file than have a database entry whose backing file is missing. When 43 // doing FSCK operations, if you find a loose backing file with no reference, 44 // you may safely delete it. 45 // 46 // This class must be deleted on the FILE thread, because that's where 47 // DropDatabases needs to be called. 48 class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE ObfuscatedFileUtil 49 : public FileSystemFileUtil { 50 public: 51 // Origin enumerator interface. 52 // An instance of this interface is assumed to be called on the file thread. 53 class AbstractOriginEnumerator { 54 public: 55 virtual ~AbstractOriginEnumerator() {} 56 57 // Returns the next origin. Returns empty if there are no more origins. 58 virtual GURL Next() = 0; 59 60 // Returns the current origin's information. 61 virtual bool HasFileSystemType(FileSystemType type) const = 0; 62 }; 63 64 ObfuscatedFileUtil( 65 quota::SpecialStoragePolicy* special_storage_policy, 66 const base::FilePath& file_system_directory, 67 base::SequencedTaskRunner* file_task_runner); 68 virtual ~ObfuscatedFileUtil(); 69 70 // FileSystemFileUtil overrides. 71 virtual base::PlatformFileError CreateOrOpen( 72 FileSystemOperationContext* context, 73 const FileSystemURL& url, 74 int file_flags, 75 base::PlatformFile* file_handle, 76 bool* created) OVERRIDE; 77 virtual base::PlatformFileError Close( 78 FileSystemOperationContext* context, 79 base::PlatformFile file) OVERRIDE; 80 virtual base::PlatformFileError EnsureFileExists( 81 FileSystemOperationContext* context, 82 const FileSystemURL& url, bool* created) OVERRIDE; 83 virtual base::PlatformFileError CreateDirectory( 84 FileSystemOperationContext* context, 85 const FileSystemURL& url, 86 bool exclusive, 87 bool recursive) OVERRIDE; 88 virtual base::PlatformFileError GetFileInfo( 89 FileSystemOperationContext* context, 90 const FileSystemURL& url, 91 base::PlatformFileInfo* file_info, 92 base::FilePath* platform_file) OVERRIDE; 93 virtual scoped_ptr<AbstractFileEnumerator> CreateFileEnumerator( 94 FileSystemOperationContext* context, 95 const FileSystemURL& root_url) OVERRIDE; 96 virtual base::PlatformFileError GetLocalFilePath( 97 FileSystemOperationContext* context, 98 const FileSystemURL& file_system_url, 99 base::FilePath* local_path) OVERRIDE; 100 virtual base::PlatformFileError Touch( 101 FileSystemOperationContext* context, 102 const FileSystemURL& url, 103 const base::Time& last_access_time, 104 const base::Time& last_modified_time) OVERRIDE; 105 virtual base::PlatformFileError Truncate( 106 FileSystemOperationContext* context, 107 const FileSystemURL& url, 108 int64 length) OVERRIDE; 109 virtual base::PlatformFileError CopyOrMoveFile( 110 FileSystemOperationContext* context, 111 const FileSystemURL& src_url, 112 const FileSystemURL& dest_url, 113 bool copy) OVERRIDE; 114 virtual base::PlatformFileError CopyInForeignFile( 115 FileSystemOperationContext* context, 116 const base::FilePath& src_file_path, 117 const FileSystemURL& dest_url) OVERRIDE; 118 virtual base::PlatformFileError DeleteFile( 119 FileSystemOperationContext* context, 120 const FileSystemURL& url) OVERRIDE; 121 virtual base::PlatformFileError DeleteDirectory( 122 FileSystemOperationContext* context, 123 const FileSystemURL& url) OVERRIDE; 124 virtual webkit_blob::ScopedFile CreateSnapshotFile( 125 FileSystemOperationContext* context, 126 const FileSystemURL& url, 127 base::PlatformFileError* error, 128 base::PlatformFileInfo* file_info, 129 base::FilePath* platform_path) OVERRIDE; 130 131 // Same as the other CreateFileEnumerator, but with recursive support. 132 scoped_ptr<AbstractFileEnumerator> CreateFileEnumerator( 133 FileSystemOperationContext* context, 134 const FileSystemURL& root_url, 135 bool recursive); 136 137 // Returns true if the directory |url| is empty. 138 bool IsDirectoryEmpty( 139 FileSystemOperationContext* context, 140 const FileSystemURL& url); 141 142 // Gets the topmost directory specific to this origin and type. This will 143 // contain both the directory database's files and all the backing file 144 // subdirectories. 145 // Returns an empty path if the directory is undefined (e.g. because |type| 146 // is invalid). If the directory is defined, it will be returned, even if 147 // there is a file system error (e.g. the directory doesn't exist on disk and 148 // |create| is false). Callers should always check |error_code| to make sure 149 // the returned path is usable. 150 base::FilePath GetDirectoryForOriginAndType( 151 const GURL& origin, 152 FileSystemType type, 153 bool create, 154 base::PlatformFileError* error_code); 155 156 // Deletes the topmost directory specific to this origin and type. This will 157 // delete its directory database. 158 bool DeleteDirectoryForOriginAndType(const GURL& origin, FileSystemType type); 159 160 // TODO(ericu): This doesn't really feel like it belongs in this class. 161 // The previous version lives in FileSystemPathManager, but perhaps 162 // SandboxFileSystemBackend would be better? 163 static base::FilePath::StringType GetDirectoryNameForType( 164 FileSystemType type); 165 166 // This method and all methods of its returned class must be called only on 167 // the FILE thread. The caller is responsible for deleting the returned 168 // object. 169 AbstractOriginEnumerator* CreateOriginEnumerator(); 170 171 // Deletes a directory database from the database list in the ObfuscatedFSFU 172 // and destroys the database on the disk. 173 bool DestroyDirectoryDatabase(const GURL& origin, FileSystemType type); 174 175 // Computes a cost for storing a given file in the obfuscated FSFU. 176 // As the cost of a file is independent of the cost of its parent directories, 177 // this ignores all but the BaseName of the supplied path. In order to 178 // compute the cost of adding a multi-segment directory recursively, call this 179 // on each path segment and add the results. 180 static int64 ComputeFilePathCost(const base::FilePath& path); 181 182 void MaybePrepopulateDatabase(); 183 184 private: 185 typedef SandboxDirectoryDatabase::FileId FileId; 186 typedef SandboxDirectoryDatabase::FileInfo FileInfo; 187 188 friend class ObfuscatedFileEnumerator; 189 FRIEND_TEST_ALL_PREFIXES(ObfuscatedFileUtilTest, MaybeDropDatabasesAliveCase); 190 FRIEND_TEST_ALL_PREFIXES(ObfuscatedFileUtilTest, 191 MaybeDropDatabasesAlreadyDeletedCase); 192 FRIEND_TEST_ALL_PREFIXES(ObfuscatedFileUtilTest, 193 DestroyDirectoryDatabase_Isolated); 194 FRIEND_TEST_ALL_PREFIXES(ObfuscatedFileUtilTest, 195 GetDirectoryDatabase_Isolated); 196 FRIEND_TEST_ALL_PREFIXES(ObfuscatedFileUtilTest, 197 MigrationBackFromIsolated); 198 199 base::PlatformFileError GetFileInfoInternal( 200 SandboxDirectoryDatabase* db, 201 FileSystemOperationContext* context, 202 const GURL& origin, 203 FileSystemType type, 204 FileId file_id, 205 FileInfo* local_info, 206 base::PlatformFileInfo* file_info, 207 base::FilePath* platform_file_path); 208 209 // Creates a new file, both the underlying backing file and the entry in the 210 // database. |dest_file_info| is an in-out parameter. Supply the name and 211 // parent_id; data_path is ignored. On success, data_path will 212 // always be set to the relative path [from the root of the type-specific 213 // filesystem directory] of a NEW backing file, and handle, if supplied, will 214 // hold open PlatformFile for the backing file, which the caller is 215 // responsible for closing. If you supply a path in |source_path|, it will be 216 // used as a source from which to COPY data. 217 // Caveat: do not supply handle if you're also supplying a data path. It was 218 // easier not to support this, and no code has needed it so far, so it will 219 // DCHECK and handle will hold base::kInvalidPlatformFileValue. 220 base::PlatformFileError CreateFile( 221 FileSystemOperationContext* context, 222 const base::FilePath& source_file_path, 223 const GURL& dest_origin, 224 FileSystemType dest_type, 225 FileInfo* dest_file_info, 226 int file_flags, 227 base::PlatformFile* handle); 228 229 // This converts from a relative path [as is stored in the FileInfo.data_path 230 // field] to an absolute platform path that can be given to the native 231 // filesystem. 232 base::FilePath DataPathToLocalPath( 233 const GURL& origin, 234 FileSystemType type, 235 const base::FilePath& data_file_path); 236 237 std::string GetDirectoryDatabaseKey(const GURL& origin, FileSystemType type); 238 239 // This returns NULL if |create| flag is false and a filesystem does not 240 // exist for the given |origin_url| and |type|. 241 // For read operations |create| should be false. 242 SandboxDirectoryDatabase* GetDirectoryDatabase( 243 const GURL& origin_url, FileSystemType type, bool create); 244 245 // Gets the topmost directory specific to this origin. This will 246 // contain both the filesystem type subdirectories. 247 base::FilePath GetDirectoryForOrigin(const GURL& origin, 248 bool create, 249 base::PlatformFileError* error_code); 250 251 void InvalidateUsageCache(FileSystemOperationContext* context, 252 const GURL& origin, 253 FileSystemType type); 254 255 void MarkUsed(); 256 void DropDatabases(); 257 bool InitOriginDatabase(bool create); 258 259 base::PlatformFileError GenerateNewLocalPath( 260 SandboxDirectoryDatabase* db, 261 FileSystemOperationContext* context, 262 const GURL& origin, 263 FileSystemType type, 264 base::FilePath* local_path); 265 266 base::PlatformFileError CreateOrOpenInternal( 267 FileSystemOperationContext* context, 268 const FileSystemURL& url, 269 int file_flags, 270 base::PlatformFile* file_handle, 271 bool* created); 272 273 bool HasIsolatedStorage(const GURL& origin); 274 275 typedef std::map<std::string, SandboxDirectoryDatabase*> DirectoryMap; 276 DirectoryMap directories_; 277 scoped_ptr<SandboxOriginDatabaseInterface> origin_database_; 278 scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_; 279 base::FilePath file_system_directory_; 280 281 // Used to delete database after a certain period of inactivity. 282 int64 db_flush_delay_seconds_; 283 284 scoped_refptr<base::SequencedTaskRunner> file_task_runner_; 285 scoped_ptr<TimedTaskHelper> timer_; 286 287 // If this instance is initialized for an isolated partition, this should 288 // only see a single origin. 289 GURL isolated_origin_; 290 291 DISALLOW_COPY_AND_ASSIGN(ObfuscatedFileUtil); 292 }; 293 294 } // namespace fileapi 295 296 #endif // WEBKIT_BROWSER_FILEAPI_OBFUSCATED_FILE_UTIL_H_ 297