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 STORAGE_BROWSER_FILEAPI_ISOLATED_CONTEXT_H_
      6 #define STORAGE_BROWSER_FILEAPI_ISOLATED_CONTEXT_H_
      7 
      8 #include <map>
      9 #include <set>
     10 #include <string>
     11 #include <vector>
     12 
     13 #include "base/basictypes.h"
     14 #include "base/files/file_path.h"
     15 #include "base/lazy_instance.h"
     16 #include "base/memory/singleton.h"
     17 #include "base/synchronization/lock.h"
     18 #include "storage/browser/fileapi/mount_points.h"
     19 #include "storage/browser/storage_browser_export.h"
     20 #include "storage/common/fileapi/file_system_types.h"
     21 
     22 namespace storage {
     23 class FileSystemURL;
     24 }
     25 
     26 namespace storage {
     27 
     28 // Manages isolated filesystem mount points which have no well-known names
     29 // and are identified by a string 'filesystem ID', which usually just looks
     30 // like random value.
     31 // This type of filesystem can be created on the fly and may go away when it has
     32 // no references from renderers.
     33 // Files in an isolated filesystem are registered with corresponding names and
     34 // identified by a filesystem URL like:
     35 //
     36 //   filesystem:<origin>/isolated/<filesystem_id>/<name>/relative/path
     37 //
     38 // Some methods of this class are virtual just for mocking.
     39 //
     40 class STORAGE_EXPORT IsolatedContext : public MountPoints {
     41  public:
     42   class STORAGE_EXPORT FileInfoSet {
     43    public:
     44     FileInfoSet();
     45     ~FileInfoSet();
     46 
     47     // Add the given |path| to the set and populates |registered_name| with
     48     // the registered name assigned for the path. |path| needs to be
     49     // absolute and should not contain parent references.
     50     // Return false if the |path| is not valid and could not be added.
     51     bool AddPath(const base::FilePath& path, std::string* registered_name);
     52 
     53     // Add the given |path| with the |name|.
     54     // Return false if the |name| is already registered in the set or
     55     // is not valid and could not be added.
     56     bool AddPathWithName(const base::FilePath& path, const std::string& name);
     57 
     58     const std::set<MountPointInfo>& fileset() const { return fileset_; }
     59 
     60    private:
     61     std::set<MountPointInfo> fileset_;
     62   };
     63 
     64   // The instance is lazily created per browser process.
     65   static IsolatedContext* GetInstance();
     66 
     67   // Returns true if the given filesystem type is managed by IsolatedContext
     68   // (i.e. if the given |type| is Isolated or External).
     69   // TODO(kinuko): needs a better function name.
     70   static bool IsIsolatedType(FileSystemType type);
     71 
     72   // Registers a new isolated filesystem with the given FileInfoSet |files|
     73   // and returns the new filesystem_id.  The files are registered with their
     74   // register_name as their keys so that later we can resolve the full paths
     75   // for the given name.  We only expose the name and the ID for the
     76   // newly created filesystem to the renderer for the sake of security.
     77   //
     78   // The renderer will be sending filesystem requests with a virtual path like
     79   // '/<filesystem_id>/<registered_name>/<relative_path_from_the_dropped_path>'
     80   // for which we could crack in the browser process by calling
     81   // CrackIsolatedPath to get the full path.
     82   //
     83   // For example: if a dropped file has a path like '/a/b/foo' and we register
     84   // the path with the name 'foo' in the newly created filesystem.
     85   // Later if the context is asked to crack a virtual path like '/<fsid>/foo'
     86   // it can properly return the original path '/a/b/foo' by looking up the
     87   // internal mapping.  Similarly if a dropped entry is a directory and its
     88   // path is like '/a/b/dir' a virtual path like '/<fsid>/dir/foo' can be
     89   // cracked into '/a/b/dir/foo'.
     90   //
     91   // Note that the path in |fileset| that contains '..' or is not an
     92   // absolute path is skipped and is not registered.
     93   std::string RegisterDraggedFileSystem(const FileInfoSet& files);
     94 
     95   // Registers a new isolated filesystem for a given |path| of filesystem
     96   // |type| filesystem with |filesystem_id| and returns a new filesystem ID.
     97   // |path| must be an absolute path which has no parent references ('..').
     98   // If |register_name| is non-null and has non-empty string the path is
     99   // registered as the given |register_name|, otherwise it is populated
    100   // with the name internally assigned to the path.
    101   std::string RegisterFileSystemForPath(FileSystemType type,
    102                                         const std::string& filesystem_id,
    103                                         const base::FilePath& path,
    104                                         std::string* register_name);
    105 
    106   // Registers a virtual filesystem. This is different from
    107   // RegisterFileSystemForPath because register_name is required, and
    108   // cracked_path_prefix is allowed to be non-absolute.
    109   // |register_name| is required, since we cannot infer one from the path.
    110   // |cracked_path_prefix| has no parent references, but can be relative.
    111   std::string RegisterFileSystemForVirtualPath(
    112       FileSystemType type,
    113       const std::string& register_name,
    114       const base::FilePath& cracked_path_prefix);
    115 
    116   // Revokes all filesystem(s) registered for the given path.
    117   // This is assumed to be called when the registered path becomes
    118   // globally invalid, e.g. when a device for the path is detached.
    119   //
    120   // Note that this revokes the filesystem no matter how many references it has.
    121   // It is ok to call this for the path that has no associated filesystems.
    122   // Note that this only works for the filesystems registered by
    123   // |RegisterFileSystemForPath|.
    124   void RevokeFileSystemByPath(const base::FilePath& path);
    125 
    126   // Adds a reference to a filesystem specified by the given filesystem_id.
    127   void AddReference(const std::string& filesystem_id);
    128 
    129   // Removes a reference to a filesystem specified by the given filesystem_id.
    130   // If the reference count reaches 0 the isolated context gets destroyed.
    131   // It is OK to call this on the filesystem that has been already deleted
    132   // (e.g. by RevokeFileSystemByPath).
    133   void RemoveReference(const std::string& filesystem_id);
    134 
    135   // Returns a set of dragged MountPointInfos registered for the
    136   // |filesystem_id|.
    137   // The filesystem_id must be pointing to a dragged file system
    138   // (i.e. must be the one registered by RegisterDraggedFileSystem).
    139   // Returns false if the |filesystem_id| is not valid.
    140   bool GetDraggedFileInfo(const std::string& filesystem_id,
    141                           std::vector<MountPointInfo>* files) const;
    142 
    143   // MountPoints overrides.
    144   virtual bool HandlesFileSystemMountType(FileSystemType type) const OVERRIDE;
    145   virtual bool RevokeFileSystem(const std::string& filesystem_id) OVERRIDE;
    146   virtual bool GetRegisteredPath(const std::string& filesystem_id,
    147                                  base::FilePath* path) const OVERRIDE;
    148   virtual bool CrackVirtualPath(
    149       const base::FilePath& virtual_path,
    150       std::string* filesystem_id,
    151       FileSystemType* type,
    152       std::string* cracked_id,
    153       base::FilePath* path,
    154       FileSystemMountOption* mount_option) const OVERRIDE;
    155   virtual FileSystemURL CrackURL(const GURL& url) const OVERRIDE;
    156   virtual FileSystemURL CreateCrackedFileSystemURL(
    157       const GURL& origin,
    158       FileSystemType type,
    159       const base::FilePath& path) const OVERRIDE;
    160 
    161   // Returns the virtual root path that looks like /<filesystem_id>.
    162   base::FilePath CreateVirtualRootPath(const std::string& filesystem_id) const;
    163 
    164  private:
    165   friend struct base::DefaultLazyInstanceTraits<IsolatedContext>;
    166 
    167   // Represents each file system instance (defined in the .cc).
    168   class Instance;
    169 
    170   typedef std::map<std::string, Instance*> IDToInstance;
    171 
    172   // Reverse map from registered path to IDs.
    173   typedef std::map<base::FilePath, std::set<std::string> > PathToID;
    174 
    175   // Obtain an instance of this class via GetInstance().
    176   IsolatedContext();
    177   virtual ~IsolatedContext();
    178 
    179   // MountPoints overrides.
    180   virtual FileSystemURL CrackFileSystemURL(
    181       const FileSystemURL& url) const OVERRIDE;
    182 
    183   // Unregisters a file system of given |filesystem_id|. Must be called with
    184   // lock_ held.  Returns true if the file system is unregistered.
    185   bool UnregisterFileSystem(const std::string& filesystem_id);
    186 
    187   // Returns a new filesystem_id.  Called with lock.
    188   std::string GetNewFileSystemId() const;
    189 
    190   // This lock needs to be obtained when accessing the instance_map_.
    191   mutable base::Lock lock_;
    192 
    193   IDToInstance instance_map_;
    194   PathToID path_to_id_map_;
    195 
    196   DISALLOW_COPY_AND_ASSIGN(IsolatedContext);
    197 };
    198 
    199 }  // namespace storage
    200 
    201 #endif  // STORAGE_BROWSER_FILEAPI_ISOLATED_CONTEXT_H_
    202