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