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_ISOLATED_CONTEXT_H_ 6#define WEBKIT_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 "webkit/browser/fileapi/mount_points.h" 19#include "webkit/browser/webkit_storage_browser_export.h" 20#include "webkit/common/fileapi/file_system_types.h" 21 22namespace fileapi { 23class FileSystemURL; 24} 25 26namespace fileapi { 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// 40class WEBKIT_STORAGE_BROWSER_EXPORT IsolatedContext : public MountPoints { 41 public: 42 class WEBKIT_STORAGE_BROWSER_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 fileapi 200 201#endif // WEBKIT_BROWSER_FILEAPI_ISOLATED_CONTEXT_H_ 202