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 "chrome/browser/sync_file_system/local/canned_syncable_file_system.h" 6 7 #include <algorithm> 8 #include <iterator> 9 10 #include "base/bind.h" 11 #include "base/bind_helpers.h" 12 #include "base/files/file.h" 13 #include "base/files/file_util.h" 14 #include "base/guid.h" 15 #include "base/run_loop.h" 16 #include "base/single_thread_task_runner.h" 17 #include "base/task_runner_util.h" 18 #include "base/thread_task_runner_handle.h" 19 #include "chrome/browser/sync_file_system/file_change.h" 20 #include "chrome/browser/sync_file_system/local/local_file_change_tracker.h" 21 #include "chrome/browser/sync_file_system/local/local_file_sync_context.h" 22 #include "chrome/browser/sync_file_system/local/sync_file_system_backend.h" 23 #include "chrome/browser/sync_file_system/syncable_file_system_util.h" 24 #include "content/public/test/mock_blob_url_request_context.h" 25 #include "content/public/test/mock_special_storage_policy.h" 26 #include "content/public/test/test_file_system_options.h" 27 #include "storage/browser/fileapi/external_mount_points.h" 28 #include "storage/browser/fileapi/file_system_backend.h" 29 #include "storage/browser/fileapi/file_system_context.h" 30 #include "storage/browser/fileapi/file_system_operation_context.h" 31 #include "storage/browser/fileapi/file_system_operation_runner.h" 32 #include "storage/browser/quota/quota_manager.h" 33 #include "storage/common/blob/shareable_file_reference.h" 34 #include "testing/gtest/include/gtest/gtest.h" 35 36 using base::File; 37 using storage::FileSystemContext; 38 using storage::FileSystemOperationRunner; 39 using storage::FileSystemURL; 40 using storage::FileSystemURLSet; 41 using storage::QuotaManager; 42 using content::MockBlobURLRequestContext; 43 using content::ScopedTextBlob; 44 45 namespace sync_file_system { 46 47 namespace { 48 49 template <typename R> 50 void AssignAndQuit(base::TaskRunner* original_task_runner, 51 const base::Closure& quit_closure, 52 R* result_out, R result) { 53 DCHECK(result_out); 54 *result_out = result; 55 original_task_runner->PostTask(FROM_HERE, quit_closure); 56 } 57 58 template <typename R> 59 R RunOnThread( 60 base::SingleThreadTaskRunner* task_runner, 61 const tracked_objects::Location& location, 62 const base::Callback<void(const base::Callback<void(R)>& callback)>& task) { 63 R result; 64 base::RunLoop run_loop; 65 task_runner->PostTask( 66 location, 67 base::Bind(task, base::Bind(&AssignAndQuit<R>, 68 base::ThreadTaskRunnerHandle::Get(), 69 run_loop.QuitClosure(), 70 &result))); 71 run_loop.Run(); 72 return result; 73 } 74 75 void RunOnThread(base::SingleThreadTaskRunner* task_runner, 76 const tracked_objects::Location& location, 77 const base::Closure& task) { 78 base::RunLoop run_loop; 79 task_runner->PostTaskAndReply( 80 location, task, 81 base::Bind(base::IgnoreResult( 82 base::Bind(&base::SingleThreadTaskRunner::PostTask, 83 base::ThreadTaskRunnerHandle::Get(), 84 FROM_HERE, run_loop.QuitClosure())))); 85 run_loop.Run(); 86 } 87 88 void EnsureRunningOn(base::SingleThreadTaskRunner* runner) { 89 EXPECT_TRUE(runner->RunsTasksOnCurrentThread()); 90 } 91 92 void VerifySameTaskRunner( 93 base::SingleThreadTaskRunner* runner1, 94 base::SingleThreadTaskRunner* runner2) { 95 ASSERT_TRUE(runner1 != NULL); 96 ASSERT_TRUE(runner2 != NULL); 97 runner1->PostTask(FROM_HERE, 98 base::Bind(&EnsureRunningOn, make_scoped_refptr(runner2))); 99 } 100 101 void OnCreateSnapshotFileAndVerifyData( 102 const std::string& expected_data, 103 const CannedSyncableFileSystem::StatusCallback& callback, 104 base::File::Error result, 105 const base::File::Info& file_info, 106 const base::FilePath& platform_path, 107 const scoped_refptr<storage::ShareableFileReference>& /* file_ref */) { 108 if (result != base::File::FILE_OK) { 109 callback.Run(result); 110 return; 111 } 112 EXPECT_EQ(expected_data.size(), static_cast<size_t>(file_info.size)); 113 std::string data; 114 const bool read_status = base::ReadFileToString(platform_path, &data); 115 EXPECT_TRUE(read_status); 116 EXPECT_EQ(expected_data, data); 117 callback.Run(result); 118 } 119 120 void OnCreateSnapshotFile( 121 base::File::Info* file_info_out, 122 base::FilePath* platform_path_out, 123 const CannedSyncableFileSystem::StatusCallback& callback, 124 base::File::Error result, 125 const base::File::Info& file_info, 126 const base::FilePath& platform_path, 127 const scoped_refptr<storage::ShareableFileReference>& file_ref) { 128 DCHECK(!file_ref.get()); 129 DCHECK(file_info_out); 130 DCHECK(platform_path_out); 131 *file_info_out = file_info; 132 *platform_path_out = platform_path; 133 callback.Run(result); 134 } 135 136 void OnReadDirectory(CannedSyncableFileSystem::FileEntryList* entries_out, 137 const CannedSyncableFileSystem::StatusCallback& callback, 138 base::File::Error error, 139 const storage::FileSystemOperation::FileEntryList& entries, 140 bool has_more) { 141 DCHECK(entries_out); 142 entries_out->reserve(entries_out->size() + entries.size()); 143 std::copy(entries.begin(), entries.end(), std::back_inserter(*entries_out)); 144 145 if (!has_more) 146 callback.Run(error); 147 } 148 149 class WriteHelper { 150 public: 151 WriteHelper() : bytes_written_(0) {} 152 WriteHelper(MockBlobURLRequestContext* request_context, 153 const std::string& blob_data) 154 : bytes_written_(0), 155 request_context_(request_context), 156 blob_data_(new ScopedTextBlob(*request_context, 157 base::GenerateGUID(), 158 blob_data)) { 159 } 160 161 ~WriteHelper() { 162 if (request_context_) { 163 base::ThreadTaskRunnerHandle::Get()->DeleteSoon( 164 FROM_HERE, request_context_.release()); 165 } 166 } 167 168 ScopedTextBlob* scoped_text_blob() const { return blob_data_.get(); } 169 170 void DidWrite(const base::Callback<void(int64 result)>& completion_callback, 171 File::Error error, int64 bytes, bool complete) { 172 if (error == base::File::FILE_OK) { 173 bytes_written_ += bytes; 174 if (!complete) 175 return; 176 } 177 completion_callback.Run(error == base::File::FILE_OK ? 178 bytes_written_ : static_cast<int64>(error)); 179 } 180 181 private: 182 int64 bytes_written_; 183 scoped_ptr<MockBlobURLRequestContext> request_context_; 184 scoped_ptr<ScopedTextBlob> blob_data_; 185 186 DISALLOW_COPY_AND_ASSIGN(WriteHelper); 187 }; 188 189 void DidGetUsageAndQuota(const storage::StatusCallback& callback, 190 int64* usage_out, 191 int64* quota_out, 192 storage::QuotaStatusCode status, 193 int64 usage, 194 int64 quota) { 195 *usage_out = usage; 196 *quota_out = quota; 197 callback.Run(status); 198 } 199 200 void EnsureLastTaskRuns(base::SingleThreadTaskRunner* runner) { 201 base::RunLoop run_loop; 202 runner->PostTaskAndReply( 203 FROM_HERE, base::Bind(&base::DoNothing), run_loop.QuitClosure()); 204 run_loop.Run(); 205 } 206 207 } // namespace 208 209 CannedSyncableFileSystem::CannedSyncableFileSystem( 210 const GURL& origin, 211 leveldb::Env* env_override, 212 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, 213 const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner) 214 : origin_(origin), 215 type_(storage::kFileSystemTypeSyncable), 216 result_(base::File::FILE_OK), 217 sync_status_(sync_file_system::SYNC_STATUS_OK), 218 env_override_(env_override), 219 io_task_runner_(io_task_runner), 220 file_task_runner_(file_task_runner), 221 is_filesystem_set_up_(false), 222 is_filesystem_opened_(false), 223 sync_status_observers_(new ObserverList) { 224 } 225 226 CannedSyncableFileSystem::~CannedSyncableFileSystem() {} 227 228 void CannedSyncableFileSystem::SetUp(QuotaMode quota_mode) { 229 ASSERT_FALSE(is_filesystem_set_up_); 230 ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); 231 232 scoped_refptr<storage::SpecialStoragePolicy> storage_policy = 233 new content::MockSpecialStoragePolicy(); 234 235 if (quota_mode == QUOTA_ENABLED) { 236 quota_manager_ = new QuotaManager(false /* is_incognito */, 237 data_dir_.path(), 238 io_task_runner_.get(), 239 base::ThreadTaskRunnerHandle::Get().get(), 240 storage_policy.get()); 241 } 242 243 std::vector<std::string> additional_allowed_schemes; 244 additional_allowed_schemes.push_back(origin_.scheme()); 245 storage::FileSystemOptions options( 246 storage::FileSystemOptions::PROFILE_MODE_NORMAL, 247 additional_allowed_schemes, 248 env_override_); 249 250 ScopedVector<storage::FileSystemBackend> additional_backends; 251 additional_backends.push_back(SyncFileSystemBackend::CreateForTesting()); 252 253 file_system_context_ = new FileSystemContext( 254 io_task_runner_.get(), 255 file_task_runner_.get(), 256 storage::ExternalMountPoints::CreateRefCounted().get(), 257 storage_policy.get(), 258 quota_manager_.get() ? quota_manager_->proxy() : NULL, 259 additional_backends.Pass(), 260 std::vector<storage::URLRequestAutoMountHandler>(), 261 data_dir_.path(), 262 options); 263 264 is_filesystem_set_up_ = true; 265 } 266 267 void CannedSyncableFileSystem::TearDown() { 268 quota_manager_ = NULL; 269 file_system_context_ = NULL; 270 271 // Make sure we give some more time to finish tasks on other threads. 272 EnsureLastTaskRuns(io_task_runner_.get()); 273 EnsureLastTaskRuns(file_task_runner_.get()); 274 } 275 276 FileSystemURL CannedSyncableFileSystem::URL(const std::string& path) const { 277 EXPECT_TRUE(is_filesystem_set_up_); 278 EXPECT_FALSE(root_url_.is_empty()); 279 280 GURL url(root_url_.spec() + path); 281 return file_system_context_->CrackURL(url); 282 } 283 284 File::Error CannedSyncableFileSystem::OpenFileSystem() { 285 EXPECT_TRUE(is_filesystem_set_up_); 286 287 base::RunLoop run_loop; 288 io_task_runner_->PostTask( 289 FROM_HERE, 290 base::Bind(&CannedSyncableFileSystem::DoOpenFileSystem, 291 base::Unretained(this), 292 base::Bind(&CannedSyncableFileSystem::DidOpenFileSystem, 293 base::Unretained(this), 294 base::ThreadTaskRunnerHandle::Get(), 295 run_loop.QuitClosure()))); 296 run_loop.Run(); 297 298 if (backend()->sync_context()) { 299 // Register 'this' as a sync status observer. 300 RunOnThread( 301 io_task_runner_.get(), 302 FROM_HERE, 303 base::Bind(&CannedSyncableFileSystem::InitializeSyncStatusObserver, 304 base::Unretained(this))); 305 } 306 return result_; 307 } 308 309 void CannedSyncableFileSystem::AddSyncStatusObserver( 310 LocalFileSyncStatus::Observer* observer) { 311 sync_status_observers_->AddObserver(observer); 312 } 313 314 void CannedSyncableFileSystem::RemoveSyncStatusObserver( 315 LocalFileSyncStatus::Observer* observer) { 316 sync_status_observers_->RemoveObserver(observer); 317 } 318 319 SyncStatusCode CannedSyncableFileSystem::MaybeInitializeFileSystemContext( 320 LocalFileSyncContext* sync_context) { 321 DCHECK(sync_context); 322 base::RunLoop run_loop; 323 sync_status_ = sync_file_system::SYNC_STATUS_UNKNOWN; 324 VerifySameTaskRunner(io_task_runner_.get(), 325 sync_context->io_task_runner_.get()); 326 sync_context->MaybeInitializeFileSystemContext( 327 origin_, 328 file_system_context_.get(), 329 base::Bind(&CannedSyncableFileSystem::DidInitializeFileSystemContext, 330 base::Unretained(this), 331 run_loop.QuitClosure())); 332 run_loop.Run(); 333 return sync_status_; 334 } 335 336 File::Error CannedSyncableFileSystem::CreateDirectory( 337 const FileSystemURL& url) { 338 return RunOnThread<File::Error>( 339 io_task_runner_.get(), 340 FROM_HERE, 341 base::Bind(&CannedSyncableFileSystem::DoCreateDirectory, 342 base::Unretained(this), 343 url)); 344 } 345 346 File::Error CannedSyncableFileSystem::CreateFile(const FileSystemURL& url) { 347 return RunOnThread<File::Error>( 348 io_task_runner_.get(), 349 FROM_HERE, 350 base::Bind(&CannedSyncableFileSystem::DoCreateFile, 351 base::Unretained(this), 352 url)); 353 } 354 355 File::Error CannedSyncableFileSystem::Copy( 356 const FileSystemURL& src_url, const FileSystemURL& dest_url) { 357 return RunOnThread<File::Error>(io_task_runner_.get(), 358 FROM_HERE, 359 base::Bind(&CannedSyncableFileSystem::DoCopy, 360 base::Unretained(this), 361 src_url, 362 dest_url)); 363 } 364 365 File::Error CannedSyncableFileSystem::Move( 366 const FileSystemURL& src_url, const FileSystemURL& dest_url) { 367 return RunOnThread<File::Error>(io_task_runner_.get(), 368 FROM_HERE, 369 base::Bind(&CannedSyncableFileSystem::DoMove, 370 base::Unretained(this), 371 src_url, 372 dest_url)); 373 } 374 375 File::Error CannedSyncableFileSystem::TruncateFile( 376 const FileSystemURL& url, int64 size) { 377 return RunOnThread<File::Error>( 378 io_task_runner_.get(), 379 FROM_HERE, 380 base::Bind(&CannedSyncableFileSystem::DoTruncateFile, 381 base::Unretained(this), 382 url, 383 size)); 384 } 385 386 File::Error CannedSyncableFileSystem::TouchFile( 387 const FileSystemURL& url, 388 const base::Time& last_access_time, 389 const base::Time& last_modified_time) { 390 return RunOnThread<File::Error>( 391 io_task_runner_.get(), 392 FROM_HERE, 393 base::Bind(&CannedSyncableFileSystem::DoTouchFile, 394 base::Unretained(this), 395 url, 396 last_access_time, 397 last_modified_time)); 398 } 399 400 File::Error CannedSyncableFileSystem::Remove( 401 const FileSystemURL& url, bool recursive) { 402 return RunOnThread<File::Error>( 403 io_task_runner_.get(), 404 FROM_HERE, 405 base::Bind(&CannedSyncableFileSystem::DoRemove, 406 base::Unretained(this), 407 url, 408 recursive)); 409 } 410 411 File::Error CannedSyncableFileSystem::FileExists( 412 const FileSystemURL& url) { 413 return RunOnThread<File::Error>( 414 io_task_runner_.get(), 415 FROM_HERE, 416 base::Bind(&CannedSyncableFileSystem::DoFileExists, 417 base::Unretained(this), 418 url)); 419 } 420 421 File::Error CannedSyncableFileSystem::DirectoryExists( 422 const FileSystemURL& url) { 423 return RunOnThread<File::Error>( 424 io_task_runner_.get(), 425 FROM_HERE, 426 base::Bind(&CannedSyncableFileSystem::DoDirectoryExists, 427 base::Unretained(this), 428 url)); 429 } 430 431 File::Error CannedSyncableFileSystem::VerifyFile( 432 const FileSystemURL& url, 433 const std::string& expected_data) { 434 return RunOnThread<File::Error>( 435 io_task_runner_.get(), 436 FROM_HERE, 437 base::Bind(&CannedSyncableFileSystem::DoVerifyFile, 438 base::Unretained(this), 439 url, 440 expected_data)); 441 } 442 443 File::Error CannedSyncableFileSystem::GetMetadataAndPlatformPath( 444 const FileSystemURL& url, 445 base::File::Info* info, 446 base::FilePath* platform_path) { 447 return RunOnThread<File::Error>( 448 io_task_runner_.get(), 449 FROM_HERE, 450 base::Bind(&CannedSyncableFileSystem::DoGetMetadataAndPlatformPath, 451 base::Unretained(this), 452 url, 453 info, 454 platform_path)); 455 } 456 457 File::Error CannedSyncableFileSystem::ReadDirectory( 458 const storage::FileSystemURL& url, 459 FileEntryList* entries) { 460 return RunOnThread<File::Error>( 461 io_task_runner_.get(), 462 FROM_HERE, 463 base::Bind(&CannedSyncableFileSystem::DoReadDirectory, 464 base::Unretained(this), 465 url, 466 entries)); 467 } 468 469 int64 CannedSyncableFileSystem::Write( 470 net::URLRequestContext* url_request_context, 471 const FileSystemURL& url, 472 scoped_ptr<storage::BlobDataHandle> blob_data_handle) { 473 return RunOnThread<int64>(io_task_runner_.get(), 474 FROM_HERE, 475 base::Bind(&CannedSyncableFileSystem::DoWrite, 476 base::Unretained(this), 477 url_request_context, 478 url, 479 base::Passed(&blob_data_handle))); 480 } 481 482 int64 CannedSyncableFileSystem::WriteString( 483 const FileSystemURL& url, const std::string& data) { 484 return RunOnThread<int64>(io_task_runner_.get(), 485 FROM_HERE, 486 base::Bind(&CannedSyncableFileSystem::DoWriteString, 487 base::Unretained(this), 488 url, 489 data)); 490 } 491 492 File::Error CannedSyncableFileSystem::DeleteFileSystem() { 493 EXPECT_TRUE(is_filesystem_set_up_); 494 return RunOnThread<File::Error>( 495 io_task_runner_.get(), 496 FROM_HERE, 497 base::Bind(&FileSystemContext::DeleteFileSystem, 498 file_system_context_, 499 origin_, 500 type_)); 501 } 502 503 storage::QuotaStatusCode CannedSyncableFileSystem::GetUsageAndQuota( 504 int64* usage, 505 int64* quota) { 506 return RunOnThread<storage::QuotaStatusCode>( 507 io_task_runner_.get(), 508 FROM_HERE, 509 base::Bind(&CannedSyncableFileSystem::DoGetUsageAndQuota, 510 base::Unretained(this), 511 usage, 512 quota)); 513 } 514 515 void CannedSyncableFileSystem::GetChangedURLsInTracker( 516 FileSystemURLSet* urls) { 517 RunOnThread(file_task_runner_.get(), 518 FROM_HERE, 519 base::Bind(&LocalFileChangeTracker::GetAllChangedURLs, 520 base::Unretained(backend()->change_tracker()), 521 urls)); 522 } 523 524 void CannedSyncableFileSystem::ClearChangeForURLInTracker( 525 const FileSystemURL& url) { 526 RunOnThread(file_task_runner_.get(), 527 FROM_HERE, 528 base::Bind(&LocalFileChangeTracker::ClearChangesForURL, 529 base::Unretained(backend()->change_tracker()), 530 url)); 531 } 532 533 void CannedSyncableFileSystem::GetChangesForURLInTracker( 534 const FileSystemURL& url, 535 FileChangeList* changes) { 536 RunOnThread(file_task_runner_.get(), 537 FROM_HERE, 538 base::Bind(&LocalFileChangeTracker::GetChangesForURL, 539 base::Unretained(backend()->change_tracker()), 540 url, 541 changes)); 542 } 543 544 SyncFileSystemBackend* CannedSyncableFileSystem::backend() { 545 return SyncFileSystemBackend::GetBackend(file_system_context_.get()); 546 } 547 548 FileSystemOperationRunner* CannedSyncableFileSystem::operation_runner() { 549 return file_system_context_->operation_runner(); 550 } 551 552 void CannedSyncableFileSystem::OnSyncEnabled(const FileSystemURL& url) { 553 sync_status_observers_->Notify(&LocalFileSyncStatus::Observer::OnSyncEnabled, 554 url); 555 } 556 557 void CannedSyncableFileSystem::OnWriteEnabled(const FileSystemURL& url) { 558 sync_status_observers_->Notify(&LocalFileSyncStatus::Observer::OnWriteEnabled, 559 url); 560 } 561 562 void CannedSyncableFileSystem::DoOpenFileSystem( 563 const OpenFileSystemCallback& callback) { 564 EXPECT_TRUE(io_task_runner_->RunsTasksOnCurrentThread()); 565 EXPECT_FALSE(is_filesystem_opened_); 566 file_system_context_->OpenFileSystem( 567 origin_, 568 type_, 569 storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, 570 callback); 571 } 572 573 void CannedSyncableFileSystem::DoCreateDirectory( 574 const FileSystemURL& url, 575 const StatusCallback& callback) { 576 EXPECT_TRUE(io_task_runner_->RunsTasksOnCurrentThread()); 577 EXPECT_TRUE(is_filesystem_opened_); 578 operation_runner()->CreateDirectory( 579 url, false /* exclusive */, false /* recursive */, callback); 580 } 581 582 void CannedSyncableFileSystem::DoCreateFile( 583 const FileSystemURL& url, 584 const StatusCallback& callback) { 585 EXPECT_TRUE(io_task_runner_->RunsTasksOnCurrentThread()); 586 EXPECT_TRUE(is_filesystem_opened_); 587 operation_runner()->CreateFile(url, false /* exclusive */, callback); 588 } 589 590 void CannedSyncableFileSystem::DoCopy( 591 const FileSystemURL& src_url, 592 const FileSystemURL& dest_url, 593 const StatusCallback& callback) { 594 EXPECT_TRUE(io_task_runner_->RunsTasksOnCurrentThread()); 595 EXPECT_TRUE(is_filesystem_opened_); 596 operation_runner()->Copy( 597 src_url, 598 dest_url, 599 storage::FileSystemOperation::OPTION_NONE, 600 storage::FileSystemOperationRunner::CopyProgressCallback(), 601 callback); 602 } 603 604 void CannedSyncableFileSystem::DoMove( 605 const FileSystemURL& src_url, 606 const FileSystemURL& dest_url, 607 const StatusCallback& callback) { 608 EXPECT_TRUE(io_task_runner_->RunsTasksOnCurrentThread()); 609 EXPECT_TRUE(is_filesystem_opened_); 610 operation_runner()->Move( 611 src_url, dest_url, storage::FileSystemOperation::OPTION_NONE, callback); 612 } 613 614 void CannedSyncableFileSystem::DoTruncateFile( 615 const FileSystemURL& url, int64 size, 616 const StatusCallback& callback) { 617 EXPECT_TRUE(io_task_runner_->RunsTasksOnCurrentThread()); 618 EXPECT_TRUE(is_filesystem_opened_); 619 operation_runner()->Truncate(url, size, callback); 620 } 621 622 void CannedSyncableFileSystem::DoTouchFile( 623 const FileSystemURL& url, 624 const base::Time& last_access_time, 625 const base::Time& last_modified_time, 626 const StatusCallback& callback) { 627 EXPECT_TRUE(io_task_runner_->RunsTasksOnCurrentThread()); 628 EXPECT_TRUE(is_filesystem_opened_); 629 operation_runner()->TouchFile(url, last_access_time, 630 last_modified_time, callback); 631 } 632 633 void CannedSyncableFileSystem::DoRemove( 634 const FileSystemURL& url, bool recursive, 635 const StatusCallback& callback) { 636 EXPECT_TRUE(io_task_runner_->RunsTasksOnCurrentThread()); 637 EXPECT_TRUE(is_filesystem_opened_); 638 operation_runner()->Remove(url, recursive, callback); 639 } 640 641 void CannedSyncableFileSystem::DoFileExists( 642 const FileSystemURL& url, const StatusCallback& callback) { 643 EXPECT_TRUE(io_task_runner_->RunsTasksOnCurrentThread()); 644 EXPECT_TRUE(is_filesystem_opened_); 645 operation_runner()->FileExists(url, callback); 646 } 647 648 void CannedSyncableFileSystem::DoDirectoryExists( 649 const FileSystemURL& url, const StatusCallback& callback) { 650 EXPECT_TRUE(io_task_runner_->RunsTasksOnCurrentThread()); 651 EXPECT_TRUE(is_filesystem_opened_); 652 operation_runner()->DirectoryExists(url, callback); 653 } 654 655 void CannedSyncableFileSystem::DoVerifyFile( 656 const FileSystemURL& url, 657 const std::string& expected_data, 658 const StatusCallback& callback) { 659 EXPECT_TRUE(io_task_runner_->RunsTasksOnCurrentThread()); 660 EXPECT_TRUE(is_filesystem_opened_); 661 operation_runner()->CreateSnapshotFile( 662 url, 663 base::Bind(&OnCreateSnapshotFileAndVerifyData, expected_data, callback)); 664 } 665 666 void CannedSyncableFileSystem::DoGetMetadataAndPlatformPath( 667 const FileSystemURL& url, 668 base::File::Info* info, 669 base::FilePath* platform_path, 670 const StatusCallback& callback) { 671 EXPECT_TRUE(io_task_runner_->RunsTasksOnCurrentThread()); 672 EXPECT_TRUE(is_filesystem_opened_); 673 operation_runner()->CreateSnapshotFile( 674 url, base::Bind(&OnCreateSnapshotFile, info, platform_path, callback)); 675 } 676 677 void CannedSyncableFileSystem::DoReadDirectory( 678 const FileSystemURL& url, 679 FileEntryList* entries, 680 const StatusCallback& callback) { 681 EXPECT_TRUE(io_task_runner_->RunsTasksOnCurrentThread()); 682 EXPECT_TRUE(is_filesystem_opened_); 683 operation_runner()->ReadDirectory( 684 url, base::Bind(&OnReadDirectory, entries, callback)); 685 } 686 687 void CannedSyncableFileSystem::DoWrite( 688 net::URLRequestContext* url_request_context, 689 const FileSystemURL& url, 690 scoped_ptr<storage::BlobDataHandle> blob_data_handle, 691 const WriteCallback& callback) { 692 EXPECT_TRUE(io_task_runner_->RunsTasksOnCurrentThread()); 693 EXPECT_TRUE(is_filesystem_opened_); 694 WriteHelper* helper = new WriteHelper; 695 operation_runner()->Write(url_request_context, url, 696 blob_data_handle.Pass(), 0, 697 base::Bind(&WriteHelper::DidWrite, 698 base::Owned(helper), callback)); 699 } 700 701 void CannedSyncableFileSystem::DoWriteString( 702 const FileSystemURL& url, 703 const std::string& data, 704 const WriteCallback& callback) { 705 EXPECT_TRUE(io_task_runner_->RunsTasksOnCurrentThread()); 706 EXPECT_TRUE(is_filesystem_opened_); 707 MockBlobURLRequestContext* url_request_context( 708 new MockBlobURLRequestContext(file_system_context_.get())); 709 WriteHelper* helper = new WriteHelper(url_request_context, data); 710 operation_runner()->Write(url_request_context, url, 711 helper->scoped_text_blob()->GetBlobDataHandle(), 0, 712 base::Bind(&WriteHelper::DidWrite, 713 base::Owned(helper), callback)); 714 } 715 716 void CannedSyncableFileSystem::DoGetUsageAndQuota( 717 int64* usage, 718 int64* quota, 719 const storage::StatusCallback& callback) { 720 EXPECT_TRUE(io_task_runner_->RunsTasksOnCurrentThread()); 721 EXPECT_TRUE(is_filesystem_opened_); 722 DCHECK(quota_manager_.get()); 723 quota_manager_->GetUsageAndQuota( 724 origin_, storage_type(), 725 base::Bind(&DidGetUsageAndQuota, callback, usage, quota)); 726 } 727 728 void CannedSyncableFileSystem::DidOpenFileSystem( 729 base::SingleThreadTaskRunner* original_task_runner, 730 const base::Closure& quit_closure, 731 const GURL& root, 732 const std::string& name, 733 File::Error result) { 734 if (io_task_runner_->RunsTasksOnCurrentThread()) { 735 EXPECT_FALSE(is_filesystem_opened_); 736 is_filesystem_opened_ = true; 737 } 738 if (!original_task_runner->RunsTasksOnCurrentThread()) { 739 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); 740 original_task_runner->PostTask( 741 FROM_HERE, 742 base::Bind(&CannedSyncableFileSystem::DidOpenFileSystem, 743 base::Unretained(this), 744 make_scoped_refptr(original_task_runner), 745 quit_closure, 746 root, name, result)); 747 return; 748 } 749 result_ = result; 750 root_url_ = root; 751 quit_closure.Run(); 752 } 753 754 void CannedSyncableFileSystem::DidInitializeFileSystemContext( 755 const base::Closure& quit_closure, 756 SyncStatusCode status) { 757 sync_status_ = status; 758 quit_closure.Run(); 759 } 760 761 void CannedSyncableFileSystem::InitializeSyncStatusObserver() { 762 ASSERT_TRUE(io_task_runner_->RunsTasksOnCurrentThread()); 763 backend()->sync_context()->sync_status()->AddObserver(this); 764 } 765 766 } // namespace sync_file_system 767