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

Side by Side Diff: webkit/fileapi/isolated_context.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
« no previous file with comments | « webkit/fileapi/isolated_context.h ('k') | webkit/fileapi/isolated_context_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "webkit/fileapi/isolated_context.h"
6
7 #include "base/basictypes.h"
8 #include "base/files/file_path.h"
9 #include "base/logging.h"
10 #include "base/rand_util.h"
11 #include "base/stl_util.h"
12 #include "base/string_util.h"
13 #include "base/stringprintf.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "webkit/fileapi/file_system_url.h"
16
17 namespace fileapi {
18
19 namespace {
20
21 base::FilePath::StringType GetRegisterNameForPath(const base::FilePath& path) {
22 // If it's not a root path simply return a base name.
23 if (path.DirName() != path)
24 return path.BaseName().value();
25
26 #if defined(FILE_PATH_USES_DRIVE_LETTERS)
27 base::FilePath::StringType name;
28 for (size_t i = 0;
29 i < path.value().size() && !base::FilePath::IsSeparator(path.value()[i]) ;
30 ++i) {
31 if (path.value()[i] == L':') {
32 name.append(L"_drive");
33 break;
34 }
35 name.append(1, path.value()[i]);
36 }
37 return name;
38 #else
39 return FILE_PATH_LITERAL("<root>");
40 #endif
41 }
42
43 bool IsSinglePathIsolatedFileSystem(FileSystemType type) {
44 switch (type) {
45 // As of writing dragged file system is the only filesystem
46 // which could have multiple top-level paths.
47 case kFileSystemTypeDragged:
48 return false;
49
50 case kFileSystemTypeUnknown:
51 NOTREACHED();
52 return true;
53
54 default:
55 return true;
56 }
57 NOTREACHED();
58 return true;
59 }
60
61 static base::LazyInstance<IsolatedContext>::Leaky g_isolated_context =
62 LAZY_INSTANCE_INITIALIZER;
63
64 } // namespace
65
66 IsolatedContext::FileInfoSet::FileInfoSet() {}
67 IsolatedContext::FileInfoSet::~FileInfoSet() {}
68
69 bool IsolatedContext::FileInfoSet::AddPath(
70 const base::FilePath& path, std::string* registered_name) {
71 // The given path should not contain any '..' and should be absolute.
72 if (path.ReferencesParent() || !path.IsAbsolute())
73 return false;
74 base::FilePath::StringType name = GetRegisterNameForPath(path);
75 std::string utf8name = base::FilePath(name).AsUTF8Unsafe();
76 base::FilePath normalized_path = path.NormalizePathSeparators();
77 bool inserted =
78 fileset_.insert(MountPointInfo(utf8name, normalized_path)).second;
79 if (!inserted) {
80 int suffix = 1;
81 std::string basepart = base::FilePath(name).RemoveExtension().AsUTF8Unsafe() ;
82 std::string ext = base::FilePath(base::FilePath(name).Extension()).AsUTF8Uns afe();
83 while (!inserted) {
84 utf8name = base::StringPrintf("%s (%d)", basepart.c_str(), suffix++);
85 if (!ext.empty())
86 utf8name.append(ext);
87 inserted =
88 fileset_.insert(MountPointInfo(utf8name, normalized_path)).second;
89 }
90 }
91 if (registered_name)
92 *registered_name = utf8name;
93 return true;
94 }
95
96 bool IsolatedContext::FileInfoSet::AddPathWithName(
97 const base::FilePath& path, const std::string& name) {
98 // The given path should not contain any '..' and should be absolute.
99 if (path.ReferencesParent() || !path.IsAbsolute())
100 return false;
101 return fileset_.insert(
102 MountPointInfo(name, path.NormalizePathSeparators())).second;
103 }
104
105 //--------------------------------------------------------------------------
106
107 class IsolatedContext::Instance {
108 public:
109 enum PathType {
110 PLATFORM_PATH,
111 VIRTUAL_PATH
112 };
113
114 // For a single-path isolated file system, which could be registered by
115 // IsolatedContext::RegisterFileSystemForPath() or
116 // IsolatedContext::RegisterFileSystemForVirtualPath().
117 // Most of isolated file system contexts should be of this type.
118 Instance(FileSystemType type, const MountPointInfo& file_info,
119 PathType path_type);
120
121 // For a multi-paths isolated file system. As of writing only file system
122 // type which could have multi-paths is Dragged file system, and
123 // could be registered by IsolatedContext::RegisterDraggedFileSystem().
124 Instance(FileSystemType type, const std::set<MountPointInfo>& files);
125
126 ~Instance();
127
128 FileSystemType type() const { return type_; }
129 const MountPointInfo& file_info() const { return file_info_; }
130 const std::set<MountPointInfo>& files() const { return files_; }
131 int ref_counts() const { return ref_counts_; }
132
133 void AddRef() { ++ref_counts_; }
134 void RemoveRef() { --ref_counts_; }
135
136 bool ResolvePathForName(const std::string& name, base::FilePath* path) const;
137
138 // Returns true if the instance is a single-path instance.
139 bool IsSinglePathInstance() const;
140
141 private:
142 const FileSystemType type_;
143
144 // For single-path instance.
145 const MountPointInfo file_info_;
146 const PathType path_type_;
147
148 // For multiple-path instance (e.g. dragged file system).
149 const std::set<MountPointInfo> files_;
150
151 // Reference counts. Note that an isolated filesystem is created with ref==0
152 // and will get deleted when the ref count reaches <=0.
153 int ref_counts_;
154
155 DISALLOW_COPY_AND_ASSIGN(Instance);
156 };
157
158 IsolatedContext::Instance::Instance(FileSystemType type,
159 const MountPointInfo& file_info,
160 Instance::PathType path_type)
161 : type_(type),
162 file_info_(file_info),
163 path_type_(path_type),
164 ref_counts_(0) {
165 DCHECK(IsSinglePathIsolatedFileSystem(type_));
166 }
167
168 IsolatedContext::Instance::Instance(FileSystemType type,
169 const std::set<MountPointInfo>& files)
170 : type_(type),
171 path_type_(PLATFORM_PATH),
172 files_(files),
173 ref_counts_(0) {
174 DCHECK(!IsSinglePathIsolatedFileSystem(type_));
175 }
176
177 IsolatedContext::Instance::~Instance() {}
178
179 bool IsolatedContext::Instance::ResolvePathForName(const std::string& name,
180 base::FilePath* path) const {
181 if (IsSinglePathIsolatedFileSystem(type_)) {
182 switch (path_type_) {
183 case PLATFORM_PATH:
184 *path = file_info_.path;
185 break;
186 case VIRTUAL_PATH:
187 *path = base::FilePath();
188 break;
189 default:
190 NOTREACHED();
191 }
192
193 return file_info_.name == name;
194 }
195 std::set<MountPointInfo>::const_iterator found = files_.find(
196 MountPointInfo(name, base::FilePath()));
197 if (found == files_.end())
198 return false;
199 *path = found->path;
200 return true;
201 }
202
203 bool IsolatedContext::Instance::IsSinglePathInstance() const {
204 return IsSinglePathIsolatedFileSystem(type_);
205 }
206
207 //--------------------------------------------------------------------------
208
209 // static
210 IsolatedContext* IsolatedContext::GetInstance() {
211 return g_isolated_context.Pointer();
212 }
213
214 // static
215 bool IsolatedContext::IsIsolatedType(FileSystemType type) {
216 return type == kFileSystemTypeIsolated || type == kFileSystemTypeExternal;
217 }
218
219 std::string IsolatedContext::RegisterDraggedFileSystem(
220 const FileInfoSet& files) {
221 base::AutoLock locker(lock_);
222 std::string filesystem_id = GetNewFileSystemId();
223 instance_map_[filesystem_id] = new Instance(
224 kFileSystemTypeDragged, files.fileset());
225 return filesystem_id;
226 }
227
228 std::string IsolatedContext::RegisterFileSystemForPath(
229 FileSystemType type,
230 const base::FilePath& path_in,
231 std::string* register_name) {
232 base::FilePath path(path_in.NormalizePathSeparators());
233 if (path.ReferencesParent() || !path.IsAbsolute())
234 return std::string();
235 std::string name;
236 if (register_name && !register_name->empty()) {
237 name = *register_name;
238 } else {
239 name = base::FilePath(GetRegisterNameForPath(path)).AsUTF8Unsafe();
240 if (register_name)
241 register_name->assign(name);
242 }
243
244 base::AutoLock locker(lock_);
245 std::string filesystem_id = GetNewFileSystemId();
246 instance_map_[filesystem_id] = new Instance(type, MountPointInfo(name, path),
247 Instance::PLATFORM_PATH);
248 path_to_id_map_[path].insert(filesystem_id);
249 return filesystem_id;
250 }
251
252 std::string IsolatedContext::RegisterFileSystemForVirtualPath(
253 FileSystemType type,
254 const std::string& register_name,
255 const base::FilePath& cracked_path_prefix) {
256 base::AutoLock locker(lock_);
257 base::FilePath path(cracked_path_prefix.NormalizePathSeparators());
258 if (path.ReferencesParent())
259 return std::string();
260 std::string filesystem_id = GetNewFileSystemId();
261 instance_map_[filesystem_id] = new Instance(
262 type,
263 MountPointInfo(register_name, cracked_path_prefix),
264 Instance::VIRTUAL_PATH);
265 path_to_id_map_[path].insert(filesystem_id);
266 return filesystem_id;
267 }
268
269 bool IsolatedContext::HandlesFileSystemMountType(FileSystemType type) const {
270 return type == kFileSystemTypeIsolated;
271 }
272
273 bool IsolatedContext::RevokeFileSystem(const std::string& filesystem_id) {
274 base::AutoLock locker(lock_);
275 return UnregisterFileSystem(filesystem_id);
276 }
277
278 bool IsolatedContext::GetRegisteredPath(
279 const std::string& filesystem_id, base::FilePath* path) const {
280 DCHECK(path);
281 base::AutoLock locker(lock_);
282 IDToInstance::const_iterator found = instance_map_.find(filesystem_id);
283 if (found == instance_map_.end() || !found->second->IsSinglePathInstance())
284 return false;
285 *path = found->second->file_info().path;
286 return true;
287 }
288
289 bool IsolatedContext::CrackVirtualPath(const base::FilePath& virtual_path,
290 std::string* id_or_name,
291 FileSystemType* type,
292 base::FilePath* path) const {
293 DCHECK(id_or_name);
294 DCHECK(path);
295
296 // This should not contain any '..' references.
297 if (virtual_path.ReferencesParent())
298 return false;
299
300 // The virtual_path should comprise <id_or_name> and <relative_path> parts.
301 std::vector<base::FilePath::StringType> components;
302 virtual_path.GetComponents(&components);
303 if (components.size() < 1)
304 return false;
305 std::vector<base::FilePath::StringType>::iterator component_iter =
306 components.begin();
307 std::string fsid = base::FilePath(*component_iter++).MaybeAsASCII();
308 if (fsid.empty())
309 return false;
310
311 base::FilePath cracked_path;
312 {
313 base::AutoLock locker(lock_);
314 IDToInstance::const_iterator found_instance = instance_map_.find(fsid);
315 if (found_instance == instance_map_.end())
316 return false;
317 *id_or_name = fsid;
318 const Instance* instance = found_instance->second;
319 if (type)
320 *type = instance->type();
321
322 if (component_iter == components.end()) {
323 // The virtual root case.
324 path->clear();
325 return true;
326 }
327
328 // *component_iter should be a name of the registered path.
329 std::string name = base::FilePath(*component_iter++).AsUTF8Unsafe();
330 if (!instance->ResolvePathForName(name, &cracked_path))
331 return false;
332 }
333
334 for (; component_iter != components.end(); ++component_iter)
335 cracked_path = cracked_path.Append(*component_iter);
336 *path = cracked_path;
337 return true;
338 }
339
340 FileSystemURL IsolatedContext::CrackURL(const GURL& url) const {
341 FileSystemURL filesystem_url = FileSystemURL(url);
342 if (!filesystem_url.is_valid())
343 return FileSystemURL();
344 return CrackFileSystemURL(filesystem_url);
345 }
346
347 FileSystemURL IsolatedContext::CreateCrackedFileSystemURL(
348 const GURL& origin,
349 FileSystemType type,
350 const base::FilePath& path) const {
351 return CrackFileSystemURL(FileSystemURL(origin, type, path));
352 }
353
354 void IsolatedContext::RevokeFileSystemByPath(const base::FilePath& path_in) {
355 base::AutoLock locker(lock_);
356 base::FilePath path(path_in.NormalizePathSeparators());
357 PathToID::iterator ids_iter = path_to_id_map_.find(path);
358 if (ids_iter == path_to_id_map_.end())
359 return;
360 std::set<std::string>& ids = ids_iter->second;
361 for (std::set<std::string>::iterator iter = ids.begin();
362 iter != ids.end(); ++iter) {
363 IDToInstance::iterator found = instance_map_.find(*iter);
364 if (found != instance_map_.end()) {
365 delete found->second;
366 instance_map_.erase(found);
367 }
368 }
369 path_to_id_map_.erase(ids_iter);
370 }
371
372 void IsolatedContext::AddReference(const std::string& filesystem_id) {
373 base::AutoLock locker(lock_);
374 DCHECK(instance_map_.find(filesystem_id) != instance_map_.end());
375 instance_map_[filesystem_id]->AddRef();
376 }
377
378 void IsolatedContext::RemoveReference(const std::string& filesystem_id) {
379 base::AutoLock locker(lock_);
380 // This could get called for non-existent filesystem if it has been
381 // already deleted by RevokeFileSystemByPath.
382 IDToInstance::iterator found = instance_map_.find(filesystem_id);
383 if (found == instance_map_.end())
384 return;
385 Instance* instance = found->second;
386 DCHECK_GT(instance->ref_counts(), 0);
387 instance->RemoveRef();
388 if (instance->ref_counts() == 0) {
389 bool deleted = UnregisterFileSystem(filesystem_id);
390 DCHECK(deleted);
391 }
392 }
393
394 bool IsolatedContext::GetDraggedFileInfo(
395 const std::string& filesystem_id,
396 std::vector<MountPointInfo>* files) const {
397 DCHECK(files);
398 base::AutoLock locker(lock_);
399 IDToInstance::const_iterator found = instance_map_.find(filesystem_id);
400 if (found == instance_map_.end() ||
401 found->second->type() != kFileSystemTypeDragged)
402 return false;
403 files->assign(found->second->files().begin(),
404 found->second->files().end());
405 return true;
406 }
407
408 base::FilePath IsolatedContext::CreateVirtualRootPath(
409 const std::string& filesystem_id) const {
410 return base::FilePath().AppendASCII(filesystem_id);
411 }
412
413 IsolatedContext::IsolatedContext() {
414 }
415
416 IsolatedContext::~IsolatedContext() {
417 STLDeleteContainerPairSecondPointers(instance_map_.begin(),
418 instance_map_.end());
419 }
420
421 FileSystemURL IsolatedContext::CrackFileSystemURL(
422 const FileSystemURL& url) const {
423 if (!HandlesFileSystemMountType(url.type()))
424 return FileSystemURL();
425
426 std::string mount_name;
427 FileSystemType cracked_type;
428 base::FilePath cracked_path;
429 if (!CrackVirtualPath(url.path(), &mount_name, &cracked_type, &cracked_path))
430 return FileSystemURL();
431
432 return FileSystemURL(
433 url.origin(), url.mount_type(), url.virtual_path(),
434 !url.filesystem_id().empty() ? url.filesystem_id() : mount_name,
435 cracked_type, cracked_path, mount_name);
436 }
437
438 bool IsolatedContext::UnregisterFileSystem(const std::string& filesystem_id) {
439 lock_.AssertAcquired();
440 IDToInstance::iterator found = instance_map_.find(filesystem_id);
441 if (found == instance_map_.end())
442 return false;
443 Instance* instance = found->second;
444 if (instance->IsSinglePathInstance()) {
445 PathToID::iterator ids_iter = path_to_id_map_.find(
446 instance->file_info().path);
447 DCHECK(ids_iter != path_to_id_map_.end());
448 ids_iter->second.erase(filesystem_id);
449 if (ids_iter->second.empty())
450 path_to_id_map_.erase(ids_iter);
451 }
452 delete found->second;
453 instance_map_.erase(found);
454 return true;
455 }
456
457 std::string IsolatedContext::GetNewFileSystemId() const {
458 // Returns an arbitrary random string which must be unique in the map.
459 lock_.AssertAcquired();
460 uint32 random_data[4];
461 std::string id;
462 do {
463 base::RandBytes(random_data, sizeof(random_data));
464 id = base::HexEncode(random_data, sizeof(random_data));
465 } while (instance_map_.find(id) != instance_map_.end());
466 return id;
467 }
468
469 } // namespace fileapi
OLDNEW
« no previous file with comments | « webkit/fileapi/isolated_context.h ('k') | webkit/fileapi/isolated_context_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698