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