OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "webkit/fileapi/obfuscated_file_system_file_util.h" | |
6 | |
7 #include <queue> | |
8 #include <vector> | |
9 | |
10 #include "base/file_util.h" | |
11 #include "base/format_macros.h" | |
12 #include "base/logging.h" | |
13 #include "base/message_loop.h" | |
14 #include "base/string_number_conversions.h" | |
15 #include "base/stringprintf.h" | |
16 #include "base/sys_string_conversions.h" | |
17 #include "base/stl_util.h" | |
18 #include "googleurl/src/gurl.h" | |
19 #include "webkit/fileapi/file_system_context.h" | |
20 #include "webkit/fileapi/file_system_operation_context.h" | |
21 #include "webkit/fileapi/file_system_path_manager.h" | |
22 #include "webkit/fileapi/file_system_util.h" | |
23 #include "webkit/fileapi/sandbox_mount_point_provider.h" | |
24 | |
25 namespace { | |
26 | |
27 const int64 kFlushDelaySeconds = 10 * 60; // 10 minutes | |
28 | |
29 const char kOriginDatabaseName[] = "Origins"; | |
30 const char kDirectoryDatabaseName[] = "Paths"; | |
31 | |
32 void InitFileInfo( | |
33 fileapi::FileSystemDirectoryDatabase::FileInfo* file_info, | |
34 fileapi::FileSystemDirectoryDatabase::FileId parent_id, | |
35 const FilePath::StringType& file_name) { | |
36 DCHECK(file_info); | |
37 file_info->parent_id = parent_id; | |
38 file_info->name = file_name; | |
39 } | |
40 | |
41 bool IsRootDirectory(const FilePath& virtual_path) { | |
42 return (virtual_path.empty() || | |
43 virtual_path.value() == FILE_PATH_LITERAL("/")); | |
44 } | |
45 | |
46 const FilePath::CharType kLegacyDataDirectory[] = FILE_PATH_LITERAL("Legacy"); | |
47 | |
48 const FilePath::CharType kTemporaryDirectoryName[] = FILE_PATH_LITERAL("t"); | |
49 const FilePath::CharType kPersistentDirectoryName[] = FILE_PATH_LITERAL("p"); | |
50 | |
51 } // namespace | |
52 | |
53 namespace fileapi { | |
54 | |
55 using base::PlatformFile; | |
56 using base::PlatformFileError; | |
57 | |
58 ObfuscatedFileSystemFileUtil::ObfuscatedFileSystemFileUtil( | |
59 const FilePath& file_system_directory, | |
60 FileSystemFileUtil* underlying_file_util) | |
61 : file_system_directory_(file_system_directory), | |
62 underlying_file_util_(underlying_file_util) { | |
63 } | |
64 | |
65 ObfuscatedFileSystemFileUtil::~ObfuscatedFileSystemFileUtil() { | |
66 DropDatabases(); | |
67 } | |
68 | |
69 PlatformFileError ObfuscatedFileSystemFileUtil::CreateOrOpen( | |
70 FileSystemOperationContext* context, | |
71 const FilePath& virtual_path, int file_flags, | |
72 PlatformFile* file_handle, bool* created) { | |
73 DCHECK(!(file_flags & (base::PLATFORM_FILE_DELETE_ON_CLOSE | | |
74 base::PLATFORM_FILE_HIDDEN | base::PLATFORM_FILE_EXCLUSIVE_READ | | |
75 base::PLATFORM_FILE_EXCLUSIVE_WRITE))); | |
76 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
77 context->src_origin_url(), context->src_type(), true); | |
78 if (!db) | |
79 return base::PLATFORM_FILE_ERROR_FAILED; | |
80 FileId file_id; | |
81 if (!db->GetFileWithPath(virtual_path, &file_id)) { | |
82 // The file doesn't exist. | |
83 if (!(file_flags & (base::PLATFORM_FILE_CREATE | | |
84 base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_OPEN_ALWAYS))) | |
85 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
86 FileId parent_id; | |
87 if (!db->GetFileWithPath(virtual_path.DirName(), &parent_id)) | |
88 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
89 FileInfo file_info; | |
90 InitFileInfo(&file_info, parent_id, virtual_path.BaseName().value()); | |
91 PlatformFileError error = CreateFile( | |
92 context, context->src_origin_url(), context->src_type(), FilePath(), | |
93 &file_info, file_flags, file_handle); | |
94 if (created && base::PLATFORM_FILE_OK == error) | |
95 *created = true; | |
96 return error; | |
97 } | |
98 if (file_flags & base::PLATFORM_FILE_CREATE) | |
99 return base::PLATFORM_FILE_ERROR_EXISTS; | |
100 | |
101 FileInfo file_info; | |
102 if (!db->GetFileInfo(file_id, &file_info)) { | |
103 NOTREACHED(); | |
104 return base::PLATFORM_FILE_ERROR_FAILED; | |
105 } | |
106 if (file_info.is_directory()) | |
107 return base::PLATFORM_FILE_ERROR_NOT_A_FILE; | |
108 FilePath data_path = DataPathToLocalPath(context->src_origin_url(), | |
109 context->src_type(), file_info.data_path); | |
110 return underlying_file_util_->CreateOrOpen( | |
111 context, data_path, file_flags, file_handle, created); | |
112 } | |
113 | |
114 PlatformFileError ObfuscatedFileSystemFileUtil::EnsureFileExists( | |
115 FileSystemOperationContext* context, | |
116 const FilePath& virtual_path, | |
117 bool* created) { | |
118 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
119 context->src_origin_url(), context->src_type(), true); | |
120 if (!db) | |
121 return base::PLATFORM_FILE_ERROR_FAILED; | |
122 FileId file_id; | |
123 if (db->GetFileWithPath(virtual_path, &file_id)) { | |
124 FileInfo file_info; | |
125 if (!db->GetFileInfo(file_id, &file_info)) { | |
126 NOTREACHED(); | |
127 return base::PLATFORM_FILE_ERROR_FAILED; | |
128 } | |
129 if (file_info.is_directory()) | |
130 return base::PLATFORM_FILE_ERROR_NOT_A_FILE; | |
131 if (created) | |
132 *created = false; | |
133 return base::PLATFORM_FILE_OK; | |
134 } | |
135 FileId parent_id; | |
136 if (!db->GetFileWithPath(virtual_path.DirName(), &parent_id)) | |
137 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
138 | |
139 FileInfo file_info; | |
140 InitFileInfo(&file_info, parent_id, virtual_path.BaseName().value()); | |
141 PlatformFileError error = CreateFile(context, context->src_origin_url(), | |
142 context->src_type(), FilePath(), &file_info, 0, NULL); | |
143 if (created && base::PLATFORM_FILE_OK == error) | |
144 *created = true; | |
145 return error; | |
146 } | |
147 | |
148 PlatformFileError ObfuscatedFileSystemFileUtil::GetLocalFilePath( | |
149 FileSystemOperationContext* context, | |
150 const FilePath& virtual_path, | |
151 FilePath* local_path) { | |
152 FilePath path = | |
153 GetLocalPath(context->src_origin_url(), context->src_type(), | |
154 virtual_path); | |
155 if (path.empty()) | |
156 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
157 | |
158 *local_path = path; | |
159 return base::PLATFORM_FILE_OK; | |
160 } | |
161 | |
162 PlatformFileError ObfuscatedFileSystemFileUtil::GetFileInfo( | |
163 FileSystemOperationContext* context, | |
164 const FilePath& virtual_path, | |
165 base::PlatformFileInfo* file_info, | |
166 FilePath* platform_file_path) { | |
167 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
168 context->src_origin_url(), context->src_type(), false); | |
169 if (!db) | |
170 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
171 FileId file_id; | |
172 if (!db->GetFileWithPath(virtual_path, &file_id)) | |
173 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
174 FileInfo local_info; | |
175 return GetFileInfoInternal(db, context, file_id, | |
176 &local_info, file_info, platform_file_path); | |
177 } | |
178 | |
179 PlatformFileError ObfuscatedFileSystemFileUtil::ReadDirectory( | |
180 FileSystemOperationContext* context, | |
181 const FilePath& virtual_path, | |
182 std::vector<base::FileUtilProxy::Entry>* entries) { | |
183 // TODO(kkanetkar): Implement directory read in multiple chunks. | |
184 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
185 context->src_origin_url(), context->src_type(), false); | |
186 if (!db) { | |
187 if (IsRootDirectory(virtual_path)) { | |
188 // It's the root directory and the database hasn't been initialized yet. | |
189 entries->clear(); | |
190 return base::PLATFORM_FILE_OK; | |
191 } | |
192 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
193 } | |
194 FileId file_id; | |
195 if (!db->GetFileWithPath(virtual_path, &file_id)) | |
196 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
197 FileInfo file_info; | |
198 if (!db->GetFileInfo(file_id, &file_info)) { | |
199 DCHECK(!file_id); | |
200 // It's the root directory and the database hasn't been initialized yet. | |
201 entries->clear(); | |
202 return base::PLATFORM_FILE_OK; | |
203 } | |
204 if (!file_info.is_directory()) | |
205 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
206 std::vector<FileId> children; | |
207 if (!db->ListChildren(file_id, &children)) { | |
208 NOTREACHED(); | |
209 return base::PLATFORM_FILE_ERROR_FAILED; | |
210 } | |
211 std::vector<FileId>::iterator iter; | |
212 for (iter = children.begin(); iter != children.end(); ++iter) { | |
213 base::PlatformFileInfo platform_file_info; | |
214 FilePath file_path; | |
215 if (GetFileInfoInternal(db, context, *iter, | |
216 &file_info, &platform_file_info, &file_path) != | |
217 base::PLATFORM_FILE_OK) { | |
218 NOTREACHED(); | |
219 return base::PLATFORM_FILE_ERROR_FAILED; | |
220 } | |
221 | |
222 base::FileUtilProxy::Entry entry; | |
223 entry.name = file_info.name; | |
224 entry.is_directory = file_info.is_directory(); | |
225 entry.size = entry.is_directory ? 0 : platform_file_info.size; | |
226 entry.last_modified_time = platform_file_info.last_modified; | |
227 entries->push_back(entry); | |
228 } | |
229 return base::PLATFORM_FILE_OK; | |
230 } | |
231 | |
232 PlatformFileError ObfuscatedFileSystemFileUtil::CreateDirectory( | |
233 FileSystemOperationContext* context, | |
234 const FilePath& virtual_path, | |
235 bool exclusive, | |
236 bool recursive) { | |
237 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
238 context->src_origin_url(), context->src_type(), true); | |
239 if (!db) | |
240 return base::PLATFORM_FILE_ERROR_FAILED; | |
241 FileId file_id; | |
242 if (db->GetFileWithPath(virtual_path, &file_id)) { | |
243 FileInfo file_info; | |
244 if (exclusive) | |
245 return base::PLATFORM_FILE_ERROR_EXISTS; | |
246 if (!db->GetFileInfo(file_id, &file_info)) { | |
247 NOTREACHED(); | |
248 return base::PLATFORM_FILE_ERROR_FAILED; | |
249 } | |
250 if (!file_info.is_directory()) | |
251 return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; | |
252 return base::PLATFORM_FILE_OK; | |
253 } | |
254 | |
255 std::vector<FilePath::StringType> components; | |
256 virtual_path.GetComponents(&components); | |
257 FileId parent_id = 0; | |
258 size_t index; | |
259 for (index = 0; index < components.size(); ++index) { | |
260 FilePath::StringType name = components[index]; | |
261 if (name == FILE_PATH_LITERAL("/")) | |
262 continue; | |
263 if (!db->GetChildWithName(parent_id, name, &parent_id)) | |
264 break; | |
265 } | |
266 if (!recursive && components.size() - index > 1) | |
267 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
268 // TODO(dmikurube): Eliminate do_not_write_actually in future. | |
269 bool do_not_write_actually = context->do_not_write_actually(); | |
270 context->set_do_not_write_actually(true); | |
271 underlying_file_util_->CreateDirectory(context, | |
272 FilePath(), exclusive, recursive); | |
273 context->set_do_not_write_actually(do_not_write_actually); | |
274 for (; index < components.size(); ++index) { | |
275 FileInfo file_info; | |
276 file_info.name = components[index]; | |
277 if (file_info.name == FILE_PATH_LITERAL("/")) | |
278 continue; | |
279 file_info.modification_time = base::Time::Now(); | |
280 file_info.parent_id = parent_id; | |
281 if (!db->AddFileInfo(file_info, &parent_id)) { | |
282 NOTREACHED(); | |
283 return base::PLATFORM_FILE_ERROR_FAILED; | |
284 } | |
285 } | |
286 return base::PLATFORM_FILE_OK; | |
287 } | |
288 | |
289 PlatformFileError ObfuscatedFileSystemFileUtil::CopyOrMoveFile( | |
290 FileSystemOperationContext* context, | |
291 const FilePath& src_file_path, | |
292 const FilePath& dest_file_path, | |
293 bool copy) { | |
294 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
295 context->src_origin_url(), context->src_type(), true); | |
296 if (!db) | |
297 return base::PLATFORM_FILE_ERROR_FAILED; | |
298 FileId src_file_id; | |
299 if (!db->GetFileWithPath(src_file_path, &src_file_id)) | |
300 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
301 FileId dest_file_id; | |
302 bool overwrite = db->GetFileWithPath(dest_file_path, &dest_file_id); | |
303 FileInfo src_file_info; | |
304 FileInfo dest_file_info; | |
305 if (!db->GetFileInfo(src_file_id, &src_file_info) || | |
306 src_file_info.is_directory()) { | |
307 NOTREACHED(); | |
308 return base::PLATFORM_FILE_ERROR_FAILED; | |
309 } | |
310 if (overwrite) { | |
311 if (!db->GetFileInfo(dest_file_id, &dest_file_info) || | |
312 dest_file_info.is_directory()) { | |
313 NOTREACHED(); | |
314 return base::PLATFORM_FILE_ERROR_FAILED; | |
315 } | |
316 } | |
317 /* | |
318 * Copy-with-overwrite | |
319 * Just overwrite data file | |
320 * Copy-without-overwrite | |
321 * Copy backing file | |
322 * Create new metadata pointing to new backing file. | |
323 * Move-with-overwrite | |
324 * transaction: | |
325 * Remove source entry. | |
326 * Point target entry to source entry's backing file. | |
327 * Delete target entry's old backing file | |
328 * Move-without-overwrite | |
329 * Just update metadata | |
330 */ | |
331 if (copy) { | |
332 FilePath src_data_path = DataPathToLocalPath(context->src_origin_url(), | |
333 context->src_type(), src_file_info.data_path); | |
334 if (overwrite) { | |
335 FilePath dest_data_path = DataPathToLocalPath(context->src_origin_url(), | |
336 context->src_type(), dest_file_info.data_path); | |
337 return underlying_file_util_->CopyOrMoveFile(context, | |
338 src_data_path, dest_data_path, copy); | |
339 } else { | |
340 FileId dest_parent_id; | |
341 if (!db->GetFileWithPath(dest_file_path.DirName(), &dest_parent_id)) { | |
342 NOTREACHED(); // We shouldn't be called in this case. | |
343 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
344 } | |
345 InitFileInfo(&dest_file_info, dest_parent_id, | |
346 dest_file_path.BaseName().value()); | |
347 return CreateFile(context, context->dest_origin_url(), | |
348 context->dest_type(), src_data_path, &dest_file_info, 0, | |
349 NULL); | |
350 } | |
351 } else { // It's a move. | |
352 if (overwrite) { | |
353 if (!db->OverwritingMoveFile(src_file_id, dest_file_id)) | |
354 return base::PLATFORM_FILE_ERROR_FAILED; | |
355 FilePath dest_data_path = DataPathToLocalPath(context->src_origin_url(), | |
356 context->src_type(), dest_file_info.data_path); | |
357 if (base::PLATFORM_FILE_OK != | |
358 underlying_file_util_->DeleteFile(context, dest_data_path)) | |
359 LOG(WARNING) << "Leaked a backing file."; | |
360 return base::PLATFORM_FILE_OK; | |
361 } else { | |
362 FileId dest_parent_id; | |
363 if (!db->GetFileWithPath(dest_file_path.DirName(), &dest_parent_id)) { | |
364 NOTREACHED(); | |
365 return base::PLATFORM_FILE_ERROR_FAILED; | |
366 } | |
367 src_file_info.parent_id = dest_parent_id; | |
368 src_file_info.name = dest_file_path.BaseName().value(); | |
369 if (!db->UpdateFileInfo(src_file_id, src_file_info)) | |
370 return base::PLATFORM_FILE_ERROR_FAILED; | |
371 return base::PLATFORM_FILE_OK; | |
372 } | |
373 } | |
374 NOTREACHED(); | |
375 return base::PLATFORM_FILE_ERROR_FAILED; | |
376 } | |
377 | |
378 PlatformFileError ObfuscatedFileSystemFileUtil::CopyInForeignFile( | |
379 FileSystemOperationContext* context, | |
380 const FilePath& src_file_path, | |
381 const FilePath& dest_file_path) { | |
382 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
383 context->dest_origin_url(), context->dest_type(), true); | |
384 if (!db) | |
385 return base::PLATFORM_FILE_ERROR_FAILED; | |
386 FileId dest_file_id; | |
387 bool overwrite = db->GetFileWithPath(dest_file_path, &dest_file_id); | |
388 FileInfo dest_file_info; | |
389 if (overwrite) { | |
390 if (!db->GetFileInfo(dest_file_id, &dest_file_info) || | |
391 dest_file_info.is_directory()) { | |
392 NOTREACHED(); | |
393 return base::PLATFORM_FILE_ERROR_FAILED; | |
394 } | |
395 FilePath dest_data_path = DataPathToLocalPath(context->dest_origin_url(), | |
396 context->dest_type(), dest_file_info.data_path); | |
397 return underlying_file_util_->CopyOrMoveFile(context, | |
398 src_file_path, dest_data_path, true /* copy */); | |
399 } else { | |
400 FileId dest_parent_id; | |
401 if (!db->GetFileWithPath(dest_file_path.DirName(), &dest_parent_id)) { | |
402 NOTREACHED(); // We shouldn't be called in this case. | |
403 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
404 } | |
405 InitFileInfo(&dest_file_info, dest_parent_id, | |
406 dest_file_path.BaseName().value()); | |
407 return CreateFile(context, context->dest_origin_url(), | |
408 context->dest_type(), src_file_path, &dest_file_info, 0, NULL); | |
409 } | |
410 return base::PLATFORM_FILE_ERROR_FAILED; | |
411 } | |
412 | |
413 PlatformFileError ObfuscatedFileSystemFileUtil::DeleteFile( | |
414 FileSystemOperationContext* context, | |
415 const FilePath& virtual_path) { | |
416 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
417 context->src_origin_url(), context->src_type(), true); | |
418 if (!db) | |
419 return base::PLATFORM_FILE_ERROR_FAILED; | |
420 FileId file_id; | |
421 if (!db->GetFileWithPath(virtual_path, &file_id)) | |
422 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
423 FileInfo file_info; | |
424 if (!db->GetFileInfo(file_id, &file_info) || file_info.is_directory()) { | |
425 NOTREACHED(); | |
426 return base::PLATFORM_FILE_ERROR_FAILED; | |
427 } | |
428 if (!db->RemoveFileInfo(file_id)) { | |
429 NOTREACHED(); | |
430 return base::PLATFORM_FILE_ERROR_FAILED; | |
431 } | |
432 FilePath data_path = DataPathToLocalPath(context->src_origin_url(), | |
433 context->src_type(), file_info.data_path); | |
434 if (base::PLATFORM_FILE_OK != | |
435 underlying_file_util_->DeleteFile(context, data_path)) | |
436 LOG(WARNING) << "Leaked a backing file."; | |
437 return base::PLATFORM_FILE_OK; | |
438 } | |
439 | |
440 PlatformFileError ObfuscatedFileSystemFileUtil::DeleteSingleDirectory( | |
441 FileSystemOperationContext* context, | |
442 const FilePath& virtual_path) { | |
443 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
444 context->src_origin_url(), context->src_type(), true); | |
445 if (!db) | |
446 return base::PLATFORM_FILE_ERROR_FAILED; | |
447 FileId file_id; | |
448 if (!db->GetFileWithPath(virtual_path, &file_id)) | |
449 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
450 FileInfo file_info; | |
451 if (!db->GetFileInfo(file_id, &file_info) || !file_info.is_directory()) { | |
452 NOTREACHED(); | |
453 return base::PLATFORM_FILE_ERROR_FAILED; | |
454 } | |
455 if (!db->RemoveFileInfo(file_id)) | |
456 return base::PLATFORM_FILE_ERROR_NOT_EMPTY; | |
457 return base::PLATFORM_FILE_OK; | |
458 } | |
459 | |
460 PlatformFileError ObfuscatedFileSystemFileUtil::Touch( | |
461 FileSystemOperationContext* context, | |
462 const FilePath& virtual_path, | |
463 const base::Time& last_access_time, | |
464 const base::Time& last_modified_time) { | |
465 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
466 context->src_origin_url(), context->src_type(), true); | |
467 if (!db) | |
468 return base::PLATFORM_FILE_ERROR_FAILED; | |
469 FileId file_id; | |
470 if (db->GetFileWithPath(virtual_path, &file_id)) { | |
471 FileInfo file_info; | |
472 if (!db->GetFileInfo(file_id, &file_info)) { | |
473 NOTREACHED(); | |
474 return base::PLATFORM_FILE_ERROR_FAILED; | |
475 } | |
476 if (file_info.is_directory()) { | |
477 file_info.modification_time = last_modified_time; | |
478 if (!db->UpdateFileInfo(file_id, file_info)) | |
479 return base::PLATFORM_FILE_ERROR_FAILED; | |
480 return base::PLATFORM_FILE_OK; | |
481 } | |
482 FilePath data_path = DataPathToLocalPath(context->src_origin_url(), | |
483 context->src_type(), file_info.data_path); | |
484 return underlying_file_util_->Touch( | |
485 context, data_path, last_access_time, last_modified_time); | |
486 } | |
487 FileId parent_id; | |
488 if (!db->GetFileWithPath(virtual_path.DirName(), &parent_id)) | |
489 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
490 | |
491 FileInfo file_info; | |
492 InitFileInfo(&file_info, parent_id, virtual_path.BaseName().value()); | |
493 // In the event of a sporadic underlying failure, we might create a new file, | |
494 // but fail to update its mtime + atime. | |
495 PlatformFileError error = CreateFile(context, context->src_origin_url(), | |
496 context->src_type(), FilePath(), &file_info, 0, NULL); | |
497 if (base::PLATFORM_FILE_OK != error) | |
498 return error; | |
499 | |
500 FilePath data_path = DataPathToLocalPath(context->src_origin_url(), | |
501 context->src_type(), file_info.data_path); | |
502 return underlying_file_util_->Touch(context, data_path, | |
503 last_access_time, last_modified_time); | |
504 } | |
505 | |
506 PlatformFileError ObfuscatedFileSystemFileUtil::Truncate( | |
507 FileSystemOperationContext* context, | |
508 const FilePath& virtual_path, | |
509 int64 length) { | |
510 FilePath local_path = | |
511 GetLocalPath(context->src_origin_url(), context->src_type(), | |
512 virtual_path); | |
513 if (local_path.empty()) | |
514 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
515 return underlying_file_util_->Truncate( | |
516 context, local_path, length); | |
517 } | |
518 | |
519 bool ObfuscatedFileSystemFileUtil::PathExists( | |
520 FileSystemOperationContext* context, | |
521 const FilePath& virtual_path) { | |
522 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
523 context->src_origin_url(), context->src_type(), false); | |
524 if (!db) | |
525 return false; | |
526 FileId file_id; | |
527 return db->GetFileWithPath(virtual_path, &file_id); | |
528 } | |
529 | |
530 bool ObfuscatedFileSystemFileUtil::DirectoryExists( | |
531 FileSystemOperationContext* context, | |
532 const FilePath& virtual_path) { | |
533 if (IsRootDirectory(virtual_path)) { | |
534 // It's questionable whether we should return true or false for the | |
535 // root directory of nonexistent origin, but here we return true | |
536 // as the current implementation of ReadDirectory always returns an empty | |
537 // array (rather than erroring out with NOT_FOUND_ERR even) for | |
538 // nonexistent origins. | |
539 // Note: if you're going to change this behavior please also consider | |
540 // changiing the ReadDirectory's behavior! | |
541 return true; | |
542 } | |
543 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
544 context->src_origin_url(), context->src_type(), false); | |
545 if (!db) | |
546 return false; | |
547 FileId file_id; | |
548 if (!db->GetFileWithPath(virtual_path, &file_id)) | |
549 return false; | |
550 FileInfo file_info; | |
551 if (!db->GetFileInfo(file_id, &file_info)) { | |
552 NOTREACHED(); | |
553 return false; | |
554 } | |
555 return file_info.is_directory(); | |
556 } | |
557 | |
558 bool ObfuscatedFileSystemFileUtil::IsDirectoryEmpty( | |
559 FileSystemOperationContext* context, | |
560 const FilePath& virtual_path) { | |
561 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
562 context->src_origin_url(), context->src_type(), false); | |
563 if (!db) | |
564 return true; // Not a great answer, but it's what others do. | |
565 FileId file_id; | |
566 if (!db->GetFileWithPath(virtual_path, &file_id)) | |
567 return true; // Ditto. | |
568 FileInfo file_info; | |
569 if (!db->GetFileInfo(file_id, &file_info)) { | |
570 DCHECK(!file_id); | |
571 // It's the root directory and the database hasn't been initialized yet. | |
572 return true; | |
573 } | |
574 if (!file_info.is_directory()) | |
575 return true; | |
576 std::vector<FileId> children; | |
577 // TODO(ericu): This could easily be made faster with help from the database. | |
578 if (!db->ListChildren(file_id, &children)) | |
579 return true; | |
580 return children.empty(); | |
581 } | |
582 | |
583 class ObfuscatedFileSystemFileEnumerator | |
584 : public FileSystemFileUtil::AbstractFileEnumerator { | |
585 public: | |
586 ObfuscatedFileSystemFileEnumerator( | |
587 FileSystemDirectoryDatabase* db, const FilePath& virtual_root_path) | |
588 : db_(db) { | |
589 FileId file_id; | |
590 FileInfo file_info; | |
591 if (!db_->GetFileWithPath(virtual_root_path, &file_id)) | |
592 return; | |
593 if (!db_->GetFileInfo(file_id, &file_info)) | |
594 return; | |
595 if (!file_info.is_directory()) | |
596 return; | |
597 FileRecord record = { file_id, file_info, virtual_root_path }; | |
598 display_queue_.push(record); | |
599 Next(); // Enumerators don't include the directory itself. | |
600 } | |
601 | |
602 ~ObfuscatedFileSystemFileEnumerator() {} | |
603 | |
604 virtual FilePath Next() { | |
605 ProcessRecurseQueue(); | |
606 if (display_queue_.empty()) | |
607 return FilePath(); | |
608 current_ = display_queue_.front(); | |
609 display_queue_.pop(); | |
610 if (current_.file_info.is_directory()) | |
611 recurse_queue_.push(current_); | |
612 return current_.file_path; | |
613 } | |
614 | |
615 virtual bool IsDirectory() { | |
616 return current_.file_info.is_directory(); | |
617 } | |
618 | |
619 private: | |
620 typedef FileSystemDirectoryDatabase::FileId FileId; | |
621 typedef FileSystemDirectoryDatabase::FileInfo FileInfo; | |
622 | |
623 struct FileRecord { | |
624 FileId file_id; | |
625 FileInfo file_info; | |
626 FilePath file_path; | |
627 }; | |
628 | |
629 void ProcessRecurseQueue() { | |
630 while (display_queue_.empty() && !recurse_queue_.empty()) { | |
631 FileRecord directory = recurse_queue_.front(); | |
632 std::vector<FileId> children; | |
633 recurse_queue_.pop(); | |
634 if (!db_->ListChildren(directory.file_id, &children)) | |
635 return; | |
636 std::vector<FileId>::iterator iter; | |
637 for (iter = children.begin(); iter != children.end(); ++iter) { | |
638 FileRecord child; | |
639 child.file_id = *iter; | |
640 if (!db_->GetFileInfo(child.file_id, &child.file_info)) | |
641 return; | |
642 child.file_path = directory.file_path.Append(child.file_info.name); | |
643 display_queue_.push(child); | |
644 } | |
645 } | |
646 } | |
647 | |
648 std::queue<FileRecord> display_queue_; | |
649 std::queue<FileRecord> recurse_queue_; | |
650 FileRecord current_; | |
651 FileSystemDirectoryDatabase* db_; | |
652 }; | |
653 | |
654 class ObfuscatedFileSystemOriginEnumerator | |
655 : public ObfuscatedFileSystemFileUtil::AbstractOriginEnumerator { | |
656 public: | |
657 typedef FileSystemOriginDatabase::OriginRecord OriginRecord; | |
658 ObfuscatedFileSystemOriginEnumerator( | |
659 FileSystemOriginDatabase* origin_database, | |
660 const FilePath& base_path) | |
661 : base_path_(base_path) { | |
662 if (origin_database) | |
663 origin_database->ListAllOrigins(&origins_); | |
664 } | |
665 | |
666 ~ObfuscatedFileSystemOriginEnumerator() {} | |
667 | |
668 // Returns the next origin. Returns empty if there are no more origins. | |
669 virtual GURL Next() OVERRIDE { | |
670 OriginRecord record; | |
671 if (!origins_.empty()) { | |
672 record = origins_.back(); | |
673 origins_.pop_back(); | |
674 } | |
675 current_ = record; | |
676 return GetOriginURLFromIdentifier(record.origin); | |
677 } | |
678 | |
679 // Returns the current origin's information. | |
680 virtual bool HasFileSystemType(FileSystemType type) const OVERRIDE { | |
681 if (current_.path.empty()) | |
682 return false; | |
683 FilePath::StringType type_string = | |
684 ObfuscatedFileSystemFileUtil::GetDirectoryNameForType(type); | |
685 if (type_string.empty()) { | |
686 NOTREACHED(); | |
687 return false; | |
688 } | |
689 FilePath path = base_path_.Append(current_.path).Append(type_string); | |
690 return file_util::DirectoryExists(path); | |
691 } | |
692 | |
693 private: | |
694 std::vector<OriginRecord> origins_; | |
695 OriginRecord current_; | |
696 FilePath base_path_; | |
697 }; | |
698 | |
699 ObfuscatedFileSystemFileUtil::AbstractOriginEnumerator* | |
700 ObfuscatedFileSystemFileUtil::CreateOriginEnumerator() { | |
701 std::vector<FileSystemOriginDatabase::OriginRecord> origins; | |
702 | |
703 InitOriginDatabase(false); | |
704 return new ObfuscatedFileSystemOriginEnumerator( | |
705 origin_database_.get(), file_system_directory_); | |
706 } | |
707 | |
708 FileSystemFileUtil::AbstractFileEnumerator* | |
709 ObfuscatedFileSystemFileUtil::CreateFileEnumerator( | |
710 FileSystemOperationContext* context, | |
711 const FilePath& root_path) { | |
712 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
713 context->src_origin_url(), context->src_type(), false); | |
714 if (!db) | |
715 return new FileSystemFileUtil::EmptyFileEnumerator(); | |
716 return new ObfuscatedFileSystemFileEnumerator(db, root_path); | |
717 } | |
718 | |
719 PlatformFileError ObfuscatedFileSystemFileUtil::GetFileInfoInternal( | |
720 FileSystemDirectoryDatabase* db, | |
721 FileSystemOperationContext* context, | |
722 FileId file_id, | |
723 FileInfo* local_info, | |
724 base::PlatformFileInfo* file_info, | |
725 FilePath* platform_file_path) { | |
726 DCHECK(db); | |
727 DCHECK(context); | |
728 DCHECK(file_info); | |
729 DCHECK(platform_file_path); | |
730 | |
731 if (!db->GetFileInfo(file_id, local_info)) { | |
732 NOTREACHED(); | |
733 return base::PLATFORM_FILE_ERROR_FAILED; | |
734 } | |
735 | |
736 if (local_info->is_directory()) { | |
737 file_info->is_directory = true; | |
738 file_info->is_symbolic_link = false; | |
739 file_info->last_modified = local_info->modification_time; | |
740 *platform_file_path = FilePath(); | |
741 // We don't fill in ctime or atime. | |
742 return base::PLATFORM_FILE_OK; | |
743 } | |
744 if (local_info->data_path.empty()) | |
745 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | |
746 FilePath data_path = DataPathToLocalPath(context->src_origin_url(), | |
747 context->src_type(), local_info->data_path); | |
748 return underlying_file_util_->GetFileInfo( | |
749 context, data_path, file_info, platform_file_path); | |
750 } | |
751 | |
752 PlatformFileError ObfuscatedFileSystemFileUtil::CreateFile( | |
753 FileSystemOperationContext* context, | |
754 const GURL& origin_url, FileSystemType type, const FilePath& source_path, | |
755 FileInfo* file_info, int file_flags, PlatformFile* handle) { | |
756 if (handle) | |
757 *handle = base::kInvalidPlatformFileValue; | |
758 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
759 origin_url, type, true); | |
760 int64 number; | |
761 if (!db || !db->GetNextInteger(&number)) | |
762 return base::PLATFORM_FILE_ERROR_FAILED; | |
763 // We use the third- and fourth-to-last digits as the directory. | |
764 int64 directory_number = number % 10000 / 100; | |
765 FilePath path = | |
766 GetDirectoryForOriginAndType(origin_url, type, false); | |
767 if (path.empty()) | |
768 return base::PLATFORM_FILE_ERROR_FAILED; | |
769 | |
770 path = path.AppendASCII(StringPrintf("%02" PRIu64, directory_number)); | |
771 if (file_util::DirectoryExists(path.DirName())) { | |
772 if (!file_util::DirectoryExists(path) && !file_util::CreateDirectory(path)) | |
773 return base::PLATFORM_FILE_ERROR_FAILED; | |
774 } else { | |
775 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
776 } | |
777 path = path.AppendASCII(StringPrintf("%08" PRIu64, number)); | |
778 FilePath data_path = LocalPathToDataPath(origin_url, type, path); | |
779 if (data_path.empty()) | |
780 return base::PLATFORM_FILE_ERROR_FAILED; | |
781 PlatformFileError error; | |
782 bool created = false; | |
783 if (!source_path.empty()) { | |
784 DCHECK(!file_flags); | |
785 DCHECK(!handle); | |
786 error = underlying_file_util_->CopyOrMoveFile( | |
787 context, source_path, path, true /* copy */); | |
788 created = true; | |
789 } else { | |
790 if (handle) { | |
791 error = underlying_file_util_->CreateOrOpen( | |
792 context, path, file_flags, handle, &created); | |
793 // If this succeeds, we must close handle on any subsequent error. | |
794 } else { | |
795 DCHECK(!file_flags); // file_flags is only used by CreateOrOpen. | |
796 error = underlying_file_util_->EnsureFileExists( | |
797 context, path, &created); | |
798 } | |
799 } | |
800 if (error != base::PLATFORM_FILE_OK) | |
801 return error; | |
802 | |
803 if (!created) { | |
804 NOTREACHED(); | |
805 if (handle) { | |
806 DCHECK_NE(base::kInvalidPlatformFileValue, *handle); | |
807 base::ClosePlatformFile(*handle); | |
808 underlying_file_util_->DeleteFile(context, path); | |
809 } | |
810 return base::PLATFORM_FILE_ERROR_FAILED; | |
811 } | |
812 file_info->data_path = data_path; | |
813 FileId file_id; | |
814 if (!db->AddFileInfo(*file_info, &file_id)) { | |
815 if (handle) { | |
816 DCHECK_NE(base::kInvalidPlatformFileValue, *handle); | |
817 base::ClosePlatformFile(*handle); | |
818 } | |
819 underlying_file_util_->DeleteFile(context, path); | |
820 return base::PLATFORM_FILE_ERROR_FAILED; | |
821 } | |
822 | |
823 return base::PLATFORM_FILE_OK; | |
824 } | |
825 | |
826 FilePath ObfuscatedFileSystemFileUtil::GetLocalPath( | |
827 const GURL& origin_url, | |
828 FileSystemType type, | |
829 const FilePath& virtual_path) { | |
830 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
831 origin_url, type, false); | |
832 if (!db) | |
833 return FilePath(); | |
834 FileId file_id; | |
835 if (!db->GetFileWithPath(virtual_path, &file_id)) | |
836 return FilePath(); | |
837 FileInfo file_info; | |
838 if (!db->GetFileInfo(file_id, &file_info) || file_info.is_directory()) { | |
839 NOTREACHED(); | |
840 return FilePath(); // Directories have no local path. | |
841 } | |
842 return DataPathToLocalPath(origin_url, type, file_info.data_path); | |
843 } | |
844 | |
845 FilePath ObfuscatedFileSystemFileUtil::GetDirectoryForOriginAndType( | |
846 const GURL& origin, FileSystemType type, bool create) { | |
847 FilePath origin_dir = GetDirectoryForOrigin(origin, create); | |
848 if (origin_dir.empty()) | |
849 return FilePath(); | |
850 FilePath::StringType type_string = GetDirectoryNameForType(type); | |
851 if (type_string.empty()) { | |
852 LOG(WARNING) << "Unknown filesystem type requested:" << type; | |
853 return FilePath(); | |
854 } | |
855 FilePath path = origin_dir.Append(type_string); | |
856 if (!file_util::DirectoryExists(path) && | |
857 (!create || !file_util::CreateDirectory(path))) | |
858 return FilePath(); | |
859 return path; | |
860 } | |
861 | |
862 bool ObfuscatedFileSystemFileUtil::DeleteDirectoryForOriginAndType( | |
863 const GURL& origin, FileSystemType type) { | |
864 FilePath origin_type_path = GetDirectoryForOriginAndType(origin, type, false); | |
865 if (!file_util::PathExists(origin_type_path)) | |
866 return true; | |
867 | |
868 // TODO(dmikurube): Consider the return value of DestroyDirectoryDatabase. | |
869 // We ignore its error now since 1) it doesn't matter the final result, and | |
870 // 2) it always returns false in Windows because of LevelDB's implementation. | |
871 // Information about failure would be useful for debugging. | |
872 DestroyDirectoryDatabase(origin, type); | |
873 if (!file_util::Delete(origin_type_path, true /* recursive */)) | |
874 return false; | |
875 | |
876 FilePath origin_path = origin_type_path.DirName(); | |
877 DCHECK_EQ(origin_path.value(), GetDirectoryForOrigin(origin, false).value()); | |
878 | |
879 // Delete the origin directory if the deleted one was the last remaining | |
880 // type for the origin. | |
881 if (file_util::Delete(origin_path, false /* recursive */)) { | |
882 InitOriginDatabase(false); | |
883 if (origin_database_.get()) | |
884 origin_database_->RemovePathForOrigin(GetOriginIdentifierFromURL(origin)); | |
885 } | |
886 | |
887 // At this point we are sure we had successfully deleted the origin/type | |
888 // directory, so just returning true here. | |
889 return true; | |
890 } | |
891 | |
892 bool ObfuscatedFileSystemFileUtil::MigrateFromOldSandbox( | |
893 const GURL& origin_url, FileSystemType type, const FilePath& src_root) { | |
894 if (!DestroyDirectoryDatabase(origin_url, type)) | |
895 return false; | |
896 FilePath dest_root = GetDirectoryForOriginAndType(origin_url, type, true); | |
897 if (dest_root.empty()) | |
898 return false; | |
899 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
900 origin_url, type, false); | |
901 if (!db) | |
902 return false; | |
903 | |
904 file_util::FileEnumerator file_enum(src_root, true, | |
905 static_cast<file_util::FileEnumerator::FILE_TYPE>( | |
906 file_util::FileEnumerator::FILES | | |
907 file_util::FileEnumerator::DIRECTORIES)); | |
908 FilePath src_full_path; | |
909 size_t root_path_length = src_root.value().length() + 1; // +1 for the slash | |
910 while (!(src_full_path = file_enum.Next()).empty()) { | |
911 file_util::FileEnumerator::FindInfo info; | |
912 file_enum.GetFindInfo(&info); | |
913 FilePath relative_virtual_path = | |
914 FilePath(src_full_path.value().substr(root_path_length)); | |
915 if (relative_virtual_path.empty()) { | |
916 LOG(WARNING) << "Failed to convert path to relative: " << | |
917 src_full_path.value(); | |
918 return false; | |
919 } | |
920 FileId file_id; | |
921 if (db->GetFileWithPath(relative_virtual_path, &file_id)) { | |
922 NOTREACHED(); // File already exists. | |
923 return false; | |
924 } | |
925 if (!db->GetFileWithPath(relative_virtual_path.DirName(), &file_id)) { | |
926 NOTREACHED(); // Parent doesn't exist. | |
927 return false; | |
928 } | |
929 | |
930 FileInfo file_info; | |
931 file_info.name = src_full_path.BaseName().value(); | |
932 if (file_util::FileEnumerator::IsDirectory(info)) { | |
933 #if defined(OS_WIN) | |
934 file_info.modification_time = | |
935 base::Time::FromFileTime(info.ftLastWriteTime); | |
936 #elif defined(OS_POSIX) | |
937 file_info.modification_time = base::Time::FromTimeT(info.stat.st_mtime); | |
938 #endif | |
939 } else { | |
940 file_info.data_path = | |
941 FilePath(kLegacyDataDirectory).Append(relative_virtual_path); | |
942 } | |
943 file_info.parent_id = file_id; | |
944 if (!db->AddFileInfo(file_info, &file_id)) { | |
945 NOTREACHED(); | |
946 return false; | |
947 } | |
948 } | |
949 // TODO(ericu): Should we adjust the mtime of the root directory to match as | |
950 // well? | |
951 FilePath legacy_dest_dir = dest_root.Append(kLegacyDataDirectory); | |
952 | |
953 if (!file_util::Move(src_root, legacy_dest_dir)) { | |
954 LOG(WARNING) << | |
955 "The final step of a migration failed; I'll try to clean up."; | |
956 db = NULL; | |
957 DestroyDirectoryDatabase(origin_url, type); | |
958 return false; | |
959 } | |
960 return true; | |
961 } | |
962 | |
963 // static | |
964 FilePath::StringType ObfuscatedFileSystemFileUtil::GetDirectoryNameForType( | |
965 FileSystemType type) { | |
966 switch (type) { | |
967 case kFileSystemTypeTemporary: | |
968 return kTemporaryDirectoryName; | |
969 case kFileSystemTypePersistent: | |
970 return kPersistentDirectoryName; | |
971 case kFileSystemTypeUnknown: | |
972 default: | |
973 return FilePath::StringType(); | |
974 } | |
975 } | |
976 | |
977 FilePath ObfuscatedFileSystemFileUtil::DataPathToLocalPath( | |
978 const GURL& origin, FileSystemType type, const FilePath& data_path) { | |
979 FilePath root = GetDirectoryForOriginAndType(origin, type, false); | |
980 if (root.empty()) | |
981 return root; | |
982 return root.Append(data_path); | |
983 } | |
984 | |
985 FilePath ObfuscatedFileSystemFileUtil::LocalPathToDataPath( | |
986 const GURL& origin, FileSystemType type, const FilePath& local_path) { | |
987 FilePath root = GetDirectoryForOriginAndType(origin, type, false); | |
988 if (root.empty()) | |
989 return root; | |
990 // This removes the root, including the trailing slash, leaving a relative | |
991 // path. | |
992 return FilePath(local_path.value().substr(root.value().length() + 1)); | |
993 } | |
994 | |
995 // TODO: How to do the whole validation-without-creation thing? We may not have | |
996 // quota even to create the database. Ah, in that case don't even get here? | |
997 // Still doesn't answer the quota issue, though. | |
998 FileSystemDirectoryDatabase* ObfuscatedFileSystemFileUtil::GetDirectoryDatabase( | |
999 const GURL& origin, FileSystemType type, bool create) { | |
1000 std::string type_string = | |
1001 FileSystemPathManager::GetFileSystemTypeString(type); | |
1002 if (type_string.empty()) { | |
1003 LOG(WARNING) << "Unknown filesystem type requested:" << type; | |
1004 return NULL; | |
1005 } | |
1006 std::string key = GetOriginIdentifierFromURL(origin) + type_string; | |
1007 DirectoryMap::iterator iter = directories_.find(key); | |
1008 if (iter != directories_.end()) { | |
1009 MarkUsed(); | |
1010 return iter->second; | |
1011 } | |
1012 | |
1013 FilePath path = GetDirectoryForOriginAndType(origin, type, create); | |
1014 if (path.empty()) | |
1015 return NULL; | |
1016 if (!file_util::DirectoryExists(path)) { | |
1017 if (!file_util::CreateDirectory(path)) { | |
1018 LOG(WARNING) << "Failed to origin+type directory: " << path.value(); | |
1019 return NULL; | |
1020 } | |
1021 } | |
1022 MarkUsed(); | |
1023 path = path.AppendASCII(kDirectoryDatabaseName); | |
1024 FileSystemDirectoryDatabase* database = new FileSystemDirectoryDatabase(path); | |
1025 directories_[key] = database; | |
1026 return database; | |
1027 } | |
1028 | |
1029 FilePath ObfuscatedFileSystemFileUtil::GetDirectoryForOrigin( | |
1030 const GURL& origin, bool create) { | |
1031 if (!InitOriginDatabase(create)) | |
1032 return FilePath(); | |
1033 FilePath directory_name; | |
1034 std::string id = GetOriginIdentifierFromURL(origin); | |
1035 if (!create && !origin_database_->HasOriginPath(id)) | |
1036 return FilePath(); | |
1037 if (!origin_database_->GetPathForOrigin(id, &directory_name)) | |
1038 return FilePath(); | |
1039 FilePath path = file_system_directory_.Append(directory_name); | |
1040 if (!file_util::DirectoryExists(path) && | |
1041 (!create || !file_util::CreateDirectory(path))) | |
1042 return FilePath(); | |
1043 return path; | |
1044 } | |
1045 | |
1046 void ObfuscatedFileSystemFileUtil::MarkUsed() { | |
1047 if (timer_.IsRunning()) | |
1048 timer_.Reset(); | |
1049 else | |
1050 timer_.Start(base::TimeDelta::FromSeconds(kFlushDelaySeconds), this, | |
1051 &ObfuscatedFileSystemFileUtil::DropDatabases); | |
1052 } | |
1053 | |
1054 void ObfuscatedFileSystemFileUtil::DropDatabases() { | |
1055 origin_database_.reset(); | |
1056 STLDeleteContainerPairSecondPointers( | |
1057 directories_.begin(), directories_.end()); | |
1058 directories_.clear(); | |
1059 } | |
1060 | |
1061 bool ObfuscatedFileSystemFileUtil::DestroyDirectoryDatabase( | |
1062 const GURL& origin, FileSystemType type) { | |
1063 std::string type_string = | |
1064 FileSystemPathManager::GetFileSystemTypeString(type); | |
1065 if (type_string.empty()) { | |
1066 LOG(WARNING) << "Unknown filesystem type requested:" << type; | |
1067 return true; | |
1068 } | |
1069 std::string key = GetOriginIdentifierFromURL(origin) + type_string; | |
1070 DirectoryMap::iterator iter = directories_.find(key); | |
1071 if (iter != directories_.end()) { | |
1072 FileSystemDirectoryDatabase* database = iter->second; | |
1073 directories_.erase(iter); | |
1074 delete database; | |
1075 } | |
1076 | |
1077 FilePath path = GetDirectoryForOriginAndType(origin, type, false); | |
1078 if (path.empty()) | |
1079 return true; | |
1080 if (!file_util::DirectoryExists(path)) | |
1081 return true; | |
1082 path = path.AppendASCII(kDirectoryDatabaseName); | |
1083 return FileSystemDirectoryDatabase::DestroyDatabase(path); | |
1084 } | |
1085 | |
1086 bool ObfuscatedFileSystemFileUtil::InitOriginDatabase(bool create) { | |
1087 if (!origin_database_.get()) { | |
1088 if (!create && !file_util::DirectoryExists(file_system_directory_)) | |
1089 return false; | |
1090 if (!file_util::CreateDirectory(file_system_directory_)) { | |
1091 LOG(WARNING) << "Failed to create FileSystem directory: " << | |
1092 file_system_directory_.value(); | |
1093 return false; | |
1094 } | |
1095 origin_database_.reset( | |
1096 new FileSystemOriginDatabase( | |
1097 file_system_directory_.AppendASCII(kOriginDatabaseName))); | |
1098 } | |
1099 return true; | |
1100 } | |
1101 | |
1102 } // namespace fileapi | |
OLD | NEW |