OLD | NEW |
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_file_util.h" | 5 #include "webkit/fileapi/isolated_file_util.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 namespace fileapi { | 21 namespace fileapi { |
22 | 22 |
23 typedef IsolatedContext::FileInfo FileInfo; | 23 typedef IsolatedContext::FileInfo FileInfo; |
24 | 24 |
25 namespace { | 25 namespace { |
26 | 26 |
27 // Simply enumerate each path from a given fileinfo set. | 27 // Simply enumerate each path from a given fileinfo set. |
28 // Used to enumerate top-level paths of an isolated filesystem. | 28 // Used to enumerate top-level paths of an isolated filesystem. |
29 class SetFileEnumerator : public FileSystemFileUtil::AbstractFileEnumerator { | 29 class SetFileEnumerator : public FileSystemFileUtil::AbstractFileEnumerator { |
30 public: | 30 public: |
31 SetFileEnumerator(const std::vector<FileInfo>& files, | 31 explicit SetFileEnumerator(const std::vector<FileInfo>& files) |
32 const FilePath& root) | 32 : files_(files) { |
33 : files_(files), | |
34 root_(root) { | |
35 file_iter_ = files_.begin(); | 33 file_iter_ = files_.begin(); |
36 } | 34 } |
37 virtual ~SetFileEnumerator() {} | 35 virtual ~SetFileEnumerator() {} |
38 | 36 |
39 // AbstractFileEnumerator overrides. | 37 // AbstractFileEnumerator overrides. |
40 virtual FilePath Next() OVERRIDE { | 38 virtual FilePath Next() OVERRIDE { |
41 if (file_iter_ == files_.end()) | 39 if (file_iter_ == files_.end()) |
42 return FilePath(); | 40 return FilePath(); |
43 FilePath platform_file = (file_iter_++)->path; | 41 FilePath platform_file = (file_iter_++)->path; |
44 NativeFileUtil::GetFileInfo(platform_file, &file_info_); | 42 NativeFileUtil::GetFileInfo(platform_file, &file_info_); |
45 return root_.Append(platform_file.BaseName()); | 43 return platform_file; |
46 } | 44 } |
47 virtual int64 Size() OVERRIDE { return file_info_.size; } | 45 virtual int64 Size() OVERRIDE { return file_info_.size; } |
48 virtual bool IsDirectory() OVERRIDE { return file_info_.is_directory; } | 46 virtual bool IsDirectory() OVERRIDE { return file_info_.is_directory; } |
49 virtual base::Time LastModifiedTime() OVERRIDE { | 47 virtual base::Time LastModifiedTime() OVERRIDE { |
50 return file_info_.last_modified; | 48 return file_info_.last_modified; |
51 } | 49 } |
52 | 50 |
53 private: | 51 private: |
54 std::vector<FileInfo> files_; | 52 std::vector<FileInfo> files_; |
55 std::vector<FileInfo>::const_iterator file_iter_; | 53 std::vector<FileInfo>::const_iterator file_iter_; |
56 FilePath root_; | |
57 base::PlatformFileInfo file_info_; | 54 base::PlatformFileInfo file_info_; |
58 }; | 55 }; |
59 | 56 |
60 // A wrapper file enumerator which returns a virtual path of the path returned | |
61 // by the wrapped enumerator. | |
62 // | |
63 // A virtual path is constructed as following: | |
64 // virtual_path = |virtual_base_path| + relative-path-to-|platform_base_path| | |
65 // | |
66 // Where |virtual_base_path| is in our case the virtual top-level directory | |
67 // that looks like: '/<filesystem_id>'. | |
68 // | |
69 // Example: | |
70 // Suppose virtual_base_path is: '/CAFEBABE/dir', | |
71 // platform_base_path is: '/full/path/to/example/dir', and | |
72 // a path returned by wrapped_ is: '/full/path/to/example/dir/a/b/c', | |
73 // Next() would return: '/CAFEBABE/dir/a/b/c'. | |
74 // | |
75 class PathConverterEnumerator | |
76 : public FileSystemFileUtil::AbstractFileEnumerator { | |
77 public: | |
78 PathConverterEnumerator( | |
79 FileSystemFileUtil::AbstractFileEnumerator* wrapped, | |
80 const FilePath& virtual_base_path, | |
81 const FilePath& platform_base_path) | |
82 : wrapped_(wrapped), | |
83 virtual_base_path_(virtual_base_path), | |
84 platform_base_path_(platform_base_path) {} | |
85 virtual ~PathConverterEnumerator() {} | |
86 | |
87 // AbstractFileEnumerator overrides. | |
88 virtual FilePath Next() OVERRIDE { | |
89 DCHECK(wrapped_.get()); | |
90 FilePath path = wrapped_->Next(); | |
91 // Don't return symlinks in subdirectories. | |
92 while (!path.empty() && file_util::IsLink(path)) | |
93 path = wrapped_->Next(); | |
94 if (path.empty()) | |
95 return path; | |
96 FilePath virtual_path = virtual_base_path_; | |
97 platform_base_path_.AppendRelativePath(path, &virtual_path); | |
98 return virtual_path; | |
99 } | |
100 virtual int64 Size() OVERRIDE { return wrapped_->Size(); } | |
101 virtual bool IsDirectory() OVERRIDE { return wrapped_->IsDirectory(); } | |
102 virtual base::Time LastModifiedTime() OVERRIDE { | |
103 return wrapped_->LastModifiedTime(); | |
104 } | |
105 | |
106 private: | |
107 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> wrapped_; | |
108 FilePath virtual_base_path_; | |
109 FilePath platform_base_path_; | |
110 }; | |
111 | |
112 // Recursively enumerate each path from a given paths set. | 57 // Recursively enumerate each path from a given paths set. |
113 class RecursiveSetFileEnumerator | 58 class RecursiveSetFileEnumerator |
114 : public FileSystemFileUtil::AbstractFileEnumerator { | 59 : public FileSystemFileUtil::AbstractFileEnumerator { |
115 public: | 60 public: |
116 RecursiveSetFileEnumerator(const FilePath& virtual_base_path, | 61 RecursiveSetFileEnumerator(const std::vector<FileInfo>& files) |
117 const std::vector<FileInfo>& files, | 62 : files_(files) { |
118 const FilePath& root) | |
119 : virtual_base_path_(virtual_base_path), | |
120 files_(files), | |
121 root_(root) { | |
122 file_iter_ = files_.begin(); | 63 file_iter_ = files_.begin(); |
123 current_enumerator_.reset(new SetFileEnumerator(files, root)); | 64 current_enumerator_.reset(new SetFileEnumerator(files)); |
124 } | 65 } |
125 virtual ~RecursiveSetFileEnumerator() {} | 66 virtual ~RecursiveSetFileEnumerator() {} |
126 | 67 |
127 // AbstractFileEnumerator overrides. | 68 // AbstractFileEnumerator overrides. |
128 virtual FilePath Next() OVERRIDE; | 69 virtual FilePath Next() OVERRIDE; |
129 virtual int64 Size() OVERRIDE { | 70 virtual int64 Size() OVERRIDE { |
130 DCHECK(current_enumerator_.get()); | 71 DCHECK(current_enumerator_.get()); |
131 return current_enumerator_->Size(); | 72 return current_enumerator_->Size(); |
132 } | 73 } |
133 virtual bool IsDirectory() OVERRIDE { | 74 virtual bool IsDirectory() OVERRIDE { |
134 DCHECK(current_enumerator_.get()); | 75 DCHECK(current_enumerator_.get()); |
135 return current_enumerator_->IsDirectory(); | 76 return current_enumerator_->IsDirectory(); |
136 } | 77 } |
137 virtual base::Time LastModifiedTime() OVERRIDE { | 78 virtual base::Time LastModifiedTime() OVERRIDE { |
138 DCHECK(current_enumerator_.get()); | 79 DCHECK(current_enumerator_.get()); |
139 return current_enumerator_->LastModifiedTime(); | 80 return current_enumerator_->LastModifiedTime(); |
140 } | 81 } |
141 | 82 |
142 private: | 83 private: |
143 FilePath virtual_base_path_; | |
144 std::vector<FileInfo> files_; | 84 std::vector<FileInfo> files_; |
145 std::vector<FileInfo>::iterator file_iter_; | 85 std::vector<FileInfo>::iterator file_iter_; |
146 base::PlatformFileInfo file_info_; | 86 base::PlatformFileInfo file_info_; |
147 FilePath root_; | |
148 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> current_enumerator_; | 87 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> current_enumerator_; |
149 }; | 88 }; |
150 | 89 |
151 FilePath RecursiveSetFileEnumerator::Next() { | 90 FilePath RecursiveSetFileEnumerator::Next() { |
152 if (current_enumerator_.get()) { | 91 if (current_enumerator_.get()) { |
153 FilePath path = current_enumerator_->Next(); | 92 FilePath path = current_enumerator_->Next(); |
154 if (!path.empty()) | 93 if (!path.empty()) |
155 return path; | 94 return path; |
156 } | 95 } |
157 | 96 |
158 // We reached the end. | 97 // We reached the end. |
159 if (file_iter_ == files_.end()) | 98 if (file_iter_ == files_.end()) |
160 return FilePath(); | 99 return FilePath(); |
161 | 100 |
162 // Enumerates subdirectories of the next path. | 101 // Enumerates subdirectories of the next path. |
163 FileInfo& next_file = *file_iter_++; | 102 FileInfo& next_file = *file_iter_++; |
164 current_enumerator_.reset( | 103 current_enumerator_.reset( |
165 new PathConverterEnumerator( | 104 NativeFileUtil::CreateFileEnumerator( |
166 NativeFileUtil::CreateFileEnumerator( | 105 next_file.path, true /* recursive */)); |
167 next_file.path, true /* recursive */), | |
168 virtual_base_path_.AppendASCII(next_file.name), next_file.path)); | |
169 DCHECK(current_enumerator_.get()); | 106 DCHECK(current_enumerator_.get()); |
170 return current_enumerator_->Next(); | 107 return current_enumerator_->Next(); |
171 } | 108 } |
172 | 109 |
173 } // namespace | 110 } // namespace |
174 | 111 |
175 IsolatedFileUtil::IsolatedFileUtil() { | 112 //------------------------------------------------------------------------- |
| 113 |
| 114 IsolatedFileUtil::IsolatedFileUtil() {} |
| 115 |
| 116 PlatformFileError IsolatedFileUtil::GetLocalFilePath( |
| 117 FileSystemOperationContext* context, |
| 118 const FileSystemURL& url, |
| 119 FilePath* local_file_path) { |
| 120 DCHECK(local_file_path); |
| 121 if (url.path().empty()) { |
| 122 // Root direcory case, which should not be accessed. |
| 123 return base::PLATFORM_FILE_ERROR_ACCESS_DENIED; |
| 124 } |
| 125 *local_file_path = url.path(); |
| 126 return base::PLATFORM_FILE_OK; |
176 } | 127 } |
177 | 128 |
178 PlatformFileError IsolatedFileUtil::CreateOrOpen( | 129 //------------------------------------------------------------------------- |
179 FileSystemOperationContext* context, | |
180 const FileSystemURL& url, int file_flags, | |
181 PlatformFile* file_handle, bool* created) { | |
182 return base::PLATFORM_FILE_ERROR_SECURITY; | |
183 } | |
184 | 130 |
185 PlatformFileError IsolatedFileUtil::Close( | 131 DraggedFileUtil::DraggedFileUtil() {} |
186 FileSystemOperationContext* context, | |
187 PlatformFile file_handle) { | |
188 // We don't allow open thus Close won't be called. | |
189 return base::PLATFORM_FILE_ERROR_SECURITY; | |
190 } | |
191 | 132 |
192 PlatformFileError IsolatedFileUtil::EnsureFileExists( | 133 PlatformFileError DraggedFileUtil::GetFileInfo( |
193 FileSystemOperationContext* context, | |
194 const FileSystemURL& url, | |
195 bool* created) { | |
196 return base::PLATFORM_FILE_ERROR_SECURITY; | |
197 } | |
198 | |
199 PlatformFileError IsolatedFileUtil::CreateDirectory( | |
200 FileSystemOperationContext* context, | |
201 const FileSystemURL& url, | |
202 bool exclusive, | |
203 bool recursive) { | |
204 return base::PLATFORM_FILE_ERROR_SECURITY; | |
205 } | |
206 | |
207 PlatformFileError IsolatedFileUtil::GetFileInfo( | |
208 FileSystemOperationContext* context, | 134 FileSystemOperationContext* context, |
209 const FileSystemURL& url, | 135 const FileSystemURL& url, |
210 PlatformFileInfo* file_info, | 136 PlatformFileInfo* file_info, |
211 FilePath* platform_path) { | 137 FilePath* platform_path) { |
212 DCHECK(file_info); | 138 DCHECK(file_info); |
213 std::string filesystem_id; | 139 std::string filesystem_id; |
214 FilePath cracked_path; | 140 if (url.path().empty()) { |
215 if (!IsolatedContext::GetInstance()->CrackIsolatedPath( | |
216 url.path(), &filesystem_id, NULL, &cracked_path)) | |
217 return base::PLATFORM_FILE_ERROR_SECURITY; | |
218 if (cracked_path.empty()) { | |
219 // The root directory case. | 141 // The root directory case. |
220 // For now we leave three time fields (modified/accessed/creation time) | 142 // For now we leave three time fields (modified/accessed/creation time) |
221 // NULL as it is not really clear what to be set for this virtual directory. | 143 // NULL as it is not really clear what to be set for this virtual directory. |
222 // TODO(kinuko): Maybe we want to set the time when this filesystem is | 144 // TODO(kinuko): Maybe we want to set the time when this filesystem is |
223 // created (i.e. when the files/directories are dropped). | 145 // created (i.e. when the files/directories are dropped). |
224 file_info->is_directory = true; | 146 file_info->is_directory = true; |
225 file_info->is_symbolic_link = false; | 147 file_info->is_symbolic_link = false; |
226 file_info->size = 0; | 148 file_info->size = 0; |
227 return base::PLATFORM_FILE_OK; | 149 return base::PLATFORM_FILE_OK; |
228 } | 150 } |
229 base::PlatformFileError error = | 151 base::PlatformFileError error = |
230 NativeFileUtil::GetFileInfo(cracked_path, file_info); | 152 NativeFileUtil::GetFileInfo(url.path(), file_info); |
231 if (file_util::IsLink(cracked_path) && !FilePath().IsParent(cracked_path)) { | 153 if (file_util::IsLink(url.path()) && !FilePath().IsParent(url.path())) { |
232 // Don't follow symlinks unless it's the one that are selected by the user. | 154 // Don't follow symlinks unless it's the one that are selected by the user. |
233 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | 155 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
234 } | 156 } |
235 if (error == base::PLATFORM_FILE_OK) | 157 if (error == base::PLATFORM_FILE_OK) |
236 *platform_path = cracked_path; | 158 *platform_path = url.path(); |
237 return error; | 159 return error; |
238 } | 160 } |
239 | 161 |
240 FileSystemFileUtil::AbstractFileEnumerator* | 162 FileSystemFileUtil::AbstractFileEnumerator* |
241 IsolatedFileUtil::CreateFileEnumerator( | 163 DraggedFileUtil::CreateFileEnumerator( |
242 FileSystemOperationContext* context, | 164 FileSystemOperationContext* context, |
243 const FileSystemURL& root, | 165 const FileSystemURL& root, |
244 bool recursive) { | 166 bool recursive) { |
245 std::string filesystem_id; | 167 if (!root.path().empty()) |
246 FileInfo root_info; | 168 return NativeFileUtil::CreateFileEnumerator(root.path(), recursive); |
247 FilePath cracked_path; | |
248 if (!IsolatedContext::GetInstance()->CrackIsolatedPath( | |
249 root.path(), &filesystem_id, &root_info, &cracked_path)) | |
250 return NULL; | |
251 | |
252 FilePath virtual_base_path = | |
253 IsolatedContext::GetInstance()->CreateVirtualRootPath(filesystem_id); | |
254 | |
255 if (!cracked_path.empty()) { | |
256 return new PathConverterEnumerator( | |
257 NativeFileUtil::CreateFileEnumerator(cracked_path, recursive), | |
258 virtual_base_path.AppendASCII(root_info.name), root_info.path); | |
259 } | |
260 | 169 |
261 // Root path case. | 170 // Root path case. |
262 std::vector<FileInfo> toplevels; | 171 std::vector<FileInfo> toplevels; |
263 IsolatedContext::GetInstance()->GetDraggedFileInfo( | 172 IsolatedContext::GetInstance()->GetDraggedFileInfo( |
264 filesystem_id, &toplevels); | 173 root.filesystem_id(), &toplevels); |
265 if (!recursive) | 174 if (!recursive) |
266 return new SetFileEnumerator(toplevels, root.path()); | 175 return new SetFileEnumerator(toplevels); |
267 return new RecursiveSetFileEnumerator( | 176 return new RecursiveSetFileEnumerator(toplevels); |
268 virtual_base_path, toplevels, root.path()); | |
269 } | 177 } |
270 | 178 |
271 PlatformFileError IsolatedFileUtil::GetLocalFilePath( | 179 bool DraggedFileUtil::PathExists( |
272 FileSystemOperationContext* context, | |
273 const FileSystemURL& file_system_url, | |
274 FilePath* local_file_path) { | |
275 if (GetPlatformPath(file_system_url, local_file_path)) | |
276 return base::PLATFORM_FILE_OK; | |
277 return base::PLATFORM_FILE_ERROR_SECURITY; | |
278 } | |
279 | |
280 PlatformFileError IsolatedFileUtil::Touch( | |
281 FileSystemOperationContext* context, | |
282 const FileSystemURL& url, | |
283 const base::Time& last_access_time, | |
284 const base::Time& last_modified_time) { | |
285 FilePath platform_path; | |
286 if (!GetPlatformPath(url, &platform_path) || platform_path.empty()) | |
287 return base::PLATFORM_FILE_ERROR_SECURITY; | |
288 return NativeFileUtil::Touch( | |
289 platform_path, last_access_time, last_modified_time); | |
290 } | |
291 | |
292 PlatformFileError IsolatedFileUtil::Truncate( | |
293 FileSystemOperationContext* context, | |
294 const FileSystemURL& url, | |
295 int64 length) { | |
296 FilePath platform_path; | |
297 if (!GetPlatformPath(url, &platform_path) || platform_path.empty()) | |
298 return base::PLATFORM_FILE_ERROR_SECURITY; | |
299 return NativeFileUtil::Truncate(platform_path, length); | |
300 } | |
301 | |
302 bool IsolatedFileUtil::PathExists( | |
303 FileSystemOperationContext* context, | 180 FileSystemOperationContext* context, |
304 const FileSystemURL& url) { | 181 const FileSystemURL& url) { |
305 FilePath platform_path; | 182 if (url.path().empty()) { |
306 if (!GetPlatformPath(url, &platform_path)) | |
307 return false; | |
308 if (platform_path.empty()) { | |
309 // The root directory case. | 183 // The root directory case. |
310 return true; | 184 return true; |
311 } | 185 } |
312 return NativeFileUtil::PathExists(platform_path); | 186 return NativeFileUtil::PathExists(url.path()); |
313 } | 187 } |
314 | 188 |
315 bool IsolatedFileUtil::DirectoryExists( | 189 bool DraggedFileUtil::DirectoryExists( |
316 FileSystemOperationContext* context, | 190 FileSystemOperationContext* context, |
317 const FileSystemURL& url) { | 191 const FileSystemURL& url) { |
318 FilePath platform_path; | 192 if (url.path().empty()) { |
319 if (!GetPlatformPath(url, &platform_path)) | |
320 return false; | |
321 if (platform_path.empty()) { | |
322 // The root directory case. | 193 // The root directory case. |
323 return true; | 194 return true; |
324 } | 195 } |
325 return NativeFileUtil::DirectoryExists(platform_path); | 196 return NativeFileUtil::DirectoryExists(url.path()); |
326 } | 197 } |
327 | 198 |
328 bool IsolatedFileUtil::IsDirectoryEmpty( | 199 bool DraggedFileUtil::IsDirectoryEmpty( |
329 FileSystemOperationContext* context, | 200 FileSystemOperationContext* context, |
330 const FileSystemURL& url) { | 201 const FileSystemURL& url) { |
331 std::string filesystem_id; | 202 if (url.path().empty()) { |
332 FilePath platform_path; | |
333 if (!IsolatedContext::GetInstance()->CrackIsolatedPath( | |
334 url.path(), &filesystem_id, | |
335 NULL, &platform_path)) | |
336 return false; | |
337 if (platform_path.empty()) { | |
338 // The root directory case. | 203 // The root directory case. |
339 std::vector<FileInfo> toplevels; | 204 std::vector<FileInfo> toplevels; |
340 bool success = IsolatedContext::GetInstance()->GetDraggedFileInfo( | 205 bool success = IsolatedContext::GetInstance()->GetDraggedFileInfo( |
341 filesystem_id, &toplevels); | 206 url.filesystem_id(), &toplevels); |
342 DCHECK(success); | 207 DCHECK(success); |
343 return toplevels.empty(); | 208 return toplevels.empty(); |
344 } | 209 } |
345 return NativeFileUtil::IsDirectoryEmpty(platform_path); | 210 return NativeFileUtil::IsDirectoryEmpty(url.path()); |
346 } | |
347 | |
348 PlatformFileError IsolatedFileUtil::CopyOrMoveFile( | |
349 FileSystemOperationContext* context, | |
350 const FileSystemURL& src_url, | |
351 const FileSystemURL& dest_url, | |
352 bool copy) { | |
353 return base::PLATFORM_FILE_ERROR_SECURITY; | |
354 } | |
355 | |
356 PlatformFileError IsolatedFileUtil::CopyInForeignFile( | |
357 FileSystemOperationContext* context, | |
358 const FilePath& src_file_path, | |
359 const FileSystemURL& dest_url) { | |
360 return base::PLATFORM_FILE_ERROR_SECURITY; | |
361 } | |
362 | |
363 PlatformFileError IsolatedFileUtil::DeleteFile( | |
364 FileSystemOperationContext* context, | |
365 const FileSystemURL& url) { | |
366 return base::PLATFORM_FILE_ERROR_SECURITY; | |
367 } | |
368 | |
369 PlatformFileError IsolatedFileUtil::DeleteSingleDirectory( | |
370 FileSystemOperationContext* context, | |
371 const FileSystemURL& url) { | |
372 return base::PLATFORM_FILE_ERROR_SECURITY; | |
373 } | |
374 | |
375 scoped_refptr<webkit_blob::ShareableFileReference> | |
376 IsolatedFileUtil::CreateSnapshotFile( | |
377 FileSystemOperationContext* context, | |
378 const FileSystemURL& url, | |
379 base::PlatformFileError* result, | |
380 base::PlatformFileInfo* file_info, | |
381 FilePath* platform_path) { | |
382 DCHECK(result); | |
383 *result = GetFileInfo(context, url, file_info, platform_path); | |
384 return NULL; | |
385 } | |
386 | |
387 bool IsolatedFileUtil::GetPlatformPath(const FileSystemURL& url, | |
388 FilePath* platform_path) const { | |
389 DCHECK(platform_path); | |
390 std::string filesystem_id; | |
391 if (!IsolatedContext::GetInstance()->CrackIsolatedPath( | |
392 url.path(), &filesystem_id, NULL, platform_path)) | |
393 return false; | |
394 return true; | |
395 } | 211 } |
396 | 212 |
397 } // namespace | 213 } // namespace |
OLD | NEW |