| 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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 if (quota_io_->CheckIfExceedsQuota(offset_ + bytes_to_write_)) { | 85 if (quota_io_->CheckIfExceedsQuota(offset_ + bytes_to_write_)) { |
| 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()); |
| 95 |
| 96 PluginDelegate* plugin_delegate = quota_io_->GetPluginDelegate(); |
| 97 if (!plugin_delegate) { |
| 98 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
| 99 return; |
| 100 } |
| 101 |
| 93 if (!base::FileUtilProxy::Write( | 102 if (!base::FileUtilProxy::Write( |
| 94 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), | 103 plugin_delegate->GetFileThreadMessageLoopProxy(), |
| 95 quota_io_->file_, offset_, buffer_.get(), bytes_to_write_, | 104 quota_io_->file_, offset_, buffer_.get(), bytes_to_write_, |
| 96 callback_factory_.NewCallback(&WriteOperation::DidFinish))) { | 105 callback_factory_.NewCallback(&WriteOperation::DidFinish))) { |
| 97 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 106 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
| 98 return; | 107 return; |
| 99 } | 108 } |
| 100 } | 109 } |
| 101 | 110 |
| 102 virtual void DidFail(PlatformFileError error) OVERRIDE { | 111 virtual void DidFail(PlatformFileError error) OVERRIDE { |
| 103 DidFinish(error, 0); | 112 DidFinish(error, 0); |
| 104 } | 113 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 virtual void Run() OVERRIDE { | 165 virtual void Run() OVERRIDE { |
| 157 DCHECK(quota_io_); | 166 DCHECK(quota_io_); |
| 158 if (quota_io_->CheckIfExceedsQuota(length_)) { | 167 if (quota_io_->CheckIfExceedsQuota(length_)) { |
| 159 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); | 168 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); |
| 160 return; | 169 return; |
| 161 } | 170 } |
| 162 if (is_will_operation_) { | 171 if (is_will_operation_) { |
| 163 DidFinish(base::PLATFORM_FILE_OK); | 172 DidFinish(base::PLATFORM_FILE_OK); |
| 164 return; | 173 return; |
| 165 } | 174 } |
| 175 |
| 176 PluginDelegate* plugin_delegate = quota_io_->GetPluginDelegate(); |
| 177 if (!plugin_delegate) { |
| 178 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
| 179 return; |
| 180 } |
| 181 |
| 166 if (!base::FileUtilProxy::Truncate( | 182 if (!base::FileUtilProxy::Truncate( |
| 167 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), | 183 plugin_delegate->GetFileThreadMessageLoopProxy(), |
| 168 quota_io_->file_, length_, | 184 quota_io_->file_, length_, |
| 169 callback_factory_.NewCallback(&SetLengthOperation::DidFinish))) { | 185 callback_factory_.NewCallback(&SetLengthOperation::DidFinish))) { |
| 170 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 186 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
| 171 return; | 187 return; |
| 172 } | 188 } |
| 173 } | 189 } |
| 174 | 190 |
| 175 virtual void DidFail(PlatformFileError error) OVERRIDE { | 191 virtual void DidFail(PlatformFileError error) OVERRIDE { |
| 176 DidFinish(error); | 192 DidFinish(error); |
| 177 } | 193 } |
| 178 | 194 |
| 179 private: | 195 private: |
| 180 void DidFinish(PlatformFileError status) { | 196 void DidFinish(PlatformFileError status) { |
| 181 quota_io_->DidSetLength(status, length_); | 197 quota_io_->DidSetLength(status, length_); |
| 182 DCHECK(callback_.get()); | 198 DCHECK(callback_.get()); |
| 183 callback_->Run(status); | 199 callback_->Run(status); |
| 184 callback_.reset(); | 200 callback_.reset(); |
| 185 delete this; | 201 delete this; |
| 186 } | 202 } |
| 187 | 203 |
| 188 int64_t length_; | 204 int64_t length_; |
| 189 scoped_ptr<StatusCallback> callback_; | 205 scoped_ptr<StatusCallback> callback_; |
| 190 base::ScopedCallbackFactory<SetLengthOperation> callback_factory_; | 206 base::ScopedCallbackFactory<SetLengthOperation> callback_factory_; |
| 191 }; | 207 }; |
| 192 | 208 |
| 193 // QuotaFileIO -------------------------------------------------------------- | 209 // QuotaFileIO -------------------------------------------------------------- |
| 194 | 210 |
| 195 QuotaFileIO::QuotaFileIO( | 211 QuotaFileIO::QuotaFileIO( |
| 196 PluginInstance* instance, | 212 PP_Instance instance, |
| 197 PlatformFile file, | 213 PlatformFile file, |
| 198 const GURL& file_url, | 214 const GURL& file_url, |
| 199 PP_FileSystemType type) | 215 PP_FileSystemType type) |
| 200 : instance_(instance), | 216 : pp_instance_(instance), |
| 201 file_(file), | 217 file_(file), |
| 202 file_url_(file_url), | 218 file_url_(file_url), |
| 203 storage_type_(PPFileSystemTypeToQuotaStorageType(type)), | 219 storage_type_(PPFileSystemTypeToQuotaStorageType(type)), |
| 204 cached_file_size_(0), | 220 cached_file_size_(0), |
| 205 cached_available_space_(0), | 221 cached_available_space_(0), |
| 206 outstanding_quota_queries_(0), | 222 outstanding_quota_queries_(0), |
| 207 outstanding_errors_(0), | 223 outstanding_errors_(0), |
| 208 max_written_offset_(0), | 224 max_written_offset_(0), |
| 209 inflight_operations_(0), | 225 inflight_operations_(0), |
| 210 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 226 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| 211 DCHECK(instance_); | |
| 212 DCHECK_NE(base::kInvalidPlatformFileValue, file_); | 227 DCHECK_NE(base::kInvalidPlatformFileValue, file_); |
| 213 DCHECK_NE(quota::kStorageTypeUnknown, storage_type_); | 228 DCHECK_NE(quota::kStorageTypeUnknown, storage_type_); |
| 214 } | 229 } |
| 215 | 230 |
| 216 QuotaFileIO::~QuotaFileIO() { | 231 QuotaFileIO::~QuotaFileIO() { |
| 217 // Note that this doesn't dispatch pending callbacks. | 232 // Note that this doesn't dispatch pending callbacks. |
| 218 STLDeleteContainerPointers(pending_operations_.begin(), | 233 STLDeleteContainerPointers(pending_operations_.begin(), |
| 219 pending_operations_.end()); | 234 pending_operations_.end()); |
| 220 STLDeleteContainerPointers(pending_callbacks_.begin(), | 235 STLDeleteContainerPointers(pending_callbacks_.begin(), |
| 221 pending_callbacks_.end()); | 236 pending_callbacks_.end()); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 246 this, true, offset, NULL, bytes_to_write, callback); | 261 this, true, offset, NULL, bytes_to_write, callback); |
| 247 return RegisterOperationForQuotaChecks(op); | 262 return RegisterOperationForQuotaChecks(op); |
| 248 } | 263 } |
| 249 | 264 |
| 250 bool QuotaFileIO::WillSetLength(int64_t length, StatusCallback* callback) { | 265 bool QuotaFileIO::WillSetLength(int64_t length, StatusCallback* callback) { |
| 251 DCHECK(pending_operations_.empty()); | 266 DCHECK(pending_operations_.empty()); |
| 252 SetLengthOperation* op = new SetLengthOperation(this, true, length, callback); | 267 SetLengthOperation* op = new SetLengthOperation(this, true, length, callback); |
| 253 return RegisterOperationForQuotaChecks(op); | 268 return RegisterOperationForQuotaChecks(op); |
| 254 } | 269 } |
| 255 | 270 |
| 271 PluginDelegate* QuotaFileIO::GetPluginDelegate() const { |
| 272 PluginInstance* instance = ResourceTracker::Get()->GetInstance(pp_instance_); |
| 273 if (instance) |
| 274 return instance->delegate(); |
| 275 return NULL; |
| 276 } |
| 277 |
| 256 bool QuotaFileIO::RegisterOperationForQuotaChecks( | 278 bool QuotaFileIO::RegisterOperationForQuotaChecks( |
| 257 PendingOperationBase* op_ptr) { | 279 PendingOperationBase* op_ptr) { |
| 258 scoped_ptr<PendingOperationBase> op(op_ptr); | 280 scoped_ptr<PendingOperationBase> op(op_ptr); |
| 259 if (pending_operations_.empty()) { | 281 if (pending_operations_.empty()) { |
| 260 // This is the first pending quota check. Run querying the file size | 282 // This is the first pending quota check. Run querying the file size |
| 261 // and available space. | 283 // and available space. |
| 262 outstanding_quota_queries_ = 0; | 284 outstanding_quota_queries_ = 0; |
| 263 outstanding_errors_ = 0; | 285 outstanding_errors_ = 0; |
| 264 | 286 |
| 287 PluginDelegate* plugin_delegate = GetPluginDelegate(); |
| 288 if (!plugin_delegate) |
| 289 return false; |
| 290 |
| 265 // Query the file size. | 291 // Query the file size. |
| 266 ++outstanding_quota_queries_; | 292 ++outstanding_quota_queries_; |
| 267 if (!base::FileUtilProxy::GetFileInfoFromPlatformFile( | 293 if (!base::FileUtilProxy::GetFileInfoFromPlatformFile( |
| 268 instance_->delegate()->GetFileThreadMessageLoopProxy(), file_, | 294 plugin_delegate->GetFileThreadMessageLoopProxy(), file_, |
| 269 callback_factory_.NewCallback( | 295 callback_factory_.NewCallback( |
| 270 &QuotaFileIO::DidQueryInfoForQuota))) { | 296 &QuotaFileIO::DidQueryInfoForQuota))) { |
| 271 // This makes the call fail synchronously; we do not fire the callback | 297 // This makes the call fail synchronously; we do not fire the callback |
| 272 // here but just delete the operation and return false. | 298 // here but just delete the operation and return false. |
| 273 return false; | 299 return false; |
| 274 } | 300 } |
| 275 | 301 |
| 276 // Query the current available space. | 302 // Query the current available space. |
| 277 ++outstanding_quota_queries_; | 303 ++outstanding_quota_queries_; |
| 278 instance_->delegate()->QueryAvailableSpace( | 304 plugin_delegate->QueryAvailableSpace( |
| 279 GURL(file_url_.path()).GetOrigin(), storage_type_, | 305 GURL(file_url_.path()).GetOrigin(), storage_type_, |
| 280 callback_factory_.NewCallback(&QuotaFileIO::DidQueryAvailableSpace)); | 306 callback_factory_.NewCallback(&QuotaFileIO::DidQueryAvailableSpace)); |
| 281 } | 307 } |
| 282 pending_operations_.push_back(op.release()); | 308 pending_operations_.push_back(op.release()); |
| 283 return true; | 309 return true; |
| 284 } | 310 } |
| 285 | 311 |
| 286 void QuotaFileIO::DidQueryInfoForQuota( | 312 void QuotaFileIO::DidQueryInfoForQuota( |
| 287 base::PlatformFileError error_code, | 313 base::PlatformFileError error_code, |
| 288 const base::PlatformFileInfo& file_info) { | 314 const base::PlatformFileInfo& file_info) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 317 } | 343 } |
| 318 | 344 |
| 319 bool QuotaFileIO::CheckIfExceedsQuota(int64_t new_file_size) const { | 345 bool QuotaFileIO::CheckIfExceedsQuota(int64_t new_file_size) const { |
| 320 DCHECK_GE(cached_file_size_, 0); | 346 DCHECK_GE(cached_file_size_, 0); |
| 321 DCHECK_GE(cached_available_space_, 0); | 347 DCHECK_GE(cached_available_space_, 0); |
| 322 return new_file_size - cached_file_size_ > cached_available_space_; | 348 return new_file_size - cached_file_size_ > cached_available_space_; |
| 323 } | 349 } |
| 324 | 350 |
| 325 void QuotaFileIO::WillUpdate() { | 351 void QuotaFileIO::WillUpdate() { |
| 326 if (inflight_operations_++ == 0) { | 352 if (inflight_operations_++ == 0) { |
| 327 instance_->delegate()->WillUpdateFile(file_url_); | 353 PluginDelegate* plugin_delegate = GetPluginDelegate(); |
| 354 if (plugin_delegate) |
| 355 plugin_delegate->WillUpdateFile(file_url_); |
| 328 DCHECK_EQ(0, max_written_offset_); | 356 DCHECK_EQ(0, max_written_offset_); |
| 329 } | 357 } |
| 330 } | 358 } |
| 331 | 359 |
| 332 void QuotaFileIO::DidWrite(WriteOperation* op, | 360 void QuotaFileIO::DidWrite(WriteOperation* op, |
| 333 int64_t written_offset_end) { | 361 int64_t written_offset_end) { |
| 334 max_written_offset_ = std::max(max_written_offset_, written_offset_end); | 362 max_written_offset_ = std::max(max_written_offset_, written_offset_end); |
| 335 DCHECK_GT(inflight_operations_, 0); | 363 DCHECK_GT(inflight_operations_, 0); |
| 336 DCHECK(!pending_callbacks_.empty()); | 364 DCHECK(!pending_callbacks_.empty()); |
| 337 // Fire callbacks for finished operations. | 365 // Fire callbacks for finished operations. |
| 338 while (!pending_callbacks_.empty()) { | 366 while (!pending_callbacks_.empty()) { |
| 339 WriteOperation* op = static_cast<WriteOperation*>( | 367 WriteOperation* op = static_cast<WriteOperation*>( |
| 340 pending_callbacks_.front()); | 368 pending_callbacks_.front()); |
| 341 if (!op->finished()) | 369 if (!op->finished()) |
| 342 break; | 370 break; |
| 343 pending_callbacks_.pop_front(); | 371 pending_callbacks_.pop_front(); |
| 344 op->WillRunCallback(); | 372 op->WillRunCallback(); |
| 345 } | 373 } |
| 346 // If we have no more pending writes, notify the browser that we did | 374 // If we have no more pending writes, notify the browser that we did |
| 347 // update the file. | 375 // update the file. |
| 348 if (--inflight_operations_ == 0) { | 376 if (--inflight_operations_ == 0) { |
| 349 DCHECK(pending_operations_.empty()); | 377 DCHECK(pending_operations_.empty()); |
| 350 int64_t growth = max_written_offset_ - cached_file_size_; | 378 int64_t growth = max_written_offset_ - cached_file_size_; |
| 351 growth = growth < 0 ? 0 : growth; | 379 growth = growth < 0 ? 0 : growth; |
| 352 instance_->delegate()->DidUpdateFile(file_url_, growth); | 380 |
| 381 PluginDelegate* plugin_delegate = GetPluginDelegate(); |
| 382 if (plugin_delegate) |
| 383 plugin_delegate->DidUpdateFile(file_url_, growth); |
| 353 max_written_offset_ = 0; | 384 max_written_offset_ = 0; |
| 354 } | 385 } |
| 355 } | 386 } |
| 356 | 387 |
| 357 void QuotaFileIO::DidSetLength(PlatformFileError error, int64_t new_file_size) { | 388 void QuotaFileIO::DidSetLength(PlatformFileError error, int64_t new_file_size) { |
| 358 DCHECK_EQ(1, inflight_operations_); | 389 DCHECK_EQ(1, inflight_operations_); |
| 359 pending_callbacks_.pop_front(); | 390 pending_callbacks_.pop_front(); |
| 360 DCHECK(pending_callbacks_.empty()); | 391 DCHECK(pending_callbacks_.empty()); |
| 361 int64_t delta = (error != base::PLATFORM_FILE_OK) ? 0 : | 392 int64_t delta = (error != base::PLATFORM_FILE_OK) ? 0 : |
| 362 new_file_size - cached_file_size_; | 393 new_file_size - cached_file_size_; |
| 363 instance_->delegate()->DidUpdateFile(file_url_, delta); | 394 |
| 395 |
| 396 PluginDelegate* plugin_delegate = GetPluginDelegate(); |
| 397 if (plugin_delegate) |
| 398 plugin_delegate->DidUpdateFile(file_url_, delta); |
| 364 inflight_operations_ = 0; | 399 inflight_operations_ = 0; |
| 365 } | 400 } |
| 366 | 401 |
| 367 } // namespace ppapi | 402 } // namespace ppapi |
| 368 } // namespace webkit | 403 } // namespace webkit |
| OLD | NEW |