Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/plugins/ppapi/quota_file_io.h" | 5 #include "webkit/plugins/ppapi/quota_file_io.h" |
| 6 | 6 |
| 7 #include "base/stl_util.h" | 7 #include "base/stl_util.h" |
| 8 #include "base/message_loop_proxy.h" | 8 #include "base/message_loop_proxy.h" |
| 9 #include "base/task.h" | 9 #include "base/task.h" |
| 10 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | 10 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 76 } | 76 } |
| 77 virtual ~WriteOperation() {} | 77 virtual ~WriteOperation() {} |
| 78 virtual void Run() OVERRIDE { | 78 virtual void Run() OVERRIDE { |
| 79 DCHECK(quota_io_); | 79 DCHECK(quota_io_); |
| 80 if (quota_io_->CheckIfExceedsQuota(offset_ + bytes_to_write_)) { | 80 if (quota_io_->CheckIfExceedsQuota(offset_ + bytes_to_write_)) { |
| 81 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); | 81 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); |
| 82 return; | 82 return; |
| 83 } | 83 } |
| 84 if (is_will_operation_) { | 84 if (is_will_operation_) { |
| 85 // Assuming the write will succeed. | 85 // Assuming the write will succeed. |
| 86 base::MessageLoopProxy::CreateForCurrentThread()->PostTask( | 86 DidFinish(base::PLATFORM_FILE_OK, bytes_to_write_); |
| 87 FROM_HERE, runnable_factory_.NewRunnableMethod( | |
| 88 &WriteOperation::DidFinish, | |
| 89 base::PLATFORM_FILE_OK, bytes_to_write_)); | |
| 90 return; | 87 return; |
| 91 } | 88 } |
| 92 DCHECK(buffer_.get()); | 89 DCHECK(buffer_.get()); |
| 93 if (!base::FileUtilProxy::Write( | 90 if (!base::FileUtilProxy::Write( |
| 94 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), | 91 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), |
| 95 quota_io_->file_, offset_, buffer_.get(), bytes_to_write_, | 92 quota_io_->file_, offset_, buffer_.get(), bytes_to_write_, |
| 96 callback_factory_.NewCallback(&WriteOperation::DidFinish))) { | 93 callback_factory_.NewCallback(&WriteOperation::DidFinish))) { |
| 97 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 94 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
| 98 return; | 95 return; |
| 99 } | 96 } |
| 100 } | 97 } |
| 101 | 98 |
| 102 virtual void DidFail(PlatformFileError error) OVERRIDE { | 99 virtual void DidFail(PlatformFileError error) OVERRIDE { |
| 103 base::MessageLoopProxy::CreateForCurrentThread()->PostTask( | 100 DidFinish(error, 0); |
| 104 FROM_HERE, runnable_factory_.NewRunnableMethod( | |
| 105 &WriteOperation::DidFinish, error, 0)); | |
| 106 } | 101 } |
| 107 | 102 |
| 108 bool finished() const { return finished_; } | 103 bool finished() const { return finished_; } |
| 109 | 104 |
| 110 void RunCallback() { | 105 virtual void WillRunCallback() { |
| 111 DCHECK(callback_.get()); | 106 base::MessageLoopProxy::CreateForCurrentThread()->PostTask( |
| 112 callback_->Run(status_, bytes_written_); | 107 FROM_HERE, runnable_factory_.NewRunnableMethod( |
| 113 callback_.reset(); | 108 &WriteOperation::RunCallback)); |
| 114 delete this; | |
| 115 } | 109 } |
| 116 | 110 |
| 117 private: | 111 private: |
| 118 void DidFinish(PlatformFileError status, int bytes_written) { | 112 void DidFinish(PlatformFileError status, int bytes_written) { |
| 119 finished_ = true; | 113 finished_ = true; |
| 120 status_ = status; | 114 status_ = status; |
| 121 bytes_written_ = bytes_written; | 115 bytes_written_ = bytes_written; |
| 122 int64_t max_offset = | 116 int64_t max_offset = |
| 123 (status != base::PLATFORM_FILE_OK) ? 0 : offset_ + bytes_written; | 117 (status != base::PLATFORM_FILE_OK) ? 0 : offset_ + bytes_written; |
| 124 // This may delete itself by calling RunCallback. | 118 // This may delete itself by calling RunCallback. |
| 125 quota_io_->DidWrite(this, max_offset); | 119 quota_io_->DidWrite(this, max_offset); |
| 126 } | 120 } |
| 127 | 121 |
| 122 virtual void RunCallback() { | |
| 123 DCHECK(callback_.get()); | |
| 124 callback_->Run(status_, bytes_written_); | |
| 125 callback_.reset(); | |
| 126 delete this; | |
| 127 } | |
| 128 | |
| 128 const int64_t offset_; | 129 const int64_t offset_; |
| 129 scoped_array<char> buffer_; | 130 scoped_array<char> buffer_; |
| 130 const int32_t bytes_to_write_; | 131 const int32_t bytes_to_write_; |
| 131 scoped_ptr<WriteCallback> callback_; | 132 scoped_ptr<WriteCallback> callback_; |
| 132 bool finished_; | 133 bool finished_; |
| 133 PlatformFileError status_; | 134 PlatformFileError status_; |
| 134 int64_t bytes_written_; | 135 int64_t bytes_written_; |
| 135 base::ScopedCallbackFactory<QuotaFileIO::WriteOperation> callback_factory_; | 136 base::ScopedCallbackFactory<WriteOperation> callback_factory_; |
| 136 ScopedRunnableMethodFactory<QuotaFileIO::WriteOperation> runnable_factory_; | 137 ScopedRunnableMethodFactory<WriteOperation> runnable_factory_; |
| 137 }; | 138 }; |
| 138 | 139 |
| 139 class QuotaFileIO::SetLengthOperation : public PendingOperationBase { | 140 class QuotaFileIO::SetLengthOperation : public PendingOperationBase { |
| 140 public: | 141 public: |
| 141 SetLengthOperation(QuotaFileIO* quota_io, | 142 SetLengthOperation(QuotaFileIO* quota_io, |
| 142 bool is_will_operation, | 143 bool is_will_operation, |
| 143 int64_t length, | 144 int64_t length, |
| 144 StatusCallback* callback) | 145 StatusCallback* callback) |
| 145 : PendingOperationBase(quota_io, is_will_operation), | 146 : PendingOperationBase(quota_io, is_will_operation), |
| 146 length_(length), | 147 length_(length), |
| 147 callback_(callback), | 148 callback_(callback), |
| 148 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 149 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} |
| 149 runnable_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} | 150 |
| 151 protected: | |
|
yzshen1
2011/08/05 20:31:46
Is this 'protected' intended for all the methods b
kinuko
2011/08/08 11:21:12
Oops, this was a remnant of the other (reverted) c
| |
| 150 virtual ~SetLengthOperation() {} | 152 virtual ~SetLengthOperation() {} |
| 151 | 153 |
| 152 virtual void Run() OVERRIDE { | 154 virtual void Run() OVERRIDE { |
| 153 DCHECK(quota_io_); | 155 DCHECK(quota_io_); |
| 154 if (quota_io_->CheckIfExceedsQuota(length_)) { | 156 if (quota_io_->CheckIfExceedsQuota(length_)) { |
| 155 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); | 157 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); |
| 156 return; | 158 return; |
| 157 } | 159 } |
| 158 if (is_will_operation_) { | 160 if (is_will_operation_) { |
| 159 base::MessageLoopProxy::CreateForCurrentThread()->PostTask( | 161 DidFinish(base::PLATFORM_FILE_OK); |
| 160 FROM_HERE, runnable_factory_.NewRunnableMethod( | |
| 161 &SetLengthOperation::DidFinish, | |
| 162 base::PLATFORM_FILE_OK)); | |
| 163 return; | 162 return; |
| 164 } | 163 } |
| 165 if (!base::FileUtilProxy::Truncate( | 164 if (!base::FileUtilProxy::Truncate( |
| 166 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), | 165 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), |
| 167 quota_io_->file_, length_, | 166 quota_io_->file_, length_, |
| 168 callback_factory_.NewCallback(&SetLengthOperation::DidFinish))) { | 167 callback_factory_.NewCallback(&SetLengthOperation::DidFinish))) { |
| 169 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 168 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
| 170 return; | 169 return; |
| 171 } | 170 } |
| 172 } | 171 } |
| 173 | 172 |
| 174 virtual void DidFail(PlatformFileError error) OVERRIDE { | 173 virtual void DidFail(PlatformFileError error) OVERRIDE { |
| 175 base::MessageLoopProxy::CreateForCurrentThread()->PostTask( | 174 DidFinish(error); |
| 176 FROM_HERE, runnable_factory_.NewRunnableMethod( | |
| 177 &SetLengthOperation::DidFinish, error)); | |
| 178 } | 175 } |
| 179 | 176 |
| 180 private: | 177 private: |
| 181 void DidFinish(PlatformFileError status) { | 178 void DidFinish(PlatformFileError status) { |
| 182 quota_io_->DidSetLength(status, length_); | 179 quota_io_->DidSetLength(status, length_); |
| 183 DCHECK(callback_.get()); | 180 DCHECK(callback_.get()); |
| 184 callback_->Run(status); | 181 callback_->Run(status); |
| 185 callback_.reset(); | 182 callback_.reset(); |
| 186 delete this; | 183 delete this; |
| 187 } | 184 } |
| 188 | 185 |
| 189 int64_t length_; | 186 int64_t length_; |
| 190 scoped_ptr<StatusCallback> callback_; | 187 scoped_ptr<StatusCallback> callback_; |
| 191 base::ScopedCallbackFactory<QuotaFileIO::SetLengthOperation> | 188 base::ScopedCallbackFactory<SetLengthOperation> callback_factory_; |
| 192 callback_factory_; | |
| 193 ScopedRunnableMethodFactory<QuotaFileIO::SetLengthOperation> | |
| 194 runnable_factory_; | |
| 195 }; | 189 }; |
| 196 | 190 |
| 197 // QuotaFileIO -------------------------------------------------------------- | 191 // QuotaFileIO -------------------------------------------------------------- |
| 198 | 192 |
| 199 QuotaFileIO::QuotaFileIO( | 193 QuotaFileIO::QuotaFileIO( |
| 200 PluginInstance* instance, | 194 PluginInstance* instance, |
| 201 PlatformFile file, | 195 PlatformFile file, |
| 202 const GURL& file_url, | 196 const GURL& file_url, |
| 203 PP_FileSystemType type) | 197 PP_FileSystemType type) |
| 204 : instance_(instance), | 198 : instance_(instance), |
| 205 file_(file), | 199 file_(file), |
| 206 file_url_(file_url), | 200 file_url_(file_url), |
| 207 storage_type_(PPFileSystemTypeToQuotaStorageType(type)), | 201 storage_type_(PPFileSystemTypeToQuotaStorageType(type)), |
| 208 cached_file_size_(0), | 202 cached_file_size_(0), |
| 209 cached_available_space_(0), | 203 cached_available_space_(0), |
| 210 outstanding_quota_queries_(0), | 204 outstanding_quota_queries_(0), |
| 211 outstanding_errors_(0), | 205 outstanding_errors_(0), |
| 212 max_written_offset_(0), | 206 max_written_offset_(0), |
| 213 inflight_operations_(0), | 207 inflight_operations_(0), |
| 214 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 208 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| 215 DCHECK(instance_); | 209 DCHECK(instance_); |
| 216 DCHECK_NE(base::kInvalidPlatformFileValue, file_); | 210 DCHECK_NE(base::kInvalidPlatformFileValue, file_); |
| 217 DCHECK_NE(quota::kStorageTypeUnknown, storage_type_); | 211 DCHECK_NE(quota::kStorageTypeUnknown, storage_type_); |
| 218 } | 212 } |
| 219 | 213 |
| 220 QuotaFileIO::~QuotaFileIO() { | 214 QuotaFileIO::~QuotaFileIO() { |
| 221 // Note that this doesn't dispatch pending callbacks. | 215 // Note that this doesn't dispatch pending callbacks. |
| 222 STLDeleteContainerPointers(pending_operations_.begin(), | 216 STLDeleteContainerPointers(pending_operations_.begin(), |
| 223 pending_operations_.end()); | 217 pending_operations_.end()); |
| 218 STLDeleteContainerPointers(pending_callbacks_.begin(), | |
| 219 pending_callbacks_.end()); | |
| 224 } | 220 } |
| 225 | 221 |
| 226 bool QuotaFileIO::Write( | 222 bool QuotaFileIO::Write( |
| 227 int64_t offset, const char* buffer, int32_t bytes_to_write, | 223 int64_t offset, const char* buffer, int32_t bytes_to_write, |
| 228 WriteCallback* callback) { | 224 WriteCallback* callback) { |
| 229 WriteOperation* op = new WriteOperation( | 225 WriteOperation* op = new WriteOperation( |
| 230 this, false, offset, buffer, bytes_to_write, callback); | 226 this, false, offset, buffer, bytes_to_write, callback); |
| 231 return RegisterOperationForQuotaChecks(op); | 227 return RegisterOperationForQuotaChecks(op); |
| 232 } | 228 } |
| 233 | 229 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 295 void QuotaFileIO::DidQueryAvailableSpace(int64_t avail_space) { | 291 void QuotaFileIO::DidQueryAvailableSpace(int64_t avail_space) { |
| 296 cached_available_space_ = avail_space; | 292 cached_available_space_ = avail_space; |
| 297 DCHECK_GT(outstanding_quota_queries_, 0); | 293 DCHECK_GT(outstanding_quota_queries_, 0); |
| 298 if (--outstanding_quota_queries_ == 0) | 294 if (--outstanding_quota_queries_ == 0) |
| 299 DidQueryForQuotaCheck(); | 295 DidQueryForQuotaCheck(); |
| 300 } | 296 } |
| 301 | 297 |
| 302 void QuotaFileIO::DidQueryForQuotaCheck() { | 298 void QuotaFileIO::DidQueryForQuotaCheck() { |
| 303 DCHECK(!pending_operations_.empty()); | 299 DCHECK(!pending_operations_.empty()); |
| 304 DCHECK_GT(inflight_operations_, 0); | 300 DCHECK_GT(inflight_operations_, 0); |
| 305 for (std::deque<PendingOperationBase*>::iterator iter = | 301 while (!pending_operations_.empty()) { |
| 306 pending_operations_.begin(); | 302 PendingOperationBase* op = pending_operations_.front(); |
| 307 iter != pending_operations_.end(); | 303 pending_operations_.pop_front(); |
| 308 ++iter) { | 304 pending_callbacks_.push_back(op); |
| 309 PendingOperationBase* op = *iter; | |
| 310 if (outstanding_errors_ > 0) { | 305 if (outstanding_errors_ > 0) { |
| 311 op->DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 306 op->DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
| 312 continue; | 307 continue; |
| 313 } | 308 } |
| 314 op->Run(); | 309 op->Run(); |
| 315 } | 310 } |
| 316 } | 311 } |
| 317 | 312 |
| 318 bool QuotaFileIO::CheckIfExceedsQuota(int64_t new_file_size) const { | 313 bool QuotaFileIO::CheckIfExceedsQuota(int64_t new_file_size) const { |
| 319 DCHECK_GE(cached_file_size_, 0); | 314 DCHECK_GE(cached_file_size_, 0); |
| 320 DCHECK_GE(cached_available_space_, 0); | 315 DCHECK_GE(cached_available_space_, 0); |
| 321 return new_file_size - cached_file_size_ > cached_available_space_; | 316 return new_file_size - cached_file_size_ > cached_available_space_; |
| 322 } | 317 } |
| 323 | 318 |
| 324 void QuotaFileIO::WillUpdate() { | 319 void QuotaFileIO::WillUpdate() { |
| 325 if (inflight_operations_++ == 0) { | 320 if (inflight_operations_++ == 0) { |
| 326 instance_->delegate()->WillUpdateFile(file_url_); | 321 instance_->delegate()->WillUpdateFile(file_url_); |
| 327 DCHECK_EQ(0, max_written_offset_); | 322 DCHECK_EQ(0, max_written_offset_); |
| 328 } | 323 } |
| 329 } | 324 } |
| 330 | 325 |
| 331 void QuotaFileIO::DidWrite(WriteOperation* op, | 326 void QuotaFileIO::DidWrite(WriteOperation* op, |
| 332 int64_t written_offset_end) { | 327 int64_t written_offset_end) { |
| 333 max_written_offset_ = std::max(max_written_offset_, written_offset_end); | 328 max_written_offset_ = std::max(max_written_offset_, written_offset_end); |
| 334 DCHECK_GT(inflight_operations_, 0); | 329 DCHECK_GT(inflight_operations_, 0); |
| 335 DCHECK(!pending_operations_.empty()); | 330 DCHECK(!pending_callbacks_.empty()); |
| 336 // Fire callbacks for finished operations. | 331 // Fire callbacks for finished operations. |
| 337 while (!pending_operations_.empty()) { | 332 while (!pending_callbacks_.empty()) { |
| 338 WriteOperation* op = static_cast<WriteOperation*>( | 333 WriteOperation* op = static_cast<WriteOperation*>( |
| 339 pending_operations_.front()); | 334 pending_callbacks_.front()); |
| 340 if (!op->finished()) | 335 if (!op->finished()) |
| 341 break; | 336 break; |
| 342 op->RunCallback(); | 337 pending_callbacks_.pop_front(); |
| 343 pending_operations_.pop_front(); | 338 op->WillRunCallback(); |
| 344 } | 339 } |
| 345 // If we have no more pending writes, notify the browser that we did | 340 // If we have no more pending writes, notify the browser that we did |
| 346 // update the file. | 341 // update the file. |
| 347 if (--inflight_operations_ == 0) { | 342 if (--inflight_operations_ == 0) { |
| 348 DCHECK(pending_operations_.empty()); | 343 DCHECK(pending_operations_.empty()); |
| 349 int64_t growth = max_written_offset_ - cached_file_size_; | 344 int64_t growth = max_written_offset_ - cached_file_size_; |
| 350 growth = growth < 0 ? 0 : growth; | 345 growth = growth < 0 ? 0 : growth; |
| 351 instance_->delegate()->DidUpdateFile(file_url_, growth); | 346 instance_->delegate()->DidUpdateFile(file_url_, growth); |
| 352 max_written_offset_ = 0; | 347 max_written_offset_ = 0; |
| 353 } | 348 } |
| 354 } | 349 } |
| 355 | 350 |
| 356 void QuotaFileIO::DidSetLength(PlatformFileError error, int64_t new_file_size) { | 351 void QuotaFileIO::DidSetLength(PlatformFileError error, int64_t new_file_size) { |
| 357 DCHECK_EQ(1, inflight_operations_); | 352 DCHECK_EQ(1, inflight_operations_); |
| 358 pending_operations_.pop_front(); | 353 pending_callbacks_.pop_front(); |
| 359 DCHECK(pending_operations_.empty()); | 354 DCHECK(pending_callbacks_.empty()); |
| 360 int64_t delta = (error != base::PLATFORM_FILE_OK) ? 0 : | 355 int64_t delta = (error != base::PLATFORM_FILE_OK) ? 0 : |
| 361 new_file_size - cached_file_size_; | 356 new_file_size - cached_file_size_; |
| 362 instance_->delegate()->DidUpdateFile(file_url_, delta); | 357 instance_->delegate()->DidUpdateFile(file_url_, delta); |
| 363 inflight_operations_ = 0; | 358 inflight_operations_ = 0; |
| 364 } | 359 } |
| 365 | 360 |
| 366 } // namespace ppapi | 361 } // namespace ppapi |
| 367 } // namespace webkit | 362 } // namespace webkit |
| OLD | NEW |