summaryrefslogtreecommitdiffstats
path: root/ppapi
diff options
context:
space:
mode:
authorteravest@chromium.org <teravest@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-02 09:10:41 +0000
committerteravest@chromium.org <teravest@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-02 09:10:41 +0000
commitd4edb10981caaa389d94036be4f522925ea3d159 (patch)
treebf80a6ddc3f546c458cfbe07b22b985c98751a8a /ppapi
parent9c01b408cf7799799d1a3acec89685510ef94e51 (diff)
downloadchromium_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.idl21
-rw-r--r--ppapi/c/ppb_file_ref.h46
-rw-r--r--ppapi/cpp/file_ref.cc148
-rw-r--r--ppapi/cpp/file_ref.h14
-rw-r--r--ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c92
-rw-r--r--ppapi/proxy/enter_proxy.h17
-rw-r--r--ppapi/proxy/ppapi_messages.h20
-rw-r--r--ppapi/proxy/ppb_file_ref_proxy.cc90
-rw-r--r--ppapi/proxy/ppb_file_ref_proxy.h25
-rw-r--r--ppapi/tests/test_file_ref.cc115
-rw-r--r--ppapi/tests/test_file_ref.h9
-rw-r--r--ppapi/thunk/interfaces_ppb_public_stable.h1
-rw-r--r--ppapi/thunk/ppb_file_ref_api.h2
-rw-r--r--ppapi/thunk/ppb_file_ref_thunk.cc32
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() {