Chromium Code Reviews| Index: webkit/fileapi/isolated_context.cc |
| diff --git a/webkit/fileapi/isolated_context.cc b/webkit/fileapi/isolated_context.cc |
| index d590f442b010facdf51b823d288e86f7dba6fa32..db31bd464b24d55790f02c9e8dc5ae35314dede9 100644 |
| --- a/webkit/fileapi/isolated_context.cc |
| +++ b/webkit/fileapi/isolated_context.cc |
| @@ -8,6 +8,7 @@ |
| #include "base/basictypes.h" |
| #include "base/logging.h" |
| #include "base/rand_util.h" |
| +#include "base/stl_util.h" |
| #include "base/string_number_conversions.h" |
| #include "base/string_util.h" |
| #include "base/stringprintf.h" |
| @@ -51,11 +52,15 @@ IsolatedContext::FileInfo::FileInfo( |
| IsolatedContext::FileInfoSet::FileInfoSet() {} |
| IsolatedContext::FileInfoSet::~FileInfoSet() {} |
| -std::string IsolatedContext::FileInfoSet::AddPath( |
| - const FilePath& path) { |
| +bool IsolatedContext::FileInfoSet::AddPath( |
| + const FilePath& path, std::string* registered_name) { |
| + // The given path should not contain any '..' and should be absolute. |
| + if (path.ReferencesParent() || !path.IsAbsolute()) |
| + return false; |
| FilePath::StringType name = GetRegisterNameForPath(path); |
| std::string utf8name = FilePath(name).AsUTF8Unsafe(); |
| - bool inserted = fileset_.insert(FileInfo(utf8name, path)).second; |
| + FilePath normalized_path = path.NormalizePathSeparators(); |
| + bool inserted = fileset_.insert(FileInfo(utf8name, normalized_path)).second; |
| if (!inserted) { |
| int suffix = 1; |
| std::string basepart = FilePath(name).RemoveExtension().AsUTF8Unsafe(); |
| @@ -64,98 +69,122 @@ std::string IsolatedContext::FileInfoSet::AddPath( |
| utf8name = base::StringPrintf("%s (%d)", basepart.c_str(), suffix++); |
| if (!ext.empty()) |
| utf8name.append(ext); |
| - inserted = fileset_.insert(FileInfo(utf8name, path)).second; |
| + inserted = fileset_.insert(FileInfo(utf8name, normalized_path)).second; |
| } |
| } |
| - return utf8name; |
| + if (registered_name) |
| + *registered_name = utf8name; |
| + return true; |
| } |
| bool IsolatedContext::FileInfoSet::AddPathWithName( |
| const FilePath& path, const std::string& name) { |
| - return fileset_.insert(FileInfo(name, path)).second; |
| + // The given path should not contain any '..' and should be absolute. |
| + if (path.ReferencesParent() || !path.IsAbsolute()) |
| + return false; |
| + return fileset_.insert(FileInfo(name, path.NormalizePathSeparators())).second; |
| +} |
| + |
| +//-------------------------------------------------------------------------- |
| + |
| +IsolatedContext::Instance::Instance(FileSystemType type, |
| + const FileInfo& file_info) |
| + : type_(type), |
| + file_info_(file_info), |
| + ref_counts_(0) {} |
| + |
| +IsolatedContext::Instance::Instance(const std::set<FileInfo>& dragged_files) |
| + : type_(kFileSystemTypeDragged), |
| + dragged_files_(dragged_files), |
| + ref_counts_(0) {} |
| + |
| +IsolatedContext::Instance::~Instance() {} |
| + |
| +bool IsolatedContext::Instance::ResolvePathForName(const std::string& name, |
| + FilePath* path) { |
| + if (type_ != kFileSystemTypeDragged) { |
| + *path = file_info_.path; |
| + return (file_info_.name == name); |
|
tzik
2012/07/24 23:15:11
Could you drop '(' and ')'?
kinuko
2012/07/25 00:05:45
Done.
|
| + } |
| + std::set<FileInfo>::const_iterator found = dragged_files_.find( |
| + FileInfo(name, FilePath())); |
| + if (found == dragged_files_.end()) |
| + return false; |
| + *path = found->path; |
| + return true; |
| } |
| +//-------------------------------------------------------------------------- |
| + |
| // static |
| IsolatedContext* IsolatedContext::GetInstance() { |
| return g_isolated_context.Pointer(); |
| } |
| -std::string IsolatedContext::RegisterFileSystem(const FileInfoSet& files) { |
| +std::string IsolatedContext::RegisterDraggedFileSystem( |
| + const FileInfoSet& files) { |
| base::AutoLock locker(lock_); |
| std::string filesystem_id = GetNewFileSystemId(); |
| - // Stores name to fullpath map, as we store the name as a key in |
| - // the filesystem's toplevel entries. |
| - FileSet toplevels; |
| - for (std::set<FileInfo>::const_iterator iter = files.fileset().begin(); |
| - iter != files.fileset().end(); |
| - ++iter) { |
| - const FileInfo& info = *iter; |
| - // The given path should not contain any '..' and should be absolute. |
| - if (info.path.ReferencesParent() || !info.path.IsAbsolute()) |
| - continue; |
| - |
| - // Register the basename -> fullpath map. (We only expose the basename |
| - // part to the user scripts) |
| - FilePath fullpath = info.path.NormalizePathSeparators(); |
| - const bool inserted = toplevels.insert( |
| - FileInfo(info.name, fullpath)).second; |
| - DCHECK(inserted); |
| - } |
| - |
| - // TODO(kinuko): we may not want to register the file system if there're |
| - // no valid paths in the given file set. |
| - |
| - toplevel_map_[filesystem_id] = toplevels; |
| - |
| - // Each file system is created with refcount == 0. |
| - ref_counts_[filesystem_id] = 0; |
| - |
| + instance_map_[filesystem_id] = new Instance(files.fileset()); |
| return filesystem_id; |
| } |
| -std::string IsolatedContext::RegisterFileSystemForFile( |
| +std::string IsolatedContext::RegisterFileSystemForPath( |
| + FileSystemType type, |
| const FilePath& path, |
| std::string* register_name) { |
| - FileInfoSet files; |
| + DCHECK(!path.ReferencesParent() && path.IsAbsolute()); |
| + std::string name; |
| if (register_name && !register_name->empty()) { |
| - const bool added = files.AddPathWithName(path, *register_name); |
| - DCHECK(added); |
| + name = *register_name; |
| } else { |
| - std::string name = files.AddPath(path); |
| + name = FilePath(GetRegisterNameForPath(path)).AsUTF8Unsafe(); |
| if (register_name) |
| register_name->assign(name); |
| } |
| - return RegisterFileSystem(files); |
| + |
| + base::AutoLock locker(lock_); |
| + std::string filesystem_id = GetNewFileSystemId(); |
| + instance_map_[filesystem_id] = new Instance(type, FileInfo(name, path)); |
| + return filesystem_id; |
| } |
| void IsolatedContext::RevokeFileSystem(const std::string& filesystem_id) { |
| base::AutoLock locker(lock_); |
| - RevokeWithoutLocking(filesystem_id); |
| + IDToInstance::iterator found = instance_map_.find(filesystem_id); |
| + if (found == instance_map_.end()) |
| + return; |
| + delete found->second; |
| + instance_map_.erase(found); |
| } |
| void IsolatedContext::AddReference(const std::string& filesystem_id) { |
| base::AutoLock locker(lock_); |
| - DCHECK(ref_counts_.find(filesystem_id) != ref_counts_.end()); |
| - ref_counts_[filesystem_id]++; |
| + DCHECK(instance_map_.find(filesystem_id) != instance_map_.end()); |
| + instance_map_[filesystem_id]->AddRef(); |
| } |
| void IsolatedContext::RemoveReference(const std::string& filesystem_id) { |
| base::AutoLock locker(lock_); |
| // This could get called for non-existent filesystem if it has been |
| // already deleted by RevokeFileSystem. |
| - if (ref_counts_.find(filesystem_id) == ref_counts_.end()) |
| + IDToInstance::iterator found = instance_map_.find(filesystem_id); |
| + if (found == instance_map_.end()) |
| return; |
| - DCHECK(ref_counts_[filesystem_id] > 0); |
| - if (--ref_counts_[filesystem_id] == 0) |
| - RevokeWithoutLocking(filesystem_id); |
| + DCHECK(found->second->ref_counts() > 0); |
| + found->second->RemoveRef(); |
| + if (found->second->ref_counts() == 0) { |
| + delete found->second; |
| + instance_map_.erase(found); |
| + } |
| } |
| bool IsolatedContext::CrackIsolatedPath(const FilePath& virtual_path, |
| std::string* filesystem_id, |
| FileInfo* root_info, |
| - FilePath* platform_path) const { |
| + FilePath* path) const { |
| DCHECK(filesystem_id); |
| - DCHECK(platform_path); |
| + DCHECK(path); |
| // This should not contain any '..' references. |
| if (virtual_path.ReferencesParent()) |
| @@ -171,36 +200,48 @@ bool IsolatedContext::CrackIsolatedPath(const FilePath& virtual_path, |
| std::string fsid = FilePath(components[0]).MaybeAsASCII(); |
| if (fsid.empty()) |
| return false; |
| - IDToFileSet::const_iterator found_toplevels = toplevel_map_.find(fsid); |
| - if (found_toplevels == toplevel_map_.end()) |
| + IDToInstance::const_iterator found_instance = instance_map_.find(fsid); |
| + if (found_instance == instance_map_.end()) |
| return false; |
| *filesystem_id = fsid; |
| if (components.size() == 1) { |
| - platform_path->clear(); |
| + path->clear(); |
| return true; |
| } |
| - // components[1] should be a name of the dropped paths. |
| - FileSet::const_iterator found = found_toplevels->second.find( |
| - FileInfo(FilePath(components[1]).AsUTF8Unsafe(), FilePath())); |
| - if (found == found_toplevels->second.end()) |
| + // components[1] should be a name of the registered paths. |
| + FilePath cracked_path; |
| + std::string name = FilePath(components[1]).AsUTF8Unsafe(); |
| + if (!found_instance->second->ResolvePathForName(name, &cracked_path)) |
| return false; |
| if (root_info) |
| - *root_info = *found; |
| - FilePath path = found->path; |
| + *root_info = FileInfo(name, cracked_path); |
| for (size_t i = 2; i < components.size(); ++i) |
| - path = path.Append(components[i]); |
| - *platform_path = path; |
| + cracked_path = cracked_path.Append(components[i]); |
| + *path = cracked_path; |
| return true; |
| } |
| -bool IsolatedContext::GetRegisteredFileInfo( |
| +bool IsolatedContext::GetDraggedFileInfo( |
| const std::string& filesystem_id, std::vector<FileInfo>* files) const { |
| DCHECK(files); |
| base::AutoLock locker(lock_); |
| - IDToFileSet::const_iterator found = toplevel_map_.find(filesystem_id); |
| - if (found == toplevel_map_.end()) |
| + IDToInstance::const_iterator found = instance_map_.find(filesystem_id); |
| + if (found == instance_map_.end() || |
| + found->second->type() != kFileSystemTypeDragged) |
| return false; |
| - files->assign(found->second.begin(), found->second.end()); |
| + files->assign(found->second->dragged_files().begin(), |
| + found->second->dragged_files().end()); |
| + return true; |
| +} |
| + |
| +bool IsolatedContext::GetRegisteredPath( |
| + const std::string& filesystem_id, FilePath* path) const { |
| + DCHECK(path); |
| + base::AutoLock locker(lock_); |
| + IDToInstance::const_iterator found = instance_map_.find(filesystem_id); |
| + if (found == instance_map_.end() || found->second->type() == kFileSystemTypeDragged) |
| + return false; |
| + *path = found->second->file_info().path; |
| return true; |
| } |
| @@ -213,12 +254,8 @@ IsolatedContext::IsolatedContext() { |
| } |
| IsolatedContext::~IsolatedContext() { |
| -} |
| - |
| -void IsolatedContext::RevokeWithoutLocking( |
| - const std::string& filesystem_id) { |
| - toplevel_map_.erase(filesystem_id); |
| - ref_counts_.erase(filesystem_id); |
| + STLDeleteContainerPairSecondPointers(instance_map_.begin(), |
| + instance_map_.end()); |
| } |
| std::string IsolatedContext::GetNewFileSystemId() const { |
| @@ -228,7 +265,7 @@ std::string IsolatedContext::GetNewFileSystemId() const { |
| do { |
| base::RandBytes(random_data, sizeof(random_data)); |
| id = base::HexEncode(random_data, sizeof(random_data)); |
| - } while (toplevel_map_.find(id) != toplevel_map_.end()); |
| + } while (instance_map_.find(id) != instance_map_.end()); |
| return id; |
| } |