| Index: webkit/fileapi/isolated_context.cc
|
| diff --git a/webkit/fileapi/isolated_context.cc b/webkit/fileapi/isolated_context.cc
|
| index d590f442b010facdf51b823d288e86f7dba6fa32..d57b8737612de894da11e8f4c10dda4077a705e1 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,120 @@ 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) {}
|
| +
|
| +bool IsolatedContext::Instance::ResolvePathForName(const std::string& name,
|
| + FilePath* path) {
|
| + if (type_ != kFileSystemTypeDragged) {
|
| + *path = file_info_.path;
|
| + return (file_info_.name == name);
|
| + }
|
| + 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 = GetRegisterNameForPath(path);
|
| 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 +198,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 +252,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 +263,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;
|
| }
|
|
|
|
|