| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "webkit/browser/fileapi/sandbox_file_stream_writer.h" | 5 #include "storage/browser/fileapi/sandbox_file_stream_writer.h" |
| 6 | 6 |
| 7 #include "base/files/file_util_proxy.h" | 7 #include "base/files/file_util_proxy.h" |
| 8 #include "base/sequenced_task_runner.h" | 8 #include "base/sequenced_task_runner.h" |
| 9 #include "net/base/io_buffer.h" | 9 #include "net/base/io_buffer.h" |
| 10 #include "net/base/net_errors.h" | 10 #include "net/base/net_errors.h" |
| 11 #include "webkit/browser/blob/file_stream_reader.h" | 11 #include "storage/browser/blob/file_stream_reader.h" |
| 12 #include "webkit/browser/fileapi/file_observers.h" | 12 #include "storage/browser/fileapi/file_observers.h" |
| 13 #include "webkit/browser/fileapi/file_stream_writer.h" | 13 #include "storage/browser/fileapi/file_stream_writer.h" |
| 14 #include "webkit/browser/fileapi/file_system_context.h" | 14 #include "storage/browser/fileapi/file_system_context.h" |
| 15 #include "webkit/browser/fileapi/file_system_operation_runner.h" | 15 #include "storage/browser/fileapi/file_system_operation_runner.h" |
| 16 #include "webkit/browser/quota/quota_manager_proxy.h" | 16 #include "storage/browser/quota/quota_manager_proxy.h" |
| 17 #include "webkit/common/fileapi/file_system_util.h" | 17 #include "storage/common/fileapi/file_system_util.h" |
| 18 | 18 |
| 19 namespace fileapi { | 19 namespace storage { |
| 20 | 20 |
| 21 namespace { | 21 namespace { |
| 22 | 22 |
| 23 // Adjust the |quota| value in overwriting case (i.e. |file_size| > 0 and | 23 // Adjust the |quota| value in overwriting case (i.e. |file_size| > 0 and |
| 24 // |file_offset| < |file_size|) to make the remaining quota calculation easier. | 24 // |file_offset| < |file_size|) to make the remaining quota calculation easier. |
| 25 // Specifically this widens the quota for overlapping range (so that we can | 25 // Specifically this widens the quota for overlapping range (so that we can |
| 26 // simply compare written bytes against the adjusted quota). | 26 // simply compare written bytes against the adjusted quota). |
| 27 int64 AdjustQuotaForOverlap(int64 quota, | 27 int64 AdjustQuotaForOverlap(int64 quota, int64 file_offset, int64 file_size) { |
| 28 int64 file_offset, | |
| 29 int64 file_size) { | |
| 30 DCHECK_LE(file_offset, file_size); | 28 DCHECK_LE(file_offset, file_size); |
| 31 if (quota < 0) | 29 if (quota < 0) |
| 32 quota = 0; | 30 quota = 0; |
| 33 int64 overlap = file_size - file_offset; | 31 int64 overlap = file_size - file_offset; |
| 34 if (kint64max - overlap > quota) | 32 if (kint64max - overlap > quota) |
| 35 quota += overlap; | 33 quota += overlap; |
| 36 return quota; | 34 return quota; |
| 37 } | 35 } |
| 38 | 36 |
| 39 } // namespace | 37 } // namespace |
| 40 | 38 |
| 41 SandboxFileStreamWriter::SandboxFileStreamWriter( | 39 SandboxFileStreamWriter::SandboxFileStreamWriter( |
| 42 FileSystemContext* file_system_context, | 40 FileSystemContext* file_system_context, |
| 43 const FileSystemURL& url, | 41 const FileSystemURL& url, |
| 44 int64 initial_offset, | 42 int64 initial_offset, |
| 45 const UpdateObserverList& observers) | 43 const UpdateObserverList& observers) |
| 46 : file_system_context_(file_system_context), | 44 : file_system_context_(file_system_context), |
| 47 url_(url), | 45 url_(url), |
| 48 initial_offset_(initial_offset), | 46 initial_offset_(initial_offset), |
| 49 observers_(observers), | 47 observers_(observers), |
| 50 file_size_(0), | 48 file_size_(0), |
| 51 total_bytes_written_(0), | 49 total_bytes_written_(0), |
| 52 allowed_bytes_to_write_(0), | 50 allowed_bytes_to_write_(0), |
| 53 has_pending_operation_(false), | 51 has_pending_operation_(false), |
| 54 default_quota_(kint64max), | 52 default_quota_(kint64max), |
| 55 weak_factory_(this) { | 53 weak_factory_(this) { |
| 56 DCHECK(url_.is_valid()); | 54 DCHECK(url_.is_valid()); |
| 57 } | 55 } |
| 58 | 56 |
| 59 SandboxFileStreamWriter::~SandboxFileStreamWriter() {} | 57 SandboxFileStreamWriter::~SandboxFileStreamWriter() { |
| 58 } |
| 60 | 59 |
| 61 int SandboxFileStreamWriter::Write( | 60 int SandboxFileStreamWriter::Write(net::IOBuffer* buf, |
| 62 net::IOBuffer* buf, int buf_len, | 61 int buf_len, |
| 63 const net::CompletionCallback& callback) { | 62 const net::CompletionCallback& callback) { |
| 64 has_pending_operation_ = true; | 63 has_pending_operation_ = true; |
| 65 if (local_file_writer_) | 64 if (local_file_writer_) |
| 66 return WriteInternal(buf, buf_len, callback); | 65 return WriteInternal(buf, buf_len, callback); |
| 67 | 66 |
| 68 net::CompletionCallback write_task = | 67 net::CompletionCallback write_task = |
| 69 base::Bind(&SandboxFileStreamWriter::DidInitializeForWrite, | 68 base::Bind(&SandboxFileStreamWriter::DidInitializeForWrite, |
| 70 weak_factory_.GetWeakPtr(), | 69 weak_factory_.GetWeakPtr(), |
| 71 make_scoped_refptr(buf), buf_len, callback); | 70 make_scoped_refptr(buf), |
| 71 buf_len, |
| 72 callback); |
| 72 file_system_context_->operation_runner()->CreateSnapshotFile( | 73 file_system_context_->operation_runner()->CreateSnapshotFile( |
| 73 url_, base::Bind(&SandboxFileStreamWriter::DidCreateSnapshotFile, | 74 url_, |
| 74 weak_factory_.GetWeakPtr(), write_task)); | 75 base::Bind(&SandboxFileStreamWriter::DidCreateSnapshotFile, |
| 76 weak_factory_.GetWeakPtr(), |
| 77 write_task)); |
| 75 return net::ERR_IO_PENDING; | 78 return net::ERR_IO_PENDING; |
| 76 } | 79 } |
| 77 | 80 |
| 78 int SandboxFileStreamWriter::Cancel(const net::CompletionCallback& callback) { | 81 int SandboxFileStreamWriter::Cancel(const net::CompletionCallback& callback) { |
| 79 if (!has_pending_operation_) | 82 if (!has_pending_operation_) |
| 80 return net::ERR_UNEXPECTED; | 83 return net::ERR_UNEXPECTED; |
| 81 | 84 |
| 82 DCHECK(!callback.is_null()); | 85 DCHECK(!callback.is_null()); |
| 83 cancel_callback_ = callback; | 86 cancel_callback_ = callback; |
| 84 return net::ERR_IO_PENDING; | 87 return net::ERR_IO_PENDING; |
| 85 } | 88 } |
| 86 | 89 |
| 87 int SandboxFileStreamWriter::WriteInternal( | 90 int SandboxFileStreamWriter::WriteInternal( |
| 88 net::IOBuffer* buf, int buf_len, | 91 net::IOBuffer* buf, |
| 92 int buf_len, |
| 89 const net::CompletionCallback& callback) { | 93 const net::CompletionCallback& callback) { |
| 90 // allowed_bytes_to_write could be negative if the file size is | 94 // allowed_bytes_to_write could be negative if the file size is |
| 91 // greater than the current (possibly new) quota. | 95 // greater than the current (possibly new) quota. |
| 92 DCHECK(total_bytes_written_ <= allowed_bytes_to_write_ || | 96 DCHECK(total_bytes_written_ <= allowed_bytes_to_write_ || |
| 93 allowed_bytes_to_write_ < 0); | 97 allowed_bytes_to_write_ < 0); |
| 94 if (total_bytes_written_ >= allowed_bytes_to_write_) { | 98 if (total_bytes_written_ >= allowed_bytes_to_write_) { |
| 95 has_pending_operation_ = false; | 99 has_pending_operation_ = false; |
| 96 return net::ERR_FILE_NO_SPACE; | 100 return net::ERR_FILE_NO_SPACE; |
| 97 } | 101 } |
| 98 | 102 |
| 99 if (buf_len > allowed_bytes_to_write_ - total_bytes_written_) | 103 if (buf_len > allowed_bytes_to_write_ - total_bytes_written_) |
| 100 buf_len = allowed_bytes_to_write_ - total_bytes_written_; | 104 buf_len = allowed_bytes_to_write_ - total_bytes_written_; |
| 101 | 105 |
| 102 DCHECK(local_file_writer_.get()); | 106 DCHECK(local_file_writer_.get()); |
| 103 const int result = local_file_writer_->Write( | 107 const int result = |
| 104 buf, buf_len, | 108 local_file_writer_->Write(buf, |
| 105 base::Bind(&SandboxFileStreamWriter::DidWrite, weak_factory_.GetWeakPtr(), | 109 buf_len, |
| 106 callback)); | 110 base::Bind(&SandboxFileStreamWriter::DidWrite, |
| 111 weak_factory_.GetWeakPtr(), |
| 112 callback)); |
| 107 if (result != net::ERR_IO_PENDING) | 113 if (result != net::ERR_IO_PENDING) |
| 108 has_pending_operation_ = false; | 114 has_pending_operation_ = false; |
| 109 return result; | 115 return result; |
| 110 } | 116 } |
| 111 | 117 |
| 112 void SandboxFileStreamWriter::DidCreateSnapshotFile( | 118 void SandboxFileStreamWriter::DidCreateSnapshotFile( |
| 113 const net::CompletionCallback& callback, | 119 const net::CompletionCallback& callback, |
| 114 base::File::Error file_error, | 120 base::File::Error file_error, |
| 115 const base::File::Info& file_info, | 121 const base::File::Info& file_info, |
| 116 const base::FilePath& platform_path, | 122 const base::FilePath& platform_path, |
| 117 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { | 123 const scoped_refptr<storage::ShareableFileReference>& file_ref) { |
| 118 DCHECK(!file_ref.get()); | 124 DCHECK(!file_ref.get()); |
| 119 | 125 |
| 120 if (CancelIfRequested()) | 126 if (CancelIfRequested()) |
| 121 return; | 127 return; |
| 122 if (file_error != base::File::FILE_OK) { | 128 if (file_error != base::File::FILE_OK) { |
| 123 callback.Run(net::FileErrorToNetError(file_error)); | 129 callback.Run(net::FileErrorToNetError(file_error)); |
| 124 return; | 130 return; |
| 125 } | 131 } |
| 126 if (file_info.is_directory) { | 132 if (file_info.is_directory) { |
| 127 // We should not be writing to a directory. | 133 // We should not be writing to a directory. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 150 allowed_bytes_to_write_ = default_quota_; | 156 allowed_bytes_to_write_ = default_quota_; |
| 151 callback.Run(net::OK); | 157 callback.Run(net::OK); |
| 152 return; | 158 return; |
| 153 } | 159 } |
| 154 | 160 |
| 155 DCHECK(quota_manager_proxy->quota_manager()); | 161 DCHECK(quota_manager_proxy->quota_manager()); |
| 156 quota_manager_proxy->quota_manager()->GetUsageAndQuota( | 162 quota_manager_proxy->quota_manager()->GetUsageAndQuota( |
| 157 url_.origin(), | 163 url_.origin(), |
| 158 FileSystemTypeToQuotaStorageType(url_.type()), | 164 FileSystemTypeToQuotaStorageType(url_.type()), |
| 159 base::Bind(&SandboxFileStreamWriter::DidGetUsageAndQuota, | 165 base::Bind(&SandboxFileStreamWriter::DidGetUsageAndQuota, |
| 160 weak_factory_.GetWeakPtr(), callback)); | 166 weak_factory_.GetWeakPtr(), |
| 167 callback)); |
| 161 } | 168 } |
| 162 | 169 |
| 163 void SandboxFileStreamWriter::DidGetUsageAndQuota( | 170 void SandboxFileStreamWriter::DidGetUsageAndQuota( |
| 164 const net::CompletionCallback& callback, | 171 const net::CompletionCallback& callback, |
| 165 quota::QuotaStatusCode status, | 172 quota::QuotaStatusCode status, |
| 166 int64 usage, int64 quota) { | 173 int64 usage, |
| 174 int64 quota) { |
| 167 if (CancelIfRequested()) | 175 if (CancelIfRequested()) |
| 168 return; | 176 return; |
| 169 if (status != quota::kQuotaStatusOk) { | 177 if (status != quota::kQuotaStatusOk) { |
| 170 LOG(WARNING) << "Got unexpected quota error : " << status; | 178 LOG(WARNING) << "Got unexpected quota error : " << status; |
| 171 callback.Run(net::ERR_FAILED); | 179 callback.Run(net::ERR_FAILED); |
| 172 return; | 180 return; |
| 173 } | 181 } |
| 174 | 182 |
| 175 allowed_bytes_to_write_ = quota - usage; | 183 allowed_bytes_to_write_ = quota - usage; |
| 176 callback.Run(net::OK); | 184 callback.Run(net::OK); |
| 177 } | 185 } |
| 178 | 186 |
| 179 void SandboxFileStreamWriter::DidInitializeForWrite( | 187 void SandboxFileStreamWriter::DidInitializeForWrite( |
| 180 net::IOBuffer* buf, int buf_len, | 188 net::IOBuffer* buf, |
| 189 int buf_len, |
| 181 const net::CompletionCallback& callback, | 190 const net::CompletionCallback& callback, |
| 182 int init_status) { | 191 int init_status) { |
| 183 if (CancelIfRequested()) | 192 if (CancelIfRequested()) |
| 184 return; | 193 return; |
| 185 if (init_status != net::OK) { | 194 if (init_status != net::OK) { |
| 186 has_pending_operation_ = false; | 195 has_pending_operation_ = false; |
| 187 callback.Run(init_status); | 196 callback.Run(init_status); |
| 188 return; | 197 return; |
| 189 } | 198 } |
| 190 allowed_bytes_to_write_ = AdjustQuotaForOverlap( | 199 allowed_bytes_to_write_ = AdjustQuotaForOverlap( |
| 191 allowed_bytes_to_write_, initial_offset_, file_size_); | 200 allowed_bytes_to_write_, initial_offset_, file_size_); |
| 192 const int result = WriteInternal(buf, buf_len, callback); | 201 const int result = WriteInternal(buf, buf_len, callback); |
| 193 if (result != net::ERR_IO_PENDING) | 202 if (result != net::ERR_IO_PENDING) |
| 194 callback.Run(result); | 203 callback.Run(result); |
| 195 } | 204 } |
| 196 | 205 |
| 197 void SandboxFileStreamWriter::DidWrite( | 206 void SandboxFileStreamWriter::DidWrite(const net::CompletionCallback& callback, |
| 198 const net::CompletionCallback& callback, | 207 int write_response) { |
| 199 int write_response) { | |
| 200 DCHECK(has_pending_operation_); | 208 DCHECK(has_pending_operation_); |
| 201 has_pending_operation_ = false; | 209 has_pending_operation_ = false; |
| 202 | 210 |
| 203 if (write_response <= 0) { | 211 if (write_response <= 0) { |
| 204 if (CancelIfRequested()) | 212 if (CancelIfRequested()) |
| 205 return; | 213 return; |
| 206 callback.Run(write_response); | 214 callback.Run(write_response); |
| 207 return; | 215 return; |
| 208 } | 216 } |
| 209 | 217 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 236 DCHECK(!has_pending_operation_); | 244 DCHECK(!has_pending_operation_); |
| 237 DCHECK(cancel_callback_.is_null()); | 245 DCHECK(cancel_callback_.is_null()); |
| 238 | 246 |
| 239 // Write() is not called yet, so there's nothing to flush. | 247 // Write() is not called yet, so there's nothing to flush. |
| 240 if (!local_file_writer_) | 248 if (!local_file_writer_) |
| 241 return net::OK; | 249 return net::OK; |
| 242 | 250 |
| 243 return local_file_writer_->Flush(callback); | 251 return local_file_writer_->Flush(callback); |
| 244 } | 252 } |
| 245 | 253 |
| 246 } // namespace fileapi | 254 } // namespace storage |
| OLD | NEW |