summaryrefslogtreecommitdiffstats
path: root/ppapi
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-26 22:21:59 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-26 22:21:59 +0000
commit11f515acdda3473200ff0cc4106a0020a7d4dc74 (patch)
treecdfd9713928d6f0fa73b5cd7bedbd965fc93e329 /ppapi
parentf60d96e82acd547ac834b93cd68865b66ab5b4da (diff)
downloadchromium_src-11f515acdda3473200ff0cc4106a0020a7d4dc74.zip
chromium_src-11f515acdda3473200ff0cc4106a0020a7d4dc74.tar.gz
chromium_src-11f515acdda3473200ff0cc4106a0020a7d4dc74.tar.bz2
New file chooser interface that uses the new PP_ArrayOutput feature. This also changes PP_ArrayOutput to be pass-by-value.
This keeps backwards compat for the old interface. It fixes some bugs in the callback system that I found when working on the patch and adds some new machinery for doing array output in the proxy. It also re-enables the file chooser feature which was recently broken. BUG=118857 Review URL: https://chromiumcodereview.appspot.com/9728001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@129022 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi')
-rw-r--r--ppapi/api/dev/ppb_file_chooser_dev.idl30
-rw-r--r--ppapi/api/pp_array_output.idl1
-rw-r--r--ppapi/api/trusted/ppb_file_chooser_trusted.idl30
-rw-r--r--ppapi/c/dev/ppb_file_chooser_dev.h39
-rw-r--r--ppapi/c/trusted/ppb_file_chooser_trusted.h18
-rw-r--r--ppapi/cpp/array_output.h6
-rw-r--r--ppapi/cpp/completion_callback.h6
-rw-r--r--ppapi/cpp/dev/file_chooser_dev.cc82
-rw-r--r--ppapi/cpp/dev/file_chooser_dev.h54
-rw-r--r--ppapi/cpp/output_traits.h6
-rw-r--r--ppapi/cpp/trusted/file_chooser_trusted.cc39
-rw-r--r--ppapi/cpp/trusted/file_chooser_trusted.h3
-rw-r--r--ppapi/examples/file_chooser/file_chooser.cc15
-rw-r--r--ppapi/ppapi_proxy.gypi11
-rw-r--r--ppapi/ppapi_shared.gypi2
-rw-r--r--ppapi/proxy/DEPS5
-rw-r--r--ppapi/proxy/enter_proxy.h46
-rw-r--r--ppapi/proxy/ppapi_messages.h4
-rw-r--r--ppapi/proxy/ppb_file_chooser_proxy.cc120
-rw-r--r--ppapi/proxy/ppb_file_chooser_proxy.h12
-rw-r--r--ppapi/proxy/ppb_instance_proxy.cc6
-rw-r--r--ppapi/proxy/proxy_array_output.cc21
-rw-r--r--ppapi/proxy/proxy_array_output.h138
-rw-r--r--ppapi/shared_impl/array_writer.cc79
-rw-r--r--ppapi/shared_impl/array_writer.h98
-rw-r--r--ppapi/thunk/interfaces_ppb_public_dev.h2
-rw-r--r--ppapi/thunk/ppb_file_chooser_api.h19
-rw-r--r--ppapi/thunk/ppb_file_chooser_thunk.cc77
28 files changed, 797 insertions, 172 deletions
diff --git a/ppapi/api/dev/ppb_file_chooser_dev.idl b/ppapi/api/dev/ppb_file_chooser_dev.idl
index 980df57..425154b 100644
--- a/ppapi/api/dev/ppb_file_chooser_dev.idl
+++ b/ppapi/api/dev/ppb_file_chooser_dev.idl
@@ -9,7 +9,8 @@
*/
label Chrome {
- M16 = 0.5
+ M16 = 0.5,
+ M19 = 0.6
};
/**
@@ -80,6 +81,7 @@ interface PPB_FileChooser_Dev {
* @return PP_OK_COMPLETIONPENDING if request to show the dialog was
* successful, another error code from pp_errors.h on failure.
*/
+ [deprecate=0.6]
int32_t Show(
[in] PP_Resource chooser,
[in] PP_CompletionCallback callback);
@@ -96,7 +98,33 @@ interface PPB_FileChooser_Dev {
* @return A <code>PP_Resource</code> containing the next file chosen by the
* user, or 0 if there are no more files.
*/
+ [deprecate=0.6]
PP_Resource GetNextChosenFile(
[in] PP_Resource chooser);
+
+ /**
+ * This function displays a previously created file chooser resource as a
+ * dialog box, prompting the user to choose a file or files. This function
+ * must be called in response to a user gesture, such as a mouse click or
+ * touch event. The callback is called with PP_OK on successful completion
+ * with a file (or files) selected, PP_ERROR_USERCANCEL if the user selected
+ * no file, or another error code from pp_errors.h on failure.
+ *
+ * @param[in] chooser The file chooser resource.
+ *
+ * @param[in] output An output array which will receive PP_Resource(s)
+ * identifying the <code>PPB_FileRef</code> objects that the user selected on
+ * success.
+ *
+ * @param[in] callback A <code>CompletionCallback</code> to be called after
+ * the user has closed the file chooser dialog.
+ *
+ * @return PP_OK_COMPLETIONPENDING if request to show the dialog was
+ * successful, another error code from pp_errors.h on failure.
+ */
+ [version=0.6]
+ int32_t Show([in] PP_Resource chooser,
+ [in] PP_ArrayOutput output,
+ [in] PP_CompletionCallback callback);
};
diff --git a/ppapi/api/pp_array_output.idl b/ppapi/api/pp_array_output.idl
index 46411d8..b3b508a 100644
--- a/ppapi/api/pp_array_output.idl
+++ b/ppapi/api/pp_array_output.idl
@@ -75,6 +75,7 @@ typedef mem_t PP_ArrayOutput_GetDataBuffer([inout] mem_t user_data,
* }
* @endcode
*/
+[passByValue]
struct PP_ArrayOutput {
/**
* A pointer to the allocation function that the browser implements.
diff --git a/ppapi/api/trusted/ppb_file_chooser_trusted.idl b/ppapi/api/trusted/ppb_file_chooser_trusted.idl
index d921c81..3d9aea0 100644
--- a/ppapi/api/trusted/ppb_file_chooser_trusted.idl
+++ b/ppapi/api/trusted/ppb_file_chooser_trusted.idl
@@ -9,7 +9,8 @@
*/
label Chrome {
- M16 = 0.5
+ M16 = 0.5,
+ M20 = 0.6
};
[macro="PPB_FILECHOOSER_TRUSTED_INTERFACE"]
@@ -32,10 +33,37 @@ interface PPB_FileChooserTrusted {
* @return PP_OK_COMPLETIONPENDING if request to show the dialog was
* successful, another error code from pp_errors.h on failure.
*/
+ [deprecate=0.6]
int32_t ShowWithoutUserGesture(
[in] PP_Resource chooser,
[in] PP_Bool save_as,
[in] PP_Var suggested_file_name,
[in] PP_CompletionCallback callback);
+
+ /**
+ * This function displays a previously created file chooser resource as a
+ * dialog box, prompting the user to choose a file or files to open, or a
+ * single file for saving. The callback is called with PP_OK on successful
+ * completion with a file (or files) selected or PP_ERROR_USERCANCEL if the
+ * user selected no file.
+ *
+ * @param[in] chooser The file chooser resource.
+ * @param[in] save_as A <code>PP_Bool</code> value indicating if this dialog
+ * is choosing a file for saving.
+ * @param[in] suggested_file_name If saving, the suggested name for the
+ * file, otherwise, null or undefined.
+ * @param[in] callback A <code>CompletionCallback</code> to be called after
+ * the user has closed the file chooser dialog.
+ *
+ * @return PP_OK_COMPLETIONPENDING if request to show the dialog was
+ * successful, another error code from pp_errors.h on failure.
+ */
+ [version=0.6]
+ int32_t ShowWithoutUserGesture(
+ [in] PP_Resource chooser,
+ [in] PP_Bool save_as,
+ [in] PP_Var suggested_file_name,
+ [in] PP_ArrayOutput output,
+ [in] PP_CompletionCallback callback);
};
diff --git a/ppapi/c/dev/ppb_file_chooser_dev.h b/ppapi/c/dev/ppb_file_chooser_dev.h
index a2ef7ce..81e8f52 100644
--- a/ppapi/c/dev/ppb_file_chooser_dev.h
+++ b/ppapi/c/dev/ppb_file_chooser_dev.h
@@ -3,11 +3,12 @@
* found in the LICENSE file.
*/
-/* From dev/ppb_file_chooser_dev.idl modified Mon Nov 14 10:36:01 2011. */
+/* From dev/ppb_file_chooser_dev.idl modified Thu Mar 15 09:29:39 2012. */
#ifndef PPAPI_C_DEV_PPB_FILE_CHOOSER_DEV_H_
#define PPAPI_C_DEV_PPB_FILE_CHOOSER_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_instance.h"
@@ -17,7 +18,8 @@
#include "ppapi/c/pp_var.h"
#define PPB_FILECHOOSER_DEV_INTERFACE_0_5 "PPB_FileChooser(Dev);0.5"
-#define PPB_FILECHOOSER_DEV_INTERFACE PPB_FILECHOOSER_DEV_INTERFACE_0_5
+#define PPB_FILECHOOSER_DEV_INTERFACE_0_6 "PPB_FileChooser(Dev);0.6"
+#define PPB_FILECHOOSER_DEV_INTERFACE PPB_FILECHOOSER_DEV_INTERFACE_0_6
/**
* @file
@@ -52,7 +54,7 @@ PP_COMPILE_ASSERT_SIZE_IN_BYTES(PP_FileChooserMode_Dev, 4);
* @addtogroup Interfaces
* @{
*/
-struct PPB_FileChooser_Dev_0_5 {
+struct PPB_FileChooser_Dev_0_6 {
/**
* This function creates a file chooser dialog resource. The chooser is
* associated with a particular instance, so that it may be positioned on the
@@ -94,29 +96,32 @@ struct PPB_FileChooser_Dev_0_5 {
* no file, or another error code from pp_errors.h on failure.
*
* @param[in] chooser The file chooser resource.
+ *
+ * @param[in] output An output array which will receive PP_Resource(s)
+ * identifying the <code>PPB_FileRef</code> objects that the user selected on
+ * success.
+ *
* @param[in] callback A <code>CompletionCallback</code> to be called after
* the user has closed the file chooser dialog.
*
* @return PP_OK_COMPLETIONPENDING if request to show the dialog was
* successful, another error code from pp_errors.h on failure.
*/
+ int32_t (*Show)(PP_Resource chooser,
+ struct PP_ArrayOutput output,
+ struct PP_CompletionCallback callback);
+};
+
+typedef struct PPB_FileChooser_Dev_0_6 PPB_FileChooser_Dev;
+
+struct PPB_FileChooser_Dev_0_5 {
+ PP_Resource (*Create)(PP_Instance instance,
+ PP_FileChooserMode_Dev mode,
+ struct PP_Var accept_mime_types);
+ PP_Bool (*IsFileChooser)(PP_Resource resource);
int32_t (*Show)(PP_Resource chooser, struct PP_CompletionCallback callback);
- /**
- * After a successful completion callback call from Show, this method may be
- * used to query the chosen files. It should be called in a loop until it
- * returns 0. Their file system type will be PP_FileSystemType_External. If
- * the user chose no files or canceled the dialog, then this method will
- * simply return 0 the first time it is called.
- *
- * @param[in] chooser The file chooser resource.
- *
- * @return A <code>PP_Resource</code> containing the next file chosen by the
- * user, or 0 if there are no more files.
- */
PP_Resource (*GetNextChosenFile)(PP_Resource chooser);
};
-
-typedef struct PPB_FileChooser_Dev_0_5 PPB_FileChooser_Dev;
/**
* @}
*/
diff --git a/ppapi/c/trusted/ppb_file_chooser_trusted.h b/ppapi/c/trusted/ppb_file_chooser_trusted.h
index 85187a7..048639a 100644
--- a/ppapi/c/trusted/ppb_file_chooser_trusted.h
+++ b/ppapi/c/trusted/ppb_file_chooser_trusted.h
@@ -4,12 +4,13 @@
*/
/* From trusted/ppb_file_chooser_trusted.idl,
- * modified Wed Jan 4 11:09:00 2012.
+ * modified Fri Mar 16 10:00:48 2012.
*/
#ifndef PPAPI_C_TRUSTED_PPB_FILE_CHOOSER_TRUSTED_H_
#define PPAPI_C_TRUSTED_PPB_FILE_CHOOSER_TRUSTED_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_macros.h"
@@ -18,7 +19,8 @@
#include "ppapi/c/pp_var.h"
#define PPB_FILECHOOSER_TRUSTED_INTERFACE_0_5 "PPB_FileChooserTrusted;0.5"
-#define PPB_FILECHOOSER_TRUSTED_INTERFACE PPB_FILECHOOSER_TRUSTED_INTERFACE_0_5
+#define PPB_FILECHOOSER_TRUSTED_INTERFACE_0_6 "PPB_FileChooserTrusted;0.6"
+#define PPB_FILECHOOSER_TRUSTED_INTERFACE PPB_FILECHOOSER_TRUSTED_INTERFACE_0_6
/**
* @file
@@ -30,7 +32,7 @@
* @addtogroup Interfaces
* @{
*/
-struct PPB_FileChooserTrusted_0_5 {
+struct PPB_FileChooserTrusted_0_6 {
/**
* This function displays a previously created file chooser resource as a
* dialog box, prompting the user to choose a file or files to open, or a
@@ -52,10 +54,18 @@ struct PPB_FileChooserTrusted_0_5 {
int32_t (*ShowWithoutUserGesture)(PP_Resource chooser,
PP_Bool save_as,
struct PP_Var suggested_file_name,
+ struct PP_ArrayOutput output,
struct PP_CompletionCallback callback);
};
-typedef struct PPB_FileChooserTrusted_0_5 PPB_FileChooserTrusted;
+typedef struct PPB_FileChooserTrusted_0_6 PPB_FileChooserTrusted;
+
+struct PPB_FileChooserTrusted_0_5 {
+ int32_t (*ShowWithoutUserGesture)(PP_Resource chooser,
+ PP_Bool save_as,
+ struct PP_Var suggested_file_name,
+ struct PP_CompletionCallback callback);
+};
/**
* @}
*/
diff --git a/ppapi/cpp/array_output.h b/ppapi/cpp/array_output.h
index 4441386..7081507 100644
--- a/ppapi/cpp/array_output.h
+++ b/ppapi/cpp/array_output.h
@@ -47,7 +47,7 @@ class ArrayOutputAdapterBase {
}
virtual ~ArrayOutputAdapterBase() {}
- PP_ArrayOutput* pp_array_output() { return &pp_array_output_; }
+ const PP_ArrayOutput& pp_array_output() { return pp_array_output_; }
protected:
virtual void* GetDataBuffer(uint32_t element_count,
@@ -92,6 +92,8 @@ class ArrayOutputAdapter : public ArrayOutputAdapterBase {
// ArrayOutputAdapterBase implementation.
virtual void* GetDataBuffer(uint32_t element_count, uint32_t element_size) {
+ if (element_count == 0)
+ return NULL;
PP_DCHECK(element_size == sizeof(T));
if (element_size != sizeof(T))
return NULL;
@@ -140,6 +142,8 @@ class ResourceArrayOutputAdapter : public ArrayOutputAdapterBase {
// ArrayOutputAdapterBase implementation.
virtual void* GetDataBuffer(uint32_t element_count,
uint32_t element_size) {
+ if (element_count == 0)
+ return NULL;
PP_DCHECK(element_size == sizeof(PP_Resource));
if (element_size != sizeof(PP_Resource))
return NULL;
diff --git a/ppapi/cpp/completion_callback.h b/ppapi/cpp/completion_callback.h
index f1a20b3..3d142e8 100644
--- a/ppapi/cpp/completion_callback.h
+++ b/ppapi/cpp/completion_callback.h
@@ -185,6 +185,8 @@ class CompletionCallbackWithOutput : public CompletionCallback {
/// specializations for all of these cases.
typedef typename internal::CallbackOutputTraits<T>::StorageType
OutputStorageType;
+ typedef typename internal::CallbackOutputTraits<T>::APIArgType
+ APIArgType;
/// The default constructor will create a blocking
/// <code>CompletionCallback</code> that references the given output
@@ -237,7 +239,9 @@ class CompletionCallbackWithOutput : public CompletionCallback {
output_(output) {
}
- OutputStorageType* output() const { return output_; }
+ APIArgType output() const {
+ return internal::CallbackOutputTraits<T>::StorageToAPIArg(*output_);
+ }
private:
OutputStorageType* output_;
diff --git a/ppapi/cpp/dev/file_chooser_dev.cc b/ppapi/cpp/dev/file_chooser_dev.cc
index 7987f48..a773def 100644
--- a/ppapi/cpp/dev/file_chooser_dev.cc
+++ b/ppapi/cpp/dev/file_chooser_dev.cc
@@ -4,6 +4,8 @@
#include "ppapi/cpp/dev/file_chooser_dev.h"
+#include <string.h>
+
#include "ppapi/c/dev/ppb_file_chooser_dev.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/cpp/completion_callback.h"
@@ -16,8 +18,12 @@ namespace pp {
namespace {
-template <> const char* interface_name<PPB_FileChooser_Dev>() {
- return PPB_FILECHOOSER_DEV_INTERFACE;
+template <> const char* interface_name<PPB_FileChooser_Dev_0_5>() {
+ return PPB_FILECHOOSER_DEV_INTERFACE_0_5;
+}
+
+template <> const char* interface_name<PPB_FileChooser_Dev_0_6>() {
+ return PPB_FILECHOOSER_DEV_INTERFACE_0_6;
}
} // namespace
@@ -25,28 +31,72 @@ template <> const char* interface_name<PPB_FileChooser_Dev>() {
FileChooser_Dev::FileChooser_Dev(const InstanceHandle& instance,
PP_FileChooserMode_Dev mode,
const Var& accept_mime_types) {
- if (!has_interface<PPB_FileChooser_Dev>())
- return;
- PassRefFromConstructor(get_interface<PPB_FileChooser_Dev>()->Create(
- instance.pp_instance(), mode, accept_mime_types.pp_var()));
+ if (has_interface<PPB_FileChooser_Dev_0_6>()) {
+ PassRefFromConstructor(get_interface<PPB_FileChooser_Dev_0_6>()->Create(
+ instance.pp_instance(), mode, accept_mime_types.pp_var()));
+ } else if (has_interface<PPB_FileChooser_Dev_0_5>()) {
+ PassRefFromConstructor(get_interface<PPB_FileChooser_Dev_0_5>()->Create(
+ instance.pp_instance(), mode, accept_mime_types.pp_var()));
+ }
}
FileChooser_Dev::FileChooser_Dev(const FileChooser_Dev& other)
: Resource(other) {
}
-int32_t FileChooser_Dev::Show(const CompletionCallback& cc) {
- if (!has_interface<PPB_FileChooser_Dev>())
- return cc.MayForce(PP_ERROR_NOINTERFACE);
- return get_interface<PPB_FileChooser_Dev>()->Show(
- pp_resource(), cc.pp_completion_callback());
+int32_t FileChooser_Dev::Show(
+ const CompletionCallbackWithOutput< std::vector<FileRef> >& callback) {
+ if (has_interface<PPB_FileChooser_Dev_0_6>()) {
+ return get_interface<PPB_FileChooser_Dev_0_6>()->Show(
+ pp_resource(),
+ callback.output(),
+ callback.pp_completion_callback());
+ }
+ if (has_interface<PPB_FileChooser_Dev_0_5>()) {
+ // Data for our callback wrapper. The callback handler will delete it.
+ ChooseCallbackData0_5* data = new ChooseCallbackData0_5;
+ data->file_chooser = pp_resource();
+ data->output = callback.output();
+ data->original_callback = callback.pp_completion_callback();
+
+ return get_interface<PPB_FileChooser_Dev_0_5>()->Show(
+ pp_resource(), PP_MakeCompletionCallback(&CallbackConverter, data));
+ }
+ return callback.MayForce(PP_ERROR_NOINTERFACE);
}
-FileRef FileChooser_Dev::GetNextChosenFile() const {
- if (!has_interface<PPB_FileChooser_Dev>())
- return FileRef();
- return FileRef(PASS_REF,
- get_interface<PPB_FileChooser_Dev>()->GetNextChosenFile(pp_resource()));
+// static
+void FileChooser_Dev::CallbackConverter(void* user_data, int32_t result) {
+ ChooseCallbackData0_5* data = static_cast<ChooseCallbackData0_5*>(user_data);
+
+ // Get all of the selected file resources using the iterator API.
+ std::vector<PP_Resource> selected_files;
+ if (result == PP_OK) {
+ const PPB_FileChooser_Dev_0_5* chooser =
+ get_interface<PPB_FileChooser_Dev_0_5>();
+ while (PP_Resource cur = chooser->GetNextChosenFile(data->file_chooser))
+ selected_files.push_back(cur);
+ }
+
+ // Need to issue the "GetDataBuffer" even for error cases & when the
+ // number of items is 0.
+ void* output_buf = data->output.GetDataBuffer(
+ data->output.user_data,
+ selected_files.size(), sizeof(PP_Resource));
+ if (output_buf) {
+ if (!selected_files.empty()) {
+ memcpy(output_buf, &selected_files[0],
+ sizeof(PP_Resource) * selected_files.size());
+ }
+ } else {
+ // Error allocating, need to free the resource IDs.
+ for (size_t i = 0; i < selected_files.size(); i++)
+ Module::Get()->core()->ReleaseResource(selected_files[i]);
+ }
+
+ // Now execute the original callback.
+ PP_RunCompletionCallback(&data->original_callback, result);
+ delete data;
}
} // namespace pp
diff --git a/ppapi/cpp/dev/file_chooser_dev.h b/ppapi/cpp/dev/file_chooser_dev.h
index c2abc70..b588ac85 100644
--- a/ppapi/cpp/dev/file_chooser_dev.h
+++ b/ppapi/cpp/dev/file_chooser_dev.h
@@ -5,7 +5,11 @@
#ifndef PPAPI_CPP_DEV_FILE_CHOOSER_DEV_H_
#define PPAPI_CPP_DEV_FILE_CHOOSER_DEV_H_
+#include <vector>
+
#include "ppapi/c/dev/ppb_file_chooser_dev.h"
+#include "ppapi/cpp/completion_callback.h"
+#include "ppapi/cpp/file_ref.h"
#include "ppapi/cpp/resource.h"
namespace pp {
@@ -49,23 +53,47 @@ class FileChooser_Dev : public Resource {
FileChooser_Dev(const FileChooser_Dev& other);
/// This function displays a previously created file chooser resource as a
- /// dialog box, prompting the user to choose a file or files. The callback is
- /// called with PP_OK on successful completion with a file (or files) selected
- /// or PP_ERROR_USERCANCEL if the user selected no file.
+ /// dialog box, prompting the user to choose a file or files. This function
+ /// must be called in response to a user gesture, such as a mouse click or
+ /// touch event. The callback is called with PP_OK on successful completion
+ /// with a file (or files) selected, PP_ERROR_USERCANCEL if the user selected
+ /// no file, or another error code from pp_errors.h on failure.
+ ///
+ /// @param callback The completion callback that will be executed. On success,
+ /// the selected files 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 OnFilesSelected(int32_t result,
+ /// const std::vector<pp::FileRef>& files) {
+ /// if (result == PP_OK)
+ /// // use files...
+ /// }
+ /// @endcode
///
/// @return PP_OK_COMPLETIONPENDING if request to show the dialog was
/// successful, another error code from pp_errors.h on failure.
- virtual int32_t Show(const CompletionCallback& cc);
+ virtual int32_t Show(
+ const CompletionCallbackWithOutput< std::vector<FileRef> >& callback);
+
+ protected:
+ // Heap-allocated data passed to the CallbackConverter for backwards compat.
+ struct ChooseCallbackData0_5 {
+ PP_Resource file_chooser;
+ PP_ArrayOutput output;
+ PP_CompletionCallback original_callback;
+ };
- /// After a successful completion callback call from Show, this method may be
- /// used to query the chosen files. It should be called in a loop until it
- /// returns an is_null() FileRef. Depending on the PP_ChooseFileMode
- /// requested when the FileChooser was created, the file refs will either
- /// be readable or writable. Their file system type will be
- /// PP_FileSystemType_External. If the user chose no files or cancelled the
- /// dialog, then this method will simply return an is_null() FileRef the
- /// first time it is called.
- virtual FileRef GetNextChosenFile() const;
+ // Provide backwards-compatability for older versions. Converts the old-style
+ // 0.5 "iterator" interface to the new-style 0.6 "array output" interface that
+ // the caller is expecting.
+ //
+ // This takes a heap-allocated ChooseCallbackData0_5 struct passed as the
+ // user data and deletes it when the call completes.
+ static void CallbackConverter(void* user_data, int32_t result);
};
} // namespace pp
diff --git a/ppapi/cpp/output_traits.h b/ppapi/cpp/output_traits.h
index 6326c32..237b0bc 100644
--- a/ppapi/cpp/output_traits.h
+++ b/ppapi/cpp/output_traits.h
@@ -149,7 +149,7 @@ struct CallbackOutputTraits<Var> {
template<typename T>
struct GenericVectorCallbackOutputTraits {
// All arrays are output via a PP_ArrayOutput type.
- typedef PP_ArrayOutput* APIArgType;
+ typedef PP_ArrayOutput APIArgType;
// We store the array as this adapter which combines the PP_ArrayOutput
// structure with the underlying std::vector that it will write into.
@@ -177,7 +177,7 @@ struct GenericVectorCallbackOutputTraits {
// class of pp::Resource.
template<typename T>
struct ResourceVectorCallbackOutputTraits {
- typedef PP_ArrayOutput* APIArgType;
+ typedef PP_ArrayOutput APIArgType;
typedef ResourceArrayOutputAdapterWithStorage<T> StorageType;
static inline APIArgType StorageToAPIArg(StorageType& t) {
@@ -207,7 +207,7 @@ struct CallbackOutputTraits< std::vector<T> >
template<>
struct CallbackOutputTraits< std::vector<pp::Var> > {
// All arrays are output via a PP_ArrayOutput type.
- typedef PP_ArrayOutput* APIArgType;
+ typedef PP_ArrayOutput APIArgType;
// We store the array as this adapter which combines the PP_ArrayOutput
// structure with the underlying std::vector that it will write into.
diff --git a/ppapi/cpp/trusted/file_chooser_trusted.cc b/ppapi/cpp/trusted/file_chooser_trusted.cc
index a5f6879..d925518 100644
--- a/ppapi/cpp/trusted/file_chooser_trusted.cc
+++ b/ppapi/cpp/trusted/file_chooser_trusted.cc
@@ -15,8 +15,12 @@ namespace pp {
namespace {
-template <> const char* interface_name<PPB_FileChooserTrusted>() {
- return PPB_FILECHOOSER_TRUSTED_INTERFACE;
+template <> const char* interface_name<PPB_FileChooserTrusted_0_5>() {
+ return PPB_FILECHOOSER_TRUSTED_INTERFACE_0_5;
+}
+
+template <> const char* interface_name<PPB_FileChooserTrusted_0_6>() {
+ return PPB_FILECHOOSER_TRUSTED_INTERFACE_0_6;
}
} // namespace
@@ -48,14 +52,29 @@ FileChooser_Trusted& FileChooser_Trusted::operator=(
return *this;
}
-int32_t FileChooser_Trusted::Show(const CompletionCallback& cc) {
- if (!has_interface<PPB_FileChooserTrusted>())
- return cc.MayForce(PP_ERROR_NOINTERFACE);
- return get_interface<PPB_FileChooserTrusted>()->ShowWithoutUserGesture(
- pp_resource(),
- PP_FromBool(save_as_),
- Var(suggested_file_name_).pp_var(),
- cc.pp_completion_callback());
+int32_t FileChooser_Trusted::Show(
+ const CompletionCallbackWithOutput< std::vector<FileRef> >& callback) {
+ if (has_interface<PPB_FileChooserTrusted_0_6>()) {
+ return get_interface<PPB_FileChooserTrusted_0_6>()->ShowWithoutUserGesture(
+ pp_resource(),
+ PP_FromBool(save_as_),
+ Var(suggested_file_name_).pp_var(),
+ callback.output(),
+ callback.pp_completion_callback());
+ }
+ if (has_interface<PPB_FileChooserTrusted_0_5>()) {
+ // Data for our callback. The callback handler will delete it.
+ ChooseCallbackData0_5* data = new ChooseCallbackData0_5;
+ data->file_chooser = pp_resource();
+ data->output = callback.output();
+
+ return get_interface<PPB_FileChooserTrusted_0_5>()->ShowWithoutUserGesture(
+ pp_resource(),
+ PP_FromBool(save_as_),
+ Var(suggested_file_name_).pp_var(),
+ PP_MakeCompletionCallback(&CallbackConverter, data));
+ }
+ return callback.MayForce(PP_ERROR_NOINTERFACE);
}
} // namespace pp
diff --git a/ppapi/cpp/trusted/file_chooser_trusted.h b/ppapi/cpp/trusted/file_chooser_trusted.h
index d730dbf..6b3c1c1 100644
--- a/ppapi/cpp/trusted/file_chooser_trusted.h
+++ b/ppapi/cpp/trusted/file_chooser_trusted.h
@@ -28,7 +28,8 @@ class FileChooser_Trusted : public FileChooser_Dev {
// Overrides of method in superclass. This shows without requiring a user
// gesture (and can also show save dialogs).
- virtual int32_t Show(const CompletionCallback& cc);
+ virtual int32_t Show(
+ const CompletionCallbackWithOutput< std::vector<FileRef> >& callback);
private:
bool save_as_;
diff --git a/ppapi/examples/file_chooser/file_chooser.cc b/ppapi/examples/file_chooser/file_chooser.cc
index 136ff31..959e649 100644
--- a/ppapi/examples/file_chooser/file_chooser.cc
+++ b/ppapi/examples/file_chooser/file_chooser.cc
@@ -49,19 +49,16 @@ class MyInstance : public pp::InstancePrivate {
std::string accept_mime_types = (multi_select ? "" : "plain/text");
chooser_ = pp::FileChooser_Dev(this, mode, accept_mime_types);
- chooser_.Show(callback_factory_.NewCallback(
+ chooser_.Show(callback_factory_.NewCallbackWithOutput(
&MyInstance::ShowSelectedFileNames));
}
- void ShowSelectedFileNames(int32_t result) {
- if (!result != PP_OK)
+ void ShowSelectedFileNames(int32_t result,
+ const std::vector<pp::FileRef>& files) {
+ if (result != PP_OK)
return;
-
- pp::FileRef file_ref = chooser_.GetNextChosenFile();
- while (!file_ref.is_null()) {
- Log(file_ref.GetName());
- file_ref = chooser_.GetNextChosenFile();
- }
+ for (size_t i = 0; i < files.size(); i++)
+ Log(files[i].GetName());
}
void RecreateConsole() {
diff --git a/ppapi/ppapi_proxy.gypi b/ppapi/ppapi_proxy.gypi
index 84913e0..17850f1 100644
--- a/ppapi/ppapi_proxy.gypi
+++ b/ppapi/ppapi_proxy.gypi
@@ -28,6 +28,15 @@
'../..', # For nacl includes to work.
],
'sources': [
+ # Take some standalong files from the C++ wrapper allowing us to more
+ # easily make async callbacks in the proxy. We can't depend on the
+ # full C++ wrappers at this layer since the C++ wrappers expect
+ # symbols defining the globals for "being a plugin" which we are not.
+ # These callback files are standalone.
+ 'cpp/completion_callback.cc',
+ 'cpp/completion_callback.h',
+ 'utility/completion_callback_factory.h',
+
'proxy/broker_dispatcher.cc',
'proxy/broker_dispatcher.h',
'proxy/dispatcher.cc',
@@ -151,6 +160,8 @@
'proxy/ppp_text_input_proxy.h',
'proxy/ppp_video_decoder_proxy.cc',
'proxy/ppp_video_decoder_proxy.h',
+ 'proxy/proxy_array_output.cc',
+ 'proxy/proxy_array_output.h',
'proxy/proxy_channel.cc',
'proxy/proxy_channel.h',
'proxy/proxy_module.cc',
diff --git a/ppapi/ppapi_shared.gypi b/ppapi/ppapi_shared.gypi
index 48180c6..f1621e2 100644
--- a/ppapi/ppapi_shared.gypi
+++ b/ppapi/ppapi_shared.gypi
@@ -52,6 +52,8 @@
}],
],
'sources': [
+ 'shared_impl/array_writer.cc',
+ 'shared_impl/array_writer.h',
'shared_impl/callback_tracker.cc',
'shared_impl/callback_tracker.h',
'shared_impl/file_type_conversion.cc',
diff --git a/ppapi/proxy/DEPS b/ppapi/proxy/DEPS
index a159be3..1bfd52f 100644
--- a/ppapi/proxy/DEPS
+++ b/ppapi/proxy/DEPS
@@ -8,8 +8,9 @@ include_rules = [
# We don't want the proxy to depend on the C++ layer, which is appropriate
# for plugins only. However, the completion callback factory is a very useful
# tool that we would otherwise have to duplicate, and has no other
- # dependencies, so we allow that.
+ # dependencies, so we allow that (and the output traits it depends on).
"-ppapi/cpp",
- "+ppapi/cpp/completion_callback.h"
+ "+ppapi/cpp/completion_callback.h",
+ "+ppapi/cpp/output_traits.h"
]
diff --git a/ppapi/proxy/enter_proxy.h b/ppapi/proxy/enter_proxy.h
index 5306a80..86ee7a0 100644
--- a/ppapi/proxy/enter_proxy.h
+++ b/ppapi/proxy/enter_proxy.h
@@ -89,6 +89,14 @@ template<typename ResourceT>
class EnterHostFromHostResourceForceCallback
: public EnterHostFromHostResource<ResourceT> {
public:
+ EnterHostFromHostResourceForceCallback(
+ const HostResource& host_resource,
+ const pp::CompletionCallback& callback)
+ : EnterHostFromHostResource<ResourceT>(host_resource),
+ needs_running_(true),
+ callback_(callback) {
+ }
+
// For callbacks that take no parameters except the "int32_t result". Most
// implementations will use the 1-extra-argument constructor below.
template<class CallbackFactory, typename Method>
@@ -168,42 +176,12 @@ template<typename FunctionT>
class EnterHostFunctionForceCallback
: public thunk::EnterFunctionNoLock<FunctionT> {
public:
- // For callbacks that take no parameters except the "int32_t result". Most
- // implementations will use the 1-extra-argument constructor below.
- template<class CallbackFactory, typename Method>
- EnterHostFunctionForceCallback(PP_Instance instance,
- CallbackFactory& factory,
- Method method)
+ EnterHostFunctionForceCallback(
+ PP_Instance instance,
+ const pp::CompletionCallback& callback)
: thunk::EnterFunctionNoLock<FunctionT>(instance, false),
needs_running_(true),
- callback_(factory.NewOptionalCallback(method)) {
- if (this->failed())
- RunCallback(PP_ERROR_BADARGUMENT);
- }
-
- // For callbacks that take an extra parameter as a closure.
- template<class CallbackFactory, typename Method, typename A>
- EnterHostFunctionForceCallback(PP_Instance instance,
- CallbackFactory& factory,
- Method method,
- const A& a)
- : thunk::EnterFunctionNoLock<FunctionT>(instance, false),
- needs_running_(true),
- callback_(factory.NewOptionalCallback(method, a)) {
- if (this->failed())
- RunCallback(PP_ERROR_BADARGUMENT);
- }
-
- // For callbacks that take two extra parameters as a closure.
- template<class CallbackFactory, typename Method, typename A, typename B>
- EnterHostFunctionForceCallback(PP_Instance instance,
- CallbackFactory& factory,
- Method method,
- const A& a,
- const B& b)
- : thunk::EnterFunctionNoLock<FunctionT>(instance),
- needs_running_(true),
- callback_(factory.NewOptionalCallback(method, a, b)) {
+ callback_(callback) {
if (this->failed())
RunCallback(PP_ERROR_BADARGUMENT);
}
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
index 1043f59..dc46b5a 100644
--- a/ppapi/proxy/ppapi_messages.h
+++ b/ppapi/proxy/ppapi_messages.h
@@ -702,8 +702,8 @@ IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBFileChooser_Create,
ppapi::HostResource /* result */)
IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBFileChooser_Show,
ppapi::HostResource /* file_chooser */,
- bool /* save_as */,
- std::string /* suggested_file_name */,
+ PP_Bool /* save_as */,
+ ppapi::proxy::SerializedVar /* suggested_file_name */,
bool /* require_user_gesture */)
// PPB_FileIO.
diff --git a/ppapi/proxy/ppb_file_chooser_proxy.cc b/ppapi/proxy/ppb_file_chooser_proxy.cc
index fa8df55..47ea3a7 100644
--- a/ppapi/proxy/ppb_file_chooser_proxy.cc
+++ b/ppapi/proxy/ppb_file_chooser_proxy.cc
@@ -17,6 +17,7 @@
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/ppb_file_ref_proxy.h"
#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/shared_impl/array_writer.h"
#include "ppapi/shared_impl/ppapi_globals.h"
#include "ppapi/shared_impl/resource_tracker.h"
#include "ppapi/shared_impl/tracked_callback.h"
@@ -44,11 +45,18 @@ class FileChooser : public Resource,
virtual PPB_FileChooser_API* AsPPB_FileChooser_API() OVERRIDE;
// PPB_FileChooser_API implementation.
- virtual int32_t Show(const PP_CompletionCallback& callback) OVERRIDE;
- virtual PP_Resource GetNextChosenFile() OVERRIDE;
+ virtual int32_t Show(const PP_ArrayOutput& output,
+ const PP_CompletionCallback& callback) OVERRIDE;
virtual int32_t ShowWithoutUserGesture(
- bool save_as,
- const char* suggested_file_name,
+ PP_Bool save_as,
+ PP_Var suggested_file_name,
+ const PP_ArrayOutput& output,
+ const PP_CompletionCallback& callback);
+ virtual int32_t Show0_5(const PP_CompletionCallback& callback) OVERRIDE;
+ virtual PP_Resource GetNextChosenFile() OVERRIDE;
+ virtual int32_t ShowWithoutUserGesture0_5(
+ PP_Bool save_as,
+ PP_Var suggested_file_name,
const PP_CompletionCallback& callback) OVERRIDE;
// Handles the choose complete notification from the host.
@@ -58,16 +66,19 @@ class FileChooser : public Resource,
private:
int32_t Show(bool require_user_gesture,
- bool save_as,
- const char* suggested_file_name,
+ PP_Bool save_as,
+ PP_Var suggested_file_name,
const PP_CompletionCallback& callback);
+ // When using v0.6 of the API, contains the array output info.
+ ArrayWriter output_;
+
scoped_refptr<TrackedCallback> current_show_callback_;
- // All files returned by the current show callback that haven't yet been
- // given to the plugin. The plugin will repeatedly call us to get the next
- // file, and we'll vend those out of this queue, removing them when ownership
- // has transferred to the plugin.
+ // When using v0.5 of the API, contains all files returned by the current
+ // show callback that haven't yet been given to the plugin. The plugin will
+ // repeatedly call us to get the next file, and we'll vend those out of this
+ // queue, removing them when ownership has transferred to the plugin.
std::queue<PP_Resource> file_queue_;
DISALLOW_COPY_AND_ASSIGN(FileChooser);
@@ -91,20 +102,39 @@ PPB_FileChooser_API* FileChooser::AsPPB_FileChooser_API() {
return this;
}
-int32_t FileChooser::Show(const PP_CompletionCallback& callback) {
- return Show(true, false, NULL, callback);
+int32_t FileChooser::Show(const PP_ArrayOutput& output,
+ const PP_CompletionCallback& callback) {
+ int32_t result = Show(true, PP_FALSE, PP_MakeUndefined(), callback);
+ if (result == PP_OK_COMPLETIONPENDING)
+ output_.set_pp_array_output(output);
+ return result;
}
int32_t FileChooser::ShowWithoutUserGesture(
- bool save_as,
- const char* suggested_file_name,
+ PP_Bool save_as,
+ PP_Var suggested_file_name,
+ const PP_ArrayOutput& output,
+ const PP_CompletionCallback& callback) {
+ int32_t result = Show(false, save_as, PP_MakeUndefined(), callback);
+ if (result == PP_OK_COMPLETIONPENDING)
+ output_.set_pp_array_output(output);
+ return result;
+}
+
+int32_t FileChooser::Show0_5(const PP_CompletionCallback& callback) {
+ return Show(true, PP_FALSE, PP_MakeUndefined(), callback);
+}
+
+int32_t FileChooser::ShowWithoutUserGesture0_5(
+ PP_Bool save_as,
+ PP_Var suggested_file_name,
const PP_CompletionCallback& callback) {
return Show(false, save_as, suggested_file_name, callback);
}
int32_t FileChooser::Show(bool require_user_gesture,
- bool save_as,
- const char* suggested_file_name,
+ PP_Bool save_as,
+ PP_Var suggested_file_name,
const PP_CompletionCallback& callback) {
if (!callback.func)
return PP_ERROR_BLOCKS_MAIN_THREAD;
@@ -113,12 +143,13 @@ int32_t FileChooser::Show(bool require_user_gesture,
return PP_ERROR_INPROGRESS; // Can't show more than once.
current_show_callback_ = new TrackedCallback(this, callback);
- PluginDispatcher::GetForResource(this)->Send(
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForResource(this);
+ dispatcher->Send(
new PpapiHostMsg_PPBFileChooser_Show(
API_ID_PPB_FILE_CHOOSER,
host_resource(),
save_as,
- suggested_file_name ? suggested_file_name : "",
+ SerializedVarSendInput(dispatcher, suggested_file_name),
require_user_gesture));
return PP_OK_COMPLETIONPENDING;
}
@@ -138,11 +169,21 @@ PP_Resource FileChooser::GetNextChosenFile() {
void FileChooser::ChooseComplete(
int32_t result_code,
const std::vector<PPB_FileRef_CreateInfo>& chosen_files) {
- // Convert each of the passed in file infos to resources. These will be owned
- // by the FileChooser object until they're passed to the plugin.
- DCHECK(file_queue_.empty());
- for (size_t i = 0; i < chosen_files.size(); i++)
- file_queue_.push(PPB_FileRef_Proxy::DeserializeFileRef(chosen_files[i]));
+ if (output_.is_valid()) {
+ // Using v0.6 of the API with the output array.
+ std::vector<PP_Resource> files;
+ for (size_t i = 0; i < chosen_files.size(); i++)
+ files.push_back(PPB_FileRef_Proxy::DeserializeFileRef(chosen_files[i]));
+ output_.StoreResourceVector(files);
+ } else {
+ // Convert each of the passed in file infos to resources. These will be
+ // owned by the FileChooser object until they're passed to the plugin.
+ DCHECK(file_queue_.empty());
+ for (size_t i = 0; i < chosen_files.size(); i++) {
+ file_queue_.push(PPB_FileRef_Proxy::DeserializeFileRef(
+ chosen_files[i]));
+ }
+ }
// Notify the plugin of the new data.
TrackedCallback::ClearAndRun(&current_show_callback_, result_code);
@@ -223,19 +264,24 @@ void PPB_FileChooser_Proxy::OnMsgCreate(
void PPB_FileChooser_Proxy::OnMsgShow(
const HostResource& chooser,
- bool save_as,
- std::string suggested_file_name,
+ PP_Bool save_as,
+ SerializedVarReceiveInput suggested_file_name,
bool require_user_gesture) {
+ scoped_refptr<RefCountedArrayOutputAdapter<PP_Resource> > output(
+ new RefCountedArrayOutputAdapter<PP_Resource>);
EnterHostFromHostResourceForceCallback<PPB_FileChooser_API> enter(
- chooser, callback_factory_, &PPB_FileChooser_Proxy::OnShowCallback,
- chooser);
+ chooser,
+ callback_factory_.NewOptionalCallback(
+ &PPB_FileChooser_Proxy::OnShowCallback, output, chooser));
if (enter.succeeded()) {
if (require_user_gesture) {
- enter.SetResult(enter.object()->Show(enter.callback()));
+ enter.SetResult(enter.object()->Show(output->pp_array_output(),
+ enter.callback()));
} else {
enter.SetResult(enter.object()->ShowWithoutUserGesture(
save_as,
- suggested_file_name.c_str(),
+ suggested_file_name.Get(dispatcher()),
+ output->pp_array_output(),
enter.callback()));
}
}
@@ -252,8 +298,11 @@ void PPB_FileChooser_Proxy::OnMsgChooseComplete(
}
}
-void PPB_FileChooser_Proxy::OnShowCallback(int32_t result,
- const HostResource& chooser) {
+void PPB_FileChooser_Proxy::OnShowCallback(
+ int32_t result,
+ scoped_refptr<RefCountedArrayOutputAdapter<PP_Resource> >
+ output,
+ HostResource chooser) {
EnterHostFromHostResource<PPB_FileChooser_API> enter(chooser);
std::vector<PPB_FileRef_CreateInfo> files;
@@ -262,11 +311,14 @@ void PPB_FileChooser_Proxy::OnShowCallback(int32_t result,
dispatcher()->GetInterfaceProxy(API_ID_PPB_FILE_REF));
// Convert the returned files to the serialized info.
- while (PP_Resource cur_file_resource =
- enter.object()->GetNextChosenFile()) {
+ ResourceTracker* tracker = PpapiGlobals::Get()->GetResourceTracker();
+ for (size_t i = 0; i < output->output().size(); i++) {
PPB_FileRef_CreateInfo cur_create_info;
- file_ref_proxy->SerializeFileRef(cur_file_resource, &cur_create_info);
+ file_ref_proxy->SerializeFileRef(output->output()[i], &cur_create_info);
files.push_back(cur_create_info);
+
+ // Done with this resource, caller gave us a ref.
+ tracker->ReleaseResource(output->output()[i]);
}
}
diff --git a/ppapi/proxy/ppb_file_chooser_proxy.h b/ppapi/proxy/ppb_file_chooser_proxy.h
index da45a2c..530aec3 100644
--- a/ppapi/proxy/ppb_file_chooser_proxy.h
+++ b/ppapi/proxy/ppb_file_chooser_proxy.h
@@ -11,8 +11,11 @@
#include "base/basictypes.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/proxy_array_output.h"
#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h"
+#include "ppapi/proxy/serialized_var.h"
#include "ppapi/thunk/ppb_file_chooser_api.h"
+#include "ppapi/cpp/output_traits.h"
#include "ppapi/utility/completion_callback_factory.h"
namespace ppapi {
@@ -46,8 +49,8 @@ class PPB_FileChooser_Proxy : public InterfaceProxy {
std::string accept_mime_types,
ppapi::HostResource* result);
void OnMsgShow(const ppapi::HostResource& chooser,
- bool save_as,
- std::string suggested_file_name,
+ PP_Bool save_as,
+ SerializedVarReceiveInput suggested_file_name,
bool require_user_gesture);
// Host -> plugin message handlers.
@@ -58,7 +61,10 @@ class PPB_FileChooser_Proxy : public InterfaceProxy {
// Called when the show is complete in the host. This will notify the plugin
// via IPC and OnMsgChooseComplete will be called there.
- void OnShowCallback(int32_t result, const ppapi::HostResource& chooser);
+ void OnShowCallback(
+ int32_t result,
+ scoped_refptr<RefCountedArrayOutputAdapter<PP_Resource> > output,
+ HostResource chooser);
pp::CompletionCallbackFactory<PPB_FileChooser_Proxy,
ProxyNonThreadSafeRefCount> callback_factory_;
diff --git a/ppapi/proxy/ppb_instance_proxy.cc b/ppapi/proxy/ppb_instance_proxy.cc
index 7f29c66..758e67f 100644
--- a/ppapi/proxy/ppb_instance_proxy.cc
+++ b/ppapi/proxy/ppb_instance_proxy.cc
@@ -573,8 +573,10 @@ void PPB_Instance_Proxy::OnHostMsgPostMessage(
void PPB_Instance_Proxy::OnHostMsgLockMouse(PP_Instance instance) {
EnterHostFunctionForceCallback<PPB_Instance_FunctionAPI> enter(
- instance, callback_factory_,
- &PPB_Instance_Proxy::MouseLockCompleteInHost, instance);
+ instance,
+ callback_factory_.NewCallback(
+ &PPB_Instance_Proxy::MouseLockCompleteInHost,
+ instance));
if (enter.succeeded())
enter.SetResult(enter.functions()->LockMouse(instance, enter.callback()));
}
diff --git a/ppapi/proxy/proxy_array_output.cc b/ppapi/proxy/proxy_array_output.cc
new file mode 100644
index 0000000..e550b1c
--- /dev/null
+++ b/ppapi/proxy/proxy_array_output.cc
@@ -0,0 +1,21 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/proxy_array_output.h"
+
+#include "base/logging.h"
+
+namespace ppapi {
+namespace proxy {
+
+// static
+void* ArrayOutputAdapterBase::GetDataBufferThunk(void* user_data,
+ uint32_t element_count,
+ uint32_t element_size) {
+ return static_cast<ArrayOutputAdapterBase*>(user_data)->
+ GetDataBuffer(element_count, element_size);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/ppapi/proxy/proxy_array_output.h b/ppapi/proxy/proxy_array_output.h
new file mode 100644
index 0000000..d717909
--- /dev/null
+++ b/ppapi/proxy/proxy_array_output.h
@@ -0,0 +1,138 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PROXY_ARRAY_OUTPUT_H_
+#define PPAPI_PROXY_PROXY_ARRAY_OUTPUT_H_
+
+#include <vector>
+
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "ppapi/c/pp_array_output.h"
+
+// Like ppapi/cpp/array_output.h file in the C++ wrappers but for use in the
+// proxy where we can't link to the C++ wrappers. This also adds a refcounted
+// version.
+//
+// Use ArrayOutputAdapter when calling a function that synchronously returns
+// an array of data. Use RefCountedArrayOutputAdapterWithStorage for
+// asynchronous returns:
+//
+// void OnCallbackComplete(
+// int32_t result,
+// scoped_refptr<RefCountedArrayOutputAdapter<PP_Resource> > output) {
+// // Vector is in output->output().
+// }
+//
+// void ScheduleCallback() {
+// base::scoped_refptr<RefCountedArrayOutputAdapter<PP_Resource> > output;
+//
+// callback = factory.NewOptionalCallback(&OnCallbackComplete, output);
+// DoSomethingAsynchronously(output->pp_array_output(),
+// callback.PP_CompletionCallback());
+// ...
+namespace ppapi {
+namespace proxy {
+
+// Non-templatized base class for the array output conversion. It provides the
+// C implementation of a PP_ArrayOutput whose callback function is implemented
+// as a virtual call on a derived class. Do not use directly, use one of the
+// derived classes below.
+class ArrayOutputAdapterBase {
+ public:
+ ArrayOutputAdapterBase() {
+ pp_array_output_.GetDataBuffer =
+ &ArrayOutputAdapterBase::GetDataBufferThunk;
+ pp_array_output_.user_data = this;
+ }
+ virtual ~ArrayOutputAdapterBase() {}
+
+ const PP_ArrayOutput& pp_array_output() { return pp_array_output_; }
+
+ protected:
+ virtual void* GetDataBuffer(uint32_t element_count,
+ uint32_t element_size) = 0;
+
+ private:
+ static void* GetDataBufferThunk(void* user_data,
+ uint32_t element_count,
+ uint32_t element_size);
+
+ PP_ArrayOutput pp_array_output_;
+
+ // Disallow copying and assignment. This will do the wrong thing for most
+ // subclasses.
+ ArrayOutputAdapterBase(const ArrayOutputAdapterBase&);
+ ArrayOutputAdapterBase& operator=(const ArrayOutputAdapterBase&);
+};
+
+// This adapter provides functionality for implementing a PP_ArrayOutput
+// structure as writing to a given vector object.
+//
+// This is generally used internally in the C++ wrapper objects to
+// write into an output parameter supplied by the plugin. If the element size
+// that the browser is writing does not match the size of the type we're using
+// this will assert and return NULL (which will cause the browser to fail the
+// call).
+//
+// Example that allows the browser to write into a given vector:
+// void DoFoo(std::vector<int>* results) {
+// ArrayOutputAdapter<int> adapter(results);
+// ppb_foo->DoFoo(adapter.pp_array_output());
+// }
+template<typename T>
+class ArrayOutputAdapter : public ArrayOutputAdapterBase {
+ public:
+ ArrayOutputAdapter(std::vector<T>* output) : output_(output) {}
+
+ protected:
+ // Two-step init for the "with storage" version below.
+ ArrayOutputAdapter() : output_(NULL) {}
+ void set_output(std::vector<T>* output) { output_ = output; }
+
+ // ArrayOutputAdapterBase implementation.
+ virtual void* GetDataBuffer(uint32_t element_count, uint32_t element_size) {
+ DCHECK(element_size == sizeof(T));
+ if (element_count == 0 || element_size != sizeof(T))
+ return NULL;
+ output_->resize(element_count);
+ return &(*output_)[0];
+ }
+
+ private:
+ std::vector<T>* output_;
+};
+
+template<typename T>
+class ArrayOutputAdapterWithStorage : public ArrayOutputAdapter<T> {
+ public:
+ ArrayOutputAdapterWithStorage() {
+ // Note: "this->" is required due to two-phase name lookup where it isn't
+ // allowed to look in the base class during parsing.
+ this->set_output(&output_storage_);
+ }
+
+ std::vector<T>& output() { return output_storage_; }
+
+ private:
+ std::vector<T> output_storage_;
+};
+
+// A reference counted version of ArrayOutputAdapterWithStorage. Since it
+// doesn't make much sense to heap-allocate one without storage, we don't
+// call it "with storage" to keep the name length under control.
+template<typename T>
+class RefCountedArrayOutputAdapter
+ : public ArrayOutputAdapterWithStorage<T>,
+ public base::RefCounted<RefCountedArrayOutputAdapter<T> > {
+ public:
+ RefCountedArrayOutputAdapter()
+ : ArrayOutputAdapterWithStorage<T>() {
+ }
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PROXY_ARRAY_OUTPUT_H_
diff --git a/ppapi/shared_impl/array_writer.cc b/ppapi/shared_impl/array_writer.cc
new file mode 100644
index 0000000..957ff77
--- /dev/null
+++ b/ppapi/shared_impl/array_writer.cc
@@ -0,0 +1,79 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/shared_impl/array_writer.h"
+
+#include <algorithm>
+
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/resource.h"
+#include "ppapi/shared_impl/resource_tracker.h"
+
+namespace ppapi {
+
+ArrayWriter::ArrayWriter() {
+ Reset();
+}
+
+ArrayWriter::ArrayWriter(const PP_ArrayOutput& output)
+ : pp_array_output_(output) {
+}
+
+ArrayWriter::~ArrayWriter() {
+}
+
+void ArrayWriter::Reset() {
+ pp_array_output_.GetDataBuffer = NULL;
+ pp_array_output_.user_data = NULL;
+}
+
+bool ArrayWriter::StoreResourceVector(
+ const std::vector< scoped_refptr<Resource> >& input) {
+ // Always call the alloc function, even on 0 array size.
+ void* dest = pp_array_output_.GetDataBuffer(
+ pp_array_output_.user_data,
+ static_cast<uint32_t>(input.size()),
+ sizeof(PP_Resource));
+
+ // Regardless of success, we clear the output to prevent future calls on
+ // this same output object.
+ Reset();
+
+ if (input.empty())
+ return true; // Allow plugin to return NULL on 0 elements.
+ if (!dest)
+ return false;
+
+ // Convert to PP_Resources.
+ PP_Resource* dest_resources = static_cast<PP_Resource*>(dest);
+ for (size_t i = 0; i < input.size(); i++)
+ dest_resources[i] = input[i]->GetReference();
+ return true;
+}
+
+bool ArrayWriter::StoreResourceVector(const std::vector<PP_Resource>& input) {
+ // Always call the alloc function, even on 0 array size.
+ void* dest = pp_array_output_.GetDataBuffer(
+ pp_array_output_.user_data,
+ static_cast<uint32_t>(input.size()),
+ sizeof(PP_Resource));
+
+ // Regardless of success, we clear the output to prevent future calls on
+ // this same output object.
+ Reset();
+
+ if (input.empty())
+ return true; // Allow plugin to return NULL on 0 elements.
+ if (!dest) {
+ // Free the resources.
+ for (size_t i = 0; i < input.size(); i++)
+ PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(input[i]);
+ return false;
+ }
+
+ std::copy(input.begin(), input.end(), static_cast<PP_Resource*>(dest));
+ return true;
+}
+
+} // namespace ppapi
diff --git a/ppapi/shared_impl/array_writer.h b/ppapi/shared_impl/array_writer.h
new file mode 100644
index 0000000..cabd0af
--- /dev/null
+++ b/ppapi/shared_impl/array_writer.h
@@ -0,0 +1,98 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_SHARED_IMPL_ARRAY_WRITER_H_
+#define PPAPI_SHARED_IMPL_ARRAY_WRITER_H_
+
+#include <string.h>
+
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "ppapi/c/pp_array_output.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/shared_impl/ppapi_shared_export.h"
+
+namespace ppapi {
+
+class Resource;
+
+// Holds a PP_ArrayWriter and provides helper functions for writing arrays
+// to it. It also handles 0-initialization of the raw C struct and attempts
+// to prevent you from writing the array twice.
+class PPAPI_SHARED_EXPORT ArrayWriter {
+ public:
+ ArrayWriter(); // Creates an is_null() object
+ ArrayWriter(const PP_ArrayOutput& output);
+ ~ArrayWriter();
+
+ bool is_valid() const { return !!pp_array_output_.GetDataBuffer; }
+ bool is_null() const { return !is_valid(); }
+
+ void set_pp_array_output(const PP_ArrayOutput& output) {
+ pp_array_output_ = output;
+ }
+
+ // Sets the array output back to its is_null() state.
+ void Reset();
+
+ // Copies the given vector of data to the plugin output array.
+ //
+ // Returns true on success, false if the plugin reported allocation failure.
+ // In either case, the object will become is_null() immediately after the
+ // call since one output function should only be issued once.
+ //
+ // THIS IS DESIGNED FOR POD ONLY. For the case of resources, for example, we
+ // want to transfer a reference only on success. Likewise, if you have a
+ // structure of PP_Vars or a struct that contains a PP_Resource, we need to
+ // make sure that the right thing happens with the ref on success and failure.
+ template<typename T>
+ bool StoreVector(const std::vector<T>& input) {
+ // Always call the alloc function, even on 0 array size.
+ void* dest = pp_array_output_.GetDataBuffer(
+ pp_array_output_.user_data,
+ static_cast<uint32_t>(input.size()),
+ sizeof(T));
+
+ // Regardless of success, we clear the output to prevent future calls on
+ // this same output object.
+ Reset();
+
+ if (input.empty())
+ return true; // Allow plugin to return NULL on 0 elements.
+ if (!dest)
+ return false;
+
+ memcpy(dest, &input[0], sizeof(T) * input.size());
+ return true;
+ }
+
+ // Stores the given vector of resources as PP_Resources to the output vector,
+ // adding one reference to each.
+ //
+ // On failure this returns false, nothing will be copied, and the resource
+ // refcounts will be unchanged. In either case, the object will become
+ // is_null() immediately after the call since one output function should only
+ // be issued once.
+ //
+ // Note: potentially this could be a template in case you have a vector of
+ // FileRef objects, for example. However, this saves code since there's only
+ // one instantiation and is sufficient for now.
+ bool StoreResourceVector(
+ const std::vector< scoped_refptr<Resource> >& input);
+
+ // Like the above version but takes an array of AddRed'ed PP_Resources. On
+ // storage failure, this will release each resource.
+ bool StoreResourceVector(const std::vector<PP_Resource>& input);
+
+ private:
+ PP_ArrayOutput pp_array_output_;
+
+ DISALLOW_COPY_AND_ASSIGN(ArrayWriter);
+};
+
+} // namespace ppapi
+
+#endif // PPAPI_SHARED_IMPL_ARRAY_WRITER_H_
diff --git a/ppapi/thunk/interfaces_ppb_public_dev.h b/ppapi/thunk/interfaces_ppb_public_dev.h
index 72de91e..0296a2d 100644
--- a/ppapi/thunk/interfaces_ppb_public_dev.h
+++ b/ppapi/thunk/interfaces_ppb_public_dev.h
@@ -41,6 +41,8 @@ UNPROXIED_IFACE(PPB_DirectoryReader, PPB_DIRECTORYREADER_DEV_INTERFACE_0_5,
UNPROXIED_IFACE(PPB_Find, PPB_FIND_DEV_INTERFACE_0_3, PPB_Find_Dev_0_3)
PROXIED_IFACE(PPB_FileChooser, PPB_FILECHOOSER_DEV_INTERFACE_0_5,
PPB_FileChooser_Dev_0_5)
+PROXIED_IFACE(PPB_FileChooser, PPB_FILECHOOSER_DEV_INTERFACE_0_6,
+ PPB_FileChooser_Dev_0_6)
PROXIED_IFACE(PPB_Instance, PPB_CHAR_SET_DEV_INTERFACE_0_4, PPB_CharSet_Dev_0_4)
PROXIED_IFACE(PPB_Instance, PPB_CONSOLE_DEV_INTERFACE_0_1, PPB_Console_Dev_0_1)
PROXIED_IFACE(PPB_Instance, PPB_URLUTIL_DEV_INTERFACE_0_6, PPB_URLUtil_Dev_0_6)
diff --git a/ppapi/thunk/ppb_file_chooser_api.h b/ppapi/thunk/ppb_file_chooser_api.h
index 494f7bd..ed94782 100644
--- a/ppapi/thunk/ppb_file_chooser_api.h
+++ b/ppapi/thunk/ppb_file_chooser_api.h
@@ -14,13 +14,24 @@ class PPB_FileChooser_API {
public:
virtual ~PPB_FileChooser_API() {}
- virtual int32_t Show(const PP_CompletionCallback& callback) = 0;
- virtual PP_Resource GetNextChosenFile() = 0;
+ virtual int32_t Show(const PP_ArrayOutput& output,
+ const PP_CompletionCallback& callback) = 0;
// Trusted API.
virtual int32_t ShowWithoutUserGesture(
- bool save_as,
- const char* suggested_file_name,
+ PP_Bool save_as,
+ PP_Var suggested_file_name,
+ const PP_ArrayOutput& output,
+ const PP_CompletionCallback& callback) = 0;
+
+ // Version 0.5 API.
+ virtual int32_t Show0_5(const PP_CompletionCallback& callback) = 0;
+ virtual PP_Resource GetNextChosenFile() = 0;
+
+ // Trusted version 0.5 API.
+ virtual int32_t ShowWithoutUserGesture0_5(
+ PP_Bool save_as,
+ PP_Var suggested_file_name,
const PP_CompletionCallback& callback) = 0;
};
diff --git a/ppapi/thunk/ppb_file_chooser_thunk.cc b/ppapi/thunk/ppb_file_chooser_thunk.cc
index b43b06a..4e590c7 100644
--- a/ppapi/thunk/ppb_file_chooser_thunk.cc
+++ b/ppapi/thunk/ppb_file_chooser_thunk.cc
@@ -34,53 +34,102 @@ PP_Bool IsFileChooser(PP_Resource resource) {
return PP_FromBool(enter.succeeded());
}
-int32_t Show(PP_Resource chooser, PP_CompletionCallback callback) {
+int32_t Show0_5(PP_Resource chooser, PP_CompletionCallback callback) {
EnterResource<PPB_FileChooser_API> enter(chooser, callback, true);
if (enter.failed())
return enter.retval();
- return enter.SetResult(enter.object()->Show(callback));
+ return enter.SetResult(enter.object()->Show0_5(callback));
}
-PP_Resource GetNextChosenFile(PP_Resource chooser) {
+PP_Resource GetNextChosenFile0_5(PP_Resource chooser) {
EnterResource<PPB_FileChooser_API> enter(chooser, true);
if (enter.failed())
return 0;
return enter.object()->GetNextChosenFile();
}
+int32_t Show(PP_Resource chooser,
+ PP_ArrayOutput output,
+ PP_CompletionCallback callback) {
+ EnterResource<PPB_FileChooser_API> enter(chooser, callback, true);
+ if (enter.failed())
+ return enter.retval();
+ return enter.SetResult(enter.object()->Show(output, callback));
+}
+
+
int32_t ShowWithoutUserGesture(PP_Resource chooser,
PP_Bool save_as,
PP_Var suggested_file_name,
+ const PP_ArrayOutput* output,
PP_CompletionCallback callback) {
EnterResource<PPB_FileChooser_API> enter(chooser, callback, true);
if (enter.failed())
return enter.retval();
- scoped_refptr<StringVar> string_var =
- StringVar::FromPPVar(suggested_file_name);
- std::string str = string_var ? string_var->value() : std::string();
return enter.SetResult(enter.object()->ShowWithoutUserGesture(
- save_as == PP_TRUE, str.c_str(), callback));
+ save_as, suggested_file_name, *output, callback));
}
-const PPB_FileChooser_Dev g_ppb_file_chooser_thunk = {
+int32_t ShowWithoutUserGesture0_5(PP_Resource chooser,
+ PP_Bool save_as,
+ PP_Var suggested_file_name,
+ PP_CompletionCallback callback) {
+ EnterResource<PPB_FileChooser_API> enter(chooser, callback, true);
+ if (enter.failed())
+ return enter.retval();
+ return enter.SetResult(enter.object()->ShowWithoutUserGesture0_5(
+ save_as, suggested_file_name, callback));
+}
+
+int32_t ShowWithoutUserGesture0_6(PP_Resource chooser,
+ PP_Bool save_as,
+ PP_Var suggested_file_name,
+ PP_ArrayOutput output,
+ PP_CompletionCallback callback) {
+ EnterResource<PPB_FileChooser_API> enter(chooser, callback, true);
+ if (enter.failed())
+ return enter.retval();
+ return enter.SetResult(enter.object()->ShowWithoutUserGesture(
+ save_as, suggested_file_name, output, callback));
+}
+
+const PPB_FileChooser_Dev_0_5 g_ppb_file_chooser_0_5_thunk = {
+ &Create,
+ &IsFileChooser,
+ &Show0_5,
+ &GetNextChosenFile0_5
+};
+
+const PPB_FileChooser_Dev_0_6 g_ppb_file_chooser_0_6_thunk = {
&Create,
&IsFileChooser,
- &Show,
- &GetNextChosenFile
+ &Show
+};
+
+const PPB_FileChooserTrusted_0_5 g_ppb_file_chooser_trusted_0_5_thunk = {
+ &ShowWithoutUserGesture0_5
};
-const PPB_FileChooserTrusted g_ppb_file_chooser_trusted_thunk = {
- &ShowWithoutUserGesture
+const PPB_FileChooserTrusted_0_6 g_ppb_file_chooser_trusted_0_6_thunk = {
+ &ShowWithoutUserGesture0_6
};
} // namespace
const PPB_FileChooser_Dev_0_5* GetPPB_FileChooser_Dev_0_5_Thunk() {
- return &g_ppb_file_chooser_thunk;
+ return &g_ppb_file_chooser_0_5_thunk;
+}
+
+const PPB_FileChooser_Dev_0_6* GetPPB_FileChooser_Dev_0_6_Thunk() {
+ return &g_ppb_file_chooser_0_6_thunk;
}
const PPB_FileChooserTrusted_0_5* GetPPB_FileChooser_Trusted_0_5_Thunk() {
- return &g_ppb_file_chooser_trusted_thunk;
+ return &g_ppb_file_chooser_trusted_0_5_thunk;
+}
+
+const PPB_FileChooserTrusted_0_6* GetPPB_FileChooser_Trusted_0_6_Thunk() {
+ return &g_ppb_file_chooser_trusted_0_6_thunk;
}
} // namespace thunk