| 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 <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
| 10 #include "base/message_loop_proxy.h" | 10 #include "base/message_loop_proxy.h" |
| 11 #include "base/task.h" | 11 #include "base/task.h" |
| 12 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | 12 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" |
| 13 #include "webkit/plugins/ppapi/resource_helper.h" |
| 14 #include "webkit/plugins/ppapi/resource_tracker.h" |
| 13 | 15 |
| 14 using base::PlatformFile; | 16 using base::PlatformFile; |
| 15 using base::PlatformFileError; | 17 using base::PlatformFileError; |
| 16 using quota::StorageType; | 18 using quota::StorageType; |
| 17 | 19 |
| 18 namespace webkit { | 20 namespace webkit { |
| 19 namespace ppapi { | 21 namespace ppapi { |
| 20 | 22 |
| 21 namespace { | 23 namespace { |
| 22 StorageType PPFileSystemTypeToQuotaStorageType(PP_FileSystemType type) { | 24 StorageType PPFileSystemTypeToQuotaStorageType(PP_FileSystemType type) { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); | 86 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); |
| 85 return; | 87 return; |
| 86 } | 88 } |
| 87 if (is_will_operation_) { | 89 if (is_will_operation_) { |
| 88 // Assuming the write will succeed. | 90 // Assuming the write will succeed. |
| 89 DidFinish(base::PLATFORM_FILE_OK, bytes_to_write_); | 91 DidFinish(base::PLATFORM_FILE_OK, bytes_to_write_); |
| 90 return; | 92 return; |
| 91 } | 93 } |
| 92 DCHECK(buffer_.get()); | 94 DCHECK(buffer_.get()); |
| 93 if (!base::FileUtilProxy::Write( | 95 if (!base::FileUtilProxy::Write( |
| 94 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), | 96 quota_io_->GetPluginDelegate()->GetFileThreadMessageLoopProxy(), |
| 95 quota_io_->file_, offset_, buffer_.get(), bytes_to_write_, | 97 quota_io_->file_, offset_, buffer_.get(), bytes_to_write_, |
| 96 callback_factory_.NewCallback(&WriteOperation::DidFinish))) { | 98 callback_factory_.NewCallback(&WriteOperation::DidFinish))) { |
| 97 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 99 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
| 98 return; | 100 return; |
| 99 } | 101 } |
| 100 } | 102 } |
| 101 | 103 |
| 102 virtual void DidFail(PlatformFileError error) OVERRIDE { | 104 virtual void DidFail(PlatformFileError error) OVERRIDE { |
| 103 DidFinish(error, 0); | 105 DidFinish(error, 0); |
| 104 } | 106 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 DCHECK(quota_io_); | 159 DCHECK(quota_io_); |
| 158 if (quota_io_->CheckIfExceedsQuota(length_)) { | 160 if (quota_io_->CheckIfExceedsQuota(length_)) { |
| 159 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); | 161 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); |
| 160 return; | 162 return; |
| 161 } | 163 } |
| 162 if (is_will_operation_) { | 164 if (is_will_operation_) { |
| 163 DidFinish(base::PLATFORM_FILE_OK); | 165 DidFinish(base::PLATFORM_FILE_OK); |
| 164 return; | 166 return; |
| 165 } | 167 } |
| 166 if (!base::FileUtilProxy::Truncate( | 168 if (!base::FileUtilProxy::Truncate( |
| 167 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), | 169 quota_io_->GetPluginDelegate()->GetFileThreadMessageLoopProxy(), |
| 168 quota_io_->file_, length_, | 170 quota_io_->file_, length_, |
| 169 callback_factory_.NewCallback(&SetLengthOperation::DidFinish))) { | 171 callback_factory_.NewCallback(&SetLengthOperation::DidFinish))) { |
| 170 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 172 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
| 171 return; | 173 return; |
| 172 } | 174 } |
| 173 } | 175 } |
| 174 | 176 |
| 175 virtual void DidFail(PlatformFileError error) OVERRIDE { | 177 virtual void DidFail(PlatformFileError error) OVERRIDE { |
| 176 DidFinish(error); | 178 DidFinish(error); |
| 177 } | 179 } |
| 178 | 180 |
| 179 private: | 181 private: |
| 180 void DidFinish(PlatformFileError status) { | 182 void DidFinish(PlatformFileError status) { |
| 181 quota_io_->DidSetLength(status, length_); | 183 quota_io_->DidSetLength(status, length_); |
| 182 DCHECK(callback_.get()); | 184 DCHECK(callback_.get()); |
| 183 callback_->Run(status); | 185 callback_->Run(status); |
| 184 callback_.reset(); | 186 callback_.reset(); |
| 185 delete this; | 187 delete this; |
| 186 } | 188 } |
| 187 | 189 |
| 188 int64_t length_; | 190 int64_t length_; |
| 189 scoped_ptr<StatusCallback> callback_; | 191 scoped_ptr<StatusCallback> callback_; |
| 190 base::ScopedCallbackFactory<SetLengthOperation> callback_factory_; | 192 base::ScopedCallbackFactory<SetLengthOperation> callback_factory_; |
| 191 }; | 193 }; |
| 192 | 194 |
| 193 // QuotaFileIO -------------------------------------------------------------- | 195 // QuotaFileIO -------------------------------------------------------------- |
| 194 | 196 |
| 195 QuotaFileIO::QuotaFileIO( | 197 QuotaFileIO::QuotaFileIO( |
| 196 PluginInstance* instance, | 198 PP_Instance instance, |
| 197 PlatformFile file, | 199 PlatformFile file, |
| 198 const GURL& file_url, | 200 const GURL& file_url, |
| 199 PP_FileSystemType type) | 201 PP_FileSystemType type) |
| 200 : instance_(instance), | 202 : pp_instance_(instance), |
| 201 file_(file), | 203 file_(file), |
| 202 file_url_(file_url), | 204 file_url_(file_url), |
| 203 storage_type_(PPFileSystemTypeToQuotaStorageType(type)), | 205 storage_type_(PPFileSystemTypeToQuotaStorageType(type)), |
| 204 cached_file_size_(0), | 206 cached_file_size_(0), |
| 205 cached_available_space_(0), | 207 cached_available_space_(0), |
| 206 outstanding_quota_queries_(0), | 208 outstanding_quota_queries_(0), |
| 207 outstanding_errors_(0), | 209 outstanding_errors_(0), |
| 208 max_written_offset_(0), | 210 max_written_offset_(0), |
| 209 inflight_operations_(0), | 211 inflight_operations_(0), |
| 210 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 212 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| 211 DCHECK(instance_); | |
| 212 DCHECK_NE(base::kInvalidPlatformFileValue, file_); | 213 DCHECK_NE(base::kInvalidPlatformFileValue, file_); |
| 213 DCHECK_NE(quota::kStorageTypeUnknown, storage_type_); | 214 DCHECK_NE(quota::kStorageTypeUnknown, storage_type_); |
| 214 } | 215 } |
| 215 | 216 |
| 216 QuotaFileIO::~QuotaFileIO() { | 217 QuotaFileIO::~QuotaFileIO() { |
| 217 // Note that this doesn't dispatch pending callbacks. | 218 // Note that this doesn't dispatch pending callbacks. |
| 218 STLDeleteContainerPointers(pending_operations_.begin(), | 219 STLDeleteContainerPointers(pending_operations_.begin(), |
| 219 pending_operations_.end()); | 220 pending_operations_.end()); |
| 220 STLDeleteContainerPointers(pending_callbacks_.begin(), | 221 STLDeleteContainerPointers(pending_callbacks_.begin(), |
| 221 pending_callbacks_.end()); | 222 pending_callbacks_.end()); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 246 this, true, offset, NULL, bytes_to_write, callback); | 247 this, true, offset, NULL, bytes_to_write, callback); |
| 247 return RegisterOperationForQuotaChecks(op); | 248 return RegisterOperationForQuotaChecks(op); |
| 248 } | 249 } |
| 249 | 250 |
| 250 bool QuotaFileIO::WillSetLength(int64_t length, StatusCallback* callback) { | 251 bool QuotaFileIO::WillSetLength(int64_t length, StatusCallback* callback) { |
| 251 DCHECK(pending_operations_.empty()); | 252 DCHECK(pending_operations_.empty()); |
| 252 SetLengthOperation* op = new SetLengthOperation(this, true, length, callback); | 253 SetLengthOperation* op = new SetLengthOperation(this, true, length, callback); |
| 253 return RegisterOperationForQuotaChecks(op); | 254 return RegisterOperationForQuotaChecks(op); |
| 254 } | 255 } |
| 255 | 256 |
| 257 PluginDelegate* QuotaFileIO::GetPluginDelegate() const { |
| 258 PluginInstance* instance = ResourceTracker::Get()->GetInstance(pp_instance_); |
| 259 if (instance) |
| 260 return instance->delegate(); |
| 261 return NULL; |
| 262 } |
| 263 |
| 256 bool QuotaFileIO::RegisterOperationForQuotaChecks( | 264 bool QuotaFileIO::RegisterOperationForQuotaChecks( |
| 257 PendingOperationBase* op_ptr) { | 265 PendingOperationBase* op_ptr) { |
| 258 scoped_ptr<PendingOperationBase> op(op_ptr); | 266 scoped_ptr<PendingOperationBase> op(op_ptr); |
| 259 if (pending_operations_.empty()) { | 267 if (pending_operations_.empty()) { |
| 260 // This is the first pending quota check. Run querying the file size | 268 // This is the first pending quota check. Run querying the file size |
| 261 // and available space. | 269 // and available space. |
| 262 outstanding_quota_queries_ = 0; | 270 outstanding_quota_queries_ = 0; |
| 263 outstanding_errors_ = 0; | 271 outstanding_errors_ = 0; |
| 264 | 272 |
| 265 // Query the file size. | 273 // Query the file size. |
| 266 ++outstanding_quota_queries_; | 274 ++outstanding_quota_queries_; |
| 267 if (!base::FileUtilProxy::GetFileInfoFromPlatformFile( | 275 if (!base::FileUtilProxy::GetFileInfoFromPlatformFile( |
| 268 instance_->delegate()->GetFileThreadMessageLoopProxy(), file_, | 276 GetPluginDelegate()->GetFileThreadMessageLoopProxy(), file_, |
| 269 callback_factory_.NewCallback( | 277 callback_factory_.NewCallback( |
| 270 &QuotaFileIO::DidQueryInfoForQuota))) { | 278 &QuotaFileIO::DidQueryInfoForQuota))) { |
| 271 // This makes the call fail synchronously; we do not fire the callback | 279 // This makes the call fail synchronously; we do not fire the callback |
| 272 // here but just delete the operation and return false. | 280 // here but just delete the operation and return false. |
| 273 return false; | 281 return false; |
| 274 } | 282 } |
| 275 | 283 |
| 276 // Query the current available space. | 284 // Query the current available space. |
| 277 ++outstanding_quota_queries_; | 285 ++outstanding_quota_queries_; |
| 278 instance_->delegate()->QueryAvailableSpace( | 286 GetPluginDelegate()->QueryAvailableSpace( |
| 279 GURL(file_url_.path()).GetOrigin(), storage_type_, | 287 GURL(file_url_.path()).GetOrigin(), storage_type_, |
| 280 callback_factory_.NewCallback(&QuotaFileIO::DidQueryAvailableSpace)); | 288 callback_factory_.NewCallback(&QuotaFileIO::DidQueryAvailableSpace)); |
| 281 } | 289 } |
| 282 pending_operations_.push_back(op.release()); | 290 pending_operations_.push_back(op.release()); |
| 283 return true; | 291 return true; |
| 284 } | 292 } |
| 285 | 293 |
| 286 void QuotaFileIO::DidQueryInfoForQuota( | 294 void QuotaFileIO::DidQueryInfoForQuota( |
| 287 base::PlatformFileError error_code, | 295 base::PlatformFileError error_code, |
| 288 const base::PlatformFileInfo& file_info) { | 296 const base::PlatformFileInfo& file_info) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 317 } | 325 } |
| 318 | 326 |
| 319 bool QuotaFileIO::CheckIfExceedsQuota(int64_t new_file_size) const { | 327 bool QuotaFileIO::CheckIfExceedsQuota(int64_t new_file_size) const { |
| 320 DCHECK_GE(cached_file_size_, 0); | 328 DCHECK_GE(cached_file_size_, 0); |
| 321 DCHECK_GE(cached_available_space_, 0); | 329 DCHECK_GE(cached_available_space_, 0); |
| 322 return new_file_size - cached_file_size_ > cached_available_space_; | 330 return new_file_size - cached_file_size_ > cached_available_space_; |
| 323 } | 331 } |
| 324 | 332 |
| 325 void QuotaFileIO::WillUpdate() { | 333 void QuotaFileIO::WillUpdate() { |
| 326 if (inflight_operations_++ == 0) { | 334 if (inflight_operations_++ == 0) { |
| 327 instance_->delegate()->WillUpdateFile(file_url_); | 335 GetPluginDelegate()->WillUpdateFile(file_url_); |
| 328 DCHECK_EQ(0, max_written_offset_); | 336 DCHECK_EQ(0, max_written_offset_); |
| 329 } | 337 } |
| 330 } | 338 } |
| 331 | 339 |
| 332 void QuotaFileIO::DidWrite(WriteOperation* op, | 340 void QuotaFileIO::DidWrite(WriteOperation* op, |
| 333 int64_t written_offset_end) { | 341 int64_t written_offset_end) { |
| 334 max_written_offset_ = std::max(max_written_offset_, written_offset_end); | 342 max_written_offset_ = std::max(max_written_offset_, written_offset_end); |
| 335 DCHECK_GT(inflight_operations_, 0); | 343 DCHECK_GT(inflight_operations_, 0); |
| 336 DCHECK(!pending_callbacks_.empty()); | 344 DCHECK(!pending_callbacks_.empty()); |
| 337 // Fire callbacks for finished operations. | 345 // Fire callbacks for finished operations. |
| 338 while (!pending_callbacks_.empty()) { | 346 while (!pending_callbacks_.empty()) { |
| 339 WriteOperation* op = static_cast<WriteOperation*>( | 347 WriteOperation* op = static_cast<WriteOperation*>( |
| 340 pending_callbacks_.front()); | 348 pending_callbacks_.front()); |
| 341 if (!op->finished()) | 349 if (!op->finished()) |
| 342 break; | 350 break; |
| 343 pending_callbacks_.pop_front(); | 351 pending_callbacks_.pop_front(); |
| 344 op->WillRunCallback(); | 352 op->WillRunCallback(); |
| 345 } | 353 } |
| 346 // If we have no more pending writes, notify the browser that we did | 354 // If we have no more pending writes, notify the browser that we did |
| 347 // update the file. | 355 // update the file. |
| 348 if (--inflight_operations_ == 0) { | 356 if (--inflight_operations_ == 0) { |
| 349 DCHECK(pending_operations_.empty()); | 357 DCHECK(pending_operations_.empty()); |
| 350 int64_t growth = max_written_offset_ - cached_file_size_; | 358 int64_t growth = max_written_offset_ - cached_file_size_; |
| 351 growth = growth < 0 ? 0 : growth; | 359 growth = growth < 0 ? 0 : growth; |
| 352 instance_->delegate()->DidUpdateFile(file_url_, growth); | 360 GetPluginDelegate()->DidUpdateFile(file_url_, growth); |
| 353 max_written_offset_ = 0; | 361 max_written_offset_ = 0; |
| 354 } | 362 } |
| 355 } | 363 } |
| 356 | 364 |
| 357 void QuotaFileIO::DidSetLength(PlatformFileError error, int64_t new_file_size) { | 365 void QuotaFileIO::DidSetLength(PlatformFileError error, int64_t new_file_size) { |
| 358 DCHECK_EQ(1, inflight_operations_); | 366 DCHECK_EQ(1, inflight_operations_); |
| 359 pending_callbacks_.pop_front(); | 367 pending_callbacks_.pop_front(); |
| 360 DCHECK(pending_callbacks_.empty()); | 368 DCHECK(pending_callbacks_.empty()); |
| 361 int64_t delta = (error != base::PLATFORM_FILE_OK) ? 0 : | 369 int64_t delta = (error != base::PLATFORM_FILE_OK) ? 0 : |
| 362 new_file_size - cached_file_size_; | 370 new_file_size - cached_file_size_; |
| 363 instance_->delegate()->DidUpdateFile(file_url_, delta); | 371 GetPluginDelegate()->DidUpdateFile(file_url_, delta); |
| 364 inflight_operations_ = 0; | 372 inflight_operations_ = 0; |
| 365 } | 373 } |
| 366 | 374 |
| 367 } // namespace ppapi | 375 } // namespace ppapi |
| 368 } // namespace webkit | 376 } // namespace webkit |
| OLD | NEW |