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

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

Issue 10810053: Enables internal filesystem types via Isolated filesystems (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 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
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/file_path.h"
8 #include "base/basictypes.h" 8 #include "base/basictypes.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/rand_util.h" 10 #include "base/rand_util.h"
11 #include "base/stl_util.h"
11 #include "base/string_number_conversions.h" 12 #include "base/string_number_conversions.h"
12 #include "base/string_util.h" 13 #include "base/string_util.h"
13 #include "base/stringprintf.h" 14 #include "base/stringprintf.h"
14 15
15 namespace fileapi { 16 namespace fileapi {
16 17
17 namespace { 18 namespace {
18 19
19 FilePath::StringType GetRegisterNameForPath(const FilePath& path) { 20 FilePath::StringType GetRegisterNameForPath(const FilePath& path) {
20 // If it's not a root path simply return a base name. 21 // If it's not a root path simply return a base name.
(...skipping 23 matching lines...) Expand all
44 LAZY_INSTANCE_INITIALIZER; 45 LAZY_INSTANCE_INITIALIZER;
45 46
46 IsolatedContext::FileInfo::FileInfo() {} 47 IsolatedContext::FileInfo::FileInfo() {}
47 IsolatedContext::FileInfo::FileInfo( 48 IsolatedContext::FileInfo::FileInfo(
48 const std::string& name, const FilePath& path) 49 const std::string& name, const FilePath& path)
49 : name(name), path(path) {} 50 : name(name), path(path) {}
50 51
51 IsolatedContext::FileInfoSet::FileInfoSet() {} 52 IsolatedContext::FileInfoSet::FileInfoSet() {}
52 IsolatedContext::FileInfoSet::~FileInfoSet() {} 53 IsolatedContext::FileInfoSet::~FileInfoSet() {}
53 54
54 std::string IsolatedContext::FileInfoSet::AddPath( 55 bool IsolatedContext::FileInfoSet::AddPath(
55 const FilePath& path) { 56 const FilePath& path, std::string* registered_name) {
57 // The given path should not contain any '..' and should be absolute.
58 if (path.ReferencesParent() || !path.IsAbsolute())
59 return false;
56 FilePath::StringType name = GetRegisterNameForPath(path); 60 FilePath::StringType name = GetRegisterNameForPath(path);
57 std::string utf8name = FilePath(name).AsUTF8Unsafe(); 61 std::string utf8name = FilePath(name).AsUTF8Unsafe();
58 bool inserted = fileset_.insert(FileInfo(utf8name, path)).second; 62 FilePath normalized_path = path.NormalizePathSeparators();
63 bool inserted = fileset_.insert(FileInfo(utf8name, normalized_path)).second;
59 if (!inserted) { 64 if (!inserted) {
60 int suffix = 1; 65 int suffix = 1;
61 std::string basepart = FilePath(name).RemoveExtension().AsUTF8Unsafe(); 66 std::string basepart = FilePath(name).RemoveExtension().AsUTF8Unsafe();
62 std::string ext = FilePath(FilePath(name).Extension()).AsUTF8Unsafe(); 67 std::string ext = FilePath(FilePath(name).Extension()).AsUTF8Unsafe();
63 while (!inserted) { 68 while (!inserted) {
64 utf8name = base::StringPrintf("%s (%d)", basepart.c_str(), suffix++); 69 utf8name = base::StringPrintf("%s (%d)", basepart.c_str(), suffix++);
65 if (!ext.empty()) 70 if (!ext.empty())
66 utf8name.append(ext); 71 utf8name.append(ext);
67 inserted = fileset_.insert(FileInfo(utf8name, path)).second; 72 inserted = fileset_.insert(FileInfo(utf8name, normalized_path)).second;
68 } 73 }
69 } 74 }
70 return utf8name; 75 if (registered_name)
76 *registered_name = utf8name;
77 return true;
71 } 78 }
72 79
73 bool IsolatedContext::FileInfoSet::AddPathWithName( 80 bool IsolatedContext::FileInfoSet::AddPathWithName(
74 const FilePath& path, const std::string& name) { 81 const FilePath& path, const std::string& name) {
75 return fileset_.insert(FileInfo(name, path)).second; 82 // The given path should not contain any '..' and should be absolute.
83 if (path.ReferencesParent() || !path.IsAbsolute())
84 return false;
85 return fileset_.insert(FileInfo(name, path.NormalizePathSeparators())).second;
76 } 86 }
77 87
88 //--------------------------------------------------------------------------
89
90 IsolatedContext::Instance::Instance(FileSystemType type,
91 const FileInfo& file_info)
92 : type_(type),
93 file_info_(file_info),
94 ref_counts_(0) {}
95
96 IsolatedContext::Instance::Instance(const std::set<FileInfo>& dragged_files)
97 : type_(kFileSystemTypeDragged),
98 dragged_files_(dragged_files),
99 ref_counts_(0) {}
100
101 bool IsolatedContext::Instance::ResolvePathForName(const std::string& name,
102 FilePath* path) {
103 if (type_ != kFileSystemTypeDragged) {
104 *path = file_info_.path;
105 return (file_info_.name == name);
106 }
107 std::set<FileInfo>::const_iterator found = dragged_files_.find(
108 FileInfo(name, FilePath()));
109 if (found == dragged_files_.end())
110 return false;
111 *path = found->path;
112 return true;
113 }
114
115 //--------------------------------------------------------------------------
116
78 // static 117 // static
79 IsolatedContext* IsolatedContext::GetInstance() { 118 IsolatedContext* IsolatedContext::GetInstance() {
80 return g_isolated_context.Pointer(); 119 return g_isolated_context.Pointer();
81 } 120 }
82 121
83 std::string IsolatedContext::RegisterFileSystem(const FileInfoSet& files) { 122 std::string IsolatedContext::RegisterDraggedFileSystem(
123 const FileInfoSet& files) {
84 base::AutoLock locker(lock_); 124 base::AutoLock locker(lock_);
85 std::string filesystem_id = GetNewFileSystemId(); 125 std::string filesystem_id = GetNewFileSystemId();
86 // Stores name to fullpath map, as we store the name as a key in 126 instance_map_[filesystem_id] = new Instance(files.fileset());
87 // the filesystem's toplevel entries.
88 FileSet toplevels;
89 for (std::set<FileInfo>::const_iterator iter = files.fileset().begin();
90 iter != files.fileset().end();
91 ++iter) {
92 const FileInfo& info = *iter;
93 // The given path should not contain any '..' and should be absolute.
94 if (info.path.ReferencesParent() || !info.path.IsAbsolute())
95 continue;
96
97 // Register the basename -> fullpath map. (We only expose the basename
98 // part to the user scripts)
99 FilePath fullpath = info.path.NormalizePathSeparators();
100 const bool inserted = toplevels.insert(
101 FileInfo(info.name, fullpath)).second;
102 DCHECK(inserted);
103 }
104
105 // TODO(kinuko): we may not want to register the file system if there're
106 // no valid paths in the given file set.
107
108 toplevel_map_[filesystem_id] = toplevels;
109
110 // Each file system is created with refcount == 0.
111 ref_counts_[filesystem_id] = 0;
112
113 return filesystem_id; 127 return filesystem_id;
114 } 128 }
115 129
116 std::string IsolatedContext::RegisterFileSystemForFile( 130 std::string IsolatedContext::RegisterFileSystemForPath(
131 FileSystemType type,
117 const FilePath& path, 132 const FilePath& path,
118 std::string* register_name) { 133 std::string* register_name) {
119 FileInfoSet files; 134 DCHECK(!path.ReferencesParent() && path.IsAbsolute());
135 std::string name;
120 if (register_name && !register_name->empty()) { 136 if (register_name && !register_name->empty()) {
121 const bool added = files.AddPathWithName(path, *register_name); 137 name = *register_name;
122 DCHECK(added);
123 } else { 138 } else {
124 std::string name = files.AddPath(path); 139 name = GetRegisterNameForPath(path);
125 if (register_name) 140 if (register_name)
126 register_name->assign(name); 141 register_name->assign(name);
127 } 142 }
128 return RegisterFileSystem(files); 143
144 base::AutoLock locker(lock_);
145 std::string filesystem_id = GetNewFileSystemId();
146 instance_map_[filesystem_id] = new Instance(type, FileInfo(name, path));
147 return filesystem_id;
129 } 148 }
130 149
131 void IsolatedContext::RevokeFileSystem(const std::string& filesystem_id) { 150 void IsolatedContext::RevokeFileSystem(const std::string& filesystem_id) {
132 base::AutoLock locker(lock_); 151 base::AutoLock locker(lock_);
133 RevokeWithoutLocking(filesystem_id); 152 IDToInstance::iterator found = instance_map_.find(filesystem_id);
153 if (found == instance_map_.end())
154 return;
155 delete found->second;
156 instance_map_.erase(found);
134 } 157 }
135 158
136 void IsolatedContext::AddReference(const std::string& filesystem_id) { 159 void IsolatedContext::AddReference(const std::string& filesystem_id) {
137 base::AutoLock locker(lock_); 160 base::AutoLock locker(lock_);
138 DCHECK(ref_counts_.find(filesystem_id) != ref_counts_.end()); 161 DCHECK(instance_map_.find(filesystem_id) != instance_map_.end());
139 ref_counts_[filesystem_id]++; 162 instance_map_[filesystem_id]->AddRef();
140 } 163 }
141 164
142 void IsolatedContext::RemoveReference(const std::string& filesystem_id) { 165 void IsolatedContext::RemoveReference(const std::string& filesystem_id) {
143 base::AutoLock locker(lock_); 166 base::AutoLock locker(lock_);
144 // This could get called for non-existent filesystem if it has been 167 // This could get called for non-existent filesystem if it has been
145 // already deleted by RevokeFileSystem. 168 // already deleted by RevokeFileSystem.
146 if (ref_counts_.find(filesystem_id) == ref_counts_.end()) 169 IDToInstance::iterator found = instance_map_.find(filesystem_id);
170 if (found == instance_map_.end())
147 return; 171 return;
148 DCHECK(ref_counts_[filesystem_id] > 0); 172 DCHECK(found->second->ref_counts() > 0);
149 if (--ref_counts_[filesystem_id] == 0) 173 found->second->RemoveRef();
150 RevokeWithoutLocking(filesystem_id); 174 if (found->second->ref_counts() == 0) {
175 delete found->second;
176 instance_map_.erase(found);
177 }
151 } 178 }
152 179
153 bool IsolatedContext::CrackIsolatedPath(const FilePath& virtual_path, 180 bool IsolatedContext::CrackIsolatedPath(const FilePath& virtual_path,
154 std::string* filesystem_id, 181 std::string* filesystem_id,
155 FileInfo* root_info, 182 FileInfo* root_info,
156 FilePath* platform_path) const { 183 FilePath* path) const {
157 DCHECK(filesystem_id); 184 DCHECK(filesystem_id);
158 DCHECK(platform_path); 185 DCHECK(path);
159 186
160 // This should not contain any '..' references. 187 // This should not contain any '..' references.
161 if (virtual_path.ReferencesParent()) 188 if (virtual_path.ReferencesParent())
162 return false; 189 return false;
163 190
164 // The virtual_path should comprise <filesystem_id> and <relative_path> parts. 191 // The virtual_path should comprise <filesystem_id> and <relative_path> parts.
165 std::vector<FilePath::StringType> components; 192 std::vector<FilePath::StringType> components;
166 virtual_path.GetComponents(&components); 193 virtual_path.GetComponents(&components);
167 if (components.size() < 1) 194 if (components.size() < 1)
168 return false; 195 return false;
169 196
170 base::AutoLock locker(lock_); 197 base::AutoLock locker(lock_);
171 std::string fsid = FilePath(components[0]).MaybeAsASCII(); 198 std::string fsid = FilePath(components[0]).MaybeAsASCII();
172 if (fsid.empty()) 199 if (fsid.empty())
173 return false; 200 return false;
174 IDToFileSet::const_iterator found_toplevels = toplevel_map_.find(fsid); 201 IDToInstance::const_iterator found_instance = instance_map_.find(fsid);
175 if (found_toplevels == toplevel_map_.end()) 202 if (found_instance == instance_map_.end())
176 return false; 203 return false;
177 *filesystem_id = fsid; 204 *filesystem_id = fsid;
178 if (components.size() == 1) { 205 if (components.size() == 1) {
179 platform_path->clear(); 206 path->clear();
180 return true; 207 return true;
181 } 208 }
182 // components[1] should be a name of the dropped paths. 209 // components[1] should be a name of the registered paths.
183 FileSet::const_iterator found = found_toplevels->second.find( 210 FilePath cracked_path;
184 FileInfo(FilePath(components[1]).AsUTF8Unsafe(), FilePath())); 211 std::string name = FilePath(components[1]).AsUTF8Unsafe();
185 if (found == found_toplevels->second.end()) 212 if (!found_instance->second->ResolvePathForName(name, &cracked_path))
186 return false; 213 return false;
187 if (root_info) 214 if (root_info)
188 *root_info = *found; 215 *root_info = FileInfo(name, cracked_path);
189 FilePath path = found->path;
190 for (size_t i = 2; i < components.size(); ++i) 216 for (size_t i = 2; i < components.size(); ++i)
191 path = path.Append(components[i]); 217 cracked_path = cracked_path.Append(components[i]);
192 *platform_path = path; 218 *path = cracked_path;
193 return true; 219 return true;
194 } 220 }
195 221
196 bool IsolatedContext::GetRegisteredFileInfo( 222 bool IsolatedContext::GetDraggedFileInfo(
197 const std::string& filesystem_id, std::vector<FileInfo>* files) const { 223 const std::string& filesystem_id, std::vector<FileInfo>* files) const {
198 DCHECK(files); 224 DCHECK(files);
199 base::AutoLock locker(lock_); 225 base::AutoLock locker(lock_);
200 IDToFileSet::const_iterator found = toplevel_map_.find(filesystem_id); 226 IDToInstance::const_iterator found = instance_map_.find(filesystem_id);
201 if (found == toplevel_map_.end()) 227 if (found == instance_map_.end() ||
228 found->second->type() != kFileSystemTypeDragged)
202 return false; 229 return false;
203 files->assign(found->second.begin(), found->second.end()); 230 files->assign(found->second->dragged_files().begin(),
231 found->second->dragged_files().end());
204 return true; 232 return true;
205 } 233 }
206 234
235 bool IsolatedContext::GetRegisteredPath(
236 const std::string& filesystem_id, FilePath* path) const {
237 DCHECK(path);
238 base::AutoLock locker(lock_);
239 IDToInstance::const_iterator found = instance_map_.find(filesystem_id);
240 if (found == instance_map_.end() || found->second->type() == kFileSystemTypeDr agged)
241 return false;
242 *path = found->second->file_info().path;
243 return true;
244 }
245
207 FilePath IsolatedContext::CreateVirtualRootPath( 246 FilePath IsolatedContext::CreateVirtualRootPath(
208 const std::string& filesystem_id) const { 247 const std::string& filesystem_id) const {
209 return FilePath().AppendASCII(filesystem_id); 248 return FilePath().AppendASCII(filesystem_id);
210 } 249 }
211 250
212 IsolatedContext::IsolatedContext() { 251 IsolatedContext::IsolatedContext() {
213 } 252 }
214 253
215 IsolatedContext::~IsolatedContext() { 254 IsolatedContext::~IsolatedContext() {
216 } 255 STLDeleteContainerPairSecondPointers(instance_map_.begin(),
217 256 instance_map_.end());
218 void IsolatedContext::RevokeWithoutLocking(
219 const std::string& filesystem_id) {
220 toplevel_map_.erase(filesystem_id);
221 ref_counts_.erase(filesystem_id);
222 } 257 }
223 258
224 std::string IsolatedContext::GetNewFileSystemId() const { 259 std::string IsolatedContext::GetNewFileSystemId() const {
225 // Returns an arbitrary random string which must be unique in the map. 260 // Returns an arbitrary random string which must be unique in the map.
226 uint32 random_data[4]; 261 uint32 random_data[4];
227 std::string id; 262 std::string id;
228 do { 263 do {
229 base::RandBytes(random_data, sizeof(random_data)); 264 base::RandBytes(random_data, sizeof(random_data));
230 id = base::HexEncode(random_data, sizeof(random_data)); 265 id = base::HexEncode(random_data, sizeof(random_data));
231 } while (toplevel_map_.find(id) != toplevel_map_.end()); 266 } while (instance_map_.find(id) != instance_map_.end());
232 return id; 267 return id;
233 } 268 }
234 269
235 } // namespace fileapi 270 } // namespace fileapi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698