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, 244 insertions, 290 deletions
diff --git a/ppapi/api/dev/ppb_directory_reader_dev.idl b/ppapi/api/dev/ppb_directory_reader_dev.idl index 5ba6065..659ed09 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 { - M27 = 0.6 + M13 = 0.5 }; [assert_size(8)] @@ -29,18 +29,23 @@ interface PPB_DirectoryReader_Dev { // DirectoryReader. PP_Bool IsDirectoryReader([in] PP_Resource resource); - // Reads all entries in the directory. + // 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. // - // @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. + // EXAMPLE USAGE: // - // @return An error code from <code>pp_errors.h</code>. + // 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); // - int32_t ReadEntries([in] PP_Resource directory_reader, - [in] PP_ArrayOutput output, - [in] PP_CompletionCallback callback); + int32_t GetNextEntry([in] PP_Resource directory_reader, + [out] PP_DirectoryEntry_Dev entry, + [in] PP_CompletionCallback callback); }; diff --git a/ppapi/api/pp_macros.idl b/ppapi/api/pp_macros.idl index 999da67..edb4684 100644 --- a/ppapi/api/pp_macros.idl +++ b/ppapi/api/pp_macros.idl @@ -108,3 +108,4 @@ 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 060e489..eda9e8f 100644 --- a/ppapi/c/dev/ppb_directory_reader_dev.h +++ b/ppapi/c/dev/ppb_directory_reader_dev.h @@ -3,12 +3,11 @@ * found in the LICENSE file. */ -/* From dev/ppb_directory_reader_dev.idl modified Fri Feb 15 16:46:46 2013. */ +/* From dev/ppb_directory_reader_dev.idl modified Mon Nov 26 13:52:22 2012. */ #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" @@ -16,8 +15,8 @@ #include "ppapi/c/pp_resource.h" #include "ppapi/c/pp_stdint.h" -#define PPB_DIRECTORYREADER_DEV_INTERFACE_0_6 "PPB_DirectoryReader(Dev);0.6" -#define PPB_DIRECTORYREADER_DEV_INTERFACE PPB_DIRECTORYREADER_DEV_INTERFACE_0_6 +#define PPB_DIRECTORYREADER_DEV_INTERFACE_0_5 "PPB_DirectoryReader(Dev);0.5" +#define PPB_DIRECTORYREADER_DEV_INTERFACE PPB_DIRECTORYREADER_DEV_INTERFACE_0_5 /** * @file @@ -43,7 +42,7 @@ PP_COMPILE_ASSERT_STRUCT_SIZE_IN_BYTES(PP_DirectoryEntry_Dev, 8); * @addtogroup Interfaces * @{ */ -struct PPB_DirectoryReader_Dev_0_6 { +struct PPB_DirectoryReader_Dev_0_5 { /* 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 @@ -53,23 +52,28 @@ struct PPB_DirectoryReader_Dev_0_6 { * PP_FALSE if the resource is invalid or some type other than a * DirectoryReader. */ PP_Bool (*IsDirectoryReader)(PP_Resource resource); - /* Reads all entries in the directory. + /* 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. * - * @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. + * EXAMPLE USAGE: * - * @return An error code from <code>pp_errors.h</code>. + * 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); */ - int32_t (*ReadEntries)(PP_Resource directory_reader, - struct PP_ArrayOutput output, - struct PP_CompletionCallback callback); + int32_t (*GetNextEntry)(PP_Resource directory_reader, + struct PP_DirectoryEntry_Dev* entry, + struct PP_CompletionCallback callback); }; -typedef struct PPB_DirectoryReader_Dev_0_6 PPB_DirectoryReader_Dev; +typedef struct PPB_DirectoryReader_Dev_0_5 PPB_DirectoryReader_Dev; /** * @} */ diff --git a/ppapi/c/pp_macros.h b/ppapi/c/pp_macros.h index 83f85d6..1f8b6d8 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 Fri Feb 15 16:46:46 2013. */ +/* From pp_macros.idl modified Wed Jan 9 18:07:46 2013. */ #ifndef PPAPI_C_PP_MACROS_H_ #define PPAPI_C_PP_MACROS_H_ -#define PPAPI_RELEASE 27 +#define PPAPI_RELEASE 25 /** * @file diff --git a/ppapi/cpp/array_output.h b/ppapi/cpp/array_output.h index 3a52190..fe0bbc3 100644 --- a/ppapi/cpp/array_output.h +++ b/ppapi/cpp/array_output.h @@ -7,10 +7,8 @@ #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" @@ -269,47 +267,6 @@ 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 bef42c3..80de22f 100644 --- a/ppapi/cpp/dev/directory_entry_dev.cc +++ b/ppapi/cpp/dev/directory_entry_dev.cc @@ -14,12 +14,6 @@ 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 9866213..6b91ebf 100644 --- a/ppapi/cpp/dev/directory_entry_dev.h +++ b/ppapi/cpp/dev/directory_entry_dev.h @@ -13,9 +13,7 @@ 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); @@ -30,6 +28,7 @@ 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 aebdca5..3a53ca1 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_0_6>() { - return PPB_DIRECTORYREADER_DEV_INTERFACE_0_6; +template <> const char* interface_name<PPB_DirectoryReader_Dev>() { + return PPB_DIRECTORYREADER_DEV_INTERFACE; } } // namespace DirectoryReader_Dev::DirectoryReader_Dev(const FileRef& directory_ref) { - if (!has_interface<PPB_DirectoryReader_Dev_0_6>()) + if (!has_interface<PPB_DirectoryReader_Dev>()) return; - PassRefFromConstructor(get_interface<PPB_DirectoryReader_Dev_0_6>()->Create( + PassRefFromConstructor(get_interface<PPB_DirectoryReader_Dev>()->Create( directory_ref.pp_resource())); } @@ -32,13 +32,12 @@ DirectoryReader_Dev::DirectoryReader_Dev(const DirectoryReader_Dev& other) : Resource(other) { } -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()); +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()); } } // namespace pp diff --git a/ppapi/cpp/dev/directory_reader_dev.h b/ppapi/cpp/dev/directory_reader_dev.h index cd2ce78..09b2e57 100644 --- a/ppapi/cpp/dev/directory_reader_dev.h +++ b/ppapi/cpp/dev/directory_reader_dev.h @@ -5,50 +5,27 @@ #ifndef PPAPI_CPP_DEV_DIRECTORY_READER_DEV_H_ #define PPAPI_CPP_DEV_DIRECTORY_READER_DEV_H_ -#include <vector> +#include <stdlib.h> #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: - /// 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. + // Creates a DirectoryReader for the given directory. explicit DirectoryReader_Dev(const FileRef& directory_ref); DirectoryReader_Dev(const DirectoryReader_Dev& other); - /// 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); + // See PPB_DirectoryReader::GetNextEntry. + int32_t GetNextEntry(DirectoryEntry_Dev* entry, + const CompletionCallback& cc); }; } // namespace pp diff --git a/ppapi/cpp/output_traits.h b/ppapi/cpp/output_traits.h index cc04330..5b45aa47e 100644 --- a/ppapi/cpp/output_traits.h +++ b/ppapi/cpp/output_traits.h @@ -5,11 +5,8 @@ #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 @@ -236,24 +233,6 @@ 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 8cb31f7..62d984a 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) 2013 The Chromium Authors. All rights reserved. +/* 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. */ @@ -114,8 +114,14 @@ /* Use local strcmp to avoid dependency on libc. */ static int mystrcmp(const char* s1, const char *s2) { - while((*s1 && *s2) && (*s1++ == *s2++)); - return *(--s1) - *(--s2); + while (1) { + if (*s1 == 0) break; + if (*s2 == 0) break; + if (*s1 != *s2) break; + ++s1; + ++s2; + } + return *(s1) - *(s2); } /* BEGIN Declarations for all Wrapper Infos */ @@ -177,7 +183,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_6; +static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_DirectoryReader_Dev_0_5; 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; @@ -1632,27 +1638,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_6 */ +/* Begin wrapper methods for PPB_DirectoryReader_Dev_0_5 */ static __attribute__((pnaclcall)) -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; +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; return iface->Create(directory_ref); } static __attribute__((pnaclcall)) -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; +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; return iface->IsDirectoryReader(resource); } static __attribute__((pnaclcall)) -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); +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); } -/* End wrapper methods for PPB_DirectoryReader_Dev_0_6 */ +/* End wrapper methods for PPB_DirectoryReader_Dev_0_5 */ /* Begin wrapper methods for PPB_FileChooser_Dev_0_5 */ @@ -3876,10 +3882,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_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_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_FileChooser_Dev_0_5 Pnacl_Wrappers_PPB_FileChooser_Dev_0_5 = { @@ -4693,9 +4699,9 @@ static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_DeviceRef_Dev_0_1 = { .real_iface = NULL }; -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, +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, .real_iface = NULL }; @@ -5219,7 +5225,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_6, + &Pnacl_WrapperInfo_PPB_DirectoryReader_Dev_0_5, &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 17826d03..99075a3 100644 --- a/ppapi/proxy/directory_reader_resource.cc +++ b/ppapi/proxy/directory_reader_resource.cc @@ -21,22 +21,13 @@ 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) { + : PluginResource(connection, instance), + output_(NULL), + did_receive_get_entries_reply_(false) { directory_resource_ = PpapiGlobals::Get()->GetResourceTracker()->GetResource(directory_ref); } @@ -49,14 +40,18 @@ DirectoryReaderResource::AsPPB_DirectoryReader_API() { return this; } -int32_t DirectoryReaderResource::ReadEntries( - const PP_ArrayOutput& output, +int32_t DirectoryReaderResource::GetNextEntry( + PP_DirectoryEntry_Dev* entry, 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()); @@ -64,44 +59,61 @@ int32_t DirectoryReaderResource::ReadEntries( directory_resource_->host_resource()); Call<PpapiPluginMsg_DirectoryReader_GetEntriesReply>( RENDERER, msg, - base::Bind(&DirectoryReaderResource::OnPluginMsgGetEntriesReply, - this, output)); + base::Bind(&DirectoryReaderResource::OnPluginMsgGetEntriesReply, this)); 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) { - PP_DirectoryEntry_Dev entry; - entry.file_ref = PPB_FileRef_Proxy::DeserializeFileRef(infos[i]); + DirectoryEntry entry; + entry.file_resource = ScopedPPResource( + ScopedPPResource::PassRef(), + PPB_FileRef_Proxy::DeserializeFileRef(infos[i])); entry.file_type = file_types[i]; - entries.push_back(entry); + entries_.push(entry); } - if (!TrackedCallback::IsPending(callback_)) { - ReleaseEntries(entries); - entries.clear(); + if (!TrackedCallback::IsPending(callback_)) 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); } - ArrayWriter writer(output); - if (!writer.is_valid()) { - ReleaseEntries(entries); - entries.clear(); - callback_->Run(PP_ERROR_FAILED); - return; + 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; } - writer.StoreVector(entries); - entries.clear(); - callback_->Run(params.result()); + // 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; } } // namespace proxy diff --git a/ppapi/proxy/directory_reader_resource.h b/ppapi/proxy/directory_reader_resource.h index e532414..b79993a 100644 --- a/ppapi/proxy/directory_reader_resource.h +++ b/ppapi/proxy/directory_reader_resource.h @@ -5,15 +5,16 @@ #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 { @@ -35,18 +36,32 @@ class PPAPI_PROXY_EXPORT DirectoryReaderResource virtual thunk::PPB_DirectoryReader_API* AsPPB_DirectoryReader_API() OVERRIDE; // PPB_DirectoryReader_API. - virtual int32_t ReadEntries( - const PP_ArrayOutput& output, + virtual int32_t GetNextEntry( + PP_DirectoryEntry_Dev* entry, 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 6f23bcaf..254a355 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; } -} // 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) +int32_t DeleteDirectoryRecursively(pp::FileRef* dir, + TestCompletionCallback* callback) { + if (!dir || !callback) 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); - 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(); + 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(); it != entries.end(); ++it) { pp::FileRef file_ref = it->file_ref(); if (it->file_type() == PP_FILETYPE_DIRECTORY) { - rv = DeleteDirectoryRecursively(&file_ref); + rv = DeleteDirectoryRecursively(&file_ref, callback); 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; } -std::string TestDirectoryReader::TestReadEntries() { +} // namespace + +bool TestDirectoryReader::Init() { + return CheckTestingInterface() && EnsureRunningOverHTTP(); +} + +void TestDirectoryReader::RunTests(const std::string& filter) { + RUN_TEST(GetNextFile, filter); +} + +std::string TestDirectoryReader::TestGetNextFile() { TestCompletionCallback callback(instance_->pp_instance(), force_async_); pp::FileSystem file_system( instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY); @@ -97,7 +97,7 @@ std::string TestDirectoryReader::TestReadEntries() { const char* dir_prefix = "dir_"; pp::FileRef test_dir(file_system, test_dir_name); - rv = DeleteDirectoryRecursively(&test_dir); + rv = DeleteDirectoryRecursively(&test_dir, &callback); if (rv != PP_OK && rv != PP_ERROR_FILENOTFOUND) return ReportError("DeleteDirectoryRecursively", rv); @@ -144,29 +144,31 @@ std::string TestDirectoryReader::TestReadEntries() { expected_dir_names.insert(buffer); } - // Test that |ReadEntries()| is able to fetch all directories and files that - // we created. + // Test that |GetNextEntry()| is able to enumerate all directories and files + // that we created. { - TestCompletionCallbackWithOutput<Entries> output_callback( - instance_->pp_instance(), force_async_); - pp::DirectoryReader_Dev directory_reader(test_dir); - 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); + 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()); - 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 (Entries::const_iterator it = entries.begin(); - it != entries.end(); ++it) { + for (std::vector<pp::DirectoryEntry_Dev>::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 = @@ -188,27 +190,34 @@ std::string TestDirectoryReader::TestReadEntries() { return "Expected more file paths."; } - // Test cancellation of asynchronous |ReadEntries()|. + // Test cancellation of asynchronous |GetNextEntry()|. { - TestCompletionCallbackWithOutput<Entries> output_callback( - instance_->pp_instance(), force_async_); - + // 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(); // Note that the directory reader will be deleted immediately. - rv = pp::DirectoryReader_Dev(test_dir).ReadEntries(output_callback); + rv = pp::DirectoryReader_Dev(test_dir).GetNextEntry(&entry, callback); if (force_async_ && rv != PP_OK_COMPLETIONPENDING) - return ReportError("DirectoryReader::ReadEntries force_async", rv); - if (output_callback.run_count() > 0) - return "DirectoryReader::ReadEntries ran callback synchronously."; + return ReportError("DirectoryReader::GetNextEntry force_async", rv); + if (callback.run_count() > 0) + return "DirectoryReader::GetNextEntry ran callback synchronously."; - // If |ReadEntries()| is completing asynchronously, the callback should be + // If |GetNextEntry()| 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) { - rv = output_callback.WaitForResult(); + // |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(); if (rv != PP_ERROR_ABORTED) - return "DirectoryReader::ReadEntries not aborted."; + return "DirectoryReader::GetNextEntry not aborted."; + if (entry.is_null() != entry_is_null) + return "DirectoryReader::GetNextEntry wrote result after destruction."; } else if (rv != PP_OK) { - return ReportError("DirectoryReader::ReadEntries", rv); + return ReportError("DirectoryReader::GetNextEntry", rv); } } diff --git a/ppapi/tests/test_directory_reader.h b/ppapi/tests/test_directory_reader.h index ee446c5..8f68530 100644 --- a/ppapi/tests/test_directory_reader.h +++ b/ppapi/tests/test_directory_reader.h @@ -9,10 +9,6 @@ #include "ppapi/tests/test_case.h" -namespace pp { -class FileRef; -} - class TestDirectoryReader : public TestCase { public: explicit TestDirectoryReader(TestingInstance* instance) @@ -23,9 +19,7 @@ class TestDirectoryReader : public TestCase { virtual void RunTests(const std::string& filter); private: - int32_t DeleteDirectoryRecursively(pp::FileRef*); - - std::string TestReadEntries(); + std::string TestGetNextFile(); }; #endif // PAPPI_TESTS_TEST_DIRECTORY_READER_H_ diff --git a/ppapi/tests/test_file_ref.cc b/ppapi/tests/test_file_ref.cc index 09260120..b1638b7 100644 --- a/ppapi/tests/test_file_ref.cc +++ b/ppapi/tests/test_file_ref.cc @@ -716,23 +716,26 @@ 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.ReadEntries(output_callback); + rv = directory_reader.GetNextEntry(&entry, callback); if (rv == PP_OK_COMPLETIONPENDING) - rv = output_callback.WaitForResult(); + rv = callback.WaitForResult(); if (rv != PP_OK && rv != PP_ERROR_FILENOTFOUND) - return ReportError("DirectoryEntry_Dev::ReadEntries", rv); - - std::vector<pp::DirectoryEntry_Dev> entries = output_callback.output(); - if (entries.empty()) + return ReportError("DirectoryEntry_Dev::GetNextEntry", rv); + if (entry.is_null()) return "Entry was not found."; - if (entries.size() != 1) - return "Directory had too many entries."; - if (entries.front().file_ref().GetName().AsString() != kTerribleName) + if (entry.file_ref().GetName().AsString() != kTerribleName) return "Entry name did not match."; + + 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()) + return "Directory had too many entries."; } PASS(); diff --git a/ppapi/thunk/interfaces_ppb_public_dev.h b/ppapi/thunk/interfaces_ppb_public_dev.h index 708b6ef..f45a138 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_6, - PPB_DirectoryReader_Dev_0_6) +PROXIED_IFACE(NoAPIName, PPB_DIRECTORYREADER_DEV_INTERFACE_0_5, + PPB_DirectoryReader_Dev_0_5) 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 cf71ddf..6a32934 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 ReadEntries(const PP_ArrayOutput& output, - scoped_refptr<TrackedCallback> callback) = 0; + virtual int32_t GetNextEntry(PP_DirectoryEntry_Dev* entry, + 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 aaee6f7..eaa7c2d 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 ReadEntries(PP_Resource directory_reader, - PP_ArrayOutput output, - PP_CompletionCallback callback) { +int32_t GetNextEntry(PP_Resource directory_reader, + PP_DirectoryEntry_Dev* entry, + PP_CompletionCallback callback) { EnterResource<PPB_DirectoryReader_API> enter( directory_reader, callback, true); if (enter.failed()) return enter.retval(); - return enter.SetResult(enter.object()->ReadEntries(output, enter.callback())); + return enter.SetResult(enter.object()->GetNextEntry(entry, enter.callback())); } const PPB_DirectoryReader_Dev g_ppb_directory_reader_thunk = { &Create, &IsDirectoryReader, - &ReadEntries + &GetNextEntry }; } // namespace -const PPB_DirectoryReader_Dev_0_6* GetPPB_DirectoryReader_Dev_0_6_Thunk() { +const PPB_DirectoryReader_Dev_0_5* GetPPB_DirectoryReader_Dev_0_5_Thunk() { return &g_ppb_directory_reader_thunk; } |