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