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 <set> 10 #include <string> 11 #include <vector> 12 13 #include "base/callback_forward.h" 14 #include "base/files/file_path.h" 15 #include "base/files/file_util_proxy.h" 16 #include "base/gtest_prod_util.h" 17 #include "base/memory/scoped_ptr.h" 18 #include "base/platform_file.h" 19 #include "webkit/browser/fileapi/file_system_file_util.h" 20 #include "webkit/browser/fileapi/file_system_url.h" 21 #include "webkit/browser/fileapi/sandbox_directory_database.h" 22 #include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h" 23 #include "webkit/browser/webkit_storage_browser_export.h" 24 #include "webkit/common/blob/shareable_file_reference.h" 25 #include "webkit/common/fileapi/file_system_types.h" 26 27 namespace base { 28 class SequencedTaskRunner; 29 class TimeTicks; 30 } 31 32 namespace quota { 33 class SpecialStoragePolicy; 34 } 35 36 class GURL; 37 38 namespace fileapi { 39 40 class FileSystemOperationContext; 41 class SandboxOriginDatabaseInterface; 42 class TimedTaskHelper; 43 44 // This file util stores directory information in LevelDB to obfuscate 45 // and to neutralize virtual file paths given by arbitrary apps. 46 // Files are stored with two-level isolation: per-origin and per-type. 47 // The isolation is done by storing data in separate directory partitions. 48 // For example, a file in Temporary file system for origin 'www.example.com' 49 // is stored in a different partition for a file in Persistent file system 50 // for the same origin, or for Temporary file system for another origin. 51 // 52 // * Per-origin directory name information is stored in a separate LevelDB, 53 // which is maintained by SandboxOriginDatabase. 54 // * Per-type directory name information is given by 55 // GetTypeStringForURLCallback that is given in CTOR. 56 // We use a small static mapping (e.g. 't' for Temporary type) for 57 // regular sandbox filesystems. 58 // 59 // The overall implementation philosophy of this class is that partial failures 60 // should leave us with an intact database; we'd prefer to leak the occasional 61 // backing file than have a database entry whose backing file is missing. When 62 // doing FSCK operations, if you find a loose backing file with no reference, 63 // you may safely delete it. 64 // 65 // This class must be deleted on the FILE thread, because that's where 66 // DropDatabases needs to be called. 67 class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE ObfuscatedFileUtil 68 : public FileSystemFileUtil { 69 public: 70 // Origin enumerator interface. 71 // An instance of this interface is assumed to be called on the file thread. 72 class AbstractOriginEnumerator { 73 public: 74 virtual ~AbstractOriginEnumerator() {} 75 76 // Returns the next origin. Returns empty if there are no more origins. 77 virtual GURL Next() = 0; 78 79 // Returns the current origin's information. 80 // |type_string| must be ascii string. 81 virtual bool HasTypeDirectory(const std::string& type_string) const = 0; 82 }; 83 84 typedef base::Callback<std::string(const FileSystemURL&)> 85 GetTypeStringForURLCallback; 86 87 // |get_type_string_for_url| is user-defined callback that should return 88 // a type string for the given FileSystemURL. The type string is used 89 // to provide per-type isolation in the sandboxed filesystem directory. 90 // Note that this method is called on file_task_runner. 91 // 92 // |known_type_strings| are known type string names that this file system 93 // should care about. 94 // This info is used to determine whether we could delete the entire 95 // origin directory or not in DeleteDirectoryForOriginAndType. If no directory 96 // for any known type exists the origin directory may get deleted when 97 // one origin/type pair is deleted. 98 // 99 ObfuscatedFileUtil( 100 quota::SpecialStoragePolicy* special_storage_policy, 101 const base::FilePath& file_system_directory, 102 base::SequencedTaskRunner* file_task_runner, 103 const GetTypeStringForURLCallback& get_type_string_for_url, 104 const std::set<std::string>& known_type_strings, 105 SandboxFileSystemBackendDelegate* sandbox_delegate); 106 virtual ~ObfuscatedFileUtil(); 107 108 // FileSystemFileUtil overrides. 109 virtual base::PlatformFileError CreateOrOpen( 110 FileSystemOperationContext* context, 111 const FileSystemURL& url, 112 int file_flags, 113 base::PlatformFile* file_handle, 114 bool* created) OVERRIDE; 115 virtual base::PlatformFileError Close( 116 FileSystemOperationContext* context, 117 base::PlatformFile file) OVERRIDE; 118 virtual base::PlatformFileError EnsureFileExists( 119 FileSystemOperationContext* context, 120 const FileSystemURL& url, bool* created) OVERRIDE; 121 virtual base::PlatformFileError CreateDirectory( 122 FileSystemOperationContext* context, 123 const FileSystemURL& url, 124 bool exclusive, 125 bool recursive) OVERRIDE; 126 virtual base::PlatformFileError GetFileInfo( 127 FileSystemOperationContext* context, 128 const FileSystemURL& url, 129 base::PlatformFileInfo* file_info, 130 base::FilePath* platform_file) OVERRIDE; 131 virtual scoped_ptr<AbstractFileEnumerator> CreateFileEnumerator( 132 FileSystemOperationContext* context, 133 const FileSystemURL& root_url) OVERRIDE; 134 virtual base::PlatformFileError GetLocalFilePath( 135 FileSystemOperationContext* context, 136 const FileSystemURL& file_system_url, 137 base::FilePath* local_path) OVERRIDE; 138 virtual base::PlatformFileError Touch( 139 FileSystemOperationContext* context, 140 const FileSystemURL& url, 141 const base::Time& last_access_time, 142 const base::Time& last_modified_time) OVERRIDE; 143 virtual base::PlatformFileError Truncate( 144 FileSystemOperationContext* context, 145 const FileSystemURL& url, 146 int64 length) OVERRIDE; 147 virtual base::PlatformFileError CopyOrMoveFile( 148 FileSystemOperationContext* context, 149 const FileSystemURL& src_url, 150 const FileSystemURL& dest_url, 151 CopyOrMoveOption option, 152 bool copy) OVERRIDE; 153 virtual base::PlatformFileError CopyInForeignFile( 154 FileSystemOperationContext* context, 155 const base::FilePath& src_file_path, 156 const FileSystemURL& dest_url) OVERRIDE; 157 virtual base::PlatformFileError DeleteFile( 158 FileSystemOperationContext* context, 159 const FileSystemURL& url) OVERRIDE; 160 virtual base::PlatformFileError DeleteDirectory( 161 FileSystemOperationContext* context, 162 const FileSystemURL& url) OVERRIDE; 163 virtual webkit_blob::ScopedFile CreateSnapshotFile( 164 FileSystemOperationContext* context, 165 const FileSystemURL& url, 166 base::PlatformFileError* error, 167 base::PlatformFileInfo* file_info, 168 base::FilePath* platform_path) OVERRIDE; 169 170 // Same as the other CreateFileEnumerator, but with recursive support. 171 scoped_ptr<AbstractFileEnumerator> CreateFileEnumerator( 172 FileSystemOperationContext* context, 173 const FileSystemURL& root_url, 174 bool recursive); 175 176 // Returns true if the directory |url| is empty. 177 bool IsDirectoryEmpty( 178 FileSystemOperationContext* context, 179 const FileSystemURL& url); 180 181 // Gets the topmost directory specific to this origin and type. This will 182 // contain both the directory database's files and all the backing file 183 // subdirectories. 184 // Returns the topmost origin directory if |type_string| is empty. 185 // Returns an empty path if the directory is undefined. 186 // If the directory is defined, it will be returned, even if 187 // there is a file system error (e.g. the directory doesn't exist on disk and 188 // |create| is false). Callers should always check |error_code| to make sure 189 // the returned path is usable. 190 base::FilePath GetDirectoryForOriginAndType( 191 const GURL& origin, 192 const std::string& type_string, 193 bool create, 194 base::PlatformFileError* error_code); 195 196 // Deletes the topmost directory specific to this origin and type. This will 197 // delete its directory database. 198 // Deletes the topmost origin directory if |type_string| is empty. 199 bool DeleteDirectoryForOriginAndType( 200 const GURL& origin, 201 const std::string& type_string); 202 203 // This method and all methods of its returned class must be called only on 204 // the FILE thread. The caller is responsible for deleting the returned 205 // object. 206 AbstractOriginEnumerator* CreateOriginEnumerator(); 207 208 // Deletes a directory database from the database list in the ObfuscatedFSFU 209 // and destroys the database on the disk. 210 bool DestroyDirectoryDatabase(const GURL& origin, 211 const std::string& type_string); 212 213 // Computes a cost for storing a given file in the obfuscated FSFU. 214 // As the cost of a file is independent of the cost of its parent directories, 215 // this ignores all but the BaseName of the supplied path. In order to 216 // compute the cost of adding a multi-segment directory recursively, call this 217 // on each path segment and add the results. 218 static int64 ComputeFilePathCost(const base::FilePath& path); 219 220 // Tries to prepopulate directory database for the given type strings. 221 // This tries from the first one in the given type_strings and stops 222 // once it succeeds to do so for one database (i.e. it prepopulates 223 // at most one database). 224 void MaybePrepopulateDatabase( 225 const std::vector<std::string>& type_strings_to_prepopulate); 226 227 private: 228 typedef SandboxDirectoryDatabase::FileId FileId; 229 typedef SandboxDirectoryDatabase::FileInfo FileInfo; 230 231 friend class ObfuscatedFileEnumerator; 232 friend class ObfuscatedFileUtilTest; 233 friend class QuotaBackendImplTest; 234 FRIEND_TEST_ALL_PREFIXES(ObfuscatedFileUtilTest, MaybeDropDatabasesAliveCase); 235 FRIEND_TEST_ALL_PREFIXES(ObfuscatedFileUtilTest, 236 MaybeDropDatabasesAlreadyDeletedCase); 237 FRIEND_TEST_ALL_PREFIXES(ObfuscatedFileUtilTest, 238 DestroyDirectoryDatabase_Isolated); 239 FRIEND_TEST_ALL_PREFIXES(ObfuscatedFileUtilTest, 240 GetDirectoryDatabase_Isolated); 241 FRIEND_TEST_ALL_PREFIXES(ObfuscatedFileUtilTest, 242 MigrationBackFromIsolated); 243 244 // Helper method to create an obfuscated file util for regular 245 // (temporary, persistent) file systems. Used only for testing. 246 // Note: this is implemented in sandbox_file_system_backend_delegate.cc. 247 static ObfuscatedFileUtil* CreateForTesting( 248 quota::SpecialStoragePolicy* special_storage_policy, 249 const base::FilePath& file_system_directory, 250 base::SequencedTaskRunner* file_task_runner); 251 252 base::FilePath GetDirectoryForURL( 253 const FileSystemURL& url, 254 bool create, 255 base::PlatformFileError* error_code); 256 257 // This just calls get_type_string_for_url_ callback that is given in ctor. 258 std::string CallGetTypeStringForURL(const FileSystemURL& url); 259 260 base::PlatformFileError GetFileInfoInternal( 261 SandboxDirectoryDatabase* db, 262 FileSystemOperationContext* context, 263 const FileSystemURL& url, 264 FileId file_id, 265 FileInfo* local_info, 266 base::PlatformFileInfo* file_info, 267 base::FilePath* platform_file_path); 268 269 // Creates a new file, both the underlying backing file and the entry in the 270 // database. |dest_file_info| is an in-out parameter. Supply the name and 271 // parent_id; data_path is ignored. On success, data_path will 272 // always be set to the relative path [from the root of the type-specific 273 // filesystem directory] of a NEW backing file, and handle, if supplied, will 274 // hold open PlatformFile for the backing file, which the caller is 275 // responsible for closing. If you supply a path in |source_path|, it will be 276 // used as a source from which to COPY data. 277 // Caveat: do not supply handle if you're also supplying a data path. It was 278 // easier not to support this, and no code has needed it so far, so it will 279 // DCHECK and handle will hold base::kInvalidPlatformFileValue. 280 base::PlatformFileError CreateFile( 281 FileSystemOperationContext* context, 282 const base::FilePath& source_file_path, 283 const FileSystemURL& dest_url, 284 FileInfo* dest_file_info, 285 int file_flags, 286 base::PlatformFile* handle); 287 288 // This converts from a relative path [as is stored in the FileInfo.data_path 289 // field] to an absolute platform path that can be given to the native 290 // filesystem. 291 base::FilePath DataPathToLocalPath( 292 const FileSystemURL& url, 293 const base::FilePath& data_file_path); 294 295 std::string GetDirectoryDatabaseKey(const GURL& origin, 296 const std::string& type_string); 297 298 // This returns NULL if |create| flag is false and a filesystem does not 299 // exist for the given |url|. 300 // For read operations |create| should be false. 301 SandboxDirectoryDatabase* GetDirectoryDatabase(const FileSystemURL& url, 302 bool create); 303 304 // Gets the topmost directory specific to this origin. This will 305 // contain both the filesystem type subdirectories. 306 base::FilePath GetDirectoryForOrigin(const GURL& origin, 307 bool create, 308 base::PlatformFileError* error_code); 309 310 void InvalidateUsageCache(FileSystemOperationContext* context, 311 const GURL& origin, 312 FileSystemType type); 313 314 void MarkUsed(); 315 void DropDatabases(); 316 317 // Initializes the origin database. |origin_hint| may be used as a hint 318 // for initializing database if it's not empty. 319 bool InitOriginDatabase(const GURL& origin_hint, bool create); 320 321 base::PlatformFileError GenerateNewLocalPath( 322 SandboxDirectoryDatabase* db, 323 FileSystemOperationContext* context, 324 const FileSystemURL& url, 325 base::FilePath* local_path); 326 327 base::PlatformFileError CreateOrOpenInternal( 328 FileSystemOperationContext* context, 329 const FileSystemURL& url, 330 int file_flags, 331 base::PlatformFile* file_handle, 332 bool* created); 333 334 bool HasIsolatedStorage(const GURL& origin); 335 336 typedef std::map<std::string, SandboxDirectoryDatabase*> DirectoryMap; 337 DirectoryMap directories_; 338 scoped_ptr<SandboxOriginDatabaseInterface> origin_database_; 339 scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_; 340 base::FilePath file_system_directory_; 341 342 // Used to delete database after a certain period of inactivity. 343 int64 db_flush_delay_seconds_; 344 345 scoped_refptr<base::SequencedTaskRunner> file_task_runner_; 346 scoped_ptr<TimedTaskHelper> timer_; 347 348 GetTypeStringForURLCallback get_type_string_for_url_; 349 std::set<std::string> known_type_strings_; 350 351 // Not owned. 352 SandboxFileSystemBackendDelegate* sandbox_delegate_; 353 354 DISALLOW_COPY_AND_ASSIGN(ObfuscatedFileUtil); 355 }; 356 357 } // namespace fileapi 358 359 #endif // WEBKIT_BROWSER_FILEAPI_OBFUSCATED_FILE_UTIL_H_ 360