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.
5 #ifndef WEBKIT_FILEAPI_ISOLATED_CONTEXT_H_
6 #define WEBKIT_FILEAPI_ISOLATED_CONTEXT_H_
13 #include "base/basictypes.h"
14 #include "base/file_path.h"
15 #include "base/memory/singleton.h"
16 #include "base/synchronization/lock.h"
17 #include "base/lazy_instance.h"
18 #include "webkit/fileapi/fileapi_export.h"
22 // Manages isolated filename namespaces. A namespace is simply defined as a
23 // set of file paths and corresponding filesystem ID. This context class is
24 // a singleton and access to the context is thread-safe (protected with a
26 // Some methods of this class are virtual just for mocking.
27 class FILEAPI_EXPORT IsolatedContext
{
29 struct FILEAPI_EXPORT FileInfo
{
31 FileInfo(const std::string
& name
, const FilePath
& path
);
33 // The name to be used to register the file. The registered file can
34 // be referred by a virtual path /<filesystem_id>/<name>.
35 // The name should NOT contain a path separator '/'.
38 // The path of the file.
42 bool operator<(const FileInfo
& that
) const { return name
< that
.name
; }
45 class FILEAPI_EXPORT FileInfoSet
{
50 // Add the given |path| to the set and returns the registered name
51 // assigned for the path.
52 std::string
AddPath(const FilePath
& path
);
54 // Add the given |path| with the |name|.
55 // Returns false if the |name| is already registered in the set.
56 bool AddPathWithName(const FilePath
& path
, const std::string
& name
);
58 const std::set
<FileInfo
>& fileset() const { return fileset_
; }
61 std::set
<FileInfo
> fileset_
;
64 // The instance is lazily created per browser process.
65 static IsolatedContext
* GetInstance();
67 // Registers a new isolated filesystem with the given FileInfoSet |files|
68 // and returns the new filesystem_id. The files are registered with their
69 // register_name as their keys so that later we can resolve the full paths
70 // for the given name. We only expose the name and the ID for the
71 // newly created filesystem to the renderer for the sake of security.
73 // The renderer will be sending filesystem requests with a virtual path like
74 // '/<filesystem_id>/<registered_name>/<relative_path_from_the_dropped_path>'
75 // for which we could crack in the browser process by calling
76 // CrackIsolatedPath to get the full path.
78 // For example: if a dropped file has a path like '/a/b/foo' and we register
79 // the path with the name 'foo' in the newly created filesystem.
80 // Later if the context is asked to crack a virtual path like '/<fsid>/foo'
81 // it can properly return the original path '/a/b/foo' by looking up the
82 // internal mapping. Similarly if a dropped entry is a directory and its
83 // path is like '/a/b/dir' a virtual path like '/<fsid>/dir/foo' can be
84 // cracked into '/a/b/dir/foo'.
86 // Note that the path in |fileset| that contains '..' or is not an
87 // absolute path is skipped and is not registerred.
88 std::string
RegisterFileSystem(const FileInfoSet
& files
);
90 // Registers a new isolated filesystem for a given |path|.
91 // If |register_name| is non-null and has non-empty string the path is
92 // registered as the given |register_name|, otherwise it is populated
93 // with the name internally assigned to the path.
94 std::string
RegisterFileSystemForFile(const FilePath
& path
,
95 std::string
* register_name
);
97 // Revokes filesystem specified by the given filesystem_id.
98 // Note that this revokes the filesystem no matter how many references it has.
99 // It is ok to call this on the filesystem that has been already deleted
100 // (if its reference count had reached 0).
101 void RevokeFileSystem(const std::string
& filesystem_id
);
103 // Adds a reference to a filesystem specified by the given filesystem_id.
104 void AddReference(const std::string
& filesystem_id
);
106 // Removes a reference to a filesystem specified by the given filesystem_id.
107 // If the reference count reaches 0 the isolated context gets destroyed.
108 // It is ok to call this on the filesystem that has been already deleted
109 // (e.g. by RevokeFileSystem).
110 void RemoveReference(const std::string
& filesystem_id
);
112 // Cracks the given |virtual_path| (which should look like
113 // "/<filesystem_id>/<registered_name>/<relative_path>") and populates
114 // the |filesystem_id| and |platform_path| if the embedded <filesystem_id>
115 // is registerred to this context. |root_path| is also populated to have
116 // the registered root (toplevel) file info for the |virtual_path|.
118 // Returns false if the given virtual_path or the cracked filesystem_id
121 // Note that |root_info| and |platform_path| are set to empty paths if
122 // |virtual_path| has no <relative_path> part (i.e. pointing to
123 // the virtual root).
124 bool CrackIsolatedPath(const FilePath
& virtual_path
,
125 std::string
* filesystem_id
,
127 FilePath
* platform_path
) const;
129 // Returns a set of FileInfo registered for the |filesystem_id|.
130 // Returns false if the |filesystem_id| is not valid.
131 bool GetRegisteredFileInfo(const std::string
& filesystem_id
,
132 std::vector
<FileInfo
>* files
) const;
134 // Returns the virtual root path that looks like /<filesystem_id>.
135 FilePath
CreateVirtualRootPath(const std::string
& filesystem_id
) const;
138 friend struct base::DefaultLazyInstanceTraits
<IsolatedContext
>;
140 // Maps from filesystem id to a path conversion map for top-level entries.
141 typedef std::set
<FileInfo
> FileSet
;
142 typedef std::map
<std::string
, FileSet
> IDToFileSet
;
144 // Obtain an instance of this class via GetInstance().
148 // Removes the given filesystem without locking.
149 // (The caller must hold a lock)
150 void RevokeWithoutLocking(const std::string
& filesystem_id
);
152 // Returns a new filesystem_id. Called with lock.
153 std::string
GetNewFileSystemId() const;
155 // This lock needs to be obtained when accessing the toplevel_map_.
156 mutable base::Lock lock_
;
158 // Maps the toplevel entries to the filesystem id.
159 IDToFileSet toplevel_map_
;
161 // Reference counts. Note that an isolated filesystem is created with ref==0.
162 // and will get deleted when the ref count reaches <=0.
163 std::map
<std::string
, int> ref_counts_
;
165 DISALLOW_COPY_AND_ASSIGN(IsolatedContext
);
168 } // namespace fileapi
170 #endif // WEBKIT_FILEAPI_ISOLATED_CONTEXT_H_