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/blob/shareable_file_reference.h"
14 #include "storage/browser/fileapi/file_system_context.h"
15 #include "storage/browser/fileapi/file_system_operation.h"
16 #include "storage/browser/fileapi/file_system_operation_context.h"
17 #include "storage/browser/fileapi/file_system_url.h"
18 #include "storage/browser/fileapi/file_writer_delegate.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 ~QueueableTask() override
{ DCHECK(!operation_
); }
48 DCHECK(!task_
.is_null());
53 void Cancel() override
{
54 DCHECK(!task_
.is_null());
56 operation_
->OnCancelled();
61 const std::vector
<FileSystemURL
>& target_paths() const override
{
66 base::WeakPtr
<SyncableFileSystemOperation
> operation_
;
68 std::vector
<FileSystemURL
> target_paths_
;
69 DISALLOW_COPY_AND_ASSIGN(QueueableTask
);
72 SyncableFileSystemOperation::~SyncableFileSystemOperation() {}
74 void SyncableFileSystemOperation::CreateFile(
75 const FileSystemURL
& url
,
77 const StatusCallback
& callback
) {
78 DCHECK(CalledOnValidThread());
79 if (!operation_runner_
.get()) {
80 callback
.Run(base::File::FILE_ERROR_NOT_FOUND
);
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()),
91 base::Bind(&self::DidFinish
, weak_factory_
.GetWeakPtr()))));
92 operation_runner_
->PostOperationTask(task
.Pass());
95 void SyncableFileSystemOperation::CreateDirectory(
96 const FileSystemURL
& url
,
99 const StatusCallback
& callback
) {
100 DCHECK(CalledOnValidThread());
101 if (!operation_runner_
.get()) {
102 callback
.Run(base::File::FILE_ERROR_NOT_FOUND
);
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());
117 void SyncableFileSystemOperation::Copy(
118 const FileSystemURL
& src_url
,
119 const FileSystemURL
& dest_url
,
120 CopyOrMoveOption option
,
121 ErrorBehavior error_behavior
,
122 const CopyProgressCallback
& progress_callback
,
123 const StatusCallback
& callback
) {
124 DCHECK(CalledOnValidThread());
125 if (!operation_runner_
.get()) {
126 callback
.Run(base::File::FILE_ERROR_NOT_FOUND
);
129 DCHECK(operation_runner_
.get());
130 target_paths_
.push_back(dest_url
);
131 completion_callback_
= callback
;
132 scoped_ptr
<SyncableFileOperationRunner::Task
> task(new QueueableTask(
133 weak_factory_
.GetWeakPtr(),
134 base::Bind(&FileSystemOperation::Copy
, base::Unretained(impl_
.get()),
135 src_url
, dest_url
, option
, error_behavior
, progress_callback
,
136 base::Bind(&self::DidFinish
, weak_factory_
.GetWeakPtr()))));
137 operation_runner_
->PostOperationTask(task
.Pass());
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
);
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());
163 void SyncableFileSystemOperation::DirectoryExists(
164 const FileSystemURL
& url
,
165 const StatusCallback
& callback
) {
166 DCHECK(CalledOnValidThread());
167 impl_
->DirectoryExists(url
, callback
);
170 void SyncableFileSystemOperation::FileExists(
171 const FileSystemURL
& url
,
172 const StatusCallback
& callback
) {
173 DCHECK(CalledOnValidThread());
174 impl_
->FileExists(url
, callback
);
177 void SyncableFileSystemOperation::GetMetadata(
178 const FileSystemURL
& url
,
179 const GetMetadataCallback
& callback
) {
180 DCHECK(CalledOnValidThread());
181 impl_
->GetMetadata(url
, callback
);
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
);
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
);
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()),
210 base::Bind(&self::DidFinish
, weak_factory_
.GetWeakPtr()))));
211 operation_runner_
->PostOperationTask(task
.Pass());
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);
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()),
232 base::Passed(&writer_delegate
),
233 base::Passed(&blob_request
),
234 base::Bind(&self::DidWrite
, weak_factory_
.GetWeakPtr(),
236 operation_runner_
->PostOperationTask(task
.Pass());
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
);
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()),
255 base::Bind(&self::DidFinish
, weak_factory_
.GetWeakPtr()))));
256 operation_runner_
->PostOperationTask(task
.Pass());
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
);
268 void SyncableFileSystemOperation::OpenFile(
269 const FileSystemURL
& url
,
271 const OpenFileCallback
& callback
) {
275 void SyncableFileSystemOperation::Cancel(
276 const StatusCallback
& cancel_callback
) {
277 DCHECK(CalledOnValidThread());
278 impl_
->Cancel(cancel_callback
);
281 void SyncableFileSystemOperation::CreateSnapshotFile(
282 const FileSystemURL
& path
,
283 const SnapshotFileCallback
& callback
) {
284 DCHECK(CalledOnValidThread());
285 impl_
->CreateSnapshotFile(path
, callback
);
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
);
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());
309 void SyncableFileSystemOperation::RemoveFile(
310 const FileSystemURL
& url
,
311 const StatusCallback
& callback
) {
312 DCHECK(CalledOnValidThread());
313 impl_
->RemoveFile(url
, callback
);
316 void SyncableFileSystemOperation::RemoveDirectory(
317 const FileSystemURL
& url
,
318 const StatusCallback
& callback
) {
319 DCHECK(CalledOnValidThread());
320 impl_
->RemoveDirectory(url
, callback
);
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
);
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
);
342 base::File::Error
SyncableFileSystemOperation::SyncGetPlatformPath(
343 const FileSystemURL
& url
,
344 base::FilePath
* platform_path
) {
345 return impl_
->SyncGetPlatformPath(url
, platform_path
);
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
);
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.
363 impl_
.reset(storage::FileSystemOperation::Create(
364 url_
, file_system_context
, operation_context
.Pass()));
365 operation_runner_
= backend
->sync_context()->operation_runner();
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
);
376 void SyncableFileSystemOperation::DidWrite(
377 const WriteCallback
& callback
,
378 base::File::Error result
,
381 DCHECK(CalledOnValidThread());
383 callback
.Run(result
, bytes
, complete
);
386 if (operation_runner_
.get())
387 operation_runner_
->OnOperationCompleted(target_paths_
);
388 callback
.Run(result
, bytes
, complete
);
391 void SyncableFileSystemOperation::OnCancelled() {
392 DCHECK(!completion_callback_
.is_null());
393 completion_callback_
.Run(base::File::FILE_ERROR_ABORT
);
396 } // namespace sync_file_system