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 27namespace base { 28class SequencedTaskRunner; 29class TimeTicks; 30} 31 32namespace content { 33class ObfuscatedFileUtilTest; 34class QuotaBackendImplTest; 35} 36 37namespace storage { 38class SpecialStoragePolicy; 39} 40 41class GURL; 42 43namespace storage { 44 45class FileSystemOperationContext; 46class SandboxOriginDatabaseInterface; 47class 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. 72class 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