blob: 5cee4a1dae085783a3b5058d5d6c0ffe42577619 [file] [log] [blame]
[email protected]61b48e02013-08-01 15:00:101// Copyright 2013 The Chromium Authors. All rights reserved.
[email protected]f05ca652010-09-16 04:46:142// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]61b48e02013-08-01 15:00:105#include "webkit/browser/fileapi/file_system_operation_impl.h"
[email protected]f05ca652010-09-16 04:46:146
[email protected]30c1eea2011-10-17 18:40:307#include "base/bind.h"
[email protected]dc57ec82012-08-07 03:50:108#include "base/single_thread_task_runner.h"
[email protected]906265872013-06-07 22:40:459#include "base/strings/utf_string_conversions.h"
[email protected]0a8ebe12013-06-28 15:23:2310#include "base/time/time.h"
[email protected]41e889432011-04-13 19:53:3011#include "net/base/escape.h"
[email protected]1a6e3902013-06-13 07:09:4012#include "net/url_request/url_request.h"
[email protected]c6f9203a2013-05-28 02:08:0713#include "webkit/browser/fileapi/async_file_util.h"
[email protected]f17d6a12013-06-04 06:57:0714#include "webkit/browser/fileapi/copy_or_move_operation_delegate.h"
[email protected]f25e1132013-05-24 13:58:0415#include "webkit/browser/fileapi/file_observers.h"
[email protected]f19bbf62013-07-09 01:22:3216#include "webkit/browser/fileapi/file_system_backend.h"
[email protected]c6f9203a2013-05-28 02:08:0717#include "webkit/browser/fileapi/file_system_context.h"
[email protected]5a20d042013-05-22 12:54:1818#include "webkit/browser/fileapi/file_system_file_util.h"
[email protected]c6f9203a2013-05-28 02:08:0719#include "webkit/browser/fileapi/file_system_operation_context.h"
[email protected]c6f9203a2013-05-28 02:08:0720#include "webkit/browser/fileapi/file_system_url.h"
21#include "webkit/browser/fileapi/file_writer_delegate.h"
22#include "webkit/browser/fileapi/remove_operation_delegate.h"
[email protected]57acf8a2013-08-30 00:06:4723#include "webkit/browser/fileapi/sandbox_file_system_backend.h"
[email protected]844a7f82014-01-17 16:59:4524#include "webkit/browser/quota/quota_manager_proxy.h"
[email protected]b76b556d2013-05-29 03:09:4325#include "webkit/common/blob/shareable_file_reference.h"
[email protected]61d271f32013-05-28 04:59:2326#include "webkit/common/fileapi/file_system_types.h"
27#include "webkit/common/fileapi/file_system_util.h"
[email protected]7660ec92013-05-30 05:12:3928#include "webkit/common/quota/quota_types.h"
[email protected]f05ca652010-09-16 04:46:1429
[email protected]7ab45cfa82013-04-26 07:13:2030using webkit_blob::ScopedFile;
[email protected]826df822012-08-04 01:23:5631
[email protected]f05ca652010-09-16 04:46:1432namespace fileapi {
33
[email protected]bd69f572013-09-09 06:15:2334FileSystemOperation* FileSystemOperation::Create(
[email protected]5dfa47c2013-06-10 04:57:1535 const FileSystemURL& url,
[email protected]84780b42013-04-19 14:56:1136 FileSystemContext* file_system_context,
[email protected]bd69f572013-09-09 06:15:2337 scoped_ptr<FileSystemOperationContext> operation_context) {
38 return new FileSystemOperationImpl(url, file_system_context,
39 operation_context.Pass());
[email protected]84780b42013-04-19 14:56:1140}
41
[email protected]61b48e02013-08-01 15:00:1042FileSystemOperationImpl::~FileSystemOperationImpl() {
[email protected]02a60542012-07-24 20:05:3343}
44
[email protected]61b48e02013-08-01 15:00:1045void FileSystemOperationImpl::CreateFile(const FileSystemURL& url,
46 bool exclusive,
47 const StatusCallback& callback) {
[email protected]f7fdd4d2012-02-16 11:32:4548 DCHECK(SetPendingOperationType(kOperationCreateFile));
[email protected]2a504462012-02-28 18:55:2249 GetUsageAndQuotaThenRunTask(
[email protected]949f25a2012-06-27 01:53:0950 url,
[email protected]61b48e02013-08-01 15:00:1051 base::Bind(&FileSystemOperationImpl::DoCreateFile,
[email protected]c420e4c2013-08-28 06:28:3752 weak_factory_.GetWeakPtr(), url, callback, exclusive),
[email protected]141bcc52014-01-27 21:36:0053 base::Bind(callback, base::File::FILE_ERROR_FAILED));
[email protected]ffac1ac42011-07-25 15:03:1554}
55
[email protected]61b48e02013-08-01 15:00:1056void FileSystemOperationImpl::CreateDirectory(const FileSystemURL& url,
57 bool exclusive,
58 bool recursive,
59 const StatusCallback& callback) {
[email protected]f7fdd4d2012-02-16 11:32:4560 DCHECK(SetPendingOperationType(kOperationCreateDirectory));
[email protected]2a504462012-02-28 18:55:2261 GetUsageAndQuotaThenRunTask(
[email protected]949f25a2012-06-27 01:53:0962 url,
[email protected]61b48e02013-08-01 15:00:1063 base::Bind(&FileSystemOperationImpl::DoCreateDirectory,
[email protected]c420e4c2013-08-28 06:28:3764 weak_factory_.GetWeakPtr(), url, callback,
65 exclusive, recursive),
[email protected]141bcc52014-01-27 21:36:0066 base::Bind(callback, base::File::FILE_ERROR_FAILED));
[email protected]ffac1ac42011-07-25 15:03:1567}
68
[email protected]af349562013-09-09 14:18:5369void FileSystemOperationImpl::Copy(
70 const FileSystemURL& src_url,
71 const FileSystemURL& dest_url,
[email protected]824d3892013-09-25 13:00:3072 CopyOrMoveOption option,
[email protected]af349562013-09-09 14:18:5373 const CopyProgressCallback& progress_callback,
74 const StatusCallback& callback) {
[email protected]f7fdd4d2012-02-16 11:32:4575 DCHECK(SetPendingOperationType(kOperationCopy));
[email protected]aeba9c12013-01-28 10:44:4276 DCHECK(!recursive_operation_delegate_);
[email protected]af349562013-09-09 14:18:5377
78 // TODO(hidehiko): Support |progress_callback|. (crbug.com/278038).
[email protected]aeba9c12013-01-28 10:44:4279 recursive_operation_delegate_.reset(
[email protected]f17d6a12013-06-04 06:57:0780 new CopyOrMoveOperationDelegate(
[email protected]a85efc32013-03-04 10:45:5181 file_system_context(),
[email protected]a85efc32013-03-04 10:45:5182 src_url, dest_url,
[email protected]f17d6a12013-06-04 06:57:0783 CopyOrMoveOperationDelegate::OPERATION_COPY,
[email protected]824d3892013-09-25 13:00:3084 option,
[email protected]b2ef40c2013-09-12 13:07:4285 progress_callback,
[email protected]61b48e02013-08-01 15:00:1086 base::Bind(&FileSystemOperationImpl::DidFinishOperation,
[email protected]c420e4c2013-08-28 06:28:3787 weak_factory_.GetWeakPtr(), callback)));
[email protected]aeba9c12013-01-28 10:44:4288 recursive_operation_delegate_->RunRecursively();
[email protected]b97b5d32011-05-10 11:20:5689}
90
[email protected]61b48e02013-08-01 15:00:1091void FileSystemOperationImpl::Move(const FileSystemURL& src_url,
92 const FileSystemURL& dest_url,
[email protected]824d3892013-09-25 13:00:3093 CopyOrMoveOption option,
[email protected]61b48e02013-08-01 15:00:1094 const StatusCallback& callback) {
[email protected]f7fdd4d2012-02-16 11:32:4595 DCHECK(SetPendingOperationType(kOperationMove));
[email protected]aeba9c12013-01-28 10:44:4296 DCHECK(!recursive_operation_delegate_);
97 recursive_operation_delegate_.reset(
[email protected]f17d6a12013-06-04 06:57:0798 new CopyOrMoveOperationDelegate(
[email protected]a85efc32013-03-04 10:45:5199 file_system_context(),
[email protected]a85efc32013-03-04 10:45:51100 src_url, dest_url,
[email protected]f17d6a12013-06-04 06:57:07101 CopyOrMoveOperationDelegate::OPERATION_MOVE,
[email protected]824d3892013-09-25 13:00:30102 option,
[email protected]b2ef40c2013-09-12 13:07:42103 FileSystemOperation::CopyProgressCallback(),
[email protected]61b48e02013-08-01 15:00:10104 base::Bind(&FileSystemOperationImpl::DidFinishOperation,
[email protected]c420e4c2013-08-28 06:28:37105 weak_factory_.GetWeakPtr(), callback)));
[email protected]aeba9c12013-01-28 10:44:42106 recursive_operation_delegate_->RunRecursively();
[email protected]b97b5d32011-05-10 11:20:56107}
108
[email protected]61b48e02013-08-01 15:00:10109void FileSystemOperationImpl::DirectoryExists(const FileSystemURL& url,
110 const StatusCallback& callback) {
[email protected]f7fdd4d2012-02-16 11:32:45111 DCHECK(SetPendingOperationType(kOperationDirectoryExists));
[email protected]25b697992013-01-29 07:10:05112 async_file_util_->GetFileInfo(
[email protected]2c02c8d2013-06-10 17:52:43113 operation_context_.Pass(), url,
[email protected]61b48e02013-08-01 15:00:10114 base::Bind(&FileSystemOperationImpl::DidDirectoryExists,
[email protected]c420e4c2013-08-28 06:28:37115 weak_factory_.GetWeakPtr(), callback));
[email protected]f05ca652010-09-16 04:46:14116}
117
[email protected]61b48e02013-08-01 15:00:10118void FileSystemOperationImpl::FileExists(const FileSystemURL& url,
119 const StatusCallback& callback) {
[email protected]f7fdd4d2012-02-16 11:32:45120 DCHECK(SetPendingOperationType(kOperationFileExists));
[email protected]25b697992013-01-29 07:10:05121 async_file_util_->GetFileInfo(
[email protected]2c02c8d2013-06-10 17:52:43122 operation_context_.Pass(), url,
[email protected]61b48e02013-08-01 15:00:10123 base::Bind(&FileSystemOperationImpl::DidFileExists,
[email protected]c420e4c2013-08-28 06:28:37124 weak_factory_.GetWeakPtr(), callback));
[email protected]f05ca652010-09-16 04:46:14125}
126
[email protected]61b48e02013-08-01 15:00:10127void FileSystemOperationImpl::GetMetadata(
[email protected]02a60542012-07-24 20:05:33128 const FileSystemURL& url, const GetMetadataCallback& callback) {
[email protected]f7fdd4d2012-02-16 11:32:45129 DCHECK(SetPendingOperationType(kOperationGetMetadata));
[email protected]2c02c8d2013-06-10 17:52:43130 async_file_util_->GetFileInfo(operation_context_.Pass(), url, callback);
[email protected]f05ca652010-09-16 04:46:14131}
132
[email protected]61b48e02013-08-01 15:00:10133void FileSystemOperationImpl::ReadDirectory(
[email protected]02a60542012-07-24 20:05:33134 const FileSystemURL& url, const ReadDirectoryCallback& callback) {
[email protected]f7fdd4d2012-02-16 11:32:45135 DCHECK(SetPendingOperationType(kOperationReadDirectory));
[email protected]25b697992013-01-29 07:10:05136 async_file_util_->ReadDirectory(
[email protected]2c02c8d2013-06-10 17:52:43137 operation_context_.Pass(), url, callback);
[email protected]f05ca652010-09-16 04:46:14138}
139
[email protected]61b48e02013-08-01 15:00:10140void FileSystemOperationImpl::Remove(const FileSystemURL& url,
141 bool recursive,
142 const StatusCallback& callback) {
[email protected]f7fdd4d2012-02-16 11:32:45143 DCHECK(SetPendingOperationType(kOperationRemove));
[email protected]aeba9c12013-01-28 10:44:42144 DCHECK(!recursive_operation_delegate_);
[email protected]ef1cc9f2013-07-01 20:15:36145
146 if (recursive) {
147 // For recursive removal, try to delegate the operation to AsyncFileUtil
148 // first. If not supported, it is delegated to RemoveOperationDelegate
149 // in DidDeleteRecursively.
150 async_file_util_->DeleteRecursively(
151 operation_context_.Pass(), url,
[email protected]61b48e02013-08-01 15:00:10152 base::Bind(&FileSystemOperationImpl::DidDeleteRecursively,
[email protected]c420e4c2013-08-28 06:28:37153 weak_factory_.GetWeakPtr(), url, callback));
[email protected]ef1cc9f2013-07-01 20:15:36154 return;
155 }
156
[email protected]aeba9c12013-01-28 10:44:42157 recursive_operation_delegate_.reset(
158 new RemoveOperationDelegate(
[email protected]3c631b22013-06-05 16:13:34159 file_system_context(), url,
[email protected]61b48e02013-08-01 15:00:10160 base::Bind(&FileSystemOperationImpl::DidFinishOperation,
[email protected]c420e4c2013-08-28 06:28:37161 weak_factory_.GetWeakPtr(), callback)));
[email protected]ef1cc9f2013-07-01 20:15:36162 recursive_operation_delegate_->Run();
[email protected]f05ca652010-09-16 04:46:14163}
164
[email protected]61b48e02013-08-01 15:00:10165void FileSystemOperationImpl::Write(
[email protected]949f25a2012-06-27 01:53:09166 const FileSystemURL& url,
[email protected]1a6e3902013-06-13 07:09:40167 scoped_ptr<FileWriterDelegate> writer_delegate,
168 scoped_ptr<net::URLRequest> blob_request,
[email protected]81f8a3d2012-02-14 08:40:37169 const WriteCallback& callback) {
[email protected]1a6e3902013-06-13 07:09:40170 DCHECK(SetPendingOperationType(kOperationWrite));
171 file_writer_delegate_ = writer_delegate.Pass();
172 file_writer_delegate_->Start(
173 blob_request.Pass(),
[email protected]c420e4c2013-08-28 06:28:37174 base::Bind(&FileSystemOperationImpl::DidWrite,
175 weak_factory_.GetWeakPtr(), url, callback));
[email protected]b97b5d32011-05-10 11:20:56176}
177
[email protected]61b48e02013-08-01 15:00:10178void FileSystemOperationImpl::Truncate(const FileSystemURL& url, int64 length,
179 const StatusCallback& callback) {
[email protected]f7fdd4d2012-02-16 11:32:45180 DCHECK(SetPendingOperationType(kOperationTruncate));
[email protected]2a504462012-02-28 18:55:22181 GetUsageAndQuotaThenRunTask(
[email protected]949f25a2012-06-27 01:53:09182 url,
[email protected]61b48e02013-08-01 15:00:10183 base::Bind(&FileSystemOperationImpl::DoTruncate,
[email protected]c420e4c2013-08-28 06:28:37184 weak_factory_.GetWeakPtr(), url, callback, length),
[email protected]141bcc52014-01-27 21:36:00185 base::Bind(callback, base::File::FILE_ERROR_FAILED));
[email protected]b97b5d32011-05-10 11:20:56186}
187
[email protected]61b48e02013-08-01 15:00:10188void FileSystemOperationImpl::TouchFile(const FileSystemURL& url,
189 const base::Time& last_access_time,
190 const base::Time& last_modified_time,
191 const StatusCallback& callback) {
[email protected]f7fdd4d2012-02-16 11:32:45192 DCHECK(SetPendingOperationType(kOperationTouchFile));
[email protected]25b697992013-01-29 07:10:05193 async_file_util_->Touch(
[email protected]2c02c8d2013-06-10 17:52:43194 operation_context_.Pass(), url,
[email protected]65c337e02012-02-29 04:31:10195 last_access_time, last_modified_time,
[email protected]61b48e02013-08-01 15:00:10196 base::Bind(&FileSystemOperationImpl::DidFinishOperation,
[email protected]c420e4c2013-08-28 06:28:37197 weak_factory_.GetWeakPtr(), callback));
[email protected]ed7ae172010-09-27 21:22:01198}
199
[email protected]61b48e02013-08-01 15:00:10200void FileSystemOperationImpl::OpenFile(const FileSystemURL& url,
201 int file_flags,
[email protected]61b48e02013-08-01 15:00:10202 const OpenFileCallback& callback) {
[email protected]f7fdd4d2012-02-16 11:32:45203 DCHECK(SetPendingOperationType(kOperationOpenFile));
[email protected]49b67d22011-10-26 11:18:26204
[email protected]45d5c602013-10-07 18:33:22205 if (file_flags &
206 (base::PLATFORM_FILE_TEMPORARY | base::PLATFORM_FILE_HIDDEN)) {
[email protected]141bcc52014-01-27 21:36:00207 callback.Run(base::File::FILE_ERROR_FAILED,
[email protected]1aa9e15d2013-04-26 13:51:20208 base::kInvalidPlatformFileValue,
[email protected]10c39222013-11-13 20:09:25209 base::Closure());
[email protected]07c3d212011-04-16 00:02:53210 return;
211 }
[email protected]2a504462012-02-28 18:55:22212 GetUsageAndQuotaThenRunTask(
[email protected]949f25a2012-06-27 01:53:09213 url,
[email protected]61b48e02013-08-01 15:00:10214 base::Bind(&FileSystemOperationImpl::DoOpenFile,
[email protected]c420e4c2013-08-28 06:28:37215 weak_factory_.GetWeakPtr(),
[email protected]949f25a2012-06-27 01:53:09216 url, callback, file_flags),
[email protected]141bcc52014-01-27 21:36:00217 base::Bind(callback, base::File::FILE_ERROR_FAILED,
[email protected]2a504462012-02-28 18:55:22218 base::kInvalidPlatformFileValue,
[email protected]10c39222013-11-13 20:09:25219 base::Closure()));
[email protected]ffac1ac42011-07-25 15:03:15220}
221
[email protected]7eb68a22010-10-05 02:26:47222// We can only get here on a write or truncate that's not yet completed.
223// We don't support cancelling any other operation at this time.
[email protected]61b48e02013-08-01 15:00:10224void FileSystemOperationImpl::Cancel(const StatusCallback& cancel_callback) {
[email protected]2c02c8d2013-06-10 17:52:43225 DCHECK(cancel_callback_.is_null());
226 cancel_callback_ = cancel_callback;
227
228 if (file_writer_delegate_.get()) {
[email protected]f7fdd4d2012-02-16 11:32:45229 DCHECK_EQ(kOperationWrite, pending_operation_);
[email protected]2c02c8d2013-06-10 17:52:43230 // This will call DidWrite() with ABORT status code.
231 file_writer_delegate_->Cancel();
[email protected]4f976f7612013-09-13 15:51:27232 } else if (recursive_operation_delegate_) {
233 // This will call DidFinishOperation() with ABORT status code.
234 recursive_operation_delegate_->Cancel();
[email protected]bd152382010-10-07 23:24:38235 } else {
[email protected]2c02c8d2013-06-10 17:52:43236 // For truncate we have no way to cancel the inflight operation (for now).
237 // Let it just run and dispatch cancel callback later.
[email protected]f7fdd4d2012-02-16 11:32:45238 DCHECK_EQ(kOperationTruncate, pending_operation_);
[email protected]bd152382010-10-07 23:24:38239 }
[email protected]ac716262010-09-24 01:06:00240}
241
[email protected]61b48e02013-08-01 15:00:10242void FileSystemOperationImpl::CreateSnapshotFile(
[email protected]949f25a2012-06-27 01:53:09243 const FileSystemURL& url,
[email protected]47373872012-02-28 06:27:30244 const SnapshotFileCallback& callback) {
[email protected]d0a1f0372012-07-19 11:17:37245 DCHECK(SetPendingOperationType(kOperationCreateSnapshotFile));
[email protected]25b697992013-01-29 07:10:05246 async_file_util_->CreateSnapshotFile(
[email protected]2c02c8d2013-06-10 17:52:43247 operation_context_.Pass(), url, callback);
[email protected]47373872012-02-28 06:27:30248}
249
[email protected]61b48e02013-08-01 15:00:10250void FileSystemOperationImpl::CopyInForeignFile(
[email protected]a3ef4832013-02-02 05:12:33251 const base::FilePath& src_local_disk_file_path,
[email protected]d9543892012-10-12 06:49:56252 const FileSystemURL& dest_url,
253 const StatusCallback& callback) {
254 DCHECK(SetPendingOperationType(kOperationCopyInForeignFile));
[email protected]d9543892012-10-12 06:49:56255 GetUsageAndQuotaThenRunTask(
256 dest_url,
[email protected]61b48e02013-08-01 15:00:10257 base::Bind(&FileSystemOperationImpl::DoCopyInForeignFile,
[email protected]c420e4c2013-08-28 06:28:37258 weak_factory_.GetWeakPtr(), src_local_disk_file_path, dest_url,
[email protected]d9543892012-10-12 06:49:56259 callback),
[email protected]141bcc52014-01-27 21:36:00260 base::Bind(callback, base::File::FILE_ERROR_FAILED));
[email protected]d9543892012-10-12 06:49:56261}
262
[email protected]61b48e02013-08-01 15:00:10263void FileSystemOperationImpl::RemoveFile(
[email protected]92b808802013-01-28 05:10:51264 const FileSystemURL& url,
265 const StatusCallback& callback) {
266 DCHECK(SetPendingOperationType(kOperationRemove));
[email protected]25b697992013-01-29 07:10:05267 async_file_util_->DeleteFile(
[email protected]2c02c8d2013-06-10 17:52:43268 operation_context_.Pass(), url,
[email protected]61b48e02013-08-01 15:00:10269 base::Bind(&FileSystemOperationImpl::DidFinishOperation,
[email protected]c420e4c2013-08-28 06:28:37270 weak_factory_.GetWeakPtr(), callback));
[email protected]92b808802013-01-28 05:10:51271}
272
[email protected]61b48e02013-08-01 15:00:10273void FileSystemOperationImpl::RemoveDirectory(
[email protected]92b808802013-01-28 05:10:51274 const FileSystemURL& url,
275 const StatusCallback& callback) {
276 DCHECK(SetPendingOperationType(kOperationRemove));
[email protected]25b697992013-01-29 07:10:05277 async_file_util_->DeleteDirectory(
[email protected]2c02c8d2013-06-10 17:52:43278 operation_context_.Pass(), url,
[email protected]61b48e02013-08-01 15:00:10279 base::Bind(&FileSystemOperationImpl::DidFinishOperation,
[email protected]c420e4c2013-08-28 06:28:37280 weak_factory_.GetWeakPtr(), callback));
[email protected]92b808802013-01-28 05:10:51281}
282
[email protected]61b48e02013-08-01 15:00:10283void FileSystemOperationImpl::CopyFileLocal(
[email protected]aeba9c12013-01-28 10:44:42284 const FileSystemURL& src_url,
285 const FileSystemURL& dest_url,
[email protected]824d3892013-09-25 13:00:30286 CopyOrMoveOption option,
[email protected]af349562013-09-09 14:18:53287 const CopyFileProgressCallback& progress_callback,
[email protected]aeba9c12013-01-28 10:44:42288 const StatusCallback& callback) {
289 DCHECK(SetPendingOperationType(kOperationCopy));
[email protected]4c413de02013-05-27 06:00:59290 DCHECK(src_url.IsInSameFileSystem(dest_url));
[email protected]af349562013-09-09 14:18:53291
[email protected]aeba9c12013-01-28 10:44:42292 GetUsageAndQuotaThenRunTask(
293 dest_url,
[email protected]61b48e02013-08-01 15:00:10294 base::Bind(&FileSystemOperationImpl::DoCopyFileLocal,
[email protected]824d3892013-09-25 13:00:30295 weak_factory_.GetWeakPtr(), src_url, dest_url, option,
[email protected]9ebe87902013-09-12 01:31:56296 progress_callback, callback),
[email protected]141bcc52014-01-27 21:36:00297 base::Bind(callback, base::File::FILE_ERROR_FAILED));
[email protected]aeba9c12013-01-28 10:44:42298}
299
[email protected]61b48e02013-08-01 15:00:10300void FileSystemOperationImpl::MoveFileLocal(
[email protected]aeba9c12013-01-28 10:44:42301 const FileSystemURL& src_url,
302 const FileSystemURL& dest_url,
[email protected]824d3892013-09-25 13:00:30303 CopyOrMoveOption option,
[email protected]aeba9c12013-01-28 10:44:42304 const StatusCallback& callback) {
305 DCHECK(SetPendingOperationType(kOperationMove));
[email protected]4c413de02013-05-27 06:00:59306 DCHECK(src_url.IsInSameFileSystem(dest_url));
[email protected]aeba9c12013-01-28 10:44:42307 GetUsageAndQuotaThenRunTask(
308 dest_url,
[email protected]61b48e02013-08-01 15:00:10309 base::Bind(&FileSystemOperationImpl::DoMoveFileLocal,
[email protected]824d3892013-09-25 13:00:30310 weak_factory_.GetWeakPtr(),
311 src_url, dest_url, option, callback),
[email protected]141bcc52014-01-27 21:36:00312 base::Bind(callback, base::File::FILE_ERROR_FAILED));
[email protected]aeba9c12013-01-28 10:44:42313}
314
[email protected]141bcc52014-01-27 21:36:00315base::File::Error FileSystemOperationImpl::SyncGetPlatformPath(
[email protected]5d4d7a62013-08-27 07:43:31316 const FileSystemURL& url,
317 base::FilePath* platform_path) {
318 DCHECK(SetPendingOperationType(kOperationGetLocalPath));
[email protected]57acf8a2013-08-30 00:06:47319 if (!file_system_context()->IsSandboxFileSystem(url.type()))
[email protected]141bcc52014-01-27 21:36:00320 return base::File::FILE_ERROR_INVALID_OPERATION;
[email protected]57acf8a2013-08-30 00:06:47321 FileSystemFileUtil* file_util =
322 file_system_context()->sandbox_delegate()->sync_file_util();
[email protected]5d4d7a62013-08-27 07:43:31323 file_util->GetLocalFilePath(operation_context_.get(), url, platform_path);
[email protected]141bcc52014-01-27 21:36:00324 return base::File::FILE_OK;
[email protected]5d4d7a62013-08-27 07:43:31325}
326
[email protected]bd69f572013-09-09 06:15:23327FileSystemOperationImpl::FileSystemOperationImpl(
328 const FileSystemURL& url,
329 FileSystemContext* file_system_context,
330 scoped_ptr<FileSystemOperationContext> operation_context)
331 : file_system_context_(file_system_context),
332 operation_context_(operation_context.Pass()),
333 async_file_util_(NULL),
[email protected]bd69f572013-09-09 06:15:23334 pending_operation_(kOperationNone),
335 weak_factory_(this) {
336 DCHECK(operation_context_.get());
337 operation_context_->DetachUserDataThread();
338 async_file_util_ = file_system_context_->GetAsyncFileUtil(url.type());
339 DCHECK(async_file_util_);
340}
341
[email protected]61b48e02013-08-01 15:00:10342void FileSystemOperationImpl::GetUsageAndQuotaThenRunTask(
[email protected]949f25a2012-06-27 01:53:09343 const FileSystemURL& url,
[email protected]2a504462012-02-28 18:55:22344 const base::Closure& task,
345 const base::Closure& error_callback) {
[email protected]b97b5d32011-05-10 11:20:56346 quota::QuotaManagerProxy* quota_manager_proxy =
347 file_system_context()->quota_manager_proxy();
[email protected]81484d72011-09-20 07:21:07348 if (!quota_manager_proxy ||
[email protected]949f25a2012-06-27 01:53:09349 !file_system_context()->GetQuotaUtil(url.type())) {
[email protected]81484d72011-09-20 07:21:07350 // If we don't have the quota manager or the requested filesystem type
351 // does not support quota, we should be able to let it go.
[email protected]2c02c8d2013-06-10 17:52:43352 operation_context_->set_allowed_bytes_growth(kint64max);
[email protected]2a504462012-02-28 18:55:22353 task.Run();
[email protected]81484d72011-09-20 07:21:07354 return;
[email protected]b97b5d32011-05-10 11:20:56355 }
[email protected]2a504462012-02-28 18:55:22356
[email protected]81484d72011-09-20 07:21:07357 DCHECK(quota_manager_proxy);
358 DCHECK(quota_manager_proxy->quota_manager());
359 quota_manager_proxy->quota_manager()->GetUsageAndQuota(
[email protected]949f25a2012-06-27 01:53:09360 url.origin(),
361 FileSystemTypeToQuotaStorageType(url.type()),
[email protected]61b48e02013-08-01 15:00:10362 base::Bind(&FileSystemOperationImpl::DidGetUsageAndQuotaAndRunTask,
[email protected]c420e4c2013-08-28 06:28:37363 weak_factory_.GetWeakPtr(), task, error_callback));
[email protected]b97b5d32011-05-10 11:20:56364}
365
[email protected]61b48e02013-08-01 15:00:10366void FileSystemOperationImpl::DidGetUsageAndQuotaAndRunTask(
[email protected]caf66702012-09-07 07:02:20367 const base::Closure& task,
368 const base::Closure& error_callback,
[email protected]2a504462012-02-28 18:55:22369 quota::QuotaStatusCode status,
370 int64 usage, int64 quota) {
371 if (status != quota::kQuotaStatusOk) {
372 LOG(WARNING) << "Got unexpected quota error : " << status;
[email protected]caf66702012-09-07 07:02:20373 error_callback.Run();
[email protected]2a504462012-02-28 18:55:22374 return;
375 }
376
[email protected]2c02c8d2013-06-10 17:52:43377 operation_context_->set_allowed_bytes_growth(quota - usage);
[email protected]caf66702012-09-07 07:02:20378 task.Run();
[email protected]2a504462012-02-28 18:55:22379}
380
[email protected]61b48e02013-08-01 15:00:10381void FileSystemOperationImpl::DoCreateFile(
[email protected]949f25a2012-06-27 01:53:09382 const FileSystemURL& url,
[email protected]2a504462012-02-28 18:55:22383 const StatusCallback& callback,
384 bool exclusive) {
[email protected]25b697992013-01-29 07:10:05385 async_file_util_->EnsureFileExists(
[email protected]2c02c8d2013-06-10 17:52:43386 operation_context_.Pass(), url,
[email protected]787a399e2012-02-28 01:05:54387 base::Bind(
[email protected]02a60542012-07-24 20:05:33388 exclusive ?
[email protected]61b48e02013-08-01 15:00:10389 &FileSystemOperationImpl::DidEnsureFileExistsExclusive :
390 &FileSystemOperationImpl::DidEnsureFileExistsNonExclusive,
[email protected]c420e4c2013-08-28 06:28:37391 weak_factory_.GetWeakPtr(), callback));
[email protected]787a399e2012-02-28 01:05:54392}
393
[email protected]61b48e02013-08-01 15:00:10394void FileSystemOperationImpl::DoCreateDirectory(
[email protected]949f25a2012-06-27 01:53:09395 const FileSystemURL& url,
[email protected]787a399e2012-02-28 01:05:54396 const StatusCallback& callback,
[email protected]2a504462012-02-28 18:55:22397 bool exclusive, bool recursive) {
[email protected]25b697992013-01-29 07:10:05398 async_file_util_->CreateDirectory(
[email protected]2c02c8d2013-06-10 17:52:43399 operation_context_.Pass(),
[email protected]25b697992013-01-29 07:10:05400 url, exclusive, recursive,
[email protected]61b48e02013-08-01 15:00:10401 base::Bind(&FileSystemOperationImpl::DidFinishOperation,
[email protected]c420e4c2013-08-28 06:28:37402 weak_factory_.GetWeakPtr(), callback));
[email protected]787a399e2012-02-28 01:05:54403}
404
[email protected]61b48e02013-08-01 15:00:10405void FileSystemOperationImpl::DoCopyFileLocal(
[email protected]aeba9c12013-01-28 10:44:42406 const FileSystemURL& src_url,
407 const FileSystemURL& dest_url,
[email protected]824d3892013-09-25 13:00:30408 CopyOrMoveOption option,
[email protected]9ebe87902013-09-12 01:31:56409 const CopyFileProgressCallback& progress_callback,
[email protected]aeba9c12013-01-28 10:44:42410 const StatusCallback& callback) {
[email protected]25b697992013-01-29 07:10:05411 async_file_util_->CopyFileLocal(
[email protected]824d3892013-09-25 13:00:30412 operation_context_.Pass(), src_url, dest_url, option, progress_callback,
[email protected]61b48e02013-08-01 15:00:10413 base::Bind(&FileSystemOperationImpl::DidFinishOperation,
[email protected]c420e4c2013-08-28 06:28:37414 weak_factory_.GetWeakPtr(), callback));
[email protected]aeba9c12013-01-28 10:44:42415}
416
[email protected]61b48e02013-08-01 15:00:10417void FileSystemOperationImpl::DoMoveFileLocal(
[email protected]aeba9c12013-01-28 10:44:42418 const FileSystemURL& src_url,
419 const FileSystemURL& dest_url,
[email protected]824d3892013-09-25 13:00:30420 CopyOrMoveOption option,
[email protected]aeba9c12013-01-28 10:44:42421 const StatusCallback& callback) {
[email protected]25b697992013-01-29 07:10:05422 async_file_util_->MoveFileLocal(
[email protected]824d3892013-09-25 13:00:30423 operation_context_.Pass(), src_url, dest_url, option,
[email protected]61b48e02013-08-01 15:00:10424 base::Bind(&FileSystemOperationImpl::DidFinishOperation,
[email protected]c420e4c2013-08-28 06:28:37425 weak_factory_.GetWeakPtr(), callback));
[email protected]787a399e2012-02-28 01:05:54426}
427
[email protected]61b48e02013-08-01 15:00:10428void FileSystemOperationImpl::DoCopyInForeignFile(
[email protected]a3ef4832013-02-02 05:12:33429 const base::FilePath& src_local_disk_file_path,
[email protected]dd684562012-09-14 04:30:02430 const FileSystemURL& dest_url,
431 const StatusCallback& callback) {
[email protected]25b697992013-01-29 07:10:05432 async_file_util_->CopyInForeignFile(
[email protected]2c02c8d2013-06-10 17:52:43433 operation_context_.Pass(),
[email protected]25b697992013-01-29 07:10:05434 src_local_disk_file_path, dest_url,
[email protected]61b48e02013-08-01 15:00:10435 base::Bind(&FileSystemOperationImpl::DidFinishOperation,
[email protected]c420e4c2013-08-28 06:28:37436 weak_factory_.GetWeakPtr(), callback));
[email protected]787a399e2012-02-28 01:05:54437}
438
[email protected]61b48e02013-08-01 15:00:10439void FileSystemOperationImpl::DoTruncate(const FileSystemURL& url,
440 const StatusCallback& callback,
441 int64 length) {
[email protected]25b697992013-01-29 07:10:05442 async_file_util_->Truncate(
[email protected]2c02c8d2013-06-10 17:52:43443 operation_context_.Pass(), url, length,
[email protected]61b48e02013-08-01 15:00:10444 base::Bind(&FileSystemOperationImpl::DidFinishOperation,
[email protected]c420e4c2013-08-28 06:28:37445 weak_factory_.GetWeakPtr(), callback));
[email protected]787a399e2012-02-28 01:05:54446}
447
[email protected]61b48e02013-08-01 15:00:10448void FileSystemOperationImpl::DoOpenFile(const FileSystemURL& url,
449 const OpenFileCallback& callback,
450 int file_flags) {
[email protected]25b697992013-01-29 07:10:05451 async_file_util_->CreateOrOpen(
[email protected]2c02c8d2013-06-10 17:52:43452 operation_context_.Pass(), url, file_flags,
[email protected]61b48e02013-08-01 15:00:10453 base::Bind(&FileSystemOperationImpl::DidOpenFile,
[email protected]c420e4c2013-08-28 06:28:37454 weak_factory_.GetWeakPtr(), callback));
[email protected]787a399e2012-02-28 01:05:54455}
456
[email protected]61b48e02013-08-01 15:00:10457void FileSystemOperationImpl::DidEnsureFileExistsExclusive(
[email protected]81f8a3d2012-02-14 08:40:37458 const StatusCallback& callback,
[email protected]141bcc52014-01-27 21:36:00459 base::File::Error rv, bool created) {
460 if (rv == base::File::FILE_OK && !created) {
461 callback.Run(base::File::FILE_ERROR_EXISTS);
[email protected]ed514e82011-05-25 09:15:43462 } else {
[email protected]2c02c8d2013-06-10 17:52:43463 DidFinishOperation(callback, rv);
[email protected]ed514e82011-05-25 09:15:43464 }
[email protected]f05ca652010-09-16 04:46:14465}
466
[email protected]61b48e02013-08-01 15:00:10467void FileSystemOperationImpl::DidEnsureFileExistsNonExclusive(
[email protected]81f8a3d2012-02-14 08:40:37468 const StatusCallback& callback,
[email protected]141bcc52014-01-27 21:36:00469 base::File::Error rv, bool /* created */) {
[email protected]2c02c8d2013-06-10 17:52:43470 DidFinishOperation(callback, rv);
[email protected]f05ca652010-09-16 04:46:14471}
472
[email protected]61b48e02013-08-01 15:00:10473void FileSystemOperationImpl::DidFinishOperation(
[email protected]81f8a3d2012-02-14 08:40:37474 const StatusCallback& callback,
[email protected]141bcc52014-01-27 21:36:00475 base::File::Error rv) {
[email protected]81f8a3d2012-02-14 08:40:37476 if (!cancel_callback_.is_null()) {
[email protected]2c02c8d2013-06-10 17:52:43477 StatusCallback cancel_callback = cancel_callback_;
[email protected]20228942013-09-05 15:52:41478 callback.Run(rv);
479
480 // Return OK only if we succeeded to stop the operation.
[email protected]141bcc52014-01-27 21:36:00481 cancel_callback.Run(rv == base::File::FILE_ERROR_ABORT ?
482 base::File::FILE_OK :
483 base::File::FILE_ERROR_INVALID_OPERATION);
[email protected]81f8a3d2012-02-14 08:40:37484 } else {
485 callback.Run(rv);
[email protected]7eb68a22010-10-05 02:26:47486 }
[email protected]f05ca652010-09-16 04:46:14487}
488
[email protected]61b48e02013-08-01 15:00:10489void FileSystemOperationImpl::DidDirectoryExists(
[email protected]81f8a3d2012-02-14 08:40:37490 const StatusCallback& callback,
[email protected]141bcc52014-01-27 21:36:00491 base::File::Error rv,
492 const base::File::Info& file_info) {
493 if (rv == base::File::FILE_OK && !file_info.is_directory)
494 rv = base::File::FILE_ERROR_NOT_A_DIRECTORY;
[email protected]81f8a3d2012-02-14 08:40:37495 callback.Run(rv);
[email protected]f05ca652010-09-16 04:46:14496}
497
[email protected]61b48e02013-08-01 15:00:10498void FileSystemOperationImpl::DidFileExists(
[email protected]81f8a3d2012-02-14 08:40:37499 const StatusCallback& callback,
[email protected]141bcc52014-01-27 21:36:00500 base::File::Error rv,
501 const base::File::Info& file_info) {
502 if (rv == base::File::FILE_OK && file_info.is_directory)
503 rv = base::File::FILE_ERROR_NOT_A_FILE;
[email protected]81f8a3d2012-02-14 08:40:37504 callback.Run(rv);
[email protected]f05ca652010-09-16 04:46:14505}
506
[email protected]61b48e02013-08-01 15:00:10507void FileSystemOperationImpl::DidDeleteRecursively(
[email protected]ef1cc9f2013-07-01 20:15:36508 const FileSystemURL& url,
509 const StatusCallback& callback,
[email protected]141bcc52014-01-27 21:36:00510 base::File::Error rv) {
511 if (rv == base::File::FILE_ERROR_INVALID_OPERATION) {
[email protected]ef1cc9f2013-07-01 20:15:36512 // Recursive removal is not supported on this platform.
513 DCHECK(!recursive_operation_delegate_);
514 recursive_operation_delegate_.reset(
515 new RemoveOperationDelegate(
516 file_system_context(), url,
[email protected]61b48e02013-08-01 15:00:10517 base::Bind(&FileSystemOperationImpl::DidFinishOperation,
[email protected]c420e4c2013-08-28 06:28:37518 weak_factory_.GetWeakPtr(), callback)));
[email protected]ef1cc9f2013-07-01 20:15:36519 recursive_operation_delegate_->RunRecursively();
520 return;
521 }
522
523 callback.Run(rv);
524}
525
[email protected]61b48e02013-08-01 15:00:10526void FileSystemOperationImpl::DidWrite(
[email protected]ca474482012-09-26 11:21:21527 const FileSystemURL& url,
[email protected]2c02c8d2013-06-10 17:52:43528 const WriteCallback& write_callback,
[email protected]141bcc52014-01-27 21:36:00529 base::File::Error rv,
[email protected]ac716262010-09-24 01:06:00530 int64 bytes,
[email protected]ca474482012-09-26 11:21:21531 FileWriterDelegate::WriteProgressStatus write_status) {
[email protected]ca474482012-09-26 11:21:21532 const bool complete = (
533 write_status != FileWriterDelegate::SUCCESS_IO_PENDING);
534 if (complete && write_status != FileWriterDelegate::ERROR_WRITE_NOT_STARTED) {
[email protected]2c02c8d2013-06-10 17:52:43535 DCHECK(operation_context_);
536 operation_context_->change_observers()->Notify(
[email protected]ca474482012-09-26 11:21:21537 &FileChangeObserver::OnModifyFile, MakeTuple(url));
538 }
539
[email protected]2c02c8d2013-06-10 17:52:43540 StatusCallback cancel_callback = cancel_callback_;
541 write_callback.Run(rv, bytes, complete);
542 if (!cancel_callback.is_null())
[email protected]141bcc52014-01-27 21:36:00543 cancel_callback.Run(base::File::FILE_OK);
[email protected]ed7ae172010-09-27 21:22:01544}
545
[email protected]61b48e02013-08-01 15:00:10546void FileSystemOperationImpl::DidOpenFile(
[email protected]81f8a3d2012-02-14 08:40:37547 const OpenFileCallback& callback,
[email protected]141bcc52014-01-27 21:36:00548 base::File::Error rv,
[email protected]969cbbe2013-07-10 07:55:18549 base::PassPlatformFile file,
550 const base::Closure& on_close_callback) {
[email protected]10c39222013-11-13 20:09:25551 callback.Run(rv, file.ReleaseValue(), on_close_callback);
[email protected]07c3d212011-04-16 00:02:53552}
553
[email protected]61b48e02013-08-01 15:00:10554bool FileSystemOperationImpl::SetPendingOperationType(OperationType type) {
[email protected]f7fdd4d2012-02-16 11:32:45555 if (pending_operation_ != kOperationNone)
556 return false;
557 pending_operation_ = type;
558 return true;
559}
560
[email protected]f05ca652010-09-16 04:46:14561} // namespace fileapi