Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(286)

Side by Side Diff: webkit/fileapi/local_file_system_operation.cc

Issue 14895013: Move webkit/fileapi/file_system_mount_point_provider.h to webkit/browser/fileapi (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 "webkit/fileapi/local_file_system_operation.h"
6
7 #include "base/bind.h"
8 #include "base/single_thread_task_runner.h"
9 #include "base/time.h"
10 #include "base/utf_string_conversions.h"
11 #include "net/base/escape.h"
12 #include "net/url_request/url_request_context.h"
13 #include "webkit/blob/shareable_file_reference.h"
14 #include "webkit/fileapi/async_file_util.h"
15 #include "webkit/fileapi/cross_operation_delegate.h"
16 #include "webkit/fileapi/file_observers.h"
17 #include "webkit/fileapi/file_system_context.h"
18 #include "webkit/fileapi/file_system_file_util.h"
19 #include "webkit/fileapi/file_system_mount_point_provider.h"
20 #include "webkit/fileapi/file_system_operation_context.h"
21 #include "webkit/fileapi/file_system_task_runners.h"
22 #include "webkit/fileapi/file_system_types.h"
23 #include "webkit/fileapi/file_system_url.h"
24 #include "webkit/fileapi/file_system_util.h"
25 #include "webkit/fileapi/file_writer_delegate.h"
26 #include "webkit/fileapi/remove_operation_delegate.h"
27 #include "webkit/fileapi/sandbox_file_stream_writer.h"
28 #include "webkit/quota/quota_manager.h"
29 #include "webkit/quota/quota_types.h"
30
31 using webkit_blob::ScopedFile;
32 using webkit_blob::ShareableFileReference;
33
34 namespace fileapi {
35
36 namespace {
37 void NopCloseFileCallback() {}
38 }
39
40 LocalFileSystemOperation::LocalFileSystemOperation(
41 FileSystemContext* file_system_context,
42 scoped_ptr<FileSystemOperationContext> operation_context)
43 : file_system_context_(file_system_context),
44 operation_context_(operation_context.Pass()),
45 async_file_util_(NULL),
46 peer_handle_(base::kNullProcessHandle),
47 pending_operation_(kOperationNone),
48 weak_factory_(this) {
49 DCHECK(operation_context_.get());
50 operation_context_->DetachUserDataThread();
51 }
52
53 LocalFileSystemOperation::~LocalFileSystemOperation() {
54 if (!operation_context())
55 return;
56 operation_context()->DetachUserDataThread();
57 if (write_target_url_.is_valid()) {
58 operation_context()->update_observers()->Notify(
59 &FileUpdateObserver::OnEndUpdate, MakeTuple(write_target_url_));
60 }
61 }
62
63 void LocalFileSystemOperation::CreateFile(const FileSystemURL& url,
64 bool exclusive,
65 const StatusCallback& callback) {
66 DCHECK(SetPendingOperationType(kOperationCreateFile));
67
68 base::PlatformFileError result = SetUp(url, OPERATION_MODE_WRITE);
69 if (result != base::PLATFORM_FILE_OK) {
70 callback.Run(result);
71 delete this;
72 return;
73 }
74
75 GetUsageAndQuotaThenRunTask(
76 url,
77 base::Bind(&LocalFileSystemOperation::DoCreateFile,
78 base::Unretained(this), url, callback, exclusive),
79 base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED));
80 }
81
82 void LocalFileSystemOperation::CreateDirectory(const FileSystemURL& url,
83 bool exclusive,
84 bool recursive,
85 const StatusCallback& callback) {
86 DCHECK(SetPendingOperationType(kOperationCreateDirectory));
87
88 base::PlatformFileError result = SetUp(url, OPERATION_MODE_WRITE);
89 if (result != base::PLATFORM_FILE_OK) {
90 callback.Run(result);
91 delete this;
92 return;
93 }
94 GetUsageAndQuotaThenRunTask(
95 url,
96 base::Bind(&LocalFileSystemOperation::DoCreateDirectory,
97 base::Unretained(this), url, callback, exclusive, recursive),
98 base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED));
99 }
100
101 void LocalFileSystemOperation::Copy(const FileSystemURL& src_url,
102 const FileSystemURL& dest_url,
103 const StatusCallback& callback) {
104 DCHECK(SetPendingOperationType(kOperationCopy));
105 scoped_ptr<LocalFileSystemOperation> deleter(this);
106
107 // Setting up this (dest) operation.
108 base::PlatformFileError result = SetUp(dest_url, OPERATION_MODE_WRITE);
109 if (result != base::PLATFORM_FILE_OK) {
110 callback.Run(result);
111 return;
112 }
113
114 // Setting up a new operation for source.
115 FileSystemOperation* operation =
116 file_system_context()->CreateFileSystemOperation(src_url, &result);
117 if (result != base::PLATFORM_FILE_OK) {
118 callback.Run(result);
119 return;
120 }
121 scoped_ptr<LocalFileSystemOperation> src_operation(
122 operation->AsLocalFileSystemOperation());
123 DCHECK(src_operation);
124 result = src_operation->SetUp(src_url, OPERATION_MODE_READ);
125 if (result != base::PLATFORM_FILE_OK) {
126 callback.Run(result);
127 return;
128 }
129
130 DCHECK(!recursive_operation_delegate_);
131 recursive_operation_delegate_.reset(
132 new CrossOperationDelegate(
133 file_system_context(),
134 src_operation.Pass(),
135 deleter.release(),
136 src_url, dest_url,
137 CrossOperationDelegate::OPERATION_COPY,
138 base::Bind(&LocalFileSystemOperation::DidFinishDelegatedOperation,
139 base::Unretained(this), callback)));
140 recursive_operation_delegate_->RunRecursively();
141 }
142
143 void LocalFileSystemOperation::Move(const FileSystemURL& src_url,
144 const FileSystemURL& dest_url,
145 const StatusCallback& callback) {
146 DCHECK(SetPendingOperationType(kOperationMove));
147 scoped_ptr<LocalFileSystemOperation> deleter(this);
148
149 // Setting up this (dest) operation.
150 base::PlatformFileError result = SetUp(dest_url, OPERATION_MODE_WRITE);
151 if (result != base::PLATFORM_FILE_OK) {
152 callback.Run(result);
153 return;
154 }
155
156 // Setting up a new operation for source.
157 base::PlatformFileError error = base::PLATFORM_FILE_OK;
158 FileSystemOperation* operation =
159 file_system_context()->CreateFileSystemOperation(src_url, &error);
160 if (error != base::PLATFORM_FILE_OK) {
161 DCHECK(!operation);
162 callback.Run(error);
163 return;
164 }
165 scoped_ptr<LocalFileSystemOperation> src_operation(
166 operation->AsLocalFileSystemOperation());
167 DCHECK(src_operation);
168 result = src_operation->SetUp(src_url, OPERATION_MODE_WRITE);
169 if (result != base::PLATFORM_FILE_OK) {
170 callback.Run(result);
171 return;
172 }
173
174 DCHECK(!recursive_operation_delegate_);
175 recursive_operation_delegate_.reset(
176 new CrossOperationDelegate(
177 file_system_context(),
178 src_operation.Pass(),
179 deleter.release(),
180 src_url, dest_url,
181 CrossOperationDelegate::OPERATION_MOVE,
182 base::Bind(&LocalFileSystemOperation::DidFinishDelegatedOperation,
183 base::Unretained(this), callback)));
184 recursive_operation_delegate_->RunRecursively();
185 }
186
187 void LocalFileSystemOperation::DirectoryExists(const FileSystemURL& url,
188 const StatusCallback& callback) {
189 DCHECK(SetPendingOperationType(kOperationDirectoryExists));
190
191 base::PlatformFileError result = SetUp(url, OPERATION_MODE_READ);
192 if (result != base::PLATFORM_FILE_OK) {
193 callback.Run(result);
194 delete this;
195 return;
196 }
197
198 async_file_util_->GetFileInfo(
199 operation_context(), url,
200 base::Bind(&LocalFileSystemOperation::DidDirectoryExists,
201 base::Owned(this), callback));
202 }
203
204 void LocalFileSystemOperation::FileExists(const FileSystemURL& url,
205 const StatusCallback& callback) {
206 DCHECK(SetPendingOperationType(kOperationFileExists));
207
208 base::PlatformFileError result = SetUp(url, OPERATION_MODE_READ);
209 if (result != base::PLATFORM_FILE_OK) {
210 callback.Run(result);
211 delete this;
212 return;
213 }
214
215 async_file_util_->GetFileInfo(
216 operation_context(), url,
217 base::Bind(&LocalFileSystemOperation::DidFileExists,
218 base::Owned(this), callback));
219 }
220
221 void LocalFileSystemOperation::GetMetadata(
222 const FileSystemURL& url, const GetMetadataCallback& callback) {
223 DCHECK(SetPendingOperationType(kOperationGetMetadata));
224
225 base::PlatformFileError result = SetUp(url, OPERATION_MODE_READ);
226 if (result != base::PLATFORM_FILE_OK) {
227 callback.Run(result, base::PlatformFileInfo(), base::FilePath());
228 delete this;
229 return;
230 }
231
232 async_file_util_->GetFileInfo(
233 operation_context(), url,
234 base::Bind(&LocalFileSystemOperation::DidGetMetadata,
235 base::Owned(this), callback));
236 }
237
238 void LocalFileSystemOperation::ReadDirectory(
239 const FileSystemURL& url, const ReadDirectoryCallback& callback) {
240 DCHECK(SetPendingOperationType(kOperationReadDirectory));
241
242 base::PlatformFileError result = SetUp(url, OPERATION_MODE_READ);
243 if (result != base::PLATFORM_FILE_OK) {
244 callback.Run(result, std::vector<base::FileUtilProxy::Entry>(), false);
245 delete this;
246 return;
247 }
248
249 async_file_util_->ReadDirectory(
250 operation_context(), url,
251 base::Bind(&LocalFileSystemOperation::DidReadDirectory,
252 base::Owned(this), callback));
253 }
254
255 void LocalFileSystemOperation::Remove(const FileSystemURL& url,
256 bool recursive,
257 const StatusCallback& callback) {
258 DCHECK(SetPendingOperationType(kOperationRemove));
259
260 base::PlatformFileError result = SetUp(url, OPERATION_MODE_WRITE);
261 if (result != base::PLATFORM_FILE_OK) {
262 callback.Run(result);
263 delete this;
264 return;
265 }
266
267 DCHECK(!recursive_operation_delegate_);
268 recursive_operation_delegate_.reset(
269 new RemoveOperationDelegate(
270 file_system_context(),
271 this, url,
272 base::Bind(&LocalFileSystemOperation::DidFinishDelegatedOperation,
273 base::Unretained(this), callback)));
274 if (recursive)
275 recursive_operation_delegate_->RunRecursively();
276 else
277 recursive_operation_delegate_->Run();
278 }
279
280 void LocalFileSystemOperation::Write(
281 const net::URLRequestContext* url_request_context,
282 const FileSystemURL& url,
283 const GURL& blob_url,
284 int64 offset,
285 const WriteCallback& callback) {
286 GetWriteClosure(url_request_context, url, blob_url, offset, callback).Run();
287 }
288
289 void LocalFileSystemOperation::Truncate(const FileSystemURL& url, int64 length,
290 const StatusCallback& callback) {
291 DCHECK(SetPendingOperationType(kOperationTruncate));
292
293 base::PlatformFileError result = SetUp(url, OPERATION_MODE_WRITE);
294 if (result != base::PLATFORM_FILE_OK) {
295 callback.Run(result);
296 delete this;
297 return;
298 }
299 GetUsageAndQuotaThenRunTask(
300 url,
301 base::Bind(&LocalFileSystemOperation::DoTruncate,
302 base::Unretained(this), url, callback, length),
303 base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED));
304 }
305
306 void LocalFileSystemOperation::TouchFile(const FileSystemURL& url,
307 const base::Time& last_access_time,
308 const base::Time& last_modified_time,
309 const StatusCallback& callback) {
310 DCHECK(SetPendingOperationType(kOperationTouchFile));
311
312 base::PlatformFileError result = SetUp(url, OPERATION_MODE_WRITE);
313 if (result != base::PLATFORM_FILE_OK) {
314 callback.Run(result);
315 delete this;
316 return;
317 }
318
319 async_file_util_->Touch(
320 operation_context(), url,
321 last_access_time, last_modified_time,
322 base::Bind(&LocalFileSystemOperation::DidTouchFile,
323 base::Owned(this), callback));
324 }
325
326 void LocalFileSystemOperation::OpenFile(const FileSystemURL& url,
327 int file_flags,
328 base::ProcessHandle peer_handle,
329 const OpenFileCallback& callback) {
330 DCHECK(SetPendingOperationType(kOperationOpenFile));
331 scoped_ptr<LocalFileSystemOperation> deleter(this);
332
333 peer_handle_ = peer_handle;
334
335 if (file_flags & (
336 (base::PLATFORM_FILE_ENUMERATE | base::PLATFORM_FILE_TEMPORARY |
337 base::PLATFORM_FILE_HIDDEN))) {
338 callback.Run(base::PLATFORM_FILE_ERROR_FAILED,
339 base::kInvalidPlatformFileValue,
340 base::Closure(),
341 base::kNullProcessHandle);
342 return;
343 }
344 if (file_flags &
345 (base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_OPEN_ALWAYS |
346 base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_OPEN_TRUNCATED |
347 base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_EXCLUSIVE_WRITE |
348 base::PLATFORM_FILE_DELETE_ON_CLOSE |
349 base::PLATFORM_FILE_WRITE_ATTRIBUTES)) {
350 base::PlatformFileError result = SetUp(url, OPERATION_MODE_WRITE);
351 if (result != base::PLATFORM_FILE_OK) {
352 callback.Run(result,
353 base::kInvalidPlatformFileValue,
354 base::Closure(),
355 base::kNullProcessHandle);
356 return;
357 }
358 } else {
359 base::PlatformFileError result = SetUp(url, OPERATION_MODE_READ);
360 if (result != base::PLATFORM_FILE_OK) {
361 callback.Run(result,
362 base::kInvalidPlatformFileValue,
363 base::Closure(),
364 base::kNullProcessHandle);
365 return;
366 }
367 }
368 GetUsageAndQuotaThenRunTask(
369 url,
370 base::Bind(&LocalFileSystemOperation::DoOpenFile,
371 base::Unretained(deleter.release()),
372 url, callback, file_flags),
373 base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED,
374 base::kInvalidPlatformFileValue,
375 base::Closure(),
376 base::kNullProcessHandle));
377 }
378
379 // We can only get here on a write or truncate that's not yet completed.
380 // We don't support cancelling any other operation at this time.
381 void LocalFileSystemOperation::Cancel(const StatusCallback& cancel_callback) {
382 if (file_writer_delegate_) {
383 DCHECK_EQ(kOperationWrite, pending_operation_);
384
385 // Writes are done without proxying through FileUtilProxy after the initial
386 // opening of the PlatformFile. All state changes are done on this thread,
387 // so we're guaranteed to be able to shut down atomically.
388 const bool delete_now = file_writer_delegate_->Cancel();
389
390 if (!write_callback_.is_null()) {
391 // Notify the failure status to the ongoing operation's callback.
392 write_callback_.Run(base::PLATFORM_FILE_ERROR_ABORT, 0, false);
393 }
394 cancel_callback.Run(base::PLATFORM_FILE_OK);
395 write_callback_.Reset();
396
397 if (delete_now) {
398 delete this;
399 return;
400 }
401 } else {
402 DCHECK_EQ(kOperationTruncate, pending_operation_);
403 // We're cancelling a truncate operation, but we can't actually stop it
404 // since it's been proxied to another thread. We need to save the
405 // cancel_callback so that when the truncate returns, it can see that it's
406 // been cancelled, report it, and report that the cancel has succeeded.
407 DCHECK(cancel_callback_.is_null());
408 cancel_callback_ = cancel_callback;
409 }
410 }
411
412 LocalFileSystemOperation*
413 LocalFileSystemOperation::AsLocalFileSystemOperation() {
414 return this;
415 }
416
417 void LocalFileSystemOperation::SyncGetPlatformPath(const FileSystemURL& url,
418 base::FilePath* platform_path ) {
419 DCHECK(SetPendingOperationType(kOperationGetLocalPath));
420
421 base::PlatformFileError result = SetUp(url, OPERATION_MODE_READ);
422 if (result != base::PLATFORM_FILE_OK) {
423 delete this;
424 return;
425 }
426
427 FileSystemFileUtil* file_util = file_system_context()->GetFileUtil(
428 url.type());
429 DCHECK(file_util);
430 file_util->GetLocalFilePath(operation_context(), url, platform_path);
431
432 delete this;
433 }
434
435 void LocalFileSystemOperation::CreateSnapshotFile(
436 const FileSystemURL& url,
437 const SnapshotFileCallback& callback) {
438 DCHECK(SetPendingOperationType(kOperationCreateSnapshotFile));
439
440 base::PlatformFileError result = SetUp(url, OPERATION_MODE_READ);
441 if (result != base::PLATFORM_FILE_OK) {
442 callback.Run(result, base::PlatformFileInfo(), base::FilePath(), NULL);
443 delete this;
444 return;
445 }
446
447 async_file_util_->CreateSnapshotFile(
448 operation_context(), url,
449 base::Bind(&LocalFileSystemOperation::DidCreateSnapshotFile,
450 base::Owned(this), callback));
451 }
452
453 LocalFileSystemOperation* LocalFileSystemOperation::CreateNestedOperation() {
454 LocalFileSystemOperation* operation = new LocalFileSystemOperation(
455 file_system_context(),
456 make_scoped_ptr(new FileSystemOperationContext(file_system_context())));
457 operation->parent_operation_ = weak_factory_.GetWeakPtr();
458 return operation;
459 }
460
461 void LocalFileSystemOperation::CopyInForeignFile(
462 const base::FilePath& src_local_disk_file_path,
463 const FileSystemURL& dest_url,
464 const StatusCallback& callback) {
465 DCHECK(SetPendingOperationType(kOperationCopyInForeignFile));
466
467 base::PlatformFileError result = SetUp(dest_url, OPERATION_MODE_WRITE);
468 if (result != base::PLATFORM_FILE_OK) {
469 callback.Run(result);
470 delete this;
471 return;
472 }
473
474 GetUsageAndQuotaThenRunTask(
475 dest_url,
476 base::Bind(&LocalFileSystemOperation::DoCopyInForeignFile,
477 base::Unretained(this), src_local_disk_file_path, dest_url,
478 callback),
479 base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED));
480 }
481
482 void LocalFileSystemOperation::RemoveFile(
483 const FileSystemURL& url,
484 const StatusCallback& callback) {
485 DCHECK(SetPendingOperationType(kOperationRemove));
486 base::PlatformFileError result = SetUp(url, OPERATION_MODE_WRITE);
487 if (result != base::PLATFORM_FILE_OK) {
488 callback.Run(result);
489 delete this;
490 return;
491 }
492
493 async_file_util_->DeleteFile(
494 operation_context(), url,
495 base::Bind(&LocalFileSystemOperation::DidFinishFileOperation,
496 base::Owned(this), callback));
497 }
498
499 void LocalFileSystemOperation::RemoveDirectory(
500 const FileSystemURL& url,
501 const StatusCallback& callback) {
502 DCHECK(SetPendingOperationType(kOperationRemove));
503 base::PlatformFileError result = SetUp(url, OPERATION_MODE_WRITE);
504 if (result != base::PLATFORM_FILE_OK) {
505 callback.Run(result);
506 delete this;
507 return;
508 }
509
510 async_file_util_->DeleteDirectory(
511 operation_context(), url,
512 base::Bind(&LocalFileSystemOperation::DidFinishFileOperation,
513 base::Owned(this), callback));
514 }
515
516 void LocalFileSystemOperation::CopyFileLocal(
517 const FileSystemURL& src_url,
518 const FileSystemURL& dest_url,
519 const StatusCallback& callback) {
520 DCHECK(SetPendingOperationType(kOperationCopy));
521 DCHECK(AreSameFileSystem(src_url, dest_url));
522
523 base::PlatformFileError result = SetUp(src_url, OPERATION_MODE_READ);
524 if (result == base::PLATFORM_FILE_OK)
525 result = SetUp(dest_url, OPERATION_MODE_WRITE);
526 if (result != base::PLATFORM_FILE_OK) {
527 callback.Run(result);
528 delete this;
529 return;
530 }
531
532 GetUsageAndQuotaThenRunTask(
533 dest_url,
534 base::Bind(&LocalFileSystemOperation::DoCopyFileLocal,
535 base::Unretained(this), src_url, dest_url, callback),
536 base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED));
537 }
538
539 void LocalFileSystemOperation::MoveFileLocal(
540 const FileSystemURL& src_url,
541 const FileSystemURL& dest_url,
542 const StatusCallback& callback) {
543 DCHECK(SetPendingOperationType(kOperationMove));
544 DCHECK(AreSameFileSystem(src_url, dest_url));
545
546 base::PlatformFileError result = SetUp(src_url, OPERATION_MODE_WRITE);
547 if (result == base::PLATFORM_FILE_OK)
548 result = SetUp(dest_url, OPERATION_MODE_WRITE);
549 if (result != base::PLATFORM_FILE_OK) {
550 callback.Run(result);
551 delete this;
552 return;
553 }
554
555 GetUsageAndQuotaThenRunTask(
556 dest_url,
557 base::Bind(&LocalFileSystemOperation::DoMoveFileLocal,
558 base::Unretained(this), src_url, dest_url, callback),
559 base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED));
560 }
561
562 void LocalFileSystemOperation::GetUsageAndQuotaThenRunTask(
563 const FileSystemURL& url,
564 const base::Closure& task,
565 const base::Closure& error_callback) {
566 quota::QuotaManagerProxy* quota_manager_proxy =
567 file_system_context()->quota_manager_proxy();
568 if (!quota_manager_proxy ||
569 !file_system_context()->GetQuotaUtil(url.type())) {
570 // If we don't have the quota manager or the requested filesystem type
571 // does not support quota, we should be able to let it go.
572 operation_context()->set_allowed_bytes_growth(kint64max);
573 task.Run();
574 return;
575 }
576
577 DCHECK(quota_manager_proxy);
578 DCHECK(quota_manager_proxy->quota_manager());
579 quota_manager_proxy->quota_manager()->GetUsageAndQuota(
580 url.origin(),
581 FileSystemTypeToQuotaStorageType(url.type()),
582 base::Bind(&LocalFileSystemOperation::DidGetUsageAndQuotaAndRunTask,
583 weak_factory_.GetWeakPtr(), task, error_callback));
584 }
585
586 void LocalFileSystemOperation::DidGetUsageAndQuotaAndRunTask(
587 const base::Closure& task,
588 const base::Closure& error_callback,
589 quota::QuotaStatusCode status,
590 int64 usage, int64 quota) {
591 if (status != quota::kQuotaStatusOk) {
592 LOG(WARNING) << "Got unexpected quota error : " << status;
593 error_callback.Run();
594 return;
595 }
596
597 operation_context()->set_allowed_bytes_growth(quota - usage);
598 task.Run();
599 }
600
601 base::Closure LocalFileSystemOperation::GetWriteClosure(
602 const net::URLRequestContext* url_request_context,
603 const FileSystemURL& url,
604 const GURL& blob_url,
605 int64 offset,
606 const WriteCallback& callback) {
607 DCHECK(SetPendingOperationType(kOperationWrite));
608
609 base::PlatformFileError result = SetUp(url, OPERATION_MODE_WRITE);
610 if (result != base::PLATFORM_FILE_OK) {
611 return base::Bind(&LocalFileSystemOperation::DidFailWrite,
612 base::Owned(this), callback, result);
613 }
614
615 scoped_ptr<FileStreamWriter> writer(
616 file_system_context()->CreateFileStreamWriter(url, offset));
617
618 if (!writer) {
619 // Write is not supported.
620 return base::Bind(&LocalFileSystemOperation::DidFailWrite,
621 base::Owned(this), callback,
622 base::PLATFORM_FILE_ERROR_SECURITY);
623 }
624
625 DCHECK(blob_url.is_valid());
626 file_writer_delegate_.reset(new FileWriterDelegate(
627 base::Bind(&LocalFileSystemOperation::DidWrite,
628 weak_factory_.GetWeakPtr(), url),
629 writer.Pass()));
630
631 write_callback_ = callback;
632 scoped_ptr<net::URLRequest> blob_request(url_request_context->CreateRequest(
633 blob_url, file_writer_delegate_.get()));
634
635 return base::Bind(&FileWriterDelegate::Start,
636 base::Unretained(file_writer_delegate_.get()),
637 base::Passed(&blob_request));
638 }
639
640 void LocalFileSystemOperation::DidFailWrite(
641 const WriteCallback& callback,
642 base::PlatformFileError result) {
643 callback.Run(result, 0, false);
644 }
645
646 void LocalFileSystemOperation::DoCreateFile(
647 const FileSystemURL& url,
648 const StatusCallback& callback,
649 bool exclusive) {
650 async_file_util_->EnsureFileExists(
651 operation_context(), url,
652 base::Bind(
653 exclusive ?
654 &LocalFileSystemOperation::DidEnsureFileExistsExclusive :
655 &LocalFileSystemOperation::DidEnsureFileExistsNonExclusive,
656 base::Owned(this), callback));
657 }
658
659 void LocalFileSystemOperation::DoCreateDirectory(
660 const FileSystemURL& url,
661 const StatusCallback& callback,
662 bool exclusive, bool recursive) {
663 async_file_util_->CreateDirectory(
664 operation_context(),
665 url, exclusive, recursive,
666 base::Bind(&LocalFileSystemOperation::DidFinishFileOperation,
667 base::Owned(this), callback));
668 }
669
670 void LocalFileSystemOperation::DoCopyFileLocal(
671 const FileSystemURL& src_url,
672 const FileSystemURL& dest_url,
673 const StatusCallback& callback) {
674 async_file_util_->CopyFileLocal(
675 operation_context(), src_url, dest_url,
676 base::Bind(&LocalFileSystemOperation::DidFinishFileOperation,
677 base::Owned(this), callback));
678 }
679
680 void LocalFileSystemOperation::DoMoveFileLocal(
681 const FileSystemURL& src_url,
682 const FileSystemURL& dest_url,
683 const StatusCallback& callback) {
684 async_file_util_->MoveFileLocal(
685 operation_context(), src_url, dest_url,
686 base::Bind(&LocalFileSystemOperation::DidFinishFileOperation,
687 base::Owned(this), callback));
688 }
689
690 void LocalFileSystemOperation::DoCopyInForeignFile(
691 const base::FilePath& src_local_disk_file_path,
692 const FileSystemURL& dest_url,
693 const StatusCallback& callback) {
694 async_file_util_->CopyInForeignFile(
695 operation_context(),
696 src_local_disk_file_path, dest_url,
697 base::Bind(&LocalFileSystemOperation::DidFinishFileOperation,
698 base::Owned(this), callback));
699 }
700
701 void LocalFileSystemOperation::DoTruncate(const FileSystemURL& url,
702 const StatusCallback& callback,
703 int64 length) {
704 async_file_util_->Truncate(
705 operation_context(), url, length,
706 base::Bind(&LocalFileSystemOperation::DidFinishFileOperation,
707 base::Owned(this), callback));
708 }
709
710 void LocalFileSystemOperation::DoOpenFile(const FileSystemURL& url,
711 const OpenFileCallback& callback,
712 int file_flags) {
713 async_file_util_->CreateOrOpen(
714 operation_context(), url, file_flags,
715 base::Bind(&LocalFileSystemOperation::DidOpenFile,
716 base::Owned(this), callback));
717 }
718
719 void LocalFileSystemOperation::DidEnsureFileExistsExclusive(
720 const StatusCallback& callback,
721 base::PlatformFileError rv, bool created) {
722 if (rv == base::PLATFORM_FILE_OK && !created) {
723 callback.Run(base::PLATFORM_FILE_ERROR_EXISTS);
724 } else {
725 DidFinishFileOperation(callback, rv);
726 }
727 }
728
729 void LocalFileSystemOperation::DidEnsureFileExistsNonExclusive(
730 const StatusCallback& callback,
731 base::PlatformFileError rv, bool /* created */) {
732 DidFinishFileOperation(callback, rv);
733 }
734
735 void LocalFileSystemOperation::DidFinishFileOperation(
736 const StatusCallback& callback,
737 base::PlatformFileError rv) {
738 if (!cancel_callback_.is_null()) {
739 DCHECK_EQ(kOperationTruncate, pending_operation_);
740
741 callback.Run(base::PLATFORM_FILE_ERROR_ABORT);
742 cancel_callback_.Run(base::PLATFORM_FILE_OK);
743 cancel_callback_.Reset();
744 } else {
745 callback.Run(rv);
746 }
747 }
748
749 void LocalFileSystemOperation::DidFinishDelegatedOperation(
750 const StatusCallback& callback,
751 base::PlatformFileError rv) {
752 // The callback might be held by the delegate and Owned() may not work,
753 // so just explicitly delete this now.
754 callback.Run(rv);
755 delete this;
756 }
757
758 void LocalFileSystemOperation::DidDirectoryExists(
759 const StatusCallback& callback,
760 base::PlatformFileError rv,
761 const base::PlatformFileInfo& file_info,
762 const base::FilePath& unused) {
763 if (rv == base::PLATFORM_FILE_OK && !file_info.is_directory)
764 rv = base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
765 callback.Run(rv);
766 }
767
768 void LocalFileSystemOperation::DidFileExists(
769 const StatusCallback& callback,
770 base::PlatformFileError rv,
771 const base::PlatformFileInfo& file_info,
772 const base::FilePath& unused) {
773 if (rv == base::PLATFORM_FILE_OK && file_info.is_directory)
774 rv = base::PLATFORM_FILE_ERROR_NOT_A_FILE;
775 callback.Run(rv);
776 }
777
778 void LocalFileSystemOperation::DidGetMetadata(
779 const GetMetadataCallback& callback,
780 base::PlatformFileError rv,
781 const base::PlatformFileInfo& file_info,
782 const base::FilePath& platform_path) {
783 callback.Run(rv, file_info, platform_path);
784 }
785
786 void LocalFileSystemOperation::DidReadDirectory(
787 const ReadDirectoryCallback& callback,
788 base::PlatformFileError rv,
789 const std::vector<base::FileUtilProxy::Entry>& entries,
790 bool has_more) {
791 callback.Run(rv, entries, has_more);
792 }
793
794 void LocalFileSystemOperation::DidWrite(
795 const FileSystemURL& url,
796 base::PlatformFileError rv,
797 int64 bytes,
798 FileWriterDelegate::WriteProgressStatus write_status) {
799 if (write_callback_.is_null()) {
800 // If cancelled, callback is already invoked and set to null in Cancel().
801 // We must not call it twice. Just shut down this operation object.
802 delete this;
803 return;
804 }
805
806 const bool complete = (
807 write_status != FileWriterDelegate::SUCCESS_IO_PENDING);
808 if (complete && write_status != FileWriterDelegate::ERROR_WRITE_NOT_STARTED) {
809 operation_context()->change_observers()->Notify(
810 &FileChangeObserver::OnModifyFile, MakeTuple(url));
811 }
812
813 write_callback_.Run(rv, bytes, complete);
814 if (complete || rv != base::PLATFORM_FILE_OK)
815 delete this;
816 }
817
818 void LocalFileSystemOperation::DidTouchFile(const StatusCallback& callback,
819 base::PlatformFileError rv) {
820 callback.Run(rv);
821 }
822
823 void LocalFileSystemOperation::DidOpenFile(
824 const OpenFileCallback& callback,
825 base::PlatformFileError rv,
826 base::PassPlatformFile file,
827 bool unused) {
828 if (rv == base::PLATFORM_FILE_OK)
829 CHECK_NE(base::kNullProcessHandle, peer_handle_);
830 callback.Run(rv, file.ReleaseValue(),
831 base::Bind(&NopCloseFileCallback),
832 peer_handle_);
833 }
834
835 void LocalFileSystemOperation::DidCreateSnapshotFile(
836 const SnapshotFileCallback& callback,
837 base::PlatformFileError result,
838 const base::PlatformFileInfo& file_info,
839 const base::FilePath& platform_path,
840 const scoped_refptr<ShareableFileReference>& file_ref) {
841 callback.Run(result, file_info, platform_path, file_ref);
842 }
843
844 base::PlatformFileError LocalFileSystemOperation::SetUp(
845 const FileSystemURL& url,
846 OperationMode mode) {
847 DCHECK(url.is_valid());
848
849 async_file_util_ = file_system_context()->GetAsyncFileUtil(url.type());
850 if (!async_file_util_)
851 return base::PLATFORM_FILE_ERROR_SECURITY;
852
853 // If this operation is created for recursive sub-operations (i.e.
854 // it has the parent operation) we skip duplicated notifications.
855 if (parent_operation_)
856 return base::PLATFORM_FILE_OK;
857
858 switch (mode) {
859 case OPERATION_MODE_READ:
860 operation_context()->access_observers()->Notify(
861 &FileAccessObserver::OnAccess, MakeTuple(url));
862 break;
863 case OPERATION_MODE_WRITE:
864 operation_context()->update_observers()->Notify(
865 &FileUpdateObserver::OnStartUpdate, MakeTuple(url));
866 DCHECK(!write_target_url_.is_valid());
867 write_target_url_ = url;
868 break;
869 }
870
871 return base::PLATFORM_FILE_OK;
872 }
873
874 bool LocalFileSystemOperation::SetPendingOperationType(OperationType type) {
875 if (pending_operation_ != kOperationNone)
876 return false;
877 pending_operation_ = type;
878 return true;
879 }
880
881 } // namespace fileapi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698