Home | History | Annotate | Download | only in local
      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 
     33 using base::PlatformFileError;
     34 using fileapi::FileSystemContext;
     35 using fileapi::FileSystemOperationRunner;
     36 using fileapi::FileSystemURL;
     37 using fileapi::FileSystemURLSet;
     38 using quota::QuotaManager;
     39 using webkit_blob::MockBlobURLRequestContext;
     40 using webkit_blob::ScopedTextBlob;
     41 
     42 namespace sync_file_system {
     43 
     44 namespace {
     45 
     46 void Quit() { base::MessageLoop::current()->Quit(); }
     47 
     48 template <typename R>
     49 void 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 
     56 template <typename R>
     57 R 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 
     71 void 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 
     83 void EnsureRunningOn(base::SingleThreadTaskRunner* runner) {
     84   EXPECT_TRUE(runner->RunsTasksOnCurrentThread());
     85 }
     86 
     87 void 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 
     96 void 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 
    115 void 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 
    131 void 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 
    145 class 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 
    181 void 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 
    190 void 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 
    199 CannedSyncableFileSystem::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 
    214 CannedSyncableFileSystem::~CannedSyncableFileSystem() {}
    215 
    216 void 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 
    250 void 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 
    259 FileSystemURL 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 
    267 PlatformFileError 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 
    287 void CannedSyncableFileSystem::AddSyncStatusObserver(
    288     LocalFileSyncStatus::Observer* observer) {
    289   sync_status_observers_->AddObserver(observer);
    290 }
    291 
    292 void CannedSyncableFileSystem::RemoveSyncStatusObserver(
    293     LocalFileSyncStatus::Observer* observer) {
    294   sync_status_observers_->RemoveObserver(observer);
    295 }
    296 
    297 SyncStatusCode 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 
    312 PlatformFileError 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 
    322 PlatformFileError 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 
    332 PlatformFileError 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 
    343 PlatformFileError 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 
    354 PlatformFileError 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 
    365 PlatformFileError 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 
    379 PlatformFileError 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 
    390 PlatformFileError 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 
    400 PlatformFileError 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 
    410 PlatformFileError 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 
    422 PlatformFileError 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 
    436 PlatformFileError 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 
    448 int64 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 
    460 int64 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 
    470 PlatformFileError 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 
    481 quota::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 
    492 void 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 
    502 void 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 
    512 SyncFileSystemBackend* CannedSyncableFileSystem::backend() {
    513   return SyncFileSystemBackend::GetBackend(file_system_context_);
    514 }
    515 
    516 FileSystemOperationRunner* CannedSyncableFileSystem::operation_runner() {
    517   return file_system_context_->operation_runner();
    518 }
    519 
    520 void CannedSyncableFileSystem::OnSyncEnabled(const FileSystemURL& url) {
    521   sync_status_observers_->Notify(&LocalFileSyncStatus::Observer::OnSyncEnabled,
    522                                  url);
    523 }
    524 
    525 void CannedSyncableFileSystem::OnWriteEnabled(const FileSystemURL& url) {
    526   sync_status_observers_->Notify(&LocalFileSyncStatus::Observer::OnWriteEnabled,
    527                                  url);
    528 }
    529 
    530 void 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 
    538 void 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 
    545 void 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 
    553 void 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 
    561 void 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 
    568 void 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 
    578 void 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 
    585 void CannedSyncableFileSystem::DoFileExists(
    586     const FileSystemURL& url, const StatusCallback& callback) {
    587   EXPECT_TRUE(is_filesystem_opened_);
    588   operation_runner()->FileExists(url, callback);
    589 }
    590 
    591 void CannedSyncableFileSystem::DoDirectoryExists(
    592     const FileSystemURL& url, const StatusCallback& callback) {
    593   EXPECT_TRUE(is_filesystem_opened_);
    594   operation_runner()->DirectoryExists(url, callback);
    595 }
    596 
    597 void 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 
    607 void 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 
    617 void 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 
    626 void 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 
    637 void 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 
    650 void 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 
    659 void 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 
    667 void CannedSyncableFileSystem::DidInitializeFileSystemContext(
    668     SyncStatusCode status) {
    669   sync_status_ = status;
    670   base::MessageLoop::current()->Quit();
    671 }
    672 
    673 void 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