Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(24)

Side by Side Diff: webkit/fileapi/external_mount_points.cc

Issue 11648027: Extract external file systems handling from isolated context. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013 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 #include "webkit/fileapi/external_mount_points.h"
6
7 #include "base/file_path.h"
8 #include "base/lazy_instance.h"
9 #include "base/path_service.h"
10 #include "base/stl_util.h"
11 #include "webkit/fileapi/remote_file_system_proxy.h"
12
13 namespace {
14
15 // Normalizes file path so it has normalized separators and ends with exactly
16 // one separator. Paths have to be normalized this way for use in
17 // GetVirtualPath method. Separators cannot be completely stripped, or
18 // GetVirtualPath could not working in some edge cases.
19 // For example, /a/b/c(1)/d would be erroneously resolved as c/d if the
20 // following mount points were registered: "/a/b/c", "/a/b/c(1)". (Note:
21 // "/a/b/c" < "/a/b/c(1)" < "/a/b/c/").
22 FilePath NormalizeFilePath(const FilePath& path) {
23 if (path.empty())
24 return path;
25
26 FilePath::StringType path_str = path.StripTrailingSeparators().value();
27 if (!FilePath::IsSeparator(path_str[path_str.length() - 1]))
28 path_str.append(FILE_PATH_LITERAL("/"));
29
30 return FilePath(path_str).NormalizePathSeparators();
31 }
32
33 // Wrapper around ref-counted ExternalMountPoints that will be used to lazily
34 // create and initialize LazyInstance system ExternalMountPoints.
35 class SystemMountPointsLazyWrapper {
36 public:
37 SystemMountPointsLazyWrapper()
38 : system_mount_points_(fileapi::ExternalMountPoints::CreateRefCounted()) {
39 RegisterDefaultMountPoints();
40 }
41
42 ~SystemMountPointsLazyWrapper() {}
43
44 fileapi::ExternalMountPoints* get() {
45 return system_mount_points_.get();
46 }
47
48 private:
49 void RegisterDefaultMountPoints() {
50 #if defined(OS_CHROMEOS)
51 // Add default system mount points.
52 system_mount_points_->RegisterFileSystem(
53 "archive",
54 fileapi::kFileSystemTypeNativeLocal,
55 FilePath(FILE_PATH_LITERAL("/media/archive")));
56 system_mount_points_->RegisterFileSystem(
57 "removable",
58 fileapi::kFileSystemTypeNativeLocal,
59 FilePath(FILE_PATH_LITERAL("/media/removable")));
60 system_mount_points_->RegisterFileSystem(
61 "oem",
62 fileapi::kFileSystemTypeRestrictedNativeLocal,
63 FilePath(FILE_PATH_LITERAL("/usr/share/oem")));
64
65 // TODO(tbarzic): Move this out of here.
66 FilePath home_path;
67 if (PathService::Get(base::DIR_HOME, &home_path)) {
68 system_mount_points_->RegisterFileSystem(
69 "Downloads",
70 fileapi::kFileSystemTypeNativeLocal,
71 home_path.AppendASCII("Downloads"));
72 }
73 #endif // defined(OS_CHROMEOS)
74 }
75
76 scoped_refptr<fileapi::ExternalMountPoints> system_mount_points_;
77 };
78
79 base::LazyInstance<SystemMountPointsLazyWrapper>::Leaky
80 g_external_mount_points = LAZY_INSTANCE_INITIALIZER;
81
82 } // namespace
83
84 namespace fileapi {
85
86 class ExternalMountPoints::Instance {
87 public:
88 Instance(FileSystemType type,
89 const FilePath& path,
90 RemoteFileSystemProxyInterface* remote_proxy);
91
92 ~Instance();
93
94 FileSystemType type() const { return type_; }
95 const FilePath& path() const { return path_; }
96 RemoteFileSystemProxyInterface* remote_proxy() const {
97 return remote_proxy_.get();
98 }
99
100 private:
101 const FileSystemType type_;
102 const FilePath path_;
103
104 // For file systems that have a remote file system proxy.
105 scoped_refptr<RemoteFileSystemProxyInterface> remote_proxy_;
106
107 DISALLOW_COPY_AND_ASSIGN(Instance);
108 };
109
110 ExternalMountPoints::Instance::Instance(FileSystemType type,
111 const FilePath& path,
112 RemoteFileSystemProxyInterface* proxy)
113 : type_(type),
114 path_(path.StripTrailingSeparators()),
115 remote_proxy_(proxy) {
116 DCHECK(!proxy || (kFileSystemTypeDrive == type_));
117 }
118
119 ExternalMountPoints::Instance::~Instance() {}
120
121 //--------------------------------------------------------------------------
122
123 // static
124 ExternalMountPoints* ExternalMountPoints::GetSystemInstance() {
125 return g_external_mount_points.Pointer()->get();
126 }
127
128 // static
129 scoped_refptr<ExternalMountPoints> ExternalMountPoints::CreateRefCounted() {
130 return new ExternalMountPoints();
131 }
132
133 bool ExternalMountPoints::RegisterFileSystem(
134 const std::string& mount_name,
135 FileSystemType type,
136 const FilePath& path) {
137 return RegisterRemoteFileSystem(mount_name, type, NULL, path);
138 }
139
140 bool ExternalMountPoints::RegisterRemoteFileSystem(
141 const std::string& mount_name,
142 FileSystemType type,
143 RemoteFileSystemProxyInterface* remote_proxy,
144 const FilePath& path_in) {
145 base::AutoLock locker(lock_);
146
147 FilePath path = NormalizeFilePath(path_in);
148 if (!ValidateNewMountPoint(mount_name, path))
149 return false;
150
151 instance_map_[mount_name] = new Instance(type, path, remote_proxy);
152 if (!path.empty())
153 path_to_name_map_.insert(std::make_pair(path, mount_name));
154 return true;
155 }
156
157 bool ExternalMountPoints::RevokeFileSystem(const std::string& mount_name) {
158 base::AutoLock locker(lock_);
159 NameToInstance::iterator found = instance_map_.find(mount_name);
160 if (found == instance_map_.end())
161 return false;
162 Instance* instance = found->second;
163 path_to_name_map_.erase(NormalizeFilePath(instance->path()));
164 delete found->second;
165 instance_map_.erase(found);
166 return true;
167 }
168
169 bool ExternalMountPoints::GetRegisteredPath(
170 const std::string& filesystem_id, FilePath* path) const {
171 DCHECK(path);
172 base::AutoLock locker(lock_);
173 NameToInstance::const_iterator found = instance_map_.find(filesystem_id);
174 if (found == instance_map_.end())
175 return false;
176 *path = found->second->path();
177 return true;
178 }
179
180 bool ExternalMountPoints::CrackVirtualPath(const FilePath& virtual_path,
181 std::string* mount_name,
182 FileSystemType* type,
183 FilePath* path) const {
184 DCHECK(mount_name);
185 DCHECK(path);
186
187 // The path should not contain any '..' references.
188 if (virtual_path.ReferencesParent())
189 return false;
190
191 // The virtual_path should comprise of <mount_name> and <relative_path> parts.
192 std::vector<FilePath::StringType> components;
193 virtual_path.GetComponents(&components);
194 if (components.size() < 1)
195 return false;
196
197 std::vector<FilePath::StringType>::iterator component_iter =
198 components.begin();
199 std::string maybe_mount_name = FilePath(*component_iter++).MaybeAsASCII();
200 if (maybe_mount_name.empty())
201 return false;
202
203 FilePath cracked_path;
204 {
205 base::AutoLock locker(lock_);
206 NameToInstance::const_iterator found_instance =
207 instance_map_.find(maybe_mount_name);
208 if (found_instance == instance_map_.end())
209 return false;
210
211 *mount_name = maybe_mount_name;
212 const Instance* instance = found_instance->second;
213 if (type)
214 *type = instance->type();
215 cracked_path = instance->path();
216 }
217
218 for (; component_iter != components.end(); ++component_iter)
219 cracked_path = cracked_path.Append(*component_iter);
220 *path = cracked_path;
221 return true;
222 }
223
224 RemoteFileSystemProxyInterface* ExternalMountPoints::GetRemoteFileSystemProxy(
225 const std::string& mount_name) const {
226 base::AutoLock locker(lock_);
227 NameToInstance::const_iterator found = instance_map_.find(mount_name);
228 if (found == instance_map_.end())
229 return NULL;
230 return found->second->remote_proxy();
231 }
232
233 void ExternalMountPoints::AddMountPointInfosTo(
234 std::vector<MountPointInfo>* mount_points) const {
235 base::AutoLock locker(lock_);
236 DCHECK(mount_points);
237 for (NameToInstance::const_iterator iter = instance_map_.begin();
238 iter != instance_map_.end(); ++iter) {
239 mount_points->push_back(MountPointInfo(iter->first, iter->second->path()));
240 }
241 }
242
243 bool ExternalMountPoints::GetVirtualPath(const FilePath& path_in,
244 FilePath* virtual_path) {
245 DCHECK(virtual_path);
246
247 base::AutoLock locker(lock_);
248
249 FilePath path = NormalizeFilePath(path_in);
250 std::map<FilePath, std::string>::reverse_iterator iter(
251 path_to_name_map_.upper_bound(path));
252 if (iter == path_to_name_map_.rend())
253 return false;
254
255 *virtual_path = CreateVirtualRootPath(iter->second);
256 if (iter->first == path)
257 return true;
258 return iter->first.AppendRelativePath(path, virtual_path);
259 }
260
261 FilePath ExternalMountPoints::CreateVirtualRootPath(
262 const std::string& mount_name) const {
263 return FilePath().AppendASCII(mount_name);
264 }
265
266 ExternalMountPoints::ExternalMountPoints() {}
267
268 ExternalMountPoints::~ExternalMountPoints() {
269 STLDeleteContainerPairSecondPointers(instance_map_.begin(),
270 instance_map_.end());
271 }
272
273 bool ExternalMountPoints::ValidateNewMountPoint(const std::string& mount_name,
274 const FilePath& path) {
275 lock_.AssertAcquired();
276
277 // Mount name must not be empty.
278 if (mount_name.empty())
279 return false;
280
281 // Verify there is no registered mount point with the same name.
282 NameToInstance::iterator found = instance_map_.find(mount_name);
283 if (found != instance_map_.end())
284 return false;
285
286 // Allow empty paths.
287 if (path.empty())
288 return true;
289
290 // Verify path is legal.
291 if (path.ReferencesParent() || !path.IsAbsolute())
292 return false;
293
294 // Check there the new path does not overlap with one of the existing ones.
295 std::map<FilePath, std::string>::reverse_iterator potential_parent(
296 path_to_name_map_.upper_bound(path));
297 if (potential_parent != path_to_name_map_.rend()) {
298 if (potential_parent->first == path ||
299 potential_parent->first.IsParent(path)) {
300 return false;
301 }
302 }
303
304 std::map<FilePath, std::string>::iterator potential_child =
305 path_to_name_map_.upper_bound(path);
306 if (potential_child == path_to_name_map_.end())
307 return true;
308 return !(potential_child->first == path) &&
309 !path.IsParent(potential_child->first);
310 }
311
312 ScopedExternalFileSystem::ScopedExternalFileSystem(
313 const std::string& mount_name,
314 FileSystemType type,
315 const FilePath& path)
316 : mount_name_(mount_name) {
317 ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
318 mount_name, type, path);
319 }
320
321 FilePath ScopedExternalFileSystem::GetVirtualRootPath() const {
322 return ExternalMountPoints::GetSystemInstance()->
323 CreateVirtualRootPath(mount_name_);
324 }
325
326 ScopedExternalFileSystem::~ScopedExternalFileSystem() {
327 ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(mount_name_);
328 }
329
330 } // namespace fileapi
331
OLDNEW
« no previous file with comments | « webkit/fileapi/external_mount_points.h ('k') | webkit/fileapi/external_mount_points_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698