12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/proxy/file_io_resource.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 8ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/task_runner_util.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/ipc_message.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/c/pp_errors.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/shared_impl/array_writer.h" 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ppapi/shared_impl/file_ref_create_info.h" 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ppapi/shared_impl/file_system_util.h" 15ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ppapi/shared_impl/file_type_conversion.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/shared_impl/ppapi_globals.h" 17ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ppapi/shared_impl/proxy_lock.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/shared_impl/resource_tracker.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/thunk/enter.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/thunk/ppb_file_ref_api.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/thunk/ppb_file_system_api.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ppapi::thunk::EnterResourceNoLock; 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ppapi::thunk::PPB_FileIO_API; 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ppapi::thunk::PPB_FileRef_API; 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using ppapi::thunk::PPB_FileSystem_API; 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 30ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// We must allocate a buffer sized according to the request of the plugin. To 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// reduce the chance of out-of-memory errors, we cap the read and write size to 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 32MB. This is OK since the API specifies that it may perform a partial read 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// or write. 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static const int32_t kMaxReadWriteSize = 32 * 1024 * 1024; // 32MB 35ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// An adapter to let Read() share the same implementation with ReadToArray(). 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void* DummyGetDataBuffer(void* user_data, uint32_t count, uint32_t size) { 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return user_data; 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 41ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// File thread task to close the file handle. 4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void DoClose(base::File auto_close_file) { 43ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 44ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace ppapi { 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace proxy { 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)FileIOResource::QueryOp::QueryOp(scoped_refptr<FileHolder> file_holder) 5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) : file_holder_(file_holder) { 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(file_holder_.get()); 53ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 54ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 55ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochFileIOResource::QueryOp::~QueryOp() { 56ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 57ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 58ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochint32_t FileIOResource::QueryOp::DoWork() { 5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return file_holder_->file()->GetInfo(&file_info_) ? PP_OK : PP_ERROR_FAILED; 60ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 61ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)FileIOResource::ReadOp::ReadOp(scoped_refptr<FileHolder> file_holder, 63ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch int64_t offset, 64ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch int32_t bytes_to_read) 6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) : file_holder_(file_holder), 66ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch offset_(offset), 67ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bytes_to_read_(bytes_to_read) { 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(file_holder_.get()); 69ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 70ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 71ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochFileIOResource::ReadOp::~ReadOp() { 72ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 73ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 74ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochint32_t FileIOResource::ReadOp::DoWork() { 75ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(!buffer_.get()); 76ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch buffer_.reset(new char[bytes_to_read_]); 7746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return file_holder_->file()->Read(offset_, buffer_.get(), bytes_to_read_); 78ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 79ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)FileIOResource::WriteOp::WriteOp(scoped_refptr<FileHolder> file_holder, 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t offset, 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<char[]> buffer, 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int32_t bytes_to_write, 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool append) 8546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) : file_holder_(file_holder), 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) offset_(offset), 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) buffer_(buffer.Pass()), 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bytes_to_write_(bytes_to_write), 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) append_(append) { 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)FileIOResource::WriteOp::~WriteOp() { 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int32_t FileIOResource::WriteOp::DoWork() { 9646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // In append mode, we can't call Write, since NaCl doesn't implement fcntl, 9746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // causing the function to call pwrite, which is incorrect. 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (append_) { 9946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return file_holder_->file()->WriteAtCurrentPos(buffer_.get(), 10046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bytes_to_write_); 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 10246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return file_holder_->file()->Write(offset_, buffer_.get(), bytes_to_write_); 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FileIOResource::FileIOResource(Connection connection, PP_Instance instance) 107ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch : PluginResource(connection, instance), 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_system_type_(PP_FILESYSTEMTYPE_INVALID), 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) open_flags_(0), 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) max_written_offset_(0), 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) append_mode_write_amount_(0), 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) check_quota_(false), 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) called_close_(false) { 1140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) SendCreate(BROWSER, PpapiHostMsg_FileIO_Create()); 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FileIOResource::~FileIOResource() { 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Close(); 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PPB_FileIO_API* FileIOResource::AsPPB_FileIO_API() { 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return this; 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::Open(PP_Resource file_ref, 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32_t open_flags, 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<TrackedCallback> callback) { 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EnterResourceNoLock<PPB_FileRef_API> enter_file_ref(file_ref, true); 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (enter_file_ref.failed()) 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return PP_ERROR_BADRESOURCE; 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PPB_FileRef_API* file_ref_api = enter_file_ref.object(); 133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const FileRefCreateInfo& create_info = file_ref_api->GetCreateInfo(); 134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!FileSystemTypeIsValid(create_info.file_system_type)) { 135ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch NOTREACHED(); 136ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return PP_ERROR_FAILED; 137ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32_t rv = state_manager_.CheckOperationState( 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FileIOStateManager::OPERATION_EXCLUSIVE, false); 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv != PP_OK) 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) open_flags_ = open_flags; 144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) file_system_type_ = create_info.file_system_type; 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (create_info.file_system_plugin_resource) { 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EnterResourceNoLock<PPB_FileSystem_API> enter_file_system( 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) create_info.file_system_plugin_resource, true); 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (enter_file_system.failed()) 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_ERROR_FAILED; 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Take a reference on the FileSystem resource. The FileIO host uses the 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // FileSystem host for running tasks and checking quota. 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_system_resource_ = enter_file_system.resource(); 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 156d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Take a reference on the FileRef resource while we're opening the file; we 157d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // don't want the plugin destroying it during the Open operation. 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_ref_ = enter_file_ref.resource(); 159d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 1600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) Call<PpapiPluginMsg_FileIO_OpenReply>(BROWSER, 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PpapiHostMsg_FileIO_Open( 162d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) file_ref, 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) open_flags), 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&FileIOResource::OnPluginMsgOpenFileComplete, this, 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback)); 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return PP_OK_COMPLETIONPENDING; 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::Query(PP_FileInfo* info, 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<TrackedCallback> callback) { 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32_t rv = state_manager_.CheckOperationState( 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FileIOStateManager::OPERATION_EXCLUSIVE, true); 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv != PP_OK) 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 177ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!info) 178ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return PP_ERROR_BADARGUMENT; 17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!FileHolder::IsValid(file_holder_)) 180ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return PP_ERROR_FAILED; 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); 183ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 184ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If the callback is blocking, perform the task on the calling thread. 185ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (callback->is_blocking()) { 1861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int32_t result = PP_ERROR_FAILED; 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::File::Info file_info; 1881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // The plugin could release its reference to this instance when we release 1891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // the proxy lock below. 1901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_refptr<FileIOResource> protect(this); 191ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch { 192ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Release the proxy lock while making a potentially slow file call. 193ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ProxyAutoUnlock unlock; 19446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (file_holder_->file()->GetInfo(&file_info)) 1951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) result = PP_OK; 1961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (result == PP_OK) { 1981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // This writes the file info into the plugin's PP_FileInfo struct. 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ppapi::FileInfoToPepperFileInfo(file_info, 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_system_type_, 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) info); 202ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 2031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) state_manager_.SetOperationFinished(); 2041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return result; 205ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 206ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 207ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // For the non-blocking case, post a task to the file thread and add a 208ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // completion task to write the result. 20946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_refptr<QueryOp> query_op(new QueryOp(file_holder_)); 210ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::PostTaskAndReplyWithResult( 2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) PpapiGlobals::Get()->GetFileTaskRunner(), 212ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch FROM_HERE, 213ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch Bind(&FileIOResource::QueryOp::DoWork, query_op), 214ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch RunWhileLocked(Bind(&TrackedCallback::Run, callback))); 215ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch callback->set_completion_task( 216ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch Bind(&FileIOResource::OnQueryComplete, this, query_op, info)); 217ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return PP_OK_COMPLETIONPENDING; 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::Touch(PP_Time last_access_time, 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PP_Time last_modified_time, 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<TrackedCallback> callback) { 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32_t rv = state_manager_.CheckOperationState( 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FileIOStateManager::OPERATION_EXCLUSIVE, true); 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv != PP_OK) 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER, 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PpapiHostMsg_FileIO_Touch(last_access_time, last_modified_time), 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback)); 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return PP_OK_COMPLETIONPENDING; 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::Read(int64_t offset, 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) char* buffer, 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32_t bytes_to_read, 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<TrackedCallback> callback) { 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32_t rv = state_manager_.CheckOperationState( 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FileIOStateManager::OPERATION_READ, true); 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv != PP_OK) 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PP_ArrayOutput output_adapter; 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_adapter.GetDataBuffer = &DummyGetDataBuffer; 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_adapter.user_data = buffer; 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ReadValidated(offset, bytes_to_read, output_adapter, callback); 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::ReadToArray(int64_t offset, 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32_t max_read_length, 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PP_ArrayOutput* array_output, 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<TrackedCallback> callback) { 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(array_output); 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32_t rv = state_manager_.CheckOperationState( 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FileIOStateManager::OPERATION_READ, true); 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv != PP_OK) 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ReadValidated(offset, max_read_length, *array_output, callback); 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::Write(int64_t offset, 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* buffer, 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32_t bytes_to_write, 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<TrackedCallback> callback) { 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!buffer) 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_ERROR_FAILED; 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (offset < 0 || bytes_to_write < 0) 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_ERROR_FAILED; 27446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!FileHolder::IsValid(file_holder_)) 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_ERROR_FAILED; 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32_t rv = state_manager_.CheckOperationState( 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FileIOStateManager::OPERATION_WRITE, true); 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv != PP_OK) 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_WRITE); 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (check_quota_) { 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t increase = 0; 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64_t max_offset = 0; 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool append = (open_flags_ & PP_FILEOPENFLAG_APPEND) != 0; 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (append) { 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) increase = bytes_to_write; 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64_t max_offset = offset + bytes_to_write; 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (max_offset > static_cast<uint64_t>(kint64max)) 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_ERROR_FAILED; // amount calculation would overflow. 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) increase = static_cast<int64_t>(max_offset) - max_written_offset_; 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (increase > 0) { 298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Request a quota reservation. This makes the Write asynchronous, so we 299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // must copy the plugin's buffer. 300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<char[]> copy(new char[bytes_to_write]); 301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) memcpy(copy.get(), buffer, bytes_to_write); 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t result = 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_system_resource_->AsPPB_FileSystem_API()->RequestQuota( 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) increase, 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&FileIOResource::OnRequestWriteQuotaComplete, 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this, 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) offset, 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Passed(©), 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bytes_to_write, 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callback)); 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (result == PP_OK_COMPLETIONPENDING) 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_OK_COMPLETIONPENDING; 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(result == increase); 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (append) 3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) append_mode_write_amount_ += bytes_to_write; 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) max_written_offset_ = max_offset; 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return WriteValidated(offset, buffer, bytes_to_write, callback); 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::SetLength(int64_t length, 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<TrackedCallback> callback) { 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32_t rv = state_manager_.CheckOperationState( 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FileIOStateManager::OPERATION_EXCLUSIVE, true); 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv != PP_OK) 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (length < 0) 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_ERROR_FAILED; 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (check_quota_) { 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t increase = length - max_written_offset_; 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (increase > 0) { 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int32_t result = 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_system_resource_->AsPPB_FileSystem_API()->RequestQuota( 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) increase, 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&FileIOResource::OnRequestSetLengthQuotaComplete, 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this, 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) length, callback)); 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (result == PP_OK_COMPLETIONPENDING) { 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) state_manager_.SetPendingOperation( 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileIOStateManager::OPERATION_EXCLUSIVE); 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_OK_COMPLETIONPENDING; 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(result == increase); 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) max_written_offset_ = length; 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetLengthValidated(length, callback); 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return PP_OK_COMPLETIONPENDING; 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::Flush(scoped_refptr<TrackedCallback> callback) { 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32_t rv = state_manager_.CheckOperationState( 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FileIOStateManager::OPERATION_EXCLUSIVE, true); 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv != PP_OK) 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER, 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PpapiHostMsg_FileIO_Flush(), 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback)); 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return PP_OK_COMPLETIONPENDING; 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int64_t FileIOResource::GetMaxWrittenOffset() const { 3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return max_written_offset_; 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int64_t FileIOResource::GetAppendModeWriteAmount() const { 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return append_mode_write_amount_; 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FileIOResource::SetMaxWrittenOffset(int64_t max_written_offset) { 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) max_written_offset_ = max_written_offset; 3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FileIOResource::SetAppendModeWriteAmount( 3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t append_mode_write_amount) { 3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) append_mode_write_amount_ = append_mode_write_amount; 3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FileIOResource::Close() { 3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (called_close_) 3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) called_close_ = true; 3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (check_quota_) { 3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) check_quota_ = false; 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_system_resource_->AsPPB_FileSystem_API()->CloseQuotaFile( 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pp_resource()); 3984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (file_holder_.get()) 40146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) file_holder_ = NULL; 4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Post(BROWSER, PpapiHostMsg_FileIO_Close( 4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileGrowth(max_written_offset_, append_mode_write_amount_))); 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 407ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochint32_t FileIOResource::RequestOSFileHandle( 408ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PP_FileHandle* handle, 409ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch scoped_refptr<TrackedCallback> callback) { 410ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch int32_t rv = state_manager_.CheckOperationState( 411ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch FileIOStateManager::OPERATION_EXCLUSIVE, true); 412ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (rv != PP_OK) 413ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return rv; 414ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 4150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) Call<PpapiPluginMsg_FileIO_RequestOSFileHandleReply>(BROWSER, 416ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PpapiHostMsg_FileIO_RequestOSFileHandle(), 417ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::Bind(&FileIOResource::OnPluginMsgRequestOSFileHandleComplete, this, 418ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch callback, handle)); 419ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 420ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); 421ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return PP_OK_COMPLETIONPENDING; 422ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 423ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 42446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)FileIOResource::FileHolder::FileHolder(PP_FileHandle file_handle) 42546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) : file_(file_handle) { 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// static 42946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool FileIOResource::FileHolder::IsValid( 43046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const scoped_refptr<FileIOResource::FileHolder>& handle) { 4311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return handle.get() && handle->file_.IsValid(); 4324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 433ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 43446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)FileIOResource::FileHolder::~FileHolder() { 43546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (file_.IsValid()) { 4364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::TaskRunner* file_task_runner = 4374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) PpapiGlobals::Get()->GetFileTaskRunner(); 4384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_task_runner->PostTask(FROM_HERE, 43946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&DoClose, Passed(&file_))); 4404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::ReadValidated(int64_t offset, 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32_t bytes_to_read, 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const PP_ArrayOutput& array_output, 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<TrackedCallback> callback) { 447ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (bytes_to_read < 0) 448ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return PP_ERROR_FAILED; 44946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!FileHolder::IsValid(file_holder_)) 450ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return PP_ERROR_FAILED; 451ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 452ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ); 453ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bytes_to_read = std::min(bytes_to_read, kMaxReadWriteSize); 455ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (callback->is_blocking()) { 4561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) char* buffer = static_cast<char*>( 4571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) array_output.GetDataBuffer(array_output.user_data, bytes_to_read, 1)); 4581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int32_t result = PP_ERROR_FAILED; 4591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // The plugin could release its reference to this instance when we release 4601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // the proxy lock below. 4611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_refptr<FileIOResource> protect(this); 4621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (buffer) { 463ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Release the proxy lock while making a potentially slow file call. 464ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ProxyAutoUnlock unlock; 46546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) result = file_holder_->file()->Read(offset, buffer, bytes_to_read); 4661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (result < 0) 4671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) result = PP_ERROR_FAILED; 468ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 4691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) state_manager_.SetOperationFinished(); 4701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return result; 471ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 472ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 473ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // For the non-blocking case, post a task to the file thread. 4741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_refptr<ReadOp> read_op( 47546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new ReadOp(file_holder_, offset, bytes_to_read)); 476ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::PostTaskAndReplyWithResult( 4774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) PpapiGlobals::Get()->GetFileTaskRunner(), 478ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch FROM_HERE, 479ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch Bind(&FileIOResource::ReadOp::DoWork, read_op), 480ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch RunWhileLocked(Bind(&TrackedCallback::Run, callback))); 481ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch callback->set_completion_task( 482ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch Bind(&FileIOResource::OnReadComplete, this, read_op, array_output)); 483ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return PP_OK_COMPLETIONPENDING; 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int32_t FileIOResource::WriteValidated( 4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t offset, 4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const char* buffer, 4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int32_t bytes_to_write, 4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<TrackedCallback> callback) { 4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool append = (open_flags_ & PP_FILEOPENFLAG_APPEND) != 0; 4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (callback->is_blocking()) { 4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int32_t result; 4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) { 4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Release the proxy lock while making a potentially slow file call. 4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ProxyAutoUnlock unlock; 4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (append) { 49946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) result = file_holder_->file()->WriteAtCurrentPos(buffer, 50046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bytes_to_write); 5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 50246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) result = file_holder_->file()->Write(offset, buffer, bytes_to_write); 5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (result < 0) 5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result = PP_ERROR_FAILED; 5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) state_manager_.SetOperationFinished(); 5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return result; 5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 512cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // For the non-blocking case, post a task to the file thread. We must copy the 513cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // plugin's buffer at this point. 514cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<char[]> copy(new char[bytes_to_write]); 515cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) memcpy(copy.get(), buffer, bytes_to_write); 5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<WriteOp> write_op( 51746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new WriteOp(file_holder_, offset, copy.Pass(), bytes_to_write, append)); 5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::PostTaskAndReplyWithResult( 5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PpapiGlobals::Get()->GetFileTaskRunner(), 5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Bind(&FileIOResource::WriteOp::DoWork, write_op), 5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunWhileLocked(Bind(&TrackedCallback::Run, callback))); 523cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callback->set_completion_task(Bind(&FileIOResource::OnWriteComplete, this)); 5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PP_OK_COMPLETIONPENDING; 5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FileIOResource::SetLengthValidated( 5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t length, 5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<TrackedCallback> callback) { 5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER, 5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PpapiHostMsg_FileIO_SetLength(length), 5335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, 5345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback)); 5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // On the browser side we grow |max_written_offset_| monotonically, due to the 5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // unpredictable ordering of plugin side Write and SetLength calls. Match that 5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // behavior here. 5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (max_written_offset_ < length) 5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) max_written_offset_ = length; 5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 543ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochint32_t FileIOResource::OnQueryComplete(scoped_refptr<QueryOp> query_op, 544ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PP_FileInfo* info, 545ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch int32_t result) { 546ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(state_manager_.get_pending_operation() == 547ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch FileIOStateManager::OPERATION_EXCLUSIVE); 548ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 549ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (result == PP_OK) { 550ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // This writes the file info into the plugin's PP_FileInfo struct. 5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ppapi::FileInfoToPepperFileInfo(query_op->file_info(), 5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_system_type_, 5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) info); 554ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 555ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch state_manager_.SetOperationFinished(); 556ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return result; 557ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 558ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 559ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochint32_t FileIOResource::OnReadComplete(scoped_refptr<ReadOp> read_op, 560ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PP_ArrayOutput array_output, 561ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch int32_t result) { 562ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(state_manager_.get_pending_operation() == 563ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch FileIOStateManager::OPERATION_READ); 564ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (result >= 0) { 565ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ArrayWriter output; 566ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch output.set_pp_array_output(array_output); 567ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (output.is_valid()) 568ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch output.StoreArray(read_op->buffer(), result); 569ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch else 570ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch result = PP_ERROR_FAILED; 571ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } else { 572ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // The read operation failed. 573ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch result = PP_ERROR_FAILED; 574ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 575ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch state_manager_.SetOperationFinished(); 576ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return result; 577c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FileIOResource::OnRequestWriteQuotaComplete( 5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t offset, 581cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<char[]> buffer, 5825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int32_t bytes_to_write, 5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<TrackedCallback> callback, 5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t granted) { 5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(granted >= 0); 5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (granted == 0) { 5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback->Run(PP_ERROR_NOQUOTA); 5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (open_flags_ & PP_FILEOPENFLAG_APPEND) { 5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_LE(bytes_to_write, granted); 5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) append_mode_write_amount_ += bytes_to_write; 5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 5945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_LE(offset + bytes_to_write - max_written_offset_, granted); 5955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t max_offset = offset + bytes_to_write; 5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (max_written_offset_ < max_offset) 5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) max_written_offset_ = max_offset; 5995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 601cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (callback->is_blocking()) { 602cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int32_t result = 603cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) WriteValidated(offset, buffer.get(), bytes_to_write, callback); 604cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(result != PP_OK_COMPLETIONPENDING); 6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback->Run(result); 606cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 607cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool append = (open_flags_ & PP_FILEOPENFLAG_APPEND) != 0; 608cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<WriteOp> write_op(new WriteOp( 60946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) file_holder_, offset, buffer.Pass(), bytes_to_write, append)); 610cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::PostTaskAndReplyWithResult( 611cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PpapiGlobals::Get()->GetFileTaskRunner(), 612cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 613cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Bind(&FileIOResource::WriteOp::DoWork, write_op), 614cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) RunWhileLocked(Bind(&TrackedCallback::Run, callback))); 615cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callback->set_completion_task(Bind(&FileIOResource::OnWriteComplete, this)); 616cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FileIOResource::OnRequestSetLengthQuotaComplete( 6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t length, 6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<TrackedCallback> callback, 6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t granted) { 6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(granted >= 0); 6245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (granted == 0) { 6255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback->Run(PP_ERROR_NOQUOTA); 6265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 6275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_LE(length - max_written_offset_, granted); 6305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (max_written_offset_ < length) 6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) max_written_offset_ = length; 6325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetLengthValidated(length, callback); 6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 635cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int32_t FileIOResource::OnWriteComplete(int32_t result) { 6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(state_manager_.get_pending_operation() == 6375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileIOStateManager::OPERATION_WRITE); 6385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // |result| is the return value of WritePlatformFile; -1 indicates failure. 6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (result < 0) 6405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result = PP_ERROR_FAILED; 6415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) state_manager_.SetOperationFinished(); 6435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return result; 6445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FileIOResource::OnPluginMsgGeneralComplete( 6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<TrackedCallback> callback, 6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ResourceMessageReplyParams& params) { 6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(state_manager_.get_pending_operation() == 6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FileIOStateManager::OPERATION_EXCLUSIVE || 6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_manager_.get_pending_operation() == 6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FileIOStateManager::OPERATION_WRITE); 653ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // End this operation now, so the user's callback can execute another FileIO 654ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // operation, assuming there are no other pending operations. 6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_manager_.SetOperationFinished(); 6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback->Run(params.result()); 6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FileIOResource::OnPluginMsgOpenFileComplete( 6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<TrackedCallback> callback, 6615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ResourceMessageReplyParams& params, 6625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_Resource quota_file_system, 6635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t max_written_offset) { 6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(state_manager_.get_pending_operation() == 6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FileIOStateManager::OPERATION_EXCLUSIVE); 666d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 667d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Release the FileRef resource. 668d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) file_ref_ = NULL; 6695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int32_t result = params.result(); 6705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (result == PP_OK) { 6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_manager_.SetOpenSucceed(); 672a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 6735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (quota_file_system) { 6745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(quota_file_system == file_system_resource_->pp_resource()); 6755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) check_quota_ = true; 6765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) max_written_offset_ = max_written_offset; 6775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_system_resource_->AsPPB_FileSystem_API()->OpenQuotaFile( 6785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pp_resource()); 6795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IPC::PlatformFileForTransit transit_file; 6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (params.TakeFileHandleAtIndex(0, &transit_file)) { 68346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) file_holder_ = new FileHolder( 6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IPC::PlatformFileForTransitToPlatformFile(transit_file)); 6855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 687ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // End this operation now, so the user's callback can execute another FileIO 688ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // operation, assuming there are no other pending operations. 6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_manager_.SetOperationFinished(); 690a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) callback->Run(result); 6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 693c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void FileIOResource::OnPluginMsgRequestOSFileHandleComplete( 694c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<TrackedCallback> callback, 695c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PP_FileHandle* output_handle, 696c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ResourceMessageReplyParams& params) { 697c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(state_manager_.get_pending_operation() == 698c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FileIOStateManager::OPERATION_EXCLUSIVE); 699c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 700c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!TrackedCallback::IsPending(callback)) { 701c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) state_manager_.SetOperationFinished(); 702c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 703c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 704c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 705c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int32_t result = params.result(); 706c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) IPC::PlatformFileForTransit transit_file; 707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!params.TakeFileHandleAtIndex(0, &transit_file)) 708c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result = PP_ERROR_FAILED; 709c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *output_handle = IPC::PlatformFileForTransitToPlatformFile(transit_file); 710c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 711ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // End this operation now, so the user's callback can execute another FileIO 712ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // operation, assuming there are no other pending operations. 713c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) state_manager_.SetOperationFinished(); 714c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) callback->Run(result); 715c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 716c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace proxy 7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace ppapi 719