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

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

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