Chromium Code Reviews| Index: ppapi/proxy/file_io_resource.cc |
| diff --git a/ppapi/proxy/file_io_resource.cc b/ppapi/proxy/file_io_resource.cc |
| index 7d98356994abc5765634ee5b997d5f10fbdd402d..da5728479558f74217f6d54c1fa0b324b772c3df 100644 |
| --- a/ppapi/proxy/file_io_resource.cc |
| +++ b/ppapi/proxy/file_io_resource.cc |
| @@ -5,11 +5,15 @@ |
| #include "ppapi/proxy/file_io_resource.h" |
| #include "base/bind.h" |
| +#include "base/files/file_util_proxy.h" |
| #include "ipc/ipc_message.h" |
| #include "ppapi/c/pp_errors.h" |
| +#include "ppapi/proxy/plugin_globals.h" |
| #include "ppapi/proxy/ppapi_messages.h" |
| #include "ppapi/shared_impl/array_writer.h" |
| +#include "ppapi/shared_impl/file_type_conversion.h" |
| #include "ppapi/shared_impl/ppapi_globals.h" |
| +#include "ppapi/shared_impl/proxy_lock.h" |
| #include "ppapi/shared_impl/resource_tracker.h" |
| #include "ppapi/thunk/enter.h" |
| #include "ppapi/thunk/ppb_file_ref_api.h" |
| @@ -25,17 +29,24 @@ void* DummyGetDataBuffer(void* user_data, uint32_t count, uint32_t size) { |
| return user_data; |
| } |
| +// Dummy close callback allows us to call CloseFileHandle in the destructor. |
| +void DummyCloseCallback(base::PlatformFileError error_code) { |
| +} |
| + |
| } // namespace |
| namespace ppapi { |
| namespace proxy { |
| FileIOResource::FileIOResource(Connection connection, PP_Instance instance) |
| - : PluginResource(connection, instance) { |
| + : PluginResource(connection, instance), |
| + file_handle_(PP_kInvalidFileHandle), |
| + file_system_type_(PP_FILESYSTEMTYPE_INVALID) { |
| SendCreate(RENDERER, PpapiHostMsg_FileIO_Create()); |
| } |
| FileIOResource::~FileIOResource() { |
| + CloseFileHandle(); |
| } |
| PPB_FileIO_API* FileIOResource::AsPPB_FileIO_API() { |
| @@ -49,6 +60,17 @@ int32_t FileIOResource::Open(PP_Resource file_ref, |
| if (enter.failed()) |
| return PP_ERROR_BADRESOURCE; |
| + PPB_FileRef_API* file_ref_api = enter.object(); |
| + PP_FileSystemType type = file_ref_api->GetFileSystemType(); |
| + if (type != PP_FILESYSTEMTYPE_LOCALPERSISTENT && |
| + type != PP_FILESYSTEMTYPE_LOCALTEMPORARY && |
| + type != PP_FILESYSTEMTYPE_EXTERNAL && |
| + type != PP_FILESYSTEMTYPE_ISOLATED) { |
| + NOTREACHED(); |
| + return PP_ERROR_FAILED; |
| + } |
| + file_system_type_ = type; |
| + |
| int32_t rv = state_manager_.CheckOperationState( |
| FileIOStateManager::OPERATION_EXCLUSIVE, false); |
| if (rv != PP_OK) |
| @@ -72,11 +94,17 @@ int32_t FileIOResource::Query(PP_FileInfo* info, |
| if (rv != PP_OK) |
| return rv; |
| - Call<PpapiPluginMsg_FileIO_QueryReply>(RENDERER, |
| - PpapiHostMsg_FileIO_Query(), |
| - base::Bind(&FileIOResource::OnPluginMsgQueryComplete, this, |
| - callback, info)); |
| + if (file_handle_ == base::kInvalidPlatformFileValue) |
| + return PP_ERROR_FAILED; |
| + PassedRef passed_ref(new scoped_refptr<FileIOResource>(this)); |
| + if (!base::FileUtilProxy::GetFileInfoFromPlatformFile( |
| + PpapiGlobals::Get()->GetFileTaskRunner(pp_instance()), |
| + file_handle_, |
| + base::Bind(&QueryCallback, base::Passed(&passed_ref), |
| + callback, info))) { |
| + return PP_ERROR_FAILED; |
| + } |
| state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); |
| return PP_OK_COMPLETIONPENDING; |
| } |
| @@ -110,7 +138,6 @@ int32_t FileIOResource::Read(int64_t offset, |
| PP_ArrayOutput output_adapter; |
| output_adapter.GetDataBuffer = &DummyGetDataBuffer; |
| output_adapter.user_data = buffer; |
| - state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ); |
| return ReadValidated(offset, bytes_to_read, output_adapter, callback); |
| } |
| @@ -124,7 +151,6 @@ int32_t FileIOResource::ReadToArray(int64_t offset, |
| if (rv != PP_OK) |
| return rv; |
| - state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ); |
| return ReadValidated(offset, max_read_length, *array_output, callback); |
| } |
| @@ -181,6 +207,7 @@ int32_t FileIOResource::Flush(scoped_refptr<TrackedCallback> callback) { |
| } |
| void FileIOResource::Close() { |
| + CloseFileHandle(); |
| Post(RENDERER, PpapiHostMsg_FileIO_Close()); |
| } |
| @@ -192,6 +219,23 @@ int32_t FileIOResource::GetOSFileDescriptor() { |
| return file_descriptor; |
| } |
| +int32_t FileIOResource::RequestOSFileHandle( |
| + PP_FileHandle* handle, |
| + scoped_refptr<TrackedCallback> callback) { |
| + int32_t rv = state_manager_.CheckOperationState( |
| + FileIOStateManager::OPERATION_EXCLUSIVE, true); |
| + if (rv != PP_OK) |
| + return rv; |
| + |
| + Call<PpapiPluginMsg_FileIO_RequestOSFileHandleReply>(RENDERER, |
| + PpapiHostMsg_FileIO_RequestOSFileHandle(), |
| + base::Bind(&FileIOResource::OnPluginMsgRequestOSFileHandleComplete, this, |
| + callback, handle)); |
| + |
| + state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); |
| + return PP_OK_COMPLETIONPENDING; |
| +} |
| + |
| int32_t FileIOResource::WillWrite(int64_t offset, |
| int32_t bytes_to_write, |
| scoped_refptr<TrackedCallback> callback) { |
| @@ -217,90 +261,144 @@ int32_t FileIOResource::ReadValidated(int64_t offset, |
| int32_t bytes_to_read, |
| const PP_ArrayOutput& array_output, |
| scoped_refptr<TrackedCallback> callback) { |
| - Call<PpapiPluginMsg_FileIO_ReadReply>(RENDERER, |
| - PpapiHostMsg_FileIO_Read(offset, bytes_to_read), |
| - base::Bind(&FileIOResource::OnPluginMsgReadComplete, this, |
| - callback, array_output)); |
| + if (file_handle_ == base::kInvalidPlatformFileValue) |
| + return PP_ERROR_FAILED; |
| + |
| + PassedRef passed_ref(new scoped_refptr<FileIOResource>(this)); |
| + if (!base::FileUtilProxy::Read( |
| + PpapiGlobals::Get()->GetFileTaskRunner(pp_instance()), |
| + file_handle_, |
| + offset, |
| + bytes_to_read, |
| + base::Bind(&ReadCallback, base::Passed(&passed_ref), |
| + callback, array_output))) { |
| + return PP_ERROR_FAILED; |
| + } |
| + |
| + state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ); |
| return PP_OK_COMPLETIONPENDING; |
| } |
| -int32_t FileIOResource::RequestOSFileHandle( |
| - PP_FileHandle* handle, |
| - scoped_refptr<TrackedCallback> callback) { |
| - int32_t rv = state_manager_.CheckOperationState( |
| - FileIOStateManager::OPERATION_EXCLUSIVE, true); |
| - if (rv != PP_OK) |
| - return rv; |
| +void FileIOResource::CloseFileHandle() { |
| + if (file_handle_ != base::kInvalidPlatformFileValue) { |
| + base::FileUtilProxy::Close( |
| + PpapiGlobals::Get()->GetFileTaskRunner(pp_instance()), |
| + file_handle_, |
| + base::Bind(&DummyCloseCallback)); |
| + file_handle_ = base::kInvalidPlatformFileValue; |
| + } |
| +} |
| - Call<PpapiPluginMsg_FileIO_RequestOSFileHandleReply>(RENDERER, |
| - PpapiHostMsg_FileIO_RequestOSFileHandle(), |
| - base::Bind(&FileIOResource::OnPluginMsgRequestOSFileHandleComplete, this, |
| - callback, handle)); |
| +// static |
| +void FileIOResource::QueryCallback(PassedRef file_io_ref, |
| + scoped_refptr<TrackedCallback> callback, |
| + PP_FileInfo* output_info, |
| + base::PlatformFileError error_code, |
| + const base::PlatformFileInfo& file_info) { |
| + ProxyAutoLock lock; |
| + scoped_refptr<FileIOResource> file_io; |
| + file_io.swap(*file_io_ref.get()); |
| + file_io->OnQueryComplete(callback, output_info, error_code, file_info); |
| +} |
| - state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); |
| - return PP_OK_COMPLETIONPENDING; |
| +// static |
| +void FileIOResource::ReadCallback(PassedRef file_io_ref, |
| + scoped_refptr<TrackedCallback> callback, |
| + PP_ArrayOutput array_output, |
| + base::PlatformFileError error_code, |
| + const char* data, int bytes_read) { |
| + ProxyAutoLock lock; |
| + scoped_refptr<FileIOResource> file_io; |
| + file_io.swap(*file_io_ref.get()); |
| + file_io->OnReadComplete(callback, array_output, error_code, data, bytes_read); |
|
dmichael (off chromium)
2013/07/25 17:42:47
It looks like this stuff snuck back in. Was that o
bbudge
2013/07/25 17:56:26
No. I'm not sure what happened here.
|
| } |
| -void FileIOResource::OnPluginMsgGeneralComplete( |
| +void FileIOResource::OnQueryComplete( |
| scoped_refptr<TrackedCallback> callback, |
| - const ResourceMessageReplyParams& params) { |
| + PP_FileInfo* output_info, |
| + base::PlatformFileError error_code, |
| + const base::PlatformFileInfo& file_info) { |
| DCHECK(state_manager_.get_pending_operation() == |
| - FileIOStateManager::OPERATION_EXCLUSIVE || |
| - state_manager_.get_pending_operation() == |
| - FileIOStateManager::OPERATION_WRITE); |
| - // End the operation now. The callback may perform another file operation. |
| + FileIOStateManager::OPERATION_EXCLUSIVE); |
| + |
| + if (!TrackedCallback::IsPending(callback)) { |
| + state_manager_.SetOperationFinished(); |
| + return; |
| + } |
| + |
| + int32_t result = ::ppapi::PlatformFileErrorToPepperError(error_code); |
| + if (result == PP_OK) { |
| + ppapi::PlatformFileInfoToPepperFileInfo(file_info, file_system_type_, |
| + output_info); |
| + } |
| + |
| + // End this operation now, so the user's callback can execute another FileIO |
| + // operation, assuming there are no other pending operations. |
| state_manager_.SetOperationFinished(); |
| - callback->Run(params.result()); |
| + callback->Run(result); |
| } |
| -void FileIOResource::OnPluginMsgOpenFileComplete( |
| +void FileIOResource::OnReadComplete( |
| scoped_refptr<TrackedCallback> callback, |
| - const ResourceMessageReplyParams& params) { |
| + PP_ArrayOutput array_output, |
| + base::PlatformFileError error_code, |
| + const char* data, int bytes_read) { |
| DCHECK(state_manager_.get_pending_operation() == |
| - FileIOStateManager::OPERATION_EXCLUSIVE); |
| - if (params.result() == PP_OK) |
| - state_manager_.SetOpenSucceed(); |
| - // End the operation now. The callback may perform another file operation. |
| + FileIOStateManager::OPERATION_READ); |
| + |
| + if (!TrackedCallback::IsPending(callback)) { |
| + state_manager_.SetOperationFinished(); |
| + return; |
| + } |
| + |
| + int32_t result = ::ppapi::PlatformFileErrorToPepperError(error_code); |
| + if (result == PP_OK) { |
| + result = std::max(0, bytes_read); |
| + ArrayWriter output; |
| + output.set_pp_array_output(array_output); |
| + if (output.is_valid()) |
| + output.StoreArray(data, result); |
| + else |
| + result = PP_ERROR_FAILED; |
| + } |
| + |
| + // End this operation now, so the user's callback can execute another FileIO |
| + // operation, assuming there are no other pending operations. |
| state_manager_.SetOperationFinished(); |
| - callback->Run(params.result()); |
| + callback->Run(result); |
| } |
| -void FileIOResource::OnPluginMsgQueryComplete( |
| +void FileIOResource::OnPluginMsgGeneralComplete( |
| scoped_refptr<TrackedCallback> callback, |
| - PP_FileInfo* output_info, |
| - const ResourceMessageReplyParams& params, |
| - const PP_FileInfo& info) { |
| + const ResourceMessageReplyParams& params) { |
| DCHECK(state_manager_.get_pending_operation() == |
| - FileIOStateManager::OPERATION_EXCLUSIVE); |
| - *output_info = info; |
| - // End the operation now. The callback may perform another file operation. |
| + FileIOStateManager::OPERATION_EXCLUSIVE || |
| + state_manager_.get_pending_operation() == |
| + FileIOStateManager::OPERATION_WRITE); |
| + // End this operation now, so the user's callback can execute another FileIO |
| + // operation, assuming there are no other pending operations. |
| state_manager_.SetOperationFinished(); |
| callback->Run(params.result()); |
| } |
| -void FileIOResource::OnPluginMsgReadComplete( |
| +void FileIOResource::OnPluginMsgOpenFileComplete( |
| scoped_refptr<TrackedCallback> callback, |
| - PP_ArrayOutput array_output, |
| - const ResourceMessageReplyParams& params, |
| - const std::string& data) { |
| + const ResourceMessageReplyParams& params) { |
| DCHECK(state_manager_.get_pending_operation() == |
| - FileIOStateManager::OPERATION_READ); |
| + FileIOStateManager::OPERATION_EXCLUSIVE); |
| + if (params.result() == PP_OK) |
| + state_manager_.SetOpenSucceed(); |
| - // The result code should contain the data size if it's positive. |
| int32_t result = params.result(); |
| - DCHECK((result < 0 && data.size() == 0) || |
| - result == static_cast<int32_t>(data.size())); |
| - |
| - ArrayWriter output; |
| - output.set_pp_array_output(array_output); |
| - if (output.is_valid()) |
| - output.StoreArray(data.data(), std::max(0, result)); |
| - else |
| + IPC::PlatformFileForTransit transit_file; |
| + if (result == PP_OK && !params.TakeFileHandleAtIndex(0, &transit_file)) |
| result = PP_ERROR_FAILED; |
| + file_handle_ = IPC::PlatformFileForTransitToPlatformFile(transit_file); |
| - // End the operation now. The callback may perform another file operation. |
| + // End this operation now, so the user's callback can execute another FileIO |
| + // operation, assuming there are no other pending operations. |
| state_manager_.SetOperationFinished(); |
| - callback->Run(result); |
| + callback->Run(params.result()); |
| } |
| void FileIOResource::OnPluginMsgRequestOSFileHandleComplete( |
| @@ -321,7 +419,8 @@ void FileIOResource::OnPluginMsgRequestOSFileHandleComplete( |
| result = PP_ERROR_FAILED; |
| *output_handle = IPC::PlatformFileForTransitToPlatformFile(transit_file); |
| - // End the operation now. The callback may perform another file operation. |
| + // End this operation now, so the user's callback can execute another FileIO |
| + // operation, assuming there are no other pending operations. |
| state_manager_.SetOperationFinished(); |
| callback->Run(result); |
| } |