summaryrefslogtreecommitdiffstats
path: root/ppapi/proxy
diff options
context:
space:
mode:
Diffstat (limited to 'ppapi/proxy')
-rw-r--r--ppapi/proxy/dispatcher.cc4
-rw-r--r--ppapi/proxy/host_dispatcher.cc47
-rw-r--r--ppapi/proxy/host_dispatcher.h12
-rw-r--r--ppapi/proxy/interface_id.h2
-rw-r--r--ppapi/proxy/plugin_resource.h2
-rw-r--r--ppapi/proxy/ppapi_messages_internal.h42
-rw-r--r--ppapi/proxy/ppapi_param_traits.cc29
-rw-r--r--ppapi/proxy/ppapi_param_traits.h9
-rw-r--r--ppapi/proxy/ppb_file_chooser_proxy.cc246
-rw-r--r--ppapi/proxy/ppb_file_chooser_proxy.h66
-rw-r--r--ppapi/proxy/ppb_file_ref_proxy.cc350
-rw-r--r--ppapi/proxy/ppb_file_ref_proxy.h86
-rw-r--r--ppapi/proxy/ppb_url_loader_proxy.cc5
-rw-r--r--ppapi/proxy/serialized_structs.cc5
-rw-r--r--ppapi/proxy/serialized_structs.h11
-rw-r--r--ppapi/proxy/serialized_var.cc15
-rw-r--r--ppapi/proxy/serialized_var.h15
17 files changed, 934 insertions, 12 deletions
diff --git a/ppapi/proxy/dispatcher.cc b/ppapi/proxy/dispatcher.cc
index 4dc97f2..2eca735 100644
--- a/ppapi/proxy/dispatcher.cc
+++ b/ppapi/proxy/dispatcher.cc
@@ -48,6 +48,8 @@
#include "ppapi/proxy/ppb_context_3d_proxy.h"
#include "ppapi/proxy/ppb_core_proxy.h"
#include "ppapi/proxy/ppb_cursor_control_proxy.h"
+#include "ppapi/proxy/ppb_file_chooser_proxy.h"
+#include "ppapi/proxy/ppb_file_ref_proxy.h"
#include "ppapi/proxy/ppb_flash_proxy.h"
#include "ppapi/proxy/ppb_flash_menu_proxy.h"
#include "ppapi/proxy/ppb_font_proxy.h"
@@ -103,6 +105,8 @@ InterfaceList::InterfaceList() {
AddPPB(PPB_Context3D_Proxy::GetInfo());
AddPPB(PPB_Core_Proxy::GetInfo());
AddPPB(PPB_CursorControl_Proxy::GetInfo());
+ AddPPB(PPB_FileChooser_Proxy::GetInfo());
+ AddPPB(PPB_FileRef_Proxy::GetInfo());
AddPPB(PPB_Flash_Proxy::GetInfo());
AddPPB(PPB_Flash_Menu_Proxy::GetInfo());
AddPPB(PPB_Font_Proxy::GetInfo());
diff --git a/ppapi/proxy/host_dispatcher.cc b/ppapi/proxy/host_dispatcher.cc
index 5572e91..aa972b5 100644
--- a/ppapi/proxy/host_dispatcher.cc
+++ b/ppapi/proxy/host_dispatcher.cc
@@ -94,17 +94,7 @@ bool HostDispatcher::OnMessageReceived(const IPC::Message& msg) {
if (!info ||
(info->is_trusted && disallow_trusted_interfaces()))
return true;
-
- const void* local_interface = GetLocalInterface(info->name);
- if (!local_interface) {
- // This should always succeed since the browser should support the stuff
- // the proxy does. If this happens, something is out of sync.
- NOTREACHED();
- return true;
- }
-
- proxy = info->create_proxy(this, local_interface);
- target_proxies_[info->id].reset(proxy);
+ proxy = CreatePPBInterfaceProxy(info);
}
return proxy->OnMessageReceived(msg);
@@ -142,6 +132,26 @@ const void* HostDispatcher::GetProxiedInterface(const std::string& interface) {
return NULL;
}
+InterfaceProxy* HostDispatcher::GetOrCreatePPBInterfaceProxy(
+ InterfaceID id) {
+ InterfaceProxy* proxy = target_proxies_[id].get();
+ if (!proxy) {
+ const InterfaceProxy::Info* info = GetPPBInterfaceInfo(id);
+ if (!info)
+ return NULL;
+
+ // Sanity check. This function won't normally be called for trusted
+ // interfaces, but in case somebody does this, we don't want to then give
+ // the plugin the ability to call that trusted interface (since the
+ // checking occurs at proxy-creation time).
+ if (info->is_trusted && disallow_trusted_interfaces())
+ return NULL;
+
+ proxy = CreatePPBInterfaceProxy(info);
+ }
+ return proxy;
+}
+
const PPB_Proxy_Private* HostDispatcher::GetPPBProxy() {
if (!ppb_proxy_) {
ppb_proxy_ = reinterpret_cast<const PPB_Proxy_Private*>(
@@ -150,6 +160,21 @@ const PPB_Proxy_Private* HostDispatcher::GetPPBProxy() {
return ppb_proxy_;
}
+InterfaceProxy* HostDispatcher::CreatePPBInterfaceProxy(
+ const InterfaceProxy::Info* info) {
+ const void* local_interface = GetLocalInterface(info->name);
+ if (!local_interface) {
+ // This should always succeed since the browser should support the stuff
+ // the proxy does. If this happens, something is out of sync.
+ NOTREACHED();
+ return NULL;
+ }
+
+ InterfaceProxy* proxy = info->create_proxy(this, local_interface);
+ target_proxies_[info->id].reset(proxy);
+ return proxy;
+}
+
} // namespace proxy
} // namespace pp
diff --git a/ppapi/proxy/host_dispatcher.h b/ppapi/proxy/host_dispatcher.h
index 5153f19..35cdece 100644
--- a/ppapi/proxy/host_dispatcher.h
+++ b/ppapi/proxy/host_dispatcher.h
@@ -70,12 +70,24 @@ class HostDispatcher : public Dispatcher {
// given interface isn't supported by the plugin or the proxy.
const void* GetProxiedInterface(const std::string& interface);
+ // Returns the proxy object associated with the given interface ID, creating
+ // it if necessary. This is used in cases where a proxy needs to access code
+ // in the proxy for another interface. It's assumed that the interface always
+ // exists, so this is only used for browser proxies.
+ //
+ // Will return NULL if an interface isn't supported.
+ InterfaceProxy* GetOrCreatePPBInterfaceProxy(InterfaceID id);
+
// Returns the proxy interface for talking to the implementation.
const PPB_Proxy_Private* GetPPBProxy();
private:
friend class HostDispatcherTest;
+ // Makes an instance of the given PPB interface proxy, storing it in the
+ // target_proxies_ array. An proxy for this interface must not exist yet.
+ InterfaceProxy* CreatePPBInterfaceProxy(const InterfaceProxy::Info* info);
+
PP_Module pp_module_;
enum PluginInterfaceSupport {
diff --git a/ppapi/proxy/interface_id.h b/ppapi/proxy/interface_id.h
index 4d38648..d3da24e 100644
--- a/ppapi/proxy/interface_id.h
+++ b/ppapi/proxy/interface_id.h
@@ -20,6 +20,8 @@ enum InterfaceID {
INTERFACE_ID_PPB_CONTEXT_3D,
INTERFACE_ID_PPB_CORE,
INTERFACE_ID_PPB_CURSORCONTROL,
+ INTERFACE_ID_PPB_FILE_CHOOSER,
+ INTERFACE_ID_PPB_FILE_REF,
INTERFACE_ID_PPB_FLASH,
INTERFACE_ID_PPB_FLASH_MENU,
INTERFACE_ID_PPB_FONT,
diff --git a/ppapi/proxy/plugin_resource.h b/ppapi/proxy/plugin_resource.h
index 115fc66..92b1b8c 100644
--- a/ppapi/proxy/plugin_resource.h
+++ b/ppapi/proxy/plugin_resource.h
@@ -17,6 +17,8 @@
F(AudioConfig) \
F(Buffer) \
F(Context3D) \
+ F(FileChooser) \
+ F(FileRef) \
F(FlashMenu) \
F(Font) \
F(Graphics2D) \
diff --git a/ppapi/proxy/ppapi_messages_internal.h b/ppapi/proxy/ppapi_messages_internal.h
index f9e09a6..be671a2 100644
--- a/ppapi/proxy/ppapi_messages_internal.h
+++ b/ppapi/proxy/ppapi_messages_internal.h
@@ -46,6 +46,13 @@ IPC_MESSAGE_ROUTED5(PpapiMsg_PPBAudio_NotifyAudioStreamCreated,
base::SharedMemoryHandle /* handle */,
int32_t /* length */)
+// PPB_FileChooser.
+IPC_MESSAGE_ROUTED3(
+ PpapiMsg_PPBFileChooser_ChooseComplete,
+ pp::proxy::HostResource /* chooser */,
+ int32_t /* result_code (will be != PP_OK on failure */,
+ std::vector<pp::proxy::PPBFileRef_CreateInfo> /* chosen_files */)
+
// PPB_Graphics2D.
IPC_MESSAGE_ROUTED2(PpapiMsg_PPBGraphics2D_FlushACK,
pp::proxy::HostResource /* graphics_2d */,
@@ -276,6 +283,41 @@ IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBCursorControl_CanLockCursor,
PP_Instance /* instance */,
PP_Bool /* result */)
+// PPB_FileChooser.
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBFileChooser_Create,
+ PP_Instance /* instance */,
+ int /* mode */,
+ std::string /* accept_mime_types */,
+ pp::proxy::HostResource /* result */)
+IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBFileChooser_Show,
+ pp::proxy::HostResource /* file_chooser */)
+
+
+// PPB_FileRef.
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBFileRef_Create,
+ pp::proxy::HostResource /* file_system */,
+ std::string /* path */,
+ pp::proxy::PPBFileRef_CreateInfo /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFileRef_GetParent,
+ pp::proxy::HostResource /* file_ref */,
+ pp::proxy::PPBFileRef_CreateInfo /* result */)
+IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBFileRef_MakeDirectory,
+ pp::proxy::HostResource /* file_ref */,
+ PP_Bool /* make_ancestors */,
+ uint32_t /* serialized_callback */);
+IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBFileRef_Touch,
+ pp::proxy::HostResource /* file_ref */,
+ PP_Time /* last_access */,
+ PP_Time /* last_modified */,
+ uint32_t /* serialized_callback */);
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBFileRef_Delete,
+ pp::proxy::HostResource /* file_ref */,
+ uint32_t /* serialized_callback */);
+IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBFileRef_Rename,
+ pp::proxy::HostResource /* file_ref */,
+ pp::proxy::HostResource /* new_file_ref */,
+ uint32_t /* serialized_callback */);
+
// PPB_Flash.
IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBFlash_SetInstanceAlwaysOnTop,
PP_Instance /* instance */,
diff --git a/ppapi/proxy/ppapi_param_traits.cc b/ppapi/proxy/ppapi_param_traits.cc
index b3611f4..d522a37 100644
--- a/ppapi/proxy/ppapi_param_traits.cc
+++ b/ppapi/proxy/ppapi_param_traits.cc
@@ -241,6 +241,35 @@ void ParamTraits<pp::proxy::PPBFlash_DrawGlyphs_Params>::Log(
std::string* l) {
}
+// PPBFileRef_CreateInfo -------------------------------------------------------
+
+// static
+void ParamTraits<pp::proxy::PPBFileRef_CreateInfo>::Write(
+ Message* m,
+ const param_type& p) {
+ ParamTraits<pp::proxy::HostResource>::Write(m, p.resource);
+ ParamTraits<int>::Write(m, p.file_system_type);
+ ParamTraits<pp::proxy::SerializedVar>::Write(m, p.path);
+ ParamTraits<pp::proxy::SerializedVar>::Write(m, p.name);
+}
+
+// static
+bool ParamTraits<pp::proxy::PPBFileRef_CreateInfo>::Read(const Message* m,
+ void** iter,
+ param_type* r) {
+ return
+ ParamTraits<pp::proxy::HostResource>::Read(m, iter, &r->resource) &&
+ ParamTraits<int>::Read(m, iter, &r->file_system_type) &&
+ ParamTraits<pp::proxy::SerializedVar>::Read(m, iter, &r->path) &&
+ ParamTraits<pp::proxy::SerializedVar>::Read(m, iter, &r->name);
+}
+
+// static
+void ParamTraits<pp::proxy::PPBFileRef_CreateInfo>::Log(
+ const param_type& p,
+ std::string* l) {
+}
+
// PPBFont_DrawTextAt_Params ---------------------------------------------------
// static
diff --git a/ppapi/proxy/ppapi_param_traits.h b/ppapi/proxy/ppapi_param_traits.h
index 83b4342..b4fdfca 100644
--- a/ppapi/proxy/ppapi_param_traits.h
+++ b/ppapi/proxy/ppapi_param_traits.h
@@ -20,6 +20,7 @@ namespace pp {
namespace proxy {
class HostResource;
+struct PPBFileRef_CreateInfo;
struct PPBFlash_DrawGlyphs_Params;
struct PPBFont_DrawTextAt_Params;
struct PPBURLLoader_UpdateProgress_Params;
@@ -98,6 +99,14 @@ struct ParamTraits<pp::proxy::PPBFlash_DrawGlyphs_Params> {
};
template<>
+struct ParamTraits<pp::proxy::PPBFileRef_CreateInfo> {
+ typedef pp::proxy::PPBFileRef_CreateInfo param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
struct ParamTraits<pp::proxy::PPBFont_DrawTextAt_Params> {
typedef pp::proxy::PPBFont_DrawTextAt_Params param_type;
static void Write(Message* m, const param_type& p);
diff --git a/ppapi/proxy/ppb_file_chooser_proxy.cc b/ppapi/proxy/ppb_file_chooser_proxy.cc
new file mode 100644
index 0000000..a50908c4
--- /dev/null
+++ b/ppapi/proxy/ppb_file_chooser_proxy.cc
@@ -0,0 +1,246 @@
+// Copyright (c) 2011 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/ppb_file_chooser_proxy.h"
+
+#include <queue>
+
+#include "ppapi/c/dev/ppb_file_chooser_dev.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/private/ppb_proxy_private.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_file_ref_proxy.h"
+#include "ppapi/proxy/serialized_var.h"
+
+namespace pp {
+namespace proxy {
+
+class FileChooser : public PluginResource {
+ public:
+ FileChooser(const HostResource& resource);
+ virtual ~FileChooser();
+
+ virtual FileChooser* AsFileChooser();
+
+ PP_CompletionCallback 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.
+ std::queue<PP_Resource> file_queue_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FileChooser);
+};
+
+FileChooser::FileChooser(const HostResource& resource)
+ : PluginResource(resource),
+ current_show_callback_(PP_MakeCompletionCallback(NULL, NULL)) {
+}
+
+FileChooser::~FileChooser() {
+ // Always need to fire completion callbacks to prevent a leak in the plugin.
+ if (current_show_callback_.func)
+ PP_RunCompletionCallback(&current_show_callback_, PP_ERROR_ABORTED);
+
+ // Any existing files we haven't transferred ownership to the plugin need
+ // to be freed.
+ PluginResourceTracker* tracker = PluginResourceTracker::GetInstance();
+ while (!file_queue_.empty()) {
+ tracker->ReleaseResource(file_queue_.front());
+ file_queue_.pop();
+ }
+}
+
+FileChooser* FileChooser::AsFileChooser() {
+ return this;
+}
+
+namespace {
+
+PP_Resource Create(PP_Instance instance,
+ const PP_FileChooserOptions_Dev* options) {
+ Dispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+
+ HostResource result;
+ dispatcher->Send(new PpapiHostMsg_PPBFileChooser_Create(
+ INTERFACE_ID_PPB_FILE_CHOOSER, instance,
+ options->mode, options->accept_mime_types, &result));
+
+ if (result.is_null())
+ return 0;
+ linked_ptr<FileChooser> object(new FileChooser(result));
+ return PluginResourceTracker::GetInstance()->AddResource(object);
+}
+
+PP_Bool IsFileChooser(PP_Resource resource) {
+ FileChooser* object = PluginResource::GetAs<FileChooser>(resource);
+ return BoolToPPBool(!!object);
+}
+
+int32_t Show(PP_Resource chooser, struct PP_CompletionCallback callback) {
+ FileChooser* object = PluginResource::GetAs<FileChooser>(chooser);
+ if (!object)
+ return PP_ERROR_BADRESOURCE;
+ Dispatcher* dispatcher = PluginDispatcher::GetForInstance(object->instance());
+ if (!dispatcher)
+ return PP_ERROR_BADARGUMENT;
+
+ if (object->current_show_callback_.func)
+ return PP_ERROR_INPROGRESS; // Can't show more than once.
+
+ object->current_show_callback_ = callback;
+ dispatcher->Send(new PpapiHostMsg_PPBFileChooser_Show(
+ INTERFACE_ID_PPB_FILE_CHOOSER,
+ object->host_resource()));
+ return PP_ERROR_WOULDBLOCK;
+}
+
+PP_Resource GetNextChosenFile(PP_Resource chooser) {
+ FileChooser* object = PluginResource::GetAs<FileChooser>(chooser);
+ if (!object || object->file_queue_.empty())
+ return 0;
+
+ // Return the next resource in the queue. These resource have already been
+ // addrefed (they're currently owned by the FileChooser) and returning them
+ // transfers ownership of that reference to the plugin.
+ PP_Resource next = object->file_queue_.front();
+ object->file_queue_.pop();
+ return next;
+}
+
+const PPB_FileChooser_Dev file_chooser_interface = {
+ &Create,
+ &IsFileChooser,
+ &Show,
+ &GetNextChosenFile
+};
+
+InterfaceProxy* CreateFileChooserProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_FileChooser_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_FileChooser_Proxy::PPB_FileChooser_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface),
+ callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+}
+
+PPB_FileChooser_Proxy::~PPB_FileChooser_Proxy() {
+}
+
+const InterfaceProxy::Info* PPB_FileChooser_Proxy::GetInfo() {
+ static const Info info = {
+ &file_chooser_interface,
+ PPB_FILECHOOSER_DEV_INTERFACE,
+ INTERFACE_ID_PPB_FILE_CHOOSER,
+ false,
+ &CreateFileChooserProxy,
+ };
+ return &info;
+}
+
+bool PPB_FileChooser_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_FileChooser_Proxy, msg)
+ // Plugin -> host messages.
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileChooser_Create, OnMsgCreate)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileChooser_Show, OnMsgShow)
+
+ // Host -> plugin messages.
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileChooser_ChooseComplete,
+ OnMsgChooseComplete)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPB_FileChooser_Proxy::OnMsgCreate(PP_Instance instance,
+ int mode,
+ const std::string& accept_mime_types,
+ HostResource* result) {
+ PP_FileChooserOptions_Dev options;
+ options.mode = static_cast<PP_FileChooserMode_Dev>(mode);
+ options.accept_mime_types = accept_mime_types.c_str();
+ result->SetHostResource(
+ instance, ppb_file_chooser_target()->Create(instance, &options));
+}
+
+void PPB_FileChooser_Proxy::OnMsgShow(const HostResource& chooser) {
+ CompletionCallback callback = callback_factory_.NewCallback(
+ &PPB_FileChooser_Proxy::OnShowCallback, chooser);
+
+ int32_t result = ppb_file_chooser_target()->Show(
+ chooser.host_resource(), callback.pp_completion_callback());
+ if (result != PP_ERROR_WOULDBLOCK)
+ callback.Run(result);
+}
+
+void PPB_FileChooser_Proxy::OnMsgChooseComplete(
+ const HostResource& chooser,
+ int32_t result_code,
+ const std::vector<PPBFileRef_CreateInfo>& chosen_files) {
+ PP_Resource plugin_resource =
+ PluginResourceTracker::GetInstance()->PluginResourceForHostResource(
+ chooser);
+ if (!plugin_resource)
+ return;
+ FileChooser* object = PluginResource::GetAs<FileChooser>(plugin_resource);
+ if (!object)
+ return;
+
+ // 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(object->file_queue_.empty());
+ for (size_t i = 0; i < chosen_files.size(); i++) {
+ object->file_queue_.push(
+ PPB_FileRef_Proxy::DeserializeFileRef(chosen_files[i]));
+ }
+
+ // Notify the plugin of the new data. We have to swap out the callback
+ // because the plugin may trigger deleting the object from the callback, and
+ // the FileChooser object will attempt to call the callback in its destructor
+ // with the ABORTED status.
+ PP_CompletionCallback callback = object->current_show_callback_;
+ object->current_show_callback_ = PP_MakeCompletionCallback(NULL, NULL);
+ PP_RunCompletionCallback(&callback, result_code);
+ // DANGER: May delete |object|!
+}
+
+void PPB_FileChooser_Proxy::OnShowCallback(int32_t result,
+ const HostResource& chooser) {
+ std::vector<PPBFileRef_CreateInfo> files;
+ if (result == PP_OK) {
+ // Jump through some hoops to get the FileRef proxy. Since we know we're
+ // in the host at this point, we can ask the host dispatcher for it.
+ DCHECK(!dispatcher()->IsPlugin());
+ HostDispatcher* host_disp = static_cast<HostDispatcher*>(dispatcher());
+ PPB_FileRef_Proxy* file_ref_proxy = static_cast<PPB_FileRef_Proxy*>(
+ host_disp->GetOrCreatePPBInterfaceProxy(INTERFACE_ID_PPB_FILE_REF));
+
+ // Convert the returned files to the serialized info.
+ while (PP_Resource cur_file_resource =
+ ppb_file_chooser_target()->GetNextChosenFile(
+ chooser.host_resource())) {
+ PPBFileRef_CreateInfo cur_create_info;
+ file_ref_proxy->SerializeFileRef(cur_file_resource, &cur_create_info);
+ files.push_back(cur_create_info);
+ }
+ }
+
+ dispatcher()->Send(new PpapiMsg_PPBFileChooser_ChooseComplete(
+ INTERFACE_ID_PPB_FILE_CHOOSER, chooser, result, files));
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_file_chooser_proxy.h b/ppapi/proxy/ppb_file_chooser_proxy.h
new file mode 100644
index 0000000..97b3aa2
--- /dev/null
+++ b/ppapi/proxy/ppb_file_chooser_proxy.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2011 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_PPB_FILE_CHOOSER_PROXY_H_
+#define PPAPI_PROXY_PPB_FILE_CHOOSER_PROXY_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/cpp/completion_callback.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h"
+
+struct PPB_FileChooser_Dev;
+
+namespace pp {
+namespace proxy {
+
+class HostResource;
+struct PPBFileRef_CreateInfo;
+
+class PPB_FileChooser_Proxy : public InterfaceProxy {
+ public:
+ PPB_FileChooser_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_FileChooser_Proxy();
+
+ static const Info* GetInfo();
+
+ const PPB_FileChooser_Dev* ppb_file_chooser_target() const {
+ return static_cast<const PPB_FileChooser_Dev*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Plugin -> host message handlers.
+ void OnMsgCreate(PP_Instance instance,
+ int mode,
+ const std::string& accept_mime_types,
+ pp::proxy::HostResource* result);
+ void OnMsgShow(const pp::proxy::HostResource& chooser);
+
+ // Host -> plugin message handlers.
+ void OnMsgChooseComplete(
+ const pp::proxy::HostResource& chooser,
+ int32_t result_code,
+ const std::vector<PPBFileRef_CreateInfo>& chosen_files);
+
+ // 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 HostResource& chooser);
+
+ CompletionCallbackFactory<PPB_FileChooser_Proxy,
+ ProxyNonThreadSafeRefCount> callback_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_FileChooser_Proxy);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_FILE_CHOOSER_PROXY_H_
diff --git a/ppapi/proxy/ppb_file_ref_proxy.cc b/ppapi/proxy/ppb_file_ref_proxy.cc
new file mode 100644
index 0000000..85b133e
--- /dev/null
+++ b/ppapi/proxy/ppb_file_ref_proxy.cc
@@ -0,0 +1,350 @@
+// Copyright (c) 2011 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/ppb_file_ref_proxy.h"
+
+#include "ppapi/c/dev/ppb_file_ref_dev.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/private/ppb_proxy_private.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/serialized_var.h"
+
+namespace pp {
+namespace proxy {
+
+// This object maintains most of the state of the ref in the plugin for fast
+// querying. It's all set in the constructor from the "create info" sent from
+// the host.
+class FileRef : public PluginResource {
+ public:
+ FileRef(const PPBFileRef_CreateInfo& info);
+ virtual ~FileRef();
+
+ virtual FileRef* AsFileRef();
+
+ PP_FileSystemType_Dev file_system_type() const { return file_system_type_; }
+ const PP_Var& path() const { return path_; }
+ const PP_Var& name() const { return name_; }
+
+ private:
+ PP_FileSystemType_Dev file_system_type_;
+ PP_Var path_;
+ PP_Var name_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileRef);
+};
+
+FileRef::FileRef(const PPBFileRef_CreateInfo& info)
+ : PluginResource(info.resource) {
+ Dispatcher* dispatcher = PluginDispatcher::GetForInstance(instance());
+
+ file_system_type_ = static_cast<PP_FileSystemType_Dev>(info.file_system_type);
+
+ name_ = ReceiveSerializedVarReturnValue(info.name).Return(dispatcher);
+ path_ = ReceiveSerializedVarReturnValue(info.path).Return(dispatcher);
+}
+
+FileRef::~FileRef() {
+ PluginVarTracker::GetInstance()->Release(path_);
+ PluginVarTracker::GetInstance()->Release(name_);
+}
+
+FileRef* FileRef::AsFileRef() {
+ return this;
+}
+
+namespace {
+
+bool FileRefAndDispatcherForResource(PP_Resource resource,
+ FileRef** file_ref,
+ Dispatcher** dispatcher) {
+ *file_ref = PluginResource::GetAs<FileRef>(resource);
+ if (!file_ref)
+ return false;
+ *dispatcher = PluginDispatcher::GetForInstance((*file_ref)->instance());
+ return !!(*dispatcher);
+}
+
+PP_Resource Create(PP_Resource file_system, const char* path) {
+ PluginResource* file_system_object =
+ PluginResourceTracker::GetInstance()->GetResourceObject(file_system);
+ if (!file_system_object)
+ return 0;
+
+ Dispatcher* dispatcher =
+ PluginDispatcher::GetForInstance(file_system_object->instance());
+ if (!dispatcher)
+ return 0;
+
+ PPBFileRef_CreateInfo create_info;
+ dispatcher->Send(new PpapiHostMsg_PPBFileRef_Create(
+ INTERFACE_ID_PPB_FILE_REF, file_system_object->host_resource(),
+ path, &create_info));
+ return PPB_FileRef_Proxy::DeserializeFileRef(create_info);
+}
+
+PP_Bool IsFileRef(PP_Resource resource) {
+ FileRef* object = PluginResource::GetAs<FileRef>(resource);
+ return BoolToPPBool(!!object);
+}
+
+PP_FileSystemType_Dev GetFileSystemType(PP_Resource file_ref) {
+ FileRef* object = PluginResource::GetAs<FileRef>(file_ref);
+ if (!object)
+ return PP_FILESYSTEMTYPE_EXTERNAL;
+ return object->file_system_type();
+}
+
+PP_Var GetName(PP_Resource file_ref) {
+ FileRef* object = PluginResource::GetAs<FileRef>(file_ref);
+ if (!object)
+ return PP_MakeUndefined();
+
+ PluginVarTracker::GetInstance()->AddRef(object->name());
+ return object->name();
+}
+
+PP_Var GetPath(PP_Resource file_ref) {
+ FileRef* object = PluginResource::GetAs<FileRef>(file_ref);
+ if (!object)
+ return PP_MakeUndefined();
+
+ PluginVarTracker::GetInstance()->AddRef(object->path());
+ return object->path();
+}
+
+PP_Resource GetParent(PP_Resource file_ref) {
+ FileRef* object;
+ Dispatcher* dispatcher;
+ if (!FileRefAndDispatcherForResource(file_ref, &object, &dispatcher))
+ return 0;
+
+ PPBFileRef_CreateInfo create_info;
+ dispatcher->Send(new PpapiHostMsg_PPBFileRef_GetParent(
+ INTERFACE_ID_PPB_FILE_REF, object->host_resource(), &create_info));
+ return PPB_FileRef_Proxy::DeserializeFileRef(create_info);
+}
+
+int32_t MakeDirectory(PP_Resource directory_ref,
+ PP_Bool make_ancestors,
+ struct PP_CompletionCallback callback) {
+ FileRef* object;
+ Dispatcher* dispatcher;
+ if (!FileRefAndDispatcherForResource(directory_ref, &object, &dispatcher))
+ return PP_ERROR_BADRESOURCE;
+
+ dispatcher->Send(new PpapiHostMsg_PPBFileRef_MakeDirectory(
+ INTERFACE_ID_PPB_FILE_REF, object->host_resource(), make_ancestors,
+ dispatcher->callback_tracker().SendCallback(callback)));
+ return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t Touch(PP_Resource file_ref,
+ PP_Time last_access_time,
+ PP_Time last_modified_time,
+ struct PP_CompletionCallback callback) {
+ FileRef* object;
+ Dispatcher* dispatcher;
+ if (!FileRefAndDispatcherForResource(file_ref, &object, &dispatcher))
+ return PP_ERROR_BADRESOURCE;
+
+ dispatcher->Send(new PpapiHostMsg_PPBFileRef_Touch(
+ INTERFACE_ID_PPB_FILE_REF, object->host_resource(),
+ last_access_time, last_modified_time,
+ dispatcher->callback_tracker().SendCallback(callback)));
+ return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t Delete(PP_Resource file_ref,
+ struct PP_CompletionCallback callback) {
+ FileRef* object;
+ Dispatcher* dispatcher;
+ if (!FileRefAndDispatcherForResource(file_ref, &object, &dispatcher))
+ return PP_ERROR_BADRESOURCE;
+
+ dispatcher->Send(new PpapiHostMsg_PPBFileRef_Delete(
+ INTERFACE_ID_PPB_FILE_REF, object->host_resource(),
+ dispatcher->callback_tracker().SendCallback(callback)));
+ return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t Rename(PP_Resource file_ref,
+ PP_Resource new_file_ref,
+ struct PP_CompletionCallback callback) {
+ FileRef* obj1;
+ Dispatcher* dispatcher1;
+ if (!FileRefAndDispatcherForResource(file_ref, &obj1, &dispatcher1))
+ return PP_ERROR_BADRESOURCE;
+
+ FileRef* obj2;
+ Dispatcher* dispatcher2;
+ if (!FileRefAndDispatcherForResource(new_file_ref, &obj2, &dispatcher2))
+ return PP_ERROR_BADRESOURCE;
+
+ if (obj1->instance() != obj2->instance())
+ return PP_ERROR_BADRESOURCE;
+
+ dispatcher1->Send(new PpapiHostMsg_PPBFileRef_Rename(
+ INTERFACE_ID_PPB_FILE_REF, obj1->host_resource(),
+ obj2->host_resource(),
+ dispatcher1->callback_tracker().SendCallback(callback)));
+ return PP_ERROR_WOULDBLOCK;
+}
+
+const PPB_FileRef_Dev file_ref_interface = {
+ &Create,
+ &IsFileRef,
+ &GetFileSystemType,
+ &GetName,
+ &GetPath,
+ &GetParent,
+ &MakeDirectory,
+ &Touch,
+ &Delete,
+ &Rename
+};
+
+InterfaceProxy* CreateFileRefProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_FileRef_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_FileRef_Proxy::PPB_FileRef_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_FileRef_Proxy::~PPB_FileRef_Proxy() {
+}
+
+const InterfaceProxy::Info* PPB_FileRef_Proxy::GetInfo() {
+ static const Info info = {
+ &file_ref_interface,
+ PPB_FILEREF_DEV_INTERFACE,
+ INTERFACE_ID_PPB_FILE_REF,
+ false,
+ &CreateFileRefProxy,
+ };
+ return &info;
+}
+
+bool PPB_FileRef_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_FileRef_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Create, OnMsgCreate)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_GetParent, OnMsgGetParent)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_MakeDirectory,
+ OnMsgMakeDirectory)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Touch, OnMsgTouch)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Delete, OnMsgDelete)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Rename, OnMsgRename)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPB_FileRef_Proxy::SerializeFileRef(PP_Resource file_ref,
+ PPBFileRef_CreateInfo* result) {
+ // We need the instance out of the resource for serializing back to the
+ // plugin. This code can only run in the host.
+ if (dispatcher()->IsPlugin()) {
+ NOTREACHED();
+ return;
+ }
+ HostDispatcher* host_dispatcher = static_cast<HostDispatcher*>(dispatcher());
+ PP_Instance instance =
+ host_dispatcher->GetPPBProxy()->GetInstanceForResource(file_ref);
+
+ result->resource.SetHostResource(instance, file_ref);
+ result->file_system_type =
+ static_cast<int>(ppb_file_ref_target()->GetFileSystemType(file_ref));
+ result->path = SerializedVarReturnValue::Convert(
+ dispatcher(),
+ ppb_file_ref_target()->GetPath(file_ref));
+ result->name = SerializedVarReturnValue::Convert(
+ dispatcher(),
+ ppb_file_ref_target()->GetName(file_ref));
+}
+
+// static
+PP_Resource PPB_FileRef_Proxy::DeserializeFileRef(
+ const PPBFileRef_CreateInfo& serialized) {
+ if (serialized.resource.is_null())
+ return 0; // Resource invalid.
+
+ linked_ptr<FileRef> object(new FileRef(serialized));
+ return PluginResourceTracker::GetInstance()->AddResource(object);
+}
+
+void PPB_FileRef_Proxy::OnMsgCreate(const HostResource& file_system,
+ const std::string& path,
+ PPBFileRef_CreateInfo* result) {
+
+ PP_Resource resource = ppb_file_ref_target()->Create(
+ file_system.host_resource(), path.c_str());
+ if (!resource)
+ return; // CreateInfo default constructor initializes to 0.
+ SerializeFileRef(resource, result);
+}
+
+void PPB_FileRef_Proxy::OnMsgGetParent(const HostResource& host_resource,
+ PPBFileRef_CreateInfo* result) {
+ PP_Resource resource = ppb_file_ref_target()->GetParent(
+ host_resource.host_resource());
+ if (!resource)
+ return; // CreateInfo default constructor initializes to 0.
+ SerializeFileRef(resource, result);
+}
+
+void PPB_FileRef_Proxy::OnMsgMakeDirectory(const HostResource& host_resource,
+ PP_Bool make_ancestors,
+ uint32_t serialized_callback) {
+ PP_CompletionCallback callback = ReceiveCallback(serialized_callback);
+ int32_t result =
+ ppb_file_ref_target()->MakeDirectory(host_resource.host_resource(),
+ make_ancestors, callback);
+ if (result != PP_ERROR_WOULDBLOCK)
+ PP_RunCompletionCallback(&callback, result);
+}
+
+void PPB_FileRef_Proxy::OnMsgTouch(const HostResource& host_resource,
+ PP_Time last_access,
+ PP_Time last_modified,
+ uint32_t serialized_callback) {
+ PP_CompletionCallback callback = ReceiveCallback(serialized_callback);
+ int32_t result =
+ ppb_file_ref_target()->Touch(host_resource.host_resource(),
+ last_access, last_modified, callback);
+ if (result != PP_ERROR_WOULDBLOCK)
+ PP_RunCompletionCallback(&callback, result);
+}
+
+void PPB_FileRef_Proxy::OnMsgDelete(const HostResource& host_resource,
+ uint32_t serialized_callback) {
+ PP_CompletionCallback callback = ReceiveCallback(serialized_callback);
+ int32_t result =
+ ppb_file_ref_target()->Delete(host_resource.host_resource(), callback);
+ if (result != PP_ERROR_WOULDBLOCK)
+ PP_RunCompletionCallback(&callback, result);
+}
+
+void PPB_FileRef_Proxy::OnMsgRename(const HostResource& file_ref,
+ const HostResource& new_file_ref,
+ uint32_t serialized_callback) {
+ PP_CompletionCallback callback = ReceiveCallback(serialized_callback);
+ int32_t result =
+ ppb_file_ref_target()->Rename(file_ref.host_resource(),
+ new_file_ref.host_resource(),
+ callback);
+ if (result != PP_ERROR_WOULDBLOCK)
+ PP_RunCompletionCallback(&callback, result);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_file_ref_proxy.h b/ppapi/proxy/ppb_file_ref_proxy.h
new file mode 100644
index 0000000..ca0b588
--- /dev/null
+++ b/ppapi/proxy/ppb_file_ref_proxy.h
@@ -0,0 +1,86 @@
+// Copyright (c) 2011 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_PPB_FILE_REF_PROXY_H_
+#define PPAPI_PROXY_PPB_FILE_REF_PROXY_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_time.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_FileRef_Dev;
+
+namespace pp {
+namespace proxy {
+
+class HostResource;
+struct PPBFileRef_CreateInfo;
+
+class PPB_FileRef_Proxy : public InterfaceProxy {
+ public:
+ PPB_FileRef_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_FileRef_Proxy();
+
+ static const Info* GetInfo();
+
+ const PPB_FileRef_Dev* ppb_file_ref_target() const {
+ return static_cast<const PPB_FileRef_Dev*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ // Takes a resource in the host and converts it into a serialized file ref
+ // "create info" for reconstitution in the plugin. This struct contains all
+ // the necessary information about the file ref.
+ //
+ // This function is not static because it needs access to the particular
+ // dispatcher and host interface.
+ //
+ // Various PPAPI functions return file refs from various interfaces, so this
+ // function is public so anybody can send a file ref.
+ void SerializeFileRef(PP_Resource file_ref,
+ PPBFileRef_CreateInfo* result);
+
+ // Creates a plugin resource from the given CreateInfo sent from the host.
+ // The value will be the result of calling SerializeFileRef on the host.
+ // This represents passing the resource ownership to the plugin. This
+ // function also checks the validity of the result and returns 0 on failure.
+ //
+ // Various PPAPI functions return file refs from various interfaces, so this
+ // function is public so anybody can receive a file ref.
+ static PP_Resource DeserializeFileRef(
+ const PPBFileRef_CreateInfo& serialized);
+
+ private:
+ // Message handlers.
+ void OnMsgCreate(const HostResource& file_system,
+ const std::string& path,
+ PPBFileRef_CreateInfo* result);
+ void OnMsgGetParent(const HostResource& host_resource,
+ PPBFileRef_CreateInfo* result);
+ void OnMsgMakeDirectory(const HostResource& host_resource,
+ PP_Bool make_ancestors,
+ uint32_t serialized_callback);
+ void OnMsgTouch(const HostResource& host_resource,
+ PP_Time last_access,
+ PP_Time last_modified,
+ uint32_t serialized_callback);
+ void OnMsgDelete(const HostResource& host_resource,
+ uint32_t serialized_callback);
+ void OnMsgRename(const HostResource& file_ref,
+ const HostResource& new_file_ref,
+ uint32_t serialized_callback);
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_FileRef_Proxy);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_FILE_REF_PROXY_H_
diff --git a/ppapi/proxy/ppb_url_loader_proxy.cc b/ppapi/proxy/ppb_url_loader_proxy.cc
index a021eff..76e3a35 100644
--- a/ppapi/proxy/ppb_url_loader_proxy.cc
+++ b/ppapi/proxy/ppb_url_loader_proxy.cc
@@ -69,6 +69,10 @@ URLLoader::URLLoader(const HostResource& resource)
}
URLLoader::~URLLoader() {
+ // Always need to fire completion callbacks to prevent a leak in the plugin.
+ if (current_read_callback_.func)
+ PP_RunCompletionCallback(&current_read_callback_, PP_ERROR_ABORTED);
+
if (response_info_)
PluginResourceTracker::GetInstance()->ReleaseResource(response_info_);
}
@@ -365,6 +369,7 @@ void PPB_URLLoader_Proxy::OnMsgOpen(const HostResource& loader,
loader.host_resource(), request_info.host_resource(), callback);
if (result != PP_ERROR_WOULDBLOCK)
PP_RunCompletionCallback(&callback, result);
+ // TODO(brettw) bug 73236 register for the status callbacks.
}
void PPB_URLLoader_Proxy::OnMsgFollowRedirect(
diff --git a/ppapi/proxy/serialized_structs.cc b/ppapi/proxy/serialized_structs.cc
index 576e31a..1e9ded0 100644
--- a/ppapi/proxy/serialized_structs.cc
+++ b/ppapi/proxy/serialized_structs.cc
@@ -5,6 +5,7 @@
#include "ppapi/proxy/serialized_structs.h"
#include "ppapi/c/dev/ppb_font_dev.h"
+#include "ppapi/c/dev/pp_file_info_dev.h"
#include "ppapi/c/pp_rect.h"
namespace pp {
@@ -62,6 +63,10 @@ void SerializedFontDescription::SetToPPFontDescription(
desc->word_spacing = word_spacing;
}
+PPBFileRef_CreateInfo::PPBFileRef_CreateInfo()
+ : file_system_type(PP_FILESYSTEMTYPE_EXTERNAL) {
+}
+
PPBFlash_DrawGlyphs_Params::PPBFlash_DrawGlyphs_Params()
: instance(0),
font_desc(),
diff --git a/ppapi/proxy/serialized_structs.h b/ppapi/proxy/serialized_structs.h
index 8b40042..1482ab3 100644
--- a/ppapi/proxy/serialized_structs.h
+++ b/ppapi/proxy/serialized_structs.h
@@ -70,6 +70,17 @@ struct SerializedDirEntry {
bool is_dir;
};
+// FileRefs are created in a number of places and they include a number of
+// return values. This struct encapsulates everything in one place.
+struct PPBFileRef_CreateInfo {
+ PPBFileRef_CreateInfo(); // Initializes to 0.
+
+ HostResource resource;
+ int file_system_type; // One of PP_FileSystemType_Dev values.
+ SerializedVar path;
+ SerializedVar name;
+};
+
// Since there are so many parameters, DrawTextAt requires this separate
// structure. This includes everything but the font name. Because the font name
// is a var, it's much more convenient to use the normal way of passing a
diff --git a/ppapi/proxy/serialized_var.cc b/ppapi/proxy/serialized_var.cc
index a4888a0..e68c681 100644
--- a/ppapi/proxy/serialized_var.cc
+++ b/ppapi/proxy/serialized_var.cc
@@ -266,6 +266,11 @@ void SerializedVarSendInput::ConvertVector(Dispatcher* dispatcher,
ReceiveSerializedVarReturnValue::ReceiveSerializedVarReturnValue() {
}
+ReceiveSerializedVarReturnValue::ReceiveSerializedVarReturnValue(
+ const SerializedVar& serialized)
+ : SerializedVar(serialized) {
+}
+
PP_Var ReceiveSerializedVarReturnValue::Return(Dispatcher* dispatcher) {
inner_->set_serialization_rules(dispatcher->serialization_rules());
inner_->SetVar(inner_->serialization_rules()->ReceivePassRef(
@@ -421,6 +426,16 @@ void SerializedVarReturnValue::Return(Dispatcher* dispatcher,
serialized_->inner_->GetStringPtr()));
}
+// static
+SerializedVar SerializedVarReturnValue::Convert(Dispatcher* dispatcher,
+ const PP_Var& var) {
+ // Mimic what happens in the normal case.
+ SerializedVar result;
+ SerializedVarReturnValue retvalue(&result);
+ retvalue.Return(dispatcher, var);
+ return result;
+}
+
// SerializedVarOutParam -------------------------------------------------------
SerializedVarOutParam::SerializedVarOutParam(SerializedVar* serialized)
diff --git a/ppapi/proxy/serialized_var.h b/ppapi/proxy/serialized_var.h
index 75ef494..4d8d813 100644
--- a/ppapi/proxy/serialized_var.h
+++ b/ppapi/proxy/serialized_var.h
@@ -210,9 +210,17 @@ class SerializedVarSendInput : public SerializedVar {
class ReceiveSerializedVarReturnValue : public SerializedVar {
public:
// Note that we can't set the dispatcher in the constructor because the
- // data will be overridden when the return value is set.
+ // data will be overridden when the return value is set. This constructor is
+ // normally used in the pattern above (operator= will be implicitly invoked
+ // when the sync message writes the output values).
ReceiveSerializedVarReturnValue();
+ // This constructor can be used when deserializing manually. This is useful
+ // when you're getting strings "returned" via a struct and need to manually
+ // get the PP_Vars out. In this case just do:
+ // ReceiveSerializedVarReturnValue(serialized).Return(dispatcher);
+ explicit ReceiveSerializedVarReturnValue(const SerializedVar& serialized);
+
PP_Var Return(Dispatcher* dispatcher);
private:
@@ -355,6 +363,11 @@ class SerializedVarReturnValue {
void Return(Dispatcher* dispatcher, const PP_Var& var);
+ // Helper function for code that doesn't use the pattern above, but gets
+ // a return value from the remote side via a struct. You can pass in the
+ // SerializedVar and a PP_Var will be created with return value semantics.
+ static SerializedVar Convert(Dispatcher* dispatcher, const PP_Var& var);
+
private:
SerializedVar* serialized_;
};