OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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/obfuscated_file_system_file_util.h" | 5 #include "webkit/fileapi/obfuscated_file_util.h" |
6 | 6 |
7 #include <queue> | 7 #include <queue> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/file_util.h" | 11 #include "base/file_util.h" |
12 #include "base/format_macros.h" | 12 #include "base/format_macros.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/message_loop.h" | 14 #include "base/message_loop.h" |
15 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 const FilePath::CharType kTemporaryDirectoryName[] = FILE_PATH_LITERAL("t"); | 97 const FilePath::CharType kTemporaryDirectoryName[] = FILE_PATH_LITERAL("t"); |
98 const FilePath::CharType kPersistentDirectoryName[] = FILE_PATH_LITERAL("p"); | 98 const FilePath::CharType kPersistentDirectoryName[] = FILE_PATH_LITERAL("p"); |
99 | 99 |
100 } // namespace | 100 } // namespace |
101 | 101 |
102 namespace fileapi { | 102 namespace fileapi { |
103 | 103 |
104 using base::PlatformFile; | 104 using base::PlatformFile; |
105 using base::PlatformFileError; | 105 using base::PlatformFileError; |
106 | 106 |
107 ObfuscatedFileSystemFileUtil::ObfuscatedFileSystemFileUtil( | 107 class ObfuscatedFileEnumerator |
| 108 : public FileSystemFileUtil::AbstractFileEnumerator { |
| 109 public: |
| 110 ObfuscatedFileEnumerator( |
| 111 const FilePath& base_path, |
| 112 FileSystemDirectoryDatabase* db, |
| 113 FileSystemOperationContext* context, |
| 114 FileSystemFileUtil* underlying_file_util, |
| 115 const FilePath& virtual_root_path) |
| 116 : base_path_(base_path), |
| 117 db_(db), |
| 118 context_(context), |
| 119 underlying_file_util_(underlying_file_util) { |
| 120 DCHECK(db_); |
| 121 DCHECK(context_); |
| 122 DCHECK(underlying_file_util_); |
| 123 |
| 124 FileId file_id; |
| 125 FileInfo file_info; |
| 126 if (!db_->GetFileWithPath(virtual_root_path, &file_id)) |
| 127 return; |
| 128 if (!db_->GetFileInfo(file_id, &file_info)) |
| 129 return; |
| 130 if (!file_info.is_directory()) |
| 131 return; |
| 132 FileRecord record = { file_id, file_info, virtual_root_path }; |
| 133 display_queue_.push(record); |
| 134 Next(); // Enumerators don't include the directory itself. |
| 135 } |
| 136 |
| 137 ~ObfuscatedFileEnumerator() {} |
| 138 |
| 139 virtual FilePath Next() OVERRIDE { |
| 140 ProcessRecurseQueue(); |
| 141 if (display_queue_.empty()) |
| 142 return FilePath(); |
| 143 current_ = display_queue_.front(); |
| 144 display_queue_.pop(); |
| 145 if (current_.file_info.is_directory()) |
| 146 recurse_queue_.push(current_); |
| 147 return current_.file_path; |
| 148 } |
| 149 |
| 150 virtual int64 Size() OVERRIDE { |
| 151 if (IsDirectory()) |
| 152 return 0; |
| 153 |
| 154 base::PlatformFileInfo file_info; |
| 155 FilePath platform_file_path; |
| 156 |
| 157 FilePath local_path = base_path_.Append(current_.file_info.data_path); |
| 158 base::PlatformFileError error = underlying_file_util_->GetFileInfo( |
| 159 context_, local_path, &file_info, &platform_file_path); |
| 160 if (error != base::PLATFORM_FILE_OK) { |
| 161 LOG(WARNING) << "Lost a backing file."; |
| 162 return 0; |
| 163 } |
| 164 return file_info.size; |
| 165 } |
| 166 |
| 167 virtual bool IsDirectory() OVERRIDE { |
| 168 return current_.file_info.is_directory(); |
| 169 } |
| 170 |
| 171 private: |
| 172 typedef FileSystemDirectoryDatabase::FileId FileId; |
| 173 typedef FileSystemDirectoryDatabase::FileInfo FileInfo; |
| 174 |
| 175 struct FileRecord { |
| 176 FileId file_id; |
| 177 FileInfo file_info; |
| 178 FilePath file_path; |
| 179 }; |
| 180 |
| 181 void ProcessRecurseQueue() { |
| 182 while (display_queue_.empty() && !recurse_queue_.empty()) { |
| 183 FileRecord directory = recurse_queue_.front(); |
| 184 std::vector<FileId> children; |
| 185 recurse_queue_.pop(); |
| 186 if (!db_->ListChildren(directory.file_id, &children)) |
| 187 return; |
| 188 std::vector<FileId>::iterator iter; |
| 189 for (iter = children.begin(); iter != children.end(); ++iter) { |
| 190 FileRecord child; |
| 191 child.file_id = *iter; |
| 192 if (!db_->GetFileInfo(child.file_id, &child.file_info)) |
| 193 return; |
| 194 child.file_path = directory.file_path.Append(child.file_info.name); |
| 195 display_queue_.push(child); |
| 196 } |
| 197 } |
| 198 } |
| 199 |
| 200 std::queue<FileRecord> display_queue_; |
| 201 std::queue<FileRecord> recurse_queue_; |
| 202 FileRecord current_; |
| 203 FilePath base_path_; |
| 204 FileSystemDirectoryDatabase* db_; |
| 205 FileSystemOperationContext* context_; |
| 206 FileSystemFileUtil* underlying_file_util_; |
| 207 }; |
| 208 |
| 209 class ObfuscatedOriginEnumerator |
| 210 : public ObfuscatedFileUtil::AbstractOriginEnumerator { |
| 211 public: |
| 212 typedef FileSystemOriginDatabase::OriginRecord OriginRecord; |
| 213 ObfuscatedOriginEnumerator( |
| 214 FileSystemOriginDatabase* origin_database, |
| 215 const FilePath& base_path) |
| 216 : base_path_(base_path) { |
| 217 if (origin_database) |
| 218 origin_database->ListAllOrigins(&origins_); |
| 219 } |
| 220 |
| 221 ~ObfuscatedOriginEnumerator() {} |
| 222 |
| 223 // Returns the next origin. Returns empty if there are no more origins. |
| 224 virtual GURL Next() OVERRIDE { |
| 225 OriginRecord record; |
| 226 if (!origins_.empty()) { |
| 227 record = origins_.back(); |
| 228 origins_.pop_back(); |
| 229 } |
| 230 current_ = record; |
| 231 return GetOriginURLFromIdentifier(record.origin); |
| 232 } |
| 233 |
| 234 // Returns the current origin's information. |
| 235 virtual bool HasFileSystemType(FileSystemType type) const OVERRIDE { |
| 236 if (current_.path.empty()) |
| 237 return false; |
| 238 FilePath::StringType type_string = |
| 239 ObfuscatedFileUtil::GetDirectoryNameForType(type); |
| 240 if (type_string.empty()) { |
| 241 NOTREACHED(); |
| 242 return false; |
| 243 } |
| 244 FilePath path = base_path_.Append(current_.path).Append(type_string); |
| 245 return file_util::DirectoryExists(path); |
| 246 } |
| 247 |
| 248 private: |
| 249 std::vector<OriginRecord> origins_; |
| 250 OriginRecord current_; |
| 251 FilePath base_path_; |
| 252 }; |
| 253 |
| 254 ObfuscatedFileUtil::ObfuscatedFileUtil( |
108 const FilePath& file_system_directory, | 255 const FilePath& file_system_directory, |
109 FileSystemFileUtil* underlying_file_util) | 256 FileSystemFileUtil* underlying_file_util) |
110 : file_system_directory_(file_system_directory), | 257 : FileSystemFileUtil(underlying_file_util), |
111 underlying_file_util_(underlying_file_util) { | 258 file_system_directory_(file_system_directory) { |
112 } | 259 } |
113 | 260 |
114 ObfuscatedFileSystemFileUtil::~ObfuscatedFileSystemFileUtil() { | 261 ObfuscatedFileUtil::~ObfuscatedFileUtil() { |
115 DropDatabases(); | 262 DropDatabases(); |
116 } | 263 } |
117 | 264 |
118 PlatformFileError ObfuscatedFileSystemFileUtil::CreateOrOpen( | 265 PlatformFileError ObfuscatedFileUtil::CreateOrOpen( |
119 FileSystemOperationContext* context, | 266 FileSystemOperationContext* context, |
120 const FilePath& virtual_path, int file_flags, | 267 const FilePath& virtual_path, int file_flags, |
121 PlatformFile* file_handle, bool* created) { | 268 PlatformFile* file_handle, bool* created) { |
122 DCHECK(!(file_flags & (base::PLATFORM_FILE_DELETE_ON_CLOSE | | 269 DCHECK(!(file_flags & (base::PLATFORM_FILE_DELETE_ON_CLOSE | |
123 base::PLATFORM_FILE_HIDDEN | base::PLATFORM_FILE_EXCLUSIVE_READ | | 270 base::PLATFORM_FILE_HIDDEN | base::PLATFORM_FILE_EXCLUSIVE_READ | |
124 base::PLATFORM_FILE_EXCLUSIVE_WRITE))); | 271 base::PLATFORM_FILE_EXCLUSIVE_WRITE))); |
125 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | 272 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( |
126 context->src_origin_url(), context->src_type(), true); | 273 context->src_origin_url(), context->src_type(), true); |
127 if (!db) | 274 if (!db) |
128 return base::PLATFORM_FILE_ERROR_FAILED; | 275 return base::PLATFORM_FILE_ERROR_FAILED; |
(...skipping 22 matching lines...) Expand all Loading... |
151 | 298 |
152 FileInfo file_info; | 299 FileInfo file_info; |
153 if (!db->GetFileInfo(file_id, &file_info)) { | 300 if (!db->GetFileInfo(file_id, &file_info)) { |
154 NOTREACHED(); | 301 NOTREACHED(); |
155 return base::PLATFORM_FILE_ERROR_FAILED; | 302 return base::PLATFORM_FILE_ERROR_FAILED; |
156 } | 303 } |
157 if (file_info.is_directory()) | 304 if (file_info.is_directory()) |
158 return base::PLATFORM_FILE_ERROR_NOT_A_FILE; | 305 return base::PLATFORM_FILE_ERROR_NOT_A_FILE; |
159 FilePath local_path = DataPathToLocalPath(context->src_origin_url(), | 306 FilePath local_path = DataPathToLocalPath(context->src_origin_url(), |
160 context->src_type(), file_info.data_path); | 307 context->src_type(), file_info.data_path); |
161 base::PlatformFileError error = underlying_file_util_->CreateOrOpen( | 308 base::PlatformFileError error = underlying_file_util()->CreateOrOpen( |
162 context, local_path, file_flags, file_handle, created); | 309 context, local_path, file_flags, file_handle, created); |
163 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) { | 310 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) { |
164 // TODO(tzik): Also invalidate on-memory usage cache in UsageTracker. | 311 // TODO(tzik): Also invalidate on-memory usage cache in UsageTracker. |
165 // TODO(tzik): Delete database entry after ensuring the file lost. | 312 // TODO(tzik): Delete database entry after ensuring the file lost. |
166 context->file_system_context()->GetQuotaUtil(context->src_type())-> | 313 context->file_system_context()->GetQuotaUtil(context->src_type())-> |
167 InvalidateUsageCache(context->src_origin_url(), | 314 InvalidateUsageCache(context->src_origin_url(), |
168 context->src_type()); | 315 context->src_type()); |
169 LOG(WARNING) << "Lost a backing file."; | 316 LOG(WARNING) << "Lost a backing file."; |
170 error = base::PLATFORM_FILE_ERROR_FAILED; | 317 error = base::PLATFORM_FILE_ERROR_FAILED; |
171 } | 318 } |
172 return error; | 319 return error; |
173 } | 320 } |
174 | 321 |
175 PlatformFileError ObfuscatedFileSystemFileUtil::EnsureFileExists( | 322 PlatformFileError ObfuscatedFileUtil::EnsureFileExists( |
176 FileSystemOperationContext* context, | 323 FileSystemOperationContext* context, |
177 const FilePath& virtual_path, | 324 const FilePath& virtual_path, |
178 bool* created) { | 325 bool* created) { |
179 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | 326 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( |
180 context->src_origin_url(), context->src_type(), true); | 327 context->src_origin_url(), context->src_type(), true); |
181 if (!db) | 328 if (!db) |
182 return base::PLATFORM_FILE_ERROR_FAILED; | 329 return base::PLATFORM_FILE_ERROR_FAILED; |
183 FileId file_id; | 330 FileId file_id; |
184 if (db->GetFileWithPath(virtual_path, &file_id)) { | 331 if (db->GetFileWithPath(virtual_path, &file_id)) { |
185 FileInfo file_info; | 332 FileInfo file_info; |
(...skipping 15 matching lines...) Expand all Loading... |
201 InitFileInfo(&file_info, parent_id, virtual_path.BaseName().value()); | 348 InitFileInfo(&file_info, parent_id, virtual_path.BaseName().value()); |
202 if (!AllocateQuotaForPath(context, 1, file_info.name.size())) | 349 if (!AllocateQuotaForPath(context, 1, file_info.name.size())) |
203 return base::PLATFORM_FILE_ERROR_NO_SPACE; | 350 return base::PLATFORM_FILE_ERROR_NO_SPACE; |
204 PlatformFileError error = CreateFile(context, context->src_origin_url(), | 351 PlatformFileError error = CreateFile(context, context->src_origin_url(), |
205 context->src_type(), FilePath(), &file_info, 0, NULL); | 352 context->src_type(), FilePath(), &file_info, 0, NULL); |
206 if (created && base::PLATFORM_FILE_OK == error) | 353 if (created && base::PLATFORM_FILE_OK == error) |
207 *created = true; | 354 *created = true; |
208 return error; | 355 return error; |
209 } | 356 } |
210 | 357 |
211 PlatformFileError ObfuscatedFileSystemFileUtil::GetLocalFilePath( | 358 PlatformFileError ObfuscatedFileUtil::CreateDirectory( |
212 FileSystemOperationContext* context, | 359 FileSystemOperationContext* context, |
213 const FilePath& virtual_path, | 360 const FilePath& virtual_path, |
214 FilePath* local_path) { | 361 bool exclusive, |
215 FilePath path = | 362 bool recursive) { |
216 GetLocalPath(context->src_origin_url(), context->src_type(), | 363 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( |
217 virtual_path); | 364 context->src_origin_url(), context->src_type(), true); |
218 if (path.empty()) | 365 if (!db) |
| 366 return base::PLATFORM_FILE_ERROR_FAILED; |
| 367 FileId file_id; |
| 368 if (db->GetFileWithPath(virtual_path, &file_id)) { |
| 369 FileInfo file_info; |
| 370 if (exclusive) |
| 371 return base::PLATFORM_FILE_ERROR_EXISTS; |
| 372 if (!db->GetFileInfo(file_id, &file_info)) { |
| 373 NOTREACHED(); |
| 374 return base::PLATFORM_FILE_ERROR_FAILED; |
| 375 } |
| 376 if (!file_info.is_directory()) |
| 377 return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; |
| 378 return base::PLATFORM_FILE_OK; |
| 379 } |
| 380 |
| 381 std::vector<FilePath::StringType> components; |
| 382 virtual_path.GetComponents(&components); |
| 383 FileId parent_id = 0; |
| 384 size_t index; |
| 385 for (index = 0; index < components.size(); ++index) { |
| 386 FilePath::StringType name = components[index]; |
| 387 if (name == FILE_PATH_LITERAL("/")) |
| 388 continue; |
| 389 if (!db->GetChildWithName(parent_id, name, &parent_id)) |
| 390 break; |
| 391 } |
| 392 if (!recursive && components.size() - index > 1) |
219 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | 393 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
220 | 394 for (; index < components.size(); ++index) { |
221 *local_path = path; | 395 FileInfo file_info; |
| 396 file_info.name = components[index]; |
| 397 if (file_info.name == FILE_PATH_LITERAL("/")) |
| 398 continue; |
| 399 file_info.modification_time = base::Time::Now(); |
| 400 file_info.parent_id = parent_id; |
| 401 if (!AllocateQuotaForPath(context, 1, file_info.name.size())) |
| 402 return base::PLATFORM_FILE_ERROR_NO_SPACE; |
| 403 if (!db->AddFileInfo(file_info, &parent_id)) { |
| 404 NOTREACHED(); |
| 405 return base::PLATFORM_FILE_ERROR_FAILED; |
| 406 } |
| 407 UpdatePathQuotaUsage(context, context->src_origin_url(), |
| 408 context->src_type(), 1, file_info.name.size()); |
| 409 } |
222 return base::PLATFORM_FILE_OK; | 410 return base::PLATFORM_FILE_OK; |
223 } | 411 } |
224 | 412 |
225 PlatformFileError ObfuscatedFileSystemFileUtil::GetFileInfo( | 413 PlatformFileError ObfuscatedFileUtil::GetFileInfo( |
226 FileSystemOperationContext* context, | 414 FileSystemOperationContext* context, |
227 const FilePath& virtual_path, | 415 const FilePath& virtual_path, |
228 base::PlatformFileInfo* file_info, | 416 base::PlatformFileInfo* file_info, |
229 FilePath* platform_file_path) { | 417 FilePath* platform_file_path) { |
230 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | 418 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( |
231 context->src_origin_url(), context->src_type(), false); | 419 context->src_origin_url(), context->src_type(), false); |
232 if (!db) | 420 if (!db) |
233 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | 421 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
234 FileId file_id; | 422 FileId file_id; |
235 if (!db->GetFileWithPath(virtual_path, &file_id)) | 423 if (!db->GetFileWithPath(virtual_path, &file_id)) |
236 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | 424 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
237 FileInfo local_info; | 425 FileInfo local_info; |
238 return GetFileInfoInternal(db, context, file_id, | 426 return GetFileInfoInternal(db, context, file_id, |
239 &local_info, file_info, platform_file_path); | 427 &local_info, file_info, platform_file_path); |
240 } | 428 } |
241 | 429 |
242 PlatformFileError ObfuscatedFileSystemFileUtil::ReadDirectory( | 430 PlatformFileError ObfuscatedFileUtil::ReadDirectory( |
243 FileSystemOperationContext* context, | 431 FileSystemOperationContext* context, |
244 const FilePath& virtual_path, | 432 const FilePath& virtual_path, |
245 std::vector<base::FileUtilProxy::Entry>* entries) { | 433 std::vector<base::FileUtilProxy::Entry>* entries) { |
246 // TODO(kkanetkar): Implement directory read in multiple chunks. | 434 // TODO(kkanetkar): Implement directory read in multiple chunks. |
247 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | 435 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( |
248 context->src_origin_url(), context->src_type(), false); | 436 context->src_origin_url(), context->src_type(), false); |
249 if (!db) { | 437 if (!db) { |
250 if (IsRootDirectory(virtual_path)) { | 438 if (IsRootDirectory(virtual_path)) { |
251 // It's the root directory and the database hasn't been initialized yet. | 439 // It's the root directory and the database hasn't been initialized yet. |
252 entries->clear(); | 440 entries->clear(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 base::FileUtilProxy::Entry entry; | 476 base::FileUtilProxy::Entry entry; |
289 entry.name = file_info.name; | 477 entry.name = file_info.name; |
290 entry.is_directory = file_info.is_directory(); | 478 entry.is_directory = file_info.is_directory(); |
291 entry.size = entry.is_directory ? 0 : platform_file_info.size; | 479 entry.size = entry.is_directory ? 0 : platform_file_info.size; |
292 entry.last_modified_time = platform_file_info.last_modified; | 480 entry.last_modified_time = platform_file_info.last_modified; |
293 entries->push_back(entry); | 481 entries->push_back(entry); |
294 } | 482 } |
295 return base::PLATFORM_FILE_OK; | 483 return base::PLATFORM_FILE_OK; |
296 } | 484 } |
297 | 485 |
298 PlatformFileError ObfuscatedFileSystemFileUtil::CreateDirectory( | 486 FileSystemFileUtil::AbstractFileEnumerator* |
| 487 ObfuscatedFileUtil::CreateFileEnumerator( |
| 488 FileSystemOperationContext* context, |
| 489 const FilePath& root_path) { |
| 490 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( |
| 491 context->src_origin_url(), context->src_type(), false); |
| 492 if (!db) |
| 493 return new FileSystemFileUtil::EmptyFileEnumerator(); |
| 494 return new ObfuscatedFileEnumerator( |
| 495 GetDirectoryForOriginAndType(context->src_origin_url(), |
| 496 context->src_type(), false), |
| 497 db, |
| 498 context, |
| 499 underlying_file_util(), |
| 500 root_path); |
| 501 } |
| 502 |
| 503 PlatformFileError ObfuscatedFileUtil::GetLocalFilePath( |
299 FileSystemOperationContext* context, | 504 FileSystemOperationContext* context, |
300 const FilePath& virtual_path, | 505 const FilePath& virtual_path, |
301 bool exclusive, | 506 FilePath* local_path) { |
302 bool recursive) { | 507 FilePath path = |
303 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | 508 GetLocalPath(context->src_origin_url(), context->src_type(), |
304 context->src_origin_url(), context->src_type(), true); | 509 virtual_path); |
305 if (!db) | 510 if (path.empty()) |
306 return base::PLATFORM_FILE_ERROR_FAILED; | 511 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
307 FileId file_id; | |
308 if (db->GetFileWithPath(virtual_path, &file_id)) { | |
309 FileInfo file_info; | |
310 if (exclusive) | |
311 return base::PLATFORM_FILE_ERROR_EXISTS; | |
312 if (!db->GetFileInfo(file_id, &file_info)) { | |
313 NOTREACHED(); | |
314 return base::PLATFORM_FILE_ERROR_FAILED; | |
315 } | |
316 if (!file_info.is_directory()) | |
317 return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; | |
318 return base::PLATFORM_FILE_OK; | |
319 } | |
320 | 512 |
321 std::vector<FilePath::StringType> components; | 513 *local_path = path; |
322 virtual_path.GetComponents(&components); | |
323 FileId parent_id = 0; | |
324 size_t index; | |
325 for (index = 0; index < components.size(); ++index) { | |
326 FilePath::StringType name = components[index]; | |
327 if (name == FILE_PATH_LITERAL("/")) | |
328 continue; | |
329 if (!db->GetChildWithName(parent_id, name, &parent_id)) | |
330 break; | |
331 } | |
332 if (!recursive && components.size() - index > 1) | |
333 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
334 for (; index < components.size(); ++index) { | |
335 FileInfo file_info; | |
336 file_info.name = components[index]; | |
337 if (file_info.name == FILE_PATH_LITERAL("/")) | |
338 continue; | |
339 file_info.modification_time = base::Time::Now(); | |
340 file_info.parent_id = parent_id; | |
341 if (!AllocateQuotaForPath(context, 1, file_info.name.size())) | |
342 return base::PLATFORM_FILE_ERROR_NO_SPACE; | |
343 if (!db->AddFileInfo(file_info, &parent_id)) { | |
344 NOTREACHED(); | |
345 return base::PLATFORM_FILE_ERROR_FAILED; | |
346 } | |
347 UpdatePathQuotaUsage(context, context->src_origin_url(), | |
348 context->src_type(), 1, file_info.name.size()); | |
349 } | |
350 return base::PLATFORM_FILE_OK; | 514 return base::PLATFORM_FILE_OK; |
351 } | 515 } |
352 | 516 |
353 PlatformFileError ObfuscatedFileSystemFileUtil::CopyOrMoveFile( | 517 PlatformFileError ObfuscatedFileUtil::Touch( |
| 518 FileSystemOperationContext* context, |
| 519 const FilePath& virtual_path, |
| 520 const base::Time& last_access_time, |
| 521 const base::Time& last_modified_time) { |
| 522 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( |
| 523 context->src_origin_url(), context->src_type(), false); |
| 524 if (!db) |
| 525 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 526 FileId file_id; |
| 527 if (!db->GetFileWithPath(virtual_path, &file_id)) |
| 528 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 529 |
| 530 FileInfo file_info; |
| 531 if (!db->GetFileInfo(file_id, &file_info)) { |
| 532 NOTREACHED(); |
| 533 return base::PLATFORM_FILE_ERROR_FAILED; |
| 534 } |
| 535 if (file_info.is_directory()) { |
| 536 file_info.modification_time = last_modified_time; |
| 537 if (!db->UpdateFileInfo(file_id, file_info)) |
| 538 return base::PLATFORM_FILE_ERROR_FAILED; |
| 539 return base::PLATFORM_FILE_OK; |
| 540 } |
| 541 FilePath data_path = DataPathToLocalPath(context->src_origin_url(), |
| 542 context->src_type(), file_info.data_path); |
| 543 return underlying_file_util()->Touch( |
| 544 context, data_path, last_access_time, last_modified_time); |
| 545 } |
| 546 |
| 547 PlatformFileError ObfuscatedFileUtil::Truncate( |
| 548 FileSystemOperationContext* context, |
| 549 const FilePath& virtual_path, |
| 550 int64 length) { |
| 551 FilePath local_path = |
| 552 GetLocalPath(context->src_origin_url(), context->src_type(), |
| 553 virtual_path); |
| 554 if (local_path.empty()) |
| 555 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 556 return underlying_file_util()->Truncate( |
| 557 context, local_path, length); |
| 558 } |
| 559 |
| 560 bool ObfuscatedFileUtil::PathExists( |
| 561 FileSystemOperationContext* context, |
| 562 const FilePath& virtual_path) { |
| 563 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( |
| 564 context->src_origin_url(), context->src_type(), false); |
| 565 if (!db) |
| 566 return false; |
| 567 FileId file_id; |
| 568 return db->GetFileWithPath(virtual_path, &file_id); |
| 569 } |
| 570 |
| 571 bool ObfuscatedFileUtil::DirectoryExists( |
| 572 FileSystemOperationContext* context, |
| 573 const FilePath& virtual_path) { |
| 574 if (IsRootDirectory(virtual_path)) { |
| 575 // It's questionable whether we should return true or false for the |
| 576 // root directory of nonexistent origin, but here we return true |
| 577 // as the current implementation of ReadDirectory always returns an empty |
| 578 // array (rather than erroring out with NOT_FOUND_ERR even) for |
| 579 // nonexistent origins. |
| 580 // Note: if you're going to change this behavior please also consider |
| 581 // changiing the ReadDirectory's behavior! |
| 582 return true; |
| 583 } |
| 584 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( |
| 585 context->src_origin_url(), context->src_type(), false); |
| 586 if (!db) |
| 587 return false; |
| 588 FileId file_id; |
| 589 if (!db->GetFileWithPath(virtual_path, &file_id)) |
| 590 return false; |
| 591 FileInfo file_info; |
| 592 if (!db->GetFileInfo(file_id, &file_info)) { |
| 593 NOTREACHED(); |
| 594 return false; |
| 595 } |
| 596 return file_info.is_directory(); |
| 597 } |
| 598 |
| 599 bool ObfuscatedFileUtil::IsDirectoryEmpty( |
| 600 FileSystemOperationContext* context, |
| 601 const FilePath& virtual_path) { |
| 602 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( |
| 603 context->src_origin_url(), context->src_type(), false); |
| 604 if (!db) |
| 605 return true; // Not a great answer, but it's what others do. |
| 606 FileId file_id; |
| 607 if (!db->GetFileWithPath(virtual_path, &file_id)) |
| 608 return true; // Ditto. |
| 609 FileInfo file_info; |
| 610 if (!db->GetFileInfo(file_id, &file_info)) { |
| 611 DCHECK(!file_id); |
| 612 // It's the root directory and the database hasn't been initialized yet. |
| 613 return true; |
| 614 } |
| 615 if (!file_info.is_directory()) |
| 616 return true; |
| 617 std::vector<FileId> children; |
| 618 // TODO(ericu): This could easily be made faster with help from the database. |
| 619 if (!db->ListChildren(file_id, &children)) |
| 620 return true; |
| 621 return children.empty(); |
| 622 } |
| 623 |
| 624 PlatformFileError ObfuscatedFileUtil::CopyOrMoveFile( |
354 FileSystemOperationContext* context, | 625 FileSystemOperationContext* context, |
355 const FilePath& src_file_path, | 626 const FilePath& src_file_path, |
356 const FilePath& dest_file_path, | 627 const FilePath& dest_file_path, |
357 bool copy) { | 628 bool copy) { |
358 // Cross-filesystem copies and moves should be handled via CopyInForeignFile. | 629 // Cross-filesystem copies and moves should be handled via CopyInForeignFile. |
359 DCHECK(context->src_origin_url() == context->dest_origin_url()); | 630 DCHECK(context->src_origin_url() == context->dest_origin_url()); |
360 DCHECK(context->src_type() == context->dest_type()); | 631 DCHECK(context->src_type() == context->dest_type()); |
361 | 632 |
362 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | 633 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( |
363 context->src_origin_url(), context->src_type(), true); | 634 context->src_origin_url(), context->src_type(), true); |
(...skipping 28 matching lines...) Expand all Loading... |
392 * transaction: | 663 * transaction: |
393 * Remove source entry. | 664 * Remove source entry. |
394 * Point target entry to source entry's backing file. | 665 * Point target entry to source entry's backing file. |
395 * Delete target entry's old backing file | 666 * Delete target entry's old backing file |
396 * Move-without-overwrite | 667 * Move-without-overwrite |
397 * Just update metadata | 668 * Just update metadata |
398 */ | 669 */ |
399 if (copy) { | 670 if (copy) { |
400 FilePath src_data_path = DataPathToLocalPath(context->src_origin_url(), | 671 FilePath src_data_path = DataPathToLocalPath(context->src_origin_url(), |
401 context->src_type(), src_file_info.data_path); | 672 context->src_type(), src_file_info.data_path); |
402 if (!underlying_file_util_->PathExists(context, src_data_path)) { | 673 if (!underlying_file_util()->PathExists(context, src_data_path)) { |
403 // TODO(tzik): Also invalidate on-memory usage cache in UsageTracker. | 674 // TODO(tzik): Also invalidate on-memory usage cache in UsageTracker. |
404 context->file_system_context()->GetQuotaUtil(context->src_type())-> | 675 context->file_system_context()->GetQuotaUtil(context->src_type())-> |
405 InvalidateUsageCache(context->src_origin_url(), | 676 InvalidateUsageCache(context->src_origin_url(), |
406 context->src_type()); | 677 context->src_type()); |
407 LOG(WARNING) << "Lost a backing file."; | 678 LOG(WARNING) << "Lost a backing file."; |
408 return base::PLATFORM_FILE_ERROR_FAILED; | 679 return base::PLATFORM_FILE_ERROR_FAILED; |
409 } | 680 } |
410 | 681 |
411 if (overwrite) { | 682 if (overwrite) { |
412 FilePath dest_data_path = DataPathToLocalPath(context->src_origin_url(), | 683 FilePath dest_data_path = DataPathToLocalPath(context->src_origin_url(), |
413 context->src_type(), dest_file_info.data_path); | 684 context->src_type(), dest_file_info.data_path); |
414 return underlying_file_util_->CopyOrMoveFile(context, | 685 return underlying_file_util()->CopyOrMoveFile(context, |
415 src_data_path, dest_data_path, copy); | 686 src_data_path, dest_data_path, copy); |
416 } else { | 687 } else { |
417 FileId dest_parent_id; | 688 FileId dest_parent_id; |
418 if (!db->GetFileWithPath(dest_file_path.DirName(), &dest_parent_id)) { | 689 if (!db->GetFileWithPath(dest_file_path.DirName(), &dest_parent_id)) { |
419 NOTREACHED(); // We shouldn't be called in this case. | 690 NOTREACHED(); // We shouldn't be called in this case. |
420 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | 691 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
421 } | 692 } |
422 InitFileInfo(&dest_file_info, dest_parent_id, | 693 InitFileInfo(&dest_file_info, dest_parent_id, |
423 dest_file_path.BaseName().value()); | 694 dest_file_path.BaseName().value()); |
424 if (!AllocateQuotaForPath(context, 1, dest_file_info.name.size())) | 695 if (!AllocateQuotaForPath(context, 1, dest_file_info.name.size())) |
425 return base::PLATFORM_FILE_ERROR_NO_SPACE; | 696 return base::PLATFORM_FILE_ERROR_NO_SPACE; |
426 return CreateFile(context, context->dest_origin_url(), | 697 return CreateFile(context, context->dest_origin_url(), |
427 context->dest_type(), src_data_path, &dest_file_info, 0, | 698 context->dest_type(), src_data_path, &dest_file_info, 0, |
428 NULL); | 699 NULL); |
429 } | 700 } |
430 } else { // It's a move. | 701 } else { // It's a move. |
431 if (overwrite) { | 702 if (overwrite) { |
432 AllocateQuotaForPath(context, -1, | 703 AllocateQuotaForPath(context, -1, |
433 -static_cast<int64>(src_file_info.name.size())); | 704 -static_cast<int64>(src_file_info.name.size())); |
434 if (!db->OverwritingMoveFile(src_file_id, dest_file_id)) | 705 if (!db->OverwritingMoveFile(src_file_id, dest_file_id)) |
435 return base::PLATFORM_FILE_ERROR_FAILED; | 706 return base::PLATFORM_FILE_ERROR_FAILED; |
436 FilePath dest_data_path = DataPathToLocalPath(context->src_origin_url(), | 707 FilePath dest_data_path = DataPathToLocalPath(context->src_origin_url(), |
437 context->src_type(), dest_file_info.data_path); | 708 context->src_type(), dest_file_info.data_path); |
438 if (base::PLATFORM_FILE_OK != | 709 if (base::PLATFORM_FILE_OK != |
439 underlying_file_util_->DeleteFile(context, dest_data_path)) | 710 underlying_file_util()->DeleteFile(context, dest_data_path)) |
440 LOG(WARNING) << "Leaked a backing file."; | 711 LOG(WARNING) << "Leaked a backing file."; |
441 UpdatePathQuotaUsage(context, context->src_origin_url(), | 712 UpdatePathQuotaUsage(context, context->src_origin_url(), |
442 context->src_type(), -1, | 713 context->src_type(), -1, |
443 -static_cast<int64>(src_file_info.name.size())); | 714 -static_cast<int64>(src_file_info.name.size())); |
444 return base::PLATFORM_FILE_OK; | 715 return base::PLATFORM_FILE_OK; |
445 } else { | 716 } else { |
446 FileId dest_parent_id; | 717 FileId dest_parent_id; |
447 if (!db->GetFileWithPath(dest_file_path.DirName(), &dest_parent_id)) { | 718 if (!db->GetFileWithPath(dest_file_path.DirName(), &dest_parent_id)) { |
448 NOTREACHED(); | 719 NOTREACHED(); |
449 return base::PLATFORM_FILE_ERROR_FAILED; | 720 return base::PLATFORM_FILE_ERROR_FAILED; |
(...skipping 11 matching lines...) Expand all Loading... |
461 context, context->src_origin_url(), context->src_type(), 0, | 732 context, context->src_origin_url(), context->src_type(), 0, |
462 static_cast<int64>(dest_file_path.BaseName().value().size()) - | 733 static_cast<int64>(dest_file_path.BaseName().value().size()) - |
463 static_cast<int64>(src_file_path.BaseName().value().size())); | 734 static_cast<int64>(src_file_path.BaseName().value().size())); |
464 return base::PLATFORM_FILE_OK; | 735 return base::PLATFORM_FILE_OK; |
465 } | 736 } |
466 } | 737 } |
467 NOTREACHED(); | 738 NOTREACHED(); |
468 return base::PLATFORM_FILE_ERROR_FAILED; | 739 return base::PLATFORM_FILE_ERROR_FAILED; |
469 } | 740 } |
470 | 741 |
471 PlatformFileError ObfuscatedFileSystemFileUtil::CopyInForeignFile( | 742 PlatformFileError ObfuscatedFileUtil::CopyInForeignFile( |
472 FileSystemOperationContext* context, | 743 FileSystemOperationContext* context, |
473 const FilePath& src_file_path, | 744 const FilePath& src_file_path, |
474 const FilePath& dest_file_path) { | 745 const FilePath& dest_file_path) { |
475 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | 746 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( |
476 context->dest_origin_url(), context->dest_type(), true); | 747 context->dest_origin_url(), context->dest_type(), true); |
477 if (!db) | 748 if (!db) |
478 return base::PLATFORM_FILE_ERROR_FAILED; | 749 return base::PLATFORM_FILE_ERROR_FAILED; |
479 FileId dest_file_id; | 750 FileId dest_file_id; |
480 bool overwrite = db->GetFileWithPath(dest_file_path, &dest_file_id); | 751 bool overwrite = db->GetFileWithPath(dest_file_path, &dest_file_id); |
481 FileInfo dest_file_info; | 752 FileInfo dest_file_info; |
482 if (overwrite) { | 753 if (overwrite) { |
483 if (!db->GetFileInfo(dest_file_id, &dest_file_info) || | 754 if (!db->GetFileInfo(dest_file_id, &dest_file_info) || |
484 dest_file_info.is_directory()) { | 755 dest_file_info.is_directory()) { |
485 NOTREACHED(); | 756 NOTREACHED(); |
486 return base::PLATFORM_FILE_ERROR_FAILED; | 757 return base::PLATFORM_FILE_ERROR_FAILED; |
487 } | 758 } |
488 FilePath dest_data_path = DataPathToLocalPath(context->dest_origin_url(), | 759 FilePath dest_data_path = DataPathToLocalPath(context->dest_origin_url(), |
489 context->dest_type(), dest_file_info.data_path); | 760 context->dest_type(), dest_file_info.data_path); |
490 return underlying_file_util_->CopyOrMoveFile(context, | 761 return underlying_file_util()->CopyOrMoveFile(context, |
491 src_file_path, dest_data_path, true /* copy */); | 762 src_file_path, dest_data_path, true /* copy */); |
492 } else { | 763 } else { |
493 FileId dest_parent_id; | 764 FileId dest_parent_id; |
494 if (!db->GetFileWithPath(dest_file_path.DirName(), &dest_parent_id)) { | 765 if (!db->GetFileWithPath(dest_file_path.DirName(), &dest_parent_id)) { |
495 NOTREACHED(); // We shouldn't be called in this case. | 766 NOTREACHED(); // We shouldn't be called in this case. |
496 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | 767 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
497 } | 768 } |
498 InitFileInfo(&dest_file_info, dest_parent_id, | 769 InitFileInfo(&dest_file_info, dest_parent_id, |
499 dest_file_path.BaseName().value()); | 770 dest_file_path.BaseName().value()); |
500 if (!AllocateQuotaForPath(context, 1, dest_file_info.name.size())) | 771 if (!AllocateQuotaForPath(context, 1, dest_file_info.name.size())) |
501 return base::PLATFORM_FILE_ERROR_NO_SPACE; | 772 return base::PLATFORM_FILE_ERROR_NO_SPACE; |
502 return CreateFile(context, context->dest_origin_url(), | 773 return CreateFile(context, context->dest_origin_url(), |
503 context->dest_type(), src_file_path, &dest_file_info, 0, NULL); | 774 context->dest_type(), src_file_path, &dest_file_info, 0, NULL); |
504 } | 775 } |
505 return base::PLATFORM_FILE_ERROR_FAILED; | 776 return base::PLATFORM_FILE_ERROR_FAILED; |
506 } | 777 } |
507 | 778 |
508 PlatformFileError ObfuscatedFileSystemFileUtil::DeleteFile( | 779 PlatformFileError ObfuscatedFileUtil::DeleteFile( |
509 FileSystemOperationContext* context, | 780 FileSystemOperationContext* context, |
510 const FilePath& virtual_path) { | 781 const FilePath& virtual_path) { |
511 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | 782 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( |
512 context->src_origin_url(), context->src_type(), true); | 783 context->src_origin_url(), context->src_type(), true); |
513 if (!db) | 784 if (!db) |
514 return base::PLATFORM_FILE_ERROR_FAILED; | 785 return base::PLATFORM_FILE_ERROR_FAILED; |
515 FileId file_id; | 786 FileId file_id; |
516 if (!db->GetFileWithPath(virtual_path, &file_id)) | 787 if (!db->GetFileWithPath(virtual_path, &file_id)) |
517 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | 788 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
518 FileInfo file_info; | 789 FileInfo file_info; |
519 if (!db->GetFileInfo(file_id, &file_info) || file_info.is_directory()) { | 790 if (!db->GetFileInfo(file_id, &file_info) || file_info.is_directory()) { |
520 NOTREACHED(); | 791 NOTREACHED(); |
521 return base::PLATFORM_FILE_ERROR_FAILED; | 792 return base::PLATFORM_FILE_ERROR_FAILED; |
522 } | 793 } |
523 if (!db->RemoveFileInfo(file_id)) { | 794 if (!db->RemoveFileInfo(file_id)) { |
524 NOTREACHED(); | 795 NOTREACHED(); |
525 return base::PLATFORM_FILE_ERROR_FAILED; | 796 return base::PLATFORM_FILE_ERROR_FAILED; |
526 } | 797 } |
527 AllocateQuotaForPath(context, -1, -static_cast<int64>(file_info.name.size())); | 798 AllocateQuotaForPath(context, -1, -static_cast<int64>(file_info.name.size())); |
528 UpdatePathQuotaUsage(context, context->src_origin_url(), context->src_type(), | 799 UpdatePathQuotaUsage(context, context->src_origin_url(), context->src_type(), |
529 -1, -static_cast<int64>(file_info.name.size())); | 800 -1, -static_cast<int64>(file_info.name.size())); |
530 FilePath data_path = DataPathToLocalPath(context->src_origin_url(), | 801 FilePath data_path = DataPathToLocalPath(context->src_origin_url(), |
531 context->src_type(), file_info.data_path); | 802 context->src_type(), file_info.data_path); |
532 if (base::PLATFORM_FILE_OK != | 803 if (base::PLATFORM_FILE_OK != |
533 underlying_file_util_->DeleteFile(context, data_path)) | 804 underlying_file_util()->DeleteFile(context, data_path)) |
534 LOG(WARNING) << "Leaked a backing file."; | 805 LOG(WARNING) << "Leaked a backing file."; |
535 return base::PLATFORM_FILE_OK; | 806 return base::PLATFORM_FILE_OK; |
536 } | 807 } |
537 | 808 |
538 PlatformFileError ObfuscatedFileSystemFileUtil::DeleteSingleDirectory( | 809 PlatformFileError ObfuscatedFileUtil::DeleteSingleDirectory( |
539 FileSystemOperationContext* context, | 810 FileSystemOperationContext* context, |
540 const FilePath& virtual_path) { | 811 const FilePath& virtual_path) { |
541 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | 812 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( |
542 context->src_origin_url(), context->src_type(), true); | 813 context->src_origin_url(), context->src_type(), true); |
543 if (!db) | 814 if (!db) |
544 return base::PLATFORM_FILE_ERROR_FAILED; | 815 return base::PLATFORM_FILE_ERROR_FAILED; |
545 FileId file_id; | 816 FileId file_id; |
546 if (!db->GetFileWithPath(virtual_path, &file_id)) | 817 if (!db->GetFileWithPath(virtual_path, &file_id)) |
547 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | 818 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
548 FileInfo file_info; | 819 FileInfo file_info; |
549 if (!db->GetFileInfo(file_id, &file_info) || !file_info.is_directory()) { | 820 if (!db->GetFileInfo(file_id, &file_info) || !file_info.is_directory()) { |
550 NOTREACHED(); | 821 NOTREACHED(); |
551 return base::PLATFORM_FILE_ERROR_FAILED; | 822 return base::PLATFORM_FILE_ERROR_FAILED; |
552 } | 823 } |
553 if (!db->RemoveFileInfo(file_id)) | 824 if (!db->RemoveFileInfo(file_id)) |
554 return base::PLATFORM_FILE_ERROR_NOT_EMPTY; | 825 return base::PLATFORM_FILE_ERROR_NOT_EMPTY; |
555 AllocateQuotaForPath(context, -1, -static_cast<int64>(file_info.name.size())); | 826 AllocateQuotaForPath(context, -1, -static_cast<int64>(file_info.name.size())); |
556 UpdatePathQuotaUsage(context, context->src_origin_url(), context->src_type(), | 827 UpdatePathQuotaUsage(context, context->src_origin_url(), context->src_type(), |
557 -1, -static_cast<int64>(file_info.name.size())); | 828 -1, -static_cast<int64>(file_info.name.size())); |
558 return base::PLATFORM_FILE_OK; | 829 return base::PLATFORM_FILE_OK; |
559 } | 830 } |
560 | 831 |
561 PlatformFileError ObfuscatedFileSystemFileUtil::Touch( | 832 FilePath ObfuscatedFileUtil::GetDirectoryForOriginAndType( |
562 FileSystemOperationContext* context, | |
563 const FilePath& virtual_path, | |
564 const base::Time& last_access_time, | |
565 const base::Time& last_modified_time) { | |
566 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
567 context->src_origin_url(), context->src_type(), false); | |
568 if (!db) | |
569 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
570 FileId file_id; | |
571 if (!db->GetFileWithPath(virtual_path, &file_id)) | |
572 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
573 | |
574 FileInfo file_info; | |
575 if (!db->GetFileInfo(file_id, &file_info)) { | |
576 NOTREACHED(); | |
577 return base::PLATFORM_FILE_ERROR_FAILED; | |
578 } | |
579 if (file_info.is_directory()) { | |
580 file_info.modification_time = last_modified_time; | |
581 if (!db->UpdateFileInfo(file_id, file_info)) | |
582 return base::PLATFORM_FILE_ERROR_FAILED; | |
583 return base::PLATFORM_FILE_OK; | |
584 } | |
585 FilePath data_path = DataPathToLocalPath(context->src_origin_url(), | |
586 context->src_type(), file_info.data_path); | |
587 return underlying_file_util_->Touch( | |
588 context, data_path, last_access_time, last_modified_time); | |
589 } | |
590 | |
591 PlatformFileError ObfuscatedFileSystemFileUtil::Truncate( | |
592 FileSystemOperationContext* context, | |
593 const FilePath& virtual_path, | |
594 int64 length) { | |
595 FilePath local_path = | |
596 GetLocalPath(context->src_origin_url(), context->src_type(), | |
597 virtual_path); | |
598 if (local_path.empty()) | |
599 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
600 return underlying_file_util_->Truncate( | |
601 context, local_path, length); | |
602 } | |
603 | |
604 bool ObfuscatedFileSystemFileUtil::PathExists( | |
605 FileSystemOperationContext* context, | |
606 const FilePath& virtual_path) { | |
607 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
608 context->src_origin_url(), context->src_type(), false); | |
609 if (!db) | |
610 return false; | |
611 FileId file_id; | |
612 return db->GetFileWithPath(virtual_path, &file_id); | |
613 } | |
614 | |
615 bool ObfuscatedFileSystemFileUtil::DirectoryExists( | |
616 FileSystemOperationContext* context, | |
617 const FilePath& virtual_path) { | |
618 if (IsRootDirectory(virtual_path)) { | |
619 // It's questionable whether we should return true or false for the | |
620 // root directory of nonexistent origin, but here we return true | |
621 // as the current implementation of ReadDirectory always returns an empty | |
622 // array (rather than erroring out with NOT_FOUND_ERR even) for | |
623 // nonexistent origins. | |
624 // Note: if you're going to change this behavior please also consider | |
625 // changiing the ReadDirectory's behavior! | |
626 return true; | |
627 } | |
628 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
629 context->src_origin_url(), context->src_type(), false); | |
630 if (!db) | |
631 return false; | |
632 FileId file_id; | |
633 if (!db->GetFileWithPath(virtual_path, &file_id)) | |
634 return false; | |
635 FileInfo file_info; | |
636 if (!db->GetFileInfo(file_id, &file_info)) { | |
637 NOTREACHED(); | |
638 return false; | |
639 } | |
640 return file_info.is_directory(); | |
641 } | |
642 | |
643 bool ObfuscatedFileSystemFileUtil::IsDirectoryEmpty( | |
644 FileSystemOperationContext* context, | |
645 const FilePath& virtual_path) { | |
646 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
647 context->src_origin_url(), context->src_type(), false); | |
648 if (!db) | |
649 return true; // Not a great answer, but it's what others do. | |
650 FileId file_id; | |
651 if (!db->GetFileWithPath(virtual_path, &file_id)) | |
652 return true; // Ditto. | |
653 FileInfo file_info; | |
654 if (!db->GetFileInfo(file_id, &file_info)) { | |
655 DCHECK(!file_id); | |
656 // It's the root directory and the database hasn't been initialized yet. | |
657 return true; | |
658 } | |
659 if (!file_info.is_directory()) | |
660 return true; | |
661 std::vector<FileId> children; | |
662 // TODO(ericu): This could easily be made faster with help from the database. | |
663 if (!db->ListChildren(file_id, &children)) | |
664 return true; | |
665 return children.empty(); | |
666 } | |
667 | |
668 class ObfuscatedFileSystemFileEnumerator | |
669 : public FileSystemFileUtil::AbstractFileEnumerator { | |
670 public: | |
671 ObfuscatedFileSystemFileEnumerator( | |
672 const FilePath& base_path, | |
673 FileSystemDirectoryDatabase* db, | |
674 FileSystemOperationContext* context, | |
675 FileSystemFileUtil* underlying_file_util, | |
676 const FilePath& virtual_root_path) | |
677 : base_path_(base_path), | |
678 db_(db), | |
679 context_(context), | |
680 underlying_file_util_(underlying_file_util) { | |
681 DCHECK(db_); | |
682 DCHECK(context_); | |
683 DCHECK(underlying_file_util_); | |
684 | |
685 FileId file_id; | |
686 FileInfo file_info; | |
687 if (!db_->GetFileWithPath(virtual_root_path, &file_id)) | |
688 return; | |
689 if (!db_->GetFileInfo(file_id, &file_info)) | |
690 return; | |
691 if (!file_info.is_directory()) | |
692 return; | |
693 FileRecord record = { file_id, file_info, virtual_root_path }; | |
694 display_queue_.push(record); | |
695 Next(); // Enumerators don't include the directory itself. | |
696 } | |
697 | |
698 ~ObfuscatedFileSystemFileEnumerator() {} | |
699 | |
700 virtual FilePath Next() OVERRIDE { | |
701 ProcessRecurseQueue(); | |
702 if (display_queue_.empty()) | |
703 return FilePath(); | |
704 current_ = display_queue_.front(); | |
705 display_queue_.pop(); | |
706 if (current_.file_info.is_directory()) | |
707 recurse_queue_.push(current_); | |
708 return current_.file_path; | |
709 } | |
710 | |
711 virtual int64 Size() OVERRIDE { | |
712 if (IsDirectory()) | |
713 return 0; | |
714 | |
715 base::PlatformFileInfo file_info; | |
716 FilePath platform_file_path; | |
717 | |
718 FilePath local_path = base_path_.Append(current_.file_info.data_path); | |
719 base::PlatformFileError error = underlying_file_util_->GetFileInfo( | |
720 context_, local_path, &file_info, &platform_file_path); | |
721 if (error != base::PLATFORM_FILE_OK) { | |
722 LOG(WARNING) << "Lost a backing file."; | |
723 return 0; | |
724 } | |
725 return file_info.size; | |
726 } | |
727 | |
728 virtual bool IsDirectory() OVERRIDE { | |
729 return current_.file_info.is_directory(); | |
730 } | |
731 | |
732 private: | |
733 typedef FileSystemDirectoryDatabase::FileId FileId; | |
734 typedef FileSystemDirectoryDatabase::FileInfo FileInfo; | |
735 | |
736 struct FileRecord { | |
737 FileId file_id; | |
738 FileInfo file_info; | |
739 FilePath file_path; | |
740 }; | |
741 | |
742 void ProcessRecurseQueue() { | |
743 while (display_queue_.empty() && !recurse_queue_.empty()) { | |
744 FileRecord directory = recurse_queue_.front(); | |
745 std::vector<FileId> children; | |
746 recurse_queue_.pop(); | |
747 if (!db_->ListChildren(directory.file_id, &children)) | |
748 return; | |
749 std::vector<FileId>::iterator iter; | |
750 for (iter = children.begin(); iter != children.end(); ++iter) { | |
751 FileRecord child; | |
752 child.file_id = *iter; | |
753 if (!db_->GetFileInfo(child.file_id, &child.file_info)) | |
754 return; | |
755 child.file_path = directory.file_path.Append(child.file_info.name); | |
756 display_queue_.push(child); | |
757 } | |
758 } | |
759 } | |
760 | |
761 std::queue<FileRecord> display_queue_; | |
762 std::queue<FileRecord> recurse_queue_; | |
763 FileRecord current_; | |
764 FilePath base_path_; | |
765 FileSystemDirectoryDatabase* db_; | |
766 FileSystemOperationContext* context_; | |
767 FileSystemFileUtil* underlying_file_util_; | |
768 }; | |
769 | |
770 class ObfuscatedFileSystemOriginEnumerator | |
771 : public ObfuscatedFileSystemFileUtil::AbstractOriginEnumerator { | |
772 public: | |
773 typedef FileSystemOriginDatabase::OriginRecord OriginRecord; | |
774 ObfuscatedFileSystemOriginEnumerator( | |
775 FileSystemOriginDatabase* origin_database, | |
776 const FilePath& base_path) | |
777 : base_path_(base_path) { | |
778 if (origin_database) | |
779 origin_database->ListAllOrigins(&origins_); | |
780 } | |
781 | |
782 ~ObfuscatedFileSystemOriginEnumerator() {} | |
783 | |
784 // Returns the next origin. Returns empty if there are no more origins. | |
785 virtual GURL Next() OVERRIDE { | |
786 OriginRecord record; | |
787 if (!origins_.empty()) { | |
788 record = origins_.back(); | |
789 origins_.pop_back(); | |
790 } | |
791 current_ = record; | |
792 return GetOriginURLFromIdentifier(record.origin); | |
793 } | |
794 | |
795 // Returns the current origin's information. | |
796 virtual bool HasFileSystemType(FileSystemType type) const OVERRIDE { | |
797 if (current_.path.empty()) | |
798 return false; | |
799 FilePath::StringType type_string = | |
800 ObfuscatedFileSystemFileUtil::GetDirectoryNameForType(type); | |
801 if (type_string.empty()) { | |
802 NOTREACHED(); | |
803 return false; | |
804 } | |
805 FilePath path = base_path_.Append(current_.path).Append(type_string); | |
806 return file_util::DirectoryExists(path); | |
807 } | |
808 | |
809 private: | |
810 std::vector<OriginRecord> origins_; | |
811 OriginRecord current_; | |
812 FilePath base_path_; | |
813 }; | |
814 | |
815 ObfuscatedFileSystemFileUtil::AbstractOriginEnumerator* | |
816 ObfuscatedFileSystemFileUtil::CreateOriginEnumerator() { | |
817 std::vector<FileSystemOriginDatabase::OriginRecord> origins; | |
818 | |
819 InitOriginDatabase(false); | |
820 return new ObfuscatedFileSystemOriginEnumerator( | |
821 origin_database_.get(), file_system_directory_); | |
822 } | |
823 | |
824 FileSystemFileUtil::AbstractFileEnumerator* | |
825 ObfuscatedFileSystemFileUtil::CreateFileEnumerator( | |
826 FileSystemOperationContext* context, | |
827 const FilePath& root_path) { | |
828 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
829 context->src_origin_url(), context->src_type(), false); | |
830 if (!db) | |
831 return new FileSystemFileUtil::EmptyFileEnumerator(); | |
832 return new ObfuscatedFileSystemFileEnumerator( | |
833 GetDirectoryForOriginAndType(context->src_origin_url(), | |
834 context->src_type(), false), | |
835 db, | |
836 context, | |
837 underlying_file_util_.get(), | |
838 root_path); | |
839 } | |
840 | |
841 PlatformFileError ObfuscatedFileSystemFileUtil::GetFileInfoInternal( | |
842 FileSystemDirectoryDatabase* db, | |
843 FileSystemOperationContext* context, | |
844 FileId file_id, | |
845 FileInfo* local_info, | |
846 base::PlatformFileInfo* file_info, | |
847 FilePath* platform_file_path) { | |
848 DCHECK(db); | |
849 DCHECK(context); | |
850 DCHECK(file_info); | |
851 DCHECK(platform_file_path); | |
852 | |
853 if (!db->GetFileInfo(file_id, local_info)) { | |
854 NOTREACHED(); | |
855 return base::PLATFORM_FILE_ERROR_FAILED; | |
856 } | |
857 | |
858 if (local_info->is_directory()) { | |
859 file_info->is_directory = true; | |
860 file_info->is_symbolic_link = false; | |
861 file_info->last_modified = local_info->modification_time; | |
862 *platform_file_path = FilePath(); | |
863 // We don't fill in ctime or atime. | |
864 return base::PLATFORM_FILE_OK; | |
865 } | |
866 if (local_info->data_path.empty()) | |
867 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | |
868 FilePath data_path = DataPathToLocalPath(context->src_origin_url(), | |
869 context->src_type(), local_info->data_path); | |
870 return underlying_file_util_->GetFileInfo( | |
871 context, data_path, file_info, platform_file_path); | |
872 } | |
873 | |
874 PlatformFileError ObfuscatedFileSystemFileUtil::CreateFile( | |
875 FileSystemOperationContext* context, | |
876 const GURL& origin_url, FileSystemType type, const FilePath& source_path, | |
877 FileInfo* file_info, int file_flags, PlatformFile* handle) { | |
878 if (handle) | |
879 *handle = base::kInvalidPlatformFileValue; | |
880 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
881 origin_url, type, true); | |
882 int64 number; | |
883 if (!db || !db->GetNextInteger(&number)) | |
884 return base::PLATFORM_FILE_ERROR_FAILED; | |
885 // We use the third- and fourth-to-last digits as the directory. | |
886 int64 directory_number = number % 10000 / 100; | |
887 // TODO(ericu): local_path is an OS path; underlying_file_util_ isn't | |
888 // guaranteed to understand OS paths. | |
889 FilePath local_path = | |
890 GetDirectoryForOriginAndType(origin_url, type, false); | |
891 if (local_path.empty()) | |
892 return base::PLATFORM_FILE_ERROR_FAILED; | |
893 | |
894 local_path = local_path.AppendASCII(StringPrintf("%02" PRIu64, | |
895 directory_number)); | |
896 PlatformFileError error; | |
897 error = underlying_file_util_->CreateDirectory( | |
898 context, local_path, false /* exclusive */, false /* recursive */); | |
899 if (base::PLATFORM_FILE_OK != error) | |
900 return error; | |
901 local_path = local_path.AppendASCII(StringPrintf("%08" PRIu64, number)); | |
902 FilePath data_path = LocalPathToDataPath(origin_url, type, local_path); | |
903 if (data_path.empty()) | |
904 return base::PLATFORM_FILE_ERROR_FAILED; | |
905 bool created = false; | |
906 if (!source_path.empty()) { | |
907 DCHECK(!file_flags); | |
908 DCHECK(!handle); | |
909 error = underlying_file_util_->CopyOrMoveFile( | |
910 context, source_path, local_path, true /* copy */); | |
911 created = true; | |
912 } else { | |
913 FilePath path; | |
914 underlying_file_util_->GetLocalFilePath(context, local_path, &path); | |
915 if (file_util::PathExists(path)) { | |
916 if (!file_util::Delete(path, true)) { | |
917 NOTREACHED(); | |
918 return base::PLATFORM_FILE_ERROR_FAILED; | |
919 } | |
920 LOG(WARNING) << "A stray file detected"; | |
921 context->file_system_context()->GetQuotaUtil(context->src_type())-> | |
922 InvalidateUsageCache(context->src_origin_url(), context->src_type()); | |
923 } | |
924 | |
925 if (handle) { | |
926 error = underlying_file_util_->CreateOrOpen( | |
927 context, local_path, file_flags, handle, &created); | |
928 // If this succeeds, we must close handle on any subsequent error. | |
929 } else { | |
930 DCHECK(!file_flags); // file_flags is only used by CreateOrOpen. | |
931 error = underlying_file_util_->EnsureFileExists( | |
932 context, local_path, &created); | |
933 } | |
934 } | |
935 if (error != base::PLATFORM_FILE_OK) | |
936 return error; | |
937 | |
938 if (!created) { | |
939 NOTREACHED(); | |
940 if (handle) { | |
941 DCHECK_NE(base::kInvalidPlatformFileValue, *handle); | |
942 base::ClosePlatformFile(*handle); | |
943 underlying_file_util_->DeleteFile(context, local_path); | |
944 } | |
945 return base::PLATFORM_FILE_ERROR_FAILED; | |
946 } | |
947 file_info->data_path = data_path; | |
948 FileId file_id; | |
949 if (!db->AddFileInfo(*file_info, &file_id)) { | |
950 if (handle) { | |
951 DCHECK_NE(base::kInvalidPlatformFileValue, *handle); | |
952 base::ClosePlatformFile(*handle); | |
953 } | |
954 underlying_file_util_->DeleteFile(context, local_path); | |
955 return base::PLATFORM_FILE_ERROR_FAILED; | |
956 } | |
957 UpdatePathQuotaUsage(context, origin_url, type, 1, file_info->name.size()); | |
958 | |
959 return base::PLATFORM_FILE_OK; | |
960 } | |
961 | |
962 FilePath ObfuscatedFileSystemFileUtil::GetLocalPath( | |
963 const GURL& origin_url, | |
964 FileSystemType type, | |
965 const FilePath& virtual_path) { | |
966 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | |
967 origin_url, type, false); | |
968 if (!db) | |
969 return FilePath(); | |
970 FileId file_id; | |
971 if (!db->GetFileWithPath(virtual_path, &file_id)) | |
972 return FilePath(); | |
973 FileInfo file_info; | |
974 if (!db->GetFileInfo(file_id, &file_info) || file_info.is_directory()) { | |
975 NOTREACHED(); | |
976 return FilePath(); // Directories have no local path. | |
977 } | |
978 return DataPathToLocalPath(origin_url, type, file_info.data_path); | |
979 } | |
980 | |
981 FilePath ObfuscatedFileSystemFileUtil::GetDirectoryForOriginAndType( | |
982 const GURL& origin, FileSystemType type, bool create) { | 833 const GURL& origin, FileSystemType type, bool create) { |
983 FilePath origin_dir = GetDirectoryForOrigin(origin, create); | 834 FilePath origin_dir = GetDirectoryForOrigin(origin, create); |
984 if (origin_dir.empty()) | 835 if (origin_dir.empty()) |
985 return FilePath(); | 836 return FilePath(); |
986 FilePath::StringType type_string = GetDirectoryNameForType(type); | 837 FilePath::StringType type_string = GetDirectoryNameForType(type); |
987 if (type_string.empty()) { | 838 if (type_string.empty()) { |
988 LOG(WARNING) << "Unknown filesystem type requested:" << type; | 839 LOG(WARNING) << "Unknown filesystem type requested:" << type; |
989 return FilePath(); | 840 return FilePath(); |
990 } | 841 } |
991 FilePath path = origin_dir.Append(type_string); | 842 FilePath path = origin_dir.Append(type_string); |
992 if (!file_util::DirectoryExists(path) && | 843 if (!file_util::DirectoryExists(path) && |
993 (!create || !file_util::CreateDirectory(path))) | 844 (!create || !file_util::CreateDirectory(path))) |
994 return FilePath(); | 845 return FilePath(); |
995 return path; | 846 return path; |
996 } | 847 } |
997 | 848 |
998 bool ObfuscatedFileSystemFileUtil::DeleteDirectoryForOriginAndType( | 849 bool ObfuscatedFileUtil::DeleteDirectoryForOriginAndType( |
999 const GURL& origin, FileSystemType type) { | 850 const GURL& origin, FileSystemType type) { |
1000 FilePath origin_type_path = GetDirectoryForOriginAndType(origin, type, false); | 851 FilePath origin_type_path = GetDirectoryForOriginAndType(origin, type, false); |
1001 if (!file_util::PathExists(origin_type_path)) | 852 if (!file_util::PathExists(origin_type_path)) |
1002 return true; | 853 return true; |
1003 | 854 |
1004 // TODO(dmikurube): Consider the return value of DestroyDirectoryDatabase. | 855 // TODO(dmikurube): Consider the return value of DestroyDirectoryDatabase. |
1005 // We ignore its error now since 1) it doesn't matter the final result, and | 856 // We ignore its error now since 1) it doesn't matter the final result, and |
1006 // 2) it always returns false in Windows because of LevelDB's implementation. | 857 // 2) it always returns false in Windows because of LevelDB's implementation. |
1007 // Information about failure would be useful for debugging. | 858 // Information about failure would be useful for debugging. |
1008 DestroyDirectoryDatabase(origin, type); | 859 DestroyDirectoryDatabase(origin, type); |
1009 if (!file_util::Delete(origin_type_path, true /* recursive */)) | 860 if (!file_util::Delete(origin_type_path, true /* recursive */)) |
1010 return false; | 861 return false; |
1011 | 862 |
1012 FilePath origin_path = origin_type_path.DirName(); | 863 FilePath origin_path = origin_type_path.DirName(); |
1013 DCHECK_EQ(origin_path.value(), GetDirectoryForOrigin(origin, false).value()); | 864 DCHECK_EQ(origin_path.value(), GetDirectoryForOrigin(origin, false).value()); |
1014 | 865 |
1015 // Delete the origin directory if the deleted one was the last remaining | 866 // Delete the origin directory if the deleted one was the last remaining |
1016 // type for the origin. | 867 // type for the origin. |
1017 if (file_util::Delete(origin_path, false /* recursive */)) { | 868 if (file_util::Delete(origin_path, false /* recursive */)) { |
1018 InitOriginDatabase(false); | 869 InitOriginDatabase(false); |
1019 if (origin_database_.get()) | 870 if (origin_database_.get()) |
1020 origin_database_->RemovePathForOrigin(GetOriginIdentifierFromURL(origin)); | 871 origin_database_->RemovePathForOrigin(GetOriginIdentifierFromURL(origin)); |
1021 } | 872 } |
1022 | 873 |
1023 // At this point we are sure we had successfully deleted the origin/type | 874 // At this point we are sure we had successfully deleted the origin/type |
1024 // directory, so just returning true here. | 875 // directory, so just returning true here. |
1025 return true; | 876 return true; |
1026 } | 877 } |
1027 | 878 |
1028 bool ObfuscatedFileSystemFileUtil::MigrateFromOldSandbox( | 879 bool ObfuscatedFileUtil::MigrateFromOldSandbox( |
1029 const GURL& origin_url, FileSystemType type, const FilePath& src_root) { | 880 const GURL& origin_url, FileSystemType type, const FilePath& src_root) { |
1030 if (!DestroyDirectoryDatabase(origin_url, type)) | 881 if (!DestroyDirectoryDatabase(origin_url, type)) |
1031 return false; | 882 return false; |
1032 FilePath dest_root = GetDirectoryForOriginAndType(origin_url, type, true); | 883 FilePath dest_root = GetDirectoryForOriginAndType(origin_url, type, true); |
1033 if (dest_root.empty()) | 884 if (dest_root.empty()) |
1034 return false; | 885 return false; |
1035 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( | 886 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( |
1036 origin_url, type, true); | 887 origin_url, type, true); |
1037 if (!db) | 888 if (!db) |
1038 return false; | 889 return false; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1090 LOG(WARNING) << | 941 LOG(WARNING) << |
1091 "The final step of a migration failed; I'll try to clean up."; | 942 "The final step of a migration failed; I'll try to clean up."; |
1092 db = NULL; | 943 db = NULL; |
1093 DestroyDirectoryDatabase(origin_url, type); | 944 DestroyDirectoryDatabase(origin_url, type); |
1094 return false; | 945 return false; |
1095 } | 946 } |
1096 return true; | 947 return true; |
1097 } | 948 } |
1098 | 949 |
1099 // static | 950 // static |
1100 FilePath::StringType ObfuscatedFileSystemFileUtil::GetDirectoryNameForType( | 951 FilePath::StringType ObfuscatedFileUtil::GetDirectoryNameForType( |
1101 FileSystemType type) { | 952 FileSystemType type) { |
1102 switch (type) { | 953 switch (type) { |
1103 case kFileSystemTypeTemporary: | 954 case kFileSystemTypeTemporary: |
1104 return kTemporaryDirectoryName; | 955 return kTemporaryDirectoryName; |
1105 case kFileSystemTypePersistent: | 956 case kFileSystemTypePersistent: |
1106 return kPersistentDirectoryName; | 957 return kPersistentDirectoryName; |
1107 case kFileSystemTypeUnknown: | 958 case kFileSystemTypeUnknown: |
1108 default: | 959 default: |
1109 return FilePath::StringType(); | 960 return FilePath::StringType(); |
1110 } | 961 } |
1111 } | 962 } |
1112 | 963 |
1113 FilePath ObfuscatedFileSystemFileUtil::DataPathToLocalPath( | 964 ObfuscatedFileUtil::AbstractOriginEnumerator* |
| 965 ObfuscatedFileUtil::CreateOriginEnumerator() { |
| 966 std::vector<FileSystemOriginDatabase::OriginRecord> origins; |
| 967 |
| 968 InitOriginDatabase(false); |
| 969 return new ObfuscatedOriginEnumerator( |
| 970 origin_database_.get(), file_system_directory_); |
| 971 } |
| 972 |
| 973 bool ObfuscatedFileUtil::DestroyDirectoryDatabase( |
| 974 const GURL& origin, FileSystemType type) { |
| 975 std::string type_string = |
| 976 FileSystemPathManager::GetFileSystemTypeString(type); |
| 977 if (type_string.empty()) { |
| 978 LOG(WARNING) << "Unknown filesystem type requested:" << type; |
| 979 return true; |
| 980 } |
| 981 std::string key = GetOriginIdentifierFromURL(origin) + type_string; |
| 982 DirectoryMap::iterator iter = directories_.find(key); |
| 983 if (iter != directories_.end()) { |
| 984 FileSystemDirectoryDatabase* database = iter->second; |
| 985 directories_.erase(iter); |
| 986 delete database; |
| 987 } |
| 988 |
| 989 FilePath path = GetDirectoryForOriginAndType(origin, type, false); |
| 990 if (path.empty()) |
| 991 return true; |
| 992 if (!file_util::DirectoryExists(path)) |
| 993 return true; |
| 994 path = path.AppendASCII(kDirectoryDatabaseName); |
| 995 return FileSystemDirectoryDatabase::DestroyDatabase(path); |
| 996 } |
| 997 |
| 998 // static |
| 999 int64 ObfuscatedFileUtil::ComputeFilePathCost(const FilePath& path) { |
| 1000 return GetPathQuotaUsage(1, path.BaseName().value().size()); |
| 1001 } |
| 1002 |
| 1003 PlatformFileError ObfuscatedFileUtil::GetFileInfoInternal( |
| 1004 FileSystemDirectoryDatabase* db, |
| 1005 FileSystemOperationContext* context, |
| 1006 FileId file_id, |
| 1007 FileInfo* local_info, |
| 1008 base::PlatformFileInfo* file_info, |
| 1009 FilePath* platform_file_path) { |
| 1010 DCHECK(db); |
| 1011 DCHECK(context); |
| 1012 DCHECK(file_info); |
| 1013 DCHECK(platform_file_path); |
| 1014 |
| 1015 if (!db->GetFileInfo(file_id, local_info)) { |
| 1016 NOTREACHED(); |
| 1017 return base::PLATFORM_FILE_ERROR_FAILED; |
| 1018 } |
| 1019 |
| 1020 if (local_info->is_directory()) { |
| 1021 file_info->is_directory = true; |
| 1022 file_info->is_symbolic_link = false; |
| 1023 file_info->last_modified = local_info->modification_time; |
| 1024 *platform_file_path = FilePath(); |
| 1025 // We don't fill in ctime or atime. |
| 1026 return base::PLATFORM_FILE_OK; |
| 1027 } |
| 1028 if (local_info->data_path.empty()) |
| 1029 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; |
| 1030 FilePath data_path = DataPathToLocalPath(context->src_origin_url(), |
| 1031 context->src_type(), local_info->data_path); |
| 1032 return underlying_file_util()->GetFileInfo( |
| 1033 context, data_path, file_info, platform_file_path); |
| 1034 } |
| 1035 |
| 1036 PlatformFileError ObfuscatedFileUtil::CreateFile( |
| 1037 FileSystemOperationContext* context, |
| 1038 const GURL& origin_url, FileSystemType type, const FilePath& source_path, |
| 1039 FileInfo* file_info, int file_flags, PlatformFile* handle) { |
| 1040 if (handle) |
| 1041 *handle = base::kInvalidPlatformFileValue; |
| 1042 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( |
| 1043 origin_url, type, true); |
| 1044 int64 number; |
| 1045 if (!db || !db->GetNextInteger(&number)) |
| 1046 return base::PLATFORM_FILE_ERROR_FAILED; |
| 1047 // We use the third- and fourth-to-last digits as the directory. |
| 1048 int64 directory_number = number % 10000 / 100; |
| 1049 // TODO(ericu): local_path is an OS path; underlying_file_util_ isn't |
| 1050 // guaranteed to understand OS paths. |
| 1051 FilePath local_path = |
| 1052 GetDirectoryForOriginAndType(origin_url, type, false); |
| 1053 if (local_path.empty()) |
| 1054 return base::PLATFORM_FILE_ERROR_FAILED; |
| 1055 |
| 1056 local_path = local_path.AppendASCII(StringPrintf("%02" PRIu64, |
| 1057 directory_number)); |
| 1058 PlatformFileError error; |
| 1059 error = underlying_file_util()->CreateDirectory( |
| 1060 context, local_path, false /* exclusive */, false /* recursive */); |
| 1061 if (base::PLATFORM_FILE_OK != error) |
| 1062 return error; |
| 1063 local_path = local_path.AppendASCII(StringPrintf("%08" PRIu64, number)); |
| 1064 FilePath data_path = LocalPathToDataPath(origin_url, type, local_path); |
| 1065 if (data_path.empty()) |
| 1066 return base::PLATFORM_FILE_ERROR_FAILED; |
| 1067 bool created = false; |
| 1068 if (!source_path.empty()) { |
| 1069 DCHECK(!file_flags); |
| 1070 DCHECK(!handle); |
| 1071 error = underlying_file_util()->CopyOrMoveFile( |
| 1072 context, source_path, local_path, true /* copy */); |
| 1073 created = true; |
| 1074 } else { |
| 1075 FilePath path; |
| 1076 underlying_file_util()->GetLocalFilePath(context, local_path, &path); |
| 1077 if (file_util::PathExists(path)) { |
| 1078 if (!file_util::Delete(path, true)) { |
| 1079 NOTREACHED(); |
| 1080 return base::PLATFORM_FILE_ERROR_FAILED; |
| 1081 } |
| 1082 LOG(WARNING) << "A stray file detected"; |
| 1083 context->file_system_context()->GetQuotaUtil(context->src_type())-> |
| 1084 InvalidateUsageCache(context->src_origin_url(), context->src_type()); |
| 1085 } |
| 1086 |
| 1087 if (handle) { |
| 1088 error = underlying_file_util()->CreateOrOpen( |
| 1089 context, local_path, file_flags, handle, &created); |
| 1090 // If this succeeds, we must close handle on any subsequent error. |
| 1091 } else { |
| 1092 DCHECK(!file_flags); // file_flags is only used by CreateOrOpen. |
| 1093 error = underlying_file_util()->EnsureFileExists( |
| 1094 context, local_path, &created); |
| 1095 } |
| 1096 } |
| 1097 if (error != base::PLATFORM_FILE_OK) |
| 1098 return error; |
| 1099 |
| 1100 if (!created) { |
| 1101 NOTREACHED(); |
| 1102 if (handle) { |
| 1103 DCHECK_NE(base::kInvalidPlatformFileValue, *handle); |
| 1104 base::ClosePlatformFile(*handle); |
| 1105 underlying_file_util()->DeleteFile(context, local_path); |
| 1106 } |
| 1107 return base::PLATFORM_FILE_ERROR_FAILED; |
| 1108 } |
| 1109 file_info->data_path = data_path; |
| 1110 FileId file_id; |
| 1111 if (!db->AddFileInfo(*file_info, &file_id)) { |
| 1112 if (handle) { |
| 1113 DCHECK_NE(base::kInvalidPlatformFileValue, *handle); |
| 1114 base::ClosePlatformFile(*handle); |
| 1115 } |
| 1116 underlying_file_util()->DeleteFile(context, local_path); |
| 1117 return base::PLATFORM_FILE_ERROR_FAILED; |
| 1118 } |
| 1119 UpdatePathQuotaUsage(context, origin_url, type, 1, file_info->name.size()); |
| 1120 |
| 1121 return base::PLATFORM_FILE_OK; |
| 1122 } |
| 1123 |
| 1124 FilePath ObfuscatedFileUtil::GetLocalPath( |
| 1125 const GURL& origin_url, |
| 1126 FileSystemType type, |
| 1127 const FilePath& virtual_path) { |
| 1128 FileSystemDirectoryDatabase* db = GetDirectoryDatabase( |
| 1129 origin_url, type, false); |
| 1130 if (!db) |
| 1131 return FilePath(); |
| 1132 FileId file_id; |
| 1133 if (!db->GetFileWithPath(virtual_path, &file_id)) |
| 1134 return FilePath(); |
| 1135 FileInfo file_info; |
| 1136 if (!db->GetFileInfo(file_id, &file_info) || file_info.is_directory()) { |
| 1137 NOTREACHED(); |
| 1138 return FilePath(); // Directories have no local path. |
| 1139 } |
| 1140 return DataPathToLocalPath(origin_url, type, file_info.data_path); |
| 1141 } |
| 1142 |
| 1143 FilePath ObfuscatedFileUtil::DataPathToLocalPath( |
1114 const GURL& origin, FileSystemType type, const FilePath& data_path) { | 1144 const GURL& origin, FileSystemType type, const FilePath& data_path) { |
1115 FilePath root = GetDirectoryForOriginAndType(origin, type, false); | 1145 FilePath root = GetDirectoryForOriginAndType(origin, type, false); |
1116 if (root.empty()) | 1146 if (root.empty()) |
1117 return root; | 1147 return root; |
1118 return root.Append(data_path); | 1148 return root.Append(data_path); |
1119 } | 1149 } |
1120 | 1150 |
1121 FilePath ObfuscatedFileSystemFileUtil::LocalPathToDataPath( | 1151 FilePath ObfuscatedFileUtil::LocalPathToDataPath( |
1122 const GURL& origin, FileSystemType type, const FilePath& local_path) { | 1152 const GURL& origin, FileSystemType type, const FilePath& local_path) { |
1123 FilePath root = GetDirectoryForOriginAndType(origin, type, false); | 1153 FilePath root = GetDirectoryForOriginAndType(origin, type, false); |
1124 if (root.empty()) | 1154 if (root.empty()) |
1125 return root; | 1155 return root; |
1126 // This removes the root, including the trailing slash, leaving a relative | 1156 // This removes the root, including the trailing slash, leaving a relative |
1127 // path. | 1157 // path. |
1128 return FilePath(local_path.value().substr(root.value().length() + 1)); | 1158 return FilePath(local_path.value().substr(root.value().length() + 1)); |
1129 } | 1159 } |
1130 | 1160 |
1131 // TODO: How to do the whole validation-without-creation thing? We may not have | 1161 // TODO: How to do the whole validation-without-creation thing? We may not have |
1132 // quota even to create the database. Ah, in that case don't even get here? | 1162 // quota even to create the database. Ah, in that case don't even get here? |
1133 // Still doesn't answer the quota issue, though. | 1163 // Still doesn't answer the quota issue, though. |
1134 FileSystemDirectoryDatabase* ObfuscatedFileSystemFileUtil::GetDirectoryDatabase( | 1164 FileSystemDirectoryDatabase* ObfuscatedFileUtil::GetDirectoryDatabase( |
1135 const GURL& origin, FileSystemType type, bool create) { | 1165 const GURL& origin, FileSystemType type, bool create) { |
1136 std::string type_string = | 1166 std::string type_string = |
1137 FileSystemPathManager::GetFileSystemTypeString(type); | 1167 FileSystemPathManager::GetFileSystemTypeString(type); |
1138 if (type_string.empty()) { | 1168 if (type_string.empty()) { |
1139 LOG(WARNING) << "Unknown filesystem type requested:" << type; | 1169 LOG(WARNING) << "Unknown filesystem type requested:" << type; |
1140 return NULL; | 1170 return NULL; |
1141 } | 1171 } |
1142 std::string key = GetOriginIdentifierFromURL(origin) + type_string; | 1172 std::string key = GetOriginIdentifierFromURL(origin) + type_string; |
1143 DirectoryMap::iterator iter = directories_.find(key); | 1173 DirectoryMap::iterator iter = directories_.find(key); |
1144 if (iter != directories_.end()) { | 1174 if (iter != directories_.end()) { |
(...skipping 10 matching lines...) Expand all Loading... |
1155 return NULL; | 1185 return NULL; |
1156 } | 1186 } |
1157 } | 1187 } |
1158 MarkUsed(); | 1188 MarkUsed(); |
1159 path = path.AppendASCII(kDirectoryDatabaseName); | 1189 path = path.AppendASCII(kDirectoryDatabaseName); |
1160 FileSystemDirectoryDatabase* database = new FileSystemDirectoryDatabase(path); | 1190 FileSystemDirectoryDatabase* database = new FileSystemDirectoryDatabase(path); |
1161 directories_[key] = database; | 1191 directories_[key] = database; |
1162 return database; | 1192 return database; |
1163 } | 1193 } |
1164 | 1194 |
1165 FilePath ObfuscatedFileSystemFileUtil::GetDirectoryForOrigin( | 1195 FilePath ObfuscatedFileUtil::GetDirectoryForOrigin( |
1166 const GURL& origin, bool create) { | 1196 const GURL& origin, bool create) { |
1167 if (!InitOriginDatabase(create)) | 1197 if (!InitOriginDatabase(create)) |
1168 return FilePath(); | 1198 return FilePath(); |
1169 FilePath directory_name; | 1199 FilePath directory_name; |
1170 std::string id = GetOriginIdentifierFromURL(origin); | 1200 std::string id = GetOriginIdentifierFromURL(origin); |
1171 | 1201 |
1172 bool exists_in_db = origin_database_->HasOriginPath(id); | 1202 bool exists_in_db = origin_database_->HasOriginPath(id); |
1173 if (!exists_in_db && !create) | 1203 if (!exists_in_db && !create) |
1174 return FilePath(); | 1204 return FilePath(); |
1175 if (!origin_database_->GetPathForOrigin(id, &directory_name)) | 1205 if (!origin_database_->GetPathForOrigin(id, &directory_name)) |
1176 return FilePath(); | 1206 return FilePath(); |
1177 | 1207 |
1178 FilePath path = file_system_directory_.Append(directory_name); | 1208 FilePath path = file_system_directory_.Append(directory_name); |
1179 bool exists_in_fs = file_util::DirectoryExists(path); | 1209 bool exists_in_fs = file_util::DirectoryExists(path); |
1180 if (!exists_in_db && exists_in_fs) { | 1210 if (!exists_in_db && exists_in_fs) { |
1181 if (!file_util::Delete(path, true)) | 1211 if (!file_util::Delete(path, true)) |
1182 return FilePath(); | 1212 return FilePath(); |
1183 exists_in_fs = false; | 1213 exists_in_fs = false; |
1184 } | 1214 } |
1185 | 1215 |
1186 if (!exists_in_fs) { | 1216 if (!exists_in_fs) { |
1187 if (!create || !file_util::CreateDirectory(path)) | 1217 if (!create || !file_util::CreateDirectory(path)) |
1188 return FilePath(); | 1218 return FilePath(); |
1189 } | 1219 } |
1190 | 1220 |
1191 return path; | 1221 return path; |
1192 } | 1222 } |
1193 | 1223 |
1194 void ObfuscatedFileSystemFileUtil::MarkUsed() { | 1224 void ObfuscatedFileUtil::MarkUsed() { |
1195 if (timer_.IsRunning()) | 1225 if (timer_.IsRunning()) |
1196 timer_.Reset(); | 1226 timer_.Reset(); |
1197 else | 1227 else |
1198 timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(kFlushDelaySeconds), | 1228 timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(kFlushDelaySeconds), |
1199 this, &ObfuscatedFileSystemFileUtil::DropDatabases); | 1229 this, &ObfuscatedFileUtil::DropDatabases); |
1200 } | 1230 } |
1201 | 1231 |
1202 void ObfuscatedFileSystemFileUtil::DropDatabases() { | 1232 void ObfuscatedFileUtil::DropDatabases() { |
1203 origin_database_.reset(); | 1233 origin_database_.reset(); |
1204 STLDeleteContainerPairSecondPointers( | 1234 STLDeleteContainerPairSecondPointers( |
1205 directories_.begin(), directories_.end()); | 1235 directories_.begin(), directories_.end()); |
1206 directories_.clear(); | 1236 directories_.clear(); |
1207 } | 1237 } |
1208 | 1238 |
1209 // static | 1239 bool ObfuscatedFileUtil::InitOriginDatabase(bool create) { |
1210 int64 ObfuscatedFileSystemFileUtil::ComputeFilePathCost(const FilePath& path) { | |
1211 return GetPathQuotaUsage(1, path.BaseName().value().size()); | |
1212 } | |
1213 | |
1214 bool ObfuscatedFileSystemFileUtil::DestroyDirectoryDatabase( | |
1215 const GURL& origin, FileSystemType type) { | |
1216 std::string type_string = | |
1217 FileSystemPathManager::GetFileSystemTypeString(type); | |
1218 if (type_string.empty()) { | |
1219 LOG(WARNING) << "Unknown filesystem type requested:" << type; | |
1220 return true; | |
1221 } | |
1222 std::string key = GetOriginIdentifierFromURL(origin) + type_string; | |
1223 DirectoryMap::iterator iter = directories_.find(key); | |
1224 if (iter != directories_.end()) { | |
1225 FileSystemDirectoryDatabase* database = iter->second; | |
1226 directories_.erase(iter); | |
1227 delete database; | |
1228 } | |
1229 | |
1230 FilePath path = GetDirectoryForOriginAndType(origin, type, false); | |
1231 if (path.empty()) | |
1232 return true; | |
1233 if (!file_util::DirectoryExists(path)) | |
1234 return true; | |
1235 path = path.AppendASCII(kDirectoryDatabaseName); | |
1236 return FileSystemDirectoryDatabase::DestroyDatabase(path); | |
1237 } | |
1238 | |
1239 bool ObfuscatedFileSystemFileUtil::InitOriginDatabase(bool create) { | |
1240 if (!origin_database_.get()) { | 1240 if (!origin_database_.get()) { |
1241 if (!create && !file_util::DirectoryExists(file_system_directory_)) | 1241 if (!create && !file_util::DirectoryExists(file_system_directory_)) |
1242 return false; | 1242 return false; |
1243 if (!file_util::CreateDirectory(file_system_directory_)) { | 1243 if (!file_util::CreateDirectory(file_system_directory_)) { |
1244 LOG(WARNING) << "Failed to create FileSystem directory: " << | 1244 LOG(WARNING) << "Failed to create FileSystem directory: " << |
1245 file_system_directory_.value(); | 1245 file_system_directory_.value(); |
1246 return false; | 1246 return false; |
1247 } | 1247 } |
1248 origin_database_.reset( | 1248 origin_database_.reset( |
1249 new FileSystemOriginDatabase( | 1249 new FileSystemOriginDatabase( |
1250 file_system_directory_.AppendASCII(kOriginDatabaseName))); | 1250 file_system_directory_.AppendASCII(kOriginDatabaseName))); |
1251 } | 1251 } |
1252 return true; | 1252 return true; |
1253 } | 1253 } |
1254 | 1254 |
1255 } // namespace fileapi | 1255 } // namespace fileapi |
OLD | NEW |