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_OBFUSCATED_FILE_UTIL_H_ 6 #define STORAGE_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.h" 15 #include "base/files/file_path.h" 16 #include "base/files/file_util_proxy.h" 17 #include "base/gtest_prod_util.h" 18 #include "base/memory/scoped_ptr.h" 19 #include "storage/browser/fileapi/file_system_file_util.h" 20 #include "storage/browser/fileapi/file_system_url.h" 21 #include "storage/browser/fileapi/sandbox_directory_database.h" 22 #include "storage/browser/fileapi/sandbox_file_system_backend_delegate.h" 23 #include "storage/browser/storage_browser_export.h" 24 #include "storage/common/blob/shareable_file_reference.h" 25 #include "storage/common/fileapi/file_system_types.h" 26 27 namespace base { 28 class SequencedTaskRunner; 29 class TimeTicks; 30 } 31 32 namespace content { 33 class ObfuscatedFileUtilTest; 34 class QuotaBackendImplTest; 35 } 36 37 namespace storage { 38 class SpecialStoragePolicy; 39 } 40 41 class GURL; 42 43 namespace storage { 44 45 class FileSystemOperationContext; 46 class SandboxOriginDatabaseInterface; 47 class TimedTaskHelper; 48 49 // This file util stores directory information in LevelDB to obfuscate 50 // and to neutralize virtual file paths given by arbitrary apps. 51 // Files are stored with two-level isolation: per-origin and per-type. 52 // The isolation is done by storing data in separate directory partitions. 53 // For example, a file in Temporary file system for origin 'www.example.com' 54 // is stored in a different partition for a file in Persistent file system 55 // for the same origin, or for Temporary file system for another origin. 56 // 57 // * Per-origin directory name information is stored in a separate LevelDB, 58 // which is maintained by SandboxOriginDatabase. 59 // * Per-type directory name information is given by 60 // GetTypeStringForURLCallback that is given in CTOR. 61 // We use a small static mapping (e.g. 't' for Temporary type) for 62 // regular sandbox filesystems. 63 // 64 // The overall implementation philosophy of this class is that partial failures 65 // should leave us with an intact database; we'd prefer to leak the occasional 66 // backing file than have a database entry whose backing file is missing. When 67 // doing FSCK operations, if you find a loose backing file with no reference, 68 // you may safely delete it. 69 // 70 // This class must be deleted on the FILE thread, because that's where 71 // DropDatabases needs to be called. 72 class STORAGE_EXPORT_PRIVATE ObfuscatedFileUtil 73 : public FileSystemFileUtil { 74 public: 75 // Origin enumerator interface. 76 // An instance of this interface is assumed to be called on the file thread. 77 class AbstractOriginEnumerator { 78 public: 79 virtual ~AbstractOriginEnumerator() {} 80 81 // Returns the next origin. Returns empty if there are no more origins. 82 virtual GURL Next() = 0; 83 84 // Returns the current origin's information. 85 // |type_string| must be ascii string. 86 virtual bool HasTypeDirectory(const std::string& type_string) const = 0; 87 }; 88 89 typedef base::Callback<std::string(const FileSystemURL&)> 90 GetTypeStringForURLCallback; 91 92 // |get_type_string_for_url| is user-defined callback that should return 93 // a type string for the given FileSystemURL. The type string is used 94 // to provide per-type isolation in the sandboxed filesystem directory. 95 // Note that this method is called on file_task_runner. 96 // 97 // |known_type_strings| are known type string names that this file system 98 // should care about. 99 // This info is used to determine whether we could delete the entire 100 // origin directory or not in DeleteDirectoryForOriginAndType. If no directory 101 // for any known type exists the origin directory may get deleted when 102 // one origin/type pair is deleted. 103 // 104 ObfuscatedFileUtil(storage::SpecialStoragePolicy* special_storage_policy, 105 const base::FilePath& file_system_directory, 106 leveldb::Env* env_override, 107 base::SequencedTaskRunner* file_task_runner, 108 const GetTypeStringForURLCallback& get_type_string_for_url, 109 const std::set<std::string>& known_type_strings, 110 SandboxFileSystemBackendDelegate* sandbox_delegate); 111 virtual ~ObfuscatedFileUtil(); 112 113 // FileSystemFileUtil overrides. 114 virtual base::File CreateOrOpen( 115 FileSystemOperationContext* context, 116 const FileSystemURL& url, 117 int file_flags) OVERRIDE; 118 virtual base::File::Error EnsureFileExists( 119 FileSystemOperationContext* context, 120 const FileSystemURL& url, bool* created) OVERRIDE; 121 virtual base::File::Error CreateDirectory( 122 FileSystemOperationContext* context, 123 const FileSystemURL& url, 124 bool exclusive, 125 bool recursive) OVERRIDE; 126 virtual base::File::Error GetFileInfo( 127 FileSystemOperationContext* context, 128 const FileSystemURL& url, 129 base::File::Info* 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::File::Error GetLocalFilePath( 135 FileSystemOperationContext* context, 136 const FileSystemURL& file_system_url, 137 base::FilePath* local_path) OVERRIDE; 138 virtual base::File::Error 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::File::Error Truncate( 144 FileSystemOperationContext* context, 145 const FileSystemURL& url, 146 int64 length) OVERRIDE; 147 virtual base::File::Error CopyOrMoveFile( 148 FileSystemOperationContext* context, 149 const FileSystemURL& src_url, 150 const FileSystemURL& dest_url, 151 CopyOrMoveOption option, 152 bool copy) OVERRIDE; 153 virtual base::File::Error CopyInForeignFile( 154 FileSystemOperationContext* context, 155 const base::FilePath& src_file_path, 156 const FileSystemURL& dest_url) OVERRIDE; 157 virtual base::File::Error DeleteFile( 158 FileSystemOperationContext* context, 159 const FileSystemURL& url) OVERRIDE; 160 virtual base::File::Error DeleteDirectory( 161 FileSystemOperationContext* context, 162 const FileSystemURL& url) OVERRIDE; 163 virtual storage::ScopedFile CreateSnapshotFile( 164 FileSystemOperationContext* context, 165 const FileSystemURL& url, 166 base::File::Error* error, 167 base::File::Info* 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::File::Error* 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 content::ObfuscatedFileUtilTest; 233 friend class content::QuotaBackendImplTest; 234 235 // Helper method to create an obfuscated file util for regular 236 // (temporary, persistent) file systems. Used only for testing. 237 // Note: this is implemented in sandbox_file_system_backend_delegate.cc. 238 static ObfuscatedFileUtil* CreateForTesting( 239 storage::SpecialStoragePolicy* special_storage_policy, 240 const base::FilePath& file_system_directory, 241 leveldb::Env* env_override, 242 base::SequencedTaskRunner* file_task_runner); 243 244 base::FilePath GetDirectoryForURL( 245 const FileSystemURL& url, 246 bool create, 247 base::File::Error* error_code); 248 249 // This just calls get_type_string_for_url_ callback that is given in ctor. 250 std::string CallGetTypeStringForURL(const FileSystemURL& url); 251 252 base::File::Error GetFileInfoInternal( 253 SandboxDirectoryDatabase* db, 254 FileSystemOperationContext* context, 255 const FileSystemURL& url, 256 FileId file_id, 257 FileInfo* local_info, 258 base::File::Info* file_info, 259 base::FilePath* platform_file_path); 260 261 // Creates a new file, both the underlying backing file and the entry in the 262 // database. |dest_file_info| is an in-out parameter. Supply the name and 263 // parent_id; data_path is ignored. On success, data_path will 264 // always be set to the relative path [from the root of the type-specific 265 // filesystem directory] of a NEW backing file. Returns the new file. 266 base::File CreateAndOpenFile( 267 FileSystemOperationContext* context, 268 const FileSystemURL& dest_url, 269 FileInfo* dest_file_info, 270 int file_flags); 271 272 // The same as CreateAndOpenFile except that a file is not returned and if a 273 // path is provided in |source_path|, it will be used as a source from which 274 // to COPY data. 275 base::File::Error CreateFile( 276 FileSystemOperationContext* context, 277 const base::FilePath& source_file_path, 278 const FileSystemURL& dest_url, 279 FileInfo* dest_file_info); 280 281 // Updates |db| and |dest_file_info| at the end of creating a new file. 282 base::File::Error CommitCreateFile( 283 const base::FilePath& root, 284 const base::FilePath& local_path, 285 SandboxDirectoryDatabase* db, 286 FileInfo* dest_file_info); 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::File::Error* 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::File::Error GenerateNewLocalPath( 322 SandboxDirectoryDatabase* db, 323 FileSystemOperationContext* context, 324 const FileSystemURL& url, 325 base::FilePath* root, 326 base::FilePath* local_path); 327 328 base::File CreateOrOpenInternal( 329 FileSystemOperationContext* context, 330 const FileSystemURL& url, 331 int file_flags); 332 333 bool HasIsolatedStorage(const GURL& origin); 334 335 typedef std::map<std::string, SandboxDirectoryDatabase*> DirectoryMap; 336 DirectoryMap directories_; 337 scoped_ptr<SandboxOriginDatabaseInterface> origin_database_; 338 scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_; 339 base::FilePath file_system_directory_; 340 leveldb::Env* env_override_; 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 storage 358 359 #endif // STORAGE_BROWSER_FILEAPI_OBFUSCATED_FILE_UTIL_H_ 360