diff options
author | bbudge@chromium.org <bbudge@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-10 13:38:48 +0000 |
---|---|---|
committer | bbudge@chromium.org <bbudge@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-10 13:38:48 +0000 |
commit | 914a4ba94eec667b26d70f9ae82967eb7fc6bec7 (patch) | |
tree | 8f4b510b81ef738330e44ad6831b24c5af2dc2d6 /ppapi | |
parent | 994fe1999ae76f2bcc508bf8264068bfe0a55612 (diff) | |
download | chromium_src-914a4ba94eec667b26d70f9ae82967eb7fc6bec7.zip chromium_src-914a4ba94eec667b26d70f9ae82967eb7fc6bec7.tar.gz chromium_src-914a4ba94eec667b26d70f9ae82967eb7fc6bec7.tar.bz2 |
Do PPB_FileIO Query and Read in the plugin process.
Use the plugin-side file descriptor for asynchronous
callbacks too.
TBR=dmichael@chromium.org
CL only removes messages that had a LGTM in a prior CL.
https://codereview.chromium.org/18063005/
BUG=194304
Review URL: https://codereview.chromium.org/22646005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@216838 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi')
-rw-r--r-- | ppapi/proxy/file_io_resource.cc | 208 | ||||
-rw-r--r-- | ppapi/proxy/file_io_resource.h | 57 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_messages.h | 6 |
3 files changed, 167 insertions, 104 deletions
diff --git a/ppapi/proxy/file_io_resource.cc b/ppapi/proxy/file_io_resource.cc index 89b23d7..4459199 100644 --- a/ppapi/proxy/file_io_resource.cc +++ b/ppapi/proxy/file_io_resource.cc @@ -5,6 +5,7 @@ #include "ppapi/proxy/file_io_resource.h" #include "base/bind.h" +#include "base/task_runner_util.h" #include "ipc/ipc_message.h" #include "ppapi/c/pp_errors.h" #include "ppapi/proxy/ppapi_messages.h" @@ -22,6 +23,11 @@ using ppapi::thunk::PPB_FileRef_API; namespace { +// We must allocate a buffer sized according to the request of the plugin. To +// reduce the chance of out-of-memory errors, we cap the read size to 32MB. +// This is OK since the API specifies that it may perform a partial read. +static const int32_t kMaxReadSize = 32 * 1024 * 1024; // 32MB + // An adapter to let Read() share the same implementation with ReadToArray(). void* DummyGetDataBuffer(void* user_data, uint32_t count, uint32_t size) { return user_data; @@ -37,6 +43,36 @@ void DoClose(base::PlatformFile file) { namespace ppapi { namespace proxy { +FileIOResource::QueryOp::QueryOp(PP_FileHandle file_handle) + : file_handle_(file_handle) { +} + +FileIOResource::QueryOp::~QueryOp() { +} + +int32_t FileIOResource::QueryOp::DoWork() { + return base::GetPlatformFileInfo(file_handle_, &file_info_) ? + PP_OK : PP_ERROR_FAILED; +} + +FileIOResource::ReadOp::ReadOp(PP_FileHandle file_handle, + int64_t offset, + int32_t bytes_to_read) + : file_handle_(file_handle), + offset_(offset), + bytes_to_read_(bytes_to_read) { +} + +FileIOResource::ReadOp::~ReadOp() { +} + +int32_t FileIOResource::ReadOp::DoWork() { + DCHECK(!buffer_.get()); + buffer_.reset(new char[bytes_to_read_]); + return base::ReadPlatformFile( + file_handle_, offset_, buffer_.get(), bytes_to_read_); +} + FileIOResource::FileIOResource(Connection connection, PP_Instance instance) : PluginResource(connection, instance), file_handle_(base::kInvalidPlatformFileValue), @@ -92,33 +128,35 @@ int32_t FileIOResource::Query(PP_FileInfo* info, FileIOStateManager::OPERATION_EXCLUSIVE, true); if (rv != PP_OK) return rv; + if (!info) + return PP_ERROR_BADARGUMENT; + if (file_handle_ == base::kInvalidPlatformFileValue) + return PP_ERROR_FAILED; + + state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); + scoped_refptr<QueryOp> query_op(new QueryOp(file_handle_)); - if (callback->is_blocking() && - file_handle_ != base::kInvalidPlatformFileValue) { - state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); - int32_t result = PP_ERROR_FAILED; - base::PlatformFileInfo file_info; - // Release the proxy lock while making a potentially blocking file call. + // If the callback is blocking, perform the task on the calling thread. + if (callback->is_blocking()) { + int32_t result; { + // Release the proxy lock while making a potentially slow file call. ProxyAutoUnlock unlock; - result = base::GetPlatformFileInfo(file_handle_, &file_info) ? - PP_OK : PP_ERROR_FAILED; + result = query_op->DoWork(); } - if ((result == PP_OK) && TrackedCallback::IsPending(callback)) { - ppapi::PlatformFileInfoToPepperFileInfo(file_info, file_system_type_, - info); - } - - state_manager_.SetOperationFinished(); - return result; + return OnQueryComplete(query_op, info, result); } - Call<PpapiPluginMsg_FileIO_QueryReply>(RENDERER, - PpapiHostMsg_FileIO_Query(), - base::Bind(&FileIOResource::OnPluginMsgQueryComplete, this, - callback, info)); + // For the non-blocking case, post a task to the file thread and add a + // completion task to write the result. + base::PostTaskAndReplyWithResult( + PpapiGlobals::Get()->GetFileTaskRunner(pp_instance()), + FROM_HERE, + Bind(&FileIOResource::QueryOp::DoWork, query_op), + RunWhileLocked(Bind(&TrackedCallback::Run, callback))); + callback->set_completion_task( + Bind(&FileIOResource::OnQueryComplete, this, query_op, info)); - state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); return PP_OK_COMPLETIONPENDING; } @@ -274,41 +312,35 @@ int32_t FileIOResource::ReadValidated(int64_t offset, int32_t bytes_to_read, const PP_ArrayOutput& array_output, scoped_refptr<TrackedCallback> callback) { + if (bytes_to_read < 0) + return PP_ERROR_FAILED; + if (file_handle_ == base::kInvalidPlatformFileValue) + return PP_ERROR_FAILED; + state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ); - if (callback->is_blocking() && - file_handle_ != base::kInvalidPlatformFileValue) { - int32_t result = PP_ERROR_FAILED; - if (bytes_to_read >= 0) { - // We need a buffer (and therefore we must copy) since we don't know until - // reacquire the lock whether to write data to the plugin's buffer. - scoped_ptr<char[]> buffer; - // Release the proxy lock while making a potentially blocking file call. - { - ProxyAutoUnlock unlock; - buffer.reset(new char[bytes_to_read]); - int32_t bytes_read = base::ReadPlatformFile( - file_handle_, offset, buffer.get(), bytes_to_read); - result = (bytes_read < 0) ? PP_ERROR_FAILED : bytes_read; - } - if ((result >= 0) && TrackedCallback::IsPending(callback)) { - ArrayWriter output; - output.set_pp_array_output(array_output); - if (output.is_valid()) - output.StoreArray(buffer.get(), result); - else - result = PP_ERROR_FAILED; - } + bytes_to_read = std::min(bytes_to_read, kMaxReadSize); + scoped_refptr<ReadOp> read_op( + new ReadOp(file_handle_, offset, bytes_to_read)); + if (callback->is_blocking()) { + int32_t result; + { + // Release the proxy lock while making a potentially slow file call. + ProxyAutoUnlock unlock; + result = read_op->DoWork(); } - - state_manager_.SetOperationFinished(); - return result; + return OnReadComplete(read_op, array_output, result); } - Call<PpapiPluginMsg_FileIO_ReadReply>(RENDERER, - PpapiHostMsg_FileIO_Read(offset, bytes_to_read), - base::Bind(&FileIOResource::OnPluginMsgReadComplete, this, - callback, array_output)); + // For the non-blocking case, post a task to the file thread. + base::PostTaskAndReplyWithResult( + PpapiGlobals::Get()->GetFileTaskRunner(pp_instance()), + FROM_HERE, + Bind(&FileIOResource::ReadOp::DoWork, read_op), + RunWhileLocked(Bind(&TrackedCallback::Run, callback))); + callback->set_completion_task( + Bind(&FileIOResource::OnReadComplete, this, read_op, array_output)); + return PP_OK_COMPLETIONPENDING; } @@ -324,6 +356,42 @@ void FileIOResource::CloseFileHandle() { } } +int32_t FileIOResource::OnQueryComplete(scoped_refptr<QueryOp> query_op, + PP_FileInfo* info, + int32_t result) { + DCHECK(state_manager_.get_pending_operation() == + FileIOStateManager::OPERATION_EXCLUSIVE); + + if (result == PP_OK) { + // This writes the file info into the plugin's PP_FileInfo struct. + ppapi::PlatformFileInfoToPepperFileInfo(query_op->file_info(), + file_system_type_, + info); + } + state_manager_.SetOperationFinished(); + return result; +} + +int32_t FileIOResource::OnReadComplete(scoped_refptr<ReadOp> read_op, + PP_ArrayOutput array_output, + int32_t result) { + DCHECK(state_manager_.get_pending_operation() == + FileIOStateManager::OPERATION_READ); + if (result >= 0) { + ArrayWriter output; + output.set_pp_array_output(array_output); + if (output.is_valid()) + output.StoreArray(read_op->buffer(), result); + else + result = PP_ERROR_FAILED; + } else { + // The read operation failed. + result = PP_ERROR_FAILED; + } + state_manager_.SetOperationFinished(); + return result; +} + void FileIOResource::OnPluginMsgGeneralComplete( scoped_refptr<TrackedCallback> callback, const ResourceMessageReplyParams& params) { @@ -355,46 +423,6 @@ void FileIOResource::OnPluginMsgOpenFileComplete( callback->Run(result); } -void FileIOResource::OnPluginMsgQueryComplete( - scoped_refptr<TrackedCallback> callback, - PP_FileInfo* output_info, - const ResourceMessageReplyParams& params, - const PP_FileInfo& info) { - DCHECK(state_manager_.get_pending_operation() == - FileIOStateManager::OPERATION_EXCLUSIVE); - *output_info = 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()); -} - -void FileIOResource::OnPluginMsgReadComplete( - scoped_refptr<TrackedCallback> callback, - PP_ArrayOutput array_output, - const ResourceMessageReplyParams& params, - const std::string& data) { - DCHECK(state_manager_.get_pending_operation() == - FileIOStateManager::OPERATION_READ); - - // 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 - 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(result); -} - void FileIOResource::OnPluginMsgRequestOSFileHandleComplete( scoped_refptr<TrackedCallback> callback, PP_FileHandle* output_handle, diff --git a/ppapi/proxy/file_io_resource.h b/ppapi/proxy/file_io_resource.h index dffa940..1a888d1 100644 --- a/ppapi/proxy/file_io_resource.h +++ b/ppapi/proxy/file_io_resource.h @@ -67,6 +67,46 @@ class PPAPI_PROXY_EXPORT FileIOResource scoped_refptr<TrackedCallback> callback) OVERRIDE; private: + // Class to perform file query operations across multiple threads. + class QueryOp : public base::RefCountedThreadSafe<QueryOp> { + public: + explicit QueryOp(PP_FileHandle file_handle); + + // Queries the file. Called on the file thread (non-blocking) or the plugin + // thread (blocking). This should not be called when we hold the proxy lock. + int32_t DoWork(); + + const base::PlatformFileInfo& file_info() const { return file_info_; } + + private: + friend class base::RefCountedThreadSafe<QueryOp>; + ~QueryOp(); + + PP_FileHandle file_handle_; + base::PlatformFileInfo file_info_; + }; + + // Class to perform file read operations across multiple threads. + class ReadOp : public base::RefCountedThreadSafe<ReadOp> { + public: + ReadOp(PP_FileHandle file_handle, int64_t offset, int32_t bytes_to_read); + + // Reads the file. Called on the file thread (non-blocking) or the plugin + // thread (blocking). This should not be called when we hold the proxy lock. + int32_t DoWork(); + + char* buffer() const { return buffer_.get(); } + + private: + friend class base::RefCountedThreadSafe<ReadOp>; + ~ReadOp(); + + PP_FileHandle file_handle_; + int64_t offset_; + int32_t bytes_to_read_; + scoped_ptr<char[]> buffer_; + }; + int32_t ReadValidated(int64_t offset, int32_t bytes_to_read, const PP_ArrayOutput& array_output, @@ -74,19 +114,20 @@ class PPAPI_PROXY_EXPORT FileIOResource void CloseFileHandle(); + + // Completion tasks for file operations that are done in the plugin. + int32_t OnQueryComplete(scoped_refptr<QueryOp> query_op, + PP_FileInfo* info, + int32_t result); + int32_t OnReadComplete(scoped_refptr<ReadOp> read_op, + PP_ArrayOutput array_output, + int32_t result); + // Reply message handlers for operations that are done in the host. void OnPluginMsgGeneralComplete(scoped_refptr<TrackedCallback> callback, const ResourceMessageReplyParams& params); void OnPluginMsgOpenFileComplete(scoped_refptr<TrackedCallback> callback, const ResourceMessageReplyParams& params); - void OnPluginMsgQueryComplete(scoped_refptr<TrackedCallback> callback, - PP_FileInfo* output_info_, - const ResourceMessageReplyParams& params, - const PP_FileInfo& info); - void OnPluginMsgReadComplete(scoped_refptr<TrackedCallback> callback, - PP_ArrayOutput array_output, - const ResourceMessageReplyParams& params, - const std::string& data); void OnPluginMsgRequestOSFileHandleComplete( scoped_refptr<TrackedCallback> callback, PP_FileHandle* output_handle, diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index 109884a..c97ae7a 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h @@ -1295,15 +1295,9 @@ IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileIO_Open, int32_t /* open_flags */) IPC_MESSAGE_CONTROL0(PpapiPluginMsg_FileIO_OpenReply) IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileIO_Close) -IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileIO_Query) -IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FileIO_QueryReply, PP_FileInfo /* info */) IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileIO_Touch, PP_Time /* last_access_time */, PP_Time /* last_modified_time */) -IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileIO_Read, - int64_t /* offset */, - int32_t /* bytes_to_read */) -IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FileIO_ReadReply, std::string /* data */) IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileIO_Write, int64_t /* offset */, std::string /* data */) |