diff options
author | bbudge@chromium.org <bbudge@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-19 04:16:36 +0000 |
---|---|---|
committer | bbudge@chromium.org <bbudge@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-19 04:16:36 +0000 |
commit | c77144727785be9a25c10a7954e38a3a579b417a (patch) | |
tree | 5fe5083e10e8af5ec822848a07cb04b416682496 /ppapi/shared_impl | |
parent | 7a6acd091023b662745562592406b5efbc1a5b42 (diff) | |
download | chromium_src-c77144727785be9a25c10a7954e38a3a579b417a.zip chromium_src-c77144727785be9a25c10a7954e38a3a579b417a.tar.gz chromium_src-c77144727785be9a25c10a7954e38a3a579b417a.tar.bz2 |
Refactor FileIO to the new resource host system.
Taking over from Victor's CL: https://codereview.chromium.org/11419131/
Re-landing, with a fix. The original waited to reset the file state until
after the callback had completed. This is too late, as the client should be
able to perform another file operation during the callback.
Changeset #1 is the original patch. The fix is in change set #2
Original author=Victor Hsieh
BUG=none
TEST=browser_tests --gtest_filter=PPAPINaClNewlibTest.FileIO*
Review URL: https://chromiumcodereview.appspot.com/11941022
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@177830 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/shared_impl')
-rw-r--r-- | ppapi/shared_impl/file_io_state_manager.cc | 56 | ||||
-rw-r--r-- | ppapi/shared_impl/file_io_state_manager.h | 69 | ||||
-rw-r--r-- | ppapi/shared_impl/ppb_file_io_shared.cc | 244 | ||||
-rw-r--r-- | ppapi/shared_impl/ppb_file_io_shared.h | 159 |
4 files changed, 125 insertions, 403 deletions
diff --git a/ppapi/shared_impl/file_io_state_manager.cc b/ppapi/shared_impl/file_io_state_manager.cc new file mode 100644 index 0000000..9c9b6ea --- /dev/null +++ b/ppapi/shared_impl/file_io_state_manager.cc @@ -0,0 +1,56 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ppapi/shared_impl/file_io_state_manager.h" + +#include "base/logging.h" +#include "ppapi/c/pp_errors.h" + +namespace ppapi { + +FileIOStateManager::FileIOStateManager() + : num_pending_ops_(0), + pending_op_(OPERATION_NONE), + file_open_(false) { +} + +FileIOStateManager::~FileIOStateManager() { +} + +void FileIOStateManager::SetOpenSucceed() { + file_open_ = true; +} + +int32_t FileIOStateManager::CheckOperationState(OperationType new_op, + bool should_be_open) { + if (should_be_open) { + if (!file_open_) + return PP_ERROR_FAILED; + } else { + if (file_open_) + return PP_ERROR_FAILED; + } + + if (pending_op_ != OPERATION_NONE && + (pending_op_ != new_op || pending_op_ == OPERATION_EXCLUSIVE)) + return PP_ERROR_INPROGRESS; + + return PP_OK; +} + +void FileIOStateManager::SetPendingOperation(OperationType new_op) { + DCHECK(pending_op_ == OPERATION_NONE || + (pending_op_ != OPERATION_EXCLUSIVE && pending_op_ == new_op)); + pending_op_ = new_op; + num_pending_ops_++; +} + +void FileIOStateManager::SetOperationFinished() { + DCHECK_GT(num_pending_ops_, 0); + if (--num_pending_ops_ == 0) + pending_op_ = OPERATION_NONE; +} + +} // namespace ppapi + diff --git a/ppapi/shared_impl/file_io_state_manager.h b/ppapi/shared_impl/file_io_state_manager.h new file mode 100644 index 0000000..7b5f926 --- /dev/null +++ b/ppapi/shared_impl/file_io_state_manager.h @@ -0,0 +1,69 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PPAPI_SHARED_IMPL_FILE_IO_STATE_MANAGER_H_ +#define PPAPI_SHARED_IMPL_FILE_IO_STATE_MANAGER_H_ + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "ppapi/c/pp_stdint.h" +#include "ppapi/shared_impl/ppapi_shared_export.h" + +namespace ppapi { + +// FileIOStateManager is a helper class that maintains the state of operations. +// For example, some operations are mutually exclusive, meaning that an +// operation could be rejected because of the current pending operation. Also, +// most of the operations only work when the file has been opened. +class PPAPI_SHARED_EXPORT FileIOStateManager { + public: + FileIOStateManager(); + ~FileIOStateManager(); + + enum OperationType { + // There is no pending operation right now. + OPERATION_NONE, + + // If there are pending reads, any other kind of async operation is not + // allowed. + OPERATION_READ, + + // If there are pending writes, any other kind of async operation is not + // allowed. + OPERATION_WRITE, + + // If there is a pending operation that is neither read nor write, no + // further async operation is allowed. + OPERATION_EXCLUSIVE + }; + + OperationType get_pending_operation() const { return pending_op_; } + + void SetOpenSucceed(); + + // Called at the beginning of each operation. It is responsible to make sure + // that state is correct. For example, some operations are only valid after + // the file is opened, or operations might need to run exclusively. + // + // It returns |PP_OK| on success, or |PP_ERROR_...| for various reasons. + int32_t CheckOperationState(OperationType new_op, bool should_be_open); + + // Marks the state of current operations as started or finished. + void SetPendingOperation(OperationType op); + void SetOperationFinished(); + + private: + int num_pending_ops_; + OperationType pending_op_; + + // Set to true when the file has been successfully opened. + bool file_open_; + + DISALLOW_COPY_AND_ASSIGN(FileIOStateManager); +}; + +} // namespace ppapi + +#endif // PPAPI_SHARED_IMPL_FILE_IO_STATE_MANAGER_H_ + diff --git a/ppapi/shared_impl/ppb_file_io_shared.cc b/ppapi/shared_impl/ppb_file_io_shared.cc deleted file mode 100644 index 42a8d32..0000000 --- a/ppapi/shared_impl/ppb_file_io_shared.cc +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ppapi/shared_impl/ppb_file_io_shared.h" - -#include <string.h> - -#include "base/bind.h" -#include "base/logging.h" -#include "base/message_loop.h" -#include "ppapi/c/pp_errors.h" -#include "ppapi/shared_impl/array_writer.h" -#include "ppapi/shared_impl/file_type_conversion.h" -#include "ppapi/shared_impl/time_conversion.h" -#include "ppapi/thunk/enter.h" -#include "ppapi/thunk/ppb_file_ref_api.h" - -namespace ppapi { - -using thunk::EnterResourceNoLock; -using thunk::PPB_FileIO_API; -using thunk::PPB_FileRef_API; - -namespace { - -// 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; -} - -} // namespace - -PPB_FileIO_Shared::CallbackEntry::CallbackEntry() - : info(NULL) { -} - -PPB_FileIO_Shared::CallbackEntry::CallbackEntry(const CallbackEntry& entry) - : callback(entry.callback), - read_buffer(entry.read_buffer), - info(entry.info) { -} - -PPB_FileIO_Shared::CallbackEntry::~CallbackEntry() { -} - -PPB_FileIO_Shared::PPB_FileIO_Shared(PP_Instance instance) - : Resource(OBJECT_IS_IMPL, instance), - file_system_type_(PP_FILESYSTEMTYPE_INVALID), - file_open_(false), - pending_op_(OPERATION_NONE) { -} - -PPB_FileIO_Shared::PPB_FileIO_Shared(const HostResource& host_resource) - : Resource(OBJECT_IS_PROXY, host_resource), - file_system_type_(PP_FILESYSTEMTYPE_INVALID), - file_open_(false), - pending_op_(OPERATION_NONE) { -} - -PPB_FileIO_Shared::~PPB_FileIO_Shared() { -} - -thunk::PPB_FileIO_API* PPB_FileIO_Shared::AsPPB_FileIO_API() { - return this; -} - -int32_t PPB_FileIO_Shared::Open(PP_Resource file_ref, - int32_t open_flags, - scoped_refptr<TrackedCallback> callback) { - EnterResourceNoLock<PPB_FileRef_API> enter(file_ref, true); - if (enter.failed()) - return PP_ERROR_BADRESOURCE; - - int32_t rv = CommonCallValidation(false, OPERATION_EXCLUSIVE); - if (rv != PP_OK) - return rv; - - PP_FileSystemType type = enter.object()->GetFileSystemType(); - if (type != PP_FILESYSTEMTYPE_LOCALPERSISTENT && - type != PP_FILESYSTEMTYPE_LOCALTEMPORARY && - type != PP_FILESYSTEMTYPE_EXTERNAL) - return PP_ERROR_FAILED; - file_system_type_ = type; - - return OpenValidated(file_ref, enter.object(), open_flags, callback); -} - -int32_t PPB_FileIO_Shared::Query(PP_FileInfo* info, - scoped_refptr<TrackedCallback> callback) { - int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE); - if (rv != PP_OK) - return rv; - if (!info) - return PP_ERROR_BADARGUMENT; - return QueryValidated(info, callback); -} - -int32_t PPB_FileIO_Shared::Touch(PP_Time last_access_time, - PP_Time last_modified_time, - scoped_refptr<TrackedCallback> callback) { - int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE); - if (rv != PP_OK) - return rv; - return TouchValidated(last_access_time, last_modified_time, callback); -} - -int32_t PPB_FileIO_Shared::Read(int64_t offset, - char* buffer, - int32_t bytes_to_read, - scoped_refptr<TrackedCallback> callback) { - int32_t rv = CommonCallValidation(true, OPERATION_READ); - if (rv != PP_OK) - return rv; - PP_ArrayOutput buffer_adapter = { &DummyGetDataBuffer, buffer }; - return ReadValidated(offset, buffer_adapter, bytes_to_read, callback); -} - -int32_t PPB_FileIO_Shared::ReadToArray( - int64_t offset, - int32_t max_read_length, - PP_ArrayOutput* output_array_buffer, - scoped_refptr<TrackedCallback> callback) { - int32_t rv = CommonCallValidation(true, OPERATION_READ); - if (rv != PP_OK) - return rv; - if (!output_array_buffer) - return PP_ERROR_BADARGUMENT; - return ReadValidated(offset, *output_array_buffer, max_read_length, callback); -} - -int32_t PPB_FileIO_Shared::Write(int64_t offset, - const char* buffer, - int32_t bytes_to_write, - scoped_refptr<TrackedCallback> callback) { - int32_t rv = CommonCallValidation(true, OPERATION_WRITE); - if (rv != PP_OK) - return rv; - return WriteValidated(offset, buffer, bytes_to_write, callback); -} - -int32_t PPB_FileIO_Shared::SetLength(int64_t length, - scoped_refptr<TrackedCallback> callback) { - int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE); - if (rv != PP_OK) - return rv; - return SetLengthValidated(length, callback); -} - -int32_t PPB_FileIO_Shared::Flush(scoped_refptr<TrackedCallback> callback) { - int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE); - if (rv != PP_OK) - return rv; - return FlushValidated(callback); -} - -void PPB_FileIO_Shared::ExecuteGeneralCallback(int32_t pp_error) { - RunAndRemoveFirstPendingCallback(pp_error); -} - -void PPB_FileIO_Shared::ExecuteOpenFileCallback(int32_t pp_error) { - if (pp_error == PP_OK) - file_open_ = true; - ExecuteGeneralCallback(pp_error); -} - -void PPB_FileIO_Shared::ExecuteQueryCallback(int32_t pp_error, - const PP_FileInfo& info) { - if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty() || - !callbacks_.front().info) { - NOTREACHED(); - return; - } - *callbacks_.front().info = info; - RunAndRemoveFirstPendingCallback(pp_error); -} - -void PPB_FileIO_Shared::ExecuteReadCallback(int32_t pp_error_or_bytes, - const char* data) { - if (pending_op_ != OPERATION_READ || callbacks_.empty()) { - NOTREACHED(); - return; - } - - // The result code contains the number of bytes if it's positive. - ArrayWriter output; - output.set_pp_array_output(callbacks_.front().read_buffer); - if (output.is_valid()) { - output.StoreArray(data, std::max(0, pp_error_or_bytes)); - } - - // Always issue the callback. - RunAndRemoveFirstPendingCallback(pp_error_or_bytes); -} - -int32_t PPB_FileIO_Shared::CommonCallValidation(bool should_be_open, - OperationType new_op) { - // Only asynchronous operation is supported. - if (should_be_open) { - if (!file_open_) - return PP_ERROR_FAILED; - } else { - if (file_open_) - return PP_ERROR_FAILED; - } - - if (pending_op_ != OPERATION_NONE && - (pending_op_ != new_op || pending_op_ == OPERATION_EXCLUSIVE)) { - return PP_ERROR_INPROGRESS; - } - - return PP_OK; -} - -void PPB_FileIO_Shared::RegisterCallback( - OperationType op, - scoped_refptr<TrackedCallback> callback, - const PP_ArrayOutput* read_buffer, - PP_FileInfo* info) { - DCHECK(pending_op_ == OPERATION_NONE || - (pending_op_ != OPERATION_EXCLUSIVE && pending_op_ == op)); - - CallbackEntry entry; - entry.callback = callback; - if (read_buffer) - entry.read_buffer = *read_buffer; - entry.info = info; - callbacks_.push_back(entry); - - pending_op_ = op; -} - -void PPB_FileIO_Shared::RunAndRemoveFirstPendingCallback(int32_t result) { - DCHECK(!callbacks_.empty()); - - CallbackEntry front = callbacks_.front(); - callbacks_.pop_front(); - if (callbacks_.empty()) - pending_op_ = OPERATION_NONE; - - front.callback->Run(result); -} - -} // namespace ppapi diff --git a/ppapi/shared_impl/ppb_file_io_shared.h b/ppapi/shared_impl/ppb_file_io_shared.h deleted file mode 100644 index 2c39c8d..0000000 --- a/ppapi/shared_impl/ppb_file_io_shared.h +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef PPAPI_SHARED_IMPL_PPB_FILE_IO_SHARED_H_ -#define PPAPI_SHARED_IMPL_PPB_FILE_IO_SHARED_H_ - -#include <deque> - -#include "base/compiler_specific.h" -#include "ppapi/shared_impl/ppapi_shared_export.h" -#include "ppapi/shared_impl/resource.h" -#include "ppapi/shared_impl/tracked_callback.h" -#include "ppapi/thunk/ppb_file_io_api.h" - -namespace ppapi { - -namespace thunk { -class PPB_FileRef_API; -} - -class PPAPI_SHARED_EXPORT PPB_FileIO_Shared : public Resource, - public thunk::PPB_FileIO_API { - public: - PPB_FileIO_Shared(PP_Instance instance); - PPB_FileIO_Shared(const HostResource& host_resource); - ~PPB_FileIO_Shared(); - - // Resource overrides. - virtual thunk::PPB_FileIO_API* AsPPB_FileIO_API() OVERRIDE; - - // PPB_FileIO_API implementation. - virtual int32_t Open(PP_Resource file_ref, - int32_t open_flags, - scoped_refptr<TrackedCallback> callback) OVERRIDE; - virtual int32_t Query(PP_FileInfo* info, - scoped_refptr<TrackedCallback> callback) OVERRIDE; - virtual int32_t Touch(PP_Time last_access_time, - PP_Time last_modified_time, - scoped_refptr<TrackedCallback> callback) OVERRIDE; - virtual int32_t Read(int64_t offset, - char* buffer, - int32_t bytes_to_read, - scoped_refptr<TrackedCallback> callback) OVERRIDE; - virtual int32_t ReadToArray(int64_t offset, - int32_t max_read_length, - PP_ArrayOutput* output_array_buffer, - scoped_refptr<TrackedCallback> callback) OVERRIDE; - virtual int32_t Write(int64_t offset, - const char* buffer, - int32_t bytes_to_write, - scoped_refptr<TrackedCallback> callback) OVERRIDE; - virtual int32_t SetLength(int64_t length, - scoped_refptr<TrackedCallback> callback) OVERRIDE; - virtual int32_t Flush(scoped_refptr<TrackedCallback> callback) OVERRIDE; - - // Callback handler for different types of operations. - void ExecuteGeneralCallback(int32_t pp_error); - void ExecuteOpenFileCallback(int32_t pp_error); - void ExecuteQueryCallback(int32_t pp_error, const PP_FileInfo& info); - void ExecuteReadCallback(int32_t pp_error_or_bytes, const char* data); - - protected: - struct CallbackEntry { - CallbackEntry(); - CallbackEntry(const CallbackEntry& entry); - ~CallbackEntry(); - - scoped_refptr<TrackedCallback> callback; - - // Output buffer used only by |Read()|. - PP_ArrayOutput read_buffer; - - // Pointer back to the caller's PP_FileInfo structure for Query operations. - // NULL for non-query operations. Not owned. - PP_FileInfo* info; - }; - - enum OperationType { - // There is no pending operation right now. - OPERATION_NONE, - - // If there are pending reads, any other kind of async operation is not - // allowed. - OPERATION_READ, - - // If there are pending writes, any other kind of async operation is not - // allowed. - OPERATION_WRITE, - - // If there is a pending operation that is neither read nor write, no - // further async operation is allowed. - OPERATION_EXCLUSIVE - }; - - // Validated versions of the FileIO API. Subclasses in the proxy and impl - // implement these so the common error checking stays here. - virtual int32_t OpenValidated(PP_Resource file_ref_resource, - thunk::PPB_FileRef_API* file_ref_api, - int32_t open_flags, - scoped_refptr<TrackedCallback> callback) = 0; - virtual int32_t QueryValidated(PP_FileInfo* info, - scoped_refptr<TrackedCallback> callback) = 0; - virtual int32_t TouchValidated(PP_Time last_access_time, - PP_Time last_modified_time, - scoped_refptr<TrackedCallback> callback) = 0; - virtual int32_t ReadValidated(int64_t offset, - const PP_ArrayOutput& buffer, - int32_t max_read_length, - scoped_refptr<TrackedCallback> callback) = 0; - virtual int32_t WriteValidated(int64_t offset, - const char* buffer, - int32_t bytes_to_write, - scoped_refptr<TrackedCallback> callback) = 0; - virtual int32_t SetLengthValidated( - int64_t length, - scoped_refptr<TrackedCallback> callback) = 0; - virtual int32_t FlushValidated(scoped_refptr<TrackedCallback> callback) = 0; - - // Called for every "Validated" function. - // - // This verifies that the callback is valid and that no callback is already - // pending, or it is a read(write) request and currently the pending - // operations are reads(writes). - // - // Returns |PP_OK| to indicate that everything is valid or |PP_ERROR_...| if - // the call should be aborted and that code returned to the plugin. - int32_t CommonCallValidation(bool should_be_open, OperationType new_op); - - // Sets up a pending callback. This should only be called once it is certain - // that |PP_OK_COMPLETIONPENDING| will be returned. - // - // |read_buffer| is only used by read operations, |info| is used only by - // query operations. - void RegisterCallback(OperationType op, - scoped_refptr<TrackedCallback> callback, - const PP_ArrayOutput* read_buffer, - PP_FileInfo* info); - - // Pops the oldest callback from the queue and runs it. - void RunAndRemoveFirstPendingCallback(int32_t result); - - // The file system type specified in the Open() call. This will be - // PP_FILESYSTEMTYPE_INVALID before open was called. This value does not - // indicate that the open command actually succeeded. - PP_FileSystemType file_system_type_; - - // Set to true when the file has been successfully opened. - bool file_open_; - - std::deque<CallbackEntry> callbacks_; - OperationType pending_op_; - - DISALLOW_COPY_AND_ASSIGN(PPB_FileIO_Shared); -}; - -} // namespace ppapi - -#endif // PPAPI_SHARED_IMPL_PPB_FILE_IO_SHARED_H_ |