diff options
-rw-r--r-- | ppapi/api/dev/ppb_directory_reader_dev.idl | 29 | ||||
-rw-r--r-- | ppapi/api/pp_macros.idl | 1 | ||||
-rw-r--r-- | ppapi/c/dev/ppb_directory_reader_dev.h | 38 | ||||
-rw-r--r-- | ppapi/c/pp_macros.h | 4 | ||||
-rw-r--r-- | ppapi/cpp/array_output.h | 43 | ||||
-rw-r--r-- | ppapi/cpp/dev/directory_entry_dev.cc | 6 | ||||
-rw-r--r-- | ppapi/cpp/dev/directory_entry_dev.h | 3 | ||||
-rw-r--r-- | ppapi/cpp/dev/directory_reader_dev.cc | 21 | ||||
-rw-r--r-- | ppapi/cpp/dev/directory_reader_dev.h | 35 | ||||
-rw-r--r-- | ppapi/cpp/output_traits.h | 21 | ||||
-rw-r--r-- | ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c | 48 | ||||
-rw-r--r-- | ppapi/proxy/directory_reader_resource.cc | 78 | ||||
-rw-r--r-- | ppapi/proxy/directory_reader_resource.h | 23 | ||||
-rw-r--r-- | ppapi/tests/test_directory_reader.cc | 131 | ||||
-rw-r--r-- | ppapi/tests/test_directory_reader.h | 8 | ||||
-rw-r--r-- | ppapi/tests/test_file_ref.cc | 25 | ||||
-rw-r--r-- | ppapi/thunk/interfaces_ppb_public_dev.h | 4 | ||||
-rw-r--r-- | ppapi/thunk/ppb_directory_reader_api.h | 4 | ||||
-rw-r--r-- | ppapi/thunk/ppb_directory_reader_thunk.cc | 12 |
19 files changed, 290 insertions, 244 deletions
diff --git a/ppapi/api/dev/ppb_directory_reader_dev.idl b/ppapi/api/dev/ppb_directory_reader_dev.idl index 659ed09..5ba6065 100644 --- a/ppapi/api/dev/ppb_directory_reader_dev.idl +++ b/ppapi/api/dev/ppb_directory_reader_dev.idl @@ -8,7 +8,7 @@ */ label Chrome { - M13 = 0.5 + M27 = 0.6 }; [assert_size(8)] @@ -29,23 +29,18 @@ interface PPB_DirectoryReader_Dev { // DirectoryReader. PP_Bool IsDirectoryReader([in] PP_Resource resource); - // Reads the next entry in the directory. Returns PP_OK and sets - // entry->file_ref to 0 to indicate reaching the end of the directory. If - // entry->file_ref is non-zero when passed to GetNextEntry, it will be - // released before the next file_ref is stored. + // Reads all entries in the directory. // - // EXAMPLE USAGE: + // @param[in] directory_reader A <code>PP_Resource</code> + // corresponding to a directory reader resource. + // @param[in] output An output array which will receive + // <code>PP_DirectoryEntry_Dev</code> objects on success. + // @param[in] callback A <code>PP_CompletionCallback</code> to run on + // completion. // - // PP_Resource reader = reader_funcs->Create(dir_ref); - // PP_DirectoryEntry entry = {0}; - // while ((reader_funcs->GetNextEntry(reader, &entry, - // PP_BlockUntilComplete()) == PP_OK) && - // entry->file_ref) { - // ProcessDirectoryEntry(entry); - // } - // core_funcs->ReleaseResource(reader); + // @return An error code from <code>pp_errors.h</code>. // - int32_t GetNextEntry([in] PP_Resource directory_reader, - [out] PP_DirectoryEntry_Dev entry, - [in] PP_CompletionCallback callback); + int32_t ReadEntries([in] PP_Resource directory_reader, + [in] PP_ArrayOutput output, + [in] PP_CompletionCallback callback); }; diff --git a/ppapi/api/pp_macros.idl b/ppapi/api/pp_macros.idl index edb4684..999da67 100644 --- a/ppapi/api/pp_macros.idl +++ b/ppapi/api/pp_macros.idl @@ -108,4 +108,3 @@ PP_COMPILE_ASSERT_SIZE_IN_BYTES_IMPL(NAME, enum NAME, SIZE) */ #endinl - diff --git a/ppapi/c/dev/ppb_directory_reader_dev.h b/ppapi/c/dev/ppb_directory_reader_dev.h index eda9e8f..060e489 100644 --- a/ppapi/c/dev/ppb_directory_reader_dev.h +++ b/ppapi/c/dev/ppb_directory_reader_dev.h @@ -3,11 +3,12 @@ * found in the LICENSE file. */ -/* From dev/ppb_directory_reader_dev.idl modified Mon Nov 26 13:52:22 2012. */ +/* From dev/ppb_directory_reader_dev.idl modified Fri Feb 15 16:46:46 2013. */ #ifndef PPAPI_C_DEV_PPB_DIRECTORY_READER_DEV_H_ #define PPAPI_C_DEV_PPB_DIRECTORY_READER_DEV_H_ +#include "ppapi/c/pp_array_output.h" #include "ppapi/c/pp_bool.h" #include "ppapi/c/pp_completion_callback.h" #include "ppapi/c/pp_file_info.h" @@ -15,8 +16,8 @@ #include "ppapi/c/pp_resource.h" #include "ppapi/c/pp_stdint.h" -#define PPB_DIRECTORYREADER_DEV_INTERFACE_0_5 "PPB_DirectoryReader(Dev);0.5" -#define PPB_DIRECTORYREADER_DEV_INTERFACE PPB_DIRECTORYREADER_DEV_INTERFACE_0_5 +#define PPB_DIRECTORYREADER_DEV_INTERFACE_0_6 "PPB_DirectoryReader(Dev);0.6" +#define PPB_DIRECTORYREADER_DEV_INTERFACE PPB_DIRECTORYREADER_DEV_INTERFACE_0_6 /** * @file @@ -42,7 +43,7 @@ PP_COMPILE_ASSERT_STRUCT_SIZE_IN_BYTES(PP_DirectoryEntry_Dev, 8); * @addtogroup Interfaces * @{ */ -struct PPB_DirectoryReader_Dev_0_5 { +struct PPB_DirectoryReader_Dev_0_6 { /* Creates a DirectoryReader for the given directory. Upon success, the * corresponding directory is classified as "in use" by the resulting * DirectoryReader object until such time as the DirectoryReader object is @@ -52,28 +53,23 @@ struct PPB_DirectoryReader_Dev_0_5 { * PP_FALSE if the resource is invalid or some type other than a * DirectoryReader. */ PP_Bool (*IsDirectoryReader)(PP_Resource resource); - /* Reads the next entry in the directory. Returns PP_OK and sets - * entry->file_ref to 0 to indicate reaching the end of the directory. If - * entry->file_ref is non-zero when passed to GetNextEntry, it will be - * released before the next file_ref is stored. + /* Reads all entries in the directory. * - * EXAMPLE USAGE: + * @param[in] directory_reader A <code>PP_Resource</code> + * corresponding to a directory reader resource. + * @param[in] output An output array which will receive + * <code>PP_DirectoryEntry_Dev</code> objects on success. + * @param[in] callback A <code>PP_CompletionCallback</code> to run on + * completion. * - * PP_Resource reader = reader_funcs->Create(dir_ref); - * PP_DirectoryEntry entry = {0}; - * while ((reader_funcs->GetNextEntry(reader, &entry, - * PP_BlockUntilComplete()) == PP_OK) && - * entry->file_ref) { - * ProcessDirectoryEntry(entry); - * } - * core_funcs->ReleaseResource(reader); + * @return An error code from <code>pp_errors.h</code>. */ - int32_t (*GetNextEntry)(PP_Resource directory_reader, - struct PP_DirectoryEntry_Dev* entry, - struct PP_CompletionCallback callback); + int32_t (*ReadEntries)(PP_Resource directory_reader, + struct PP_ArrayOutput output, + struct PP_CompletionCallback callback); }; -typedef struct PPB_DirectoryReader_Dev_0_5 PPB_DirectoryReader_Dev; +typedef struct PPB_DirectoryReader_Dev_0_6 PPB_DirectoryReader_Dev; /** * @} */ diff --git a/ppapi/c/pp_macros.h b/ppapi/c/pp_macros.h index 1f8b6d8..83f85d6 100644 --- a/ppapi/c/pp_macros.h +++ b/ppapi/c/pp_macros.h @@ -3,13 +3,13 @@ * found in the LICENSE file. */ -/* From pp_macros.idl modified Wed Jan 9 18:07:46 2013. */ +/* From pp_macros.idl modified Fri Feb 15 16:46:46 2013. */ #ifndef PPAPI_C_PP_MACROS_H_ #define PPAPI_C_PP_MACROS_H_ -#define PPAPI_RELEASE 25 +#define PPAPI_RELEASE 27 /** * @file diff --git a/ppapi/cpp/array_output.h b/ppapi/cpp/array_output.h index fe0bbc3..3a52190 100644 --- a/ppapi/cpp/array_output.h +++ b/ppapi/cpp/array_output.h @@ -7,8 +7,10 @@ #include <vector> +#include "ppapi/c/dev/ppb_directory_reader_dev.h" #include "ppapi/c/pp_array_output.h" #include "ppapi/c/pp_resource.h" +#include "ppapi/cpp/dev/directory_entry_dev.h" #include "ppapi/cpp/logging.h" #include "ppapi/cpp/pass_ref.h" #include "ppapi/cpp/var.h" @@ -267,6 +269,47 @@ class ResourceArrayOutputAdapterWithStorage std::vector<T> output_storage_; }; +class DirectoryEntryArrayOutputAdapterWithStorage + : public ArrayOutputAdapter<PP_DirectoryEntry_Dev> { + public: + DirectoryEntryArrayOutputAdapterWithStorage() { + set_output(&temp_storage_); + }; + + virtual ~DirectoryEntryArrayOutputAdapterWithStorage() { + if (!temp_storage_.empty()) { + // An easy way to release the resource references held by |temp_storage_|. + // A destructor for PP_DirectoryEntry_Dev will release them. + output(); + } + }; + + // Returns the final array of resource objects, converting the + // PP_DirectoryEntry_Dev written by the browser to pp::DirectoryEntry_Dev + // objects. + // + // This function should only be called once or we would end up converting + // the array more than once, which would mess up the refcounting. + std::vector<pp::DirectoryEntry_Dev>& output() { + PP_DCHECK(output_storage_.empty()); + typedef std::vector<PP_DirectoryEntry_Dev> Entries; + for (Entries::iterator it = temp_storage_.begin(); + it != temp_storage_.end(); ++it) + output_storage_.push_back(DirectoryEntry_Dev(PASS_REF, *it)); + temp_storage_.clear(); + return output_storage_; + } + + private: + // The browser will write the PP_DirectoryEntry_Devs into this array. + std::vector<PP_DirectoryEntry_Dev> temp_storage_; + + // When asked for the output, the PP_DirectoryEntry_Devs above will be + // converted to the pp::DirectoryEntry_Devs in this array for passing to the + // calling code. + std::vector<pp::DirectoryEntry_Dev> output_storage_; +}; + } // namespace pp #endif // PPAPI_CPP_ARRAY_OUTPUT_H_ diff --git a/ppapi/cpp/dev/directory_entry_dev.cc b/ppapi/cpp/dev/directory_entry_dev.cc index 80de22f..bef42c3 100644 --- a/ppapi/cpp/dev/directory_entry_dev.cc +++ b/ppapi/cpp/dev/directory_entry_dev.cc @@ -14,6 +14,12 @@ DirectoryEntry_Dev::DirectoryEntry_Dev() { memset(&data_, 0, sizeof(data_)); } +DirectoryEntry_Dev::DirectoryEntry_Dev( + PassRef, const PP_DirectoryEntry_Dev& data) { + data_.file_ref = data.file_ref; + data_.file_type = data.file_type; +} + DirectoryEntry_Dev::DirectoryEntry_Dev(const DirectoryEntry_Dev& other) { data_.file_ref = other.data_.file_ref; data_.file_type = other.data_.file_type; diff --git a/ppapi/cpp/dev/directory_entry_dev.h b/ppapi/cpp/dev/directory_entry_dev.h index 6b91ebf..9866213 100644 --- a/ppapi/cpp/dev/directory_entry_dev.h +++ b/ppapi/cpp/dev/directory_entry_dev.h @@ -13,7 +13,9 @@ namespace pp { class DirectoryEntry_Dev { public: DirectoryEntry_Dev(); + DirectoryEntry_Dev(PassRef, const PP_DirectoryEntry_Dev& data); DirectoryEntry_Dev(const DirectoryEntry_Dev& other); + ~DirectoryEntry_Dev(); DirectoryEntry_Dev& operator=(const DirectoryEntry_Dev& other); @@ -28,7 +30,6 @@ class DirectoryEntry_Dev { PP_FileType file_type() const { return data_.file_type; } private: - friend class DirectoryReader_Dev; PP_DirectoryEntry_Dev data_; }; diff --git a/ppapi/cpp/dev/directory_reader_dev.cc b/ppapi/cpp/dev/directory_reader_dev.cc index 3a53ca1..aebdca5 100644 --- a/ppapi/cpp/dev/directory_reader_dev.cc +++ b/ppapi/cpp/dev/directory_reader_dev.cc @@ -15,16 +15,16 @@ namespace pp { namespace { -template <> const char* interface_name<PPB_DirectoryReader_Dev>() { - return PPB_DIRECTORYREADER_DEV_INTERFACE; +template <> const char* interface_name<PPB_DirectoryReader_Dev_0_6>() { + return PPB_DIRECTORYREADER_DEV_INTERFACE_0_6; } } // namespace DirectoryReader_Dev::DirectoryReader_Dev(const FileRef& directory_ref) { - if (!has_interface<PPB_DirectoryReader_Dev>()) + if (!has_interface<PPB_DirectoryReader_Dev_0_6>()) return; - PassRefFromConstructor(get_interface<PPB_DirectoryReader_Dev>()->Create( + PassRefFromConstructor(get_interface<PPB_DirectoryReader_Dev_0_6>()->Create( directory_ref.pp_resource())); } @@ -32,12 +32,13 @@ DirectoryReader_Dev::DirectoryReader_Dev(const DirectoryReader_Dev& other) : Resource(other) { } -int32_t DirectoryReader_Dev::GetNextEntry(DirectoryEntry_Dev* entry, - const CompletionCallback& cc) { - if (!has_interface<PPB_DirectoryReader_Dev>()) - return cc.MayForce(PP_ERROR_NOINTERFACE); - return get_interface<PPB_DirectoryReader_Dev>()->GetNextEntry( - pp_resource(), &entry->data_, cc.pp_completion_callback()); +int32_t DirectoryReader_Dev::ReadEntries( + const CompletionCallbackWithOutput< std::vector<DirectoryEntry_Dev> >& + callback) { + if (!has_interface<PPB_DirectoryReader_Dev_0_6>()) + return callback.MayForce(PP_ERROR_NOINTERFACE); + return get_interface<PPB_DirectoryReader_Dev_0_6>()->ReadEntries( + pp_resource(), callback.output(), callback.pp_completion_callback()); } } // namespace pp diff --git a/ppapi/cpp/dev/directory_reader_dev.h b/ppapi/cpp/dev/directory_reader_dev.h index 09b2e57..cd2ce78 100644 --- a/ppapi/cpp/dev/directory_reader_dev.h +++ b/ppapi/cpp/dev/directory_reader_dev.h @@ -5,27 +5,50 @@ #ifndef PPAPI_CPP_DEV_DIRECTORY_READER_DEV_H_ #define PPAPI_CPP_DEV_DIRECTORY_READER_DEV_H_ -#include <stdlib.h> +#include <vector> #include "ppapi/c/dev/ppb_directory_reader_dev.h" #include "ppapi/cpp/resource.h" namespace pp { -class CompletionCallback; class DirectoryEntry_Dev; class FileRef; +template<typename T> class CompletionCallbackWithOutput; class DirectoryReader_Dev : public Resource { public: - // Creates a DirectoryReader for the given directory. + /// A constructor that creates a DirectoryReader resource for the given + /// directory. + /// + /// @param[in] directory_ref A <code>PP_Resource</code> corresponding to the + /// directory reference to be read. explicit DirectoryReader_Dev(const FileRef& directory_ref); DirectoryReader_Dev(const DirectoryReader_Dev& other); - // See PPB_DirectoryReader::GetNextEntry. - int32_t GetNextEntry(DirectoryEntry_Dev* entry, - const CompletionCallback& cc); + /// ReadEntries() Reads all entries in the directory. + /// + /// @param[in] cc A <code>CompletionCallbackWithOutput</code> to be called + /// upon completion of ReadEntries(). On success, the directory entries will + /// be passed to the given function. + /// + /// Normally you would use a CompletionCallbackFactory to allow callbacks to + /// be bound to your class. See completion_callback_factory.h for more + /// discussion on how to use this. Your callback will generally look like: + /// + /// @code + /// void OnReadEntries(int32_t result, + /// const std::vector<DirectoryEntry_Dev>& entries) { + /// if (result == PP_OK) + /// // use entries... + /// } + /// @endcode + /// + /// @return An int32_t containing an error code from <code>pp_errors.h</code>. + int32_t ReadEntries( + const CompletionCallbackWithOutput< std::vector<DirectoryEntry_Dev> >& + callback); }; } // namespace pp diff --git a/ppapi/cpp/output_traits.h b/ppapi/cpp/output_traits.h index 5b45aa47e..cc04330 100644 --- a/ppapi/cpp/output_traits.h +++ b/ppapi/cpp/output_traits.h @@ -5,8 +5,11 @@ #ifndef PPAPI_CPP_OUTPUT_TRAITS_H_ #define PPAPI_CPP_OUTPUT_TRAITS_H_ +#include <vector> + #include "ppapi/c/pp_resource.h" #include "ppapi/cpp/array_output.h" +#include "ppapi/cpp/dev/directory_entry_dev.h" /// @file /// This file defines internal templates for defining how data is passed to the @@ -233,6 +236,24 @@ struct CallbackOutputTraits< std::vector<pp::Var> > { } }; +// A specialization of CallbackOutputTraits to provide the callback system the +// information on how to handle vectors of pp::DirectoryEntry_Dev. This converts +// PP_DirectoryEntry_Dev to pp::DirectoryEntry_Dev when passing to the plugin. +template<> +struct CallbackOutputTraits< std::vector<pp::DirectoryEntry_Dev> > { + typedef PP_ArrayOutput APIArgType; + typedef DirectoryEntryArrayOutputAdapterWithStorage StorageType; + + static inline APIArgType StorageToAPIArg(StorageType& t) { + return t.pp_array_output(); + } + + static inline std::vector<pp::DirectoryEntry_Dev>& StorageToPluginArg( + StorageType& t) { + return t.output(); + } +}; + } // namespace internal } // namespace pp diff --git a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c index 62d984a..8cb31f7 100644 --- a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c +++ b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 The Chromium Authors. All rights reserved. +/* Copyright (c) 2013 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. */ @@ -114,14 +114,8 @@ /* Use local strcmp to avoid dependency on libc. */ static int mystrcmp(const char* s1, const char *s2) { - while (1) { - if (*s1 == 0) break; - if (*s2 == 0) break; - if (*s1 != *s2) break; - ++s1; - ++s2; - } - return *(s1) - *(s2); + while((*s1 && *s2) && (*s1++ == *s2++)); + return *(--s1) - *(--s2); } /* BEGIN Declarations for all Wrapper Infos */ @@ -183,7 +177,7 @@ static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Buffer_Dev_0_4; static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Crypto_Dev_0_1; static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_CursorControl_Dev_0_4; static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_DeviceRef_Dev_0_1; -static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_DirectoryReader_Dev_0_5; +static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_DirectoryReader_Dev_0_6; static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_FileChooser_Dev_0_5; static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_FileChooser_Dev_0_6; static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Find_Dev_0_3; @@ -1638,27 +1632,27 @@ struct PP_Var Pnacl_M18_PPB_DeviceRef_Dev_GetName(PP_Resource device_ref) { /* End wrapper methods for PPB_DeviceRef_Dev_0_1 */ -/* Begin wrapper methods for PPB_DirectoryReader_Dev_0_5 */ +/* Begin wrapper methods for PPB_DirectoryReader_Dev_0_6 */ static __attribute__((pnaclcall)) -PP_Resource Pnacl_M13_PPB_DirectoryReader_Dev_Create(PP_Resource directory_ref) { - const struct PPB_DirectoryReader_Dev_0_5 *iface = Pnacl_WrapperInfo_PPB_DirectoryReader_Dev_0_5.real_iface; +PP_Resource Pnacl_M27_PPB_DirectoryReader_Dev_Create(PP_Resource directory_ref) { + const struct PPB_DirectoryReader_Dev_0_6 *iface = Pnacl_WrapperInfo_PPB_DirectoryReader_Dev_0_6.real_iface; return iface->Create(directory_ref); } static __attribute__((pnaclcall)) -PP_Bool Pnacl_M13_PPB_DirectoryReader_Dev_IsDirectoryReader(PP_Resource resource) { - const struct PPB_DirectoryReader_Dev_0_5 *iface = Pnacl_WrapperInfo_PPB_DirectoryReader_Dev_0_5.real_iface; +PP_Bool Pnacl_M27_PPB_DirectoryReader_Dev_IsDirectoryReader(PP_Resource resource) { + const struct PPB_DirectoryReader_Dev_0_6 *iface = Pnacl_WrapperInfo_PPB_DirectoryReader_Dev_0_6.real_iface; return iface->IsDirectoryReader(resource); } static __attribute__((pnaclcall)) -int32_t Pnacl_M13_PPB_DirectoryReader_Dev_GetNextEntry(PP_Resource directory_reader, struct PP_DirectoryEntry_Dev* entry, struct PP_CompletionCallback callback) { - const struct PPB_DirectoryReader_Dev_0_5 *iface = Pnacl_WrapperInfo_PPB_DirectoryReader_Dev_0_5.real_iface; - return iface->GetNextEntry(directory_reader, entry, callback); +int32_t Pnacl_M27_PPB_DirectoryReader_Dev_ReadEntries(PP_Resource directory_reader, struct PP_ArrayOutput output, struct PP_CompletionCallback callback) { + const struct PPB_DirectoryReader_Dev_0_6 *iface = Pnacl_WrapperInfo_PPB_DirectoryReader_Dev_0_6.real_iface; + return iface->ReadEntries(directory_reader, output, callback); } -/* End wrapper methods for PPB_DirectoryReader_Dev_0_5 */ +/* End wrapper methods for PPB_DirectoryReader_Dev_0_6 */ /* Begin wrapper methods for PPB_FileChooser_Dev_0_5 */ @@ -3882,10 +3876,10 @@ struct PPB_DeviceRef_Dev_0_1 Pnacl_Wrappers_PPB_DeviceRef_Dev_0_1 = { .GetName = (struct PP_Var (*)(PP_Resource device_ref))&Pnacl_M18_PPB_DeviceRef_Dev_GetName }; -struct PPB_DirectoryReader_Dev_0_5 Pnacl_Wrappers_PPB_DirectoryReader_Dev_0_5 = { - .Create = (PP_Resource (*)(PP_Resource directory_ref))&Pnacl_M13_PPB_DirectoryReader_Dev_Create, - .IsDirectoryReader = (PP_Bool (*)(PP_Resource resource))&Pnacl_M13_PPB_DirectoryReader_Dev_IsDirectoryReader, - .GetNextEntry = (int32_t (*)(PP_Resource directory_reader, struct PP_DirectoryEntry_Dev* entry, struct PP_CompletionCallback callback))&Pnacl_M13_PPB_DirectoryReader_Dev_GetNextEntry +struct PPB_DirectoryReader_Dev_0_6 Pnacl_Wrappers_PPB_DirectoryReader_Dev_0_6 = { + .Create = (PP_Resource (*)(PP_Resource directory_ref))&Pnacl_M27_PPB_DirectoryReader_Dev_Create, + .IsDirectoryReader = (PP_Bool (*)(PP_Resource resource))&Pnacl_M27_PPB_DirectoryReader_Dev_IsDirectoryReader, + .ReadEntries = (int32_t (*)(PP_Resource directory_reader, struct PP_ArrayOutput output, struct PP_CompletionCallback callback))&Pnacl_M27_PPB_DirectoryReader_Dev_ReadEntries }; struct PPB_FileChooser_Dev_0_5 Pnacl_Wrappers_PPB_FileChooser_Dev_0_5 = { @@ -4699,9 +4693,9 @@ static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_DeviceRef_Dev_0_1 = { .real_iface = NULL }; -static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_DirectoryReader_Dev_0_5 = { - .iface_macro = PPB_DIRECTORYREADER_DEV_INTERFACE_0_5, - .wrapped_iface = (void *) &Pnacl_Wrappers_PPB_DirectoryReader_Dev_0_5, +static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_DirectoryReader_Dev_0_6 = { + .iface_macro = PPB_DIRECTORYREADER_DEV_INTERFACE_0_6, + .wrapped_iface = (void *) &Pnacl_Wrappers_PPB_DirectoryReader_Dev_0_6, .real_iface = NULL }; @@ -5225,7 +5219,7 @@ static struct __PnaclWrapperInfo *s_ppb_wrappers[] = { &Pnacl_WrapperInfo_PPB_Crypto_Dev_0_1, &Pnacl_WrapperInfo_PPB_CursorControl_Dev_0_4, &Pnacl_WrapperInfo_PPB_DeviceRef_Dev_0_1, - &Pnacl_WrapperInfo_PPB_DirectoryReader_Dev_0_5, + &Pnacl_WrapperInfo_PPB_DirectoryReader_Dev_0_6, &Pnacl_WrapperInfo_PPB_FileChooser_Dev_0_5, &Pnacl_WrapperInfo_PPB_FileChooser_Dev_0_6, &Pnacl_WrapperInfo_PPB_Find_Dev_0_3, diff --git a/ppapi/proxy/directory_reader_resource.cc b/ppapi/proxy/directory_reader_resource.cc index 99075a3..17826d03 100644 --- a/ppapi/proxy/directory_reader_resource.cc +++ b/ppapi/proxy/directory_reader_resource.cc @@ -21,13 +21,22 @@ using ppapi::proxy::PPB_FileRef_Proxy; namespace ppapi { namespace proxy { +namespace { + +void ReleaseEntries(const std::vector<PP_DirectoryEntry_Dev>& entries) { + ResourceTracker* tracker = PpapiGlobals::Get()->GetResourceTracker(); + for (std::vector<PP_DirectoryEntry_Dev>::const_iterator it = entries.begin(); + it != entries.end(); ++it) + tracker->ReleaseResource(it->file_ref); +} + +} // namespace + DirectoryReaderResource::DirectoryReaderResource( Connection connection, PP_Instance instance, PP_Resource directory_ref) - : PluginResource(connection, instance), - output_(NULL), - did_receive_get_entries_reply_(false) { + : PluginResource(connection, instance) { directory_resource_ = PpapiGlobals::Get()->GetResourceTracker()->GetResource(directory_ref); } @@ -40,18 +49,14 @@ DirectoryReaderResource::AsPPB_DirectoryReader_API() { return this; } -int32_t DirectoryReaderResource::GetNextEntry( - PP_DirectoryEntry_Dev* entry, +int32_t DirectoryReaderResource::ReadEntries( + const PP_ArrayOutput& output, scoped_refptr<TrackedCallback> callback) { if (TrackedCallback::IsPending(callback_)) return PP_ERROR_INPROGRESS; - output_ = entry; callback_ = callback; - if (FillUpEntry()) - return PP_OK; - if (!sent_create_to_renderer()) SendCreate(RENDERER, PpapiHostMsg_DirectoryReader_Create()); @@ -59,61 +64,44 @@ int32_t DirectoryReaderResource::GetNextEntry( directory_resource_->host_resource()); Call<PpapiPluginMsg_DirectoryReader_GetEntriesReply>( RENDERER, msg, - base::Bind(&DirectoryReaderResource::OnPluginMsgGetEntriesReply, this)); + base::Bind(&DirectoryReaderResource::OnPluginMsgGetEntriesReply, + this, output)); return PP_OK_COMPLETIONPENDING; } void DirectoryReaderResource::OnPluginMsgGetEntriesReply( + const PP_ArrayOutput& output, const ResourceMessageReplyParams& params, const std::vector<ppapi::PPB_FileRef_CreateInfo>& infos, const std::vector<PP_FileType>& file_types) { CHECK_EQ(infos.size(), file_types.size()); - did_receive_get_entries_reply_ = true; + std::vector<PP_DirectoryEntry_Dev> entries; for (std::vector<ppapi::PPB_FileRef_CreateInfo>::size_type i = 0; i < infos.size(); ++i) { - DirectoryEntry entry; - entry.file_resource = ScopedPPResource( - ScopedPPResource::PassRef(), - PPB_FileRef_Proxy::DeserializeFileRef(infos[i])); + PP_DirectoryEntry_Dev entry; + entry.file_ref = PPB_FileRef_Proxy::DeserializeFileRef(infos[i]); entry.file_type = file_types[i]; - entries_.push(entry); + entries.push_back(entry); } - if (!TrackedCallback::IsPending(callback_)) + if (!TrackedCallback::IsPending(callback_)) { + ReleaseEntries(entries); + entries.clear(); return; - - FillUpEntry(); - callback_->Run(params.result()); -} - -bool DirectoryReaderResource::FillUpEntry() { - DCHECK(output_); - - if (!did_receive_get_entries_reply_) - return false; - - if (output_->file_ref) { - // Release an existing file reference before the next reference is stored. - // (see the API doc) - PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource( - output_->file_ref); } - if (!entries_.empty()) { - DirectoryEntry entry = entries_.front(); - entries_.pop(); - output_->file_ref = entry.file_resource.Release(); - output_->file_type = entry.file_type; - output_ = NULL; - return true; + ArrayWriter writer(output); + if (!writer.is_valid()) { + ReleaseEntries(entries); + entries.clear(); + callback_->Run(PP_ERROR_FAILED); + return; } - // Set the reference to zero to indicates reaching the end of the directory. - output_->file_ref = 0; - output_->file_type = PP_FILETYPE_OTHER; - output_ = NULL; - return true; + writer.StoreVector(entries); + entries.clear(); + callback_->Run(params.result()); } } // namespace proxy diff --git a/ppapi/proxy/directory_reader_resource.h b/ppapi/proxy/directory_reader_resource.h index b79993a..e532414 100644 --- a/ppapi/proxy/directory_reader_resource.h +++ b/ppapi/proxy/directory_reader_resource.h @@ -5,16 +5,15 @@ #ifndef PPAPI_PROXY_DIRECTORY_READER_RESOURCE_H_ #define PPAPI_PROXY_DIRECTORY_READER_RESOURCE_H_ -#include <queue> #include <vector> #include "base/basictypes.h" #include "base/memory/ref_counted.h" #include "ppapi/proxy/plugin_resource.h" #include "ppapi/proxy/ppapi_proxy_export.h" +#include "ppapi/shared_impl/array_writer.h" #include "ppapi/shared_impl/ppb_file_ref_shared.h" #include "ppapi/shared_impl/resource.h" -#include "ppapi/shared_impl/scoped_pp_resource.h" #include "ppapi/thunk/ppb_directory_reader_api.h" namespace ppapi { @@ -36,32 +35,18 @@ class PPAPI_PROXY_EXPORT DirectoryReaderResource virtual thunk::PPB_DirectoryReader_API* AsPPB_DirectoryReader_API() OVERRIDE; // PPB_DirectoryReader_API. - virtual int32_t GetNextEntry( - PP_DirectoryEntry_Dev* entry, + virtual int32_t ReadEntries( + const PP_ArrayOutput& output, scoped_refptr<TrackedCallback> callback) OVERRIDE; private: - struct DirectoryEntry { - ScopedPPResource file_resource; - PP_FileType file_type; - }; - void OnPluginMsgGetEntriesReply( + const PP_ArrayOutput& output, const ResourceMessageReplyParams& params, const std::vector<ppapi::PPB_FileRef_CreateInfo>& infos, const std::vector<PP_FileType>& file_types); - // Fills up an output with the next entry in the directory. If the plugin - // resource did not receive directory entries from the host side, returns - // false. - bool FillUpEntry(); - scoped_refptr<Resource> directory_resource_; - std::queue<DirectoryEntry> entries_; - - PP_DirectoryEntry_Dev* output_; - bool did_receive_get_entries_reply_; - scoped_refptr<TrackedCallback> callback_; DISALLOW_COPY_AND_ASSIGN(DirectoryReaderResource); diff --git a/ppapi/tests/test_directory_reader.cc b/ppapi/tests/test_directory_reader.cc index 254a355..6f23bcaf 100644 --- a/ppapi/tests/test_directory_reader.cc +++ b/ppapi/tests/test_directory_reader.cc @@ -23,63 +23,63 @@ REGISTER_TEST_CASE(DirectoryReader); namespace { +typedef std::vector<pp::DirectoryEntry_Dev> Entries; + std::string IntegerToString(int value) { char result[12]; sprintf(result, "%d", value); return result; } -int32_t DeleteDirectoryRecursively(pp::FileRef* dir, - TestCompletionCallback* callback) { - if (!dir || !callback) +} // namespace + +bool TestDirectoryReader::Init() { + return CheckTestingInterface() && EnsureRunningOverHTTP(); +} + +void TestDirectoryReader::RunTests(const std::string& filter) { + RUN_TEST(ReadEntries, filter); +} + +int32_t TestDirectoryReader::DeleteDirectoryRecursively(pp::FileRef* dir) { + if (!dir) return PP_ERROR_BADARGUMENT; + TestCompletionCallback callback(instance_->pp_instance(), force_async_); + TestCompletionCallbackWithOutput<Entries> output_callback( + instance_->pp_instance(), force_async_); + int32_t rv = PP_OK; pp::DirectoryReader_Dev directory_reader(*dir); - std::vector<pp::DirectoryEntry_Dev> entries; - pp::DirectoryEntry_Dev entry; - do { - rv = directory_reader.GetNextEntry(&entry, *callback); - if (rv == PP_OK_COMPLETIONPENDING) - rv = callback->WaitForResult(); - if (rv != PP_OK && rv != PP_ERROR_FILENOTFOUND) - return rv; - if (!entry.is_null()) - entries.push_back(entry); - } while (!entry.is_null()); - - for (std::vector<pp::DirectoryEntry_Dev>::const_iterator it = entries.begin(); + rv = directory_reader.ReadEntries(output_callback); + if (rv == PP_OK_COMPLETIONPENDING) + rv = output_callback.WaitForResult(); + if (rv != PP_OK && rv != PP_ERROR_FILENOTFOUND) + return rv; + + Entries entries = output_callback.output(); + for (Entries::const_iterator it = entries.begin(); it != entries.end(); ++it) { pp::FileRef file_ref = it->file_ref(); if (it->file_type() == PP_FILETYPE_DIRECTORY) { - rv = DeleteDirectoryRecursively(&file_ref, callback); + rv = DeleteDirectoryRecursively(&file_ref); if (rv != PP_OK && rv != PP_ERROR_FILENOTFOUND) return rv; } else { - rv = file_ref.Delete(*callback); + rv = file_ref.Delete(callback); if (rv == PP_OK_COMPLETIONPENDING) - rv = callback->WaitForResult(); + rv = callback.WaitForResult(); if (rv != PP_OK && rv != PP_ERROR_FILENOTFOUND) return rv; } } - rv = dir->Delete(*callback); + rv = dir->Delete(callback); if (rv == PP_OK_COMPLETIONPENDING) - rv = callback->WaitForResult(); + rv = callback.WaitForResult(); return rv; } -} // namespace - -bool TestDirectoryReader::Init() { - return CheckTestingInterface() && EnsureRunningOverHTTP(); -} - -void TestDirectoryReader::RunTests(const std::string& filter) { - RUN_TEST(GetNextFile, filter); -} - -std::string TestDirectoryReader::TestGetNextFile() { +std::string TestDirectoryReader::TestReadEntries() { TestCompletionCallback callback(instance_->pp_instance(), force_async_); pp::FileSystem file_system( instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY); @@ -97,7 +97,7 @@ std::string TestDirectoryReader::TestGetNextFile() { const char* dir_prefix = "dir_"; pp::FileRef test_dir(file_system, test_dir_name); - rv = DeleteDirectoryRecursively(&test_dir, &callback); + rv = DeleteDirectoryRecursively(&test_dir); if (rv != PP_OK && rv != PP_ERROR_FILENOTFOUND) return ReportError("DeleteDirectoryRecursively", rv); @@ -144,31 +144,29 @@ std::string TestDirectoryReader::TestGetNextFile() { expected_dir_names.insert(buffer); } - // Test that |GetNextEntry()| is able to enumerate all directories and files - // that we created. + // Test that |ReadEntries()| is able to fetch all directories and files that + // we created. { + TestCompletionCallbackWithOutput<Entries> output_callback( + instance_->pp_instance(), force_async_); + pp::DirectoryReader_Dev directory_reader(test_dir); - std::vector<pp::DirectoryEntry_Dev> entries; - pp::DirectoryEntry_Dev entry; - do { - rv = directory_reader.GetNextEntry(&entry, callback); - if (force_async_ && rv != PP_OK_COMPLETIONPENDING) - return ReportError("DirectoryReader::GetNextEntry force_async", rv); - if (rv == PP_OK_COMPLETIONPENDING) - rv = callback.WaitForResult(); - if (rv != PP_OK) - return ReportError("DirectoryReader::GetNextEntry", rv); - if (!entry.is_null()) - entries.push_back(entry); - } while (!entry.is_null()); + rv = directory_reader.ReadEntries(output_callback); + if (force_async_ && rv != PP_OK_COMPLETIONPENDING) + return ReportError("DirectoryReader::ReadEntries force_async", rv); + if (rv == PP_OK_COMPLETIONPENDING) + rv = output_callback.WaitForResult(); + if (rv != PP_OK) + return ReportError("DirectoryReader::ReadEntries", rv); + Entries entries = output_callback.output(); size_t sum = expected_file_names.size() + expected_dir_names.size(); if (entries.size() != sum) return "Expected " + IntegerToString(sum) + " entries, got " + - IntegerToString(entries.size()); + IntegerToString(entries.size()); - for (std::vector<pp::DirectoryEntry_Dev>::const_iterator it = - entries.begin(); it != entries.end(); ++it) { + for (Entries::const_iterator it = entries.begin(); + it != entries.end(); ++it) { pp::FileRef file_ref = it->file_ref(); std::string file_path = file_ref.GetPath().AsString(); std::set<std::string>::iterator found = @@ -190,34 +188,27 @@ std::string TestDirectoryReader::TestGetNextFile() { return "Expected more file paths."; } - // Test cancellation of asynchronous |GetNextEntry()|. + // Test cancellation of asynchronous |ReadEntries()|. { - // Declaring |entry| here prevents memory corruption for some failure modes - // and lets us to detect some other failures. - pp::DirectoryEntry_Dev entry; - callback.reset_run_count(); + TestCompletionCallbackWithOutput<Entries> output_callback( + instance_->pp_instance(), force_async_); + // Note that the directory reader will be deleted immediately. - rv = pp::DirectoryReader_Dev(test_dir).GetNextEntry(&entry, callback); + rv = pp::DirectoryReader_Dev(test_dir).ReadEntries(output_callback); if (force_async_ && rv != PP_OK_COMPLETIONPENDING) - return ReportError("DirectoryReader::GetNextEntry force_async", rv); - if (callback.run_count() > 0) - return "DirectoryReader::GetNextEntry ran callback synchronously."; + return ReportError("DirectoryReader::ReadEntries force_async", rv); + if (output_callback.run_count() > 0) + return "DirectoryReader::ReadEntries ran callback synchronously."; - // If |GetNextEntry()| is completing asynchronously, the callback should be + // If |ReadEntries()| is completing asynchronously, the callback should be // aborted (i.e., called with |PP_ERROR_ABORTED| from the message loop) // since the resource was destroyed. if (rv == PP_OK_COMPLETIONPENDING) { - // |GetNextEntry()| *may* have written to |entry| (e.g., synchronously, - // before the resource was destroyed), but it must not write to it after - // destruction. - bool entry_is_null = entry.is_null(); - rv = callback.WaitForResult(); + rv = output_callback.WaitForResult(); if (rv != PP_ERROR_ABORTED) - return "DirectoryReader::GetNextEntry not aborted."; - if (entry.is_null() != entry_is_null) - return "DirectoryReader::GetNextEntry wrote result after destruction."; + return "DirectoryReader::ReadEntries not aborted."; } else if (rv != PP_OK) { - return ReportError("DirectoryReader::GetNextEntry", rv); + return ReportError("DirectoryReader::ReadEntries", rv); } } diff --git a/ppapi/tests/test_directory_reader.h b/ppapi/tests/test_directory_reader.h index 8f68530..ee446c5 100644 --- a/ppapi/tests/test_directory_reader.h +++ b/ppapi/tests/test_directory_reader.h @@ -9,6 +9,10 @@ #include "ppapi/tests/test_case.h" +namespace pp { +class FileRef; +} + class TestDirectoryReader : public TestCase { public: explicit TestDirectoryReader(TestingInstance* instance) @@ -19,7 +23,9 @@ class TestDirectoryReader : public TestCase { virtual void RunTests(const std::string& filter); private: - std::string TestGetNextFile(); + int32_t DeleteDirectoryRecursively(pp::FileRef*); + + std::string TestReadEntries(); }; #endif // PAPPI_TESTS_TEST_DIRECTORY_READER_H_ diff --git a/ppapi/tests/test_file_ref.cc b/ppapi/tests/test_file_ref.cc index b1638b7..09260120 100644 --- a/ppapi/tests/test_file_ref.cc +++ b/ppapi/tests/test_file_ref.cc @@ -716,26 +716,23 @@ std::string TestFileRef::TestFileNameEscaping() { // DirectoryReader only works out-of-process. if (testing_interface_->IsOutOfProcess()) { + TestCompletionCallbackWithOutput< std::vector<pp::DirectoryEntry_Dev> > + output_callback(instance_->pp_instance(), force_async_); pp::DirectoryReader_Dev directory_reader(test_dir_ref); - pp::DirectoryEntry_Dev entry; - rv = directory_reader.GetNextEntry(&entry, callback); + rv = directory_reader.ReadEntries(output_callback); if (rv == PP_OK_COMPLETIONPENDING) - rv = callback.WaitForResult(); + rv = output_callback.WaitForResult(); if (rv != PP_OK && rv != PP_ERROR_FILENOTFOUND) - return ReportError("DirectoryEntry_Dev::GetNextEntry", rv); - if (entry.is_null()) - return "Entry was not found."; - if (entry.file_ref().GetName().AsString() != kTerribleName) - return "Entry name did not match."; + return ReportError("DirectoryEntry_Dev::ReadEntries", rv); - rv = directory_reader.GetNextEntry(&entry, callback); - if (rv == PP_OK_COMPLETIONPENDING) - rv = callback.WaitForResult(); - if (rv != PP_OK && rv != PP_ERROR_FILENOTFOUND) - return ReportError("DirectoryEntry_Dev::GetNextEntry", rv); - if (!entry.is_null()) + std::vector<pp::DirectoryEntry_Dev> entries = output_callback.output(); + if (entries.empty()) + return "Entry was not found."; + if (entries.size() != 1) return "Directory had too many entries."; + if (entries.front().file_ref().GetName().AsString() != kTerribleName) + return "Entry name did not match."; } PASS(); diff --git a/ppapi/thunk/interfaces_ppb_public_dev.h b/ppapi/thunk/interfaces_ppb_public_dev.h index f45a138..708b6ef 100644 --- a/ppapi/thunk/interfaces_ppb_public_dev.h +++ b/ppapi/thunk/interfaces_ppb_public_dev.h @@ -52,8 +52,8 @@ PROXIED_IFACE(PPB_Graphics3D, PPB_GLESChromiumTextureMapping_Dev_0_1) PROXIED_IFACE(NoAPIName, PPB_CRYPTO_DEV_INTERFACE_0_1, PPB_Crypto_Dev_0_1) PROXIED_IFACE(NoAPIName, PPB_DEVICEREF_DEV_INTERFACE_0_1, PPB_DeviceRef_Dev_0_1) -PROXIED_IFACE(NoAPIName, PPB_DIRECTORYREADER_DEV_INTERFACE_0_5, - PPB_DirectoryReader_Dev_0_5) +PROXIED_IFACE(NoAPIName, PPB_DIRECTORYREADER_DEV_INTERFACE_0_6, + PPB_DirectoryReader_Dev_0_6) PROXIED_IFACE(NoAPIName, PPB_GRAPHICS2D_DEV_INTERFACE_0_1, PPB_Graphics2D_Dev_0_1) PROXIED_IFACE(PPB_Instance, PPB_CHAR_SET_DEV_INTERFACE_0_4, PPB_CharSet_Dev_0_4) diff --git a/ppapi/thunk/ppb_directory_reader_api.h b/ppapi/thunk/ppb_directory_reader_api.h index 6a32934..cf71ddf 100644 --- a/ppapi/thunk/ppb_directory_reader_api.h +++ b/ppapi/thunk/ppb_directory_reader_api.h @@ -18,8 +18,8 @@ class PPB_DirectoryReader_API { public: virtual ~PPB_DirectoryReader_API() {} - virtual int32_t GetNextEntry(PP_DirectoryEntry_Dev* entry, - scoped_refptr<TrackedCallback> callback) = 0; + virtual int32_t ReadEntries(const PP_ArrayOutput& output, + scoped_refptr<TrackedCallback> callback) = 0; }; } // namespace thunk diff --git a/ppapi/thunk/ppb_directory_reader_thunk.cc b/ppapi/thunk/ppb_directory_reader_thunk.cc index eaa7c2d..aaee6f7 100644 --- a/ppapi/thunk/ppb_directory_reader_thunk.cc +++ b/ppapi/thunk/ppb_directory_reader_thunk.cc @@ -35,25 +35,25 @@ PP_Bool IsDirectoryReader(PP_Resource resource) { return PP_FromBool(enter.succeeded()); } -int32_t GetNextEntry(PP_Resource directory_reader, - PP_DirectoryEntry_Dev* entry, - PP_CompletionCallback callback) { +int32_t ReadEntries(PP_Resource directory_reader, + PP_ArrayOutput output, + PP_CompletionCallback callback) { EnterResource<PPB_DirectoryReader_API> enter( directory_reader, callback, true); if (enter.failed()) return enter.retval(); - return enter.SetResult(enter.object()->GetNextEntry(entry, enter.callback())); + return enter.SetResult(enter.object()->ReadEntries(output, enter.callback())); } const PPB_DirectoryReader_Dev g_ppb_directory_reader_thunk = { &Create, &IsDirectoryReader, - &GetNextEntry + &ReadEntries }; } // namespace -const PPB_DirectoryReader_Dev_0_5* GetPPB_DirectoryReader_Dev_0_5_Thunk() { +const PPB_DirectoryReader_Dev_0_6* GetPPB_DirectoryReader_Dev_0_6_Thunk() { return &g_ppb_directory_reader_thunk; } |