summaryrefslogtreecommitdiffstats
path: root/storage/browser/fileapi/isolated_context.h
blob: ff1f58e0344b5647363b63e9466c7716736d585c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef STORAGE_BROWSER_FILEAPI_ISOLATED_CONTEXT_H_
#define STORAGE_BROWSER_FILEAPI_ISOLATED_CONTEXT_H_

#include <map>
#include <set>
#include <string>
#include <vector>

#include "base/basictypes.h"
#include "base/files/file_path.h"
#include "base/lazy_instance.h"
#include "base/memory/singleton.h"
#include "base/synchronization/lock.h"
#include "storage/browser/fileapi/mount_points.h"
#include "storage/browser/storage_browser_export.h"
#include "storage/common/fileapi/file_system_types.h"

namespace storage {
class FileSystemURL;
}

namespace storage {

// Manages isolated filesystem mount points which have no well-known names
// and are identified by a string 'filesystem ID', which usually just looks
// like random value.
// This type of filesystem can be created on the fly and may go away when it has
// no references from renderers.
// Files in an isolated filesystem are registered with corresponding names and
// identified by a filesystem URL like:
//
//   filesystem:<origin>/isolated/<filesystem_id>/<name>/relative/path
//
// Some methods of this class are virtual just for mocking.
//
class STORAGE_EXPORT IsolatedContext : public MountPoints {
 public:
  class STORAGE_EXPORT FileInfoSet {
   public:
    FileInfoSet();
    ~FileInfoSet();

    // Add the given |path| to the set and populates |registered_name| with
    // the registered name assigned for the path. |path| needs to be
    // absolute and should not contain parent references.
    // Return false if the |path| is not valid and could not be added.
    bool AddPath(const base::FilePath& path, std::string* registered_name);

    // Add the given |path| with the |name|.
    // Return false if the |name| is already registered in the set or
    // is not valid and could not be added.
    bool AddPathWithName(const base::FilePath& path, const std::string& name);

    const std::set<MountPointInfo>& fileset() const { return fileset_; }

   private:
    std::set<MountPointInfo> fileset_;
  };

  // The instance is lazily created per browser process.
  static IsolatedContext* GetInstance();

  // Returns true if the given filesystem type is managed by IsolatedContext
  // (i.e. if the given |type| is Isolated or External).
  // TODO(kinuko): needs a better function name.
  static bool IsIsolatedType(FileSystemType type);

  // Registers a new isolated filesystem with the given FileInfoSet |files|
  // and returns the new filesystem_id.  The files are registered with their
  // register_name as their keys so that later we can resolve the full paths
  // for the given name.  We only expose the name and the ID for the
  // newly created filesystem to the renderer for the sake of security.
  //
  // The renderer will be sending filesystem requests with a virtual path like
  // '/<filesystem_id>/<registered_name>/<relative_path_from_the_dropped_path>'
  // for which we could crack in the browser process by calling
  // CrackIsolatedPath to get the full path.
  //
  // For example: if a dropped file has a path like '/a/b/foo' and we register
  // the path with the name 'foo' in the newly created filesystem.
  // Later if the context is asked to crack a virtual path like '/<fsid>/foo'
  // it can properly return the original path '/a/b/foo' by looking up the
  // internal mapping.  Similarly if a dropped entry is a directory and its
  // path is like '/a/b/dir' a virtual path like '/<fsid>/dir/foo' can be
  // cracked into '/a/b/dir/foo'.
  //
  // Note that the path in |fileset| that contains '..' or is not an
  // absolute path is skipped and is not registered.
  std::string RegisterDraggedFileSystem(const FileInfoSet& files);

  // Registers a new isolated filesystem for a given |path| of filesystem
  // |type| filesystem with |filesystem_id| and returns a new filesystem ID.
  // |path| must be an absolute path which has no parent references ('..').
  // If |register_name| is non-null and has non-empty string the path is
  // registered as the given |register_name|, otherwise it is populated
  // with the name internally assigned to the path.
  std::string RegisterFileSystemForPath(FileSystemType type,
                                        const std::string& filesystem_id,
                                        const base::FilePath& path,
                                        std::string* register_name);

