file_io_resource.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 3// found in the LICENSE file. 4 5#include "ppapi/proxy/file_io_resource.h" 6 7#include "base/bind.h" 8#include "base/task_runner_util.h" 9#include "ipc/ipc_message.h" 10#include "ppapi/c/pp_errors.h" 11#include "ppapi/proxy/ppapi_messages.h" 12#include "ppapi/shared_impl/array_writer.h" 13#include "ppapi/shared_impl/file_ref_create_info.h" 14#include "ppapi/shared_impl/file_system_util.h" 15#include "ppapi/shared_impl/file_type_conversion.h" 16#include "ppapi/shared_impl/ppapi_globals.h" 17#include "ppapi/shared_impl/proxy_lock.h" 18#include "ppapi/shared_impl/resource_tracker.h" 19#include "ppapi/thunk/enter.h" 20#include "ppapi/thunk/ppb_file_ref_api.h" 21#include "ppapi/thunk/ppb_file_system_api.h" 22 23using ppapi::thunk::EnterResourceNoLock; 24using ppapi::thunk::PPB_FileIO_API; 25using ppapi::thunk::PPB_FileRef_API; 26using ppapi::thunk::PPB_FileSystem_API; 27 28namespace { 29 30// We must allocate a buffer sized according to the request of the plugin. To 31// reduce the chance of out-of-memory errors, we cap the read and write size to 32// 32MB. This is OK since the API specifies that it may perform a partial read 33// or write. 34static const int32_t kMaxReadWriteSize = 32 * 1024 * 1024; // 32MB 35 36// An adapter to let Read() share the same implementation with ReadToArray(). 37void* DummyGetDataBuffer(void* user_data, uint32_t count, uint32_t size) { 38 return user_data; 39} 40 41// File thread task to close the file handle. 42void DoClose(base::PlatformFile file) { 43 base::ClosePlatformFile(file); 44} 45 46} // namespace 47 48namespace ppapi { 49namespace proxy { 50 51FileIOResource::QueryOp::QueryOp(scoped_refptr<FileHandleHolder> file_handle) 52 : file_handle_(file_handle) { 53 DCHECK(file_handle_); 54} 55 56FileIOResource::QueryOp::~QueryOp() { 57} 58 59int32_t FileIOResource::QueryOp::DoWork() { 60 // TODO(rvargas): Convert this code to use base::File. 61 base::File file(file_handle_->raw_handle()); 62 bool success = file.GetInfo(&file_info_); 63 file.TakePlatformFile(); 64 return success ? PP_OK : PP_ERROR_FAILED; 65} 66 67FileIOResource::ReadOp::ReadOp(scoped_refptr<FileHandleHolder> file_handle, 68 int64_t offset, 69 int32_t bytes_to_read) 70 : file_handle_(file_handle), 71 offset_(offset), 72 bytes_to_read_(bytes_to_read) { 73 DCHECK(file_handle_); 74} 75 76FileIOResource::ReadOp::~ReadOp() { 77} 78 79int32_t FileIOResource::ReadOp::DoWork() { 80 DCHECK(!buffer_.get()); 81 buffer_.reset(new char[bytes_to_read_]); 82 return base::ReadPlatformFile( 83 file_handle_->raw_handle(), offset_, buffer_.get(), bytes_to_read_); 84} 85 86FileIOResource::WriteOp::WriteOp(scoped_refptr<FileHandleHolder> file_handle, 87 int64_t offset, 88 const char* buffer, 89 int32_t bytes_to_write, 90 bool append) 91 : file_handle_(file_handle), 92 offset_(offset), 93 buffer_(buffer), 94 bytes_to_write_(bytes_to_write), 95 append_(append) { 96} 97 98FileIOResource::WriteOp::~WriteOp() { 99} 100 101int32_t FileIOResource::WriteOp::DoWork() { 102 // We can't just call WritePlatformFile in append mode, since NaCl doesn't 103 // implement fcntl, causing the function to call pwrite, which is incorrect. 104 if (append_) { 105 return base::WritePlatformFileAtCurrentPos( 106 file_handle_->raw_handle(), buffer_, bytes_to_write_); 107 } else { 108 return base::WritePlatformFile( 109 file_handle_->raw_handle(), offset_, buffer_, bytes_to_write_); 110 } 111} 112 113FileIOResource::FileIOResource(Connection connection, PP_Instance instance) 114 : PluginResource(connection, instance), 115 file_system_type_(PP_FILESYSTEMTYPE_INVALID), 116 open_flags_(0), 117 max_written_offset_(0), 118 append_mode_write_amount_(0), 119 check_quota_(false), 120 called_close_(false) { 121 SendCreate(BROWSER, PpapiHostMsg_FileIO_Create()); 122} 123 124FileIOResource::~FileIOResource() { 125 Close(); 126} 127 128PPB_FileIO_API* FileIOResource::AsPPB_FileIO_API() { 129 return this; 130} 131 132int32_t FileIOResource::Open(PP_Resource file_ref, 133 int32_t open_flags, 134 scoped_refptr<TrackedCallback> callback) { 135 EnterResourceNoLock<PPB_FileRef_API> enter_file_ref(file_ref, true); 136 if (enter_file_ref.failed()) 137 return PP_ERROR_BADRESOURCE; 138 139 PPB_FileRef_API* file_ref_api = enter_file_ref.object(); 140 const FileRefCreateInfo& create_info = file_ref_api->GetCreateInfo(); 141 if (!FileSystemTypeIsValid(create_info.file_system_type)) { 142 NOTREACHED(); 143 return PP_ERROR_FAILED; 144 } 145 int32_t rv = state_manager_.CheckOperationState( 146 FileIOStateManager::OPERATION_EXCLUSIVE, false); 147 if (rv != PP_OK) 148 return rv; 149 150 open_flags_ = open_flags; 151 file_system_type_ = create_info.file_system_type; 152 153 if (create_info.file_system_plugin_resource) { 154 EnterResourceNoLock<PPB_FileSystem_API> enter_file_system( 155 create_info.file_system_plugin_resource, true); 156 if (enter_file_system.failed()) 157 return PP_ERROR_FAILED; 158 // Take a reference on the FileSystem resource. The FileIO host uses the 159 // FileSystem host for running tasks and checking quota. 160 file_system_resource_ = enter_file_system.resource(); 161 } 162 163 // Take a reference on the FileRef resource while we're opening the file; we 164 // don't want the plugin destroying it during the Open operation. 165 file_ref_ = enter_file_ref.resource(); 166 167 Call<PpapiPluginMsg_FileIO_OpenReply>(BROWSER, 168 PpapiHostMsg_FileIO_Open( 169 file_ref, 170 open_flags), 171 base::Bind(&FileIOResource::OnPluginMsgOpenFileComplete, this, 172 callback)); 173 174 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); 175 return PP_OK_COMPLETIONPENDING; 176} 177 178int32_t FileIOResource::Query(PP_FileInfo* info, 179 scoped_refptr<TrackedCallback> callback) { 180 int32_t rv = state_manager_.CheckOperationState( 181 FileIOStateManager::OPERATION_EXCLUSIVE, true); 182 if (rv != PP_OK) 183 return rv; 184 if (!info) 185 return PP_ERROR_BADARGUMENT; 186 if (!FileHandleHolder::IsValid(file_handle_)) 187 return PP_ERROR_FAILED; 188 189 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); 190 191 // If the callback is blocking, perform the task on the calling thread. 192 if (callback->is_blocking()) { 193 int32_t result = PP_ERROR_FAILED; 194 base::File::Info file_info; 195 // The plugin could release its reference to this instance when we release 196 // the proxy lock below. 197 scoped_refptr<FileIOResource> protect(this); 198 { 199 // Release the proxy lock while making a potentially slow file call. 200 ProxyAutoUnlock unlock; 201 // TODO(rvargas): Convert this code to base::File. 202 base::File file(file_handle_->raw_handle()); 203 bool success = file.GetInfo(&file_info); 204 file.TakePlatformFile(); 205 if (success) 206 result = PP_OK; 207 } 208 if (result == PP_OK) { 209 // This writes the file info into the plugin's PP_FileInfo struct. 210 ppapi::FileInfoToPepperFileInfo(file_info, 211 file_system_type_, 212 info); 213 } 214 state_manager_.SetOperationFinished(); 215 return result; 216 } 217 218 // For the non-blocking case, post a task to the file thread and add a 219 // completion task to write the result. 220 scoped_refptr<QueryOp> query_op(new QueryOp(file_handle_)); 221 base::PostTaskAndReplyWithResult( 222 PpapiGlobals::Get()->GetFileTaskRunner(), 223 FROM_HERE, 224 Bind(&FileIOResource::QueryOp::DoWork, query_op), 225 RunWhileLocked(Bind(&TrackedCallback::Run, callback))); 226 callback->set_completion_task( 227 Bind(&FileIOResource::OnQueryComplete, this, query_op, info)); 228 229 return PP_OK_COMPLETIONPENDING; 230} 231 232int32_t FileIOResource::Touch(PP_Time last_access_time, 233 PP_Time last_modified_time, 234 scoped_refptr<TrackedCallback> callback) { 235 int32_t rv = state_manager_.CheckOperationState( 236 FileIOStateManager::OPERATION_EXCLUSIVE, true); 237 if (rv != PP_OK) 238 return rv; 239 240 Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER, 241 PpapiHostMsg_FileIO_Touch(last_access_time, last_modified_time), 242 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, 243 callback)); 244 245 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); 246 return PP_OK_COMPLETIONPENDING; 247} 248 249int32_t FileIOResource::Read(int64_t offset, 250 char* buffer, 251 int32_t bytes_to_read, 252 scoped_refptr<TrackedCallback> callback) { 253 int32_t rv = state_manager_.CheckOperationState( 254 FileIOStateManager::OPERATION_READ, true); 255 if (rv != PP_OK) 256 return rv; 257 258 PP_ArrayOutput output_adapter; 259 output_adapter.GetDataBuffer = &DummyGetDataBuffer; 260 output_adapter.user_data = buffer; 261 return ReadValidated(offset, bytes_to_read, output_adapter, callback); 262} 263 264int32_t FileIOResource::ReadToArray(int64_t offset, 265 int32_t max_read_length, 266 PP_ArrayOutput* array_output, 267 scoped_refptr<TrackedCallback> callback) { 268 DCHECK(array_output); 269 int32_t rv = state_manager_.CheckOperationState( 270 FileIOStateManager::OPERATION_READ, true); 271 if (rv != PP_OK) 272 return rv; 273 274 return ReadValidated(offset, max_read_length, *array_output, callback); 275} 276 277int32_t FileIOResource::Write(int64_t offset, 278 const char* buffer, 279 int32_t bytes_to_write, 280 scoped_refptr<TrackedCallback> callback) { 281 if (!buffer) 282 return PP_ERROR_FAILED; 283 if (offset < 0 || bytes_to_write < 0) 284 return PP_ERROR_FAILED; 285 if (!FileHandleHolder::IsValid(file_handle_)) 286 return PP_ERROR_FAILED; 287 288 int32_t rv = state_manager_.CheckOperationState( 289 FileIOStateManager::OPERATION_WRITE, true); 290 if (rv != PP_OK) 291 return rv; 292 293 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_WRITE); 294 295 if (check_quota_) { 296 int64_t increase = 0; 297 uint64_t max_offset = 0; 298 bool append = (open_flags_ & PP_FILEOPENFLAG_APPEND) != 0; 299 if (append) { 300 increase = bytes_to_write; 301 } else { 302 uint64_t max_offset = offset + bytes_to_write; 303 if (max_offset > static_cast<uint64_t>(kint64max)) 304 return PP_ERROR_FAILED; // amount calculation would overflow. 305 increase = static_cast<int64_t>(max_offset) - max_written_offset_; 306 } 307 308 if (increase > 0) { 309 int64_t result = 310 file_system_resource_->AsPPB_FileSystem_API()->RequestQuota( 311 increase, 312 base::Bind(&FileIOResource::OnRequestWriteQuotaComplete, 313 this, 314 offset, buffer, bytes_to_write, callback)); 315 if (result == PP_OK_COMPLETIONPENDING) 316 return PP_OK_COMPLETIONPENDING; 317 DCHECK(result == increase); 318 319 if (append) 320 append_mode_write_amount_ += bytes_to_write; 321 else 322 max_written_offset_ = max_offset; 323 } 324 } 325 return WriteValidated(offset, buffer, bytes_to_write, callback); 326} 327 328int32_t FileIOResource::SetLength(int64_t length, 329 scoped_refptr<TrackedCallback> callback) { 330 int32_t rv = state_manager_.CheckOperationState( 331 FileIOStateManager::OPERATION_EXCLUSIVE, true); 332 if (rv != PP_OK) 333 return rv; 334 if (length < 0) 335 return PP_ERROR_FAILED; 336 337 if (check_quota_) { 338 int64_t increase = length - max_written_offset_; 339 if (increase > 0) { 340 int32_t result = 341 file_system_resource_->AsPPB_FileSystem_API()->RequestQuota( 342 increase, 343 base::Bind(&FileIOResource::OnRequestSetLengthQuotaComplete, 344 this, 345 length, callback)); 346 if (result == PP_OK_COMPLETIONPENDING) { 347 state_manager_.SetPendingOperation( 348 FileIOStateManager::OPERATION_EXCLUSIVE); 349 return PP_OK_COMPLETIONPENDING; 350 } 351 DCHECK(result == increase); 352 max_written_offset_ = length; 353 } 354 } 355 356 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); 357 SetLengthValidated(length, callback); 358 return PP_OK_COMPLETIONPENDING; 359} 360 361int32_t FileIOResource::Flush(scoped_refptr<TrackedCallback> callback) { 362 int32_t rv = state_manager_.CheckOperationState( 363 FileIOStateManager::OPERATION_EXCLUSIVE, true); 364 if (rv != PP_OK) 365 return rv; 366 367 Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER, 368 PpapiHostMsg_FileIO_Flush(), 369 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, 370 callback)); 371 372 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); 373 return PP_OK_COMPLETIONPENDING; 374} 375 376int64_t FileIOResource::GetMaxWrittenOffset() const { 377 return max_written_offset_; 378} 379 380int64_t FileIOResource::GetAppendModeWriteAmount() const { 381 return append_mode_write_amount_; 382} 383 384void FileIOResource::SetMaxWrittenOffset(int64_t max_written_offset) { 385 max_written_offset_ = max_written_offset; 386} 387 388void FileIOResource::SetAppendModeWriteAmount( 389 int64_t append_mode_write_amount) { 390 append_mode_write_amount_ = append_mode_write_amount; 391} 392 393void FileIOResource::Close() { 394 if (called_close_) 395 return; 396 397 called_close_ = true; 398 if (check_quota_) { 399 check_quota_ = false; 400 file_system_resource_->AsPPB_FileSystem_API()->CloseQuotaFile( 401 pp_resource()); 402 } 403 404 if (file_handle_) 405 file_handle_ = NULL; 406 407 Post(BROWSER, PpapiHostMsg_FileIO_Close( 408 FileGrowth(max_written_offset_, append_mode_write_amount_))); 409} 410 411int32_t FileIOResource::RequestOSFileHandle( 412 PP_FileHandle* handle, 413 scoped_refptr<TrackedCallback> callback) { 414 int32_t rv = state_manager_.CheckOperationState( 415 FileIOStateManager::OPERATION_EXCLUSIVE, true); 416 if (rv != PP_OK) 417 return rv; 418 419 Call<PpapiPluginMsg_FileIO_RequestOSFileHandleReply>(BROWSER, 420 PpapiHostMsg_FileIO_RequestOSFileHandle(), 421 base::Bind(&FileIOResource::OnPluginMsgRequestOSFileHandleComplete, this, 422 callback, handle)); 423 424 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); 425 return PP_OK_COMPLETIONPENDING; 426} 427 428FileIOResource::FileHandleHolder::FileHandleHolder(PP_FileHandle file_handle) 429 : raw_handle_(file_handle) { 430} 431 432// static 433bool FileIOResource::FileHandleHolder::IsValid( 434 const scoped_refptr<FileIOResource::FileHandleHolder>& handle) { 435 return handle && (handle->raw_handle() != base::kInvalidPlatformFileValue); 436} 437 438FileIOResource::FileHandleHolder::~FileHandleHolder() { 439 if (raw_handle_ != base::kInvalidPlatformFileValue) { 440 base::TaskRunner* file_task_runner = 441 PpapiGlobals::Get()->GetFileTaskRunner(); 442 file_task_runner->PostTask(FROM_HERE, 443 base::Bind(&DoClose, raw_handle_)); 444 } 445} 446 447int32_t FileIOResource::ReadValidated(int64_t offset, 448 int32_t bytes_to_read, 449 const PP_ArrayOutput& array_output, 450 scoped_refptr<TrackedCallback> callback) { 451 if (bytes_to_read < 0) 452 return PP_ERROR_FAILED; 453 if (!FileHandleHolder::IsValid(file_handle_)) 454 return PP_ERROR_FAILED; 455 456 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ); 457 458 bytes_to_read = std::min(bytes_to_read, kMaxReadWriteSize); 459 if (callback->is_blocking()) { 460 char* buffer = static_cast<char*>( 461 array_output.GetDataBuffer(array_output.user_data, bytes_to_read, 1)); 462 int32_t result = PP_ERROR_FAILED; 463 // The plugin could release its reference to this instance when we release 464 // the proxy lock below. 465 scoped_refptr<FileIOResource> protect(this); 466 if (buffer) { 467 // Release the proxy lock while making a potentially slow file call. 468 ProxyAutoUnlock unlock; 469 result = base::ReadPlatformFile( 470 file_handle_->raw_handle(), offset, buffer, bytes_to_read); 471 if (result < 0) 472 result = PP_ERROR_FAILED; 473 } 474 state_manager_.SetOperationFinished(); 475 return result; 476 } 477 478 // For the non-blocking case, post a task to the file thread. 479 scoped_refptr<ReadOp> read_op( 480 new ReadOp(file_handle_, offset, bytes_to_read)); 481 base::PostTaskAndReplyWithResult( 482 PpapiGlobals::Get()->GetFileTaskRunner(), 483 FROM_HERE, 484 Bind(&FileIOResource::ReadOp::DoWork, read_op), 485 RunWhileLocked(Bind(&TrackedCallback::Run, callback))); 486 callback->set_completion_task( 487 Bind(&FileIOResource::OnReadComplete, this, read_op, array_output)); 488 489 return PP_OK_COMPLETIONPENDING; 490} 491 492int32_t FileIOResource::WriteValidated( 493 int64_t offset, 494 const char* buffer, 495 int32_t bytes_to_write, 496 scoped_refptr<TrackedCallback> callback) { 497 bool append = (open_flags_ & PP_FILEOPENFLAG_APPEND) != 0; 498 if (callback->is_blocking()) { 499 int32_t result; 500 { 501 // Release the proxy lock while making a potentially slow file call. 502 ProxyAutoUnlock unlock; 503 if (append) { 504 result = base::WritePlatformFileAtCurrentPos( 505 file_handle_->raw_handle(), buffer, bytes_to_write); 506 } else { 507 result = base::WritePlatformFile( 508 file_handle_->raw_handle(), offset, buffer, bytes_to_write); 509 } 510 } 511 if (result < 0) 512 result = PP_ERROR_FAILED; 513 514 state_manager_.SetOperationFinished(); 515 return result; 516 } 517 518 // For the non-blocking case, post a task to the file thread. 519 scoped_refptr<WriteOp> write_op( 520 new WriteOp(file_handle_, offset, buffer, bytes_to_write, append)); 521 base::PostTaskAndReplyWithResult( 522 PpapiGlobals::Get()->GetFileTaskRunner(), 523 FROM_HERE, 524 Bind(&FileIOResource::WriteOp::DoWork, write_op), 525 RunWhileLocked(Bind(&TrackedCallback::Run, callback))); 526 callback->set_completion_task( 527 Bind(&FileIOResource::OnWriteComplete, this, write_op)); 528 529 return PP_OK_COMPLETIONPENDING; 530} 531 532void FileIOResource::SetLengthValidated( 533 int64_t length, 534 scoped_refptr<TrackedCallback> callback) { 535 Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER, 536 PpapiHostMsg_FileIO_SetLength(length), 537 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, 538 callback)); 539 540 // On the browser side we grow |max_written_offset_| monotonically, due to the 541 // unpredictable ordering of plugin side Write and SetLength calls. Match that 542 // behavior here. 543 if (max_written_offset_ < length) 544 max_written_offset_ = length; 545} 546 547int32_t FileIOResource::OnQueryComplete(scoped_refptr<QueryOp> query_op, 548 PP_FileInfo* info, 549 int32_t result) { 550 DCHECK(state_manager_.get_pending_operation() == 551 FileIOStateManager::OPERATION_EXCLUSIVE); 552 553 if (result == PP_OK) { 554 // This writes the file info into the plugin's PP_FileInfo struct. 555 ppapi::FileInfoToPepperFileInfo(query_op->file_info(), 556 file_system_type_, 557 info); 558 } 559 state_manager_.SetOperationFinished(); 560 return result; 561} 562 563int32_t FileIOResource::OnReadComplete(scoped_refptr<ReadOp> read_op, 564 PP_ArrayOutput array_output, 565 int32_t result) { 566 DCHECK(state_manager_.get_pending_operation() == 567 FileIOStateManager::OPERATION_READ); 568 if (result >= 0) { 569 ArrayWriter output; 570 output.set_pp_array_output(array_output); 571 if (output.is_valid()) 572 output.StoreArray(read_op->buffer(), result); 573 else 574 result = PP_ERROR_FAILED; 575 } else { 576 // The read operation failed. 577 result = PP_ERROR_FAILED; 578 } 579 state_manager_.SetOperationFinished(); 580 return result; 581} 582 583void FileIOResource::OnRequestWriteQuotaComplete( 584 int64_t offset, 585 const char* buffer, 586 int32_t bytes_to_write, 587 scoped_refptr<TrackedCallback> callback, 588 int64_t granted) { 589 DCHECK(granted >= 0); 590 if (granted == 0) { 591 callback->Run(PP_ERROR_NOQUOTA); 592 return; 593 } 594 if (open_flags_ & PP_FILEOPENFLAG_APPEND) { 595 DCHECK_LE(bytes_to_write, granted); 596 append_mode_write_amount_ += bytes_to_write; 597 } else { 598 DCHECK_LE(offset + bytes_to_write - max_written_offset_, granted); 599 600 int64_t max_offset = offset + bytes_to_write; 601 if (max_written_offset_ < max_offset) 602 max_written_offset_ = max_offset; 603 } 604 605 int32_t result = WriteValidated(offset, buffer, bytes_to_write, callback); 606 if (result != PP_OK_COMPLETIONPENDING) 607 callback->Run(result); 608} 609 610void FileIOResource::OnRequestSetLengthQuotaComplete( 611 int64_t length, 612 scoped_refptr<TrackedCallback> callback, 613 int64_t granted) { 614 DCHECK(granted >= 0); 615 if (granted == 0) { 616 callback->Run(PP_ERROR_NOQUOTA); 617 return; 618 } 619 620 DCHECK_LE(length - max_written_offset_, granted); 621 if (max_written_offset_ < length) 622 max_written_offset_ = length; 623 SetLengthValidated(length, callback); 624} 625 626int32_t FileIOResource::OnWriteComplete(scoped_refptr<WriteOp> write_op, 627 int32_t result) { 628 DCHECK(state_manager_.get_pending_operation() == 629 FileIOStateManager::OPERATION_WRITE); 630 // |result| is the return value of WritePlatformFile; -1 indicates failure. 631 if (result < 0) 632 result = PP_ERROR_FAILED; 633 634 state_manager_.SetOperationFinished(); 635 return result; 636} 637 638void FileIOResource::OnPluginMsgGeneralComplete( 639 scoped_refptr<TrackedCallback> callback, 640 const ResourceMessageReplyParams& params) { 641 DCHECK(state_manager_.get_pending_operation() == 642 FileIOStateManager::OPERATION_EXCLUSIVE || 643 state_manager_.get_pending_operation() == 644 FileIOStateManager::OPERATION_WRITE); 645 // End this operation now, so the user's callback can execute another FileIO 646 // operation, assuming there are no other pending operations. 647 state_manager_.SetOperationFinished(); 648 callback->Run(params.result()); 649} 650 651void FileIOResource::OnPluginMsgOpenFileComplete( 652 scoped_refptr<TrackedCallback> callback, 653 const ResourceMessageReplyParams& params, 654 PP_Resource quota_file_system, 655 int64_t max_written_offset) { 656 DCHECK(state_manager_.get_pending_operation() == 657 FileIOStateManager::OPERATION_EXCLUSIVE); 658 659 // Release the FileRef resource. 660 file_ref_ = NULL; 661 int32_t result = params.result(); 662 if (result == PP_OK) { 663 state_manager_.SetOpenSucceed(); 664 665 if (quota_file_system) { 666 DCHECK(quota_file_system == file_system_resource_->pp_resource()); 667 check_quota_ = true; 668 max_written_offset_ = max_written_offset; 669 file_system_resource_->AsPPB_FileSystem_API()->OpenQuotaFile( 670 pp_resource()); 671 } 672 673 IPC::PlatformFileForTransit transit_file; 674 if (params.TakeFileHandleAtIndex(0, &transit_file)) { 675 file_handle_ = new FileHandleHolder( 676 IPC::PlatformFileForTransitToPlatformFile(transit_file)); 677 } 678 } 679 // End this operation now, so the user's callback can execute another FileIO 680 // operation, assuming there are no other pending operations. 681 state_manager_.SetOperationFinished(); 682 callback->Run(result); 683} 684 685void FileIOResource::OnPluginMsgRequestOSFileHandleComplete( 686 scoped_refptr<TrackedCallback> callback, 687 PP_FileHandle* output_handle, 688 const ResourceMessageReplyParams& params) { 689 DCHECK(state_manager_.get_pending_operation() == 690 FileIOStateManager::OPERATION_EXCLUSIVE); 691 692 if (!TrackedCallback::IsPending(callback)) { 693 state_manager_.SetOperationFinished(); 694 return; 695 } 696 697 int32_t result = params.result(); 698 IPC::PlatformFileForTransit transit_file; 699 if (!params.TakeFileHandleAtIndex(0, &transit_file)) 700 result = PP_ERROR_FAILED; 701 *output_handle = IPC::PlatformFileForTransitToPlatformFile(transit_file); 702 703 // End this operation now, so the user's callback can execute another FileIO 704 // operation, assuming there are no other pending operations. 705 state_manager_.SetOperationFinished(); 706 callback->Run(result); 707} 708 709} // namespace proxy 710} // namespace ppapi 711