Home | History | Annotate | Download | only in fileapi
      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