Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / sync_file_system / local / syncable_file_system_operation.cc
blob51a3cbf94e666732ca3b1037688941159acb7847
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 "webkit/browser/fileapi/file_system_context.h"
14 #include "webkit/browser/fileapi/file_system_operation.h"
15 #include "webkit/browser/fileapi/file_system_operation_context.h"
16 #include "webkit/browser/fileapi/file_system_url.h"
17 #include "webkit/browser/fileapi/file_writer_delegate.h"
18 #include "webkit/common/blob/shareable_file_reference.h"
20 using fileapi::FileSystemURL;
22 namespace sync_file_system {
24 namespace {
26 void WriteCallbackAdapter(
27 const SyncableFileSystemOperation::WriteCallback& callback,
28 base::PlatformFileError status) {
29 callback.Run(status, 0, true);
32 } // namespace
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_) {}
43 virtual ~QueueableTask() {
44 DCHECK(!operation_);
47 virtual void Run() OVERRIDE {
48 if (!operation_)
49 return;
50 DCHECK(!task_.is_null());
51 task_.Run();
52 operation_.reset();
55 virtual void Cancel() OVERRIDE {
56 DCHECK(!task_.is_null());
57 if (operation_)
58 operation_->OnCancelled();
59 task_.Reset();
60 operation_.reset();
63 virtual const std::vector<FileSystemURL>& target_paths() const OVERRIDE {
64 return target_paths_;
67 private:
68 base::WeakPtr<SyncableFileSystemOperation> operation_;
69 base::Closure task_;
70 std::vector<FileSystemURL> target_paths_;
71 DISALLOW_COPY_AND_ASSIGN(QueueableTask);
74 SyncableFileSystemOperation::~SyncableFileSystemOperation() {}
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::PLATFORM_FILE_ERROR_NOT_FOUND);
83 return;
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());
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::PLATFORM_FILE_ERROR_NOT_FOUND);
105 return;
107 if (!is_directory_operation_enabled_) {
108 callback.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION);
109 return;
111 DCHECK(operation_runner_.get());
112 target_paths_.push_back(url);
113 completion_callback_ = callback;
114 scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
115 weak_factory_.GetWeakPtr(),
116 base::Bind(&FileSystemOperation::CreateDirectory,
117 base::Unretained(impl_.get()),
118 url, exclusive, recursive,
119 base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
120 operation_runner_->PostOperationTask(task.Pass());
123 void SyncableFileSystemOperation::Copy(
124 const FileSystemURL& src_url,
125 const FileSystemURL& dest_url,
126 CopyOrMoveOption option,
127 const CopyProgressCallback& progress_callback,
128 const StatusCallback& callback) {
129 DCHECK(CalledOnValidThread());
130 if (!operation_runner_.get()) {
131 callback.Run(base::PLATFORM_FILE_ERROR_NOT_FOUND);
132 return;
134 DCHECK(operation_runner_.get());
135 target_paths_.push_back(dest_url);
136 completion_callback_ = callback;
137 scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
138 weak_factory_.GetWeakPtr(),
139 base::Bind(&FileSystemOperation::Copy,
140 base::Unretained(impl_.get()),
141 src_url, dest_url, option, progress_callback,
142 base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
143 operation_runner_->PostOperationTask(task.Pass());
146 void SyncableFileSystemOperation::Move(
147 const FileSystemURL& src_url,
148 const FileSystemURL& dest_url,
149 CopyOrMoveOption option,
150 const StatusCallback& callback) {
151 DCHECK(CalledOnValidThread());
152 if (!operation_runner_.get()) {
153 callback.Run(base::PLATFORM_FILE_ERROR_NOT_FOUND);
154 return;
156 DCHECK(operation_runner_.get());
157 target_paths_.push_back(src_url);
158 target_paths_.push_back(dest_url);
159 completion_callback_ = callback;
160 scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
161 weak_factory_.GetWeakPtr(),
162 base::Bind(&FileSystemOperation::Move,
163 base::Unretained(impl_.get()),
164 src_url, dest_url, option,
165 base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
166 operation_runner_->PostOperationTask(task.Pass());
169 void SyncableFileSystemOperation::DirectoryExists(
170 const FileSystemURL& url,
171 const StatusCallback& callback) {
172 DCHECK(CalledOnValidThread());
173 impl_->DirectoryExists(url, callback);
176 void SyncableFileSystemOperation::FileExists(
177 const FileSystemURL& url,
178 const StatusCallback& callback) {
179 DCHECK(CalledOnValidThread());
180 impl_->FileExists(url, callback);
183 void SyncableFileSystemOperation::GetMetadata(
184 const FileSystemURL& url,
185 const GetMetadataCallback& callback) {
186 DCHECK(CalledOnValidThread());
187 impl_->GetMetadata(url, callback);
190 void SyncableFileSystemOperation::ReadDirectory(
191 const FileSystemURL& url,
192 const ReadDirectoryCallback& callback) {
193 DCHECK(CalledOnValidThread());
194 // This is a read operation and there'd be no hard to let it go even if
195 // directory operation is disabled. (And we should allow this if it's made
196 // on the root directory)
197 impl_->ReadDirectory(url, callback);
200 void SyncableFileSystemOperation::Remove(
201 const FileSystemURL& url, bool recursive,
202 const StatusCallback& callback) {
203 DCHECK(CalledOnValidThread());
204 if (!operation_runner_.get()) {
205 callback.Run(base::PLATFORM_FILE_ERROR_NOT_FOUND);
206 return;
208 DCHECK(operation_runner_.get());
209 target_paths_.push_back(url);
210 completion_callback_ = callback;
211 scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
212 weak_factory_.GetWeakPtr(),
213 base::Bind(&FileSystemOperation::Remove,
214 base::Unretained(impl_.get()),
215 url, recursive,
216 base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
217 operation_runner_->PostOperationTask(task.Pass());
220 void SyncableFileSystemOperation::Write(
221 const FileSystemURL& url,
222 scoped_ptr<fileapi::FileWriterDelegate> writer_delegate,
223 scoped_ptr<net::URLRequest> blob_request,
224 const WriteCallback& callback) {
225 DCHECK(CalledOnValidThread());
226 if (!operation_runner_.get()) {
227 callback.Run(base::PLATFORM_FILE_ERROR_NOT_FOUND, 0, true);
228 return;
230 DCHECK(operation_runner_.get());
231 target_paths_.push_back(url);
232 completion_callback_ = base::Bind(&WriteCallbackAdapter, callback);
233 scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
234 weak_factory_.GetWeakPtr(),
235 base::Bind(&FileSystemOperation::Write,
236 base::Unretained(impl_.get()),
237 url,
238 base::Passed(&writer_delegate),
239 base::Passed(&blob_request),
240 base::Bind(&self::DidWrite, weak_factory_.GetWeakPtr(),
241 callback))));
242 operation_runner_->PostOperationTask(task.Pass());
245 void SyncableFileSystemOperation::Truncate(
246 const FileSystemURL& url, int64 length,
247 const StatusCallback& callback) {
248 DCHECK(CalledOnValidThread());
249 if (!operation_runner_.get()) {
250 callback.Run(base::PLATFORM_FILE_ERROR_NOT_FOUND);
251 return;
253 DCHECK(operation_runner_.get());
254 target_paths_.push_back(url);
255 completion_callback_ = callback;
256 scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
257 weak_factory_.GetWeakPtr(),
258 base::Bind(&FileSystemOperation::Truncate,
259 base::Unretained(impl_.get()),
260 url, length,
261 base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
262 operation_runner_->PostOperationTask(task.Pass());
265 void SyncableFileSystemOperation::TouchFile(
266 const FileSystemURL& url,
267 const base::Time& last_access_time,
268 const base::Time& last_modified_time,
269 const StatusCallback& callback) {
270 DCHECK(CalledOnValidThread());
271 impl_->TouchFile(url, last_access_time, last_modified_time, callback);
274 void SyncableFileSystemOperation::OpenFile(
275 const FileSystemURL& url,
276 int file_flags,
277 const OpenFileCallback& callback) {
278 NOTREACHED();
281 void SyncableFileSystemOperation::Cancel(
282 const StatusCallback& cancel_callback) {
283 DCHECK(CalledOnValidThread());
284 impl_->Cancel(cancel_callback);
287 void SyncableFileSystemOperation::CreateSnapshotFile(
288 const FileSystemURL& path,
289 const SnapshotFileCallback& callback) {
290 DCHECK(CalledOnValidThread());
291 impl_->CreateSnapshotFile(path, callback);
294 void SyncableFileSystemOperation::CopyInForeignFile(
295 const base::FilePath& src_local_disk_path,
296 const FileSystemURL& dest_url,
297 const StatusCallback& callback) {
298 DCHECK(CalledOnValidThread());
299 if (!operation_runner_.get()) {
300 callback.Run(base::PLATFORM_FILE_ERROR_NOT_FOUND);
301 return;
303 DCHECK(operation_runner_.get());
304 target_paths_.push_back(dest_url);
305 completion_callback_ = callback;
306 scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
307 weak_factory_.GetWeakPtr(),
308 base::Bind(&FileSystemOperation::CopyInForeignFile,
309 base::Unretained(impl_.get()),
310 src_local_disk_path, dest_url,
311 base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
312 operation_runner_->PostOperationTask(task.Pass());
315 void SyncableFileSystemOperation::RemoveFile(
316 const FileSystemURL& url,
317 const StatusCallback& callback) {
318 DCHECK(CalledOnValidThread());
319 impl_->RemoveFile(url, callback);
322 void SyncableFileSystemOperation::RemoveDirectory(
323 const FileSystemURL& url,
324 const StatusCallback& callback) {
325 DCHECK(CalledOnValidThread());
326 impl_->RemoveDirectory(url, callback);
329 void SyncableFileSystemOperation::CopyFileLocal(
330 const FileSystemURL& src_url,
331 const FileSystemURL& dest_url,
332 CopyOrMoveOption option,
333 const CopyFileProgressCallback& progress_callback,
334 const StatusCallback& callback) {
335 DCHECK(CalledOnValidThread());
336 impl_->CopyFileLocal(src_url, dest_url, option, progress_callback, callback);
339 void SyncableFileSystemOperation::MoveFileLocal(
340 const FileSystemURL& src_url,
341 const FileSystemURL& dest_url,
342 CopyOrMoveOption option,
343 const StatusCallback& callback) {
344 DCHECK(CalledOnValidThread());
345 impl_->MoveFileLocal(src_url, dest_url, option, callback);
348 base::PlatformFileError SyncableFileSystemOperation::SyncGetPlatformPath(
349 const FileSystemURL& url,
350 base::FilePath* platform_path) {
351 return impl_->SyncGetPlatformPath(url, platform_path);
354 SyncableFileSystemOperation::SyncableFileSystemOperation(
355 const FileSystemURL& url,
356 fileapi::FileSystemContext* file_system_context,
357 scoped_ptr<fileapi::FileSystemOperationContext> operation_context)
358 : url_(url),
359 weak_factory_(this) {
360 DCHECK(file_system_context);
361 SyncFileSystemBackend* backend =
362 SyncFileSystemBackend::GetBackend(file_system_context);
363 DCHECK(backend);
364 if (!backend->sync_context()) {
365 // Syncable FileSystem is opened in a file system context which doesn't
366 // support (or is not initialized for) the API.
367 // Returning here to leave operation_runner_ as NULL.
368 return;
370 impl_.reset(fileapi::FileSystemOperation::Create(
371 url_, file_system_context, operation_context.Pass()));
372 operation_runner_ = backend->sync_context()->operation_runner();
373 is_directory_operation_enabled_ = IsSyncFSDirectoryOperationEnabled(
374 url.origin());
377 void SyncableFileSystemOperation::DidFinish(base::PlatformFileError status) {
378 DCHECK(CalledOnValidThread());
379 DCHECK(!completion_callback_.is_null());
380 if (operation_runner_.get())
381 operation_runner_->OnOperationCompleted(target_paths_);
382 completion_callback_.Run(status);
385 void SyncableFileSystemOperation::DidWrite(
386 const WriteCallback& callback,
387 base::PlatformFileError result,
388 int64 bytes,
389 bool complete) {
390 DCHECK(CalledOnValidThread());
391 if (!complete) {
392 callback.Run(result, bytes, complete);
393 return;
395 if (operation_runner_.get())
396 operation_runner_->OnOperationCompleted(target_paths_);
397 callback.Run(result, bytes, complete);
400 void SyncableFileSystemOperation::OnCancelled() {
401 DCHECK(!completion_callback_.is_null());
402 completion_callback_.Run(base::PLATFORM_FILE_ERROR_ABORT);
405 } // namespace sync_file_system