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