Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync_file_system / local / syncable_file_system_operation.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/syncable_file_system_operation.h"
6
7 #include "base/logging.h"
8 #include "chrome/browser/sync_file_system/local/local_file_sync_context.h"
9 #include "chrome/browser/sync_file_system/local/sync_file_system_backend.h"
10 #include "chrome/browser/sync_file_system/local/syncable_file_operation_runner.h"
11 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
12 #include "net/url_request/url_request.h"
13 #include "storage/browser/fileapi/file_system_context.h"
14 #include "storage/browser/fileapi/file_system_operation.h"
15 #include "storage/browser/fileapi/file_system_operation_context.h"
16 #include "storage/browser/fileapi/file_system_url.h"
17 #include "storage/browser/fileapi/file_writer_delegate.h"
18 #include "storage/common/blob/shareable_file_reference.h"
19
20 using storage::FileSystemURL;
21
22 namespace sync_file_system {
23
24 namespace {
25
26 void WriteCallbackAdapter(
27     const SyncableFileSystemOperation::WriteCallback& callback,
28     base::File::Error status) {
29   callback.Run(status, 0, true);
30 }
31
32 }  // namespace
33
34 class SyncableFileSystemOperation::QueueableTask
35     : public SyncableFileOperationRunner::Task {
36  public:
37   QueueableTask(base::WeakPtr<SyncableFileSystemOperation> operation,
38                 const base::Closure& task)
39       : operation_(operation),
40         task_(task),
41         target_paths_(operation->target_paths_) {}
42
43   virtual ~QueueableTask() {
44     DCHECK(!operation_);
45   }
46
47   virtual void Run() OVERRIDE {
48     if (!operation_)
49       return;
50     DCHECK(!task_.is_null());
51     task_.Run();
52     operation_.reset();
53   }
54
55   virtual void Cancel() OVERRIDE {
56     DCHECK(!task_.is_null());
57     if (operation_)
58       operation_->OnCancelled();
59     task_.Reset();
60     operation_.reset();
61   }
62
63   virtual const std::vector<FileSystemURL>& target_paths() const OVERRIDE {
64     return target_paths_;
65   }
66
67  private:
68   base::WeakPtr<SyncableFileSystemOperation> operation_;
69   base::Closure task_;
70   std::vector<FileSystemURL> target_paths_;
71   DISALLOW_COPY_AND_ASSIGN(QueueableTask);
72 };
73
74 SyncableFileSystemOperation::~SyncableFileSystemOperation() {}
75
76 void SyncableFileSystemOperation::CreateFile(
77     const FileSystemURL& url,
78     bool exclusive,
79     const StatusCallback& callback) {
80   DCHECK(CalledOnValidThread());
81   if (!operation_runner_.get()) {
82     callback.Run(base::File::FILE_ERROR_NOT_FOUND);
83     return;
84   }
85   DCHECK(operation_runner_.get());
86   target_paths_.push_back(url);
87   completion_callback_ = callback;
88   scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
89       weak_factory_.GetWeakPtr(),
90       base::Bind(&FileSystemOperation::CreateFile,
91                  base::Unretained(impl_.get()),
92                  url, exclusive,
93                  base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
94   operation_runner_->PostOperationTask(task.Pass());
95 }
96
97 void SyncableFileSystemOperation::CreateDirectory(
98     const FileSystemURL& url,
99     bool exclusive,
100     bool recursive,
101     const StatusCallback& callback) {
102   DCHECK(CalledOnValidThread());
103   if (!operation_runner_.get()) {
104     callback.Run(base::File::FILE_ERROR_NOT_FOUND);
105     return;
106   }
107   DCHECK(operation_runner_.get());
108   target_paths_.push_back(url);
109   completion_callback_ = callback;
110   scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
111       weak_factory_.GetWeakPtr(),
112       base::Bind(&FileSystemOperation::CreateDirectory,
113                  base::Unretained(impl_.get()),
114                  url, exclusive, recursive,
115                  base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
116   operation_runner_->PostOperationTask(task.Pass());
117 }
118
119 void SyncableFileSystemOperation::Copy(
120     const FileSystemURL& src_url,
121     const FileSystemURL& dest_url,
122     CopyOrMoveOption option,
123     const CopyProgressCallback& progress_callback,
124     const StatusCallback& callback) {
125   DCHECK(CalledOnValidThread());
126   if (!operation_runner_.get()) {
127     callback.Run(base::File::FILE_ERROR_NOT_FOUND);
128     return;
129   }
130   DCHECK(operation_runner_.get());
131   target_paths_.push_back(dest_url);
132   completion_callback_ = callback;
133   scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
134       weak_factory_.GetWeakPtr(),
135       base::Bind(&FileSystemOperation::Copy,
136                  base::Unretained(impl_.get()),
137                  src_url, dest_url, option, progress_callback,
138                  base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
139   operation_runner_->PostOperationTask(task.Pass());
140 }
141
142 void SyncableFileSystemOperation::Move(
143     const FileSystemURL& src_url,
144     const FileSystemURL& dest_url,
145     CopyOrMoveOption option,
146     const StatusCallback& callback) {
147   DCHECK(CalledOnValidThread());
148   if (!operation_runner_.get()) {
149     callback.Run(base::File::FILE_ERROR_NOT_FOUND);
150     return;
151   }
152   DCHECK(operation_runner_.get());
153   target_paths_.push_back(src_url);
154   target_paths_.push_back(dest_url);
155   completion_callback_ = callback;
156   scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
157       weak_factory_.GetWeakPtr(),
158       base::Bind(&FileSystemOperation::Move,
159                  base::Unretained(impl_.get()),
160                  src_url, dest_url, option,
161                  base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
162   operation_runner_->PostOperationTask(task.Pass());
163 }
164
165 void SyncableFileSystemOperation::DirectoryExists(
166     const FileSystemURL& url,
167     const StatusCallback& callback) {
168   DCHECK(CalledOnValidThread());
169   impl_->DirectoryExists(url, callback);
170 }
171
172 void SyncableFileSystemOperation::FileExists(
173     const FileSystemURL& url,
174     const StatusCallback& callback) {
175   DCHECK(CalledOnValidThread());
176   impl_->FileExists(url, callback);
177 }
178
179 void SyncableFileSystemOperation::GetMetadata(
180     const FileSystemURL& url,
181     const GetMetadataCallback& callback) {
182   DCHECK(CalledOnValidThread());
183   impl_->GetMetadata(url, callback);
184 }
185
186 void SyncableFileSystemOperation::ReadDirectory(
187     const FileSystemURL& url,
188     const ReadDirectoryCallback& callback) {
189   DCHECK(CalledOnValidThread());
190   // This is a read operation and there'd be no hard to let it go even if
191   // directory operation is disabled. (And we should allow this if it's made
192   // on the root directory)
193   impl_->ReadDirectory(url, callback);
194 }
195
196 void SyncableFileSystemOperation::Remove(
197     const FileSystemURL& url, bool recursive,
198     const StatusCallback& callback) {
199   DCHECK(CalledOnValidThread());
200   if (!operation_runner_.get()) {
201     callback.Run(base::File::FILE_ERROR_NOT_FOUND);
202     return;
203   }
204   DCHECK(operation_runner_.get());
205   target_paths_.push_back(url);
206   completion_callback_ = callback;
207   scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
208       weak_factory_.GetWeakPtr(),
209       base::Bind(&FileSystemOperation::Remove,
210                  base::Unretained(impl_.get()),
211                  url, recursive,
212                  base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
213   operation_runner_->PostOperationTask(task.Pass());
214 }
215
216 void SyncableFileSystemOperation::Write(
217     const FileSystemURL& url,
218     scoped_ptr<storage::FileWriterDelegate> writer_delegate,
219     scoped_ptr<net::URLRequest> blob_request,
220     const WriteCallback& callback) {
221   DCHECK(CalledOnValidThread());
222   if (!operation_runner_.get()) {
223     callback.Run(base::File::FILE_ERROR_NOT_FOUND, 0, true);
224     return;
225   }
226   DCHECK(operation_runner_.get());
227   target_paths_.push_back(url);
228   completion_callback_ = base::Bind(&WriteCallbackAdapter, callback);
229   scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
230       weak_factory_.GetWeakPtr(),
231       base::Bind(&FileSystemOperation::Write,
232                  base::Unretained(impl_.get()),
233                  url,
234                  base::Passed(&writer_delegate),
235                  base::Passed(&blob_request),
236                  base::Bind(&self::DidWrite, weak_factory_.GetWeakPtr(),
237                             callback))));
238   operation_runner_->PostOperationTask(task.Pass());
239 }
240
241 void SyncableFileSystemOperation::Truncate(
242     const FileSystemURL& url, int64 length,
243     const StatusCallback& callback) {
244   DCHECK(CalledOnValidThread());
245   if (!operation_runner_.get()) {
246     callback.Run(base::File::FILE_ERROR_NOT_FOUND);
247     return;
248   }
249   DCHECK(operation_runner_.get());
250   target_paths_.push_back(url);
251   completion_callback_ = callback;
252   scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
253       weak_factory_.GetWeakPtr(),
254       base::Bind(&FileSystemOperation::Truncate,
255                  base::Unretained(impl_.get()),
256                  url, length,
257                  base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
258   operation_runner_->PostOperationTask(task.Pass());
259 }
260
261 void SyncableFileSystemOperation::TouchFile(
262     const FileSystemURL& url,
263     const base::Time& last_access_time,
264     const base::Time& last_modified_time,
265     const StatusCallback& callback) {
266   DCHECK(CalledOnValidThread());
267   impl_->TouchFile(url, last_access_time, last_modified_time, callback);
268 }
269
270 void SyncableFileSystemOperation::OpenFile(
271     const FileSystemURL& url,
272     int file_flags,
273     const OpenFileCallback& callback) {
274   NOTREACHED();
275 }
276
277 void SyncableFileSystemOperation::Cancel(
278     const StatusCallback& cancel_callback) {
279   DCHECK(CalledOnValidThread());
280   impl_->Cancel(cancel_callback);
281 }
282
283 void SyncableFileSystemOperation::CreateSnapshotFile(
284     const FileSystemURL& path,
285     const SnapshotFileCallback& callback) {
286   DCHECK(CalledOnValidThread());
287   impl_->CreateSnapshotFile(path, callback);
288 }
289
290 void SyncableFileSystemOperation::CopyInForeignFile(
291     const base::FilePath& src_local_disk_path,
292     const FileSystemURL& dest_url,
293     const StatusCallback& callback) {
294   DCHECK(CalledOnValidThread());
295   if (!operation_runner_.get()) {
296     callback.Run(base::File::FILE_ERROR_NOT_FOUND);
297     return;
298   }
299   DCHECK(operation_runner_.get());
300   target_paths_.push_back(dest_url);
301   completion_callback_ = callback;
302   scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
303       weak_factory_.GetWeakPtr(),
304       base::Bind(&FileSystemOperation::CopyInForeignFile,
305                  base::Unretained(impl_.get()),
306                  src_local_disk_path, dest_url,
307                  base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
308   operation_runner_->PostOperationTask(task.Pass());
309 }
310
311 void SyncableFileSystemOperation::RemoveFile(
312     const FileSystemURL& url,
313     const StatusCallback& callback) {
314   DCHECK(CalledOnValidThread());
315   impl_->RemoveFile(url, callback);
316 }
317
318 void SyncableFileSystemOperation::RemoveDirectory(
319     const FileSystemURL& url,
320     const StatusCallback& callback) {
321   DCHECK(CalledOnValidThread());
322   impl_->RemoveDirectory(url, callback);
323 }
324
325 void SyncableFileSystemOperation::CopyFileLocal(
326     const FileSystemURL& src_url,
327     const FileSystemURL& dest_url,
328     CopyOrMoveOption option,
329     const CopyFileProgressCallback& progress_callback,
330     const StatusCallback& callback) {
331   DCHECK(CalledOnValidThread());
332   impl_->CopyFileLocal(src_url, dest_url, option, progress_callback, callback);
333 }
334
335 void SyncableFileSystemOperation::MoveFileLocal(
336     const FileSystemURL& src_url,
337     const FileSystemURL& dest_url,
338     CopyOrMoveOption option,
339     const StatusCallback& callback) {
340   DCHECK(CalledOnValidThread());
341   impl_->MoveFileLocal(src_url, dest_url, option, callback);
342 }
343
344 base::File::Error SyncableFileSystemOperation::SyncGetPlatformPath(
345     const FileSystemURL& url,
346     base::FilePath* platform_path) {
347   return impl_->SyncGetPlatformPath(url, platform_path);
348 }
349
350 SyncableFileSystemOperation::SyncableFileSystemOperation(
351     const FileSystemURL& url,
352     storage::FileSystemContext* file_system_context,
353     scoped_ptr<storage::FileSystemOperationContext> operation_context)
354     : url_(url), weak_factory_(this) {
355   DCHECK(file_system_context);
356   SyncFileSystemBackend* backend =
357       SyncFileSystemBackend::GetBackend(file_system_context);
358   DCHECK(backend);
359   if (!backend->sync_context()) {
360     // Syncable FileSystem is opened in a file system context which doesn't
361     // support (or is not initialized for) the API.
362     // Returning here to leave operation_runner_ as NULL.
363     return;
364   }
365   impl_.reset(storage::FileSystemOperation::Create(
366       url_, file_system_context, operation_context.Pass()));
367   operation_runner_ = backend->sync_context()->operation_runner();
368 }
369
370 void SyncableFileSystemOperation::DidFinish(base::File::Error status) {
371   DCHECK(CalledOnValidThread());
372   DCHECK(!completion_callback_.is_null());
373   if (operation_runner_.get())
374     operation_runner_->OnOperationCompleted(target_paths_);
375   completion_callback_.Run(status);
376 }
377
378 void SyncableFileSystemOperation::DidWrite(
379     const WriteCallback& callback,
380     base::File::Error result,
381     int64 bytes,
382     bool complete) {
383   DCHECK(CalledOnValidThread());
384   if (!complete) {
385     callback.Run(result, bytes, complete);
386     return;
387   }
388   if (operation_runner_.get())
389     operation_runner_->OnOperationCompleted(target_paths_);
390   callback.Run(result, bytes, complete);
391 }
392
393 void SyncableFileSystemOperation::OnCancelled() {
394   DCHECK(!completion_callback_.is_null());
395   completion_callback_.Run(base::File::FILE_ERROR_ABORT);
396 }
397
398 }  // namespace sync_file_system