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

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

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

Powered by Google App Engine
This is Rietveld 408576698