| Index: webkit/fileapi/isolated_context.cc
|
| diff --git a/webkit/fileapi/isolated_context.cc b/webkit/fileapi/isolated_context.cc
|
| index 20ca9a7711a275816df0d42550f6939845903289..d590f442b010facdf51b823d288e86f7dba6fa32 100644
|
| --- a/webkit/fileapi/isolated_context.cc
|
| +++ b/webkit/fileapi/isolated_context.cc
|
| @@ -4,42 +4,102 @@
|
|
|
| #include "webkit/fileapi/isolated_context.h"
|
|
|
| +#include "base/file_path.h"
|
| #include "base/basictypes.h"
|
| #include "base/logging.h"
|
| #include "base/rand_util.h"
|
| #include "base/string_number_conversions.h"
|
| #include "base/string_util.h"
|
| +#include "base/stringprintf.h"
|
|
|
| namespace fileapi {
|
|
|
| +namespace {
|
| +
|
| +FilePath::StringType GetRegisterNameForPath(const FilePath& path) {
|
| + // If it's not a root path simply return a base name.
|
| + if (path.DirName() != path)
|
| + return path.BaseName().value();
|
| +
|
| +#if defined(FILE_PATH_USES_DRIVE_LETTERS)
|
| + FilePath::StringType name;
|
| + for (size_t i = 0;
|
| + i < path.value().size() && !FilePath::IsSeparator(path.value()[i]);
|
| + ++i) {
|
| + if (path.value()[i] == L':') {
|
| + name.append(L"_drive");
|
| + break;
|
| + }
|
| + name.append(1, path.value()[i]);
|
| + }
|
| + return name;
|
| +#else
|
| + return FILE_PATH_LITERAL("<root>");
|
| +#endif
|
| +}
|
| +
|
| +}
|
| +
|
| static base::LazyInstance<IsolatedContext>::Leaky g_isolated_context =
|
| LAZY_INSTANCE_INITIALIZER;
|
|
|
| +IsolatedContext::FileInfo::FileInfo() {}
|
| +IsolatedContext::FileInfo::FileInfo(
|
| + const std::string& name, const FilePath& path)
|
| + : name(name), path(path) {}
|
| +
|
| +IsolatedContext::FileInfoSet::FileInfoSet() {}
|
| +IsolatedContext::FileInfoSet::~FileInfoSet() {}
|
| +
|
| +std::string IsolatedContext::FileInfoSet::AddPath(
|
| + const FilePath& path) {
|
| + FilePath::StringType name = GetRegisterNameForPath(path);
|
| + std::string utf8name = FilePath(name).AsUTF8Unsafe();
|
| + bool inserted = fileset_.insert(FileInfo(utf8name, path)).second;
|
| + if (!inserted) {
|
| + int suffix = 1;
|
| + std::string basepart = FilePath(name).RemoveExtension().AsUTF8Unsafe();
|
| + std::string ext = FilePath(FilePath(name).Extension()).AsUTF8Unsafe();
|
| + while (!inserted) {
|
| + utf8name = base::StringPrintf("%s (%d)", basepart.c_str(), suffix++);
|
| + if (!ext.empty())
|
| + utf8name.append(ext);
|
| + inserted = fileset_.insert(FileInfo(utf8name, path)).second;
|
| + }
|
| + }
|
| + return utf8name;
|
| +}
|
| +
|
| +bool IsolatedContext::FileInfoSet::AddPathWithName(
|
| + const FilePath& path, const std::string& name) {
|
| + return fileset_.insert(FileInfo(name, path)).second;
|
| +}
|
| +
|
| // static
|
| IsolatedContext* IsolatedContext::GetInstance() {
|
| return g_isolated_context.Pointer();
|
| }
|
|
|
| -std::string IsolatedContext::RegisterIsolatedFileSystem(
|
| - const std::set<FilePath>& files) {
|
| +std::string IsolatedContext::RegisterFileSystem(const FileInfoSet& files) {
|
| base::AutoLock locker(lock_);
|
| std::string filesystem_id = GetNewFileSystemId();
|
| - // Stores basename to fullpath map, as we store the basenames as
|
| + // Stores name to fullpath map, as we store the name as a key in
|
| // the filesystem's toplevel entries.
|
| - PathMap toplevels;
|
| - for (std::set<FilePath>::const_iterator iter = files.begin();
|
| - iter != files.end(); ++iter) {
|
| + 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 (iter->ReferencesParent() || !iter->IsAbsolute())
|
| + 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 = iter->NormalizePathSeparators();
|
| - FilePath basename = iter->BaseName();
|
| - // TODO(kinuko): Append a suffix or something if we have multiple pathnames
|
| - // with the same basename. For now we only register the first one.
|
| - toplevels.insert(std::make_pair(basename, fullpath));
|
| + 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
|
| @@ -53,8 +113,22 @@ std::string IsolatedContext::RegisterIsolatedFileSystem(
|
| return filesystem_id;
|
| }
|
|
|
| -void IsolatedContext::RevokeIsolatedFileSystem(
|
| - const std::string& filesystem_id) {
|
| +std::string IsolatedContext::RegisterFileSystemForFile(
|
| + const FilePath& path,
|
| + std::string* register_name) {
|
| + FileInfoSet files;
|
| + if (register_name && !register_name->empty()) {
|
| + const bool added = files.AddPathWithName(path, *register_name);
|
| + DCHECK(added);
|
| + } else {
|
| + std::string name = files.AddPath(path);
|
| + if (register_name)
|
| + register_name->assign(name);
|
| + }
|
| + return RegisterFileSystem(files);
|
| +}
|
| +
|
| +void IsolatedContext::RevokeFileSystem(const std::string& filesystem_id) {
|
| base::AutoLock locker(lock_);
|
| RevokeWithoutLocking(filesystem_id);
|
| }
|
| @@ -68,7 +142,7 @@ void IsolatedContext::AddReference(const std::string& filesystem_id) {
|
| 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 RevokeIsolatedFileSystem.
|
| + // already deleted by RevokeFileSystem.
|
| if (ref_counts_.find(filesystem_id) == ref_counts_.end())
|
| return;
|
| DCHECK(ref_counts_[filesystem_id] > 0);
|
| @@ -78,7 +152,7 @@ void IsolatedContext::RemoveReference(const std::string& filesystem_id) {
|
|
|
| bool IsolatedContext::CrackIsolatedPath(const FilePath& virtual_path,
|
| std::string* filesystem_id,
|
| - FilePath* root_path,
|
| + FileInfo* root_info,
|
| FilePath* platform_path) const {
|
| DCHECK(filesystem_id);
|
| DCHECK(platform_path);
|
| @@ -97,7 +171,7 @@ bool IsolatedContext::CrackIsolatedPath(const FilePath& virtual_path,
|
| std::string fsid = FilePath(components[0]).MaybeAsASCII();
|
| if (fsid.empty())
|
| return false;
|
| - IDToPathMap::const_iterator found_toplevels = toplevel_map_.find(fsid);
|
| + IDToFileSet::const_iterator found_toplevels = toplevel_map_.find(fsid);
|
| if (found_toplevels == toplevel_map_.end())
|
| return false;
|
| *filesystem_id = fsid;
|
| @@ -105,45 +179,34 @@ bool IsolatedContext::CrackIsolatedPath(const FilePath& virtual_path,
|
| platform_path->clear();
|
| return true;
|
| }
|
| - // components[1] should be a toplevel path of the dropped paths.
|
| - PathMap::const_iterator found = found_toplevels->second.find(
|
| - FilePath(components[1]));
|
| + // 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())
|
| return false;
|
| - FilePath path = found->second;
|
| - if (root_path)
|
| - *root_path = path;
|
| - for (size_t i = 2; i < components.size(); ++i) {
|
| + if (root_info)
|
| + *root_info = *found;
|
| + FilePath path = found->path;
|
| + for (size_t i = 2; i < components.size(); ++i)
|
| path = path.Append(components[i]);
|
| - }
|
| *platform_path = path;
|
| return true;
|
| }
|
|
|
| -bool IsolatedContext::GetTopLevelPaths(const std::string& filesystem_id,
|
| - std::vector<FilePath>* paths) const {
|
| - DCHECK(paths);
|
| +bool IsolatedContext::GetRegisteredFileInfo(
|
| + const std::string& filesystem_id, std::vector<FileInfo>* files) const {
|
| + DCHECK(files);
|
| base::AutoLock locker(lock_);
|
| - IDToPathMap::const_iterator found = toplevel_map_.find(filesystem_id);
|
| + IDToFileSet::const_iterator found = toplevel_map_.find(filesystem_id);
|
| if (found == toplevel_map_.end())
|
| return false;
|
| - paths->clear();
|
| - PathMap toplevels = found->second;
|
| - for (PathMap::const_iterator iter = toplevels.begin();
|
| - iter != toplevels.end(); ++iter) {
|
| - // Each path map entry holds a map of a toplevel name to its full path.
|
| - paths->push_back(iter->second);
|
| - }
|
| + files->assign(found->second.begin(), found->second.end());
|
| return true;
|
| }
|
|
|
| -FilePath IsolatedContext::CreateVirtualPath(
|
| - const std::string& filesystem_id, const FilePath& relative_path) const {
|
| - FilePath full_path;
|
| - full_path = full_path.AppendASCII(filesystem_id);
|
| - if (relative_path.value() != FILE_PATH_LITERAL("/"))
|
| - full_path = full_path.Append(relative_path);
|
| - return full_path;
|
| +FilePath IsolatedContext::CreateVirtualRootPath(
|
| + const std::string& filesystem_id) const {
|
| + return FilePath().AppendASCII(filesystem_id);
|
| }
|
|
|
| IsolatedContext::IsolatedContext() {
|
|
|