diff options
author | teravest@chromium.org <teravest@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-02 09:10:41 +0000 |
---|---|---|
committer | teravest@chromium.org <teravest@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-02 09:10:41 +0000 |
commit | d4edb10981caaa389d94036be4f522925ea3d159 (patch) | |
tree | bf80a6ddc3f546c458cfbe07b22b985c98751a8a /ppapi | |
parent | 9c01b408cf7799799d1a3acec89685510ef94e51 (diff) | |
download | chromium_src-d4edb10981caaa389d94036be4f522925ea3d159.zip chromium_src-d4edb10981caaa389d94036be4f522925ea3d159.tar.gz chromium_src-d4edb10981caaa389d94036be4f522925ea3d159.tar.bz2 |
Add Query() support to FileRef.
This change brings Query() support back to FileRef for in-process and out-of-process plugins.
I've added testing for a file that exists and one that doesn't.
BUG=170721
Review URL: https://chromiumcodereview.appspot.com/12817009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@191805 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi')
-rw-r--r-- | ppapi/api/ppb_file_ref.idl | 21 | ||||
-rw-r--r-- | ppapi/c/ppb_file_ref.h | 46 | ||||
-rw-r--r-- | ppapi/cpp/file_ref.cc | 148 | ||||
-rw-r--r-- | ppapi/cpp/file_ref.h | 14 | ||||
-rw-r--r-- | ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c | 92 | ||||
-rw-r--r-- | ppapi/proxy/enter_proxy.h | 17 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_messages.h | 20 | ||||
-rw-r--r-- | ppapi/proxy/ppb_file_ref_proxy.cc | 90 | ||||
-rw-r--r-- | ppapi/proxy/ppb_file_ref_proxy.h | 25 | ||||
-rw-r--r-- | ppapi/tests/test_file_ref.cc | 115 | ||||
-rw-r--r-- | ppapi/tests/test_file_ref.h | 9 | ||||
-rw-r--r-- | ppapi/thunk/interfaces_ppb_public_stable.h | 1 | ||||
-rw-r--r-- | ppapi/thunk/ppb_file_ref_api.h | 2 | ||||
-rw-r--r-- | ppapi/thunk/ppb_file_ref_thunk.cc | 32 |
14 files changed, 532 insertions, 100 deletions
diff --git a/ppapi/api/ppb_file_ref.idl b/ppapi/api/ppb_file_ref.idl index 1265830..cc08f8e 100644 --- a/ppapi/api/ppb_file_ref.idl +++ b/ppapi/api/ppb_file_ref.idl @@ -9,7 +9,8 @@ */ label Chrome { - M14 = 1.0 + M14 = 1.0, + M28 = 1.1 }; /** @@ -166,5 +167,23 @@ interface PPB_FileRef { int32_t Rename([in] PP_Resource file_ref, [in] PP_Resource new_file_ref, [in] PP_CompletionCallback callback); + + /* + * Query() queries info about a file or directory. You must have access to + * read this file or directory if it exists in the external filesystem. + * + * @param[in] file_ref A <code>PP_Resource</code> corresponding to a file + * reference. + * @param[out] info A pointer to a <code>PP_FileInfo</code> which will be + * populated with information about the file or directory. + * @param[in] callback A <code>PP_CompletionCallback</code> to be called upon + * completion of Query(). + * + * @return An int32_t containing an error code from <code>pp_errors.h</code>. + */ + [version=1.1] + int32_t Query([in] PP_Resource file_ref, + [out] PP_FileInfo info, + [in] PP_CompletionCallback callback); }; diff --git a/ppapi/c/ppb_file_ref.h b/ppapi/c/ppb_file_ref.h index d359a7b..910fd80 100644 --- a/ppapi/c/ppb_file_ref.h +++ b/ppapi/c/ppb_file_ref.h @@ -3,7 +3,7 @@ * found in the LICENSE file. */ -/* From ppb_file_ref.idl modified Wed Oct 5 14:06:02 2011. */ +/* From ppb_file_ref.idl modified Thu Mar 7 12:02:53 2013. */ #ifndef PPAPI_C_PPB_FILE_REF_H_ #define PPAPI_C_PPB_FILE_REF_H_ @@ -18,7 +18,8 @@ #include "ppapi/c/pp_var.h" #define PPB_FILEREF_INTERFACE_1_0 "PPB_FileRef;1.0" -#define PPB_FILEREF_INTERFACE PPB_FILEREF_INTERFACE_1_0 +#define PPB_FILEREF_INTERFACE_1_1 "PPB_FileRef;1.1" +#define PPB_FILEREF_INTERFACE PPB_FILEREF_INTERFACE_1_1 /** * @file @@ -36,7 +37,7 @@ * a file system. This struct contains a <code>PP_FileSystemType</code> * identifier and a file path string. */ -struct PPB_FileRef_1_0 { +struct PPB_FileRef_1_1 { /** * Create() creates a weak pointer to a file in the given file system. File * paths are POSIX style. @@ -177,9 +178,46 @@ struct PPB_FileRef_1_0 { int32_t (*Rename)(PP_Resource file_ref, PP_Resource new_file_ref, struct PP_CompletionCallback callback); + /* + * Query() queries info about a file or directory. You must have access to + * read this file or directory if it exists in the external filesystem. + * + * @param[in] file_ref A <code>PP_Resource</code> corresponding to a file + * reference. + * @param[out] info A pointer to a <code>PP_FileInfo</code> which will be + * populated with information about the file or directory. + * @param[in] callback A <code>PP_CompletionCallback</code> to be called upon + * completion of Query(). + * + * @return An int32_t containing an error code from <code>pp_errors.h</code>. + */ + int32_t (*Query)(PP_Resource file_ref, + struct PP_FileInfo* info, + struct PP_CompletionCallback callback); }; -typedef struct PPB_FileRef_1_0 PPB_FileRef; +typedef struct PPB_FileRef_1_1 PPB_FileRef; + +struct PPB_FileRef_1_0 { + PP_Resource (*Create)(PP_Resource file_system, const char* path); + PP_Bool (*IsFileRef)(PP_Resource resource); + PP_FileSystemType (*GetFileSystemType)(PP_Resource file_ref); + struct PP_Var (*GetName)(PP_Resource file_ref); + struct PP_Var (*GetPath)(PP_Resource file_ref); + PP_Resource (*GetParent)(PP_Resource file_ref); + int32_t (*MakeDirectory)(PP_Resource directory_ref, + PP_Bool make_ancestors, + struct PP_CompletionCallback callback); + int32_t (*Touch)(PP_Resource file_ref, + PP_Time last_access_time, + PP_Time last_modified_time, + struct PP_CompletionCallback callback); + int32_t (*Delete)(PP_Resource file_ref, + struct PP_CompletionCallback callback); + int32_t (*Rename)(PP_Resource file_ref, + PP_Resource new_file_ref, + struct PP_CompletionCallback callback); +}; /** * @} */ diff --git a/ppapi/cpp/file_ref.cc b/ppapi/cpp/file_ref.cc index fbfd49b..377fbbb 100644 --- a/ppapi/cpp/file_ref.cc +++ b/ppapi/cpp/file_ref.cc @@ -18,6 +18,10 @@ template <> const char* interface_name<PPB_FileRef_1_0>() { return PPB_FILEREF_INTERFACE_1_0; } +template <> const char* interface_name<PPB_FileRef_1_1>() { + return PPB_FILEREF_INTERFACE_1_1; +} + } // namespace FileRef::FileRef(PP_Resource resource) : Resource(resource) { @@ -28,10 +32,13 @@ FileRef::FileRef(PassRef, PP_Resource resource) : Resource(PASS_REF, resource) { FileRef::FileRef(const FileSystem& file_system, const char* path) { - if (!has_interface<PPB_FileRef_1_0>()) - return; - PassRefFromConstructor(get_interface<PPB_FileRef_1_0>()->Create( - file_system.pp_resource(), path)); + if (has_interface<PPB_FileRef_1_1>()) { + PassRefFromConstructor(get_interface<PPB_FileRef_1_1>()->Create( + file_system.pp_resource(), path)); + } else if (has_interface<PPB_FileRef_1_0>()) { + PassRefFromConstructor(get_interface<PPB_FileRef_1_0>()->Create( + file_system.pp_resource(), path)); + } } FileRef::FileRef(const FileRef& other) @@ -39,74 +46,129 @@ FileRef::FileRef(const FileRef& other) } PP_FileSystemType FileRef::GetFileSystemType() const { - if (!has_interface<PPB_FileRef_1_0>()) - return PP_FILESYSTEMTYPE_EXTERNAL; - return get_interface<PPB_FileRef_1_0>()->GetFileSystemType(pp_resource()); + if (has_interface<PPB_FileRef_1_1>()) + return get_interface<PPB_FileRef_1_1>()->GetFileSystemType(pp_resource()); + if (has_interface<PPB_FileRef_1_0>()) + return get_interface<PPB_FileRef_1_0>()->GetFileSystemType(pp_resource()); + return PP_FILESYSTEMTYPE_EXTERNAL; } Var FileRef::GetName() const { - if (!has_interface<PPB_FileRef_1_0>()) - return Var(); - return Var(PASS_REF, - get_interface<PPB_FileRef_1_0>()->GetName(pp_resource())); + if (has_interface<PPB_FileRef_1_1>()) { + return Var(PASS_REF, + get_interface<PPB_FileRef_1_1>()->GetName(pp_resource())); + } + if (has_interface<PPB_FileRef_1_0>()) { + return Var(PASS_REF, + get_interface<PPB_FileRef_1_0>()->GetName(pp_resource())); + } + return Var(); } Var FileRef::GetPath() const { - if (!has_interface<PPB_FileRef_1_0>()) - return Var(); - return Var(PASS_REF, - get_interface<PPB_FileRef_1_0>()->GetPath(pp_resource())); + if (has_interface<PPB_FileRef_1_1>()) { + return Var(PASS_REF, + get_interface<PPB_FileRef_1_1>()->GetPath(pp_resource())); + } + if (has_interface<PPB_FileRef_1_0>()) { + return Var(PASS_REF, + get_interface<PPB_FileRef_1_0>()->GetPath(pp_resource())); + } + return Var(); } FileRef FileRef::GetParent() const { - if (!has_interface<PPB_FileRef_1_0>()) - return FileRef(); - return FileRef(PASS_REF, - get_interface<PPB_FileRef_1_0>()->GetParent(pp_resource())); + if (has_interface<PPB_FileRef_1_1>()) { + return FileRef(PASS_REF, + get_interface<PPB_FileRef_1_1>()->GetParent(pp_resource())); + } + if (has_interface<PPB_FileRef_1_0>()) { + return FileRef(PASS_REF, + get_interface<PPB_FileRef_1_0>()->GetParent(pp_resource())); + } + return FileRef(); } int32_t FileRef::MakeDirectory(const CompletionCallback& cc) { - if (!has_interface<PPB_FileRef_1_0>()) - return cc.MayForce(PP_ERROR_NOINTERFACE); - return get_interface<PPB_FileRef_1_0>()->MakeDirectory( - pp_resource(), - PP_FALSE, // make_ancestors - cc.pp_completion_callback()); + if (has_interface<PPB_FileRef_1_1>()) { + return get_interface<PPB_FileRef_1_1>()->MakeDirectory( + pp_resource(), + PP_FALSE, // make_ancestors + cc.pp_completion_callback()); + } + if (has_interface<PPB_FileRef_1_0>()) { + return get_interface<PPB_FileRef_1_0>()->MakeDirectory( + pp_resource(), + PP_FALSE, // make_ancestors + cc.pp_completion_callback()); + } + return cc.MayForce(PP_ERROR_NOINTERFACE); } int32_t FileRef::MakeDirectoryIncludingAncestors( const CompletionCallback& cc) { - if (!has_interface<PPB_FileRef_1_0>()) - return cc.MayForce(PP_ERROR_NOINTERFACE); - return get_interface<PPB_FileRef_1_0>()->MakeDirectory( - pp_resource(), - PP_TRUE, // make_ancestors - cc.pp_completion_callback()); + if (has_interface<PPB_FileRef_1_1>()) { + return get_interface<PPB_FileRef_1_1>()->MakeDirectory( + pp_resource(), + PP_TRUE, // make_ancestors + cc.pp_completion_callback()); + } + if (has_interface<PPB_FileRef_1_0>()) { + return get_interface<PPB_FileRef_1_0>()->MakeDirectory( + pp_resource(), + PP_TRUE, // make_ancestors + cc.pp_completion_callback()); + } + return cc.MayForce(PP_ERROR_NOINTERFACE); } int32_t FileRef::Touch(PP_Time last_access_time, PP_Time last_modified_time, const CompletionCallback& cc) { - if (!has_interface<PPB_FileRef_1_0>()) - return cc.MayForce(PP_ERROR_NOINTERFACE); - return get_interface<PPB_FileRef_1_0>()->Touch( - pp_resource(), last_access_time, last_modified_time, - cc.pp_completion_callback()); + if (has_interface<PPB_FileRef_1_1>()) { + return get_interface<PPB_FileRef_1_1>()->Touch( + pp_resource(), last_access_time, last_modified_time, + cc.pp_completion_callback()); + } + if (has_interface<PPB_FileRef_1_0>()) { + return get_interface<PPB_FileRef_1_0>()->Touch( + pp_resource(), last_access_time, last_modified_time, + cc.pp_completion_callback()); + } + return cc.MayForce(PP_ERROR_NOINTERFACE); } int32_t FileRef::Delete(const CompletionCallback& cc) { - if (!has_interface<PPB_FileRef_1_0>()) - return cc.MayForce(PP_ERROR_NOINTERFACE); - return get_interface<PPB_FileRef_1_0>()->Delete( - pp_resource(), cc.pp_completion_callback()); + if (has_interface<PPB_FileRef_1_1>()) { + return get_interface<PPB_FileRef_1_1>()->Delete( + pp_resource(), cc.pp_completion_callback()); + } + if (has_interface<PPB_FileRef_1_0>()) { + return get_interface<PPB_FileRef_1_0>()->Delete( + pp_resource(), cc.pp_completion_callback()); + } + return cc.MayForce(PP_ERROR_NOINTERFACE); } int32_t FileRef::Rename(const FileRef& new_file_ref, const CompletionCallback& cc) { - if (!has_interface<PPB_FileRef_1_0>()) + if (has_interface<PPB_FileRef_1_1>()) { + return get_interface<PPB_FileRef_1_1>()->Rename( + pp_resource(), new_file_ref.pp_resource(), cc.pp_completion_callback()); + } + if (has_interface<PPB_FileRef_1_0>()) { + return get_interface<PPB_FileRef_1_0>()->Rename( + pp_resource(), new_file_ref.pp_resource(), cc.pp_completion_callback()); + } + return cc.MayForce(PP_ERROR_NOINTERFACE); +} + +int32_t FileRef::Query(const CompletionCallbackWithOutput<PP_FileInfo>& cc) { + if (!has_interface<PPB_FileRef_1_1>()) return cc.MayForce(PP_ERROR_NOINTERFACE); - return get_interface<PPB_FileRef_1_0>()->Rename( - pp_resource(), new_file_ref.pp_resource(), cc.pp_completion_callback()); + return get_interface<PPB_FileRef_1_1>()->Query( + pp_resource(), cc.output(), cc.pp_completion_callback()); } + } // namespace pp diff --git a/ppapi/cpp/file_ref.h b/ppapi/cpp/file_ref.h index 05cdc36..49a4b98 100644 --- a/ppapi/cpp/file_ref.h +++ b/ppapi/cpp/file_ref.h @@ -5,6 +5,7 @@ #ifndef PPAPI_CPP_FILE_REF_H_ #define PPAPI_CPP_FILE_REF_H_ +#include "ppapi/c/pp_file_info.h" #include "ppapi/c/pp_stdint.h" #include "ppapi/c/ppb_file_ref.h" #include "ppapi/cpp/resource.h" @@ -16,8 +17,9 @@ namespace pp { -class CompletionCallback; class FileSystem; +class CompletionCallback; +template <typename T> class CompletionCallbackWithOutput; /// The <code>FileRef</code> class represents a "weak pointer" to a file in /// a file system. @@ -143,6 +145,16 @@ class FileRef : public Resource { /// /// @return An int32_t containing an error code from <code>pp_errors.h</code>. int32_t Rename(const FileRef& new_file_ref, const CompletionCallback& cc); + + /// + /// Query() queries info about a file or directory. You must have access to + /// read this file or directory if it exists in the external filesystem. + /// + /// @param[in] callback A <code>CompletionCallbackWithOutput</code> + /// to be called upon completion of Query(). + /// + /// @return An int32_t containing an error code from <code>pp_errors.h</code>. + int32_t Query(const CompletionCallbackWithOutput<PP_FileInfo>& callback); }; } // 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 4f76f47..fce0641 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 @@ -140,6 +140,7 @@ static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Core_1_0; static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_FileIO_1_0; static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_FileIO_1_1; static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_FileRef_1_0; +static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_FileRef_1_1; static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_FileSystem_1_0; static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Fullscreen_1_0; static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Gamepad_1_0; @@ -537,6 +538,76 @@ int32_t Pnacl_M14_PPB_FileRef_Rename(PP_Resource file_ref, PP_Resource new_file_ /* End wrapper methods for PPB_FileRef_1_0 */ +/* Begin wrapper methods for PPB_FileRef_1_1 */ + +static __attribute__((pnaclcall)) +PP_Resource Pnacl_M27_PPB_FileRef_Create(PP_Resource file_system, const char* path) { + const struct PPB_FileRef_1_1 *iface = Pnacl_WrapperInfo_PPB_FileRef_1_1.real_iface; + return iface->Create(file_system, path); +} + +static __attribute__((pnaclcall)) +PP_Bool Pnacl_M27_PPB_FileRef_IsFileRef(PP_Resource resource) { + const struct PPB_FileRef_1_1 *iface = Pnacl_WrapperInfo_PPB_FileRef_1_1.real_iface; + return iface->IsFileRef(resource); +} + +static __attribute__((pnaclcall)) +PP_FileSystemType Pnacl_M27_PPB_FileRef_GetFileSystemType(PP_Resource file_ref) { + const struct PPB_FileRef_1_1 *iface = Pnacl_WrapperInfo_PPB_FileRef_1_1.real_iface; + return iface->GetFileSystemType(file_ref); +} + +static __attribute__((pnaclcall)) +struct PP_Var Pnacl_M27_PPB_FileRef_GetName(PP_Resource file_ref) { + const struct PPB_FileRef_1_1 *iface = Pnacl_WrapperInfo_PPB_FileRef_1_1.real_iface; + return iface->GetName(file_ref); +} + +static __attribute__((pnaclcall)) +struct PP_Var Pnacl_M27_PPB_FileRef_GetPath(PP_Resource file_ref) { + const struct PPB_FileRef_1_1 *iface = Pnacl_WrapperInfo_PPB_FileRef_1_1.real_iface; + return iface->GetPath(file_ref); +} + +static __attribute__((pnaclcall)) +PP_Resource Pnacl_M27_PPB_FileRef_GetParent(PP_Resource file_ref) { + const struct PPB_FileRef_1_1 *iface = Pnacl_WrapperInfo_PPB_FileRef_1_1.real_iface; + return iface->GetParent(file_ref); +} + +static __attribute__((pnaclcall)) +int32_t Pnacl_M27_PPB_FileRef_MakeDirectory(PP_Resource directory_ref, PP_Bool make_ancestors, struct PP_CompletionCallback callback) { + const struct PPB_FileRef_1_1 *iface = Pnacl_WrapperInfo_PPB_FileRef_1_1.real_iface; + return iface->MakeDirectory(directory_ref, make_ancestors, callback); +} + +static __attribute__((pnaclcall)) +int32_t Pnacl_M27_PPB_FileRef_Touch(PP_Resource file_ref, PP_Time last_access_time, PP_Time last_modified_time, struct PP_CompletionCallback callback) { + const struct PPB_FileRef_1_1 *iface = Pnacl_WrapperInfo_PPB_FileRef_1_1.real_iface; + return iface->Touch(file_ref, last_access_time, last_modified_time, callback); +} + +static __attribute__((pnaclcall)) +int32_t Pnacl_M27_PPB_FileRef_Delete(PP_Resource file_ref, struct PP_CompletionCallback callback) { + const struct PPB_FileRef_1_1 *iface = Pnacl_WrapperInfo_PPB_FileRef_1_1.real_iface; + return iface->Delete(file_ref, callback); +} + +static __attribute__((pnaclcall)) +int32_t Pnacl_M27_PPB_FileRef_Rename(PP_Resource file_ref, PP_Resource new_file_ref, struct PP_CompletionCallback callback) { + const struct PPB_FileRef_1_1 *iface = Pnacl_WrapperInfo_PPB_FileRef_1_1.real_iface; + return iface->Rename(file_ref, new_file_ref, callback); +} + +static __attribute__((pnaclcall)) +int32_t Pnacl_M27_PPB_FileRef_Query(PP_Resource file_ref, struct PP_FileInfo* info, struct PP_CompletionCallback callback) { + const struct PPB_FileRef_1_1 *iface = Pnacl_WrapperInfo_PPB_FileRef_1_1.real_iface; + return iface->Query(file_ref, info, callback); +} + +/* End wrapper methods for PPB_FileRef_1_1 */ + /* Begin wrapper methods for PPB_FileSystem_1_0 */ static __attribute__((pnaclcall)) @@ -3863,6 +3934,20 @@ struct PPB_FileRef_1_0 Pnacl_Wrappers_PPB_FileRef_1_0 = { .Rename = (int32_t (*)(PP_Resource file_ref, PP_Resource new_file_ref, struct PP_CompletionCallback callback))&Pnacl_M14_PPB_FileRef_Rename }; +struct PPB_FileRef_1_1 Pnacl_Wrappers_PPB_FileRef_1_1 = { + .Create = (PP_Resource (*)(PP_Resource file_system, const char* path))&Pnacl_M27_PPB_FileRef_Create, + .IsFileRef = (PP_Bool (*)(PP_Resource resource))&Pnacl_M27_PPB_FileRef_IsFileRef, + .GetFileSystemType = (PP_FileSystemType (*)(PP_Resource file_ref))&Pnacl_M27_PPB_FileRef_GetFileSystemType, + .GetName = (struct PP_Var (*)(PP_Resource file_ref))&Pnacl_M27_PPB_FileRef_GetName, + .GetPath = (struct PP_Var (*)(PP_Resource file_ref))&Pnacl_M27_PPB_FileRef_GetPath, + .GetParent = (PP_Resource (*)(PP_Resource file_ref))&Pnacl_M27_PPB_FileRef_GetParent, + .MakeDirectory = (int32_t (*)(PP_Resource directory_ref, PP_Bool make_ancestors, struct PP_CompletionCallback callback))&Pnacl_M27_PPB_FileRef_MakeDirectory, + .Touch = (int32_t (*)(PP_Resource file_ref, PP_Time last_access_time, PP_Time last_modified_time, struct PP_CompletionCallback callback))&Pnacl_M27_PPB_FileRef_Touch, + .Delete = (int32_t (*)(PP_Resource file_ref, struct PP_CompletionCallback callback))&Pnacl_M27_PPB_FileRef_Delete, + .Rename = (int32_t (*)(PP_Resource file_ref, PP_Resource new_file_ref, struct PP_CompletionCallback callback))&Pnacl_M27_PPB_FileRef_Rename, + .Query = (int32_t (*)(PP_Resource file_ref, struct PP_FileInfo* info, struct PP_CompletionCallback callback))&Pnacl_M27_PPB_FileRef_Query +}; + struct PPB_FileSystem_1_0 Pnacl_Wrappers_PPB_FileSystem_1_0 = { .Create = (PP_Resource (*)(PP_Instance instance, PP_FileSystemType type))&Pnacl_M14_PPB_FileSystem_Create, .IsFileSystem = (PP_Bool (*)(PP_Resource resource))&Pnacl_M14_PPB_FileSystem_IsFileSystem, @@ -4733,6 +4818,12 @@ static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_FileRef_1_0 = { .real_iface = NULL }; +static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_FileRef_1_1 = { + .iface_macro = PPB_FILEREF_INTERFACE_1_1, + .wrapped_iface = (void *) &Pnacl_Wrappers_PPB_FileRef_1_1, + .real_iface = NULL +}; + static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_FileSystem_1_0 = { .iface_macro = PPB_FILESYSTEM_INTERFACE_1_0, .wrapped_iface = (void *) &Pnacl_Wrappers_PPB_FileSystem_1_0, @@ -5552,6 +5643,7 @@ static struct __PnaclWrapperInfo *s_ppb_wrappers[] = { &Pnacl_WrapperInfo_PPB_FileIO_1_0, &Pnacl_WrapperInfo_PPB_FileIO_1_1, &Pnacl_WrapperInfo_PPB_FileRef_1_0, + &Pnacl_WrapperInfo_PPB_FileRef_1_1, &Pnacl_WrapperInfo_PPB_FileSystem_1_0, &Pnacl_WrapperInfo_PPB_Fullscreen_1_0, &Pnacl_WrapperInfo_PPB_Gamepad_1_0, diff --git a/ppapi/proxy/enter_proxy.h b/ppapi/proxy/enter_proxy.h index 3832a13..4ad67b1 100644 --- a/ppapi/proxy/enter_proxy.h +++ b/ppapi/proxy/enter_proxy.h @@ -151,6 +151,23 @@ class EnterHostFromHostResourceForceCallback RunCallback(PP_ERROR_BADRESOURCE); } + // For callbacks that take three extra parameters as a closure. + template<class CallbackFactory, typename Method, typename A, typename B, + typename C> + EnterHostFromHostResourceForceCallback( + const HostResource& host_resource, + CallbackFactory& factory, + Method method, + const A& a, + const B& b, + const C& c) + : EnterHostFromHostResource<ResourceT>(host_resource, + factory.NewOptionalCallback(method, a, b, c)), + needs_running_(true) { + if (this->failed()) + RunCallback(PP_ERROR_BADRESOURCE); + } + ~EnterHostFromHostResourceForceCallback() { if (needs_running_) { NOTREACHED() << "Should always call SetResult except in the " diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index eb87994..60018a6 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h @@ -450,7 +450,14 @@ IPC_MESSAGE_ROUTED4(PpapiMsg_PPBAudio_NotifyAudioStreamCreated, IPC_MESSAGE_ROUTED3( PpapiMsg_PPBFileRef_CallbackComplete, ppapi::HostResource /* resource */, - int /* callback_id */, + uint32_t /* callback_id */, + int32_t /* result */) + +IPC_MESSAGE_ROUTED4( + PpapiMsg_PPBFileRef_QueryCallbackComplete, + ppapi::HostResource /* resource */, + PP_FileInfo /* file_info */, + uint32_t /* callback_id */, int32_t /* result */) // PPB_FileSystem. @@ -793,19 +800,22 @@ IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFileRef_GetParent, IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBFileRef_MakeDirectory, ppapi::HostResource /* file_ref */, PP_Bool /* make_ancestors */, - int /* callback_id */) + uint32_t /* callback_id */) IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBFileRef_Touch, ppapi::HostResource /* file_ref */, PP_Time /* last_access */, PP_Time /* last_modified */, - int /* callback_id */) + uint32_t /* callback_id */) IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBFileRef_Delete, ppapi::HostResource /* file_ref */, - int /* callback_id */) + uint32_t /* callback_id */) IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBFileRef_Rename, ppapi::HostResource /* file_ref */, ppapi::HostResource /* new_file_ref */, - int /* callback_id */) + uint32_t /* callback_id */) +IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBFileRef_Query, + ppapi::HostResource /* file_ref */, + uint32_t /* callback_id */) IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFileRef_GetAbsolutePath, ppapi::HostResource /* file_ref */, ppapi::proxy::SerializedVar /* result */) diff --git a/ppapi/proxy/ppb_file_ref_proxy.cc b/ppapi/proxy/ppb_file_ref_proxy.cc index 49dac58..c63cccd 100644 --- a/ppapi/proxy/ppb_file_ref_proxy.cc +++ b/ppapi/proxy/ppb_file_ref_proxy.cc @@ -47,10 +47,13 @@ class FileRef : public PPB_FileRef_Shared { virtual int32_t Delete(scoped_refptr<TrackedCallback> callback) OVERRIDE; virtual int32_t Rename(PP_Resource new_file_ref, scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual int32_t Query(PP_FileInfo* info, + scoped_refptr<TrackedCallback> callback) OVERRIDE; virtual PP_Var GetAbsolutePath() OVERRIDE; // Executes the pending callback with the given ID. See pending_callbacks_. - void ExecuteCallback(int callback_id, int32_t result); + void ExecuteCallback(uint32_t callback_id, int32_t result); + void SetFileInfo(uint32_t callback_id, const PP_FileInfo& info); private: PluginDispatcher* GetDispatcher() const { @@ -58,7 +61,7 @@ class FileRef : public PPB_FileRef_Shared { } // Adds a callback to the list and returns its ID. - int SendCallback(scoped_refptr<TrackedCallback> callback); + uint32_t SendCallback(scoped_refptr<TrackedCallback> callback); // This class can have any number of out-standing requests with completion // callbacks, in contrast to most resources which have one possible pending @@ -67,11 +70,17 @@ class FileRef : public PPB_FileRef_Shared { // To keep track of them, assign integer IDs to the callbacks, which is how // the callback will be identified when it's passed to the host and then // back here. Use unsigned so that overflow is well-defined. - unsigned int next_callback_id_; - typedef std::map<unsigned int, + uint32_t next_callback_id_; + typedef std::map<uint32_t, scoped_refptr<TrackedCallback> > PendingCallbackMap; PendingCallbackMap pending_callbacks_; + // Used to keep pointers to PP_FileInfo instances that are written before + // callbacks are invoked. The id of a pending file info will match that of + // the corresponding callback. + typedef std::map<uint32_t, PP_FileInfo*> PendingFileInfoMap; + PendingFileInfoMap pending_file_infos_; + DISALLOW_IMPLICIT_CONSTRUCTORS(FileRef); }; @@ -83,11 +92,13 @@ FileRef::FileRef(const PPB_FileRef_CreateInfo& info) FileRef::~FileRef() { // The callbacks map should have been cleared by LastPluginRefWasDeleted. DCHECK(pending_callbacks_.empty()); + DCHECK(pending_file_infos_.empty()); } void FileRef::LastPluginRefWasDeleted() { // The callback tracker will abort our callbacks for us. pending_callbacks_.clear(); + pending_file_infos_.clear(); } PP_Resource FileRef::GetParent() { @@ -134,6 +145,16 @@ int32_t FileRef::Rename(PP_Resource new_file_ref, return PP_OK_COMPLETIONPENDING; } +int32_t FileRef::Query(PP_FileInfo* info, + scoped_refptr<TrackedCallback> callback) { + // Store the pending file info id. + int id = SendCallback(callback); + pending_file_infos_[id] = info; + GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Query( + API_ID_PPB_FILE_REF, host_resource(), id)); + return PP_OK_COMPLETIONPENDING; +} + PP_Var FileRef::GetAbsolutePath() { ReceiveSerializedVarReturnValue result; GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_GetAbsolutePath( @@ -141,7 +162,7 @@ PP_Var FileRef::GetAbsolutePath() { return result.Return(GetDispatcher()); } -void FileRef::ExecuteCallback(int callback_id, int32_t result) { +void FileRef::ExecuteCallback(uint32_t callback_id, int32_t result) { PendingCallbackMap::iterator found = pending_callbacks_.find(callback_id); if (found == pending_callbacks_.end()) { // This will happen when the plugin deletes its resource with a pending @@ -156,7 +177,16 @@ void FileRef::ExecuteCallback(int callback_id, int32_t result) { callback->Run(result); } -int FileRef::SendCallback(scoped_refptr<TrackedCallback> callback) { +void FileRef::SetFileInfo(uint32_t callback_id, const PP_FileInfo& info) { + PendingFileInfoMap::iterator found = pending_file_infos_.find(callback_id); + if (found == pending_file_infos_.end()) + return; + PP_FileInfo* target_info = found->second; + *target_info = info; + pending_file_infos_.erase(found); +} + +uint32_t FileRef::SendCallback(scoped_refptr<TrackedCallback> callback) { // In extreme cases the IDs may wrap around, so avoid duplicates. while (pending_callbacks_.count(next_callback_id_)) ++next_callback_id_; @@ -200,12 +230,15 @@ bool PPB_FileRef_Proxy::OnMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Touch, OnMsgTouch) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Delete, OnMsgDelete) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Rename, OnMsgRename) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Query, OnMsgQuery) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_GetAbsolutePath, OnMsgGetAbsolutePath) #endif // !defined(OS_NACL) IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileRef_CallbackComplete, OnMsgCallbackComplete) + IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileRef_QueryCallbackComplete, + OnMsgQueryCallbackComplete) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -250,7 +283,7 @@ void PPB_FileRef_Proxy::OnMsgGetParent(const HostResource& host_resource, void PPB_FileRef_Proxy::OnMsgMakeDirectory(const HostResource& host_resource, PP_Bool make_ancestors, - int callback_id) { + uint32_t callback_id) { EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter( host_resource, callback_factory_, &PPB_FileRef_Proxy::OnCallbackCompleteInHost, host_resource, callback_id); @@ -263,7 +296,7 @@ void PPB_FileRef_Proxy::OnMsgMakeDirectory(const HostResource& host_resource, void PPB_FileRef_Proxy::OnMsgTouch(const HostResource& host_resource, PP_Time last_access, PP_Time last_modified, - int callback_id) { + uint32_t callback_id) { EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter( host_resource, callback_factory_, &PPB_FileRef_Proxy::OnCallbackCompleteInHost, host_resource, callback_id); @@ -274,7 +307,7 @@ void PPB_FileRef_Proxy::OnMsgTouch(const HostResource& host_resource, } void PPB_FileRef_Proxy::OnMsgDelete(const HostResource& host_resource, - int callback_id) { + uint32_t callback_id) { EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter( host_resource, callback_factory_, &PPB_FileRef_Proxy::OnCallbackCompleteInHost, host_resource, callback_id); @@ -284,7 +317,7 @@ void PPB_FileRef_Proxy::OnMsgDelete(const HostResource& host_resource, void PPB_FileRef_Proxy::OnMsgRename(const HostResource& file_ref, const HostResource& new_file_ref, - int callback_id) { + uint32_t callback_id) { EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter( file_ref, callback_factory_, &PPB_FileRef_Proxy::OnCallbackCompleteInHost, file_ref, callback_id); @@ -294,6 +327,17 @@ void PPB_FileRef_Proxy::OnMsgRename(const HostResource& file_ref, } } +void PPB_FileRef_Proxy::OnMsgQuery(const HostResource& file_ref, + uint32_t callback_id) { + PP_FileInfo* info = new PP_FileInfo(); + EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter( + file_ref, callback_factory_, + &PPB_FileRef_Proxy::OnQueryCallbackCompleteInHost, file_ref, + base::Owned(info), callback_id); + if (enter.succeeded()) + enter.SetResult(enter.object()->Query(info, enter.callback())); +} + void PPB_FileRef_Proxy::OnMsgGetAbsolutePath(const HostResource& host_resource, SerializedVarReturnValue result) { EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource); @@ -304,7 +348,7 @@ void PPB_FileRef_Proxy::OnMsgGetAbsolutePath(const HostResource& host_resource, void PPB_FileRef_Proxy::OnMsgCallbackComplete( const HostResource& host_resource, - int callback_id, + uint32_t callback_id, int32_t result) { // Forward the callback info to the plugin resource. EnterPluginFromHostResource<PPB_FileRef_API> enter(host_resource); @@ -312,15 +356,37 @@ void PPB_FileRef_Proxy::OnMsgCallbackComplete( static_cast<FileRef*>(enter.object())->ExecuteCallback(callback_id, result); } +void PPB_FileRef_Proxy::OnMsgQueryCallbackComplete( + const HostResource& host_resource, + const PP_FileInfo& info, + uint32_t callback_id, + int32_t result) { + EnterPluginFromHostResource<PPB_FileRef_API> enter(host_resource); + if (enter.succeeded()) { + // Set the FileInfo output parameter. + static_cast<FileRef*>(enter.object())->SetFileInfo(callback_id, info); + static_cast<FileRef*>(enter.object())->ExecuteCallback(callback_id, result); + } +} + #if !defined(OS_NACL) void PPB_FileRef_Proxy::OnCallbackCompleteInHost( int32_t result, const HostResource& host_resource, - int callback_id) { + uint32_t callback_id) { // Execute OnMsgCallbackComplete in the plugin process. Send(new PpapiMsg_PPBFileRef_CallbackComplete( API_ID_PPB_FILE_REF, host_resource, callback_id, result)); } + +void PPB_FileRef_Proxy::OnQueryCallbackCompleteInHost( + int32_t result, + const HostResource& host_resource, + base::internal::OwnedWrapper<PP_FileInfo> info, + uint32_t callback_id) { + Send(new PpapiMsg_PPBFileRef_QueryCallbackComplete( + API_ID_PPB_FILE_REF, host_resource, *info.get(), callback_id, result)); +} #endif // !defined(OS_NACL) } // namespace proxy diff --git a/ppapi/proxy/ppb_file_ref_proxy.h b/ppapi/proxy/ppb_file_ref_proxy.h index e4a412e..37caa1e 100644 --- a/ppapi/proxy/ppb_file_ref_proxy.h +++ b/ppapi/proxy/ppb_file_ref_proxy.h @@ -8,6 +8,8 @@ #include <string> #include "base/basictypes.h" +#include "base/bind_helpers.h" +#include "ppapi/c/pp_file_info.h" #include "ppapi/c/pp_module.h" #include "ppapi/c/pp_resource.h" #include "ppapi/c/pp_time.h" @@ -69,27 +71,38 @@ class PPAPI_PROXY_EXPORT PPB_FileRef_Proxy PPB_FileRef_CreateInfo* result); void OnMsgMakeDirectory(const HostResource& host_resource, PP_Bool make_ancestors, - int callback_id); + uint32_t callback_id); void OnMsgTouch(const HostResource& host_resource, PP_Time last_access, PP_Time last_modified, - int callback_id); + uint32_t callback_id); void OnMsgDelete(const HostResource& host_resource, - int callback_id); + uint32_t callback_id); void OnMsgRename(const HostResource& file_ref, const HostResource& new_file_ref, - int callback_id); + uint32_t callback_id); + void OnMsgQuery(const HostResource& file_ref, + uint32_t callback_id); void OnMsgGetAbsolutePath(const HostResource& host_resource, SerializedVarReturnValue result); // Host -> Plugin message handlers. void OnMsgCallbackComplete(const HostResource& host_resource, - int callback_id, + uint32_t callback_id, int32_t result); + void OnMsgQueryCallbackComplete(const HostResource& host_resource, + const PP_FileInfo& info, + uint32_t callback_id, + int32_t result); void OnCallbackCompleteInHost(int32_t result, const HostResource& host_resource, - int callback_id); + uint32_t callback_id); + void OnQueryCallbackCompleteInHost( + int32_t result, + const HostResource& host_resource, + base::internal::OwnedWrapper<PP_FileInfo> info, + uint32_t callback_id); ProxyCompletionCallbackFactory<PPB_FileRef_Proxy> callback_factory_; diff --git a/ppapi/tests/test_file_ref.cc b/ppapi/tests/test_file_ref.cc index e8e85bc..bb9c6ff 100644 --- a/ppapi/tests/test_file_ref.cc +++ b/ppapi/tests/test_file_ref.cc @@ -49,6 +49,27 @@ bool TestFileRef::Init() { return CheckTestingInterface() && EnsureRunningOverHTTP(); } +std::string TestFileRef::MakeExternalFileRef(pp::FileRef* file_ref_ext) { + pp::URLRequestInfo request(instance_); + request.SetURL("test_url_loader_data/hello.txt"); + request.SetStreamToFile(true); + + TestCompletionCallback callback(instance_->pp_instance(), callback_type()); + + pp::URLLoader loader(instance_); + callback.WaitForResult(loader.Open(request, callback.GetCallback())); + CHECK_CALLBACK_BEHAVIOR(callback); + ASSERT_EQ(PP_OK, callback.result()); + + pp::URLResponseInfo response_info(loader.GetResponseInfo()); + ASSERT_FALSE(response_info.is_null()) + ASSERT_EQ(200, response_info.GetStatusCode()); + + *file_ref_ext = pp::FileRef(response_info.GetBodyAsFileRef()); + ASSERT_EQ(PP_FILESYSTEMTYPE_EXTERNAL, file_ref_ext->GetFileSystemType()) + PASS(); +} + void TestFileRef::RunTests(const std::string& filter) { RUN_TEST_FORCEASYNC_AND_NOT(Create, filter); RUN_TEST_FORCEASYNC_AND_NOT(GetFileSystemType, filter); @@ -59,6 +80,7 @@ void TestFileRef::RunTests(const std::string& filter) { RUN_TEST_FORCEASYNC_AND_NOT(QueryAndTouchFile, filter); RUN_TEST_FORCEASYNC_AND_NOT(DeleteFileAndDirectory, filter); RUN_TEST_FORCEASYNC_AND_NOT(RenameFileAndDirectory, filter); + RUN_CALLBACK_TEST(TestFileRef, Query, filter); #ifndef PPAPI_OS_NACL // NaCl can't run this test yet. RUN_TEST_FORCEASYNC_AND_NOT(FileNameEscaping, filter); #endif @@ -108,32 +130,10 @@ std::string TestFileRef::TestGetFileSystemType() { if (file_ref_temp.GetFileSystemType() != PP_FILESYSTEMTYPE_LOCALTEMPORARY) return "file_ref_temp expected to be temporary."; - pp::URLRequestInfo request(instance_); - request.SetURL("test_url_loader_data/hello.txt"); - request.SetStreamToFile(true); - - TestCompletionCallback callback(instance_->pp_instance(), force_async_); - - pp::URLLoader loader(instance_); - int32_t rv = loader.Open(request, callback.GetCallback()); - if (force_async_ && rv != PP_OK_COMPLETIONPENDING) - return ReportError("URLLoader::Open force_async", rv); - if (rv == PP_OK_COMPLETIONPENDING) - rv = callback.WaitForResult(); - if (rv != PP_OK) - return "URLLoader::Open() failed."; - - pp::URLResponseInfo response_info(loader.GetResponseInfo()); - if (response_info.is_null()) - return "URLLoader::GetResponseInfo returned null"; - int32_t status_code = response_info.GetStatusCode(); - if (status_code != 200) - return "Unexpected HTTP status code"; - - pp::FileRef file_ref_ext(response_info.GetBodyAsFileRef()); - if (file_ref_ext.GetFileSystemType() != PP_FILESYSTEMTYPE_EXTERNAL) - return "file_ref_ext expected to be external."; - + pp::FileRef file_ref_ext; + std::string result = MakeExternalFileRef(&file_ref_ext); + if (!result.empty()) + return result; PASS(); } @@ -682,6 +682,69 @@ std::string TestFileRef::TestRenameFileAndDirectory() { PASS(); } +std::string TestFileRef::TestQuery() { + TestCompletionCallback callback(instance_->pp_instance(), callback_type()); + + pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY); + callback.WaitForResult(file_system.Open(1024, callback.GetCallback())); + CHECK_CALLBACK_BEHAVIOR(callback); + ASSERT_EQ(PP_OK, callback.result()); + + pp::FileRef file_ref(file_system, "/file"); + pp::FileIO file_io(instance_); + callback.WaitForResult(file_io.Open(file_ref, PP_FILEOPENFLAG_CREATE, + callback.GetCallback())); + CHECK_CALLBACK_BEHAVIOR(callback); + ASSERT_EQ(PP_OK, callback.result()); + + // We touch the file so we can easily check access and modified time. + callback.WaitForResult(file_io.Touch(0, 0, callback.GetCallback())); + CHECK_CALLBACK_BEHAVIOR(callback); + ASSERT_EQ(PP_OK, callback.result()); + + TestCompletionCallbackWithOutput<PP_FileInfo> out_callback( + instance_->pp_instance(), callback_type()); + out_callback.WaitForResult(file_ref.Query(out_callback.GetCallback())); + CHECK_CALLBACK_BEHAVIOR(out_callback); + ASSERT_EQ(PP_OK, out_callback.result()); + + PP_FileInfo info = out_callback.output(); + ASSERT_EQ(0, info.size); + ASSERT_EQ(PP_FILETYPE_REGULAR, info.type); + ASSERT_EQ(PP_FILESYSTEMTYPE_LOCALTEMPORARY, info.system_type); + ASSERT_DOUBLE_EQ(0.0, info.last_access_time); + ASSERT_DOUBLE_EQ(0.0, info.last_modified_time); + + // Query a file ref on an external filesystem. + pp::FileRef file_ref_ext; + std::string result = MakeExternalFileRef(&file_ref_ext); + if (!result.empty()) + return result; + out_callback.WaitForResult(file_ref_ext.Query(out_callback.GetCallback())); + CHECK_CALLBACK_BEHAVIOR(out_callback); + if (out_callback.result() != PP_OK) + return ReportError("Query() result", out_callback.result()); + ASSERT_EQ(PP_OK, out_callback.result()); + + info = out_callback.output(); + ASSERT_EQ(PP_FILETYPE_REGULAR, info.type); + ASSERT_EQ(PP_FILESYSTEMTYPE_EXTERNAL, info.system_type); + + // We can't touch the file, so just sanity check the times. + ASSERT_TRUE(info.creation_time >= 0.0); + ASSERT_TRUE(info.last_modified_time >= 0.0); + ASSERT_TRUE(info.last_access_time >= 0.0); + + // Query a file ref for a file that doesn't exist. + pp::FileRef missing_file_ref(file_system, "/missing_file"); + out_callback.WaitForResult(missing_file_ref.Query( + out_callback.GetCallback())); + CHECK_CALLBACK_BEHAVIOR(out_callback); + ASSERT_EQ(PP_ERROR_FILENOTFOUND, out_callback.result()); + + PASS(); +} + #ifndef PPAPI_OS_NACL std::string TestFileRef::TestFileNameEscaping() { TestCompletionCallback callback(instance_->pp_instance(), force_async_); diff --git a/ppapi/tests/test_file_ref.h b/ppapi/tests/test_file_ref.h index 916ea35..97feaf1 100644 --- a/ppapi/tests/test_file_ref.h +++ b/ppapi/tests/test_file_ref.h @@ -9,6 +9,10 @@ #include "ppapi/tests/test_case.h" +namespace pp { +class FileRef; +} + class TestFileRef : public TestCase { public: explicit TestFileRef(TestingInstance* instance) : TestCase(instance) {} @@ -18,6 +22,10 @@ class TestFileRef : public TestCase { virtual void RunTests(const std::string& filter); private: + // Creates a FileRef on an external filesystem. + // Returns "" on success, a different string otherwise. + std::string MakeExternalFileRef(pp::FileRef* file_ref_ext); + std::string TestCreate(); std::string TestGetFileSystemType(); std::string TestGetName(); @@ -27,6 +35,7 @@ class TestFileRef : public TestCase { std::string TestQueryAndTouchFile(); std::string TestDeleteFileAndDirectory(); std::string TestRenameFileAndDirectory(); + std::string TestQuery(); std::string TestFileNameEscaping(); }; diff --git a/ppapi/thunk/interfaces_ppb_public_stable.h b/ppapi/thunk/interfaces_ppb_public_stable.h index 3bf9479..588896f 100644 --- a/ppapi/thunk/interfaces_ppb_public_stable.h +++ b/ppapi/thunk/interfaces_ppb_public_stable.h @@ -48,6 +48,7 @@ UNPROXIED_API(PPB_AudioConfig) // Note: Core is special and is registered manually. PROXIED_IFACE(PPB_Audio, PPB_AUDIO_INTERFACE_1_0, PPB_Audio_1_0) PROXIED_IFACE(PPB_FileRef, PPB_FILEREF_INTERFACE_1_0, PPB_FileRef_1_0) +PROXIED_IFACE(PPB_FileRef, PPB_FILEREF_INTERFACE_1_1, PPB_FileRef_1_1) PROXIED_IFACE(PPB_FileSystem, PPB_FILESYSTEM_INTERFACE_1_0, PPB_FileSystem_1_0) PROXIED_IFACE(PPB_Graphics3D, PPB_GRAPHICS_3D_INTERFACE_1_0, PPB_Graphics3D_1_0) PROXIED_IFACE(PPB_ImageData, PPB_IMAGEDATA_INTERFACE_1_0, PPB_ImageData_1_0) diff --git a/ppapi/thunk/ppb_file_ref_api.h b/ppapi/thunk/ppb_file_ref_api.h index 0f9bbaa..4ec5314 100644 --- a/ppapi/thunk/ppb_file_ref_api.h +++ b/ppapi/thunk/ppb_file_ref_api.h @@ -32,6 +32,8 @@ class PPAPI_THUNK_EXPORT PPB_FileRef_API { virtual int32_t Delete(scoped_refptr<TrackedCallback> callback) = 0; virtual int32_t Rename(PP_Resource new_file_ref, scoped_refptr<TrackedCallback> callback) = 0; + virtual int32_t Query(PP_FileInfo* info, + scoped_refptr<TrackedCallback> callback) = 0; // Internal function for use in proxying. Returns the internal CreateInfo // (the contained resource does not carry a ref on behalf of the caller). diff --git a/ppapi/thunk/ppb_file_ref_thunk.cc b/ppapi/thunk/ppb_file_ref_thunk.cc index 74db508..4e61cd6 100644 --- a/ppapi/thunk/ppb_file_ref_thunk.cc +++ b/ppapi/thunk/ppb_file_ref_thunk.cc @@ -105,6 +105,16 @@ int32_t Rename(PP_Resource file_ref, enter.callback())); } +int32_t Query(PP_Resource file_ref, + PP_FileInfo* info, + PP_CompletionCallback callback) { + EnterFileRef enter(file_ref, callback, true); + if (enter.failed()) + return enter.retval(); + return enter.SetResult(enter.object()->Query(info, + enter.callback())); +} + PP_Var GetAbsolutePath(PP_Resource file_ref) { EnterFileRef enter(file_ref, true); if (enter.failed()) @@ -112,7 +122,7 @@ PP_Var GetAbsolutePath(PP_Resource file_ref) { return enter.object()->GetAbsolutePath(); } -const PPB_FileRef g_ppb_file_ref_thunk = { +const PPB_FileRef_1_0 g_ppb_file_ref_thunk_1_0 = { &Create, &IsFileRef, &GetFileSystemType, @@ -125,6 +135,20 @@ const PPB_FileRef g_ppb_file_ref_thunk = { &Rename }; +const PPB_FileRef_1_1 g_ppb_file_ref_thunk_1_1 = { + &Create, + &IsFileRef, + &GetFileSystemType, + &GetName, + &GetPath, + &GetParent, + &MakeDirectory, + &Touch, + &Delete, + &Rename, + &Query +}; + const PPB_FileRefPrivate g_ppb_file_ref_private_thunk = { &GetAbsolutePath }; @@ -132,7 +156,11 @@ const PPB_FileRefPrivate g_ppb_file_ref_private_thunk = { } // namespace const PPB_FileRef_1_0* GetPPB_FileRef_1_0_Thunk() { - return &g_ppb_file_ref_thunk; + return &g_ppb_file_ref_thunk_1_0; +} + +const PPB_FileRef_1_1* GetPPB_FileRef_1_1_Thunk() { + return &g_ppb_file_ref_thunk_1_1; } const PPB_FileRefPrivate_0_1* GetPPB_FileRefPrivate_0_1_Thunk() { |