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.
5 #include "chrome/browser/sync_file_system/local/syncable_file_system_operation.h"
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"
20 using storage::FileSystemURL;
22 namespace sync_file_system {
26 void WriteCallbackAdapter(
27 const SyncableFileSystemOperation::WriteCallback& callback,
28 base::File::Error status) {
29 callback.Run(status, 0, true);
34 class SyncableFileSystemOperation::QueueableTask
35 : public SyncableFileOperationRunner::Task {
37 QueueableTask(base::WeakPtr<SyncableFileSystemOperation> operation,
38 const base::Closure& task)
39 : operation_(operation),
41 target_paths_(operation->target_paths_) {}
43 virtual ~QueueableTask() {
47 virtual void Run() OVERRIDE {
50 DCHECK(!task_.is_null());
55 virtual void Cancel() OVERRIDE {
56 DCHECK(!task_.is_null());
58 operation_->OnCancelled();
63 virtual const std::vector<FileSystemURL>& target_paths() const OVERRIDE {
68 base::WeakPtr<SyncableFileSystemOperation> operation_;
70 std::vector<FileSystemURL> target_paths_;
71 DISALLOW_COPY_AND_ASSIGN(QueueableTask);
74 SyncableFileSystemOperation::~SyncableFileSystemOperation() {}
76 void SyncableFileSystemOperation::CreateFile(
77 const FileSystemURL& url,
79 const StatusCallback& callback) {
80 DCHECK(CalledOnValidThread());
81 if (!operation_runner_.get()) {
82 callback.Run(base::File::FILE_ERROR_NOT_FOUND);
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()),
93 base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
94 operation_runner_->PostOperationTask(task.Pass());
97 void SyncableFileSystemOperation::CreateDirectory(
98 const FileSystemURL& url,
101 const StatusCallback& callback) {
102 DCHECK(CalledOnValidThread());
103 if (!operation_runner_.get()) {
104 callback.Run(base::File::FILE_ERROR_NOT_FOUND);
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());
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);
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());
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);
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());
165 void SyncableFileSystemOperation::DirectoryExists(
166 const FileSystemURL& url,
167 const StatusCallback& callback) {
168 DCHECK(CalledOnValidThread());
169 impl_->DirectoryExists(url, callback);
172 void SyncableFileSystemOperation::FileExists(
173 const FileSystemURL& url,
174 const StatusCallback& callback) {
175 DCHECK(CalledOnValidThread());
176 impl_->FileExists(url, callback);
179 void SyncableFileSystemOperation::GetMetadata(
180 const FileSystemURL& url,
181 const GetMetadataCallback& callback) {
182 DCHECK(CalledOnValidThread());
183 impl_->GetMetadata(url, callback);
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);
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);
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()),
212 base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
213 operation_runner_->PostOperationTask(task.Pass());
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);
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()),
234 base::Passed(&writer_delegate),
235 base::Passed(&blob_request),
236 base::Bind(&self::DidWrite, weak_factory_.GetWeakPtr(),
238 operation_runner_->PostOperationTask(task.Pass());
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);
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()),
257 base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
258 operation_runner_->PostOperationTask(task.Pass());
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);
270 void SyncableFileSystemOperation::OpenFile(
271 const FileSystemURL& url,
273 const OpenFileCallback& callback) {
277 void SyncableFileSystemOperation::Cancel(
278 const StatusCallback& cancel_callback) {
279 DCHECK(CalledOnValidThread());
280 impl_->Cancel(cancel_callback);
283 void SyncableFileSystemOperation::CreateSnapshotFile(
284 const FileSystemURL& path,
285 const SnapshotFileCallback& callback) {
286 DCHECK(CalledOnValidThread());
287 impl_->CreateSnapshotFile(path, callback);
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);
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());
311 void SyncableFileSystemOperation::RemoveFile(
312 const FileSystemURL& url,
313 const StatusCallback& callback) {
314 DCHECK(CalledOnValidThread());
315 impl_->RemoveFile(url, callback);
318 void SyncableFileSystemOperation::RemoveDirectory(
319 const FileSystemURL& url,
320 const StatusCallback& callback) {
321 DCHECK(CalledOnValidThread());
322 impl_->RemoveDirectory(url, callback);
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);
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);
344 base::File::Error SyncableFileSystemOperation::SyncGetPlatformPath(
345 const FileSystemURL& url,
346 base::FilePath* platform_path) {
347 return impl_->SyncGetPlatformPath(url, platform_path);
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);
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.
365 impl_.reset(storage::FileSystemOperation::Create(
366 url_, file_system_context, operation_context.Pass()));
367 operation_runner_ = backend->sync_context()->operation_runner();
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);
378 void SyncableFileSystemOperation::DidWrite(
379 const WriteCallback& callback,
380 base::File::Error result,
383 DCHECK(CalledOnValidThread());
385 callback.Run(result, bytes, complete);
388 if (operation_runner_.get())
389 operation_runner_->OnOperationCompleted(target_paths_);
390 callback.Run(result, bytes, complete);
393 void SyncableFileSystemOperation::OnCancelled() {
394 DCHECK(!completion_callback_.is_null());
395 completion_callback_.Run(base::File::FILE_ERROR_ABORT);
398 } // namespace sync_file_system