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

Side by Side Diff: webkit/fileapi/isolated_context.cc

Issue 10713007: Make isolated file system works for a device root (e.g. X:\\) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased Created 8 years, 5 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "webkit/fileapi/isolated_context.h" 5 #include "webkit/fileapi/isolated_context.h"
6 6
7 #include "base/file_path.h"
7 #include "base/basictypes.h" 8 #include "base/basictypes.h"
8 #include "base/logging.h" 9 #include "base/logging.h"
9 #include "base/rand_util.h" 10 #include "base/rand_util.h"
10 #include "base/string_number_conversions.h" 11 #include "base/string_number_conversions.h"
11 #include "base/string_util.h" 12 #include "base/string_util.h"
13 #include "base/stringprintf.h"
12 14
13 namespace fileapi { 15 namespace fileapi {
14 16
17 namespace {
18
19 FilePath::StringType GetRegisterNameForPath(const FilePath& path) {
20 // If it's not a root path simply return a base name.
21 if (path.DirName() != path)
22 return path.BaseName().value();
23
24 #if defined(FILE_PATH_USES_DRIVE_LETTERS)
25 FilePath::StringType name;
26 for (size_t i = 0;
27 i < path.value().size() && !FilePath::IsSeparator(path.value()[i]);
28 ++i) {
29 if (path.value()[i] == L':') {
30 name.append(L"_drive");
31 break;
32 }
33 name.append(1, path.value()[i]);
34 }
35 return name;
36 #else
37 return FILE_PATH_LITERAL("<root>");
38 #endif
39 }
40
41 }
42
15 static base::LazyInstance<IsolatedContext>::Leaky g_isolated_context = 43 static base::LazyInstance<IsolatedContext>::Leaky g_isolated_context =
16 LAZY_INSTANCE_INITIALIZER; 44 LAZY_INSTANCE_INITIALIZER;
17 45
46 IsolatedContext::FileInfo::FileInfo() {}
47 IsolatedContext::FileInfo::FileInfo(
48 const std::string& name, const FilePath& path)
49 : name(name), path(path) {}
50
51 IsolatedContext::FileInfoSet::FileInfoSet() {}
52 IsolatedContext::FileInfoSet::~FileInfoSet() {}
53
54 std::string IsolatedContext::FileInfoSet::AddPath(
55 const FilePath& path) {
56 FilePath::StringType name = GetRegisterNameForPath(path);
57 std::string utf8name = FilePath(name).AsUTF8Unsafe();
58 bool inserted = fileset_.insert(FileInfo(utf8name, path)).second;
59 if (!inserted) {
60 int suffix = 1;
61 std::string basepart = FilePath(name).RemoveExtension().AsUTF8Unsafe();
62 std::string ext = FilePath(FilePath(name).Extension()).AsUTF8Unsafe();
63 while (!inserted) {
64 utf8name = base::StringPrintf("%s (%d)", basepart.c_str(), suffix++);
65 if (!ext.empty())
66 utf8name.append(ext);
67 inserted = fileset_.insert(FileInfo(utf8name, path)).second;
68 }
69 }
70 return utf8name;
71 }
72
73 bool IsolatedContext::FileInfoSet::AddPathWithName(
74 const FilePath& path, const std::string& name) {
75 return fileset_.insert(FileInfo(name, path)).second;
76 }
77
18 // static 78 // static
19 IsolatedContext* IsolatedContext::GetInstance() { 79 IsolatedContext* IsolatedContext::GetInstance() {
20 return g_isolated_context.Pointer(); 80 return g_isolated_context.Pointer();
21 } 81 }
22 82
23 std::string IsolatedContext::RegisterIsolatedFileSystem( 83 std::string IsolatedContext::RegisterFileSystem(const FileInfoSet& files) {
24 const std::set<FilePath>& files) {
25 base::AutoLock locker(lock_); 84 base::AutoLock locker(lock_);
26 std::string filesystem_id = GetNewFileSystemId(); 85 std::string filesystem_id = GetNewFileSystemId();
27 // Stores basename to fullpath map, as we store the basenames as 86 // Stores name to fullpath map, as we store the name as a key in
28 // the filesystem's toplevel entries. 87 // the filesystem's toplevel entries.
29 PathMap toplevels; 88 FileSet toplevels;
30 for (std::set<FilePath>::const_iterator iter = files.begin(); 89 for (std::set<FileInfo>::const_iterator iter = files.fileset().begin();
31 iter != files.end(); ++iter) { 90 iter != files.fileset().end();
91 ++iter) {
92 const FileInfo& info = *iter;
32 // The given path should not contain any '..' and should be absolute. 93 // The given path should not contain any '..' and should be absolute.
33 if (iter->ReferencesParent() || !iter->IsAbsolute()) 94 if (info.path.ReferencesParent() || !info.path.IsAbsolute())
34 continue; 95 continue;
35 96
36 // Register the basename -> fullpath map. (We only expose the basename 97 // Register the basename -> fullpath map. (We only expose the basename
37 // part to the user scripts) 98 // part to the user scripts)
38 FilePath fullpath = iter->NormalizePathSeparators(); 99 FilePath fullpath = info.path.NormalizePathSeparators();
39 FilePath basename = iter->BaseName(); 100 const bool inserted = toplevels.insert(
40 // TODO(kinuko): Append a suffix or something if we have multiple pathnames 101 FileInfo(info.name, fullpath)).second;
41 // with the same basename. For now we only register the first one. 102 DCHECK(inserted);
42 toplevels.insert(std::make_pair(basename, fullpath));
43 } 103 }
44 104
45 // TODO(kinuko): we may not want to register the file system if there're 105 // TODO(kinuko): we may not want to register the file system if there're
46 // no valid paths in the given file set. 106 // no valid paths in the given file set.
47 107
48 toplevel_map_[filesystem_id] = toplevels; 108 toplevel_map_[filesystem_id] = toplevels;
49 109
50 // Each file system is created with refcount == 0. 110 // Each file system is created with refcount == 0.
51 ref_counts_[filesystem_id] = 0; 111 ref_counts_[filesystem_id] = 0;
52 112
53 return filesystem_id; 113 return filesystem_id;
54 } 114 }
55 115
56 void IsolatedContext::RevokeIsolatedFileSystem( 116 std::string IsolatedContext::RegisterFileSystemForFile(
57 const std::string& filesystem_id) { 117 const FilePath& path,
118 std::string* register_name) {
119 FileInfoSet files;
120 if (register_name && !register_name->empty()) {
121 const bool added = files.AddPathWithName(path, *register_name);
122 DCHECK(added);
123 } else {
124 std::string name = files.AddPath(path);
125 if (register_name)
126 register_name->assign(name);
127 }
128 return RegisterFileSystem(files);
129 }
130
131 void IsolatedContext::RevokeFileSystem(const std::string& filesystem_id) {
58 base::AutoLock locker(lock_); 132 base::AutoLock locker(lock_);
59 RevokeWithoutLocking(filesystem_id); 133 RevokeWithoutLocking(filesystem_id);
60 } 134 }
61 135
62 void IsolatedContext::AddReference(const std::string& filesystem_id) { 136 void IsolatedContext::AddReference(const std::string& filesystem_id) {
63 base::AutoLock locker(lock_); 137 base::AutoLock locker(lock_);
64 DCHECK(ref_counts_.find(filesystem_id) != ref_counts_.end()); 138 DCHECK(ref_counts_.find(filesystem_id) != ref_counts_.end());
65 ref_counts_[filesystem_id]++; 139 ref_counts_[filesystem_id]++;
66 } 140 }
67 141
68 void IsolatedContext::RemoveReference(const std::string& filesystem_id) { 142 void IsolatedContext::RemoveReference(const std::string& filesystem_id) {
69 base::AutoLock locker(lock_); 143 base::AutoLock locker(lock_);
70 // This could get called for non-existent filesystem if it has been 144 // This could get called for non-existent filesystem if it has been
71 // already deleted by RevokeIsolatedFileSystem. 145 // already deleted by RevokeFileSystem.
72 if (ref_counts_.find(filesystem_id) == ref_counts_.end()) 146 if (ref_counts_.find(filesystem_id) == ref_counts_.end())
73 return; 147 return;
74 DCHECK(ref_counts_[filesystem_id] > 0); 148 DCHECK(ref_counts_[filesystem_id] > 0);
75 if (--ref_counts_[filesystem_id] == 0) 149 if (--ref_counts_[filesystem_id] == 0)
76 RevokeWithoutLocking(filesystem_id); 150 RevokeWithoutLocking(filesystem_id);
77 } 151 }
78 152
79 bool IsolatedContext::CrackIsolatedPath(const FilePath& virtual_path, 153 bool IsolatedContext::CrackIsolatedPath(const FilePath& virtual_path,
80 std::string* filesystem_id, 154 std::string* filesystem_id,
81 FilePath* root_path, 155 FileInfo* root_info,
82 FilePath* platform_path) const { 156 FilePath* platform_path) const {
83 DCHECK(filesystem_id); 157 DCHECK(filesystem_id);
84 DCHECK(platform_path); 158 DCHECK(platform_path);
85 159
86 // This should not contain any '..' references. 160 // This should not contain any '..' references.
87 if (virtual_path.ReferencesParent()) 161 if (virtual_path.ReferencesParent())
88 return false; 162 return false;
89 163
90 // The virtual_path should comprise <filesystem_id> and <relative_path> parts. 164 // The virtual_path should comprise <filesystem_id> and <relative_path> parts.
91 std::vector<FilePath::StringType> components; 165 std::vector<FilePath::StringType> components;
92 virtual_path.GetComponents(&components); 166 virtual_path.GetComponents(&components);
93 if (components.size() < 1) 167 if (components.size() < 1)
94 return false; 168 return false;
95 169
96 base::AutoLock locker(lock_); 170 base::AutoLock locker(lock_);
97 std::string fsid = FilePath(components[0]).MaybeAsASCII(); 171 std::string fsid = FilePath(components[0]).MaybeAsASCII();
98 if (fsid.empty()) 172 if (fsid.empty())
99 return false; 173 return false;
100 IDToPathMap::const_iterator found_toplevels = toplevel_map_.find(fsid); 174 IDToFileSet::const_iterator found_toplevels = toplevel_map_.find(fsid);
101 if (found_toplevels == toplevel_map_.end()) 175 if (found_toplevels == toplevel_map_.end())
102 return false; 176 return false;
103 *filesystem_id = fsid; 177 *filesystem_id = fsid;
104 if (components.size() == 1) { 178 if (components.size() == 1) {
105 platform_path->clear(); 179 platform_path->clear();
106 return true; 180 return true;
107 } 181 }
108 // components[1] should be a toplevel path of the dropped paths. 182 // components[1] should be a name of the dropped paths.
109 PathMap::const_iterator found = found_toplevels->second.find( 183 FileSet::const_iterator found = found_toplevels->second.find(
110 FilePath(components[1])); 184 FileInfo(FilePath(components[1]).AsUTF8Unsafe(), FilePath()));
111 if (found == found_toplevels->second.end()) 185 if (found == found_toplevels->second.end())
112 return false; 186 return false;
113 FilePath path = found->second; 187 if (root_info)
114 if (root_path) 188 *root_info = *found;
115 *root_path = path; 189 FilePath path = found->path;
116 for (size_t i = 2; i < components.size(); ++i) { 190 for (size_t i = 2; i < components.size(); ++i)
117 path = path.Append(components[i]); 191 path = path.Append(components[i]);
118 }
119 *platform_path = path; 192 *platform_path = path;
120 return true; 193 return true;
121 } 194 }
122 195
123 bool IsolatedContext::GetTopLevelPaths(const std::string& filesystem_id, 196 bool IsolatedContext::GetRegisteredFileInfo(
124 std::vector<FilePath>* paths) const { 197 const std::string& filesystem_id, std::vector<FileInfo>* files) const {
125 DCHECK(paths); 198 DCHECK(files);
126 base::AutoLock locker(lock_); 199 base::AutoLock locker(lock_);
127 IDToPathMap::const_iterator found = toplevel_map_.find(filesystem_id); 200 IDToFileSet::const_iterator found = toplevel_map_.find(filesystem_id);
128 if (found == toplevel_map_.end()) 201 if (found == toplevel_map_.end())
129 return false; 202 return false;
130 paths->clear(); 203 files->assign(found->second.begin(), found->second.end());
131 PathMap toplevels = found->second;
132 for (PathMap::const_iterator iter = toplevels.begin();
133 iter != toplevels.end(); ++iter) {
134 // Each path map entry holds a map of a toplevel name to its full path.
135 paths->push_back(iter->second);
136 }
137 return true; 204 return true;
138 } 205 }
139 206
140 FilePath IsolatedContext::CreateVirtualPath( 207 FilePath IsolatedContext::CreateVirtualRootPath(
141 const std::string& filesystem_id, const FilePath& relative_path) const { 208 const std::string& filesystem_id) const {
142 FilePath full_path; 209 return FilePath().AppendASCII(filesystem_id);
143 full_path = full_path.AppendASCII(filesystem_id);
144 if (relative_path.value() != FILE_PATH_LITERAL("/"))
145 full_path = full_path.Append(relative_path);
146 return full_path;
147 } 210 }
148 211
149 IsolatedContext::IsolatedContext() { 212 IsolatedContext::IsolatedContext() {
150 } 213 }
151 214
152 IsolatedContext::~IsolatedContext() { 215 IsolatedContext::~IsolatedContext() {
153 } 216 }
154 217
155 void IsolatedContext::RevokeWithoutLocking( 218 void IsolatedContext::RevokeWithoutLocking(
156 const std::string& filesystem_id) { 219 const std::string& filesystem_id) {
157 toplevel_map_.erase(filesystem_id); 220 toplevel_map_.erase(filesystem_id);
158 ref_counts_.erase(filesystem_id); 221 ref_counts_.erase(filesystem_id);
159 } 222 }
160 223
161 std::string IsolatedContext::GetNewFileSystemId() const { 224 std::string IsolatedContext::GetNewFileSystemId() const {
162 // Returns an arbitrary random string which must be unique in the map. 225 // Returns an arbitrary random string which must be unique in the map.
163 uint32 random_data[4]; 226 uint32 random_data[4];
164 std::string id; 227 std::string id;
165 do { 228 do {
166 base::RandBytes(random_data, sizeof(random_data)); 229 base::RandBytes(random_data, sizeof(random_data));
167 id = base::HexEncode(random_data, sizeof(random_data)); 230 id = base::HexEncode(random_data, sizeof(random_data));
168 } while (toplevel_map_.find(id) != toplevel_map_.end()); 231 } while (toplevel_map_.find(id) != toplevel_map_.end());
169 return id; 232 return id;
170 } 233 }
171 234
172 } // namespace fileapi 235 } // 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