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

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

Issue 21370003: Rename fileapi::LocalFileSystemOperation to FileSystemOperationImpl. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 7 years, 4 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/browser/fileapi/local_file_system_operation.h"
6
7 #include "base/bind.h"
8 #include "base/single_thread_task_runner.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/time/time.h"
11 #include "net/base/escape.h"
12 #include "net/url_request/url_request.h"
13 #include "webkit/browser/fileapi/async_file_util.h"
14 #include "webkit/browser/fileapi/copy_or_move_operation_delegate.h"
15 #include "webkit/browser/fileapi/file_observers.h"
16 #include "webkit/browser/fileapi/file_system_backend.h"
17 #include "webkit/browser/fileapi/file_system_context.h"
18 #include "webkit/browser/fileapi/file_system_file_util.h"
19 #include "webkit/browser/fileapi/file_system_operation_context.h"
20 #include "webkit/browser/fileapi/file_system_task_runners.h"
21 #include "webkit/browser/fileapi/file_system_url.h"
22 #include "webkit/browser/fileapi/file_writer_delegate.h"
23 #include "webkit/browser/fileapi/remove_operation_delegate.h"
24 #include "webkit/browser/fileapi/sandbox_file_stream_writer.h"
25 #include "webkit/browser/quota/quota_manager.h"
26 #include "webkit/common/blob/shareable_file_reference.h"
27 #include "webkit/common/fileapi/file_system_types.h"
28 #include "webkit/common/fileapi/file_system_util.h"
29 #include "webkit/common/quota/quota_types.h"
30
31 using webkit_blob::ScopedFile;
32
33 namespace fileapi {
34
35 LocalFileSystemOperation::LocalFileSystemOperation(
36 const FileSystemURL& url,
37 FileSystemContext* file_system_context,
38 scoped_ptr<FileSystemOperationContext> operation_context)
39 : file_system_context_(file_system_context),
40 operation_context_(operation_context.Pass()),
41 async_file_util_(NULL),
42 peer_handle_(base::kNullProcessHandle),
43 pending_operation_(kOperationNone) {
44 DCHECK(operation_context_.get());
45 operation_context_->DetachUserDataThread();
46 async_file_util_ = file_system_context_->GetAsyncFileUtil(url.type());
47 DCHECK(async_file_util_);
48 }
49
50 LocalFileSystemOperation::~LocalFileSystemOperation() {
51 }
52
53 void LocalFileSystemOperation::CreateFile(const FileSystemURL& url,
54 bool exclusive,
55 const StatusCallback& callback) {
56 DCHECK(SetPendingOperationType(kOperationCreateFile));
57 GetUsageAndQuotaThenRunTask(
58 url,
59 base::Bind(&LocalFileSystemOperation::DoCreateFile,
60 AsWeakPtr(), url, callback, exclusive),
61 base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED));
62 }
63
64 void LocalFileSystemOperation::CreateDirectory(const FileSystemURL& url,
65 bool exclusive,
66 bool recursive,
67 const StatusCallback& callback) {
68 DCHECK(SetPendingOperationType(kOperationCreateDirectory));
69 GetUsageAndQuotaThenRunTask(
70 url,
71 base::Bind(&LocalFileSystemOperation::DoCreateDirectory,
72 AsWeakPtr(), url, callback, exclusive, recursive),
73 base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED));
74 }
75
76 void LocalFileSystemOperation::Copy(const FileSystemURL& src_url,
77 const FileSystemURL& dest_url,
78 const StatusCallback& callback) {
79 DCHECK(SetPendingOperationType(kOperationCopy));
80 DCHECK(!recursive_operation_delegate_);
81 recursive_operation_delegate_.reset(
82 new CopyOrMoveOperationDelegate(
83 file_system_context(),
84 src_url, dest_url,
85 CopyOrMoveOperationDelegate::OPERATION_COPY,
86 base::Bind(&LocalFileSystemOperation::DidFinishOperation,
87 AsWeakPtr(), callback)));
88 recursive_operation_delegate_->RunRecursively();
89 }
90
91 void LocalFileSystemOperation::Move(const FileSystemURL& src_url,
92 const FileSystemURL& dest_url,
93 const StatusCallback& callback) {
94 DCHECK(SetPendingOperationType(kOperationMove));
95 DCHECK(!recursive_operation_delegate_);
96 recursive_operation_delegate_.reset(
97 new CopyOrMoveOperationDelegate(
98 file_system_context(),
99 src_url, dest_url,
100 CopyOrMoveOperationDelegate::OPERATION_MOVE,
101 base::Bind(&LocalFileSystemOperation::DidFinishOperation,
102 AsWeakPtr(), callback)));
103 recursive_operation_delegate_->RunRecursively();
104 }
105
106 void LocalFileSystemOperation::DirectoryExists(const FileSystemURL& url,
107 const StatusCallback& callback) {
108 DCHECK(SetPendingOperationType(kOperationDirectoryExists));
109 async_file_util_->GetFileInfo(
110 operation_context_.Pass(), url,
111 base::Bind(&LocalFileSystemOperation::DidDirectoryExists,
112 AsWeakPtr(), callback));
113 }
114
115 void LocalFileSystemOperation::FileExists(const FileSystemURL& url,
116 const StatusCallback& callback) {
117 DCHECK(SetPendingOperationType(kOperationFileExists));
118 async_file_util_->GetFileInfo(
119 operation_context_.Pass(), url,
120 base::Bind(&LocalFileSystemOperation::DidFileExists,
121 AsWeakPtr(), callback));
122 }
123
124 void LocalFileSystemOperation::GetMetadata(
125 const FileSystemURL& url, const GetMetadataCallback& callback) {
126 DCHECK(SetPendingOperationType(kOperationGetMetadata));
127 async_file_util_->GetFileInfo(operation_context_.Pass(), url, callback);
128 }
129
130 void LocalFileSystemOperation::ReadDirectory(
131 const FileSystemURL& url, const ReadDirectoryCallback& callback) {
132 DCHECK(SetPendingOperationType(kOperationReadDirectory));
133 async_file_util_->ReadDirectory(
134 operation_context_.Pass(), url, callback);
135 }
136
137 void LocalFileSystemOperation::Remove(const FileSystemURL& url,
138 bool recursive,
139 const StatusCallback& callback) {
140 DCHECK(SetPendingOperationType(kOperationRemove));
141 DCHECK(!recursive_operation_delegate_);
142
143 if (recursive) {
144 // For recursive removal, try to delegate the operation to AsyncFileUtil
145 // first. If not supported, it is delegated to RemoveOperationDelegate
146 // in DidDeleteRecursively.
147 async_file_util_->DeleteRecursively(
148 operation_context_.Pass(), url,
149 base::Bind(&LocalFileSystemOperation::DidDeleteRecursively,
150 AsWeakPtr(), url, callback));
151 return;
152 }
153
154 recursive_operation_delegate_.reset(
155 new RemoveOperationDelegate(
156 file_system_context(), url,
157 base::Bind(&LocalFileSystemOperation::DidFinishOperation,
158 AsWeakPtr(), callback)));
159 recursive_operation_delegate_->Run();
160 }
161
162 void LocalFileSystemOperation::Write(
163 const FileSystemURL& url,
164 scoped_ptr<FileWriterDelegate> writer_delegate,
165 scoped_ptr<net::URLRequest> blob_request,
166 const WriteCallback& callback) {
167 DCHECK(SetPendingOperationType(kOperationWrite));
168 file_writer_delegate_ = writer_delegate.Pass();
169 file_writer_delegate_->Start(
170 blob_request.Pass(),
171 base::Bind(&LocalFileSystemOperation::DidWrite, AsWeakPtr(),
172 url, callback));
173 }
174
175 void LocalFileSystemOperation::Truncate(const FileSystemURL& url, int64 length,
176 const StatusCallback& callback) {
177 DCHECK(SetPendingOperationType(kOperationTruncate));
178 GetUsageAndQuotaThenRunTask(
179 url,
180 base::Bind(&LocalFileSystemOperation::DoTruncate,
181 AsWeakPtr(), url, callback, length),
182 base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED));
183 }
184
185 void LocalFileSystemOperation::TouchFile(const FileSystemURL& url,
186 const base::Time& last_access_time,
187 const base::Time& last_modified_time,
188 const StatusCallback& callback) {
189 DCHECK(SetPendingOperationType(kOperationTouchFile));
190 async_file_util_->Touch(
191 operation_context_.Pass(), url,
192 last_access_time, last_modified_time,
193 base::Bind(&LocalFileSystemOperation::DidFinishOperation,
194 AsWeakPtr(), callback));
195 }
196
197 void LocalFileSystemOperation::OpenFile(const FileSystemURL& url,
198 int file_flags,
199 base::ProcessHandle peer_handle,
200 const OpenFileCallback& callback) {
201 DCHECK(SetPendingOperationType(kOperationOpenFile));
202 peer_handle_ = peer_handle;
203
204 if (file_flags & (
205 (base::PLATFORM_FILE_ENUMERATE | base::PLATFORM_FILE_TEMPORARY |
206 base::PLATFORM_FILE_HIDDEN))) {
207 callback.Run(base::PLATFORM_FILE_ERROR_FAILED,
208 base::kInvalidPlatformFileValue,
209 base::Closure(),
210 base::kNullProcessHandle);
211 return;
212 }
213 GetUsageAndQuotaThenRunTask(
214 url,
215 base::Bind(&LocalFileSystemOperation::DoOpenFile,
216 AsWeakPtr(),
217 url, callback, file_flags),
218 base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED,
219 base::kInvalidPlatformFileValue,
220 base::Closure(),
221 base::kNullProcessHandle));
222 }
223
224 // We can only get here on a write or truncate that's not yet completed.
225 // We don't support cancelling any other operation at this time.
226 void LocalFileSystemOperation::Cancel(const StatusCallback& cancel_callback) {
227 DCHECK(cancel_callback_.is_null());
228 cancel_callback_ = cancel_callback;
229
230 if (file_writer_delegate_.get()) {
231 DCHECK_EQ(kOperationWrite, pending_operation_);
232 // This will call DidWrite() with ABORT status code.
233 file_writer_delegate_->Cancel();
234 } else {
235 // For truncate we have no way to cancel the inflight operation (for now).
236 // Let it just run and dispatch cancel callback later.
237 DCHECK_EQ(kOperationTruncate, pending_operation_);
238 }
239 }
240
241 LocalFileSystemOperation*
242 LocalFileSystemOperation::AsLocalFileSystemOperation() {
243 return this;
244 }
245
246 base::PlatformFileError LocalFileSystemOperation::SyncGetPlatformPath(
247 const FileSystemURL& url,
248 base::FilePath* platform_path) {
249 DCHECK(SetPendingOperationType(kOperationGetLocalPath));
250 FileSystemFileUtil* file_util = file_system_context()->GetFileUtil(
251 url.type());
252 if (!file_util)
253 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
254 file_util->GetLocalFilePath(operation_context_.get(), url, platform_path);
255 return base::PLATFORM_FILE_OK;
256 }
257
258 void LocalFileSystemOperation::CreateSnapshotFile(
259 const FileSystemURL& url,
260 const SnapshotFileCallback& callback) {
261 DCHECK(SetPendingOperationType(kOperationCreateSnapshotFile));
262 async_file_util_->CreateSnapshotFile(
263 operation_context_.Pass(), url, callback);
264 }
265
266 void LocalFileSystemOperation::CopyInForeignFile(
267 const base::FilePath& src_local_disk_file_path,
268 const FileSystemURL& dest_url,
269 const StatusCallback& callback) {
270 DCHECK(SetPendingOperationType(kOperationCopyInForeignFile));
271 GetUsageAndQuotaThenRunTask(
272 dest_url,
273 base::Bind(&LocalFileSystemOperation::DoCopyInForeignFile,
274 AsWeakPtr(), src_local_disk_file_path, dest_url,
275 callback),
276 base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED));
277 }
278
279 void LocalFileSystemOperation::RemoveFile(
280 const FileSystemURL& url,
281 const StatusCallback& callback) {
282 DCHECK(SetPendingOperationType(kOperationRemove));
283 async_file_util_->DeleteFile(
284 operation_context_.Pass(), url,
285 base::Bind(&LocalFileSystemOperation::DidFinishOperation,
286 AsWeakPtr(), callback));
287 }
288
289 void LocalFileSystemOperation::RemoveDirectory(
290 const FileSystemURL& url,
291 const StatusCallback& callback) {
292 DCHECK(SetPendingOperationType(kOperationRemove));
293 async_file_util_->DeleteDirectory(
294 operation_context_.Pass(), url,
295 base::Bind(&LocalFileSystemOperation::DidFinishOperation,
296 AsWeakPtr(), callback));
297 }
298
299 void LocalFileSystemOperation::CopyFileLocal(
300 const FileSystemURL& src_url,
301 const FileSystemURL& dest_url,
302 const StatusCallback& callback) {
303 DCHECK(SetPendingOperationType(kOperationCopy));
304 DCHECK(src_url.IsInSameFileSystem(dest_url));
305 GetUsageAndQuotaThenRunTask(
306 dest_url,
307 base::Bind(&LocalFileSystemOperation::DoCopyFileLocal,
308 AsWeakPtr(), src_url, dest_url, callback),
309 base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED));
310 }
311
312 void LocalFileSystemOperation::MoveFileLocal(
313 const FileSystemURL& src_url,
314 const FileSystemURL& dest_url,
315 const StatusCallback& callback) {
316 DCHECK(SetPendingOperationType(kOperationMove));
317 DCHECK(src_url.IsInSameFileSystem(dest_url));
318 GetUsageAndQuotaThenRunTask(
319 dest_url,
320 base::Bind(&LocalFileSystemOperation::DoMoveFileLocal,
321 AsWeakPtr(), src_url, dest_url, callback),
322 base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED));
323 }
324
325 void LocalFileSystemOperation::GetUsageAndQuotaThenRunTask(
326 const FileSystemURL& url,
327 const base::Closure& task,
328 const base::Closure& error_callback) {
329 quota::QuotaManagerProxy* quota_manager_proxy =
330 file_system_context()->quota_manager_proxy();
331 if (!quota_manager_proxy ||
332 !file_system_context()->GetQuotaUtil(url.type())) {
333 // If we don't have the quota manager or the requested filesystem type
334 // does not support quota, we should be able to let it go.
335 operation_context_->set_allowed_bytes_growth(kint64max);
336 task.Run();
337 return;
338 }
339
340 DCHECK(quota_manager_proxy);
341 DCHECK(quota_manager_proxy->quota_manager());
342 quota_manager_proxy->quota_manager()->GetUsageAndQuota(
343 url.origin(),
344 FileSystemTypeToQuotaStorageType(url.type()),
345 base::Bind(&LocalFileSystemOperation::DidGetUsageAndQuotaAndRunTask,
346 AsWeakPtr(), task, error_callback));
347 }
348
349 void LocalFileSystemOperation::DidGetUsageAndQuotaAndRunTask(
350 const base::Closure& task,
351 const base::Closure& error_callback,
352 quota::QuotaStatusCode status,
353 int64 usage, int64 quota) {
354 if (status != quota::kQuotaStatusOk) {
355 LOG(WARNING) << "Got unexpected quota error : " << status;
356 error_callback.Run();
357 return;
358 }
359
360 operation_context_->set_allowed_bytes_growth(quota - usage);
361 task.Run();
362 }
363
364 void LocalFileSystemOperation::DoCreateFile(
365 const FileSystemURL& url,
366 const StatusCallback& callback,
367 bool exclusive) {
368 async_file_util_->EnsureFileExists(
369 operation_context_.Pass(), url,
370 base::Bind(
371 exclusive ?
372 &LocalFileSystemOperation::DidEnsureFileExistsExclusive :
373 &LocalFileSystemOperation::DidEnsureFileExistsNonExclusive,
374 AsWeakPtr(), callback));
375 }
376
377 void LocalFileSystemOperation::DoCreateDirectory(
378 const FileSystemURL& url,
379 const StatusCallback& callback,
380 bool exclusive, bool recursive) {
381 async_file_util_->CreateDirectory(
382 operation_context_.Pass(),
383 url, exclusive, recursive,
384 base::Bind(&LocalFileSystemOperation::DidFinishOperation,
385 AsWeakPtr(), callback));
386 }
387
388 void LocalFileSystemOperation::DoCopyFileLocal(
389 const FileSystemURL& src_url,
390 const FileSystemURL& dest_url,
391 const StatusCallback& callback) {
392 async_file_util_->CopyFileLocal(
393 operation_context_.Pass(), src_url, dest_url,
394 base::Bind(&LocalFileSystemOperation::DidFinishOperation,
395 AsWeakPtr(), callback));
396 }
397
398 void LocalFileSystemOperation::DoMoveFileLocal(
399 const FileSystemURL& src_url,
400 const FileSystemURL& dest_url,
401 const StatusCallback& callback) {
402 async_file_util_->MoveFileLocal(
403 operation_context_.Pass(), src_url, dest_url,
404 base::Bind(&LocalFileSystemOperation::DidFinishOperation,
405 AsWeakPtr(), callback));
406 }
407
408 void LocalFileSystemOperation::DoCopyInForeignFile(
409 const base::FilePath& src_local_disk_file_path,
410 const FileSystemURL& dest_url,
411 const StatusCallback& callback) {
412 async_file_util_->CopyInForeignFile(
413 operation_context_.Pass(),
414 src_local_disk_file_path, dest_url,
415 base::Bind(&LocalFileSystemOperation::DidFinishOperation,
416 AsWeakPtr(), callback));
417 }
418
419 void LocalFileSystemOperation::DoTruncate(const FileSystemURL& url,
420 const StatusCallback& callback,
421 int64 length) {
422 async_file_util_->Truncate(
423 operation_context_.Pass(), url, length,
424 base::Bind(&LocalFileSystemOperation::DidFinishOperation,
425 AsWeakPtr(), callback));
426 }
427
428 void LocalFileSystemOperation::DoOpenFile(const FileSystemURL& url,
429 const OpenFileCallback& callback,
430 int file_flags) {
431 async_file_util_->CreateOrOpen(
432 operation_context_.Pass(), url, file_flags,
433 base::Bind(&LocalFileSystemOperation::DidOpenFile,
434 AsWeakPtr(), callback));
435 }
436
437 void LocalFileSystemOperation::DidEnsureFileExistsExclusive(
438 const StatusCallback& callback,
439 base::PlatformFileError rv, bool created) {
440 if (rv == base::PLATFORM_FILE_OK && !created) {
441 callback.Run(base::PLATFORM_FILE_ERROR_EXISTS);
442 } else {
443 DidFinishOperation(callback, rv);
444 }
445 }
446
447 void LocalFileSystemOperation::DidEnsureFileExistsNonExclusive(
448 const StatusCallback& callback,
449 base::PlatformFileError rv, bool /* created */) {
450 DidFinishOperation(callback, rv);
451 }
452
453 void LocalFileSystemOperation::DidFinishOperation(
454 const StatusCallback& callback,
455 base::PlatformFileError rv) {
456 if (!cancel_callback_.is_null()) {
457 DCHECK_EQ(kOperationTruncate, pending_operation_);
458
459 StatusCallback cancel_callback = cancel_callback_;
460 callback.Run(base::PLATFORM_FILE_ERROR_ABORT);
461 cancel_callback.Run(base::PLATFORM_FILE_OK);
462 } else {
463 callback.Run(rv);
464 }
465 }
466
467 void LocalFileSystemOperation::DidDirectoryExists(
468 const StatusCallback& callback,
469 base::PlatformFileError rv,
470 const base::PlatformFileInfo& file_info) {
471 if (rv == base::PLATFORM_FILE_OK && !file_info.is_directory)
472 rv = base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
473 callback.Run(rv);
474 }
475
476 void LocalFileSystemOperation::DidFileExists(
477 const StatusCallback& callback,
478 base::PlatformFileError rv,
479 const base::PlatformFileInfo& file_info) {
480 if (rv == base::PLATFORM_FILE_OK && file_info.is_directory)
481 rv = base::PLATFORM_FILE_ERROR_NOT_A_FILE;
482 callback.Run(rv);
483 }
484
485 void LocalFileSystemOperation::DidDeleteRecursively(
486 const FileSystemURL& url,
487 const StatusCallback& callback,
488 base::PlatformFileError rv) {
489 if (rv == base::PLATFORM_FILE_ERROR_INVALID_OPERATION) {
490 // Recursive removal is not supported on this platform.
491 DCHECK(!recursive_operation_delegate_);
492 recursive_operation_delegate_.reset(
493 new RemoveOperationDelegate(
494 file_system_context(), url,
495 base::Bind(&LocalFileSystemOperation::DidFinishOperation,
496 AsWeakPtr(), callback)));
497 recursive_operation_delegate_->RunRecursively();
498 return;
499 }
500
501 callback.Run(rv);
502 }
503
504 void LocalFileSystemOperation::DidWrite(
505 const FileSystemURL& url,
506 const WriteCallback& write_callback,
507 base::PlatformFileError rv,
508 int64 bytes,
509 FileWriterDelegate::WriteProgressStatus write_status) {
510 const bool complete = (
511 write_status != FileWriterDelegate::SUCCESS_IO_PENDING);
512 if (complete && write_status != FileWriterDelegate::ERROR_WRITE_NOT_STARTED) {
513 DCHECK(operation_context_);
514 operation_context_->change_observers()->Notify(
515 &FileChangeObserver::OnModifyFile, MakeTuple(url));
516 }
517
518 StatusCallback cancel_callback = cancel_callback_;
519 write_callback.Run(rv, bytes, complete);
520 if (!cancel_callback.is_null())
521 cancel_callback.Run(base::PLATFORM_FILE_OK);
522 }
523
524 void LocalFileSystemOperation::DidOpenFile(
525 const OpenFileCallback& callback,
526 base::PlatformFileError rv,
527 base::PassPlatformFile file,
528 const base::Closure& on_close_callback) {
529 if (rv == base::PLATFORM_FILE_OK)
530 CHECK_NE(base::kNullProcessHandle, peer_handle_);
531 callback.Run(rv, file.ReleaseValue(), on_close_callback, peer_handle_);
532 }
533
534 bool LocalFileSystemOperation::SetPendingOperationType(OperationType type) {
535 if (pending_operation_ != kOperationNone)
536 return false;
537 pending_operation_ = type;
538 return true;
539 }
540
541 } // namespace fileapi
OLDNEW
« no previous file with comments | « webkit/browser/fileapi/local_file_system_operation.h ('k') | webkit/browser/fileapi/local_file_system_operation_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698