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