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/browser/fileapi/external_mount_points.cc

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

Powered by Google App Engine
This is Rietveld 408576698