1 // Copyright 2013 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 <set> 6 #include <string> 7 #include <vector> 8 9 #include "base/bind.h" 10 #include "base/file_util.h" 11 #include "base/files/file_path.h" 12 #include "base/files/scoped_temp_dir.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/platform_file.h" 15 #include "base/run_loop.h" 16 #include "content/public/test/sandbox_file_system_test_helper.h" 17 #include "content/public/test/test_file_system_context.h" 18 #include "testing/gtest/include/gtest/gtest.h" 19 #include "webkit/browser/fileapi/async_file_test_helper.h" 20 #include "webkit/browser/fileapi/external_mount_points.h" 21 #include "webkit/browser/fileapi/file_system_backend.h" 22 #include "webkit/browser/fileapi/file_system_context.h" 23 #include "webkit/browser/fileapi/file_system_operation_context.h" 24 #include "webkit/browser/fileapi/file_system_usage_cache.h" 25 #include "webkit/browser/fileapi/mock_file_change_observer.h" 26 #include "webkit/browser/fileapi/obfuscated_file_util.h" 27 #include "webkit/browser/fileapi/sandbox_directory_database.h" 28 #include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h" 29 #include "webkit/browser/fileapi/sandbox_isolated_origin_database.h" 30 #include "webkit/browser/fileapi/sandbox_origin_database.h" 31 #include "webkit/browser/fileapi/test_file_set.h" 32 #include "webkit/browser/quota/mock_special_storage_policy.h" 33 #include "webkit/browser/quota/quota_manager.h" 34 #include "webkit/common/database/database_identifier.h" 35 #include "webkit/common/quota/quota_types.h" 36 37 namespace fileapi { 38 39 namespace { 40 41 bool FileExists(const base::FilePath& path) { 42 return base::PathExists(path) && !base::DirectoryExists(path); 43 } 44 45 int64 GetSize(const base::FilePath& path) { 46 int64 size; 47 EXPECT_TRUE(base::GetFileSize(path, &size)); 48 return size; 49 } 50 51 // After a move, the dest exists and the source doesn't. 52 // After a copy, both source and dest exist. 53 struct CopyMoveTestCaseRecord { 54 bool is_copy_not_move; 55 const char source_path[64]; 56 const char dest_path[64]; 57 bool cause_overwrite; 58 }; 59 60 const CopyMoveTestCaseRecord kCopyMoveTestCases[] = { 61 // This is the combinatoric set of: 62 // rename vs. same-name 63 // different directory vs. same directory 64 // overwrite vs. no-overwrite 65 // copy vs. move 66 // We can never be called with source and destination paths identical, so 67 // those cases are omitted. 68 {true, "dir0/file0", "dir0/file1", false}, 69 {false, "dir0/file0", "dir0/file1", false}, 70 {true, "dir0/file0", "dir0/file1", true}, 71 {false, "dir0/file0", "dir0/file1", true}, 72 73 {true, "dir0/file0", "dir1/file0", false}, 74 {false, "dir0/file0", "dir1/file0", false}, 75 {true, "dir0/file0", "dir1/file0", true}, 76 {false, "dir0/file0", "dir1/file0", true}, 77 {true, "dir0/file0", "dir1/file1", false}, 78 {false, "dir0/file0", "dir1/file1", false}, 79 {true, "dir0/file0", "dir1/file1", true}, 80 {false, "dir0/file0", "dir1/file1", true}, 81 }; 82 83 struct OriginEnumerationTestRecord { 84 std::string origin_url; 85 bool has_temporary; 86 bool has_persistent; 87 }; 88 89 const OriginEnumerationTestRecord kOriginEnumerationTestRecords[] = { 90 {"http://example.com", false, true}, 91 {"http://example1.com", true, false}, 92 {"https://example1.com", true, true}, 93 {"file://", false, true}, 94 {"http://example.com:8000", false, true}, 95 }; 96 97 FileSystemURL FileSystemURLAppend( 98 const FileSystemURL& url, const base::FilePath::StringType& child) { 99 return FileSystemURL::CreateForTest( 100 url.origin(), url.mount_type(), url.virtual_path().Append(child)); 101 } 102 103 FileSystemURL FileSystemURLAppendUTF8( 104 const FileSystemURL& url, const std::string& child) { 105 return FileSystemURL::CreateForTest( 106 url.origin(), 107 url.mount_type(), 108 url.virtual_path().Append(base::FilePath::FromUTF8Unsafe(child))); 109 } 110 111 FileSystemURL FileSystemURLDirName(const FileSystemURL& url) { 112 return FileSystemURL::CreateForTest( 113 url.origin(), url.mount_type(), VirtualPath::DirName(url.virtual_path())); 114 } 115 116 std::string GetTypeString(FileSystemType type) { 117 return SandboxFileSystemBackendDelegate::GetTypeString(type); 118 } 119 120 bool HasFileSystemType( 121 ObfuscatedFileUtil::AbstractOriginEnumerator* enumerator, 122 FileSystemType type) { 123 return enumerator->HasTypeDirectory(GetTypeString(type)); 124 } 125 126 } // namespace 127 128 // TODO(ericu): The vast majority of this and the other FSFU subclass tests 129 // could theoretically be shared. It would basically be a FSFU interface 130 // compliance test, and only the subclass-specific bits that look into the 131 // implementation would need to be written per-subclass. 132 class ObfuscatedFileUtilTest : public testing::Test { 133 public: 134 ObfuscatedFileUtilTest() 135 : origin_(GURL("http://www.example.com")), 136 type_(kFileSystemTypeTemporary), 137 weak_factory_(this), 138 sandbox_file_system_(origin_, type_), 139 quota_status_(quota::kQuotaStatusUnknown), 140 usage_(-1) { 141 } 142 143 virtual void SetUp() { 144 ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); 145 146 storage_policy_ = new quota::MockSpecialStoragePolicy(); 147 148 quota_manager_ = 149 new quota::QuotaManager(false /* is_incognito */, 150 data_dir_.path(), 151 base::MessageLoopProxy::current().get(), 152 base::MessageLoopProxy::current().get(), 153 storage_policy_.get()); 154 155 // Every time we create a new sandbox_file_system helper, 156 // it creates another context, which creates another path manager, 157 // another sandbox_backend, and another OFU. 158 // We need to pass in the context to skip all that. 159 file_system_context_ = CreateFileSystemContextForTesting( 160 quota_manager_->proxy(), 161 data_dir_.path()); 162 163 sandbox_file_system_.SetUp(file_system_context_.get()); 164 165 change_observers_ = MockFileChangeObserver::CreateList(&change_observer_); 166 } 167 168 virtual void TearDown() { 169 quota_manager_ = NULL; 170 sandbox_file_system_.TearDown(); 171 } 172 173 scoped_ptr<FileSystemOperationContext> LimitedContext( 174 int64 allowed_bytes_growth) { 175 scoped_ptr<FileSystemOperationContext> context( 176 sandbox_file_system_.NewOperationContext()); 177 context->set_allowed_bytes_growth(allowed_bytes_growth); 178 return context.Pass(); 179 } 180 181 scoped_ptr<FileSystemOperationContext> UnlimitedContext() { 182 return LimitedContext(kint64max); 183 } 184 185 FileSystemOperationContext* NewContext( 186 SandboxFileSystemTestHelper* file_system) { 187 change_observer()->ResetCount(); 188 FileSystemOperationContext* context; 189 if (file_system) 190 context = file_system->NewOperationContext(); 191 else 192 context = sandbox_file_system_.NewOperationContext(); 193 // Setting allowed_bytes_growth big enough for all tests. 194 context->set_allowed_bytes_growth(1024 * 1024); 195 context->set_change_observers(change_observers()); 196 return context; 197 } 198 199 const ChangeObserverList& change_observers() const { 200 return change_observers_; 201 } 202 203 MockFileChangeObserver* change_observer() { 204 return &change_observer_; 205 } 206 207 // This can only be used after SetUp has run and created file_system_context_ 208 // and obfuscated_file_util_. 209 // Use this for tests which need to run in multiple origins; we need a test 210 // helper per origin. 211 SandboxFileSystemTestHelper* NewFileSystem( 212 const GURL& origin, fileapi::FileSystemType type) { 213 SandboxFileSystemTestHelper* file_system = 214 new SandboxFileSystemTestHelper(origin, type); 215 216 file_system->SetUp(file_system_context_.get()); 217 return file_system; 218 } 219 220 ObfuscatedFileUtil* ofu() { 221 return static_cast<ObfuscatedFileUtil*>(sandbox_file_system_.file_util()); 222 } 223 224 const base::FilePath& test_directory() const { 225 return data_dir_.path(); 226 } 227 228 const GURL& origin() const { 229 return origin_; 230 } 231 232 fileapi::FileSystemType type() const { 233 return type_; 234 } 235 236 std::string type_string() const { 237 return GetTypeString(type_); 238 } 239 240 int64 ComputeTotalFileSize() { 241 return sandbox_file_system_.ComputeCurrentOriginUsage() - 242 sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage(); 243 } 244 245 void GetUsageFromQuotaManager() { 246 int64 quota = -1; 247 quota_status_ = 248 AsyncFileTestHelper::GetUsageAndQuota(quota_manager_.get(), 249 origin(), 250 sandbox_file_system_.type(), 251 &usage_, 252 "a); 253 EXPECT_EQ(quota::kQuotaStatusOk, quota_status_); 254 } 255 256 void RevokeUsageCache() { 257 quota_manager_->ResetUsageTracker(sandbox_file_system_.storage_type()); 258 usage_cache()->Delete(sandbox_file_system_.GetUsageCachePath()); 259 } 260 261 int64 SizeByQuotaUtil() { 262 return sandbox_file_system_.GetCachedOriginUsage(); 263 } 264 265 int64 SizeInUsageFile() { 266 base::RunLoop().RunUntilIdle(); 267 int64 usage = 0; 268 return usage_cache()->GetUsage( 269 sandbox_file_system_.GetUsageCachePath(), &usage) ? usage : -1; 270 } 271 272 bool PathExists(const FileSystemURL& url) { 273 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 274 base::PlatformFileInfo file_info; 275 base::FilePath platform_path; 276 base::PlatformFileError error = ofu()->GetFileInfo( 277 context.get(), url, &file_info, &platform_path); 278 return error == base::PLATFORM_FILE_OK; 279 } 280 281 bool DirectoryExists(const FileSystemURL& url) { 282 return AsyncFileTestHelper::DirectoryExists(file_system_context(), url); 283 } 284 285 int64 usage() const { return usage_; } 286 FileSystemUsageCache* usage_cache() { 287 return sandbox_file_system_.usage_cache(); 288 } 289 290 FileSystemURL CreateURLFromUTF8(const std::string& path) { 291 return sandbox_file_system_.CreateURLFromUTF8(path); 292 } 293 294 int64 PathCost(const FileSystemURL& url) { 295 return ObfuscatedFileUtil::ComputeFilePathCost(url.path()); 296 } 297 298 FileSystemURL CreateURL(const base::FilePath& path) { 299 return sandbox_file_system_.CreateURL(path); 300 } 301 302 void CheckFileAndCloseHandle( 303 const FileSystemURL& url, base::PlatformFile file_handle) { 304 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 305 base::FilePath local_path; 306 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetLocalFilePath( 307 context.get(), url, &local_path)); 308 309 base::PlatformFileInfo file_info0; 310 base::FilePath data_path; 311 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo( 312 context.get(), url, &file_info0, &data_path)); 313 EXPECT_EQ(data_path, local_path); 314 EXPECT_TRUE(FileExists(data_path)); 315 EXPECT_EQ(0, GetSize(data_path)); 316 317 const char data[] = "test data"; 318 const int length = arraysize(data) - 1; 319 320 if (base::kInvalidPlatformFileValue == file_handle) { 321 bool created = true; 322 base::PlatformFileError error; 323 file_handle = base::CreatePlatformFile( 324 data_path, 325 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE, 326 &created, 327 &error); 328 ASSERT_NE(base::kInvalidPlatformFileValue, file_handle); 329 ASSERT_EQ(base::PLATFORM_FILE_OK, error); 330 EXPECT_FALSE(created); 331 } 332 ASSERT_EQ(length, base::WritePlatformFile(file_handle, 0, data, length)); 333 EXPECT_TRUE(base::ClosePlatformFile(file_handle)); 334 335 base::PlatformFileInfo file_info1; 336 EXPECT_EQ(length, GetSize(data_path)); 337 context.reset(NewContext(NULL)); 338 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo( 339 context.get(), url, &file_info1, &data_path)); 340 EXPECT_EQ(data_path, local_path); 341 342 EXPECT_FALSE(file_info0.is_directory); 343 EXPECT_FALSE(file_info1.is_directory); 344 EXPECT_FALSE(file_info0.is_symbolic_link); 345 EXPECT_FALSE(file_info1.is_symbolic_link); 346 EXPECT_EQ(0, file_info0.size); 347 EXPECT_EQ(length, file_info1.size); 348 EXPECT_LE(file_info0.last_modified, file_info1.last_modified); 349 350 context.reset(NewContext(NULL)); 351 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Truncate( 352 context.get(), url, length * 2)); 353 EXPECT_EQ(length * 2, GetSize(data_path)); 354 355 context.reset(NewContext(NULL)); 356 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Truncate( 357 context.get(), url, 0)); 358 EXPECT_EQ(0, GetSize(data_path)); 359 } 360 361 void ValidateTestDirectory( 362 const FileSystemURL& root_url, 363 const std::set<base::FilePath::StringType>& files, 364 const std::set<base::FilePath::StringType>& directories) { 365 scoped_ptr<FileSystemOperationContext> context; 366 std::set<base::FilePath::StringType>::const_iterator iter; 367 for (iter = files.begin(); iter != files.end(); ++iter) { 368 bool created = true; 369 context.reset(NewContext(NULL)); 370 ASSERT_EQ(base::PLATFORM_FILE_OK, 371 ofu()->EnsureFileExists( 372 context.get(), FileSystemURLAppend(root_url, *iter), 373 &created)); 374 ASSERT_FALSE(created); 375 } 376 for (iter = directories.begin(); iter != directories.end(); ++iter) { 377 context.reset(NewContext(NULL)); 378 EXPECT_TRUE(DirectoryExists( 379 FileSystemURLAppend(root_url, *iter))); 380 } 381 } 382 383 class UsageVerifyHelper { 384 public: 385 UsageVerifyHelper(scoped_ptr<FileSystemOperationContext> context, 386 SandboxFileSystemTestHelper* file_system, 387 int64 expected_usage) 388 : context_(context.Pass()), 389 sandbox_file_system_(file_system), 390 expected_usage_(expected_usage) {} 391 392 ~UsageVerifyHelper() { 393 base::RunLoop().RunUntilIdle(); 394 Check(); 395 } 396 397 FileSystemOperationContext* context() { 398 return context_.get(); 399 } 400 401 private: 402 void Check() { 403 ASSERT_EQ(expected_usage_, 404 sandbox_file_system_->GetCachedOriginUsage()); 405 } 406 407 scoped_ptr<FileSystemOperationContext> context_; 408 SandboxFileSystemTestHelper* sandbox_file_system_; 409 int64 expected_usage_; 410 }; 411 412 scoped_ptr<UsageVerifyHelper> AllowUsageIncrease(int64 requested_growth) { 413 int64 usage = sandbox_file_system_.GetCachedOriginUsage(); 414 return scoped_ptr<UsageVerifyHelper>(new UsageVerifyHelper( 415 LimitedContext(requested_growth), 416 &sandbox_file_system_, usage + requested_growth)); 417 } 418 419 scoped_ptr<UsageVerifyHelper> DisallowUsageIncrease(int64 requested_growth) { 420 int64 usage = sandbox_file_system_.GetCachedOriginUsage(); 421 return scoped_ptr<UsageVerifyHelper>(new UsageVerifyHelper( 422 LimitedContext(requested_growth - 1), &sandbox_file_system_, usage)); 423 } 424 425 void FillTestDirectory( 426 const FileSystemURL& root_url, 427 std::set<base::FilePath::StringType>* files, 428 std::set<base::FilePath::StringType>* directories) { 429 scoped_ptr<FileSystemOperationContext> context; 430 std::vector<DirectoryEntry> entries; 431 EXPECT_EQ(base::PLATFORM_FILE_OK, 432 AsyncFileTestHelper::ReadDirectory( 433 file_system_context(), root_url, &entries)); 434 EXPECT_EQ(0UL, entries.size()); 435 436 files->clear(); 437 files->insert(FILE_PATH_LITERAL("first")); 438 files->insert(FILE_PATH_LITERAL("second")); 439 files->insert(FILE_PATH_LITERAL("third")); 440 directories->clear(); 441 directories->insert(FILE_PATH_LITERAL("fourth")); 442 directories->insert(FILE_PATH_LITERAL("fifth")); 443 directories->insert(FILE_PATH_LITERAL("sixth")); 444 std::set<base::FilePath::StringType>::iterator iter; 445 for (iter = files->begin(); iter != files->end(); ++iter) { 446 bool created = false; 447 context.reset(NewContext(NULL)); 448 ASSERT_EQ(base::PLATFORM_FILE_OK, 449 ofu()->EnsureFileExists( 450 context.get(), 451 FileSystemURLAppend(root_url, *iter), 452 &created)); 453 ASSERT_TRUE(created); 454 } 455 for (iter = directories->begin(); iter != directories->end(); ++iter) { 456 bool exclusive = true; 457 bool recursive = false; 458 context.reset(NewContext(NULL)); 459 EXPECT_EQ(base::PLATFORM_FILE_OK, 460 ofu()->CreateDirectory( 461 context.get(), 462 FileSystemURLAppend(root_url, *iter), 463 exclusive, recursive)); 464 } 465 ValidateTestDirectory(root_url, *files, *directories); 466 } 467 468 void TestReadDirectoryHelper(const FileSystemURL& root_url) { 469 std::set<base::FilePath::StringType> files; 470 std::set<base::FilePath::StringType> directories; 471 FillTestDirectory(root_url, &files, &directories); 472 473 scoped_ptr<FileSystemOperationContext> context; 474 std::vector<DirectoryEntry> entries; 475 context.reset(NewContext(NULL)); 476 EXPECT_EQ(base::PLATFORM_FILE_OK, 477 AsyncFileTestHelper::ReadDirectory( 478 file_system_context(), root_url, &entries)); 479 std::vector<DirectoryEntry>::iterator entry_iter; 480 EXPECT_EQ(files.size() + directories.size(), entries.size()); 481 EXPECT_TRUE(change_observer()->HasNoChange()); 482 for (entry_iter = entries.begin(); entry_iter != entries.end(); 483 ++entry_iter) { 484 const DirectoryEntry& entry = *entry_iter; 485 std::set<base::FilePath::StringType>::iterator iter = 486 files.find(entry.name); 487 if (iter != files.end()) { 488 EXPECT_FALSE(entry.is_directory); 489 files.erase(iter); 490 continue; 491 } 492 iter = directories.find(entry.name); 493 EXPECT_FALSE(directories.end() == iter); 494 EXPECT_TRUE(entry.is_directory); 495 directories.erase(iter); 496 } 497 } 498 499 void TestTouchHelper(const FileSystemURL& url, bool is_file) { 500 base::Time last_access_time = base::Time::Now(); 501 base::Time last_modified_time = base::Time::Now(); 502 503 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 504 EXPECT_EQ(base::PLATFORM_FILE_OK, 505 ofu()->Touch( 506 context.get(), url, last_access_time, last_modified_time)); 507 // Currently we fire no change notifications for Touch. 508 EXPECT_TRUE(change_observer()->HasNoChange()); 509 base::FilePath local_path; 510 base::PlatformFileInfo file_info; 511 context.reset(NewContext(NULL)); 512 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo( 513 context.get(), url, &file_info, &local_path)); 514 // We compare as time_t here to lower our resolution, to avoid false 515 // negatives caused by conversion to the local filesystem's native 516 // representation and back. 517 EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT()); 518 519 context.reset(NewContext(NULL)); 520 last_modified_time += base::TimeDelta::FromHours(1); 521 last_access_time += base::TimeDelta::FromHours(14); 522 EXPECT_EQ(base::PLATFORM_FILE_OK, 523 ofu()->Touch( 524 context.get(), url, last_access_time, last_modified_time)); 525 EXPECT_TRUE(change_observer()->HasNoChange()); 526 context.reset(NewContext(NULL)); 527 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo( 528 context.get(), url, &file_info, &local_path)); 529 EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT()); 530 if (is_file) // Directories in OFU don't support atime. 531 EXPECT_EQ(file_info.last_accessed.ToTimeT(), last_access_time.ToTimeT()); 532 } 533 534 void TestCopyInForeignFileHelper(bool overwrite) { 535 base::ScopedTempDir source_dir; 536 ASSERT_TRUE(source_dir.CreateUniqueTempDir()); 537 base::FilePath root_file_path = source_dir.path(); 538 base::FilePath src_file_path = root_file_path.AppendASCII("file_name"); 539 FileSystemURL dest_url = CreateURLFromUTF8("new file"); 540 int64 src_file_length = 87; 541 542 base::PlatformFileError error_code; 543 bool created = false; 544 int file_flags = base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE; 545 base::PlatformFile file_handle = 546 base::CreatePlatformFile( 547 src_file_path, file_flags, &created, &error_code); 548 EXPECT_TRUE(created); 549 ASSERT_EQ(base::PLATFORM_FILE_OK, error_code); 550 ASSERT_NE(base::kInvalidPlatformFileValue, file_handle); 551 ASSERT_TRUE(base::TruncatePlatformFile(file_handle, src_file_length)); 552 EXPECT_TRUE(base::ClosePlatformFile(file_handle)); 553 554 scoped_ptr<FileSystemOperationContext> context; 555 556 if (overwrite) { 557 context.reset(NewContext(NULL)); 558 EXPECT_EQ(base::PLATFORM_FILE_OK, 559 ofu()->EnsureFileExists(context.get(), dest_url, &created)); 560 EXPECT_TRUE(created); 561 562 // We must have observed one (and only one) create_file_count. 563 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); 564 EXPECT_TRUE(change_observer()->HasNoChange()); 565 } 566 567 const int64 path_cost = 568 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()); 569 if (!overwrite) { 570 // Verify that file creation requires sufficient quota for the path. 571 context.reset(NewContext(NULL)); 572 context->set_allowed_bytes_growth(path_cost + src_file_length - 1); 573 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, 574 ofu()->CopyInForeignFile(context.get(), 575 src_file_path, dest_url)); 576 } 577 578 context.reset(NewContext(NULL)); 579 context->set_allowed_bytes_growth(path_cost + src_file_length); 580 EXPECT_EQ(base::PLATFORM_FILE_OK, 581 ofu()->CopyInForeignFile(context.get(), 582 src_file_path, dest_url)); 583 584 EXPECT_TRUE(PathExists(dest_url)); 585 EXPECT_FALSE(DirectoryExists(dest_url)); 586 587 context.reset(NewContext(NULL)); 588 base::PlatformFileInfo file_info; 589 base::FilePath data_path; 590 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo( 591 context.get(), dest_url, &file_info, &data_path)); 592 EXPECT_NE(data_path, src_file_path); 593 EXPECT_TRUE(FileExists(data_path)); 594 EXPECT_EQ(src_file_length, GetSize(data_path)); 595 596 EXPECT_EQ(base::PLATFORM_FILE_OK, 597 ofu()->DeleteFile(context.get(), dest_url)); 598 } 599 600 void ClearTimestamp(const FileSystemURL& url) { 601 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 602 EXPECT_EQ(base::PLATFORM_FILE_OK, 603 ofu()->Touch(context.get(), url, base::Time(), base::Time())); 604 EXPECT_EQ(base::Time(), GetModifiedTime(url)); 605 } 606 607 base::Time GetModifiedTime(const FileSystemURL& url) { 608 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 609 base::FilePath data_path; 610 base::PlatformFileInfo file_info; 611 context.reset(NewContext(NULL)); 612 EXPECT_EQ(base::PLATFORM_FILE_OK, 613 ofu()->GetFileInfo(context.get(), url, &file_info, &data_path)); 614 EXPECT_TRUE(change_observer()->HasNoChange()); 615 return file_info.last_modified; 616 } 617 618 void TestDirectoryTimestampHelper(const FileSystemURL& base_dir, 619 bool copy, 620 bool overwrite) { 621 scoped_ptr<FileSystemOperationContext> context; 622 const FileSystemURL src_dir_url( 623 FileSystemURLAppendUTF8(base_dir, "foo_dir")); 624 const FileSystemURL dest_dir_url( 625 FileSystemURLAppendUTF8(base_dir, "bar_dir")); 626 627 const FileSystemURL src_file_url( 628 FileSystemURLAppendUTF8(src_dir_url, "hoge")); 629 const FileSystemURL dest_file_url( 630 FileSystemURLAppendUTF8(dest_dir_url, "fuga")); 631 632 context.reset(NewContext(NULL)); 633 EXPECT_EQ(base::PLATFORM_FILE_OK, 634 ofu()->CreateDirectory(context.get(), src_dir_url, true, true)); 635 context.reset(NewContext(NULL)); 636 EXPECT_EQ(base::PLATFORM_FILE_OK, 637 ofu()->CreateDirectory(context.get(), dest_dir_url, true, true)); 638 639 bool created = false; 640 context.reset(NewContext(NULL)); 641 EXPECT_EQ(base::PLATFORM_FILE_OK, 642 ofu()->EnsureFileExists(context.get(), src_file_url, &created)); 643 if (overwrite) { 644 context.reset(NewContext(NULL)); 645 EXPECT_EQ(base::PLATFORM_FILE_OK, 646 ofu()->EnsureFileExists(context.get(), 647 dest_file_url, &created)); 648 } 649 650 ClearTimestamp(src_dir_url); 651 ClearTimestamp(dest_dir_url); 652 context.reset(NewContext(NULL)); 653 EXPECT_EQ(base::PLATFORM_FILE_OK, 654 ofu()->CopyOrMoveFile(context.get(), 655 src_file_url, dest_file_url, 656 FileSystemOperation::OPTION_NONE, 657 copy)); 658 if (copy) 659 EXPECT_EQ(base::Time(), GetModifiedTime(src_dir_url)); 660 else 661 EXPECT_NE(base::Time(), GetModifiedTime(src_dir_url)); 662 EXPECT_NE(base::Time(), GetModifiedTime(dest_dir_url)); 663 } 664 665 int64 ComputeCurrentUsage() { 666 return sandbox_file_system_.ComputeCurrentOriginUsage() - 667 sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage(); 668 } 669 670 FileSystemContext* file_system_context() { 671 return sandbox_file_system_.file_system_context(); 672 } 673 674 const base::FilePath& data_dir_path() const { 675 return data_dir_.path(); 676 } 677 678 protected: 679 base::ScopedTempDir data_dir_; 680 base::MessageLoop message_loop_; 681 scoped_refptr<quota::MockSpecialStoragePolicy> storage_policy_; 682 scoped_refptr<quota::QuotaManager> quota_manager_; 683 scoped_refptr<FileSystemContext> file_system_context_; 684 GURL origin_; 685 fileapi::FileSystemType type_; 686 base::WeakPtrFactory<ObfuscatedFileUtilTest> weak_factory_; 687 SandboxFileSystemTestHelper sandbox_file_system_; 688 quota::QuotaStatusCode quota_status_; 689 int64 usage_; 690 MockFileChangeObserver change_observer_; 691 ChangeObserverList change_observers_; 692 693 private: 694 DISALLOW_COPY_AND_ASSIGN(ObfuscatedFileUtilTest); 695 }; 696 697 TEST_F(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) { 698 base::PlatformFile file_handle = base::kInvalidPlatformFileValue; 699 bool created; 700 FileSystemURL url = CreateURLFromUTF8("fake/file"); 701 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 702 int file_flags = base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE; 703 704 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, 705 ofu()->CreateOrOpen( 706 context.get(), url, file_flags, &file_handle, 707 &created)); 708 709 context.reset(NewContext(NULL)); 710 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, 711 ofu()->DeleteFile(context.get(), url)); 712 713 url = CreateURLFromUTF8("test file"); 714 715 EXPECT_TRUE(change_observer()->HasNoChange()); 716 717 // Verify that file creation requires sufficient quota for the path. 718 context.reset(NewContext(NULL)); 719 context->set_allowed_bytes_growth( 720 ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1); 721 ASSERT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, 722 ofu()->CreateOrOpen( 723 context.get(), url, file_flags, &file_handle, &created)); 724 725 context.reset(NewContext(NULL)); 726 context->set_allowed_bytes_growth( 727 ObfuscatedFileUtil::ComputeFilePathCost(url.path())); 728 ASSERT_EQ(base::PLATFORM_FILE_OK, 729 ofu()->CreateOrOpen( 730 context.get(), url, file_flags, &file_handle, &created)); 731 ASSERT_TRUE(created); 732 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); 733 EXPECT_NE(base::kInvalidPlatformFileValue, file_handle); 734 735 CheckFileAndCloseHandle(url, file_handle); 736 737 context.reset(NewContext(NULL)); 738 base::FilePath local_path; 739 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetLocalFilePath( 740 context.get(), url, &local_path)); 741 EXPECT_TRUE(base::PathExists(local_path)); 742 743 // Verify that deleting a file isn't stopped by zero quota, and that it frees 744 // up quote from its path. 745 context.reset(NewContext(NULL)); 746 context->set_allowed_bytes_growth(0); 747 EXPECT_EQ(base::PLATFORM_FILE_OK, 748 ofu()->DeleteFile(context.get(), url)); 749 EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count()); 750 EXPECT_FALSE(base::PathExists(local_path)); 751 EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()), 752 context->allowed_bytes_growth()); 753 754 context.reset(NewContext(NULL)); 755 bool exclusive = true; 756 bool recursive = true; 757 FileSystemURL directory_url = CreateURLFromUTF8( 758 "series/of/directories"); 759 url = FileSystemURLAppendUTF8(directory_url, "file name"); 760 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory( 761 context.get(), directory_url, exclusive, recursive)); 762 // The oepration created 3 directories recursively. 763 EXPECT_EQ(3, change_observer()->get_and_reset_create_directory_count()); 764 765 context.reset(NewContext(NULL)); 766 file_handle = base::kInvalidPlatformFileValue; 767 ASSERT_EQ(base::PLATFORM_FILE_OK, 768 ofu()->CreateOrOpen( 769 context.get(), url, file_flags, &file_handle, &created)); 770 ASSERT_TRUE(created); 771 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); 772 EXPECT_NE(base::kInvalidPlatformFileValue, file_handle); 773 774 CheckFileAndCloseHandle(url, file_handle); 775 776 context.reset(NewContext(NULL)); 777 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetLocalFilePath( 778 context.get(), url, &local_path)); 779 EXPECT_TRUE(base::PathExists(local_path)); 780 781 context.reset(NewContext(NULL)); 782 EXPECT_EQ(base::PLATFORM_FILE_OK, 783 ofu()->DeleteFile(context.get(), url)); 784 EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count()); 785 EXPECT_FALSE(base::PathExists(local_path)); 786 787 // Make sure we have no unexpected changes. 788 EXPECT_TRUE(change_observer()->HasNoChange()); 789 } 790 791 TEST_F(ObfuscatedFileUtilTest, TestTruncate) { 792 bool created = false; 793 FileSystemURL url = CreateURLFromUTF8("file"); 794 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 795 796 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, 797 ofu()->Truncate(context.get(), url, 4)); 798 799 context.reset(NewContext(NULL)); 800 ASSERT_EQ(base::PLATFORM_FILE_OK, 801 ofu()->EnsureFileExists(context.get(), url, &created)); 802 ASSERT_TRUE(created); 803 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); 804 805 context.reset(NewContext(NULL)); 806 base::FilePath local_path; 807 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetLocalFilePath( 808 context.get(), url, &local_path)); 809 EXPECT_EQ(0, GetSize(local_path)); 810 811 context.reset(NewContext(NULL)); 812 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Truncate( 813 context.get(), url, 10)); 814 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); 815 EXPECT_EQ(10, GetSize(local_path)); 816 817 context.reset(NewContext(NULL)); 818 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Truncate( 819 context.get(), url, 1)); 820 EXPECT_EQ(1, GetSize(local_path)); 821 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); 822 823 EXPECT_FALSE(DirectoryExists(url)); 824 EXPECT_TRUE(PathExists(url)); 825 826 // Make sure we have no unexpected changes. 827 EXPECT_TRUE(change_observer()->HasNoChange()); 828 } 829 830 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnTruncation) { 831 bool created = false; 832 FileSystemURL url = CreateURLFromUTF8("file"); 833 834 ASSERT_EQ(base::PLATFORM_FILE_OK, 835 ofu()->EnsureFileExists( 836 AllowUsageIncrease(PathCost(url))->context(), 837 url, &created)); 838 ASSERT_TRUE(created); 839 ASSERT_EQ(0, ComputeTotalFileSize()); 840 841 ASSERT_EQ(base::PLATFORM_FILE_OK, 842 ofu()->Truncate( 843 AllowUsageIncrease(1020)->context(), 844 url, 1020)); 845 ASSERT_EQ(1020, ComputeTotalFileSize()); 846 847 ASSERT_EQ(base::PLATFORM_FILE_OK, 848 ofu()->Truncate( 849 AllowUsageIncrease(-1020)->context(), 850 url, 0)); 851 ASSERT_EQ(0, ComputeTotalFileSize()); 852 853 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, 854 ofu()->Truncate( 855 DisallowUsageIncrease(1021)->context(), 856 url, 1021)); 857 ASSERT_EQ(0, ComputeTotalFileSize()); 858 859 EXPECT_EQ(base::PLATFORM_FILE_OK, 860 ofu()->Truncate( 861 AllowUsageIncrease(1020)->context(), 862 url, 1020)); 863 ASSERT_EQ(1020, ComputeTotalFileSize()); 864 865 EXPECT_EQ(base::PLATFORM_FILE_OK, 866 ofu()->Truncate( 867 AllowUsageIncrease(0)->context(), 868 url, 1020)); 869 ASSERT_EQ(1020, ComputeTotalFileSize()); 870 871 // quota exceeded 872 { 873 scoped_ptr<UsageVerifyHelper> helper = AllowUsageIncrease(-1); 874 helper->context()->set_allowed_bytes_growth( 875 helper->context()->allowed_bytes_growth() - 1); 876 EXPECT_EQ(base::PLATFORM_FILE_OK, 877 ofu()->Truncate(helper->context(), url, 1019)); 878 ASSERT_EQ(1019, ComputeTotalFileSize()); 879 } 880 881 // Delete backing file to make following truncation fail. 882 base::FilePath local_path; 883 ASSERT_EQ(base::PLATFORM_FILE_OK, 884 ofu()->GetLocalFilePath( 885 UnlimitedContext().get(), 886 url, &local_path)); 887 ASSERT_FALSE(local_path.empty()); 888 ASSERT_TRUE(base::DeleteFile(local_path, false)); 889 890 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, 891 ofu()->Truncate( 892 LimitedContext(1234).get(), 893 url, 1234)); 894 ASSERT_EQ(0, ComputeTotalFileSize()); 895 } 896 897 TEST_F(ObfuscatedFileUtilTest, TestEnsureFileExists) { 898 FileSystemURL url = CreateURLFromUTF8("fake/file"); 899 bool created = false; 900 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 901 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, 902 ofu()->EnsureFileExists( 903 context.get(), url, &created)); 904 EXPECT_TRUE(change_observer()->HasNoChange()); 905 906 // Verify that file creation requires sufficient quota for the path. 907 context.reset(NewContext(NULL)); 908 url = CreateURLFromUTF8("test file"); 909 created = false; 910 context->set_allowed_bytes_growth( 911 ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1); 912 ASSERT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, 913 ofu()->EnsureFileExists(context.get(), url, &created)); 914 ASSERT_FALSE(created); 915 EXPECT_TRUE(change_observer()->HasNoChange()); 916 917 context.reset(NewContext(NULL)); 918 context->set_allowed_bytes_growth( 919 ObfuscatedFileUtil::ComputeFilePathCost(url.path())); 920 ASSERT_EQ(base::PLATFORM_FILE_OK, 921 ofu()->EnsureFileExists(context.get(), url, &created)); 922 ASSERT_TRUE(created); 923 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); 924 925 CheckFileAndCloseHandle(url, base::kInvalidPlatformFileValue); 926 927 context.reset(NewContext(NULL)); 928 ASSERT_EQ(base::PLATFORM_FILE_OK, 929 ofu()->EnsureFileExists(context.get(), url, &created)); 930 ASSERT_FALSE(created); 931 EXPECT_TRUE(change_observer()->HasNoChange()); 932 933 // Also test in a subdirectory. 934 url = CreateURLFromUTF8("path/to/file.txt"); 935 context.reset(NewContext(NULL)); 936 bool exclusive = true; 937 bool recursive = true; 938 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory( 939 context.get(), 940 FileSystemURLDirName(url), 941 exclusive, recursive)); 942 // 2 directories: path/ and path/to. 943 EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count()); 944 945 context.reset(NewContext(NULL)); 946 ASSERT_EQ(base::PLATFORM_FILE_OK, 947 ofu()->EnsureFileExists(context.get(), url, &created)); 948 ASSERT_TRUE(created); 949 EXPECT_FALSE(DirectoryExists(url)); 950 EXPECT_TRUE(PathExists(url)); 951 EXPECT_TRUE(change_observer()->HasNoChange()); 952 } 953 954 TEST_F(ObfuscatedFileUtilTest, TestDirectoryOps) { 955 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 956 957 bool exclusive = false; 958 bool recursive = false; 959 FileSystemURL url = CreateURLFromUTF8("foo/bar"); 960 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, ofu()->CreateDirectory( 961 context.get(), url, exclusive, recursive)); 962 963 context.reset(NewContext(NULL)); 964 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, 965 ofu()->DeleteDirectory(context.get(), url)); 966 967 FileSystemURL root = CreateURLFromUTF8(std::string()); 968 EXPECT_FALSE(DirectoryExists(url)); 969 EXPECT_FALSE(PathExists(url)); 970 context.reset(NewContext(NULL)); 971 EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), root)); 972 973 context.reset(NewContext(NULL)); 974 exclusive = false; 975 recursive = true; 976 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory( 977 context.get(), url, exclusive, recursive)); 978 EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count()); 979 980 EXPECT_TRUE(DirectoryExists(url)); 981 EXPECT_TRUE(PathExists(url)); 982 983 context.reset(NewContext(NULL)); 984 EXPECT_FALSE(ofu()->IsDirectoryEmpty(context.get(), root)); 985 EXPECT_TRUE(DirectoryExists(FileSystemURLDirName(url))); 986 987 context.reset(NewContext(NULL)); 988 EXPECT_FALSE(ofu()->IsDirectoryEmpty(context.get(), 989 FileSystemURLDirName(url))); 990 991 // Can't remove a non-empty directory. 992 context.reset(NewContext(NULL)); 993 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY, 994 ofu()->DeleteDirectory(context.get(), 995 FileSystemURLDirName(url))); 996 EXPECT_TRUE(change_observer()->HasNoChange()); 997 998 base::PlatformFileInfo file_info; 999 base::FilePath local_path; 1000 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo( 1001 context.get(), url, &file_info, &local_path)); 1002 EXPECT_TRUE(local_path.empty()); 1003 EXPECT_TRUE(file_info.is_directory); 1004 EXPECT_FALSE(file_info.is_symbolic_link); 1005 1006 // Same create again should succeed, since exclusive is false. 1007 context.reset(NewContext(NULL)); 1008 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory( 1009 context.get(), url, exclusive, recursive)); 1010 EXPECT_TRUE(change_observer()->HasNoChange()); 1011 1012 exclusive = true; 1013 recursive = true; 1014 context.reset(NewContext(NULL)); 1015 EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory( 1016 context.get(), url, exclusive, recursive)); 1017 EXPECT_TRUE(change_observer()->HasNoChange()); 1018 1019 // Verify that deleting a directory isn't stopped by zero quota, and that it 1020 // frees up quota from its path. 1021 context.reset(NewContext(NULL)); 1022 context->set_allowed_bytes_growth(0); 1023 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->DeleteDirectory(context.get(), url)); 1024 EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count()); 1025 EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()), 1026 context->allowed_bytes_growth()); 1027 1028 url = CreateURLFromUTF8("foo/bop"); 1029 1030 EXPECT_FALSE(DirectoryExists(url)); 1031 EXPECT_FALSE(PathExists(url)); 1032 1033 context.reset(NewContext(NULL)); 1034 EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), url)); 1035 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, ofu()->GetFileInfo( 1036 context.get(), url, &file_info, &local_path)); 1037 1038 // Verify that file creation requires sufficient quota for the path. 1039 exclusive = true; 1040 recursive = false; 1041 context.reset(NewContext(NULL)); 1042 context->set_allowed_bytes_growth( 1043 ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1); 1044 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, ofu()->CreateDirectory( 1045 context.get(), url, exclusive, recursive)); 1046 EXPECT_TRUE(change_observer()->HasNoChange()); 1047 1048 context.reset(NewContext(NULL)); 1049 context->set_allowed_bytes_growth( 1050 ObfuscatedFileUtil::ComputeFilePathCost(url.path())); 1051 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory( 1052 context.get(), url, exclusive, recursive)); 1053 EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); 1054 1055 EXPECT_TRUE(DirectoryExists(url)); 1056 EXPECT_TRUE(PathExists(url)); 1057 1058 exclusive = true; 1059 recursive = false; 1060 context.reset(NewContext(NULL)); 1061 EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory( 1062 context.get(), url, exclusive, recursive)); 1063 EXPECT_TRUE(change_observer()->HasNoChange()); 1064 1065 exclusive = true; 1066 recursive = false; 1067 url = CreateURLFromUTF8("foo"); 1068 context.reset(NewContext(NULL)); 1069 EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory( 1070 context.get(), url, exclusive, recursive)); 1071 EXPECT_TRUE(change_observer()->HasNoChange()); 1072 1073 url = CreateURLFromUTF8("blah"); 1074 1075 EXPECT_FALSE(DirectoryExists(url)); 1076 EXPECT_FALSE(PathExists(url)); 1077 1078 exclusive = true; 1079 recursive = false; 1080 context.reset(NewContext(NULL)); 1081 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory( 1082 context.get(), url, exclusive, recursive)); 1083 EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); 1084 1085 EXPECT_TRUE(DirectoryExists(url)); 1086 EXPECT_TRUE(PathExists(url)); 1087 1088 exclusive = true; 1089 recursive = false; 1090 context.reset(NewContext(NULL)); 1091 EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory( 1092 context.get(), url, exclusive, recursive)); 1093 EXPECT_TRUE(change_observer()->HasNoChange()); 1094 } 1095 1096 TEST_F(ObfuscatedFileUtilTest, TestReadDirectory) { 1097 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1098 bool exclusive = true; 1099 bool recursive = true; 1100 FileSystemURL url = CreateURLFromUTF8("directory/to/use"); 1101 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory( 1102 context.get(), url, exclusive, recursive)); 1103 TestReadDirectoryHelper(url); 1104 } 1105 1106 TEST_F(ObfuscatedFileUtilTest, TestReadRootWithSlash) { 1107 TestReadDirectoryHelper(CreateURLFromUTF8(std::string())); 1108 } 1109 1110 TEST_F(ObfuscatedFileUtilTest, TestReadRootWithEmptyString) { 1111 TestReadDirectoryHelper(CreateURLFromUTF8("/")); 1112 } 1113 1114 TEST_F(ObfuscatedFileUtilTest, TestReadDirectoryOnFile) { 1115 FileSystemURL url = CreateURLFromUTF8("file"); 1116 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1117 1118 bool created = false; 1119 ASSERT_EQ(base::PLATFORM_FILE_OK, 1120 ofu()->EnsureFileExists(context.get(), url, &created)); 1121 ASSERT_TRUE(created); 1122 1123 std::vector<DirectoryEntry> entries; 1124 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY, 1125 AsyncFileTestHelper::ReadDirectory( 1126 file_system_context(), url, &entries)); 1127 1128 EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), url)); 1129 } 1130 1131 TEST_F(ObfuscatedFileUtilTest, TestTouch) { 1132 FileSystemURL url = CreateURLFromUTF8("file"); 1133 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1134 1135 base::Time last_access_time = base::Time::Now(); 1136 base::Time last_modified_time = base::Time::Now(); 1137 1138 // It's not there yet. 1139 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, 1140 ofu()->Touch( 1141 context.get(), url, last_access_time, last_modified_time)); 1142 1143 // OK, now create it. 1144 context.reset(NewContext(NULL)); 1145 bool created = false; 1146 ASSERT_EQ(base::PLATFORM_FILE_OK, 1147 ofu()->EnsureFileExists(context.get(), url, &created)); 1148 ASSERT_TRUE(created); 1149 TestTouchHelper(url, true); 1150 1151 // Now test a directory: 1152 context.reset(NewContext(NULL)); 1153 bool exclusive = true; 1154 bool recursive = false; 1155 url = CreateURLFromUTF8("dir"); 1156 ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(context.get(), 1157 url, exclusive, recursive)); 1158 TestTouchHelper(url, false); 1159 } 1160 1161 TEST_F(ObfuscatedFileUtilTest, TestPathQuotas) { 1162 FileSystemURL url = CreateURLFromUTF8("fake/file"); 1163 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1164 1165 url = CreateURLFromUTF8("file name"); 1166 context->set_allowed_bytes_growth(5); 1167 bool created = false; 1168 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, 1169 ofu()->EnsureFileExists(context.get(), url, &created)); 1170 EXPECT_FALSE(created); 1171 context->set_allowed_bytes_growth(1024); 1172 EXPECT_EQ(base::PLATFORM_FILE_OK, 1173 ofu()->EnsureFileExists(context.get(), url, &created)); 1174 EXPECT_TRUE(created); 1175 int64 path_cost = ObfuscatedFileUtil::ComputeFilePathCost(url.path()); 1176 EXPECT_EQ(1024 - path_cost, context->allowed_bytes_growth()); 1177 1178 context->set_allowed_bytes_growth(1024); 1179 bool exclusive = true; 1180 bool recursive = true; 1181 url = CreateURLFromUTF8("directory/to/use"); 1182 std::vector<base::FilePath::StringType> components; 1183 url.path().GetComponents(&components); 1184 path_cost = 0; 1185 typedef std::vector<base::FilePath::StringType>::iterator iterator; 1186 for (iterator iter = components.begin(); 1187 iter != components.end(); ++iter) { 1188 path_cost += ObfuscatedFileUtil::ComputeFilePathCost( 1189 base::FilePath(*iter)); 1190 } 1191 context.reset(NewContext(NULL)); 1192 context->set_allowed_bytes_growth(1024); 1193 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory( 1194 context.get(), url, exclusive, recursive)); 1195 EXPECT_EQ(1024 - path_cost, context->allowed_bytes_growth()); 1196 } 1197 1198 TEST_F(ObfuscatedFileUtilTest, TestCopyOrMoveFileNotFound) { 1199 FileSystemURL source_url = CreateURLFromUTF8("path0.txt"); 1200 FileSystemURL dest_url = CreateURLFromUTF8("path1.txt"); 1201 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1202 1203 bool is_copy_not_move = false; 1204 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, 1205 ofu()->CopyOrMoveFile(context.get(), source_url, dest_url, 1206 FileSystemOperation::OPTION_NONE, 1207 is_copy_not_move)); 1208 EXPECT_TRUE(change_observer()->HasNoChange()); 1209 context.reset(NewContext(NULL)); 1210 is_copy_not_move = true; 1211 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, 1212 ofu()->CopyOrMoveFile(context.get(), source_url, dest_url, 1213 FileSystemOperation::OPTION_NONE, 1214 is_copy_not_move)); 1215 EXPECT_TRUE(change_observer()->HasNoChange()); 1216 source_url = CreateURLFromUTF8("dir/dir/file"); 1217 bool exclusive = true; 1218 bool recursive = true; 1219 context.reset(NewContext(NULL)); 1220 ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory( 1221 context.get(), 1222 FileSystemURLDirName(source_url), 1223 exclusive, recursive)); 1224 EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count()); 1225 is_copy_not_move = false; 1226 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, 1227 ofu()->CopyOrMoveFile(context.get(), source_url, dest_url, 1228 FileSystemOperation::OPTION_NONE, 1229 is_copy_not_move)); 1230 EXPECT_TRUE(change_observer()->HasNoChange()); 1231 context.reset(NewContext(NULL)); 1232 is_copy_not_move = true; 1233 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, 1234 ofu()->CopyOrMoveFile(context.get(), source_url, dest_url, 1235 FileSystemOperation::OPTION_NONE, 1236 is_copy_not_move)); 1237 EXPECT_TRUE(change_observer()->HasNoChange()); 1238 } 1239 1240 TEST_F(ObfuscatedFileUtilTest, TestCopyOrMoveFileSuccess) { 1241 const int64 kSourceLength = 5; 1242 const int64 kDestLength = 50; 1243 1244 for (size_t i = 0; i < arraysize(kCopyMoveTestCases); ++i) { 1245 SCOPED_TRACE(testing::Message() << "kCopyMoveTestCase " << i); 1246 const CopyMoveTestCaseRecord& test_case = kCopyMoveTestCases[i]; 1247 SCOPED_TRACE(testing::Message() << "\t is_copy_not_move " << 1248 test_case.is_copy_not_move); 1249 SCOPED_TRACE(testing::Message() << "\t source_path " << 1250 test_case.source_path); 1251 SCOPED_TRACE(testing::Message() << "\t dest_path " << 1252 test_case.dest_path); 1253 SCOPED_TRACE(testing::Message() << "\t cause_overwrite " << 1254 test_case.cause_overwrite); 1255 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1256 1257 bool exclusive = false; 1258 bool recursive = true; 1259 FileSystemURL source_url = CreateURLFromUTF8(test_case.source_path); 1260 FileSystemURL dest_url = CreateURLFromUTF8(test_case.dest_path); 1261 1262 context.reset(NewContext(NULL)); 1263 ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory( 1264 context.get(), 1265 FileSystemURLDirName(source_url), 1266 exclusive, recursive)); 1267 context.reset(NewContext(NULL)); 1268 ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory( 1269 context.get(), 1270 FileSystemURLDirName(dest_url), 1271 exclusive, recursive)); 1272 1273 bool created = false; 1274 context.reset(NewContext(NULL)); 1275 ASSERT_EQ(base::PLATFORM_FILE_OK, 1276 ofu()->EnsureFileExists(context.get(), source_url, &created)); 1277 ASSERT_TRUE(created); 1278 context.reset(NewContext(NULL)); 1279 ASSERT_EQ(base::PLATFORM_FILE_OK, 1280 ofu()->Truncate(context.get(), source_url, kSourceLength)); 1281 1282 if (test_case.cause_overwrite) { 1283 context.reset(NewContext(NULL)); 1284 created = false; 1285 ASSERT_EQ(base::PLATFORM_FILE_OK, 1286 ofu()->EnsureFileExists(context.get(), dest_url, &created)); 1287 ASSERT_TRUE(created); 1288 context.reset(NewContext(NULL)); 1289 ASSERT_EQ(base::PLATFORM_FILE_OK, 1290 ofu()->Truncate(context.get(), dest_url, kDestLength)); 1291 } 1292 1293 context.reset(NewContext(NULL)); 1294 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CopyOrMoveFile( 1295 context.get(), source_url, dest_url, FileSystemOperation::OPTION_NONE, 1296 test_case.is_copy_not_move)); 1297 1298 if (test_case.is_copy_not_move) { 1299 base::PlatformFileInfo file_info; 1300 base::FilePath local_path; 1301 context.reset(NewContext(NULL)); 1302 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo( 1303 context.get(), source_url, &file_info, &local_path)); 1304 EXPECT_EQ(kSourceLength, file_info.size); 1305 EXPECT_EQ(base::PLATFORM_FILE_OK, 1306 ofu()->DeleteFile(context.get(), source_url)); 1307 } else { 1308 base::PlatformFileInfo file_info; 1309 base::FilePath local_path; 1310 context.reset(NewContext(NULL)); 1311 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, ofu()->GetFileInfo( 1312 context.get(), source_url, &file_info, &local_path)); 1313 } 1314 base::PlatformFileInfo file_info; 1315 base::FilePath local_path; 1316 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo( 1317 context.get(), dest_url, &file_info, &local_path)); 1318 EXPECT_EQ(kSourceLength, file_info.size); 1319 1320 EXPECT_EQ(base::PLATFORM_FILE_OK, 1321 ofu()->DeleteFile(context.get(), dest_url)); 1322 } 1323 } 1324 1325 TEST_F(ObfuscatedFileUtilTest, TestCopyPathQuotas) { 1326 FileSystemURL src_url = CreateURLFromUTF8("src path"); 1327 FileSystemURL dest_url = CreateURLFromUTF8("destination path"); 1328 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1329 bool created = false; 1330 ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists( 1331 context.get(), src_url, &created)); 1332 1333 bool is_copy = true; 1334 // Copy, no overwrite. 1335 context->set_allowed_bytes_growth( 1336 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) - 1); 1337 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, 1338 ofu()->CopyOrMoveFile( 1339 context.get(), 1340 src_url, dest_url, FileSystemOperation::OPTION_NONE, is_copy)); 1341 context.reset(NewContext(NULL)); 1342 context->set_allowed_bytes_growth( 1343 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path())); 1344 EXPECT_EQ(base::PLATFORM_FILE_OK, 1345 ofu()->CopyOrMoveFile( 1346 context.get(), 1347 src_url, dest_url, FileSystemOperation::OPTION_NONE, is_copy)); 1348 1349 // Copy, with overwrite. 1350 context.reset(NewContext(NULL)); 1351 context->set_allowed_bytes_growth(0); 1352 EXPECT_EQ(base::PLATFORM_FILE_OK, 1353 ofu()->CopyOrMoveFile( 1354 context.get(), 1355 src_url, dest_url, FileSystemOperation::OPTION_NONE, is_copy)); 1356 } 1357 1358 TEST_F(ObfuscatedFileUtilTest, TestMovePathQuotasWithRename) { 1359 FileSystemURL src_url = CreateURLFromUTF8("src path"); 1360 FileSystemURL dest_url = CreateURLFromUTF8("destination path"); 1361 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1362 bool created = false; 1363 ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists( 1364 context.get(), src_url, &created)); 1365 1366 bool is_copy = false; 1367 // Move, rename, no overwrite. 1368 context.reset(NewContext(NULL)); 1369 context->set_allowed_bytes_growth( 1370 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) - 1371 ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()) - 1); 1372 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, 1373 ofu()->CopyOrMoveFile( 1374 context.get(), 1375 src_url, dest_url, FileSystemOperation::OPTION_NONE, is_copy)); 1376 context.reset(NewContext(NULL)); 1377 context->set_allowed_bytes_growth( 1378 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) - 1379 ObfuscatedFileUtil::ComputeFilePathCost(src_url.path())); 1380 EXPECT_EQ(base::PLATFORM_FILE_OK, 1381 ofu()->CopyOrMoveFile( 1382 context.get(), 1383 src_url, dest_url, FileSystemOperation::OPTION_NONE, is_copy)); 1384 1385 context.reset(NewContext(NULL)); 1386 ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists( 1387 context.get(), src_url, &created)); 1388 1389 // Move, rename, with overwrite. 1390 context.reset(NewContext(NULL)); 1391 context->set_allowed_bytes_growth(0); 1392 EXPECT_EQ(base::PLATFORM_FILE_OK, 1393 ofu()->CopyOrMoveFile( 1394 context.get(), 1395 src_url, dest_url, FileSystemOperation::OPTION_NONE, is_copy)); 1396 } 1397 1398 TEST_F(ObfuscatedFileUtilTest, TestMovePathQuotasWithoutRename) { 1399 FileSystemURL src_url = CreateURLFromUTF8("src path"); 1400 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1401 bool created = false; 1402 ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists( 1403 context.get(), src_url, &created)); 1404 1405 bool exclusive = true; 1406 bool recursive = false; 1407 FileSystemURL dir_url = CreateURLFromUTF8("directory path"); 1408 context.reset(NewContext(NULL)); 1409 ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory( 1410 context.get(), dir_url, exclusive, recursive)); 1411 1412 FileSystemURL dest_url = FileSystemURLAppend( 1413 dir_url, src_url.path().value()); 1414 1415 bool is_copy = false; 1416 int64 allowed_bytes_growth = -1000; // Over quota, this should still work. 1417 // Move, no rename, no overwrite. 1418 context.reset(NewContext(NULL)); 1419 context->set_allowed_bytes_growth(allowed_bytes_growth); 1420 EXPECT_EQ(base::PLATFORM_FILE_OK, 1421 ofu()->CopyOrMoveFile( 1422 context.get(), 1423 src_url, dest_url, FileSystemOperation::OPTION_NONE, is_copy)); 1424 EXPECT_EQ(allowed_bytes_growth, context->allowed_bytes_growth()); 1425 1426 // Move, no rename, with overwrite. 1427 context.reset(NewContext(NULL)); 1428 ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists( 1429 context.get(), src_url, &created)); 1430 context.reset(NewContext(NULL)); 1431 context->set_allowed_bytes_growth(allowed_bytes_growth); 1432 EXPECT_EQ(base::PLATFORM_FILE_OK, 1433 ofu()->CopyOrMoveFile( 1434 context.get(), 1435 src_url, dest_url, FileSystemOperation::OPTION_NONE, is_copy)); 1436 EXPECT_EQ( 1437 allowed_bytes_growth + 1438 ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()), 1439 context->allowed_bytes_growth()); 1440 } 1441 1442 TEST_F(ObfuscatedFileUtilTest, TestCopyInForeignFile) { 1443 TestCopyInForeignFileHelper(false /* overwrite */); 1444 TestCopyInForeignFileHelper(true /* overwrite */); 1445 } 1446 1447 TEST_F(ObfuscatedFileUtilTest, TestEnumerator) { 1448 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1449 FileSystemURL src_url = CreateURLFromUTF8("source dir"); 1450 bool exclusive = true; 1451 bool recursive = false; 1452 ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory( 1453 context.get(), src_url, exclusive, recursive)); 1454 1455 std::set<base::FilePath::StringType> files; 1456 std::set<base::FilePath::StringType> directories; 1457 FillTestDirectory(src_url, &files, &directories); 1458 1459 FileSystemURL dest_url = CreateURLFromUTF8("destination dir"); 1460 1461 EXPECT_FALSE(DirectoryExists(dest_url)); 1462 ASSERT_EQ(base::PLATFORM_FILE_OK, 1463 AsyncFileTestHelper::Copy( 1464 file_system_context(), src_url, dest_url)); 1465 1466 ValidateTestDirectory(dest_url, files, directories); 1467 EXPECT_TRUE(DirectoryExists(src_url)); 1468 EXPECT_TRUE(DirectoryExists(dest_url)); 1469 recursive = true; 1470 ASSERT_EQ(base::PLATFORM_FILE_OK, 1471 AsyncFileTestHelper::Remove( 1472 file_system_context(), dest_url, recursive)); 1473 EXPECT_FALSE(DirectoryExists(dest_url)); 1474 } 1475 1476 TEST_F(ObfuscatedFileUtilTest, TestOriginEnumerator) { 1477 scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> 1478 enumerator(ofu()->CreateOriginEnumerator()); 1479 // The test helper starts out with a single filesystem. 1480 EXPECT_TRUE(enumerator.get()); 1481 EXPECT_EQ(origin(), enumerator->Next()); 1482 ASSERT_TRUE(type() == kFileSystemTypeTemporary); 1483 EXPECT_TRUE(HasFileSystemType(enumerator.get(), kFileSystemTypeTemporary)); 1484 EXPECT_FALSE(HasFileSystemType(enumerator.get(), kFileSystemTypePersistent)); 1485 EXPECT_EQ(GURL(), enumerator->Next()); 1486 EXPECT_FALSE(HasFileSystemType(enumerator.get(), kFileSystemTypeTemporary)); 1487 EXPECT_FALSE(HasFileSystemType(enumerator.get(), kFileSystemTypePersistent)); 1488 1489 std::set<GURL> origins_expected; 1490 origins_expected.insert(origin()); 1491 1492 for (size_t i = 0; i < arraysize(kOriginEnumerationTestRecords); ++i) { 1493 SCOPED_TRACE(testing::Message() << 1494 "Validating kOriginEnumerationTestRecords " << i); 1495 const OriginEnumerationTestRecord& record = 1496 kOriginEnumerationTestRecords[i]; 1497 GURL origin_url(record.origin_url); 1498 origins_expected.insert(origin_url); 1499 if (record.has_temporary) { 1500 scoped_ptr<SandboxFileSystemTestHelper> file_system( 1501 NewFileSystem(origin_url, kFileSystemTypeTemporary)); 1502 scoped_ptr<FileSystemOperationContext> context( 1503 NewContext(file_system.get())); 1504 bool created = false; 1505 ASSERT_EQ(base::PLATFORM_FILE_OK, 1506 ofu()->EnsureFileExists( 1507 context.get(), 1508 file_system->CreateURLFromUTF8("file"), 1509 &created)); 1510 EXPECT_TRUE(created); 1511 } 1512 if (record.has_persistent) { 1513 scoped_ptr<SandboxFileSystemTestHelper> file_system( 1514 NewFileSystem(origin_url, kFileSystemTypePersistent)); 1515 scoped_ptr<FileSystemOperationContext> context( 1516 NewContext(file_system.get())); 1517 bool created = false; 1518 ASSERT_EQ(base::PLATFORM_FILE_OK, 1519 ofu()->EnsureFileExists( 1520 context.get(), 1521 file_system->CreateURLFromUTF8("file"), 1522 &created)); 1523 EXPECT_TRUE(created); 1524 } 1525 } 1526 enumerator.reset(ofu()->CreateOriginEnumerator()); 1527 EXPECT_TRUE(enumerator.get()); 1528 std::set<GURL> origins_found; 1529 GURL origin_url; 1530 while (!(origin_url = enumerator->Next()).is_empty()) { 1531 origins_found.insert(origin_url); 1532 SCOPED_TRACE(testing::Message() << "Handling " << origin_url.spec()); 1533 bool found = false; 1534 for (size_t i = 0; !found && i < arraysize(kOriginEnumerationTestRecords); 1535 ++i) { 1536 const OriginEnumerationTestRecord& record = 1537 kOriginEnumerationTestRecords[i]; 1538 if (GURL(record.origin_url) != origin_url) 1539 continue; 1540 found = true; 1541 EXPECT_EQ(record.has_temporary, 1542 HasFileSystemType(enumerator.get(), kFileSystemTypeTemporary)); 1543 EXPECT_EQ(record.has_persistent, 1544 HasFileSystemType(enumerator.get(), kFileSystemTypePersistent)); 1545 } 1546 // Deal with the default filesystem created by the test helper. 1547 if (!found && origin_url == origin()) { 1548 ASSERT_TRUE(type() == kFileSystemTypeTemporary); 1549 EXPECT_TRUE(HasFileSystemType(enumerator.get(), 1550 kFileSystemTypeTemporary)); 1551 EXPECT_FALSE(HasFileSystemType(enumerator.get(), 1552 kFileSystemTypePersistent)); 1553 found = true; 1554 } 1555 EXPECT_TRUE(found); 1556 } 1557 1558 std::set<GURL> diff; 1559 std::set_symmetric_difference(origins_expected.begin(), 1560 origins_expected.end(), origins_found.begin(), origins_found.end(), 1561 inserter(diff, diff.begin())); 1562 EXPECT_TRUE(diff.empty()); 1563 } 1564 1565 TEST_F(ObfuscatedFileUtilTest, TestRevokeUsageCache) { 1566 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1567 1568 int64 expected_quota = 0; 1569 1570 for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) { 1571 SCOPED_TRACE(testing::Message() << "Creating kRegularTestCase " << i); 1572 const test::TestCaseRecord& test_case = test::kRegularTestCases[i]; 1573 base::FilePath file_path(test_case.path); 1574 expected_quota += ObfuscatedFileUtil::ComputeFilePathCost(file_path); 1575 if (test_case.is_directory) { 1576 bool exclusive = true; 1577 bool recursive = false; 1578 ASSERT_EQ(base::PLATFORM_FILE_OK, 1579 ofu()->CreateDirectory(context.get(), CreateURL(file_path), 1580 exclusive, recursive)); 1581 } else { 1582 bool created = false; 1583 ASSERT_EQ(base::PLATFORM_FILE_OK, 1584 ofu()->EnsureFileExists(context.get(), CreateURL(file_path), 1585 &created)); 1586 ASSERT_TRUE(created); 1587 ASSERT_EQ(base::PLATFORM_FILE_OK, 1588 ofu()->Truncate(context.get(), 1589 CreateURL(file_path), 1590 test_case.data_file_size)); 1591 expected_quota += test_case.data_file_size; 1592 } 1593 } 1594 1595 // Usually raw size in usage cache and the usage returned by QuotaUtil 1596 // should be same. 1597 EXPECT_EQ(expected_quota, SizeInUsageFile()); 1598 EXPECT_EQ(expected_quota, SizeByQuotaUtil()); 1599 1600 RevokeUsageCache(); 1601 EXPECT_EQ(-1, SizeInUsageFile()); 1602 EXPECT_EQ(expected_quota, SizeByQuotaUtil()); 1603 1604 // This should reconstruct the cache. 1605 GetUsageFromQuotaManager(); 1606 EXPECT_EQ(expected_quota, SizeInUsageFile()); 1607 EXPECT_EQ(expected_quota, SizeByQuotaUtil()); 1608 EXPECT_EQ(expected_quota, usage()); 1609 } 1610 1611 TEST_F(ObfuscatedFileUtilTest, TestInconsistency) { 1612 const FileSystemURL kPath1 = CreateURLFromUTF8("hoge"); 1613 const FileSystemURL kPath2 = CreateURLFromUTF8("fuga"); 1614 1615 scoped_ptr<FileSystemOperationContext> context; 1616 base::PlatformFile file; 1617 base::PlatformFileInfo file_info; 1618 base::FilePath data_path; 1619 bool created = false; 1620 1621 // Create a non-empty file. 1622 context.reset(NewContext(NULL)); 1623 EXPECT_EQ(base::PLATFORM_FILE_OK, 1624 ofu()->EnsureFileExists(context.get(), kPath1, &created)); 1625 EXPECT_TRUE(created); 1626 context.reset(NewContext(NULL)); 1627 EXPECT_EQ(base::PLATFORM_FILE_OK, 1628 ofu()->Truncate(context.get(), kPath1, 10)); 1629 context.reset(NewContext(NULL)); 1630 EXPECT_EQ(base::PLATFORM_FILE_OK, 1631 ofu()->GetFileInfo( 1632 context.get(), kPath1, &file_info, &data_path)); 1633 EXPECT_EQ(10, file_info.size); 1634 1635 // Destroy database to make inconsistency between database and filesystem. 1636 ofu()->DestroyDirectoryDatabase(origin(), type_string()); 1637 1638 // Try to get file info of broken file. 1639 EXPECT_FALSE(PathExists(kPath1)); 1640 context.reset(NewContext(NULL)); 1641 EXPECT_EQ(base::PLATFORM_FILE_OK, 1642 ofu()->EnsureFileExists(context.get(), kPath1, &created)); 1643 EXPECT_TRUE(created); 1644 context.reset(NewContext(NULL)); 1645 EXPECT_EQ(base::PLATFORM_FILE_OK, 1646 ofu()->GetFileInfo( 1647 context.get(), kPath1, &file_info, &data_path)); 1648 EXPECT_EQ(0, file_info.size); 1649 1650 // Make another broken file to |kPath2|. 1651 context.reset(NewContext(NULL)); 1652 EXPECT_EQ(base::PLATFORM_FILE_OK, 1653 ofu()->EnsureFileExists(context.get(), kPath2, &created)); 1654 EXPECT_TRUE(created); 1655 1656 // Destroy again. 1657 ofu()->DestroyDirectoryDatabase(origin(), type_string()); 1658 1659 // Repair broken |kPath1|. 1660 context.reset(NewContext(NULL)); 1661 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, 1662 ofu()->Touch(context.get(), kPath1, base::Time::Now(), 1663 base::Time::Now())); 1664 EXPECT_EQ(base::PLATFORM_FILE_OK, 1665 ofu()->EnsureFileExists(context.get(), kPath1, &created)); 1666 EXPECT_TRUE(created); 1667 1668 // Copy from sound |kPath1| to broken |kPath2|. 1669 context.reset(NewContext(NULL)); 1670 EXPECT_EQ(base::PLATFORM_FILE_OK, 1671 ofu()->CopyOrMoveFile(context.get(), kPath1, kPath2, 1672 FileSystemOperation::OPTION_NONE, 1673 true /* copy */)); 1674 1675 ofu()->DestroyDirectoryDatabase(origin(), type_string()); 1676 context.reset(NewContext(NULL)); 1677 EXPECT_EQ(base::PLATFORM_FILE_OK, 1678 ofu()->CreateOrOpen( 1679 context.get(), kPath1, 1680 base::PLATFORM_FILE_READ | base::PLATFORM_FILE_CREATE, 1681 &file, &created)); 1682 EXPECT_TRUE(created); 1683 EXPECT_TRUE(base::GetPlatformFileInfo(file, &file_info)); 1684 EXPECT_EQ(0, file_info.size); 1685 EXPECT_TRUE(base::ClosePlatformFile(file)); 1686 } 1687 1688 TEST_F(ObfuscatedFileUtilTest, TestIncompleteDirectoryReading) { 1689 const FileSystemURL kPath[] = { 1690 CreateURLFromUTF8("foo"), 1691 CreateURLFromUTF8("bar"), 1692 CreateURLFromUTF8("baz") 1693 }; 1694 const FileSystemURL empty_path = CreateURL(base::FilePath()); 1695 scoped_ptr<FileSystemOperationContext> context; 1696 1697 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kPath); ++i) { 1698 bool created = false; 1699 context.reset(NewContext(NULL)); 1700 EXPECT_EQ(base::PLATFORM_FILE_OK, 1701 ofu()->EnsureFileExists(context.get(), kPath[i], &created)); 1702 EXPECT_TRUE(created); 1703 } 1704 1705 std::vector<DirectoryEntry> entries; 1706 EXPECT_EQ(base::PLATFORM_FILE_OK, 1707 AsyncFileTestHelper::ReadDirectory( 1708 file_system_context(), empty_path, &entries)); 1709 EXPECT_EQ(3u, entries.size()); 1710 1711 base::FilePath local_path; 1712 EXPECT_EQ(base::PLATFORM_FILE_OK, 1713 ofu()->GetLocalFilePath(context.get(), kPath[0], &local_path)); 1714 EXPECT_TRUE(base::DeleteFile(local_path, false)); 1715 1716 entries.clear(); 1717 EXPECT_EQ(base::PLATFORM_FILE_OK, 1718 AsyncFileTestHelper::ReadDirectory( 1719 file_system_context(), empty_path, &entries)); 1720 EXPECT_EQ(ARRAYSIZE_UNSAFE(kPath) - 1, entries.size()); 1721 } 1722 1723 TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) { 1724 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1725 const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir"); 1726 1727 // Create working directory. 1728 EXPECT_EQ(base::PLATFORM_FILE_OK, 1729 ofu()->CreateDirectory(context.get(), dir_url, false, false)); 1730 1731 // EnsureFileExists, create case. 1732 FileSystemURL url(FileSystemURLAppendUTF8( 1733 dir_url, "EnsureFileExists_file")); 1734 bool created = false; 1735 ClearTimestamp(dir_url); 1736 context.reset(NewContext(NULL)); 1737 EXPECT_EQ(base::PLATFORM_FILE_OK, 1738 ofu()->EnsureFileExists(context.get(), url, &created)); 1739 EXPECT_TRUE(created); 1740 EXPECT_NE(base::Time(), GetModifiedTime(dir_url)); 1741 1742 // non create case. 1743 created = true; 1744 ClearTimestamp(dir_url); 1745 context.reset(NewContext(NULL)); 1746 EXPECT_EQ(base::PLATFORM_FILE_OK, 1747 ofu()->EnsureFileExists(context.get(), url, &created)); 1748 EXPECT_FALSE(created); 1749 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url)); 1750 1751 // fail case. 1752 url = FileSystemURLAppendUTF8(dir_url, "EnsureFileExists_dir"); 1753 context.reset(NewContext(NULL)); 1754 EXPECT_EQ(base::PLATFORM_FILE_OK, 1755 ofu()->CreateDirectory(context.get(), url, false, false)); 1756 1757 ClearTimestamp(dir_url); 1758 context.reset(NewContext(NULL)); 1759 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_FILE, 1760 ofu()->EnsureFileExists(context.get(), url, &created)); 1761 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url)); 1762 1763 // CreateOrOpen, create case. 1764 url = FileSystemURLAppendUTF8(dir_url, "CreateOrOpen_file"); 1765 base::PlatformFile file_handle = base::kInvalidPlatformFileValue; 1766 created = false; 1767 ClearTimestamp(dir_url); 1768 context.reset(NewContext(NULL)); 1769 EXPECT_EQ(base::PLATFORM_FILE_OK, 1770 ofu()->CreateOrOpen( 1771 context.get(), url, 1772 base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE, 1773 &file_handle, &created)); 1774 EXPECT_NE(base::kInvalidPlatformFileValue, file_handle); 1775 EXPECT_TRUE(created); 1776 EXPECT_TRUE(base::ClosePlatformFile(file_handle)); 1777 EXPECT_NE(base::Time(), GetModifiedTime(dir_url)); 1778 1779 // open case. 1780 file_handle = base::kInvalidPlatformFileValue; 1781 created = true; 1782 ClearTimestamp(dir_url); 1783 context.reset(NewContext(NULL)); 1784 EXPECT_EQ(base::PLATFORM_FILE_OK, 1785 ofu()->CreateOrOpen( 1786 context.get(), url, 1787 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE, 1788 &file_handle, &created)); 1789 EXPECT_NE(base::kInvalidPlatformFileValue, file_handle); 1790 EXPECT_FALSE(created); 1791 EXPECT_TRUE(base::ClosePlatformFile(file_handle)); 1792 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url)); 1793 1794 // fail case 1795 file_handle = base::kInvalidPlatformFileValue; 1796 ClearTimestamp(dir_url); 1797 context.reset(NewContext(NULL)); 1798 EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, 1799 ofu()->CreateOrOpen( 1800 context.get(), url, 1801 base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE, 1802 &file_handle, &created)); 1803 EXPECT_EQ(base::kInvalidPlatformFileValue, file_handle); 1804 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url)); 1805 1806 // CreateDirectory, create case. 1807 // Creating CreateDirectory_dir and CreateDirectory_dir/subdir. 1808 url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir"); 1809 FileSystemURL subdir_url(FileSystemURLAppendUTF8(url, "subdir")); 1810 ClearTimestamp(dir_url); 1811 context.reset(NewContext(NULL)); 1812 EXPECT_EQ(base::PLATFORM_FILE_OK, 1813 ofu()->CreateDirectory(context.get(), subdir_url, 1814 true /* exclusive */, true /* recursive */)); 1815 EXPECT_NE(base::Time(), GetModifiedTime(dir_url)); 1816 1817 // create subdir case. 1818 // Creating CreateDirectory_dir/subdir2. 1819 subdir_url = FileSystemURLAppendUTF8(url, "subdir2"); 1820 ClearTimestamp(dir_url); 1821 ClearTimestamp(url); 1822 context.reset(NewContext(NULL)); 1823 EXPECT_EQ(base::PLATFORM_FILE_OK, 1824 ofu()->CreateDirectory(context.get(), subdir_url, 1825 true /* exclusive */, true /* recursive */)); 1826 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url)); 1827 EXPECT_NE(base::Time(), GetModifiedTime(url)); 1828 1829 // fail case. 1830 url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir"); 1831 ClearTimestamp(dir_url); 1832 context.reset(NewContext(NULL)); 1833 EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, 1834 ofu()->CreateDirectory(context.get(), url, 1835 true /* exclusive */, true /* recursive */)); 1836 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url)); 1837 1838 // CopyInForeignFile, create case. 1839 url = FileSystemURLAppendUTF8(dir_url, "CopyInForeignFile_file"); 1840 FileSystemURL src_path = FileSystemURLAppendUTF8( 1841 dir_url, "CopyInForeignFile_src_file"); 1842 context.reset(NewContext(NULL)); 1843 EXPECT_EQ(base::PLATFORM_FILE_OK, 1844 ofu()->EnsureFileExists(context.get(), src_path, &created)); 1845 EXPECT_TRUE(created); 1846 base::FilePath src_local_path; 1847 context.reset(NewContext(NULL)); 1848 EXPECT_EQ(base::PLATFORM_FILE_OK, 1849 ofu()->GetLocalFilePath(context.get(), src_path, &src_local_path)); 1850 1851 ClearTimestamp(dir_url); 1852 context.reset(NewContext(NULL)); 1853 EXPECT_EQ(base::PLATFORM_FILE_OK, 1854 ofu()->CopyInForeignFile(context.get(), 1855 src_local_path, 1856 url)); 1857 EXPECT_NE(base::Time(), GetModifiedTime(dir_url)); 1858 } 1859 1860 TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForDeletion) { 1861 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1862 const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir"); 1863 1864 // Create working directory. 1865 EXPECT_EQ(base::PLATFORM_FILE_OK, 1866 ofu()->CreateDirectory(context.get(), dir_url, false, false)); 1867 1868 // DeleteFile, delete case. 1869 FileSystemURL url = FileSystemURLAppendUTF8( 1870 dir_url, "DeleteFile_file"); 1871 bool created = false; 1872 context.reset(NewContext(NULL)); 1873 EXPECT_EQ(base::PLATFORM_FILE_OK, 1874 ofu()->EnsureFileExists(context.get(), url, &created)); 1875 EXPECT_TRUE(created); 1876 1877 ClearTimestamp(dir_url); 1878 context.reset(NewContext(NULL)); 1879 EXPECT_EQ(base::PLATFORM_FILE_OK, 1880 ofu()->DeleteFile(context.get(), url)); 1881 EXPECT_NE(base::Time(), GetModifiedTime(dir_url)); 1882 1883 // fail case. 1884 ClearTimestamp(dir_url); 1885 context.reset(NewContext(NULL)); 1886 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, 1887 ofu()->DeleteFile(context.get(), url)); 1888 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url)); 1889 1890 // DeleteDirectory, fail case. 1891 url = FileSystemURLAppendUTF8(dir_url, "DeleteDirectory_dir"); 1892 FileSystemURL file_path(FileSystemURLAppendUTF8(url, "pakeratta")); 1893 context.reset(NewContext(NULL)); 1894 EXPECT_EQ(base::PLATFORM_FILE_OK, 1895 ofu()->CreateDirectory(context.get(), url, true, true)); 1896 created = false; 1897 context.reset(NewContext(NULL)); 1898 EXPECT_EQ(base::PLATFORM_FILE_OK, 1899 ofu()->EnsureFileExists(context.get(), file_path, &created)); 1900 EXPECT_TRUE(created); 1901 1902 ClearTimestamp(dir_url); 1903 context.reset(NewContext(NULL)); 1904 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY, 1905 ofu()->DeleteDirectory(context.get(), url)); 1906 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url)); 1907 1908 // delete case. 1909 context.reset(NewContext(NULL)); 1910 EXPECT_EQ(base::PLATFORM_FILE_OK, 1911 ofu()->DeleteFile(context.get(), file_path)); 1912 1913 ClearTimestamp(dir_url); 1914 context.reset(NewContext(NULL)); 1915 EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->DeleteDirectory(context.get(), url)); 1916 EXPECT_NE(base::Time(), GetModifiedTime(dir_url)); 1917 } 1918 1919 TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForCopyAndMove) { 1920 TestDirectoryTimestampHelper( 1921 CreateURLFromUTF8("copy overwrite"), true, true); 1922 TestDirectoryTimestampHelper( 1923 CreateURLFromUTF8("copy non-overwrite"), true, false); 1924 TestDirectoryTimestampHelper( 1925 CreateURLFromUTF8("move overwrite"), false, true); 1926 TestDirectoryTimestampHelper( 1927 CreateURLFromUTF8("move non-overwrite"), false, false); 1928 } 1929 1930 TEST_F(ObfuscatedFileUtilTest, TestFileEnumeratorTimestamp) { 1931 FileSystemURL dir = CreateURLFromUTF8("foo"); 1932 FileSystemURL url1 = FileSystemURLAppendUTF8(dir, "bar"); 1933 FileSystemURL url2 = FileSystemURLAppendUTF8(dir, "baz"); 1934 1935 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1936 EXPECT_EQ(base::PLATFORM_FILE_OK, 1937 ofu()->CreateDirectory(context.get(), dir, false, false)); 1938 1939 bool created = false; 1940 context.reset(NewContext(NULL)); 1941 EXPECT_EQ(base::PLATFORM_FILE_OK, 1942 ofu()->EnsureFileExists(context.get(), url1, &created)); 1943 EXPECT_TRUE(created); 1944 1945 context.reset(NewContext(NULL)); 1946 EXPECT_EQ(base::PLATFORM_FILE_OK, 1947 ofu()->CreateDirectory(context.get(), url2, false, false)); 1948 1949 base::FilePath file_path; 1950 context.reset(NewContext(NULL)); 1951 EXPECT_EQ(base::PLATFORM_FILE_OK, 1952 ofu()->GetLocalFilePath(context.get(), url1, &file_path)); 1953 EXPECT_FALSE(file_path.empty()); 1954 1955 context.reset(NewContext(NULL)); 1956 EXPECT_EQ(base::PLATFORM_FILE_OK, 1957 ofu()->Touch(context.get(), url1, 1958 base::Time::Now() + base::TimeDelta::FromHours(1), 1959 base::Time())); 1960 1961 context.reset(NewContext(NULL)); 1962 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> file_enum( 1963 ofu()->CreateFileEnumerator(context.get(), dir, false)); 1964 1965 int count = 0; 1966 base::FilePath file_path_each; 1967 while (!(file_path_each = file_enum->Next()).empty()) { 1968 context.reset(NewContext(NULL)); 1969 base::PlatformFileInfo file_info; 1970 base::FilePath file_path; 1971 EXPECT_EQ(base::PLATFORM_FILE_OK, 1972 ofu()->GetFileInfo(context.get(), 1973 FileSystemURL::CreateForTest( 1974 dir.origin(), 1975 dir.mount_type(), 1976 file_path_each), 1977 &file_info, &file_path)); 1978 EXPECT_EQ(file_info.is_directory, file_enum->IsDirectory()); 1979 EXPECT_EQ(file_info.last_modified, file_enum->LastModifiedTime()); 1980 EXPECT_EQ(file_info.size, file_enum->Size()); 1981 ++count; 1982 } 1983 EXPECT_EQ(2, count); 1984 } 1985 1986 // crbug.com/176470 1987 #if defined(OS_WIN) || defined(OS_ANDROID) 1988 #define MAYBE_TestQuotaOnCopyFile DISABLED_TestQuotaOnCopyFile 1989 #else 1990 #define MAYBE_TestQuotaOnCopyFile TestQuotaOnCopyFile 1991 #endif 1992 TEST_F(ObfuscatedFileUtilTest, MAYBE_TestQuotaOnCopyFile) { 1993 FileSystemURL from_file(CreateURLFromUTF8("fromfile")); 1994 FileSystemURL obstacle_file(CreateURLFromUTF8("obstaclefile")); 1995 FileSystemURL to_file1(CreateURLFromUTF8("tofile1")); 1996 FileSystemURL to_file2(CreateURLFromUTF8("tofile2")); 1997 bool created; 1998 1999 int64 expected_total_file_size = 0; 2000 ASSERT_EQ(base::PLATFORM_FILE_OK, 2001 ofu()->EnsureFileExists( 2002 AllowUsageIncrease(PathCost(from_file))->context(), 2003 from_file, &created)); 2004 ASSERT_TRUE(created); 2005 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2006 2007 ASSERT_EQ(base::PLATFORM_FILE_OK, 2008 ofu()->EnsureFileExists( 2009 AllowUsageIncrease(PathCost(obstacle_file))->context(), 2010 obstacle_file, &created)); 2011 ASSERT_TRUE(created); 2012 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2013 2014 int64 from_file_size = 1020; 2015 expected_total_file_size += from_file_size; 2016 ASSERT_EQ(base::PLATFORM_FILE_OK, 2017 ofu()->Truncate( 2018 AllowUsageIncrease(from_file_size)->context(), 2019 from_file, from_file_size)); 2020 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2021 2022 int64 obstacle_file_size = 1; 2023 expected_total_file_size += obstacle_file_size; 2024 ASSERT_EQ(base::PLATFORM_FILE_OK, 2025 ofu()->Truncate( 2026 AllowUsageIncrease(obstacle_file_size)->context(), 2027 obstacle_file, obstacle_file_size)); 2028 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2029 2030 int64 to_file1_size = from_file_size; 2031 expected_total_file_size += to_file1_size; 2032 ASSERT_EQ(base::PLATFORM_FILE_OK, 2033 ofu()->CopyOrMoveFile( 2034 AllowUsageIncrease( 2035 PathCost(to_file1) + to_file1_size)->context(), 2036 from_file, to_file1, 2037 FileSystemOperation::OPTION_NONE, 2038 true /* copy */)); 2039 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2040 2041 ASSERT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, 2042 ofu()->CopyOrMoveFile( 2043 DisallowUsageIncrease( 2044 PathCost(to_file2) + from_file_size)->context(), 2045 from_file, to_file2, FileSystemOperation::OPTION_NONE, 2046 true /* copy */)); 2047 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2048 2049 int64 old_obstacle_file_size = obstacle_file_size; 2050 obstacle_file_size = from_file_size; 2051 expected_total_file_size += obstacle_file_size - old_obstacle_file_size; 2052 ASSERT_EQ(base::PLATFORM_FILE_OK, 2053 ofu()->CopyOrMoveFile( 2054 AllowUsageIncrease( 2055 obstacle_file_size - old_obstacle_file_size)->context(), 2056 from_file, obstacle_file, 2057 FileSystemOperation::OPTION_NONE, 2058 true /* copy */)); 2059 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2060 2061 int64 old_from_file_size = from_file_size; 2062 from_file_size = old_from_file_size - 1; 2063 expected_total_file_size += from_file_size - old_from_file_size; 2064 ASSERT_EQ(base::PLATFORM_FILE_OK, 2065 ofu()->Truncate( 2066 AllowUsageIncrease( 2067 from_file_size - old_from_file_size)->context(), 2068 from_file, from_file_size)); 2069 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2070 2071 // quota exceeded 2072 { 2073 old_obstacle_file_size = obstacle_file_size; 2074 obstacle_file_size = from_file_size; 2075 expected_total_file_size += obstacle_file_size - old_obstacle_file_size; 2076 scoped_ptr<UsageVerifyHelper> helper = AllowUsageIncrease( 2077 obstacle_file_size - old_obstacle_file_size); 2078 helper->context()->set_allowed_bytes_growth( 2079 helper->context()->allowed_bytes_growth() - 1); 2080 ASSERT_EQ(base::PLATFORM_FILE_OK, 2081 ofu()->CopyOrMoveFile( 2082 helper->context(), 2083 from_file, obstacle_file, 2084 FileSystemOperation::OPTION_NONE, 2085 true /* copy */)); 2086 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2087 } 2088 } 2089 2090 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnMoveFile) { 2091 FileSystemURL from_file(CreateURLFromUTF8("fromfile")); 2092 FileSystemURL obstacle_file(CreateURLFromUTF8("obstaclefile")); 2093 FileSystemURL to_file(CreateURLFromUTF8("tofile")); 2094 bool created; 2095 2096 int64 expected_total_file_size = 0; 2097 ASSERT_EQ(base::PLATFORM_FILE_OK, 2098 ofu()->EnsureFileExists( 2099 AllowUsageIncrease(PathCost(from_file))->context(), 2100 from_file, &created)); 2101 ASSERT_TRUE(created); 2102 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2103 2104 int64 from_file_size = 1020; 2105 expected_total_file_size += from_file_size; 2106 ASSERT_EQ(base::PLATFORM_FILE_OK, 2107 ofu()->Truncate( 2108 AllowUsageIncrease(from_file_size)->context(), 2109 from_file, from_file_size)); 2110 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2111 2112 int64 to_file_size ALLOW_UNUSED = from_file_size; 2113 from_file_size = 0; 2114 ASSERT_EQ(base::PLATFORM_FILE_OK, 2115 ofu()->CopyOrMoveFile( 2116 AllowUsageIncrease(-PathCost(from_file) + 2117 PathCost(to_file))->context(), 2118 from_file, to_file, 2119 FileSystemOperation::OPTION_NONE, 2120 false /* move */)); 2121 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2122 2123 ASSERT_EQ(base::PLATFORM_FILE_OK, 2124 ofu()->EnsureFileExists( 2125 AllowUsageIncrease(PathCost(from_file))->context(), 2126 from_file, &created)); 2127 ASSERT_TRUE(created); 2128 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2129 2130 ASSERT_EQ(base::PLATFORM_FILE_OK, 2131 ofu()->EnsureFileExists( 2132 AllowUsageIncrease(PathCost(obstacle_file))->context(), 2133 obstacle_file, &created)); 2134 ASSERT_TRUE(created); 2135 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2136 2137 from_file_size = 1020; 2138 expected_total_file_size += from_file_size; 2139 ASSERT_EQ(base::PLATFORM_FILE_OK, 2140 ofu()->Truncate( 2141 AllowUsageIncrease(from_file_size)->context(), 2142 from_file, from_file_size)); 2143 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2144 2145 int64 obstacle_file_size = 1; 2146 expected_total_file_size += obstacle_file_size; 2147 ASSERT_EQ(base::PLATFORM_FILE_OK, 2148 ofu()->Truncate( 2149 AllowUsageIncrease(1)->context(), 2150 obstacle_file, obstacle_file_size)); 2151 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2152 2153 int64 old_obstacle_file_size = obstacle_file_size; 2154 obstacle_file_size = from_file_size; 2155 from_file_size = 0; 2156 expected_total_file_size -= old_obstacle_file_size; 2157 ASSERT_EQ(base::PLATFORM_FILE_OK, 2158 ofu()->CopyOrMoveFile( 2159 AllowUsageIncrease( 2160 -old_obstacle_file_size - PathCost(from_file))->context(), 2161 from_file, obstacle_file, 2162 FileSystemOperation::OPTION_NONE, 2163 false /* move */)); 2164 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2165 2166 ASSERT_EQ(base::PLATFORM_FILE_OK, 2167 ofu()->EnsureFileExists( 2168 AllowUsageIncrease(PathCost(from_file))->context(), 2169 from_file, &created)); 2170 ASSERT_TRUE(created); 2171 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2172 2173 from_file_size = 10; 2174 expected_total_file_size += from_file_size; 2175 ASSERT_EQ(base::PLATFORM_FILE_OK, 2176 ofu()->Truncate( 2177 AllowUsageIncrease(from_file_size)->context(), 2178 from_file, from_file_size)); 2179 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2180 2181 // quota exceeded even after operation 2182 old_obstacle_file_size = obstacle_file_size; 2183 obstacle_file_size = from_file_size; 2184 from_file_size = 0; 2185 expected_total_file_size -= old_obstacle_file_size; 2186 scoped_ptr<FileSystemOperationContext> context = 2187 LimitedContext(-old_obstacle_file_size - PathCost(from_file) - 1); 2188 ASSERT_EQ(base::PLATFORM_FILE_OK, 2189 ofu()->CopyOrMoveFile( 2190 context.get(), from_file, obstacle_file, 2191 FileSystemOperation::OPTION_NONE, 2192 false /* move */)); 2193 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2194 context.reset(); 2195 } 2196 2197 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnRemove) { 2198 FileSystemURL dir(CreateURLFromUTF8("dir")); 2199 FileSystemURL file(CreateURLFromUTF8("file")); 2200 FileSystemURL dfile1(CreateURLFromUTF8("dir/dfile1")); 2201 FileSystemURL dfile2(CreateURLFromUTF8("dir/dfile2")); 2202 bool created; 2203 2204 ASSERT_EQ(base::PLATFORM_FILE_OK, 2205 ofu()->EnsureFileExists( 2206 AllowUsageIncrease(PathCost(file))->context(), 2207 file, &created)); 2208 ASSERT_TRUE(created); 2209 ASSERT_EQ(0, ComputeTotalFileSize()); 2210 2211 ASSERT_EQ(base::PLATFORM_FILE_OK, 2212 ofu()->CreateDirectory( 2213 AllowUsageIncrease(PathCost(dir))->context(), 2214 dir, false, false)); 2215 ASSERT_EQ(0, ComputeTotalFileSize()); 2216 2217 ASSERT_EQ(base::PLATFORM_FILE_OK, 2218 ofu()->EnsureFileExists( 2219 AllowUsageIncrease(PathCost(dfile1))->context(), 2220 dfile1, &created)); 2221 ASSERT_TRUE(created); 2222 ASSERT_EQ(0, ComputeTotalFileSize()); 2223 2224 ASSERT_EQ(base::PLATFORM_FILE_OK, 2225 ofu()->EnsureFileExists( 2226 AllowUsageIncrease(PathCost(dfile2))->context(), 2227 dfile2, &created)); 2228 ASSERT_TRUE(created); 2229 ASSERT_EQ(0, ComputeTotalFileSize()); 2230 2231 ASSERT_EQ(base::PLATFORM_FILE_OK, 2232 ofu()->Truncate( 2233 AllowUsageIncrease(340)->context(), 2234 file, 340)); 2235 ASSERT_EQ(340, ComputeTotalFileSize()); 2236 2237 ASSERT_EQ(base::PLATFORM_FILE_OK, 2238 ofu()->Truncate( 2239 AllowUsageIncrease(1020)->context(), 2240 dfile1, 1020)); 2241 ASSERT_EQ(1360, ComputeTotalFileSize()); 2242 2243 ASSERT_EQ(base::PLATFORM_FILE_OK, 2244 ofu()->Truncate( 2245 AllowUsageIncrease(120)->context(), 2246 dfile2, 120)); 2247 ASSERT_EQ(1480, ComputeTotalFileSize()); 2248 2249 ASSERT_EQ(base::PLATFORM_FILE_OK, 2250 ofu()->DeleteFile( 2251 AllowUsageIncrease(-PathCost(file) - 340)->context(), 2252 file)); 2253 ASSERT_EQ(1140, ComputeTotalFileSize()); 2254 2255 ASSERT_EQ(base::PLATFORM_FILE_OK, 2256 AsyncFileTestHelper::Remove( 2257 file_system_context(), dir, true /* recursive */)); 2258 ASSERT_EQ(0, ComputeTotalFileSize()); 2259 } 2260 2261 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnOpen) { 2262 FileSystemURL file(CreateURLFromUTF8("file")); 2263 base::PlatformFile file_handle; 2264 bool created; 2265 2266 // Creating a file. 2267 ASSERT_EQ(base::PLATFORM_FILE_OK, 2268 ofu()->EnsureFileExists( 2269 AllowUsageIncrease(PathCost(file))->context(), 2270 file, &created)); 2271 ASSERT_TRUE(created); 2272 ASSERT_EQ(0, ComputeTotalFileSize()); 2273 2274 // Opening it, which shouldn't change the usage. 2275 ASSERT_EQ(base::PLATFORM_FILE_OK, 2276 ofu()->CreateOrOpen( 2277 AllowUsageIncrease(0)->context(), file, 2278 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE, 2279 &file_handle, &created)); 2280 ASSERT_EQ(0, ComputeTotalFileSize()); 2281 EXPECT_TRUE(base::ClosePlatformFile(file_handle)); 2282 2283 const int length = 33; 2284 ASSERT_EQ(base::PLATFORM_FILE_OK, 2285 ofu()->Truncate( 2286 AllowUsageIncrease(length)->context(), file, length)); 2287 ASSERT_EQ(length, ComputeTotalFileSize()); 2288 2289 // Opening it with CREATE_ALWAYS flag, which should truncate the file size. 2290 ASSERT_EQ(base::PLATFORM_FILE_OK, 2291 ofu()->CreateOrOpen( 2292 AllowUsageIncrease(-length)->context(), file, 2293 base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE, 2294 &file_handle, &created)); 2295 ASSERT_EQ(0, ComputeTotalFileSize()); 2296 EXPECT_TRUE(base::ClosePlatformFile(file_handle)); 2297 2298 // Extending the file again. 2299 ASSERT_EQ(base::PLATFORM_FILE_OK, 2300 ofu()->Truncate( 2301 AllowUsageIncrease(length)->context(), file, length)); 2302 ASSERT_EQ(length, ComputeTotalFileSize()); 2303 2304 // Opening it with TRUNCATED flag, which should truncate the file size. 2305 ASSERT_EQ(base::PLATFORM_FILE_OK, 2306 ofu()->CreateOrOpen( 2307 AllowUsageIncrease(-length)->context(), file, 2308 base::PLATFORM_FILE_OPEN_TRUNCATED | base::PLATFORM_FILE_WRITE, 2309 &file_handle, &created)); 2310 ASSERT_EQ(0, ComputeTotalFileSize()); 2311 EXPECT_TRUE(base::ClosePlatformFile(file_handle)); 2312 } 2313 2314 TEST_F(ObfuscatedFileUtilTest, MaybeDropDatabasesAliveCase) { 2315 scoped_ptr<ObfuscatedFileUtil> file_util( 2316 ObfuscatedFileUtil::CreateForTesting( 2317 NULL, data_dir_path(), 2318 base::MessageLoopProxy::current().get())); 2319 file_util->InitOriginDatabase(GURL(), true /*create*/); 2320 ASSERT_TRUE(file_util->origin_database_ != NULL); 2321 2322 // Callback to Drop DB is called while ObfuscatedFileUtilTest is still alive. 2323 file_util->db_flush_delay_seconds_ = 0; 2324 file_util->MarkUsed(); 2325 base::RunLoop().RunUntilIdle(); 2326 2327 ASSERT_TRUE(file_util->origin_database_ == NULL); 2328 } 2329 2330 TEST_F(ObfuscatedFileUtilTest, MaybeDropDatabasesAlreadyDeletedCase) { 2331 // Run message loop after OFU is already deleted to make sure callback doesn't 2332 // cause a crash for use after free. 2333 { 2334 scoped_ptr<ObfuscatedFileUtil> file_util( 2335 ObfuscatedFileUtil::CreateForTesting( 2336 NULL, data_dir_path(), 2337 base::MessageLoopProxy::current().get())); 2338 file_util->InitOriginDatabase(GURL(), true /*create*/); 2339 file_util->db_flush_delay_seconds_ = 0; 2340 file_util->MarkUsed(); 2341 } 2342 2343 // At this point the callback is still in the message queue but OFU is gone. 2344 base::RunLoop().RunUntilIdle(); 2345 } 2346 2347 TEST_F(ObfuscatedFileUtilTest, DestroyDirectoryDatabase_Isolated) { 2348 storage_policy_->AddIsolated(origin_); 2349 scoped_ptr<ObfuscatedFileUtil> file_util( 2350 ObfuscatedFileUtil::CreateForTesting( 2351 storage_policy_.get(), data_dir_path(), 2352 base::MessageLoopProxy::current().get())); 2353 const FileSystemURL url = FileSystemURL::CreateForTest( 2354 origin_, kFileSystemTypePersistent, base::FilePath()); 2355 2356 // Create DirectoryDatabase for isolated origin. 2357 SandboxDirectoryDatabase* db = 2358 file_util->GetDirectoryDatabase(url, true /* create */); 2359 ASSERT_TRUE(db != NULL); 2360 2361 // Destory it. 2362 ASSERT_TRUE(file_util->DestroyDirectoryDatabase( 2363 url.origin(), GetTypeString(url.type()))); 2364 ASSERT_TRUE(file_util->directories_.empty()); 2365 } 2366 2367 TEST_F(ObfuscatedFileUtilTest, GetDirectoryDatabase_Isolated) { 2368 storage_policy_->AddIsolated(origin_); 2369 scoped_ptr<ObfuscatedFileUtil> file_util( 2370 ObfuscatedFileUtil::CreateForTesting( 2371 storage_policy_.get(), data_dir_path(), 2372 base::MessageLoopProxy::current().get())); 2373 const FileSystemURL url = FileSystemURL::CreateForTest( 2374 origin_, kFileSystemTypePersistent, base::FilePath()); 2375 2376 // Create DirectoryDatabase for isolated origin. 2377 SandboxDirectoryDatabase* db = 2378 file_util->GetDirectoryDatabase(url, true /* create */); 2379 ASSERT_TRUE(db != NULL); 2380 ASSERT_EQ(1U, file_util->directories_.size()); 2381 2382 // Remove isolated. 2383 storage_policy_->RemoveIsolated(url.origin()); 2384 2385 // This should still get the same database. 2386 SandboxDirectoryDatabase* db2 = 2387 file_util->GetDirectoryDatabase(url, false /* create */); 2388 ASSERT_EQ(db, db2); 2389 } 2390 2391 TEST_F(ObfuscatedFileUtilTest, MigrationBackFromIsolated) { 2392 std::string kFakeDirectoryData("0123456789"); 2393 base::FilePath old_directory_db_path; 2394 2395 // Initialize the directory with one origin using 2396 // SandboxIsolatedOriginDatabase. 2397 { 2398 std::string origin_string = 2399 webkit_database::GetIdentifierFromOrigin(origin_); 2400 SandboxIsolatedOriginDatabase database_old( 2401 origin_string, data_dir_path(), 2402 base::FilePath( 2403 SandboxIsolatedOriginDatabase::kObsoleteOriginDirectory)); 2404 base::FilePath path; 2405 EXPECT_TRUE(database_old.GetPathForOrigin(origin_string, &path)); 2406 EXPECT_FALSE(path.empty()); 2407 2408 // Populate the origin directory with some fake data. 2409 old_directory_db_path = data_dir_path().Append(path); 2410 ASSERT_TRUE(base::CreateDirectory(old_directory_db_path)); 2411 EXPECT_EQ(static_cast<int>(kFakeDirectoryData.size()), 2412 file_util::WriteFile(old_directory_db_path.AppendASCII("dummy"), 2413 kFakeDirectoryData.data(), 2414 kFakeDirectoryData.size())); 2415 } 2416 2417 storage_policy_->AddIsolated(origin_); 2418 scoped_ptr<ObfuscatedFileUtil> file_util( 2419 ObfuscatedFileUtil::CreateForTesting( 2420 storage_policy_.get(), data_dir_path(), 2421 base::MessageLoopProxy::current().get())); 2422 base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED; 2423 base::FilePath origin_directory = file_util->GetDirectoryForOrigin( 2424 origin_, true /* create */, &error); 2425 EXPECT_EQ(base::PLATFORM_FILE_OK, error); 2426 2427 // The database is migrated from the old one. 2428 EXPECT_TRUE(base::DirectoryExists(origin_directory)); 2429 EXPECT_FALSE(base::DirectoryExists(old_directory_db_path)); 2430 2431 // Check we see the same contents in the new origin directory. 2432 std::string origin_db_data; 2433 EXPECT_TRUE(base::PathExists(origin_directory.AppendASCII("dummy"))); 2434 EXPECT_TRUE(base::ReadFileToString( 2435 origin_directory.AppendASCII("dummy"), &origin_db_data)); 2436 EXPECT_EQ(kFakeDirectoryData, origin_db_data); 2437 } 2438 2439 TEST_F(ObfuscatedFileUtilTest, OpenPathInNonDirectory) { 2440 FileSystemURL file(CreateURLFromUTF8("file")); 2441 FileSystemURL path_in_file(CreateURLFromUTF8("file/file")); 2442 bool created; 2443 2444 ASSERT_EQ(base::PLATFORM_FILE_OK, 2445 ofu()->EnsureFileExists(UnlimitedContext().get(), file, &created)); 2446 ASSERT_TRUE(created); 2447 2448 created = false; 2449 base::PlatformFile file_handle = base::kInvalidPlatformFileValue; 2450 int file_flags = base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE; 2451 ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY, 2452 ofu()->CreateOrOpen(UnlimitedContext().get(), 2453 path_in_file, 2454 file_flags, 2455 &file_handle, 2456 &created)); 2457 ASSERT_FALSE(created); 2458 ASSERT_EQ(base::kInvalidPlatformFileValue, file_handle); 2459 2460 ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY, 2461 ofu()->CreateDirectory(UnlimitedContext().get(), 2462 path_in_file, 2463 false /* exclusive */, 2464 false /* recursive */)); 2465 } 2466 2467 TEST_F(ObfuscatedFileUtilTest, CreateDirectory_NotADirectoryInRecursive) { 2468 FileSystemURL file(CreateURLFromUTF8("file")); 2469 FileSystemURL path_in_file(CreateURLFromUTF8("file/child")); 2470 FileSystemURL path_in_file_in_file( 2471 CreateURLFromUTF8("file/child/grandchild")); 2472 bool created; 2473 2474 ASSERT_EQ(base::PLATFORM_FILE_OK, 2475 ofu()->EnsureFileExists(UnlimitedContext().get(), file, &created)); 2476 ASSERT_TRUE(created); 2477 2478 ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY, 2479 ofu()->CreateDirectory(UnlimitedContext().get(), 2480 path_in_file, 2481 false /* exclusive */, 2482 true /* recursive */)); 2483 ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY, 2484 ofu()->CreateDirectory(UnlimitedContext().get(), 2485 path_in_file_in_file, 2486 false /* exclusive */, 2487 true /* recursive */)); 2488 } 2489 2490 } // namespace fileapi 2491