Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / sync_file_system / local / syncable_file_system_operation.cc
bloba5eebe7a9d1af3df2d87b46e7ed9dda7606ba416
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 {
24 namespace {
26 void WriteCallbackAdapter(
27 const SyncableFileSystemOperation::WriteCallback& callback,
28 base::File::Error 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 ~QueueableTask() override { DCHECK(!operation_); }
45 void Run() override {
46 if (!operation_)
47 return;
48 DCHECK(!task_.is_null());
49 task_.Run();
50 operation_.reset();
53 void Cancel() override {
54 DCHECK(!task_.is_null());
55 if (operation_)
56 operation_->OnCancelled();
57 task_.Reset();
58 operation_.reset();
61 const std::vector<FileSystemURL>& target_paths() const override {
62 return target_paths_;
65 private:
66 base::WeakPtr<SyncableFileSystemOperation> operation_;
67 base::Closure task_;
68 std::vector<FileSystemURL> target_paths_;
69 DISALLOW_COPY_AND_ASSIGN(QueueableTask);
72 SyncableFileSystemOperation::~SyncableFileSystemOperation() {}
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;
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());
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;
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);
127 return;
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);
148 return;
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);
200 return;
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());
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;
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());
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;
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());
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,
270 int file_flags,
271 const OpenFileCallback& callback) {
272 NOTREACHED();
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);
295 return;
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);
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;
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,
379 int64 bytes,
380 bool complete) {
381 DCHECK(CalledOnValidThread());
382 if (!complete) {
383 callback.Run(result, bytes, complete);
384 return;
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