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