  // Registers a virtual filesystem. This is different from
  // RegisterFileSystemForPath because register_name is required, and
  // cracked_path_prefix is allowed to be non-absolute.
  // |register_name| is required, since we cannot infer one from the path.
  // |cracked_path_prefix| has no parent references, but can be relative.
  std::string RegisterFileSystemForVirtualPath(
      FileSystemType type,
      const std::string& register_name,
      const base::FilePath& cracked_path_prefix);

  // Revokes all filesystem(s) registered for the given path.
  // This is assumed to be called when the registered path becomes
  // globally invalid, e.g. when a device for the path is detached.
  //
  // Note that this revokes the filesystem no matter how many references it has.
  // It is ok to call this for the path that has no associated filesystems.
  // Note that this only works for the filesystems registered by
  // |RegisterFileSystemForPath|.
  void RevokeFileSystemByPath(const base::FilePath& path);

  // Adds a reference to a filesystem specified by the given filesystem_id.
  void AddReference(const std::string& filesystem_id);

  // Removes a reference to a filesystem specified by the given filesystem_id.
  // If the reference count reaches 0 the isolated context gets destroyed.
  // It is OK to call this on the filesystem that has been already deleted
  // (e.g. by RevokeFileSystemByPath).
  void RemoveReference(const std::string& filesystem_id);

  // Returns a set of dragged MountPointInfos registered for the
  // |filesystem_id|.
  // The filesystem_id must be pointing to a dragged file system
  // (i.e. must be the one registered by RegisterDraggedFileSystem).
  // Returns false if the |filesystem_id| is not valid.
  bool GetDraggedFileInfo(const std::string& filesystem_id,
                          std::vector<MountPointInfo>* files) const;

  // MountPoints overrides.
  bool HandlesFileSystemMountType(FileSystemType type) const override;
  bool RevokeFileSystem(const std::string& filesystem_id) override;
  bool GetRegisteredPath(const std::string& filesystem_id,
                         base::FilePath* path) const override;
  bool CrackVirtualPath(const base::FilePath& virtual_path,
                        std::string* filesystem_id,
                        FileSystemType* type,
                        std::string* cracked_id,
                        base::FilePath* path,
                        FileSystemMountOption* mount_option) const override;
  FileSystemURL CrackURL(const GURL& url) const override;
  FileSystemURL CreateCrackedFileSystemURL(
      const GURL& origin,
      FileSystemType type,
      const base::FilePath& path) const override;

  // Returns the virtual root path that looks like /<filesystem_id>.
  base::FilePath CreateVirtualRootPath(const std::string& filesystem_id) const;

 private:
  friend struct base::DefaultLazyInstanceTraits<IsolatedContext>;

  // Represents each file system instance (defined in the .cc).
  class Instance;

  typedef std::map<std::string, Instance*> IDToInstance;

  // Reverse map from registered path to IDs.
  typedef std::map<base::FilePath, std::set<std::string> > PathToID;

  // Obtain an instance of this class via GetInstance().
  IsolatedContext();
  ~IsolatedContext() override;

  // MountPoints overrides.
  FileSystemURL CrackFileSystemURL(const FileSystemURL& url) const override;

  // Unregisters a file system of given |filesystem_id|. Must be called with
  // lock_ held.  Returns true if the file system is unregistered.
  bool UnregisterFileSystem(const std::string& filesystem_id);

  // Returns a new filesystem_id.  Called with lock.
  std::string GetNewFileSystemId() const;

  // This lock needs to be obtained when accessing the instance_map_.
  mutable base::Lock lock_;

  IDToInstance instance_map_;
  PathToID path_to_id_map_;

  DISALLOW_COPY_AND_ASSIGN(IsolatedContext);
};

}  // namespace storage

#endif  // STORAGE_BROWSER_FILEAPI_ISOLATED_CONTEXT_H_