summaryrefslogtreecommitdiffstats
path: root/ppapi/proxy
diff options
context:
space:
mode:
authorgrt@chromium.org <grt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-19 16:14:55 +0000
committergrt@chromium.org <grt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-19 16:14:55 +0000
commit1e78967ed2f1937b3809c19d91e7dd62d756d307 (patch)
tree054c19343eaced71ac5edf8d5425e83fb878ca0d /ppapi/proxy
parent5d4451ebf298d9d71f716cc0135f465cec41fcd0 (diff)
parentcd18d6f39a965004529d5800a7067a3d3b29a2ba (diff)
downloadchromium_src-1e78967ed2f1937b3809c19d91e7dd62d756d307.zip
chromium_src-1e78967ed2f1937b3809c19d91e7dd62d756d307.tar.gz
chromium_src-1e78967ed2f1937b3809c19d91e7dd62d756d307.tar.bz2
FileManagerDialogTest.SelectFileAndCancel flaky.
BUG=89733 TBR=robertshield@chromium.org TEST=browser_tests Review URL: http://codereview.chromium.org/7447001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93027 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/proxy')
-rw-r--r--ppapi/proxy/DEPS15
-rw-r--r--ppapi/proxy/OWNERS2
-rw-r--r--ppapi/proxy/broker_dispatcher.cc113
-rw-r--r--ppapi/proxy/broker_dispatcher.h64
-rw-r--r--ppapi/proxy/callback_tracker.cc72
-rw-r--r--ppapi/proxy/callback_tracker.h66
-rw-r--r--ppapi/proxy/dispatcher.cc272
-rw-r--r--ppapi/proxy/dispatcher.h124
-rw-r--r--ppapi/proxy/enter_proxy.h58
-rw-r--r--ppapi/proxy/host_dispatcher.cc274
-rw-r--r--ppapi/proxy/host_dispatcher.h161
-rw-r--r--ppapi/proxy/host_dispatcher_unittest.cc42
-rw-r--r--ppapi/proxy/host_resource.h70
-rw-r--r--ppapi/proxy/host_var_serialization_rules.cc96
-rw-r--r--ppapi/proxy/host_var_serialization_rules.h53
-rw-r--r--ppapi/proxy/interface_id.h71
-rw-r--r--ppapi/proxy/interface_proxy.cc36
-rw-r--r--ppapi/proxy/interface_proxy.h79
-rw-r--r--ppapi/proxy/mock_resource.cc22
-rw-r--r--ppapi/proxy/mock_resource.h29
-rw-r--r--ppapi/proxy/plugin_dispatcher.cc312
-rw-r--r--ppapi/proxy/plugin_dispatcher.h174
-rw-r--r--ppapi/proxy/plugin_dispatcher_unittest.cc89
-rw-r--r--ppapi/proxy/plugin_message_filter.cc61
-rw-r--r--ppapi/proxy/plugin_message_filter.h56
-rw-r--r--ppapi/proxy/plugin_resource.cc29
-rw-r--r--ppapi/proxy/plugin_resource.h97
-rw-r--r--ppapi/proxy/plugin_resource_tracker.cc183
-rw-r--r--ppapi/proxy/plugin_resource_tracker.h107
-rw-r--r--ppapi/proxy/plugin_resource_tracker_unittest.cc74
-rw-r--r--ppapi/proxy/plugin_var_serialization_rules.cc153
-rw-r--r--ppapi/proxy/plugin_var_serialization_rules.h46
-rw-r--r--ppapi/proxy/plugin_var_tracker.cc336
-rw-r--r--ppapi/proxy/plugin_var_tracker.h196
-rw-r--r--ppapi/proxy/plugin_var_tracker_unittest.cc189
-rw-r--r--ppapi/proxy/ppapi_messages.cc34
-rw-r--r--ppapi/proxy/ppapi_messages.h858
-rw-r--r--ppapi/proxy/ppapi_param_traits.cc510
-rw-r--r--ppapi/proxy/ppapi_param_traits.h162
-rw-r--r--ppapi/proxy/ppapi_proxy_test.cc376
-rw-r--r--ppapi/proxy/ppapi_proxy_test.h243
-rw-r--r--ppapi/proxy/ppb_audio_config_proxy.cc91
-rw-r--r--ppapi/proxy/ppb_audio_config_proxy.h42
-rw-r--r--ppapi/proxy/ppb_audio_proxy.cc318
-rw-r--r--ppapi/proxy/ppb_audio_proxy.h92
-rw-r--r--ppapi/proxy/ppb_broker_proxy.cc281
-rw-r--r--ppapi/proxy/ppb_broker_proxy.h56
-rw-r--r--ppapi/proxy/ppb_buffer_proxy.cc194
-rw-r--r--ppapi/proxy/ppb_buffer_proxy.h47
-rw-r--r--ppapi/proxy/ppb_char_set_proxy.cc112
-rw-r--r--ppapi/proxy/ppb_char_set_proxy.h61
-rw-r--r--ppapi/proxy/ppb_console_proxy.cc103
-rw-r--r--ppapi/proxy/ppb_console_proxy.h48
-rw-r--r--ppapi/proxy/ppb_context_3d_proxy.cc719
-rw-r--r--ppapi/proxy/ppb_context_3d_proxy.h144
-rw-r--r--ppapi/proxy/ppb_core_proxy.cc138
-rw-r--r--ppapi/proxy/ppb_core_proxy.h42
-rw-r--r--ppapi/proxy/ppb_crypto_proxy.cc54
-rw-r--r--ppapi/proxy/ppb_crypto_proxy.h33
-rw-r--r--ppapi/proxy/ppb_cursor_control_proxy.cc171
-rw-r--r--ppapi/proxy/ppb_cursor_control_proxy.h70
-rw-r--r--ppapi/proxy/ppb_file_chooser_proxy.cc243
-rw-r--r--ppapi/proxy/ppb_file_chooser_proxy.h71
-rw-r--r--ppapi/proxy/ppb_file_ref_proxy.cc303
-rw-r--r--ppapi/proxy/ppb_file_ref_proxy.h85
-rw-r--r--ppapi/proxy/ppb_file_system_proxy.cc205
-rw-r--r--ppapi/proxy/ppb_file_system_proxy.h61
-rw-r--r--ppapi/proxy/ppb_flash_clipboard_proxy.cc165
-rw-r--r--ppapi/proxy/ppb_flash_clipboard_proxy.h51
-rw-r--r--ppapi/proxy/ppb_flash_file_proxy.cc732
-rw-r--r--ppapi/proxy/ppb_flash_file_proxy.h98
-rw-r--r--ppapi/proxy/ppb_flash_menu_proxy.cc204
-rw-r--r--ppapi/proxy/ppb_flash_menu_proxy.h54
-rw-r--r--ppapi/proxy/ppb_flash_net_connector_proxy.cc345
-rw-r--r--ppapi/proxy/ppb_flash_net_connector_proxy.h63
-rw-r--r--ppapi/proxy/ppb_flash_proxy.cc291
-rw-r--r--ppapi/proxy/ppb_flash_proxy.h63
-rw-r--r--ppapi/proxy/ppb_flash_tcp_socket_proxy.cc439
-rw-r--r--ppapi/proxy/ppb_flash_tcp_socket_proxy.h61
-rw-r--r--ppapi/proxy/ppb_font_proxy.cc233
-rw-r--r--ppapi/proxy/ppb_font_proxy.h92
-rw-r--r--ppapi/proxy/ppb_graphics_2d_proxy.cc270
-rw-r--r--ppapi/proxy/ppb_graphics_2d_proxy.h76
-rw-r--r--ppapi/proxy/ppb_image_data_proxy.cc138
-rw-r--r--ppapi/proxy/ppb_image_data_proxy.h90
-rw-r--r--ppapi/proxy/ppb_input_event_proxy.cc102
-rw-r--r--ppapi/proxy/ppb_input_event_proxy.h40
-rw-r--r--ppapi/proxy/ppb_instance_proxy.cc367
-rw-r--r--ppapi/proxy/ppb_instance_proxy.h101
-rw-r--r--ppapi/proxy/ppb_memory_proxy.cc64
-rw-r--r--ppapi/proxy/ppb_memory_proxy.h36
-rw-r--r--ppapi/proxy/ppb_opengles2_proxy.cc939
-rw-r--r--ppapi/proxy/ppb_opengles2_proxy.h35
-rw-r--r--ppapi/proxy/ppb_pdf_proxy.cc186
-rw-r--r--ppapi/proxy/ppb_pdf_proxy.h47
-rw-r--r--ppapi/proxy/ppb_surface_3d_proxy.cc210
-rw-r--r--ppapi/proxy/ppb_surface_3d_proxy.h102
-rw-r--r--ppapi/proxy/ppb_testing_proxy.cc146
-rw-r--r--ppapi/proxy/ppb_testing_proxy.h50
-rw-r--r--ppapi/proxy/ppb_url_loader_proxy.cc595
-rw-r--r--ppapi/proxy/ppb_url_loader_proxy.h100
-rw-r--r--ppapi/proxy/ppb_url_request_info_proxy.cc206
-rw-r--r--ppapi/proxy/ppb_url_request_info_proxy.h54
-rw-r--r--ppapi/proxy/ppb_url_response_info_proxy.cc153
-rw-r--r--ppapi/proxy/ppb_url_response_info_proxy.h55
-rw-r--r--ppapi/proxy/ppb_url_util_proxy.cc228
-rw-r--r--ppapi/proxy/ppb_url_util_proxy.h54
-rw-r--r--ppapi/proxy/ppb_var_deprecated_proxy.cc523
-rw-r--r--ppapi/proxy/ppb_var_deprecated_proxy.h104
-rw-r--r--ppapi/proxy/ppb_var_proxy.cc85
-rw-r--r--ppapi/proxy/ppb_var_proxy.h36
-rw-r--r--ppapi/proxy/ppp_class_proxy.cc298
-rw-r--r--ppapi/proxy/ppp_class_proxy.h87
-rw-r--r--ppapi/proxy/ppp_graphics_3d_proxy.cc70
-rw-r--r--ppapi/proxy/ppp_graphics_3d_proxy.h39
-rw-r--r--ppapi/proxy/ppp_input_event_proxy.cc115
-rw-r--r--ppapi/proxy/ppp_input_event_proxy.h46
-rw-r--r--ppapi/proxy/ppp_instance_private_proxy.cc78
-rw-r--r--ppapi/proxy/ppp_instance_private_proxy.h45
-rw-r--r--ppapi/proxy/ppp_instance_proxy.cc250
-rw-r--r--ppapi/proxy/ppp_instance_proxy.h72
-rw-r--r--ppapi/proxy/ppp_instance_proxy_test.cc208
-rw-r--r--ppapi/proxy/proxy_channel.cc69
-rw-r--r--ppapi/proxy/proxy_channel.h110
-rw-r--r--ppapi/proxy/proxy_module.cc32
-rw-r--r--ppapi/proxy/proxy_module.h45
-rw-r--r--ppapi/proxy/proxy_non_thread_safe_ref_count.h49
-rw-r--r--ppapi/proxy/resource_creation_proxy.cc316
-rw-r--r--ppapi/proxy/resource_creation_proxy.h126
-rw-r--r--ppapi/proxy/run_all_unittests.cc9
-rw-r--r--ppapi/proxy/serialized_flash_menu.cc172
-rw-r--r--ppapi/proxy/serialized_flash_menu.h44
-rw-r--r--ppapi/proxy/serialized_structs.cc85
-rw-r--r--ppapi/proxy/serialized_structs.h128
-rw-r--r--ppapi/proxy/serialized_var.cc536
-rw-r--r--ppapi/proxy/serialized_var.h455
-rw-r--r--ppapi/proxy/serialized_var_unittest.cc74
-rw-r--r--ppapi/proxy/var_serialization_rules.h93
138 files changed, 21522 insertions, 0 deletions
diff --git a/ppapi/proxy/DEPS b/ppapi/proxy/DEPS
new file mode 100644
index 0000000..a159be3
--- /dev/null
+++ b/ppapi/proxy/DEPS
@@ -0,0 +1,15 @@
+include_rules = [
+ "+base",
+ "+ipc",
+ "+gpu",
+ "+skia",
+ "+ui/gfx/surface",
+
+ # 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.
+ "-ppapi/cpp",
+ "+ppapi/cpp/completion_callback.h"
+]
+
diff --git a/ppapi/proxy/OWNERS b/ppapi/proxy/OWNERS
new file mode 100644
index 0000000..86dac7d
--- /dev/null
+++ b/ppapi/proxy/OWNERS
@@ -0,0 +1,2 @@
+piman@chromium.org
+viettrungluu@chromium.org
diff --git a/ppapi/proxy/broker_dispatcher.cc b/ppapi/proxy/broker_dispatcher.cc
new file mode 100644
index 0000000..087e9fc
--- /dev/null
+++ b/ppapi/proxy/broker_dispatcher.cc
@@ -0,0 +1,113 @@
+// 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/broker_dispatcher.h"
+
+#include "base/sync_socket.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+int32_t PlatformFileToInt(base::PlatformFile handle) {
+#if defined(OS_WIN)
+ return static_cast<int32_t>(reinterpret_cast<intptr_t>(handle));
+#elif defined(OS_POSIX)
+ return handle;
+#else
+ #error Not implemented.
+#endif
+}
+
+} // namespace
+
+BrokerDispatcher::BrokerDispatcher(base::ProcessHandle remote_process_handle,
+ PP_ConnectInstance_Func connect_instance)
+ : ProxyChannel(remote_process_handle),
+ connect_instance_(connect_instance) {
+}
+
+BrokerDispatcher::~BrokerDispatcher() {
+}
+
+bool BrokerDispatcher::InitBrokerWithChannel(
+ ProxyChannel::Delegate* delegate,
+ const IPC::ChannelHandle& channel_handle,
+ bool is_client) {
+ return ProxyChannel::InitWithChannel(delegate, channel_handle, is_client);
+}
+
+bool BrokerDispatcher::OnMessageReceived(const IPC::Message& msg) {
+ // Control messages.
+ if (msg.routing_id() == MSG_ROUTING_CONTROL) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(BrokerDispatcher, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_ConnectToPlugin, OnMsgConnectToPlugin)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+ }
+ return false;
+}
+
+// Transfers ownership of the handle to the broker module.
+void BrokerDispatcher::OnMsgConnectToPlugin(
+ PP_Instance instance,
+ IPC::PlatformFileForTransit handle) {
+ int32_t result = PP_OK;
+ if (handle == IPC::InvalidPlatformFileForTransit()) {
+ result = PP_ERROR_FAILED;
+ } else {
+ base::SyncSocket::Handle socket_handle =
+ IPC::PlatformFileForTransitToPlatformFile(handle);
+
+ if (connect_instance_) {
+ result = connect_instance_(instance, PlatformFileToInt(socket_handle));
+ } else {
+ result = PP_ERROR_FAILED;
+ // Close the handle since there is no other owner.
+ // The easiest way to clean it up is to just put it in an object
+ // and then close them. This failure case is not performance critical.
+ base::SyncSocket temp_socket(socket_handle);
+ }
+ }
+
+ // TODO(ddorwin): Report result via IPC.
+}
+
+BrokerHostDispatcher::BrokerHostDispatcher(
+ base::ProcessHandle remote_process_handle)
+ : BrokerDispatcher(remote_process_handle, NULL) {
+}
+
+void BrokerHostDispatcher::OnChannelError() {
+ BrokerDispatcher::OnChannelError(); // Stop using the channel.
+
+ // Tell the host about the crash so it can clean up and display notification.
+ // TODO(ddorwin): Add BrokerCrashed() to PPB_Proxy_Private and call it.
+ // ppb_proxy_->BrokerCrashed(pp_module());
+}
+
+BrokerSideDispatcher::BrokerSideDispatcher(
+ base::ProcessHandle remote_process_handle,
+ PP_ConnectInstance_Func connect_instance)
+ : BrokerDispatcher(remote_process_handle, connect_instance) {
+}
+
+void BrokerSideDispatcher::OnChannelError() {
+ BrokerDispatcher::OnChannelError();
+
+ // The renderer has crashed or exited. This channel and all instances
+ // associated with it are no longer valid.
+ // TODO(ddorwin): This causes the broker process to exit, which may not be
+ // desirable in some use cases.
+ delete this;
+}
+
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/broker_dispatcher.h b/ppapi/proxy/broker_dispatcher.h
new file mode 100644
index 0000000..399bb87
--- /dev/null
+++ b/ppapi/proxy/broker_dispatcher.h
@@ -0,0 +1,64 @@
+// 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_BROKER_DISPATCHER_H_
+#define PPAPI_PROXY_BROKER_DISPATCHER_H_
+
+#include "ppapi/c/trusted/ppp_broker.h"
+#include "ppapi/proxy/proxy_channel.h"
+
+namespace pp {
+namespace proxy {
+
+class BrokerDispatcher : public ProxyChannel {
+ public:
+ virtual ~BrokerDispatcher();
+
+ // You must call this function before anything else. Returns true on success.
+ // The delegate pointer must outlive this class, ownership is not
+ // transferred.
+ virtual bool InitBrokerWithChannel(ProxyChannel::Delegate* delegate,
+ const IPC::ChannelHandle& channel_handle,
+ bool is_client);
+
+ // IPC::Channel::Listener implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ protected:
+ // You must call InitBrokerWithChannel after the constructor.
+ BrokerDispatcher(base::ProcessHandle remote_process_handle,
+ PP_ConnectInstance_Func connect_instance);
+
+ void OnMsgConnectToPlugin(PP_Instance instance,
+ IPC::PlatformFileForTransit handle);
+
+ PP_ConnectInstance_Func connect_instance_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BrokerDispatcher);
+};
+
+// The dispatcher for the browser side of the broker channel.
+class BrokerHostDispatcher : public BrokerDispatcher {
+ public:
+ BrokerHostDispatcher(base::ProcessHandle remote_process_handle);
+
+ // IPC::Channel::Listener implementation.
+ virtual void OnChannelError();
+};
+
+// The dispatcher for the broker side of the broker channel.
+class BrokerSideDispatcher : public BrokerDispatcher {
+ public:
+ BrokerSideDispatcher(base::ProcessHandle remote_process_handle,
+ PP_ConnectInstance_Func connect_instance);
+
+ // IPC::Channel::Listener implementation.
+ virtual void OnChannelError();
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_BROKER_DISPATCHER_H_
diff --git a/ppapi/proxy/callback_tracker.cc b/ppapi/proxy/callback_tracker.cc
new file mode 100644
index 0000000..9806497
--- /dev/null
+++ b/ppapi/proxy/callback_tracker.cc
@@ -0,0 +1,72 @@
+// Copyright (c) 2010 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/callback_tracker.h"
+
+#include "ppapi/proxy/dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+struct CallbackData {
+ CallbackTracker* tracker;
+ uint32_t callback_id;
+};
+
+void CallbackProxy(void* user_data, int32_t result) {
+ CallbackData* data = static_cast<CallbackData*>(user_data);
+ data->tracker->SendExecuteSerializedCallback(data->callback_id, result);
+ delete data;
+}
+
+} // namespace
+
+CallbackTracker::CallbackTracker(Dispatcher* dispatcher)
+ : dispatcher_(dispatcher),
+ next_callback_id_(1) {
+}
+
+CallbackTracker::~CallbackTracker() {
+}
+
+uint32_t CallbackTracker::SendCallback(PP_CompletionCallback callback) {
+ // Find the next callback ID we can use (being careful about wraparound).
+ while (callback_map_.find(next_callback_id_) != callback_map_.end())
+ next_callback_id_++;
+ callback_map_[next_callback_id_] = callback;
+ return next_callback_id_++;
+}
+
+PP_CompletionCallback CallbackTracker::ReceiveCallback(
+ uint32_t serialized_callback) {
+ CallbackData* data = new CallbackData;
+ data->tracker = this;
+ data->callback_id = serialized_callback;
+ return PP_MakeCompletionCallback(&CallbackProxy, data);
+}
+
+void CallbackTracker::SendExecuteSerializedCallback(
+ uint32_t serialized_callback,
+ int32_t param) {
+ dispatcher_->Send(new PpapiMsg_ExecuteCallback(serialized_callback, param));
+}
+
+void CallbackTracker::ReceiveExecuteSerializedCallback(
+ uint32_t serialized_callback,
+ int32_t param) {
+ CallbackMap::iterator found = callback_map_.find(serialized_callback);
+ if (found == callback_map_.end()) {
+ NOTREACHED();
+ return;
+ }
+
+ PP_RunCompletionCallback(&found->second, param);
+ callback_map_.erase(found);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/callback_tracker.h b/ppapi/proxy/callback_tracker.h
new file mode 100644
index 0000000..5f8233c1
--- /dev/null
+++ b/ppapi/proxy/callback_tracker.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2010 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_CALLBACK_TRACKER_H_
+#define PPAPI_PROXY_CALLBACK_TRACKER_H_
+
+#include <map>
+
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_stdint.h"
+
+namespace pp {
+namespace proxy {
+
+class Dispatcher;
+
+// This object tracks cross-process callbacks. When the plugin sends a callback
+// object to the renderer, we save the information and pass an identifier
+// instead.
+//
+// On the renderer side, this identifier is converted to a new callback in that
+// process. When executed, this new callback sends an IPC message containing the
+// previous identifier back to the plugin.
+//
+// When we receive that message, ExecuteSerializedCallback converts the
+// identifier back to the original callback information and runs the callback.
+class CallbackTracker {
+ public:
+ CallbackTracker(Dispatcher* dispatcher);
+ ~CallbackTracker();
+
+ // Converts the given callback in the context of the plugin to a serialized
+ // ID. This will be passed to ReceiveCallback on the renderer side.
+ uint32_t SendCallback(PP_CompletionCallback callback);
+
+ // Converts the given serialized callback ID to a new completion callback in
+ // the context of the current process. This callback actually will represent
+ // a proxy that will execute the callback in the plugin process.
+ PP_CompletionCallback ReceiveCallback(uint32_t serialized_callback);
+
+ // Sends a request to the remote process to execute the given callback.
+ void SendExecuteSerializedCallback(uint32_t serialized_callback,
+ int32_t param);
+
+ // Executes the given callback ID with the given result in the current
+ // process. This will also destroy the information associated with the
+ // callback and the serialized ID won't be valid any more.
+ void ReceiveExecuteSerializedCallback(uint32_t serialized_callback,
+ int32_t param);
+
+ private:
+ // Pointer to the dispatcher that owns us.
+ Dispatcher* dispatcher_;
+
+ int32_t next_callback_id_;
+
+ // Maps callback IDs to the actual callback objects in the plugin process.
+ typedef std::map<int32_t, PP_CompletionCallback> CallbackMap;
+ CallbackMap callback_map_;
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_CALLBACK_TRACKER_H_
diff --git a/ppapi/proxy/dispatcher.cc b/ppapi/proxy/dispatcher.cc
new file mode 100644
index 0000000..69e16ac
--- /dev/null
+++ b/ppapi/proxy/dispatcher.cc
@@ -0,0 +1,272 @@
+// 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/dispatcher.h"
+
+#include <string.h> // For memset.
+
+#include <map>
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "ppapi/c/dev/ppb_buffer_dev.h"
+#include "ppapi/c/dev/ppb_char_set_dev.h"
+#include "ppapi/c/dev/ppb_context_3d_dev.h"
+#include "ppapi/c/dev/ppb_crypto_dev.h"
+#include "ppapi/c/dev/ppb_cursor_control_dev.h"
+#include "ppapi/c/dev/ppb_gles_chromium_texture_mapping_dev.h"
+#include "ppapi/c/dev/ppb_font_dev.h"
+#include "ppapi/c/dev/ppb_opengles_dev.h"
+#include "ppapi/c/dev/ppb_surface_3d_dev.h"
+#include "ppapi/c/dev/ppb_testing_dev.h"
+#include "ppapi/c/dev/ppb_url_util_dev.h"
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_audio.h"
+#include "ppapi/c/ppb_audio_config.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/c/ppb_graphics_2d.h"
+#include "ppapi/c/ppb_image_data.h"
+#include "ppapi/c/ppb_instance.h"
+#include "ppapi/c/ppb_url_loader.h"
+#include "ppapi/c/ppb_url_request_info.h"
+#include "ppapi/c/ppb_url_response_info.h"
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/c/ppp_instance.h"
+#include "ppapi/c/private/ppb_flash.h"
+#include "ppapi/c/private/ppb_flash_clipboard.h"
+#include "ppapi/c/private/ppb_flash_file.h"
+#include "ppapi/c/private/ppb_flash_menu.h"
+#include "ppapi/c/private/ppb_flash_net_connector.h"
+#include "ppapi/c/private/ppb_flash_tcp_socket.h"
+#include "ppapi/c/private/ppb_pdf.h"
+#include "ppapi/c/trusted/ppb_url_loader_trusted.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_audio_config_proxy.h"
+#include "ppapi/proxy/ppb_audio_proxy.h"
+#include "ppapi/proxy/ppb_broker_proxy.h"
+#include "ppapi/proxy/ppb_buffer_proxy.h"
+#include "ppapi/proxy/ppb_char_set_proxy.h"
+#include "ppapi/proxy/ppb_console_proxy.h"
+#include "ppapi/proxy/ppb_context_3d_proxy.h"
+#include "ppapi/proxy/ppb_core_proxy.h"
+#include "ppapi/proxy/ppb_crypto_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_file_system_proxy.h"
+#include "ppapi/proxy/ppb_flash_clipboard_proxy.h"
+#include "ppapi/proxy/ppb_flash_file_proxy.h"
+#include "ppapi/proxy/ppb_flash_proxy.h"
+#include "ppapi/proxy/ppb_flash_menu_proxy.h"
+#include "ppapi/proxy/ppb_flash_net_connector_proxy.h"
+#include "ppapi/proxy/ppb_flash_tcp_socket_proxy.h"
+#include "ppapi/proxy/ppb_font_proxy.h"
+#include "ppapi/proxy/ppb_graphics_2d_proxy.h"
+#include "ppapi/proxy/ppb_image_data_proxy.h"
+#include "ppapi/proxy/ppb_input_event_proxy.h"
+#include "ppapi/proxy/ppb_instance_proxy.h"
+#include "ppapi/proxy/ppb_memory_proxy.h"
+#include "ppapi/proxy/ppb_opengles2_proxy.h"
+#include "ppapi/proxy/ppb_pdf_proxy.h"
+#include "ppapi/proxy/ppb_surface_3d_proxy.h"
+#include "ppapi/proxy/ppb_testing_proxy.h"
+#include "ppapi/proxy/ppb_url_loader_proxy.h"
+#include "ppapi/proxy/ppb_url_request_info_proxy.h"
+#include "ppapi/proxy/ppb_url_response_info_proxy.h"
+#include "ppapi/proxy/ppb_url_util_proxy.h"
+#include "ppapi/proxy/ppb_var_deprecated_proxy.h"
+#include "ppapi/proxy/ppb_var_proxy.h"
+#include "ppapi/proxy/ppp_class_proxy.h"
+#include "ppapi/proxy/ppp_graphics_3d_proxy.h"
+#include "ppapi/proxy/ppp_input_event_proxy.h"
+#include "ppapi/proxy/ppp_instance_private_proxy.h"
+#include "ppapi/proxy/ppp_instance_proxy.h"
+#include "ppapi/proxy/var_serialization_rules.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+struct InterfaceList {
+ InterfaceList();
+
+ static InterfaceList* GetInstance();
+
+ void AddPPP(const InterfaceProxy::Info* info);
+ void AddPPB(const InterfaceProxy::Info* info);
+
+ typedef std::map<std::string, const InterfaceProxy::Info*> NameToInfo;
+ NameToInfo name_to_plugin_info_;
+ NameToInfo name_to_browser_info_;
+
+ // Note that there can be multiple interface names mapping to the same ID.
+ // In this case, the ID will map to one of them. This is temporary while
+ // we're converting to the thunk system, when that is complete, we need to
+ // have a better way of handling multiple interface implemented by one
+ // proxy object.
+ const InterfaceProxy::Info* id_to_browser_info_[INTERFACE_ID_COUNT];
+};
+
+InterfaceList::InterfaceList() {
+ memset(id_to_browser_info_, 0, sizeof(id_to_browser_info_));
+
+ // PPB (browser) interfaces.
+ AddPPB(PPB_AudioConfig_Proxy::GetInfo());
+ AddPPB(PPB_Audio_Proxy::GetInfo());
+ AddPPB(PPB_Broker_Proxy::GetInfo());
+ AddPPB(PPB_Buffer_Proxy::GetInfo());
+ AddPPB(PPB_CharSet_Proxy::GetInfo());
+ AddPPB(PPB_Console_Proxy::GetInfo());
+ AddPPB(PPB_Context3D_Proxy::GetInfo());
+ AddPPB(PPB_Context3D_Proxy::GetTextureMappingInfo());
+ AddPPB(PPB_Core_Proxy::GetInfo());
+ AddPPB(PPB_Crypto_Proxy::GetInfo());
+ AddPPB(PPB_CursorControl_Proxy::GetInfo());
+ AddPPB(PPB_FileChooser_Proxy::GetInfo());
+ AddPPB(PPB_FileRef_Proxy::GetInfo());
+ AddPPB(PPB_FileSystem_Proxy::GetInfo());
+ AddPPB(PPB_Flash_Clipboard_Proxy::GetInfo());
+ AddPPB(PPB_Flash_File_FileRef_Proxy::GetInfo());
+ AddPPB(PPB_Flash_File_ModuleLocal_Proxy::GetInfo());
+ AddPPB(PPB_Flash_Proxy::GetInfo());
+ AddPPB(PPB_Flash_Menu_Proxy::GetInfo());
+ AddPPB(PPB_Flash_TCPSocket_Proxy::GetInfo());
+ AddPPB(PPB_Font_Proxy::GetInfo());
+ AddPPB(PPB_Graphics2D_Proxy::GetInfo());
+ AddPPB(PPB_ImageData_Proxy::GetInfo());
+ AddPPB(PPB_InputEvent_Proxy::GetInfo());
+ AddPPB(PPB_Instance_Proxy::GetInfo0_5());
+ AddPPB(PPB_Instance_Proxy::GetInfo1_0());
+ AddPPB(PPB_Instance_Proxy::GetInfoFullscreen());
+ AddPPB(PPB_Instance_Proxy::GetInfoMessaging());
+ AddPPB(PPB_Instance_Proxy::GetInfoPrivate());
+ AddPPB(PPB_Memory_Proxy::GetInfo());
+ AddPPB(PPB_OpenGLES2_Proxy::GetInfo());
+ AddPPB(PPB_PDF_Proxy::GetInfo());
+ AddPPB(PPB_Surface3D_Proxy::GetInfo());
+ AddPPB(PPB_Testing_Proxy::GetInfo());
+ AddPPB(PPB_URLLoader_Proxy::GetInfo());
+ AddPPB(PPB_URLLoader_Proxy::GetTrustedInfo());
+ AddPPB(PPB_URLRequestInfo_Proxy::GetInfo());
+ AddPPB(PPB_URLResponseInfo_Proxy::GetInfo());
+ AddPPB(PPB_URLUtil_Proxy::GetInfo());
+ AddPPB(PPB_Var_Deprecated_Proxy::GetInfo());
+ AddPPB(PPB_Var_Proxy::GetInfo());
+
+#ifdef ENABLE_FLAPPER_HACKS
+ AddPPB(PPB_Flash_NetConnector_Proxy::GetInfo());
+#endif
+
+ // PPP (plugin) interfaces.
+ AddPPP(PPP_Graphics3D_Proxy::GetInfo());
+ AddPPP(PPP_InputEvent_Proxy::GetInfo());
+ AddPPP(PPP_Instance_Private_Proxy::GetInfo());
+ AddPPP(PPP_Instance_Proxy::GetInfo0_5());
+}
+
+void InterfaceList::AddPPP(const InterfaceProxy::Info* info) {
+ DCHECK(name_to_plugin_info_.find(info->name) ==
+ name_to_plugin_info_.end());
+ DCHECK(info->id >= INTERFACE_ID_NONE && info->id < INTERFACE_ID_COUNT);
+
+ name_to_plugin_info_[info->name] = info;
+}
+
+void InterfaceList::AddPPB(const InterfaceProxy::Info* info) {
+ DCHECK(name_to_browser_info_.find(info->name) ==
+ name_to_browser_info_.end());
+ DCHECK(info->id >= INTERFACE_ID_NONE && info->id < INTERFACE_ID_COUNT);
+ DCHECK(info->id == INTERFACE_ID_NONE ||
+ id_to_browser_info_[info->id] == NULL);
+
+ name_to_browser_info_[std::string(info->name)] = info;
+ if (info->id != INTERFACE_ID_NONE)
+ id_to_browser_info_[info->id] = info;
+}
+
+// static
+InterfaceList* InterfaceList::GetInstance() {
+ return Singleton<InterfaceList>::get();
+}
+
+} // namespace
+
+Dispatcher::Dispatcher(base::ProcessHandle remote_process_handle,
+ GetInterfaceFunc local_get_interface)
+ : ProxyChannel(remote_process_handle),
+ disallow_trusted_interfaces_(false), // TODO(brettw) make this settable.
+ local_get_interface_(local_get_interface),
+ callback_tracker_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+}
+
+Dispatcher::~Dispatcher() {
+}
+
+bool Dispatcher::OnMessageReceived(const IPC::Message& msg) {
+ // Control messages.
+ if (msg.routing_id() == MSG_ROUTING_CONTROL) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(Dispatcher, msg)
+ IPC_MESSAGE_FORWARD(PpapiMsg_ExecuteCallback, &callback_tracker_,
+ CallbackTracker::ReceiveExecuteSerializedCallback)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+ }
+ return false;
+}
+
+// static
+const InterfaceProxy::Info* Dispatcher::GetPPBInterfaceInfo(
+ const std::string& name) {
+ const InterfaceList* list = InterfaceList::GetInstance();
+ InterfaceList::NameToInfo::const_iterator found =
+ list->name_to_browser_info_.find(name);
+ if (found == list->name_to_browser_info_.end())
+ return NULL;
+ return found->second;
+}
+
+// static
+const InterfaceProxy::Info* Dispatcher::GetPPBInterfaceInfo(InterfaceID id) {
+ if (id <= 0 || id >= INTERFACE_ID_COUNT)
+ return NULL;
+ const InterfaceList* list = InterfaceList::GetInstance();
+ return list->id_to_browser_info_[id];
+}
+
+// static
+const InterfaceProxy::Info* Dispatcher::GetPPPInterfaceInfo(
+ const std::string& name) {
+ const InterfaceList* list = InterfaceList::GetInstance();
+ InterfaceList::NameToInfo::const_iterator found =
+ list->name_to_plugin_info_.find(name);
+ if (found == list->name_to_plugin_info_.end())
+ return NULL;
+ return found->second;
+}
+
+void Dispatcher::SetSerializationRules(
+ VarSerializationRules* var_serialization_rules) {
+ serialization_rules_.reset(var_serialization_rules);
+}
+
+const void* Dispatcher::GetLocalInterface(const char* interface_name) {
+ return local_get_interface_(interface_name);
+}
+
+base::MessageLoopProxy* Dispatcher::GetIPCMessageLoop() {
+ return delegate()->GetIPCMessageLoop();
+}
+
+void Dispatcher::AddIOThreadMessageFilter(
+ IPC::ChannelProxy::MessageFilter* filter) {
+ channel()->AddFilter(filter);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/dispatcher.h b/ppapi/proxy/dispatcher.h
new file mode 100644
index 0000000..348c91c
--- /dev/null
+++ b/ppapi/proxy/dispatcher.h
@@ -0,0 +1,124 @@
+// 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_DISPATCHER_H_
+#define PPAPI_PROXY_DISPATCHER_H_
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/tracked_objects.h"
+#include "ipc/ipc_channel_proxy.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/proxy/callback_tracker.h"
+#include "ppapi/proxy/proxy_channel.h"
+#include "ppapi/proxy/interface_id.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+
+namespace ppapi {
+class WebKitForwarding;
+}
+
+namespace pp {
+namespace proxy {
+
+class VarSerializationRules;
+
+// An interface proxy can represent either end of a cross-process interface
+// call. The "source" side is where the call is invoked, and the "target" side
+// is where the call ends up being executed.
+//
+// Plugin side | Browser side
+// -------------------------------------|--------------------------------------
+// |
+// "Source" | "Target"
+// InterfaceProxy ----------------------> InterfaceProxy
+// |
+// |
+// "Target" | "Source"
+// InterfaceProxy <---------------------- InterfaceProxy
+// |
+class Dispatcher : public ProxyChannel {
+ public:
+ typedef const void* (*GetInterfaceFunc)(const char*);
+ typedef int32_t (*InitModuleFunc)(PP_Module, GetInterfaceFunc);
+
+ virtual ~Dispatcher();
+
+ // Returns true if the dispatcher is on the plugin side, or false if it's the
+ // browser side.
+ virtual bool IsPlugin() const = 0;
+
+ VarSerializationRules* serialization_rules() const {
+ return serialization_rules_.get();
+ }
+
+ // Wrapper for calling the local GetInterface function.
+ const void* GetLocalInterface(const char* interface_name);
+
+ // Returns the pointer to the IO thread for processing IPC messages.
+ // TODO(brettw) remove this. It's a hack to support the Flash
+ // ModuleLocalThreadAdapter. When the thread stuff is sorted out, this
+ // implementation detail should be hidden.
+ base::MessageLoopProxy* GetIPCMessageLoop();
+
+ // Adds the given filter to the IO thread. Takes ownership of the pointer.
+ // TODO(brettw) remove this. It's a hack to support the Flash
+ // ModuleLocalThreadAdapter. When the thread stuff is sorted out, this
+ // implementation detail should be hidden.
+ void AddIOThreadMessageFilter(IPC::ChannelProxy::MessageFilter* filter);
+
+ // TODO(brettw): What is this comment referring to?
+ // Called if the remote side is declaring to us which interfaces it supports
+ // so we don't have to query for each one. We'll pre-create proxies for
+ // each of the given interfaces.
+
+ // IPC::Channel::Listener implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ CallbackTracker& callback_tracker() {
+ return callback_tracker_;
+ }
+
+ // Retrieves the information associated with the given interface, identified
+ // either by name or ID. Each function searches either PPP or PPB interfaces.
+ static const InterfaceProxy::Info* GetPPBInterfaceInfo(
+ const std::string& name);
+ static const InterfaceProxy::Info* GetPPBInterfaceInfo(
+ InterfaceID id);
+ static const InterfaceProxy::Info* GetPPPInterfaceInfo(
+ const std::string& name);
+
+ protected:
+ Dispatcher(base::ProcessHandle remote_process_handle,
+ GetInterfaceFunc local_get_interface);
+
+ // Setter for the derived classes to set the appropriate var serialization.
+ // Takes ownership of the given pointer, which must be on the heap.
+ void SetSerializationRules(VarSerializationRules* var_serialization_rules);
+
+ bool disallow_trusted_interfaces() const {
+ return disallow_trusted_interfaces_;
+ }
+
+ private:
+ bool disallow_trusted_interfaces_;
+
+ GetInterfaceFunc local_get_interface_;
+
+ CallbackTracker callback_tracker_;
+
+ scoped_ptr<VarSerializationRules> serialization_rules_;
+
+ DISALLOW_COPY_AND_ASSIGN(Dispatcher);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_DISPATCHER_H_
diff --git a/ppapi/proxy/enter_proxy.h b/ppapi/proxy/enter_proxy.h
new file mode 100644
index 0000000..6e52705
--- /dev/null
+++ b/ppapi/proxy/enter_proxy.h
@@ -0,0 +1,58 @@
+// 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_ENTER_PROXY_H_
+#define PPAPI_PROXY_ENTER_PROXY_H_
+
+#include "base/logging.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/thunk/enter.h"
+
+namespace pp {
+namespace proxy {
+
+// Wrapper around EnterResourceNoLock that takes a host resource. This is used
+// when handling messages in the plugin from the host and we need to convert to
+// an object in the plugin side corresponding to that.
+//
+// This never locks since we assume the host Resource is coming from IPC, and
+// never logs errors since we assume the host is doing reasonable things.
+template<typename ResourceT>
+class EnterPluginFromHostResource
+ : public ::ppapi::thunk::EnterResourceNoLock<ResourceT> {
+ public:
+ EnterPluginFromHostResource(const HostResource& host_resource)
+ : ::ppapi::thunk::EnterResourceNoLock<ResourceT>(
+ PluginResourceTracker::GetInstance()->PluginResourceForHostResource(
+ host_resource),
+ false) {
+ // Validate that we're in the plugin rather than the host. Otherwise this
+ // object will do the wrong thing. In the plugin, the instance should have
+ // a corresponding plugin dispatcher (assuming the resource is valid).
+ DCHECK(this->failed() ||
+ PluginDispatcher::GetForInstance(host_resource.instance()));
+ }
+};
+
+template<typename ResourceT>
+class EnterHostFromHostResource
+ : public ::ppapi::thunk::EnterResourceNoLock<ResourceT> {
+ public:
+ EnterHostFromHostResource(const HostResource& host_resource)
+ : ::ppapi::thunk::EnterResourceNoLock<ResourceT>(
+ host_resource.host_resource(), false) {
+ // Validate that we're in the host rather than the plugin. Otherwise this
+ // object will do the wrong thing. In the host, the instance should have
+ // a corresponding host disptacher (assuming the resource is valid).
+ DCHECK(this->failed() ||
+ HostDispatcher::GetForInstance(host_resource.instance()));
+ }
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_ENTER_PROXY_H_
diff --git a/ppapi/proxy/host_dispatcher.cc b/ppapi/proxy/host_dispatcher.cc
new file mode 100644
index 0000000..1137a54
--- /dev/null
+++ b/ppapi/proxy/host_dispatcher.cc
@@ -0,0 +1,274 @@
+// 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/host_dispatcher.h"
+
+#include <map>
+
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "ppapi/c/private/ppb_proxy_private.h"
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/proxy/host_var_serialization_rules.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/resource_creation_proxy.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+typedef std::map<PP_Instance, HostDispatcher*> InstanceToDispatcherMap;
+InstanceToDispatcherMap* g_instance_to_dispatcher = NULL;
+
+typedef std::map<PP_Module, HostDispatcher*> ModuleToDispatcherMap;
+ModuleToDispatcherMap* g_module_to_dispatcher = NULL;
+
+PP_Bool ReserveInstanceID(PP_Module module, PP_Instance instance) {
+ // Default to returning true (usable) failure. Otherwise, if there's some
+ // kind of communication error or the plugin just crashed, we'll get into an
+ // infinite loop generating new instnace IDs since we think they're all in
+ // use.
+ ModuleToDispatcherMap::const_iterator found =
+ g_module_to_dispatcher->find(module);
+ if (found == g_module_to_dispatcher->end()) {
+ NOTREACHED();
+ return PP_TRUE;
+ }
+
+ bool usable = true;
+ if (!found->second->Send(new PpapiMsg_ReserveInstanceId(instance, &usable)))
+ return PP_TRUE;
+ return PP_FromBool(usable);
+}
+
+// Saves the state of the given bool and puts it back when it goes out of
+// scope.
+class BoolRestorer {
+ public:
+ BoolRestorer(bool* var) : var_(var), old_value_(*var) {
+ }
+ ~BoolRestorer() {
+ *var_ = old_value_;
+ }
+ private:
+ bool* var_;
+ bool old_value_;
+};
+
+} // namespace
+
+HostDispatcher::HostDispatcher(base::ProcessHandle remote_process_handle,
+ PP_Module module,
+ GetInterfaceFunc local_get_interface)
+ : Dispatcher(remote_process_handle, local_get_interface),
+ pp_module_(module),
+ ppb_proxy_(NULL),
+ allow_plugin_reentrancy_(false) {
+ if (!g_module_to_dispatcher)
+ g_module_to_dispatcher = new ModuleToDispatcherMap;
+ (*g_module_to_dispatcher)[pp_module_] = this;
+
+ const PPB_Var_Deprecated* var_interface =
+ static_cast<const PPB_Var_Deprecated*>(
+ local_get_interface(PPB_VAR_DEPRECATED_INTERFACE));
+ SetSerializationRules(new HostVarSerializationRules(var_interface, module));
+
+ // TODO(brettw): It might be more testable to inject the PPB_Proxy_Private
+ // instead of requesting it from GetLocalInterface.
+ ppb_proxy_ = reinterpret_cast<const PPB_Proxy_Private*>(
+ GetLocalInterface(PPB_PROXY_PRIVATE_INTERFACE));
+ DCHECK(ppb_proxy_) << "The proxy interface should always be supported.";
+
+ ppb_proxy_->SetReserveInstanceIDCallback(pp_module_, &ReserveInstanceID);
+}
+
+HostDispatcher::~HostDispatcher() {
+ g_module_to_dispatcher->erase(pp_module_);
+}
+
+bool HostDispatcher::InitHostWithChannel(
+ Delegate* delegate,
+ const IPC::ChannelHandle& channel_handle,
+ bool is_client,
+ const ppapi::Preferences& preferences) {
+ if (!Dispatcher::InitWithChannel(delegate, channel_handle, is_client))
+ return false;
+ Send(new PpapiMsg_SetPreferences(preferences));
+ return true;
+}
+
+// static
+HostDispatcher* HostDispatcher::GetForInstance(PP_Instance instance) {
+ if (!g_instance_to_dispatcher)
+ return NULL;
+ InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find(
+ instance);
+ if (found == g_instance_to_dispatcher->end())
+ return NULL;
+ return found->second;
+}
+
+// static
+void HostDispatcher::SetForInstance(PP_Instance instance,
+ HostDispatcher* dispatcher) {
+ if (!g_instance_to_dispatcher)
+ g_instance_to_dispatcher = new InstanceToDispatcherMap;
+ (*g_instance_to_dispatcher)[instance] = dispatcher;
+}
+
+// static
+void HostDispatcher::RemoveForInstance(PP_Instance instance) {
+ if (!g_instance_to_dispatcher)
+ return;
+ InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find(
+ instance);
+ if (found != g_instance_to_dispatcher->end())
+ g_instance_to_dispatcher->erase(found);
+}
+
+bool HostDispatcher::IsPlugin() const {
+ return false;
+}
+
+bool HostDispatcher::Send(IPC::Message* msg) {
+ TRACE_EVENT2("ppapi proxy", "HostDispatcher::Send",
+ "Class", IPC_MESSAGE_ID_CLASS(msg->type()),
+ "Line", IPC_MESSAGE_ID_LINE(msg->type()));
+ // Normal sync messages are set to unblock, which would normally cause the
+ // plugin to be reentered to process them. We only want to do this when we
+ // know the plugin is in a state to accept reentrancy. Since the plugin side
+ // never clears this flag on messages it sends, we can't get deadlock, but we
+ // may still get reentrancy in the host as a result.
+ if (!allow_plugin_reentrancy_)
+ msg->set_unblock(false);
+ return Dispatcher::Send(msg);
+}
+
+bool HostDispatcher::OnMessageReceived(const IPC::Message& msg) {
+ TRACE_EVENT2("ppapi proxy", "HostDispatcher::OnMessageReceived",
+ "Class", IPC_MESSAGE_ID_CLASS(msg.type()),
+ "Line", IPC_MESSAGE_ID_LINE(msg.type()));
+ // We only want to allow reentrancy when the most recent message from the
+ // plugin was a scripting message. We save the old state of the flag on the
+ // stack in case we're (we are the host) being reentered ourselves. The flag
+ // is set to false here for all messages, and then the scripting API will
+ // explicitly set it to true during processing of those messages that can be
+ // reentered.
+ BoolRestorer restorer(&allow_plugin_reentrancy_);
+ allow_plugin_reentrancy_ = false;
+
+ // Handle common control messages.
+ if (Dispatcher::OnMessageReceived(msg))
+ return true;
+
+ if (msg.routing_id() <= 0 || msg.routing_id() >= INTERFACE_ID_COUNT) {
+ NOTREACHED();
+ // TODO(brettw): kill the plugin if it starts sending invalid messages?
+ return true;
+ }
+
+ // New-style function proxies.
+ // TODO(brettw) this is hacked in for the routing for the types we've
+ // implemented in this style so far. When everything is implemented in this
+ // style, this function should be cleaned up.
+ if (msg.routing_id() == INTERFACE_ID_RESOURCE_CREATION) {
+ ResourceCreationProxy proxy(this);
+ return proxy.OnMessageReceived(msg);
+ }
+
+ InterfaceProxy* proxy = target_proxies_[msg.routing_id()].get();
+ if (!proxy) {
+ // Autocreate any proxy objects to handle requests from the plugin. Since
+ // we always support all known PPB_* interfaces (modulo the trusted bit),
+ // there's very little checking necessary.
+ const InterfaceProxy::Info* info = GetPPBInterfaceInfo(
+ static_cast<InterfaceID>(msg.routing_id()));
+ if (!info ||
+ (info->is_trusted && disallow_trusted_interfaces()))
+ return true;
+ proxy = CreatePPBInterfaceProxy(info);
+ }
+
+ return proxy->OnMessageReceived(msg);
+}
+
+void HostDispatcher::OnChannelError() {
+ Dispatcher::OnChannelError(); // Stop using the channel.
+
+ // Tell the host about the crash so it can clean up and display notification.
+ ppb_proxy_->PluginCrashed(pp_module());
+}
+
+const void* HostDispatcher::GetProxiedInterface(const std::string& interface) {
+ // First see if we even have a proxy for this interface.
+ const InterfaceProxy::Info* info = GetPPPInterfaceInfo(interface);
+ if (!info)
+ return NULL;
+
+ PluginIFSupportedMap::iterator iter(plugin_if_supported_.find(interface));
+ if (iter == plugin_if_supported_.end()) {
+ // Need to query. Cache the result so we only do this once.
+ bool supported = false;
+ Send(new PpapiMsg_SupportsInterface(interface, &supported));
+ std::pair<PluginIFSupportedMap::iterator, bool> iter_success_pair;
+ iter_success_pair = plugin_if_supported_.insert(
+ PluginIFSupportedMap::value_type(interface, supported));
+ iter = iter_success_pair.first;
+ }
+ if (iter->second)
+ return info->interface_ptr;
+ 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;
+}
+
+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;
+}
+
+// ScopedModuleReference -------------------------------------------------------
+
+ScopedModuleReference::ScopedModuleReference(Dispatcher* dispatcher) {
+ DCHECK(!dispatcher->IsPlugin());
+ dispatcher_ = static_cast<HostDispatcher*>(dispatcher);
+ dispatcher_->ppb_proxy()->AddRefModule(dispatcher_->pp_module());
+}
+
+ScopedModuleReference::~ScopedModuleReference() {
+ dispatcher_->ppb_proxy()->ReleaseModule(dispatcher_->pp_module());
+}
+
+} // namespace proxy
+} // namespace pp
+
diff --git a/ppapi/proxy/host_dispatcher.h b/ppapi/proxy/host_dispatcher.h
new file mode 100644
index 0000000..e3d9001
--- /dev/null
+++ b/ppapi/proxy/host_dispatcher.h
@@ -0,0 +1,161 @@
+// 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_HOST_DISPATCHER_H_
+#define PPAPI_PROXY_HOST_DISPATCHER_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/process.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/dispatcher.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+#include "ppapi/shared_impl/function_group_base.h"
+
+struct PPB_Proxy_Private;
+struct PPB_Var_Deprecated;
+
+namespace base {
+class WaitableEvent;
+}
+
+namespace IPC {
+class SyncChannel;
+}
+
+namespace ppapi {
+struct Preferences;
+}
+
+namespace pp {
+namespace proxy {
+
+class InterfaceProxy;
+class VarSerialization;
+
+class HostDispatcher : public Dispatcher {
+ public:
+ // Constructor for the renderer side.
+ //
+ // You must call InitHostWithChannel after the constructor.
+ HostDispatcher(base::ProcessHandle host_process_handle,
+ PP_Module module,
+ GetInterfaceFunc local_get_interface);
+ ~HostDispatcher();
+
+ // You must call this function before anything else. Returns true on success.
+ // The delegate pointer must outlive this class, ownership is not
+ // transferred.
+ virtual bool InitHostWithChannel(Delegate* delegate,
+ const IPC::ChannelHandle& channel_handle,
+ bool is_client,
+ const ppapi::Preferences& preferences);
+
+ // The host side maintains a mapping from PP_Instance to Dispatcher so
+ // that we can send the messages to the right channel.
+ static HostDispatcher* GetForInstance(PP_Instance instance);
+ static void SetForInstance(PP_Instance instance,
+ HostDispatcher* dispatcher);
+ static void RemoveForInstance(PP_Instance instance);
+
+ // Returns the host's notion of our PP_Module. This will be different than
+ // the plugin's notion of its PP_Module because the plugin process may be
+ // used by multiple renderer processes.
+ //
+ // Use this value instead of a value from the plugin whenever talking to the
+ // host.
+ PP_Module pp_module() const { return pp_module_; }
+
+ // Dispatcher overrides.
+ virtual bool IsPlugin() const;
+ virtual bool Send(IPC::Message* msg);
+
+ // IPC::Channel::Listener.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+ virtual void OnChannelError();
+
+ // Proxied version of calling GetInterface on the plugin. This will check
+ // if the plugin supports the given interface (with caching) and returns the
+ // pointer to the proxied interface if it is supported. Returns NULL if the
+ // 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);
+
+ // See the value below. Call this when processing a scripting message from
+ // the plugin that can be reentered.
+ void set_allow_plugin_reentrancy() {
+ allow_plugin_reentrancy_ = true;
+ }
+
+ // Returns the proxy interface for talking to the implementation.
+ const PPB_Proxy_Private* ppb_proxy() const { return ppb_proxy_; }
+
+ 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_;
+
+ typedef std::map<std::string, bool> PluginIFSupportedMap;
+ // Maps interface name to whether that interface is supported. If an interface
+ // name is not in the map, that implies that we haven't queried for it yet.
+ std::map<std::string, bool> plugin_if_supported_;
+
+ // All target proxies currently created. These are ones that receive
+ // messages. They are created on demand when we receive messages.
+ scoped_ptr<InterfaceProxy> target_proxies_[INTERFACE_ID_COUNT];
+
+ // Function proxies created for "new-style" FunctionGroups.
+ // TODO(brettw) this is in progress. It should be merged with the target
+ // proxies so there is one list to consult.
+ scoped_ptr< ::ppapi::FunctionGroupBase >
+ function_proxies_[INTERFACE_ID_COUNT];
+
+ // Guaranteed non-NULL.
+ const PPB_Proxy_Private* ppb_proxy_;
+
+ // Set to true when the plugin is in a state that it can be reentered by a
+ // sync message from the host. We allow reentrancy only when we're processing
+ // a sync message from the renderer that is a scripting command. When the
+ // plugin is in this state, it needs to accept reentrancy since scripting may
+ // ultimately call back into the plugin.
+ bool allow_plugin_reentrancy_;
+
+ DISALLOW_COPY_AND_ASSIGN(HostDispatcher);
+};
+
+// Create this object on the stack to prevent the module (and hence the
+// dispatcher) from being deleted out from under you. This is necessary when
+// calling some scripting functions that may delete the plugin.
+//
+// This may only be called in the host. The parameter is a plain Dispatcher
+// since that's what most callers have.
+class ScopedModuleReference {
+ public:
+ ScopedModuleReference(Dispatcher* dispatcher);
+ ~ScopedModuleReference();
+
+ private:
+ HostDispatcher* dispatcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedModuleReference);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_HOST_DISPATCHER_H_
diff --git a/ppapi/proxy/host_dispatcher_unittest.cc b/ppapi/proxy/host_dispatcher_unittest.cc
new file mode 100644
index 0000000..b2caa1a
--- /dev/null
+++ b/ppapi/proxy/host_dispatcher_unittest.cc
@@ -0,0 +1,42 @@
+// 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 "base/memory/scoped_ptr.h"
+#include "ipc/ipc_message_utils.h"
+#include "ppapi/c/ppb_audio.h"
+#include "ppapi/c/ppp_instance.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+
+namespace pp {
+namespace proxy {
+
+class HostDispatcherTest : public HostProxyTest {
+ public:
+ HostDispatcherTest() {}
+
+ bool HasTargetProxy(InterfaceID id) {
+ return !!host_dispatcher()->target_proxies_[id].get();
+ }
+};
+
+// TODO(brettw): Make and register an implementation of TrackerBase for this
+// test. Possibly fix other failures too, once that's resolved.
+TEST_F(HostDispatcherTest, FAILS_PPBCreation) {
+ RegisterTestInterface(PPB_AUDIO_INTERFACE,
+ reinterpret_cast<void*>(0xdeadbeef));
+
+ // Sending a PPB message out of the blue should create a target proxy for
+ // that interface in the plugin.
+ EXPECT_FALSE(HasTargetProxy(INTERFACE_ID_PPB_AUDIO));
+ PpapiMsg_PPBAudio_NotifyAudioStreamCreated audio_msg(
+ INTERFACE_ID_PPB_AUDIO, HostResource(), 0,
+ IPC::PlatformFileForTransit(), base::SharedMemoryHandle(), 0);
+ host_dispatcher()->OnMessageReceived(audio_msg);
+ EXPECT_TRUE(HasTargetProxy(INTERFACE_ID_PPB_AUDIO));
+}
+
+} // namespace proxy
+} // namespace pp
+
diff --git a/ppapi/proxy/host_resource.h b/ppapi/proxy/host_resource.h
new file mode 100644
index 0000000..fe1abb2
--- /dev/null
+++ b/ppapi/proxy/host_resource.h
@@ -0,0 +1,70 @@
+// 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_HOST_RESOURCE_H_
+#define PPAPI_PROXY_HOST_RESOURCE_H_
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+
+namespace pp {
+namespace proxy {
+
+// Represents a PP_Resource sent over the wire. This just wraps a PP_Resource.
+// The point is to prevent mistakes where the wrong resource value is sent.
+// Resource values are remapped in the plugin so that it can talk to multiple
+// hosts. If all values were PP_Resource, it would be easy to forget to do
+// this tranformation.
+//
+// All HostResources respresent IDs valid in the host.
+class HostResource {
+ public:
+ HostResource() : instance_(0), host_resource_(0) {
+ }
+
+ bool is_null() const {
+ return !host_resource_;
+ }
+
+ // Some resources are plugin-side only and don't have a corresponding
+ // resource in the host. Yet these resources still need an instance to be
+ // associated with. This function creates a HostResource with the given
+ // instances and a 0 host resource ID for these cases.
+ static HostResource MakeInstanceOnly(PP_Instance instance) {
+ HostResource resource;
+ resource.SetHostResource(instance, 0);
+ return resource;
+ }
+
+ // Sets and retrieves the internal PP_Resource which is valid for the host
+ // (a.k.a. renderer, as opposed to the plugin) process.
+ //
+ // DO NOT CALL THESE FUNCTIONS IN THE PLUGIN SIDE OF THE PROXY. The values
+ // will be invalid. See the class comment above.
+ void SetHostResource(PP_Instance instance, PP_Resource resource) {
+ instance_ = instance;
+ host_resource_ = resource;
+ }
+ PP_Resource host_resource() const {
+ return host_resource_;
+ }
+
+ PP_Instance instance() const { return instance_; }
+
+ // This object is used in maps so we need to provide this sorting operator.
+ bool operator<(const HostResource& other) const {
+ if (instance_ != other.instance_)
+ return instance_ < other.instance_;
+ return host_resource_ < other.host_resource_;
+ }
+
+ private:
+ PP_Instance instance_;
+ PP_Resource host_resource_;
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_HOST_RESOURCE_H_
diff --git a/ppapi/proxy/host_var_serialization_rules.cc b/ppapi/proxy/host_var_serialization_rules.cc
new file mode 100644
index 0000000..2a1d0ee
--- /dev/null
+++ b/ppapi/proxy/host_var_serialization_rules.cc
@@ -0,0 +1,96 @@
+// Copyright (c) 2010 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/host_var_serialization_rules.h"
+
+#include "base/logging.h"
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+
+namespace pp {
+namespace proxy {
+
+HostVarSerializationRules::HostVarSerializationRules(
+ const PPB_Var_Deprecated* var_interface,
+ PP_Module pp_module)
+ : var_interface_(var_interface),
+ pp_module_(pp_module) {
+}
+
+HostVarSerializationRules::~HostVarSerializationRules() {
+}
+
+PP_Var HostVarSerializationRules::SendCallerOwned(const PP_Var& var,
+ std::string* str_val) {
+ if (var.type == PP_VARTYPE_STRING)
+ VarToString(var, str_val);
+ return var;
+}
+
+PP_Var HostVarSerializationRules::BeginReceiveCallerOwned(
+ const PP_Var& var,
+ const std::string* str_val,
+ Dispatcher* /* dispatcher */) {
+ if (var.type == PP_VARTYPE_STRING) {
+ // Convert the string to the context of the current process.
+ return var_interface_->VarFromUtf8(pp_module_, str_val->c_str(),
+ static_cast<uint32_t>(str_val->size()));
+ }
+ return var;
+}
+
+void HostVarSerializationRules::EndReceiveCallerOwned(const PP_Var& var) {
+ if (var.type == PP_VARTYPE_STRING) {
+ // Destroy the string BeginReceiveCallerOwned created above.
+ var_interface_->Release(var);
+ }
+}
+
+PP_Var HostVarSerializationRules::ReceivePassRef(const PP_Var& var,
+ const std::string& str_val,
+ Dispatcher* /* dispatcher */) {
+ if (var.type == PP_VARTYPE_STRING) {
+ // Convert the string to the context of the current process.
+ return var_interface_->VarFromUtf8(pp_module_, str_val.c_str(),
+ static_cast<uint32_t>(str_val.size()));
+ }
+
+ // See PluginVarSerialization::BeginSendPassRef for an example.
+ if (var.type == PP_VARTYPE_OBJECT)
+ var_interface_->AddRef(var);
+ return var;
+}
+
+PP_Var HostVarSerializationRules::BeginSendPassRef(const PP_Var& var,
+ std::string* str_val) {
+ // See PluginVarSerialization::ReceivePassRef for an example. We don't need
+ // to do anything here other than convert the string.
+ if (var.type == PP_VARTYPE_STRING)
+ VarToString(var, str_val);
+ return var;
+}
+
+void HostVarSerializationRules::EndSendPassRef(const PP_Var& /* var */,
+ Dispatcher* /* dispatcher */) {
+ // See PluginVarSerialization::ReceivePassRef for an example. We don't need
+ // to do anything here.
+}
+
+void HostVarSerializationRules::VarToString(const PP_Var& var,
+ std::string* str) {
+ DCHECK(var.type == PP_VARTYPE_STRING);
+
+ // This could be optimized to avoid an extra string copy by going to a lower
+ // level of the browser's implementation of strings where we already have
+ // a std::string.
+ uint32_t len = 0;
+ const char* data = var_interface_->VarToUtf8(var, &len);
+ str->assign(data, len);
+}
+
+void HostVarSerializationRules::ReleaseObjectRef(const PP_Var& var) {
+ var_interface_->Release(var);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/host_var_serialization_rules.h b/ppapi/proxy/host_var_serialization_rules.h
new file mode 100644
index 0000000..4fd39be
--- /dev/null
+++ b/ppapi/proxy/host_var_serialization_rules.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2010 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_HOST_VAR_SERIALIZATION_RULES_H_
+#define PPAPI_PROXY_HOST_VAR_SERIALIZATION_RULES_H_
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/proxy/var_serialization_rules.h"
+
+struct PPB_Var_Deprecated;
+
+namespace pp {
+namespace proxy {
+
+class VarTracker;
+
+// Implementation of the VarSerializationRules interface for the host side.
+class HostVarSerializationRules : public VarSerializationRules {
+ public:
+ HostVarSerializationRules(const PPB_Var_Deprecated* var_interface,
+ PP_Module pp_module);
+ ~HostVarSerializationRules();
+
+ // VarSerialization implementation.
+ virtual PP_Var SendCallerOwned(const PP_Var& var, std::string* str_val);
+ virtual PP_Var BeginReceiveCallerOwned(const PP_Var& var,
+ const std::string* str_val,
+ Dispatcher* dispatcher);
+ virtual void EndReceiveCallerOwned(const PP_Var& var);
+ virtual PP_Var ReceivePassRef(const PP_Var& var,
+ const std::string& str_val,
+ Dispatcher* dispatcher);
+ virtual PP_Var BeginSendPassRef(const PP_Var& var, std::string* str_val);
+ virtual void EndSendPassRef(const PP_Var& var, Dispatcher* dispatcher);
+ virtual void ReleaseObjectRef(const PP_Var& var);
+
+ private:
+ // Converts the given var (which must be a VARTYPE_STRING) to the given
+ // string object.
+ void VarToString(const PP_Var& var, std::string* str);
+
+ const PPB_Var_Deprecated* var_interface_;
+ PP_Module pp_module_;
+
+ DISALLOW_COPY_AND_ASSIGN(HostVarSerializationRules);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_HOST_VAR_SERIALIZATION_RULES_H_
diff --git a/ppapi/proxy/interface_id.h b/ppapi/proxy/interface_id.h
new file mode 100644
index 0000000..26ef71f6a
--- /dev/null
+++ b/ppapi/proxy/interface_id.h
@@ -0,0 +1,71 @@
+// 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_INTERFACE_ID_H_
+#define PPAPI_PROXY_INTERFACE_ID_H_
+
+namespace pp {
+namespace proxy {
+
+// These numbers must be all small integers. They are used in a lookup table
+// to route messages to the appropriate message handler.
+enum InterfaceID {
+ // Zero is reserved for control messages.
+ INTERFACE_ID_NONE = 0,
+ INTERFACE_ID_PPB_AUDIO = 1,
+ INTERFACE_ID_PPB_AUDIO_CONFIG,
+ INTERFACE_ID_PPB_BROKER,
+ INTERFACE_ID_PPB_BUFFER,
+ INTERFACE_ID_PPB_CHAR_SET,
+ INTERFACE_ID_PPB_CONSOLE,
+ INTERFACE_ID_PPB_CONTEXT_3D,
+ INTERFACE_ID_PPB_CORE,
+ INTERFACE_ID_PPB_CRYPTO,
+ INTERFACE_ID_PPB_CURSORCONTROL,
+ INTERFACE_ID_PPB_FILE_CHOOSER,
+ INTERFACE_ID_PPB_FILE_REF,
+ INTERFACE_ID_PPB_FILE_SYSTEM,
+ INTERFACE_ID_PPB_FIND,
+ INTERFACE_ID_PPB_FLASH,
+ INTERFACE_ID_PPB_FLASH_CLIPBOARD,
+ INTERFACE_ID_PPB_FLASH_FILE_FILEREF,
+ INTERFACE_ID_PPB_FLASH_FILE_MODULELOCAL,
+ INTERFACE_ID_PPB_FLASH_MENU,
+ INTERFACE_ID_PPB_FLASH_NETCONNECTOR,
+ INTERFACE_ID_PPB_FLASH_TCPSOCKET,
+ INTERFACE_ID_PPB_FONT,
+ INTERFACE_ID_PPB_GRAPHICS_2D,
+ INTERFACE_ID_PPB_IMAGE_DATA,
+ INTERFACE_ID_PPB_INSTANCE,
+ INTERFACE_ID_PPB_INSTANCE_PRIVATE,
+ INTERFACE_ID_PPB_MEMORY,
+ INTERFACE_ID_PPB_OPENGLES2,
+ INTERFACE_ID_PPB_PDF,
+ INTERFACE_ID_PPB_SURFACE_3D,
+ INTERFACE_ID_PPB_TESTING,
+ INTERFACE_ID_PPB_URL_LOADER,
+ INTERFACE_ID_PPB_URL_REQUEST_INFO,
+ INTERFACE_ID_PPB_URL_RESPONSE_INFO,
+ INTERFACE_ID_PPB_URL_UTIL,
+ INTERFACE_ID_PPB_VAR,
+ INTERFACE_ID_PPB_VAR_DEPRECATED,
+ INTERFACE_ID_PPB_VIDEO_DECODER_DEV,
+
+ INTERFACE_ID_PPP_CLASS,
+ INTERFACE_ID_PPP_GRAPHICS_3D_DEV,
+ INTERFACE_ID_PPP_INPUT_EVENT,
+ INTERFACE_ID_PPP_INSTANCE,
+ INTERFACE_ID_PPP_INSTANCE_PRIVATE,
+ INTERFACE_ID_PPP_VIDEO_DECODER_DEV,
+
+ INTERFACE_ID_RESOURCE_CREATION,
+
+ // Must be last to indicate the number of interface IDs.
+ INTERFACE_ID_COUNT
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_INTERFACE_ID_H_
diff --git a/ppapi/proxy/interface_proxy.cc b/ppapi/proxy/interface_proxy.cc
new file mode 100644
index 0000000..7561d5e
--- /dev/null
+++ b/ppapi/proxy/interface_proxy.cc
@@ -0,0 +1,36 @@
+// Copyright (c) 2010 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/interface_proxy.h"
+
+#include "base/logging.h"
+#include "ppapi/proxy/dispatcher.h"
+
+namespace pp {
+namespace proxy {
+
+InterfaceProxy::InterfaceProxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : dispatcher_(dispatcher),
+ target_interface_(target_interface) {
+}
+
+InterfaceProxy::~InterfaceProxy() {
+}
+
+bool InterfaceProxy::Send(IPC::Message* msg) {
+ return dispatcher_->Send(msg);
+}
+
+uint32 InterfaceProxy::SendCallback(PP_CompletionCallback callback) {
+ return dispatcher_->callback_tracker().SendCallback(callback);
+}
+
+PP_CompletionCallback InterfaceProxy::ReceiveCallback(
+ uint32 serialized_callback) {
+ return dispatcher_->callback_tracker().ReceiveCallback(serialized_callback);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/interface_proxy.h b/ppapi/proxy/interface_proxy.h
new file mode 100644
index 0000000..3b16f9e
--- /dev/null
+++ b/ppapi/proxy/interface_proxy.h
@@ -0,0 +1,79 @@
+// 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_INTERFACE_PROXY_H_
+#define PPAPI_PROXY_INTERFACE_PROXY_H_
+
+#include "base/basictypes.h"
+#include "ipc/ipc_channel.h"
+#include "ipc/ipc_message.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/interface_id.h"
+
+namespace pp {
+namespace proxy {
+
+class Dispatcher;
+
+class InterfaceProxy : public IPC::Channel::Listener,
+ public IPC::Message::Sender {
+ public:
+ // Factory function type for interfaces. Ownership of the returned pointer
+ // is transferred to the caller.
+ typedef InterfaceProxy* (*Factory)(Dispatcher* dispatcher,
+ const void* target_interface);
+
+ // Information about the interface. Each interface has a static function to
+ // return its info, which allows either construction on the target side, and
+ // getting the proxied interface on the source side (see dispatcher.h for
+ // terminology).
+ struct Info {
+ const void* interface_ptr;
+
+ const char* name;
+ InterfaceID id;
+
+ bool is_trusted;
+
+ InterfaceProxy::Factory create_proxy;
+ };
+
+ virtual ~InterfaceProxy();
+
+ // The actual implementation of the given interface in the current process.
+ const void* target_interface() const { return target_interface_; }
+
+ Dispatcher* dispatcher() const { return dispatcher_; }
+
+ // IPC::Message::Sender implementation.
+ virtual bool Send(IPC::Message* msg);
+
+ // Sub-classes must implement IPC::Channel::Listener which contains this:
+ //virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ protected:
+ // Creates the given interface associated with the given dispatcher. The
+ // dispatcher manages our lifetime.
+ //
+ // The target interface pointer, when non-NULL, indicates that this is a
+ // target proxy (see dispatcher.h for a definition). In this case, the proxy
+ // will interpret this pointer to the actual implementation of the interface
+ // in the local process.
+ InterfaceProxy(Dispatcher* dispatcher, const void* target_interface);
+
+ uint32 SendCallback(PP_CompletionCallback callback);
+ PP_CompletionCallback ReceiveCallback(uint32 serialized_callback);
+
+ private:
+ Dispatcher* dispatcher_;
+ const void* target_interface_;
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_INTERFACE_PROXY_H_
+
diff --git a/ppapi/proxy/mock_resource.cc b/ppapi/proxy/mock_resource.cc
new file mode 100644
index 0000000..21e5381
--- /dev/null
+++ b/ppapi/proxy/mock_resource.cc
@@ -0,0 +1,22 @@
+// Copyright (c) 2010 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/mock_resource.h"
+
+namespace pp {
+namespace proxy {
+
+MockResource::MockResource(const HostResource& resource)
+ : PluginResource(resource) {
+}
+
+MockResource::~MockResource() {
+}
+
+MockResource* MockResource::AsMockResource() {
+ return this;
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/mock_resource.h b/ppapi/proxy/mock_resource.h
new file mode 100644
index 0000000..7e38be1
--- /dev/null
+++ b/ppapi/proxy/mock_resource.h
@@ -0,0 +1,29 @@
+// 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_MOCK_RESOURCE_H_
+#define PPAPI_PROXY_MOCK_RESOURCE_H_
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/plugin_resource.h"
+
+namespace pp {
+namespace proxy {
+
+class MockResource : public PluginResource {
+ public:
+ MockResource(const HostResource& resource);
+ virtual ~MockResource();
+
+ // Resource overrides.
+ virtual MockResource* AsMockResource();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockResource);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_MOCK_RESOURCE_H_
diff --git a/ppapi/proxy/plugin_dispatcher.cc b/ppapi/proxy/plugin_dispatcher.cc
new file mode 100644
index 0000000..53dab26
--- /dev/null
+++ b/ppapi/proxy/plugin_dispatcher.cc
@@ -0,0 +1,312 @@
+// 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/plugin_dispatcher.h"
+
+#include <map>
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_sync_channel.h"
+#include "base/debug/trace_event.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/plugin_message_filter.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/plugin_var_serialization_rules.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_char_set_proxy.h"
+#include "ppapi/proxy/ppb_cursor_control_proxy.h"
+#include "ppapi/proxy/ppb_font_proxy.h"
+#include "ppapi/proxy/ppb_instance_proxy.h"
+#include "ppapi/proxy/ppp_class_proxy.h"
+#include "ppapi/proxy/resource_creation_proxy.h"
+#include "ppapi/shared_impl/tracker_base.h"
+
+#if defined(OS_POSIX)
+#include "base/eintr_wrapper.h"
+#include "ipc/ipc_channel_posix.h"
+#endif
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+typedef std::map<PP_Instance, PluginDispatcher*> InstanceToDispatcherMap;
+InstanceToDispatcherMap* g_instance_to_dispatcher = NULL;
+
+} // namespace
+
+PluginDispatcher::PluginDispatcher(base::ProcessHandle remote_process_handle,
+ GetInterfaceFunc get_interface)
+ : Dispatcher(remote_process_handle, get_interface),
+ plugin_delegate_(NULL),
+ received_preferences_(false),
+ plugin_dispatcher_id_(0) {
+ SetSerializationRules(new PluginVarSerializationRules);
+
+ // As a plugin, we always support the PPP_Class interface. There's no
+ // GetInterface call or name for it, so we insert it into our table now.
+ target_proxies_[INTERFACE_ID_PPP_CLASS].reset(new PPP_Class_Proxy(this));
+
+ ::ppapi::TrackerBase::Init(
+ &PluginResourceTracker::GetTrackerBaseInstance);
+}
+
+PluginDispatcher::~PluginDispatcher() {
+ if (plugin_delegate_)
+ plugin_delegate_->Unregister(plugin_dispatcher_id_);
+}
+
+// static
+PluginDispatcher* PluginDispatcher::GetForInstance(PP_Instance instance) {
+ if (!g_instance_to_dispatcher)
+ return NULL;
+ InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find(
+ instance);
+ if (found == g_instance_to_dispatcher->end())
+ return NULL;
+ return found->second;
+}
+
+// static
+const void* PluginDispatcher::GetInterfaceFromDispatcher(
+ const char* interface) {
+ // All interfaces the plugin requests of the browser are "PPB".
+ const InterfaceProxy::Info* info = GetPPBInterfaceInfo(interface);
+ if (!info)
+ return NULL;
+ return info->interface_ptr;
+}
+
+bool PluginDispatcher::InitPluginWithChannel(
+ PluginDelegate* delegate,
+ const IPC::ChannelHandle& channel_handle,
+ bool is_client) {
+ if (!Dispatcher::InitWithChannel(delegate, channel_handle, is_client))
+ return false;
+ plugin_delegate_ = delegate;
+ plugin_dispatcher_id_ = plugin_delegate_->Register(this);
+
+ // The message filter will intercept and process certain messages directly
+ // on the I/O thread.
+ channel()->AddFilter(
+ new PluginMessageFilter(delegate->GetGloballySeenInstanceIDSet()));
+ return true;
+}
+
+bool PluginDispatcher::IsPlugin() const {
+ return true;
+}
+
+bool PluginDispatcher::Send(IPC::Message* msg) {
+ DCHECK(MessageLoop::current());
+ TRACE_EVENT2("ppapi proxy", "PluginDispatcher::Send",
+ "Class", IPC_MESSAGE_ID_CLASS(msg->type()),
+ "Line", IPC_MESSAGE_ID_LINE(msg->type()));
+ // We always want plugin->renderer messages to arrive in-order. If some sync
+ // and some async messages are send in response to a synchronous
+ // renderer->plugin call, the sync reply will be processed before the async
+ // reply, and everything will be confused.
+ //
+ // Allowing all async messages to unblock the renderer means more reentrancy
+ // there but gives correct ordering.
+ msg->set_unblock(true);
+ return Dispatcher::Send(msg);
+}
+
+bool PluginDispatcher::OnMessageReceived(const IPC::Message& msg) {
+ TRACE_EVENT2("ppapi proxy", "PluginDispatcher::OnMessageReceived",
+ "Class", IPC_MESSAGE_ID_CLASS(msg.type()),
+ "Line", IPC_MESSAGE_ID_LINE(msg.type()));
+ // Handle common control messages.
+ if (Dispatcher::OnMessageReceived(msg))
+ return true;
+
+ if (msg.routing_id() == MSG_ROUTING_CONTROL) {
+ // Handle some plugin-specific control messages.
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PluginDispatcher, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_SupportsInterface, OnMsgSupportsInterface)
+ IPC_MESSAGE_HANDLER(PpapiMsg_SetPreferences, OnMsgSetPreferences)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+ }
+
+ if (msg.routing_id() <= 0 || msg.routing_id() >= INTERFACE_ID_COUNT) {
+ // Host is sending us garbage. Since it's supposed to be trusted, this
+ // isn't supposed to happen. Crash here in all builds in case the renderer
+ // is compromised.
+ CHECK(false);
+ return true;
+ }
+
+ // There are two cases:
+ //
+ // * The first case is that the host is calling a PPP interface. It will
+ // always do a check for the interface before sending messages, and this
+ // will create the necessary interface proxy at that time. So when we
+ // actually receive a message, we know such a proxy will exist.
+ //
+ // * The second case is that the host is sending a response to the plugin
+ // side of a PPB interface (some, like the URL loader, have complex
+ // response messages). Since the host is trusted and not supposed to be
+ // doing silly things, we can just create a PPB proxy project on demand the
+ // first time it's needed.
+
+ InterfaceProxy* proxy = target_proxies_[msg.routing_id()].get();
+ if (!proxy) {
+ // Handle the first time the host calls a PPB reply interface by
+ // autocreating it.
+ const InterfaceProxy::Info* info = GetPPBInterfaceInfo(
+ static_cast<InterfaceID>(msg.routing_id()));
+ if (!info) {
+ NOTREACHED();
+ return true;
+ }
+ proxy = info->create_proxy(this, NULL);
+ target_proxies_[info->id].reset(proxy);
+ }
+
+ return proxy->OnMessageReceived(msg);
+}
+
+void PluginDispatcher::OnChannelError() {
+ Dispatcher::OnChannelError();
+
+ // The renderer has crashed or exited. This channel and all instances
+ // associated with it are no longer valid.
+ ForceFreeAllInstances();
+ // TODO(brettw) free resources too!
+ delete this;
+}
+
+void PluginDispatcher::DidCreateInstance(PP_Instance instance) {
+ if (!g_instance_to_dispatcher)
+ g_instance_to_dispatcher = new InstanceToDispatcherMap;
+ (*g_instance_to_dispatcher)[instance] = this;
+
+ instance_map_[instance] = InstanceData();
+}
+
+void PluginDispatcher::DidDestroyInstance(PP_Instance instance) {
+ InstanceDataMap::iterator it = instance_map_.find(instance);
+ if (it != instance_map_.end())
+ instance_map_.erase(it);
+
+ if (g_instance_to_dispatcher) {
+ InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find(
+ instance);
+ if (found != g_instance_to_dispatcher->end()) {
+ DCHECK(found->second == this);
+ g_instance_to_dispatcher->erase(found);
+ } else {
+ NOTREACHED();
+ }
+ }
+}
+
+InstanceData* PluginDispatcher::GetInstanceData(PP_Instance instance) {
+ InstanceDataMap::iterator it = instance_map_.find(instance);
+ return (it == instance_map_.end()) ? NULL : &it->second;
+}
+
+void PluginDispatcher::PostToWebKitThread(
+ const tracked_objects::Location& from_here,
+ const base::Closure& task) {
+ return plugin_delegate_->PostToWebKitThread(from_here, task);
+}
+
+bool PluginDispatcher::SendToBrowser(IPC::Message* msg) {
+ return plugin_delegate_->SendToBrowser(msg);
+}
+
+ppapi::WebKitForwarding* PluginDispatcher::GetWebKitForwarding() {
+ return plugin_delegate_->GetWebKitForwarding();
+}
+
+::ppapi::FunctionGroupBase* PluginDispatcher::GetFunctionAPI(
+ pp::proxy::InterfaceID id) {
+ scoped_ptr< ::ppapi::FunctionGroupBase >& proxy = function_proxies_[id];
+
+ if (proxy.get())
+ return proxy.get();
+
+ if (id == INTERFACE_ID_PPB_CHAR_SET)
+ proxy.reset(new PPB_CharSet_Proxy(this, NULL));
+ else if(id == INTERFACE_ID_PPB_CURSORCONTROL)
+ proxy.reset(new PPB_CursorControl_Proxy(this, NULL));
+ else if (id == INTERFACE_ID_PPB_FONT)
+ proxy.reset(new PPB_Font_Proxy(this, NULL));
+ else if (id == INTERFACE_ID_PPB_INSTANCE)
+ proxy.reset(new PPB_Instance_Proxy(this, NULL));
+ else if (id == INTERFACE_ID_RESOURCE_CREATION)
+ proxy.reset(new ResourceCreationProxy(this));
+
+ return proxy.get();
+}
+
+void PluginDispatcher::ForceFreeAllInstances() {
+ if (!g_instance_to_dispatcher)
+ return;
+
+ // Iterating will remove each item from the map, so we need to make a copy
+ // to avoid things changing out from under is.
+ InstanceToDispatcherMap temp_map = *g_instance_to_dispatcher;
+ for (InstanceToDispatcherMap::iterator i = temp_map.begin();
+ i != temp_map.end(); ++i) {
+ if (i->second == this) {
+ // Synthesize an "instance destroyed" message, this will notify the
+ // plugin and also remove it from our list of tracked plugins.
+ PpapiMsg_PPPInstance_DidDestroy msg(INTERFACE_ID_PPP_INSTANCE, i->first);
+ OnMessageReceived(msg);
+ delete msg.GetReplyDeserializer();
+ }
+ }
+}
+
+void PluginDispatcher::OnMsgSupportsInterface(
+ const std::string& interface_name,
+ bool* result) {
+ *result = false;
+
+ // Setup a proxy for receiving the messages from this interface.
+ const InterfaceProxy::Info* info = GetPPPInterfaceInfo(interface_name);
+ if (!info)
+ return; // Interface not supported by proxy.
+
+ // Check for a cached result.
+ if (target_proxies_[info->id].get()) {
+ *result = true;
+ return;
+ }
+
+ // Query the plugin & cache the result.
+ const void* interface_functions = GetLocalInterface(interface_name.c_str());
+ if (!interface_functions)
+ return;
+ target_proxies_[info->id].reset(
+ info->create_proxy(this, interface_functions));
+ *result = true;
+}
+
+void PluginDispatcher::OnMsgSetPreferences(const ::ppapi::Preferences& prefs) {
+ // The renderer may send us preferences more than once (currently this
+ // happens every time a new plugin instance is created). Since we don't have
+ // a way to signal to the plugin that the preferences have changed, changing
+ // the default fonts and such in the middle of a running plugin could be
+ // confusing to it. As a result, we never allow the preferences to be changed
+ // once they're set. The user will have to restart to get new font prefs
+ // propogated to plugins.
+ if (!received_preferences_) {
+ received_preferences_ = true;
+ preferences_ = prefs;
+ }
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/plugin_dispatcher.h b/ppapi/proxy/plugin_dispatcher.h
new file mode 100644
index 0000000..ae6da60
--- /dev/null
+++ b/ppapi/proxy/plugin_dispatcher.h
@@ -0,0 +1,174 @@
+// 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_PLUGIN_DISPATCHER_H_
+#define PPAPI_PROXY_PLUGIN_DISPATCHER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/hash_tables.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/process.h"
+#include "build/build_config.h"
+#include "ppapi/c/pp_rect.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/dispatcher.h"
+#include "ppapi/shared_impl/function_group_base.h"
+#include "ppapi/shared_impl/ppapi_preferences.h"
+
+class MessageLoop;
+
+namespace base {
+class WaitableEvent;
+}
+
+namespace ppapi {
+struct Preferences;
+}
+
+namespace pp {
+namespace proxy {
+
+// Used to keep track of per-instance data.
+struct InstanceData {
+ InstanceData() : fullscreen(PP_FALSE) {}
+ PP_Rect position;
+ PP_Bool fullscreen;
+};
+
+class PluginDispatcher : public Dispatcher {
+ public:
+ class PluginDelegate : public ProxyChannel::Delegate {
+ public:
+ // Returns the set used for globally uniquifying PP_Instances. This same
+ // set must be returned for all channels.
+ //
+ // DEREFERENCE ONLY ON THE I/O THREAD.
+ virtual std::set<PP_Instance>* GetGloballySeenInstanceIDSet() = 0;
+
+ // Returns the WebKit forwarding object used to make calls into WebKit.
+ // Necessary only on the plugin side.
+ virtual ppapi::WebKitForwarding* GetWebKitForwarding() = 0;
+
+ // Posts the given task to the WebKit thread associated with this plugin
+ // process. The WebKit thread should be lazily created if it does not
+ // exist yet.
+ virtual void PostToWebKitThread(const tracked_objects::Location& from_here,
+ const base::Closure& task) = 0;
+
+ // Sends the given message to the browser. Identical semantics to
+ // IPC::Message::Sender interface.
+ virtual bool SendToBrowser(IPC::Message* msg) = 0;
+
+ // Registers the plugin dispatcher and returns an ID.
+ // Plugin dispatcher IDs will be used to dispatch messages from the browser.
+ // Each call to Register() has to be matched with a call to Unregister().
+ virtual uint32 Register(PluginDispatcher* plugin_dispatcher) = 0;
+ virtual void Unregister(uint32 plugin_dispatcher_id) = 0;
+ };
+
+ // Constructor for the plugin side. The init and shutdown functions will be
+ // will be automatically called when requested by the renderer side. The
+ // module ID will be set upon receipt of the InitializeModule message.
+ //
+ // You must call InitPluginWithChannel after the constructor.
+ PluginDispatcher(base::ProcessHandle remote_process_handle,
+ GetInterfaceFunc get_interface);
+ virtual ~PluginDispatcher();
+
+ // The plugin side maintains a mapping from PP_Instance to Dispatcher so
+ // that we can send the messages to the right channel if there are multiple
+ // renderers sharing the same plugin. This mapping is maintained by
+ // DidCreateInstance/DidDestroyInstance.
+ static PluginDispatcher* GetForInstance(PP_Instance instance);
+
+ static const void* GetInterfaceFromDispatcher(const char* interface);
+
+ // You must call this function before anything else. Returns true on success.
+ // The delegate pointer must outlive this class, ownership is not
+ // transferred.
+ bool InitPluginWithChannel(PluginDelegate* delegate,
+ const IPC::ChannelHandle& channel_handle,
+ bool is_client);
+
+ // Dispatcher overrides.
+ virtual bool IsPlugin() const;
+ virtual bool Send(IPC::Message* msg);
+
+ // IPC::Channel::Listener implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+ virtual void OnChannelError();
+
+ // Keeps track of which dispatcher to use for each instance, active instances
+ // and tracks associated data like the current size.
+ void DidCreateInstance(PP_Instance instance);
+ void DidDestroyInstance(PP_Instance instance);
+
+ // Gets the data for an existing instance, or NULL if the instance id doesn't
+ // correspond to a known instance.
+ InstanceData* GetInstanceData(PP_Instance instance);
+
+ // Posts the given task to the WebKit thread.
+ void PostToWebKitThread(const tracked_objects::Location& from_here,
+ const base::Closure& task);
+
+ // Calls the PluginDelegate.SendToBrowser function.
+ bool SendToBrowser(IPC::Message* msg);
+
+ // Returns the WebKitForwarding object used to forward events to WebKit.
+ ppapi::WebKitForwarding* GetWebKitForwarding();
+
+ // Returns the Preferences.
+ const ppapi::Preferences& preferences() const { return preferences_; }
+
+ // Returns the "new-style" function API for the given interface ID, creating
+ // it if necessary.
+ // TODO(brettw) this is in progress. It should be merged with the target
+ // proxies so there is one list to consult.
+ ppapi::FunctionGroupBase* GetFunctionAPI(
+ pp::proxy::InterfaceID id);
+
+ uint32 plugin_dispatcher_id() const { return plugin_dispatcher_id_; }
+
+ private:
+ friend class PluginDispatcherTest;
+
+ // Notifies all live instances that they're now closed. This is used when
+ // a renderer crashes or some other error is received.
+ void ForceFreeAllInstances();
+
+ // IPC message handlers.
+ void OnMsgSupportsInterface(const std::string& interface_name, bool* result);
+ void OnMsgSetPreferences(const ::ppapi::Preferences& prefs);
+
+ PluginDelegate* plugin_delegate_;
+
+ // All target proxies currently created. These are ones that receive
+ // messages.
+ scoped_ptr<InterfaceProxy> target_proxies_[INTERFACE_ID_COUNT];
+
+ // Function proxies created for "new-style" FunctionGroups.
+ // TODO(brettw) this is in progress. It should be merged with the target
+ // proxies so there is one list to consult.
+ scoped_ptr< ::ppapi::FunctionGroupBase >
+ function_proxies_[INTERFACE_ID_COUNT];
+
+ typedef base::hash_map<PP_Instance, InstanceData> InstanceDataMap;
+ InstanceDataMap instance_map_;
+
+ // The preferences sent from the host. We only want to set this once, which
+ // is what the received_preferences_ indicates. See OnMsgSetPreferences.
+ bool received_preferences_;
+ ppapi::Preferences preferences_;
+
+ uint32 plugin_dispatcher_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginDispatcher);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PLUGIN_DISPATCHER_H_
diff --git a/ppapi/proxy/plugin_dispatcher_unittest.cc b/ppapi/proxy/plugin_dispatcher_unittest.cc
new file mode 100644
index 0000000..f3e8da5
--- /dev/null
+++ b/ppapi/proxy/plugin_dispatcher_unittest.cc
@@ -0,0 +1,89 @@
+// 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 "base/memory/scoped_ptr.h"
+#include "ipc/ipc_message_utils.h"
+#include "ppapi/c/ppb_audio.h"
+#include "ppapi/c/ppp_instance.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+bool received_create = false;
+
+// Implement PPB_Audio since it's a relatively simple PPB interface and
+// includes bidirectional communication.
+PP_Resource Create(PP_Instance instance, PP_Resource config,
+ PPB_Audio_Callback audio_callback, void* user_data) {
+ received_create = true;
+ return 0;
+}
+PP_Bool IsAudio(PP_Resource resource) {
+ return PP_FALSE;
+}
+PP_Resource GetCurrentConfig(PP_Resource audio) {
+ return 0;
+}
+PP_Bool StartPlayback(PP_Resource audio) {
+ return PP_FALSE;
+}
+PP_Bool StopPlayback(PP_Resource audio) {
+ return PP_FALSE;
+}
+
+PPB_Audio dummy_audio_interface = {
+ &Create,
+ &IsAudio,
+ &GetCurrentConfig,
+ &StartPlayback,
+ &StopPlayback
+};
+
+PPP_Instance dummy_ppp_instance_interface = {};
+
+} // namespace
+
+class PluginDispatcherTest : public PluginProxyTest {
+ public:
+ PluginDispatcherTest() {}
+
+ bool HasTargetProxy(InterfaceID id) {
+ return !!plugin_dispatcher()->target_proxies_[id].get();
+ }
+};
+
+TEST_F(PluginDispatcherTest, SupportsInterface) {
+ RegisterTestInterface(PPB_AUDIO_INTERFACE, &dummy_audio_interface);
+ RegisterTestInterface(PPP_INSTANCE_INTERFACE, &dummy_ppp_instance_interface);
+
+ // Sending a request for a random interface should fail.
+ EXPECT_FALSE(SupportsInterface("Random interface"));
+
+ // Sending a request for a PPB interface should fail even though we've
+ // registered it as existing in the GetInterface function (the plugin proxy
+ // should only respond to PPP interfaces when asked if it supports them).
+ EXPECT_FALSE(SupportsInterface(PPB_AUDIO_INTERFACE));
+
+ // Sending a request for a supported PPP interface should succeed.
+ EXPECT_TRUE(SupportsInterface(PPP_INSTANCE_INTERFACE));
+}
+
+TEST_F(PluginDispatcherTest, PPBCreation) {
+ // Sending a PPB message out of the blue should create a target proxy for
+ // that interface in the plugin.
+ EXPECT_FALSE(HasTargetProxy(INTERFACE_ID_PPB_AUDIO));
+ PpapiMsg_PPBAudio_NotifyAudioStreamCreated audio_msg(
+ INTERFACE_ID_PPB_AUDIO, HostResource(), 0,
+ IPC::PlatformFileForTransit(), base::SharedMemoryHandle(), 0);
+ plugin_dispatcher()->OnMessageReceived(audio_msg);
+ EXPECT_TRUE(HasTargetProxy(INTERFACE_ID_PPB_AUDIO));
+}
+
+} // namespace proxy
+} // namespace pp
+
diff --git a/ppapi/proxy/plugin_message_filter.cc b/ppapi/proxy/plugin_message_filter.cc
new file mode 100644
index 0000000..9df2208
--- /dev/null
+++ b/ppapi/proxy/plugin_message_filter.cc
@@ -0,0 +1,61 @@
+// 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/plugin_message_filter.h"
+
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace pp {
+namespace proxy {
+
+PluginMessageFilter::PluginMessageFilter(
+ std::set<PP_Instance>* seen_instance_ids)
+ : seen_instance_ids_(seen_instance_ids),
+ channel_(NULL) {
+}
+
+PluginMessageFilter::~PluginMessageFilter() {
+}
+
+void PluginMessageFilter::OnFilterAdded(IPC::Channel* channel) {
+ channel_ = channel;
+}
+
+void PluginMessageFilter::OnFilterRemoved() {
+ channel_ = NULL;
+}
+
+bool PluginMessageFilter::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PluginMessageFilter, message)
+ IPC_MESSAGE_HANDLER(PpapiMsg_ReserveInstanceId, OnMsgReserveInstanceId)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+bool PluginMessageFilter::Send(IPC::Message* msg) {
+ if (channel_)
+ return channel_->Send(msg);
+ delete msg;
+ return false;
+}
+
+void PluginMessageFilter::OnMsgReserveInstanceId(PP_Instance instance,
+ bool* usable) {
+ // See the message definition for how this works.
+ if (seen_instance_ids_->find(instance) != seen_instance_ids_->end()) {
+ // Instance ID already seen, reject it.
+ *usable = false;
+ return;
+ }
+
+ // This instance ID is new so we can return that it's usable and mark it as
+ // used for future reference.
+ seen_instance_ids_->insert(instance);
+ *usable = true;
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/plugin_message_filter.h b/ppapi/proxy/plugin_message_filter.h
new file mode 100644
index 0000000..fa3b2f4
--- /dev/null
+++ b/ppapi/proxy/plugin_message_filter.h
@@ -0,0 +1,56 @@
+// 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_PLUGIN_MESSAGE_FILTER_H_
+#define PPAPI_PROXY_PLUGIN_MESSAGE_FILTER_H_
+
+#include <set>
+
+#include "ipc/ipc_channel_proxy.h"
+#include "ipc/ipc_message.h"
+#include "ppapi/c/pp_instance.h"
+
+namespace pp {
+namespace proxy {
+
+// Listens for messages on the I/O thread of the plugin and handles some of
+// them to avoid needing to block on the plugin.
+//
+// There is one instance of this class for each renderer channel (same as for
+// the PluginDispatchers).
+class PluginMessageFilter : public IPC::ChannelProxy::MessageFilter,
+ public IPC::Message::Sender {
+ public:
+ // The input is a pointer to a set that will be used to uniquify PP_Instances
+ // across all renderer channels. The same pointer should be passed to each
+ // MessageFilter to ensure uniqueness, and the value should outlive this
+ // class.
+ PluginMessageFilter(std::set<PP_Instance>* seen_instance_ids);
+ virtual ~PluginMessageFilter();
+
+ // MessageFilter implementation.
+ virtual void OnFilterAdded(IPC::Channel* channel);
+ virtual void OnFilterRemoved();
+ virtual bool OnMessageReceived(const IPC::Message& message);
+
+ // Message::Sender implementation.
+ virtual bool Send(IPC::Message* msg);
+
+ private:
+ void OnMsgReserveInstanceId(PP_Instance instance, bool* usable);
+
+ // All instance IDs every queried by any renderer on this plugin. This is
+ // used to make sure that new instance IDs are unique. This is a non-owning
+ // pointer, it will be managed by the later that creates this class.
+ std::set<PP_Instance>* seen_instance_ids_;
+
+ // The IPC channel to the renderer. May be NULL if we're not currently
+ // attached as a filter.
+ IPC::Channel* channel_;
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PLUGIN_MESSAGE_FILTER_H_
diff --git a/ppapi/proxy/plugin_resource.cc b/ppapi/proxy/plugin_resource.cc
new file mode 100644
index 0000000..d25dde1
--- /dev/null
+++ b/ppapi/proxy/plugin_resource.cc
@@ -0,0 +1,29 @@
+// 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/plugin_resource.h"
+
+namespace pp {
+namespace proxy {
+
+PluginResource::PluginResource(const HostResource& resource)
+ : host_resource_(resource) {
+}
+
+PluginResource::~PluginResource() {
+}
+
+#define DEFINE_TYPE_GETTER(RESOURCE) \
+ RESOURCE* PluginResource::As##RESOURCE() { return NULL; }
+FOR_ALL_PLUGIN_RESOURCES(DEFINE_TYPE_GETTER)
+#undef DEFINE_TYPE_GETTER
+
+PluginDispatcher* PluginResource::GetDispatcher() {
+ PluginDispatcher* disp = PluginDispatcher::GetForInstance(instance());
+ CHECK(disp);
+ return disp;
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/plugin_resource.h b/ppapi/proxy/plugin_resource.h
new file mode 100644
index 0000000..eff74b4
--- /dev/null
+++ b/ppapi/proxy/plugin_resource.h
@@ -0,0 +1,97 @@
+// 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_PLUGIN_RESOURCE_H_
+#define PPAPI_PROXY_PLUGIN_RESOURCE_H_
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/shared_impl/resource_object_base.h"
+
+// If you inherit from resource, make sure you add the class name here.
+#define FOR_ALL_PLUGIN_RESOURCES(F) \
+ F(Audio) \
+ F(AudioConfig) \
+ F(Broker) \
+ F(Buffer) \
+ F(Context3D) \
+ F(FileChooser) \
+ F(FileRef) \
+ F(FileSystem) \
+ F(FlashMenu) \
+ F(FlashNetConnector) \
+ F(Font) \
+ F(Graphics2D) \
+ F(ImageData) \
+ F(MockResource) \
+ F(PrivateFontFile) \
+ F(Surface3D) \
+ F(URLLoader) \
+ F(URLRequestInfo)\
+ F(URLResponseInfo)
+
+namespace pp {
+namespace proxy {
+
+// Forward declaration of Resource classes.
+#define DECLARE_RESOURCE_CLASS(RESOURCE) class RESOURCE;
+FOR_ALL_PLUGIN_RESOURCES(DECLARE_RESOURCE_CLASS)
+#undef DECLARE_RESOURCE_CLASS
+
+class PluginResource : public ::ppapi::ResourceObjectBase {
+ public:
+ PluginResource(const HostResource& resource);
+ virtual ~PluginResource();
+
+ // Returns NULL if the resource is invalid or is a different type.
+ template<typename T> static T* GetAs(PP_Resource res) {
+ PluginResource* resource =
+ PluginResourceTracker::GetInstance()->GetResourceObject(res);
+ return resource ? resource->Cast<T>() : NULL;
+ }
+
+ template <typename T> T* Cast() { return NULL; }
+
+ PP_Instance instance() const { return host_resource_.instance(); }
+
+ // Returns the host resource ID for sending to the host process.
+ const HostResource& host_resource() const {
+ return host_resource_;
+ }
+
+ PluginDispatcher* GetDispatcher();
+
+ private:
+ // Type-specific getters for individual resource types. These will return
+ // NULL if the resource does not match the specified type. Used by the Cast()
+ // function.
+ #define DEFINE_TYPE_GETTER(RESOURCE) \
+ virtual RESOURCE* As##RESOURCE();
+ FOR_ALL_PLUGIN_RESOURCES(DEFINE_TYPE_GETTER)
+ #undef DEFINE_TYPE_GETTER
+
+ // The resource ID in the host that this object corresponds to. Inside the
+ // plugin we'll remap the resource IDs so we can have many host processes
+ // each independently generating resources (which may conflict) but the IDs
+ // in the plugin will all be unique.
+ HostResource host_resource_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginResource);
+};
+
+// Cast() specializations.
+#define DEFINE_RESOURCE_CAST(Type) \
+ template <> inline Type* PluginResource::Cast<Type>() { \
+ return As##Type(); \
+ }
+FOR_ALL_PLUGIN_RESOURCES(DEFINE_RESOURCE_CAST)
+#undef DEFINE_RESOURCE_CAST
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PLUGIN_RESOURCE_H_
diff --git a/ppapi/proxy/plugin_resource_tracker.cc b/ppapi/proxy/plugin_resource_tracker.cc
new file mode 100644
index 0000000..e1726cf
--- /dev/null
+++ b/ppapi/proxy/plugin_resource_tracker.cc
@@ -0,0 +1,183 @@
+// 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/plugin_resource_tracker.h"
+
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/shared_impl/tracker_base.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+// When non-NULL, this object overrides the ResourceTrackerSingleton.
+PluginResourceTracker* g_resource_tracker_override = NULL;
+
+::ppapi::TrackerBase* GetTrackerBase() {
+ return PluginResourceTracker::GetInstance();
+}
+
+} // namespace
+
+PluginResourceTracker::ResourceInfo::ResourceInfo() : ref_count(0) {
+}
+
+PluginResourceTracker::ResourceInfo::ResourceInfo(int rc,
+ linked_ptr<PluginResource> r)
+ : ref_count(rc),
+ resource(r) {
+}
+
+PluginResourceTracker::ResourceInfo::ResourceInfo(const ResourceInfo& other)
+ : ref_count(other.ref_count),
+ resource(other.resource) {
+ // Wire up the new shared resource tracker base to use our implementation.
+ ::ppapi::TrackerBase::Init(&GetTrackerBase);
+}
+
+PluginResourceTracker::ResourceInfo::~ResourceInfo() {
+}
+
+PluginResourceTracker::ResourceInfo&
+PluginResourceTracker::ResourceInfo::operator=(
+ const ResourceInfo& other) {
+ ref_count = other.ref_count;
+ resource = other.resource;
+ return *this;
+}
+
+// Start counting resources at a high number to avoid collisions with vars (to
+// help debugging).
+PluginResourceTracker::PluginResourceTracker()
+ : last_resource_id_(0x00100000) {
+}
+
+PluginResourceTracker::~PluginResourceTracker() {
+}
+
+// static
+void PluginResourceTracker::SetInstanceForTest(PluginResourceTracker* tracker) {
+ g_resource_tracker_override = tracker;
+}
+
+// static
+PluginResourceTracker* PluginResourceTracker::GetInstance() {
+ if (g_resource_tracker_override)
+ return g_resource_tracker_override;
+ return Singleton<PluginResourceTracker>::get();
+}
+
+// static
+::ppapi::TrackerBase*
+PluginResourceTracker::GetTrackerBaseInstance() {
+ return GetInstance();
+}
+
+PluginResource* PluginResourceTracker::GetResourceObject(
+ PP_Resource pp_resource) {
+ ResourceMap::iterator found = resource_map_.find(pp_resource);
+ if (found == resource_map_.end())
+ return NULL;
+ return found->second.resource.get();
+}
+
+PP_Resource PluginResourceTracker::AddResource(
+ linked_ptr<PluginResource> object) {
+ PP_Resource plugin_resource = ++last_resource_id_;
+ DCHECK(resource_map_.find(plugin_resource) == resource_map_.end());
+ resource_map_[plugin_resource] = ResourceInfo(1, object);
+ if (!object->host_resource().is_null()) {
+ // The host resource ID will be 0 for resources that only exist in the
+ // plugin process. Don't add those to the list.
+ host_resource_map_[object->host_resource()] = plugin_resource;
+ }
+ return plugin_resource;
+}
+
+void PluginResourceTracker::AddRefResource(PP_Resource resource) {
+ ResourceMap::iterator found = resource_map_.find(resource);
+ if (found == resource_map_.end()) {
+ NOTREACHED();
+ return;
+ }
+ found->second.ref_count++;
+}
+
+void PluginResourceTracker::ReleaseResource(PP_Resource resource) {
+ ReleasePluginResourceRef(resource, true);
+}
+
+PP_Resource PluginResourceTracker::PluginResourceForHostResource(
+ const HostResource& resource) const {
+ HostResourceMap::const_iterator found = host_resource_map_.find(resource);
+ if (found == host_resource_map_.end())
+ return 0;
+ return found->second;
+}
+
+::ppapi::ResourceObjectBase* PluginResourceTracker::GetResourceAPI(
+ PP_Resource res) {
+ ResourceMap::iterator found = resource_map_.find(res);
+ if (found == resource_map_.end())
+ return NULL;
+ return found->second.resource.get();
+}
+
+::ppapi::FunctionGroupBase* PluginResourceTracker::GetFunctionAPI(
+ PP_Instance inst,
+ pp::proxy::InterfaceID id) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(inst);
+ if (dispatcher)
+ return dispatcher->GetFunctionAPI(id);
+ return NULL;
+}
+
+PP_Instance PluginResourceTracker::GetInstanceForResource(
+ PP_Resource resource) {
+ ResourceMap::iterator found = resource_map_.find(resource);
+ if (found == resource_map_.end())
+ return 0;
+ return found->second.resource->instance();
+}
+
+void PluginResourceTracker::ReleasePluginResourceRef(
+ const PP_Resource& resource,
+ bool notify_browser_on_release) {
+ ResourceMap::iterator found = resource_map_.find(resource);
+ if (found == resource_map_.end())
+ return;
+ found->second.ref_count--;
+ if (found->second.ref_count == 0) {
+ // Keep a reference while removing in case the destructor ends up
+ // re-entering. That way, when the destructor is called, it's out of the
+ // maps.
+ linked_ptr<PluginResource> plugin_resource = found->second.resource;
+ PluginDispatcher* dispatcher =
+ PluginDispatcher::GetForInstance(plugin_resource->instance());
+ HostResource host_resource = plugin_resource->host_resource();
+ if (!host_resource.is_null())
+ host_resource_map_.erase(host_resource);
+ resource_map_.erase(found);
+ plugin_resource.reset();
+
+ // dispatcher can be NULL if the plugin held on to a resource after the
+ // instance was destroyed. In that case the browser-side resource has
+ // already been freed correctly on the browser side. The host_resource
+ // will be NULL for proxy-only resources, which we obviously don't need to
+ // tell the host about.
+ if (notify_browser_on_release && dispatcher && !host_resource.is_null()) {
+ dispatcher->Send(new PpapiHostMsg_PPBCore_ReleaseResource(
+ INTERFACE_ID_PPB_CORE, host_resource));
+ }
+ }
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/plugin_resource_tracker.h b/ppapi/proxy/plugin_resource_tracker.h
new file mode 100644
index 0000000..83b7840
--- /dev/null
+++ b/ppapi/proxy/plugin_resource_tracker.h
@@ -0,0 +1,107 @@
+// 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_PLUGIN_RESOURCE_TRACKER_H_
+#define PPAPI_PROXY_PLUGIN_RESOURCE_TRACKER_H_
+
+#include <map>
+#include <utility>
+
+#include "base/compiler_specific.h"
+#include "base/memory/linked_ptr.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_stdint.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/shared_impl/tracker_base.h"
+
+template<typename T> struct DefaultSingletonTraits;
+
+namespace pp {
+namespace proxy {
+
+class PluginDispatcher;
+class PluginResource;
+
+class PluginResourceTracker : public ::ppapi::TrackerBase {
+ public:
+ // Called by tests that want to specify a specific ResourceTracker. This
+ // allows them to use a unique one each time and avoids singletons sticking
+ // around across tests.
+ static void SetInstanceForTest(PluginResourceTracker* tracker);
+
+ // Returns the global singleton resource tracker for the plugin.
+ static PluginResourceTracker* GetInstance();
+ static ::ppapi::TrackerBase* GetTrackerBaseInstance();
+
+ // Returns the object associated with the given resource ID, or NULL if
+ // there isn't one.
+ PluginResource* GetResourceObject(PP_Resource pp_resource);
+
+ // Adds the given resource object to the tracked list, and returns the
+ // plugin-local PP_Resource ID that identifies the resource. Note that this
+ // PP_Resource is not valid to send to the host, use
+ // PluginResource.host_resource() to get that.
+ PP_Resource AddResource(linked_ptr<PluginResource> object);
+
+ void AddRefResource(PP_Resource resource);
+ void ReleaseResource(PP_Resource resource);
+
+ // Given a host resource, maps it to an existing plugin resource ID if it
+ // exists, or returns 0 on failure.
+ PP_Resource PluginResourceForHostResource(
+ const HostResource& resource) const;
+
+ // TrackerBase.
+ virtual ::ppapi::ResourceObjectBase* GetResourceAPI(
+ PP_Resource res) OVERRIDE;
+ virtual ::ppapi::FunctionGroupBase* GetFunctionAPI(
+ PP_Instance inst,
+ pp::proxy::InterfaceID id) OVERRIDE;
+ virtual PP_Instance GetInstanceForResource(PP_Resource resource) OVERRIDE;
+
+ private:
+ friend struct DefaultSingletonTraits<PluginResourceTracker>;
+ friend class PluginResourceTrackerTest;
+ friend class PluginProxyTestHarness;
+
+ PluginResourceTracker();
+ virtual ~PluginResourceTracker();
+
+ struct ResourceInfo {
+ ResourceInfo();
+ ResourceInfo(int ref_count, linked_ptr<PluginResource> r);
+ ResourceInfo(const ResourceInfo& other);
+ ~ResourceInfo();
+
+ ResourceInfo& operator=(const ResourceInfo& other);
+
+ int ref_count;
+ linked_ptr<PluginResource> resource; // May be NULL.
+ };
+
+ void ReleasePluginResourceRef(const PP_Resource& var,
+ bool notify_browser_on_release);
+
+ // Map of plugin resource IDs to the information tracking that resource.
+ typedef std::map<PP_Resource, ResourceInfo> ResourceMap;
+ ResourceMap resource_map_;
+
+ // Map of host instance/resource pairs to a plugin resource ID.
+ typedef std::map<HostResource, PP_Resource> HostResourceMap;
+ HostResourceMap host_resource_map_;
+
+ // Tracks the last ID we've sent out as a plugin resource so we don't send
+ // duplicates.
+ PP_Resource last_resource_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginResourceTracker);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PLUGIN_RESOURCE_TRACKER_H_
diff --git a/ppapi/proxy/plugin_resource_tracker_unittest.cc b/ppapi/proxy/plugin_resource_tracker_unittest.cc
new file mode 100644
index 0000000..5a317128
--- /dev/null
+++ b/ppapi/proxy/plugin_resource_tracker_unittest.cc
@@ -0,0 +1,74 @@
+// 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 "base/memory/scoped_ptr.h"
+#include "base/process.h"
+#include "ppapi/proxy/mock_resource.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+// Object so we know when a resource has been released.
+class TrackedMockResource : public MockResource {
+ public:
+ TrackedMockResource(const HostResource& serialized)
+ : MockResource(serialized) {
+ tracked_alive_count++;
+ }
+ ~TrackedMockResource() {
+ tracked_alive_count--;
+ }
+
+ static int tracked_alive_count;
+};
+
+int TrackedMockResource::tracked_alive_count = 0;
+
+} // namespace
+
+class PluginResourceTrackerTest : public PluginProxyTest {
+ public:
+ PluginResourceTrackerTest() {}
+ ~PluginResourceTrackerTest() {}
+
+ PluginResourceTracker& tracker() { return tracker_; }
+
+ private:
+ PluginResourceTracker tracker_;
+};
+
+TEST_F(PluginResourceTrackerTest, PluginResourceForHostResource) {
+ PP_Resource host_resource = 0x5678;
+
+ HostResource serialized;
+ serialized.SetHostResource(pp_instance(), host_resource);
+
+ // When we haven't added an object, the return value should be 0.
+ EXPECT_EQ(0, tracker().PluginResourceForHostResource(serialized));
+
+ EXPECT_EQ(0, TrackedMockResource::tracked_alive_count);
+ TrackedMockResource* object = new TrackedMockResource(serialized);
+ EXPECT_EQ(1, TrackedMockResource::tracked_alive_count);
+ PP_Resource plugin_resource =
+ tracker().AddResource(linked_ptr<PluginResource>(object));
+
+ // Now that the object has been added, the return value should be the plugin
+ // resource ID we already got.
+ EXPECT_EQ(plugin_resource,
+ tracker().PluginResourceForHostResource(serialized));
+
+ // Releasing the resource should have freed it.
+ tracker().ReleaseResource(plugin_resource);
+ EXPECT_EQ(0, TrackedMockResource::tracked_alive_count);
+ EXPECT_EQ(0, tracker().PluginResourceForHostResource(serialized));
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/plugin_var_serialization_rules.cc b/ppapi/proxy/plugin_var_serialization_rules.cc
new file mode 100644
index 0000000..8ba5574
--- /dev/null
+++ b/ppapi/proxy/plugin_var_serialization_rules.cc
@@ -0,0 +1,153 @@
+// 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/plugin_var_serialization_rules.h"
+
+#include "base/logging.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+
+namespace pp {
+namespace proxy {
+
+PluginVarSerializationRules::PluginVarSerializationRules()
+ : var_tracker_(PluginVarTracker::GetInstance()) {
+}
+
+PluginVarSerializationRules::~PluginVarSerializationRules() {
+}
+
+PP_Var PluginVarSerializationRules::SendCallerOwned(const PP_Var& var,
+ std::string* str_val) {
+ // Objects need special translations to get the IDs valid in the host.
+ if (var.type == PP_VARTYPE_OBJECT)
+ return var_tracker_->GetHostObject(var);
+
+ // Retrieve the string to use for IPC.
+ if (var.type == PP_VARTYPE_STRING) {
+ const std::string* var_string = var_tracker_->GetExistingString(var);
+ if (var_string)
+ *str_val = *var_string;
+ else
+ NOTREACHED() << "Trying to send unknown string over IPC.";
+ }
+ return var;
+}
+
+PP_Var PluginVarSerializationRules::BeginReceiveCallerOwned(
+ const PP_Var& var,
+ const std::string* str_val,
+ Dispatcher* dispatcher) {
+ if (var.type == PP_VARTYPE_STRING) {
+ // Convert the string to the context of the current process.
+ PP_Var ret;
+ ret.type = PP_VARTYPE_STRING;
+ ret.value.as_id = var_tracker_->MakeString(*str_val);
+ return ret;
+ }
+
+ if (var.type == PP_VARTYPE_OBJECT) {
+ DCHECK(dispatcher->IsPlugin());
+ return var_tracker_->TrackObjectWithNoReference(
+ var, static_cast<PluginDispatcher*>(dispatcher));
+ }
+
+ return var;
+}
+
+void PluginVarSerializationRules::EndReceiveCallerOwned(const PP_Var& var) {
+ if (var.type == PP_VARTYPE_STRING) {
+ // Destroy the string BeginReceiveCallerOwned created above.
+ var_tracker_->Release(var);
+ } else if (var.type == PP_VARTYPE_OBJECT) {
+ var_tracker_->StopTrackingObjectWithNoReference(var);
+ }
+}
+
+PP_Var PluginVarSerializationRules::ReceivePassRef(const PP_Var& var,
+ const std::string& str_val,
+ Dispatcher* dispatcher) {
+ if (var.type == PP_VARTYPE_STRING) {
+ // Convert the string to the context of the current process.
+ PP_Var ret;
+ ret.type = PP_VARTYPE_STRING;
+ ret.value.as_id = var_tracker_->MakeString(str_val);
+ return ret;
+ }
+
+ // Overview of sending an object with "pass ref" from the browser to the
+ // plugin:
+ // Example 1 Example 2
+ // Plugin Browser Plugin Browser
+ // Before send 3 2 0 1
+ // Browser calls BeginSendPassRef 3 2 0 1
+ // Plugin calls ReceivePassRef 4 1 1 1
+ // Browser calls EndSendPassRef 4 1 1 1
+ //
+ // In example 1 before the send, the plugin has 3 refs which are represented
+ // as one ref in the browser (since the plugin only tells the browser when
+ // it's refcount goes from 1 -> 0). The initial state is that the browser
+ // plugin code started to return a value, which means it gets another ref
+ // on behalf of the caller. This needs to be transferred to the plugin and
+ // folded in to its set of refs it maintains (with one ref representing all
+ // fo them in the browser).
+ if (var.type == PP_VARTYPE_OBJECT) {
+ DCHECK(dispatcher->IsPlugin());
+ return var_tracker_->ReceiveObjectPassRef(
+ var, static_cast<PluginDispatcher*>(dispatcher));
+ }
+
+ // Other types are unchanged.
+ return var;
+}
+
+PP_Var PluginVarSerializationRules::BeginSendPassRef(const PP_Var& var,
+ std::string* str_val) {
+ // Overview of sending an object with "pass ref" from the plugin to the
+ // browser:
+ // Example 1 Example 2
+ // Plugin Browser Plugin Browser
+ // Before send 3 1 1 1
+ // Plugin calls BeginSendPassRef 3 1 1 1
+ // Browser calls ReceivePassRef 3 2 1 2
+ // Plugin calls EndSendPassRef 2 2 0 1
+ //
+ // The plugin maintains one ref count in the browser on behalf of the
+ // entire ref count in the plugin. When the plugin refcount goes to 0, it
+ // will call the browser to deref the object. This is why in example 2
+ // transferring the object ref to the browser involves no net change in the
+ // browser's refcount.
+
+ // Objects need special translations to get the IDs valid in the host.
+ if (var.type == PP_VARTYPE_OBJECT)
+ return var_tracker_->GetHostObject(var);
+
+ if (var.type == PP_VARTYPE_STRING) {
+ const std::string* var_string = var_tracker_->GetExistingString(var);
+ if (var_string)
+ *str_val = *var_string;
+ else
+ NOTREACHED() << "Trying to send unknown string over IPC.";
+ }
+ return var;
+}
+
+void PluginVarSerializationRules::EndSendPassRef(const PP_Var& var,
+ Dispatcher* dispatcher) {
+ // See BeginSendPassRef for an example of why we release our ref here.
+ // The var we have in our inner class has been converted to a host object
+ // by BeginSendPassRef. This means it's not a normal var valid in the plugin,
+ // so we need to use the special ReleaseHostObject.
+ if (var.type == PP_VARTYPE_OBJECT) {
+ var_tracker_->ReleaseHostObject(
+ static_cast<PluginDispatcher*>(dispatcher), var);
+ }
+}
+
+void PluginVarSerializationRules::ReleaseObjectRef(const PP_Var& var) {
+ var_tracker_->Release(var);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/plugin_var_serialization_rules.h b/ppapi/proxy/plugin_var_serialization_rules.h
new file mode 100644
index 0000000..e073602
--- /dev/null
+++ b/ppapi/proxy/plugin_var_serialization_rules.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2010 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_PLUGIN_VAR_SERIALIZATION_RULES_H_
+#define PPAPI_PROXY_PLUGIN_VAR_SERIALIZATION_RULES_H_
+
+#include "base/basictypes.h"
+#include "ppapi/proxy/var_serialization_rules.h"
+
+namespace pp {
+namespace proxy {
+
+class PluginVarTracker;
+
+// Implementation of the VarSerialization interface for the plugin.
+class PluginVarSerializationRules : public VarSerializationRules {
+ public:
+ // This class will use the given non-owning pointer to the var tracker to
+ // handle object refcounting and string conversion.
+ PluginVarSerializationRules();
+ ~PluginVarSerializationRules();
+
+ // VarSerialization implementation.
+ virtual PP_Var SendCallerOwned(const PP_Var& var, std::string* str_val);
+ virtual PP_Var BeginReceiveCallerOwned(const PP_Var& var,
+ const std::string* str_val,
+ Dispatcher* dispatcher);
+ virtual void EndReceiveCallerOwned(const PP_Var& var);
+ virtual PP_Var ReceivePassRef(const PP_Var& var,
+ const std::string& str_val,
+ Dispatcher* dispatcher);
+ virtual PP_Var BeginSendPassRef(const PP_Var& var, std::string* str_val);
+ virtual void EndSendPassRef(const PP_Var& var, Dispatcher* dispatcher);
+ virtual void ReleaseObjectRef(const PP_Var& var);
+
+ private:
+ PluginVarTracker* var_tracker_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginVarSerializationRules);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PLUGIN_VAR_SERIALIZATION_RULES_H_
diff --git a/ppapi/proxy/plugin_var_tracker.cc b/ppapi/proxy/plugin_var_tracker.cc
new file mode 100644
index 0000000..5734f96
--- /dev/null
+++ b/ppapi/proxy/plugin_var_tracker.cc
@@ -0,0 +1,336 @@
+// 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/plugin_var_tracker.h"
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/singleton.h"
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/interface_id.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+// When non-NULL, this object overrides the VarTrackerSingleton.
+PluginVarTracker* var_tracker_override = NULL;
+
+} // namespace
+
+PluginVarTracker::HostVar::HostVar(PluginDispatcher* d, VarID i)
+ : dispatcher(d),
+ host_object_id(i) {
+}
+
+bool PluginVarTracker::HostVar::operator<(const HostVar& other) const {
+ if (dispatcher < other.dispatcher)
+ return true;
+ if (other.dispatcher < dispatcher)
+ return false;
+ return host_object_id < other.host_object_id;
+}
+
+PluginVarTracker::PluginVarInfo::PluginVarInfo(const HostVar& host_var)
+ : host_var(host_var),
+ ref_count(0),
+ track_with_no_reference_count(0) {
+}
+
+PluginVarTracker::PluginVarTracker() : last_plugin_var_id_(0) {
+}
+
+PluginVarTracker::~PluginVarTracker() {
+}
+
+// static
+void PluginVarTracker::SetInstanceForTest(PluginVarTracker* tracker) {
+ var_tracker_override = tracker;
+}
+
+// static
+PluginVarTracker* PluginVarTracker::GetInstance() {
+ if (var_tracker_override)
+ return var_tracker_override;
+ return Singleton<PluginVarTracker>::get();
+}
+
+PluginVarTracker::VarID PluginVarTracker::MakeString(const std::string& str) {
+ return MakeString(str.c_str(), str.length());
+}
+
+PluginVarTracker::VarID PluginVarTracker::MakeString(const char* str,
+ uint32_t len) {
+ std::pair<VarIDStringMap::iterator, bool>
+ iter_success_pair(var_id_to_string_.end(), false);
+ VarID new_id(0);
+ RefCountedStringPtr str_ptr(new RefCountedString(str, len));
+ // Pick new IDs until one is successfully inserted. This loop is very unlikely
+ // to ever run a 2nd time, since we have ~2^63 possible IDs to exhaust.
+ while (!iter_success_pair.second) {
+ new_id = GetNewVarID();
+ iter_success_pair =
+ var_id_to_string_.insert(VarIDStringMap::value_type(new_id, str_ptr));
+ }
+ iter_success_pair.first->second->AddRef();
+ return new_id;
+}
+
+const std::string* PluginVarTracker::GetExistingString(
+ const PP_Var& var) const {
+ if (var.type != PP_VARTYPE_STRING)
+ return NULL;
+ VarIDStringMap::const_iterator found =
+ var_id_to_string_.find(var.value.as_id);
+ if (found != var_id_to_string_.end())
+ return &found->second->value();
+ return NULL;
+}
+
+void PluginVarTracker::AddRef(const PP_Var& var) {
+ if (var.type == PP_VARTYPE_STRING) {
+ VarIDStringMap::iterator found = var_id_to_string_.find(var.value.as_id);
+ if (found == var_id_to_string_.end()) {
+ NOTREACHED() << "Requesting to addref an unknown string.";
+ return;
+ }
+ found->second->AddRef();
+ } else if (var.type == PP_VARTYPE_OBJECT && var.value.as_id != 0) {
+ PluginVarInfoMap::iterator found = plugin_var_info_.find(var.value.as_id);
+ if (found == plugin_var_info_.end()) {
+ NOTREACHED() << "Requesting to addref an unknown object.";
+ return;
+ }
+
+ PluginVarInfo& info = found->second;
+ if (info.ref_count == 0) {
+ // Got an AddRef for an object we have no existing reference for.
+ // We need to tell the browser we've taken a ref. This comes up when the
+ // browser passes an object as an input param and holds a ref for us.
+ // This must be a sync message since otherwise the "addref" will actually
+ // occur after the return to the browser of the sync function that
+ // presumably sent the object.
+ SendAddRefObjectMsg(info.host_var);
+ }
+ info.ref_count++;
+ }
+}
+
+void PluginVarTracker::Release(const PP_Var& var) {
+ if (var.type == PP_VARTYPE_STRING) {
+ VarIDStringMap::iterator found = var_id_to_string_.find(var.value.as_id);
+ if (found == var_id_to_string_.end()) {
+ NOTREACHED() << "Requesting to release an unknown string.";
+ return;
+ }
+ found->second->Release();
+ // If there is only 1 reference left, it's the map's reference. Erase it
+ // from the map, which will delete the string.
+ if (found->second->HasOneRef())
+ var_id_to_string_.erase(found);
+ } else if (var.type == PP_VARTYPE_OBJECT) {
+ PluginVarInfoMap::iterator found = plugin_var_info_.find(var.value.as_id);
+ if (found == plugin_var_info_.end()) {
+ NOTREACHED() << "Requesting to release an unknown object.";
+ return;
+ }
+
+ PluginVarInfo& info = found->second;
+ if (info.ref_count == 0) {
+ NOTREACHED() << "Releasing an object with zero ref.";
+ return;
+ }
+
+ info.ref_count--;
+ if (info.ref_count == 0)
+ SendReleaseObjectMsg(info.host_var);
+ DeletePluginVarInfoIfNecessary(found);
+ }
+}
+
+PP_Var PluginVarTracker::ReceiveObjectPassRef(const PP_Var& var,
+ PluginDispatcher* dispatcher) {
+ DCHECK(var.type == PP_VARTYPE_OBJECT);
+
+ // Find the plugin info.
+ PluginVarInfoMap::iterator found =
+ FindOrMakePluginVarFromHostVar(var, dispatcher);
+ if (found == plugin_var_info_.end()) {
+ // The above code should have always made an entry in the map.
+ NOTREACHED();
+ return PP_MakeUndefined();
+ }
+
+ // Fix up the references. The host (renderer) just sent us a ref. The
+ // renderer has addrefed the var in its tracker for us since it's returning
+ // it.
+ PluginVarInfo& info = found->second;
+ if (info.ref_count == 0) {
+ // We don't have a reference to this already, then we just add it to our
+ // tracker and use that one ref.
+ info.ref_count = 1;
+ } else {
+ // We already have a reference to it, that means the renderer now has two
+ // references on our behalf. We want to transfer that extra reference to
+ // our list. This means we addref in the plugin, and release the extra one
+ // in the renderer.
+ SendReleaseObjectMsg(info.host_var);
+ info.ref_count++;
+ }
+
+ PP_Var ret;
+ ret.type = PP_VARTYPE_OBJECT;
+ ret.value.as_id = found->first;
+ return ret;
+}
+
+PP_Var PluginVarTracker::TrackObjectWithNoReference(
+ const PP_Var& host_var,
+ PluginDispatcher* dispatcher) {
+ DCHECK(host_var.type == PP_VARTYPE_OBJECT);
+
+ PluginVarInfoMap::iterator found =
+ FindOrMakePluginVarFromHostVar(host_var, dispatcher);
+ if (found == plugin_var_info_.end()) {
+ // The above code should have always made an entry in the map.
+ NOTREACHED();
+ return PP_MakeUndefined();
+ }
+
+ found->second.track_with_no_reference_count++;
+
+ PP_Var ret;
+ ret.type = PP_VARTYPE_OBJECT;
+ ret.value.as_id = found->first;
+ return ret;
+}
+
+void PluginVarTracker::StopTrackingObjectWithNoReference(
+ const PP_Var& plugin_var) {
+ DCHECK(plugin_var.type == PP_VARTYPE_OBJECT);
+ PluginVarInfoMap::iterator found = plugin_var_info_.find(
+ plugin_var.value.as_id);
+ if (found == plugin_var_info_.end()) {
+ NOTREACHED();
+ return;
+ }
+
+ found->second.track_with_no_reference_count--;
+ DeletePluginVarInfoIfNecessary(found);
+}
+
+PP_Var PluginVarTracker::GetHostObject(const PP_Var& plugin_object) const {
+ DCHECK(plugin_object.type == PP_VARTYPE_OBJECT);
+ PluginVarInfoMap::const_iterator found = plugin_var_info_.find(
+ plugin_object.value.as_id);
+ if (found == plugin_var_info_.end()) {
+ NOTREACHED();
+ return PP_MakeUndefined();
+ }
+ PP_Var ret;
+ ret.type = PP_VARTYPE_OBJECT;
+ ret.value.as_id = found->second.host_var.host_object_id;
+ return ret;
+}
+
+PluginDispatcher* PluginVarTracker::DispatcherForPluginObject(
+ const PP_Var& plugin_object) const {
+ DCHECK(plugin_object.type == PP_VARTYPE_OBJECT);
+ PluginVarInfoMap::const_iterator found = plugin_var_info_.find(
+ plugin_object.value.as_id);
+ if (found != plugin_var_info_.end())
+ return found->second.host_var.dispatcher;
+ return NULL;
+}
+
+void PluginVarTracker::ReleaseHostObject(PluginDispatcher* dispatcher,
+ const PP_Var& host_object) {
+ // Convert the host object to a normal var valid in the plugin.
+ DCHECK(host_object.type == PP_VARTYPE_OBJECT);
+ HostVarToPluginVarMap::iterator found = host_var_to_plugin_var_.find(
+ HostVar(dispatcher, host_object.value.as_id));
+ if (found == host_var_to_plugin_var_.end()) {
+ NOTREACHED();
+ return;
+ }
+
+ // Now just release the object like normal.
+ PP_Var plugin_object;
+ plugin_object.type = PP_VARTYPE_OBJECT;
+ plugin_object.value.as_id = found->second;
+ Release(plugin_object);
+}
+
+int PluginVarTracker::GetRefCountForObject(const PP_Var& plugin_object) {
+ PluginVarInfoMap::iterator found = plugin_var_info_.find(
+ plugin_object.value.as_id);
+ if (found == plugin_var_info_.end())
+ return -1;
+ return found->second.ref_count;
+}
+
+int PluginVarTracker::GetTrackedWithNoReferenceCountForObject(
+ const PP_Var& plugin_object) {
+ PluginVarInfoMap::iterator found = plugin_var_info_.find(
+ plugin_object.value.as_id);
+ if (found == plugin_var_info_.end())
+ return -1;
+ return found->second.track_with_no_reference_count;
+}
+
+void PluginVarTracker::SendAddRefObjectMsg(const HostVar& host_var) {
+ int unused;
+ host_var.dispatcher->Send(new PpapiHostMsg_PPBVar_AddRefObject(
+ INTERFACE_ID_PPB_VAR_DEPRECATED, host_var.host_object_id, &unused));
+}
+
+void PluginVarTracker::SendReleaseObjectMsg(const HostVar& host_var) {
+ host_var.dispatcher->Send(new PpapiHostMsg_PPBVar_ReleaseObject(
+ INTERFACE_ID_PPB_VAR_DEPRECATED, host_var.host_object_id));
+}
+
+PluginVarTracker::PluginVarInfoMap::iterator
+PluginVarTracker::FindOrMakePluginVarFromHostVar(const PP_Var& var,
+ PluginDispatcher* dispatcher) {
+ DCHECK(var.type == PP_VARTYPE_OBJECT);
+ HostVar host_var(dispatcher, var.value.as_id);
+
+ HostVarToPluginVarMap::iterator found =
+ host_var_to_plugin_var_.find(host_var);
+ if (found != host_var_to_plugin_var_.end()) {
+ PluginVarInfoMap::iterator ret = plugin_var_info_.find(found->second);
+ DCHECK(ret != plugin_var_info_.end());
+ return ret; // Already know about this var return the ID.
+ }
+
+ // Make a new var, adding references to both maps.
+ VarID new_plugin_var_id = GetNewVarID();
+ host_var_to_plugin_var_[host_var] = new_plugin_var_id;
+ return plugin_var_info_.insert(
+ std::make_pair(new_plugin_var_id, PluginVarInfo(host_var))).first;
+}
+
+void PluginVarTracker::DeletePluginVarInfoIfNecessary(
+ PluginVarInfoMap::iterator iter) {
+ if (iter->second.ref_count != 0 ||
+ iter->second.track_with_no_reference_count != 0)
+ return; // Object still alive.
+
+ // Object ref counts are all zero, delete from both maps.
+ DCHECK(host_var_to_plugin_var_.find(iter->second.host_var) !=
+ host_var_to_plugin_var_.end());
+ host_var_to_plugin_var_.erase(iter->second.host_var);
+ plugin_var_info_.erase(iter);
+}
+
+PluginVarTracker::VarID PluginVarTracker::GetNewVarID() {
+ if (last_plugin_var_id_ == std::numeric_limits<VarID>::max())
+ last_plugin_var_id_ = 0;
+ return ++last_plugin_var_id_;
+}
+
+} // namesace proxy
+} // namespace pp
diff --git a/ppapi/proxy/plugin_var_tracker.h b/ppapi/proxy/plugin_var_tracker.h
new file mode 100644
index 0000000..748ec2d
--- /dev/null
+++ b/ppapi/proxy/plugin_var_tracker.h
@@ -0,0 +1,196 @@
+// 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_PLUGIN_VAR_TRACKER_H_
+#define PPAPI_PROXY_PLUGIN_VAR_TRACKER_H_
+
+#include <map>
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "ppapi/c/pp_stdint.h"
+#include "ppapi/c/pp_var.h"
+
+struct PPB_Var;
+
+template<typename T> struct DefaultSingletonTraits;
+
+namespace pp {
+namespace proxy {
+
+class PluginDispatcher;
+
+// Tracks live strings and objects in the plugin process.
+//
+// This object maintains its own object IDs that are used by the plugin. These
+// IDs can be mapped to the renderer that created them, and that renderer's ID.
+// This way, we can maintain multiple renderers each giving us objects, and the
+// plugin can work with them using a uniform set of unique IDs.
+//
+// We maintain our own reference count for objects. a single ref in the
+// renderer process whenever we have a nonzero refcount in the plugin process.
+// This allows AddRef and Release to not initiate too much IPC chat.
+//
+// In addition to the local reference count, we also maintain "tracked objects"
+// which are objects that the plugin is aware of, but doesn't hold a reference
+// to. This will happen when the plugin is passed an object as an argument from
+// the host (renderer) but where a reference is not passed.
+class PluginVarTracker {
+ public:
+ typedef int64_t VarID;
+
+ // Called by tests that want to specify a specific VarTracker. This allows
+ // them to use a unique one each time and avoids singletons sticking around
+ // across tests.
+ static void SetInstanceForTest(PluginVarTracker* tracker);
+
+ // Returns the global var tracker for the plugin object.
+ static PluginVarTracker* GetInstance();
+
+ // Allocates a string and returns the ID of it. The refcount will be 1.
+ VarID MakeString(const std::string& str);
+ VarID MakeString(const char* str, uint32_t len);
+
+ // Returns a pointer to the given string if it exists, or NULL if the var
+ // isn't a string var.
+ const std::string* GetExistingString(const PP_Var& plugin_var) const;
+
+ void AddRef(const PP_Var& plugin_var);
+ void Release(const PP_Var& plugin_var);
+
+ // Manages tracking for receiving a VARTYPE_OBJECT from the remote side
+ // (either the plugin or the renderer) that has already had its reference
+ // count incremented on behalf of the caller.
+ PP_Var ReceiveObjectPassRef(const PP_Var& var, PluginDispatcher* dispatcher);
+
+ PP_Var TrackObjectWithNoReference(const PP_Var& host_var,
+ PluginDispatcher* dispatcher);
+ void StopTrackingObjectWithNoReference(const PP_Var& plugin_var);
+
+ // Returns the host var for the corresponding plugin object var. The object
+ // should be a VARTYPE_OBJECT
+ PP_Var GetHostObject(const PP_Var& plugin_object) const;
+
+ PluginDispatcher* DispatcherForPluginObject(
+ const PP_Var& plugin_object) const;
+
+ // Like Release() but the var is identified by its host object ID (as
+ // returned by GetHostObject).
+ void ReleaseHostObject(PluginDispatcher* dispatcher,
+ const PP_Var& host_object);
+
+ // Retrieves the internal reference counts for testing. Returns 0 if we
+ // know about the object but the corresponding value is 0, or -1 if the
+ // given object ID isn't in our map.
+ int GetRefCountForObject(const PP_Var& plugin_object);
+ int GetTrackedWithNoReferenceCountForObject(const PP_Var& plugin_object);
+
+ private:
+ friend struct DefaultSingletonTraits<PluginVarTracker>;
+ friend class PluginProxyTestHarness;
+
+ class RefCountedString : public base::RefCounted<RefCountedString> {
+ public:
+ RefCountedString() {
+ }
+ RefCountedString(const std::string& str) : value_(str) {
+ }
+ RefCountedString(const char* data, size_t len)
+ : value_(data, len) {
+ }
+
+ const std::string& value() const { return value_; }
+
+ private:
+ std::string value_;
+
+ // Ensure only base::RefCounted can delete a RefCountedString.
+ friend void base::RefCounted<RefCountedString>::Release() const;
+ virtual ~RefCountedString() {}
+ };
+ typedef scoped_refptr<RefCountedString> RefCountedStringPtr;
+
+ // Represents a var as received from the host.
+ struct HostVar {
+ HostVar(PluginDispatcher* d, int64_t i);
+
+ bool operator<(const HostVar& other) const;
+
+ // The dispatcher that sent us this object. This is used so we know how to
+ // send back requests on this object.
+ PluginDispatcher* dispatcher;
+
+ // The object ID that the host generated to identify the object. This is
+ // unique only within that host: different hosts could give us different
+ // objects with the same ID.
+ VarID host_object_id;
+ };
+
+ // The information associated with a var object in the plugin.
+ struct PluginVarInfo {
+ PluginVarInfo(const HostVar& host_var);
+
+ // Maps back to the original var in the host.
+ HostVar host_var;
+
+ // Explicit reference count. This value is affected by the renderer calling
+ // AddRef and Release. A nonzero value here is represented by a single
+ // reference in the host on our behalf (this reduces IPC traffic).
+ int32_t ref_count;
+
+ // Tracked object count (see class comment above).
+ //
+ // "TrackObjectWithNoReference" might be called recursively in rare cases.
+ // For example, say the host calls a plugin function with an object as an
+ // argument, and in response, the plugin calls a host function that then
+ // calls another (or the same) plugin function with the same object.
+ //
+ // This value tracks the number of calls to TrackObjectWithNoReference so
+ // we know when we can stop tracking this object.
+ int32_t track_with_no_reference_count;
+ };
+
+ typedef std::map<int64_t, PluginVarInfo> PluginVarInfoMap;
+
+ PluginVarTracker();
+ ~PluginVarTracker();
+
+ // Sends an addref or release message to the browser for the given object ID.
+ void SendAddRefObjectMsg(const HostVar& host_var);
+ void SendReleaseObjectMsg(const HostVar& host_var);
+
+ PluginVarInfoMap::iterator FindOrMakePluginVarFromHostVar(
+ const PP_Var& var,
+ PluginDispatcher* dispatcher);
+
+ // Checks the reference counds of the given plugin var info and removes the
+ // tracking information if necessary. We're done with the object when its
+ // explicit reference count and its "tracked with no reference" count both
+ // reach zero.
+ void DeletePluginVarInfoIfNecessary(PluginVarInfoMap::iterator iter);
+
+ // Tracks all information about plugin vars.
+ PluginVarInfoMap plugin_var_info_;
+
+ // Maps host vars to plugin vars. This allows us to know if we've previously
+ // seen a host var and re-use the information.
+ typedef std::map<HostVar, VarID> HostVarToPluginVarMap;
+ HostVarToPluginVarMap host_var_to_plugin_var_;
+
+ // Maps plugin var IDs to ref counted strings.
+ typedef std::map<VarID, RefCountedStringPtr> VarIDStringMap;
+ VarIDStringMap var_id_to_string_;
+
+ // The last plugin PP_Var ID we've handed out. This must be unique for the
+ // process.
+ VarID last_plugin_var_id_;
+
+ // Get a new Var ID and increment last_plugin_var_id_.
+ VarID GetNewVarID();
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PLUGIN_VAR_TRACKER_H_
diff --git a/ppapi/proxy/plugin_var_tracker_unittest.cc b/ppapi/proxy/plugin_var_tracker_unittest.cc
new file mode 100644
index 0000000..08fba9b
--- /dev/null
+++ b/ppapi/proxy/plugin_var_tracker_unittest.cc
@@ -0,0 +1,189 @@
+// 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 "ipc/ipc_test_sink.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+PP_Var MakeObject(PluginVarTracker::VarID object_id) {
+ PP_Var ret;
+ ret.type = PP_VARTYPE_OBJECT;
+ ret.value.as_id = object_id;
+ return ret;
+}
+
+// Creates a PP_Var from the given string ID.
+PP_Var MakeString(PluginVarTracker::VarID string_id) {
+ PP_Var ret;
+ ret.type = PP_VARTYPE_STRING;
+ ret.value.as_id = string_id;
+ return ret;
+}
+
+} // namespace
+
+class PluginVarTrackerTest : public PluginProxyTest {
+ public:
+ PluginVarTrackerTest() {}
+
+ protected:
+ // Asserts that there is a unique "release object" IPC message in the test
+ // sink. This will return the var ID from the message or -1 if none found.
+ PluginVarTracker::VarID GetObjectIDForUniqueReleaseObject() {
+ const IPC::Message* release_msg = sink().GetUniqueMessageMatching(
+ PpapiHostMsg_PPBVar_ReleaseObject::ID);
+ if (!release_msg)
+ return -1;
+
+ Tuple1<int64> id;
+ PpapiHostMsg_PPBVar_ReleaseObject::Read(release_msg, &id);
+ return id.a;
+ }
+};
+
+TEST_F(PluginVarTrackerTest, Strings) {
+ std::string str("Hello");
+ PluginVarTracker::VarID str_id1 = var_tracker().MakeString(str);
+ EXPECT_NE(0, str_id1);
+
+ PluginVarTracker::VarID str_id2 = var_tracker().MakeString(
+ str.c_str(), static_cast<uint32_t>(str.size()));
+ EXPECT_NE(0, str_id2);
+
+ // Make sure the strings come out the other end.
+ const std::string* result =
+ var_tracker().GetExistingString(MakeString(str_id1));
+ EXPECT_EQ(str, *result);
+ result = var_tracker().GetExistingString(MakeString(str_id2));
+ EXPECT_EQ(str, *result);
+}
+
+TEST_F(PluginVarTrackerTest, GetHostObject) {
+ PP_Var host_object = MakeObject(12345);
+
+ // Round-trip through the tracker to make sure the host object comes out the
+ // other end.
+ PP_Var plugin_object = var_tracker().ReceiveObjectPassRef(
+ host_object, plugin_dispatcher());
+ PP_Var host_object2 = var_tracker().GetHostObject(plugin_object);
+ EXPECT_EQ(PP_VARTYPE_OBJECT, host_object2.type);
+ EXPECT_EQ(host_object.value.as_id, host_object2.value.as_id);
+
+ var_tracker().Release(plugin_object);
+}
+
+TEST_F(PluginVarTrackerTest, ReceiveObjectPassRef) {
+ PP_Var host_object = MakeObject(12345);
+
+ // Receive the object, we should have one ref and no messages.
+ PP_Var plugin_object = var_tracker().ReceiveObjectPassRef(
+ host_object, plugin_dispatcher());
+ EXPECT_EQ(0u, sink().message_count());
+ EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
+ EXPECT_EQ(0,
+ var_tracker().GetTrackedWithNoReferenceCountForObject(plugin_object));
+
+ // Receive the same object again, we should get the same plugin ID out.
+ PP_Var plugin_object2 = var_tracker().ReceiveObjectPassRef(
+ host_object, plugin_dispatcher());
+ EXPECT_EQ(plugin_object.value.as_id, plugin_object2.value.as_id);
+ EXPECT_EQ(2, var_tracker().GetRefCountForObject(plugin_object));
+ EXPECT_EQ(0,
+ var_tracker().GetTrackedWithNoReferenceCountForObject(plugin_object));
+
+ // It should have sent one message to decerment the refcount in the host.
+ // This is because it only maintains one host refcount for all references
+ // in the plugin, but the host just sent the second one.
+ EXPECT_EQ(host_object.value.as_id, GetObjectIDForUniqueReleaseObject());
+ sink().ClearMessages();
+
+ // Release the object, one ref at a time. The second release should free
+ // the tracking data and send a release message to the browser.
+ var_tracker().Release(plugin_object);
+ EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
+ var_tracker().Release(plugin_object);
+ EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_object));
+ EXPECT_EQ(host_object.value.as_id, GetObjectIDForUniqueReleaseObject());
+}
+
+// Tests freeing objects that have both refcounts and "tracked with no ref".
+TEST_F(PluginVarTrackerTest, FreeTrackedAndReferencedObject) {
+ PP_Var host_object = MakeObject(12345);
+
+ // Phase one: First receive via a "pass ref", then a tracked with no ref.
+ PP_Var plugin_var = var_tracker().ReceiveObjectPassRef(
+ host_object, plugin_dispatcher());
+ PP_Var plugin_var2 = var_tracker().TrackObjectWithNoReference(
+ host_object, plugin_dispatcher());
+ EXPECT_EQ(plugin_var.value.as_id, plugin_var2.value.as_id);
+ EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_var));
+ EXPECT_EQ(1,
+ var_tracker().GetTrackedWithNoReferenceCountForObject(plugin_var));
+
+ // Free via the refcount, this should release the object to the browser but
+ // maintain the tracked object.
+ var_tracker().Release(plugin_var);
+ EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_var));
+ EXPECT_EQ(1u, sink().message_count());
+ EXPECT_EQ(host_object.value.as_id, GetObjectIDForUniqueReleaseObject());
+
+ // Now free via the tracked object, this should free it.
+ var_tracker().StopTrackingObjectWithNoReference(plugin_var);
+ EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_var));
+
+ // Phase two: Receive via a tracked, then get an addref.
+ sink().ClearMessages();
+ plugin_var = var_tracker().TrackObjectWithNoReference(
+ host_object, plugin_dispatcher());
+ plugin_var2 = var_tracker().ReceiveObjectPassRef(
+ host_object, plugin_dispatcher());
+ EXPECT_EQ(plugin_var.value.as_id, plugin_var2.value.as_id);
+ EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_var));
+ EXPECT_EQ(1,
+ var_tracker().GetTrackedWithNoReferenceCountForObject(plugin_var));
+
+ // Free via the tracked object, this should have no effect.
+ var_tracker().StopTrackingObjectWithNoReference(plugin_var);
+ EXPECT_EQ(0,
+ var_tracker().GetTrackedWithNoReferenceCountForObject(plugin_var));
+ EXPECT_EQ(0u, sink().message_count());
+
+ // Now free via the refcount, this should delete it.
+ var_tracker().Release(plugin_var);
+ EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_var));
+ EXPECT_EQ(host_object.value.as_id, GetObjectIDForUniqueReleaseObject());
+}
+
+TEST_F(PluginVarTrackerTest, RecursiveTrackWithNoRef) {
+ PP_Var host_object = MakeObject(12345);
+
+ // Receive a tracked object twice.
+ PP_Var plugin_var = var_tracker().TrackObjectWithNoReference(
+ host_object, plugin_dispatcher());
+ EXPECT_EQ(1,
+ var_tracker().GetTrackedWithNoReferenceCountForObject(plugin_var));
+ PP_Var plugin_var2 = var_tracker().TrackObjectWithNoReference(
+ host_object, plugin_dispatcher());
+ EXPECT_EQ(plugin_var.value.as_id, plugin_var2.value.as_id);
+ EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_var));
+ EXPECT_EQ(2,
+ var_tracker().GetTrackedWithNoReferenceCountForObject(plugin_var));
+
+ // Now release those tracked items, the reference should be freed.
+ var_tracker().StopTrackingObjectWithNoReference(plugin_var);
+ EXPECT_EQ(1,
+ var_tracker().GetTrackedWithNoReferenceCountForObject(plugin_var));
+ var_tracker().StopTrackingObjectWithNoReference(plugin_var);
+ EXPECT_EQ(-1,
+ var_tracker().GetTrackedWithNoReferenceCountForObject(plugin_var));
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppapi_messages.cc b/ppapi/proxy/ppapi_messages.cc
new file mode 100644
index 0000000..5cee1c7
--- /dev/null
+++ b/ppapi/proxy/ppapi_messages.cc
@@ -0,0 +1,34 @@
+// Copyright (c) 2010 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.
+
+// Get basic type definitions.
+#define IPC_MESSAGE_IMPL
+#include "ppapi/proxy/ppapi_messages.h"
+
+// Generate constructors.
+#include "ipc/struct_constructor_macros.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+// Generate destructors.
+#include "ipc/struct_destructor_macros.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+// Generate param traits write methods.
+#include "ipc/param_traits_write_macros.h"
+namespace IPC {
+#include "ppapi/proxy/ppapi_messages.h"
+} // namespace IPC
+
+// Generate param traits read methods.
+#include "ipc/param_traits_read_macros.h"
+namespace IPC {
+#include "ppapi/proxy/ppapi_messages.h"
+} // namespace IPC
+
+// Generate param traits log methods.
+#include "ipc/param_traits_log_macros.h"
+namespace IPC {
+#include "ppapi/proxy/ppapi_messages.h"
+} // namespace IPC
+
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
new file mode 100644
index 0000000..c516514
--- /dev/null
+++ b/ppapi/proxy/ppapi_messages.h
@@ -0,0 +1,858 @@
+// 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.
+
+// Multiply-included message header, no traditional include guard.
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/process.h"
+#include "base/shared_memory.h"
+#include "base/string16.h"
+#include "base/sync_socket.h"
+#include "gpu/command_buffer/common/command_buffer.h"
+#include "gpu/ipc/gpu_command_buffer_traits.h"
+#include "ipc/ipc_channel_handle.h"
+#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_utils.h"
+#include "ipc/ipc_platform_file.h"
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_file_info.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_point.h"
+#include "ppapi/c/pp_rect.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_size.h"
+#include "ppapi/c/private/ppb_flash_tcp_socket.h"
+#include "ppapi/proxy/ppapi_param_traits.h"
+#include "ppapi/proxy/serialized_flash_menu.h"
+#include "ppapi/proxy/serialized_structs.h"
+#include "ppapi/shared_impl/input_event_impl.h"
+#include "ppapi/shared_impl/ppapi_preferences.h"
+
+#define IPC_MESSAGE_START PpapiMsgStart
+
+IPC_ENUM_TRAITS(PP_InputEvent_Type)
+IPC_ENUM_TRAITS(PP_InputEvent_MouseButton)
+
+IPC_STRUCT_TRAITS_BEGIN(PP_Point)
+ IPC_STRUCT_TRAITS_MEMBER(x)
+ IPC_STRUCT_TRAITS_MEMBER(y)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(PP_FloatPoint)
+ IPC_STRUCT_TRAITS_MEMBER(x)
+ IPC_STRUCT_TRAITS_MEMBER(y)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(PP_Size)
+ IPC_STRUCT_TRAITS_MEMBER(height)
+ IPC_STRUCT_TRAITS_MEMBER(width)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(PP_Rect)
+ IPC_STRUCT_TRAITS_MEMBER(point)
+ IPC_STRUCT_TRAITS_MEMBER(size)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(::ppapi::Preferences)
+ IPC_STRUCT_TRAITS_MEMBER(standard_font_family)
+ IPC_STRUCT_TRAITS_MEMBER(fixed_font_family)
+ IPC_STRUCT_TRAITS_MEMBER(serif_font_family)
+ IPC_STRUCT_TRAITS_MEMBER(sans_serif_font_family)
+ IPC_STRUCT_TRAITS_MEMBER(default_font_size)
+ IPC_STRUCT_TRAITS_MEMBER(default_fixed_font_size)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(::ppapi::InputEventData)
+ IPC_STRUCT_TRAITS_MEMBER(is_filtered)
+ IPC_STRUCT_TRAITS_MEMBER(event_type)
+ IPC_STRUCT_TRAITS_MEMBER(event_time_stamp)
+ IPC_STRUCT_TRAITS_MEMBER(event_modifiers)
+ IPC_STRUCT_TRAITS_MEMBER(mouse_button)
+ IPC_STRUCT_TRAITS_MEMBER(mouse_position)
+ IPC_STRUCT_TRAITS_MEMBER(mouse_click_count)
+ IPC_STRUCT_TRAITS_MEMBER(wheel_delta)
+ IPC_STRUCT_TRAITS_MEMBER(wheel_ticks)
+ IPC_STRUCT_TRAITS_MEMBER(wheel_scroll_by_page)
+ IPC_STRUCT_TRAITS_MEMBER(key_code)
+ IPC_STRUCT_TRAITS_MEMBER(character_text)
+IPC_STRUCT_TRAITS_END()
+
+// These are from the browser to the plugin.
+// Loads the given plugin.
+IPC_MESSAGE_CONTROL1(PpapiMsg_LoadPlugin, FilePath /* path */)
+
+// Creates a channel to talk to a renderer. The plugin will respond with
+// PpapiHostMsg_ChannelCreated.
+IPC_MESSAGE_CONTROL2(PpapiMsg_CreateChannel,
+ base::ProcessHandle /* host_process_handle */,
+ int /* renderer_id */)
+
+// Each plugin may be referenced by multiple renderers. We need the instance
+// IDs to be unique within a plugin, despite coming from different renderers,
+// and unique within a renderer, despite going to different plugins. This means
+// that neither the renderer nor the plugin can generate instance IDs without
+// consulting the other.
+//
+// We resolve this by having the renderer generate a unique instance ID inside
+// its process. It then asks the plugin to reserve that ID by sending this sync
+// message. If the plugin has not yet seen this ID, it will remember it as used
+// (to prevent a race condition if another renderer tries to then use the same
+// instance), and set usable as true.
+//
+// If the plugin has already seen the instance ID, it will set usable as false
+// and the renderer must retry a new instance ID.
+IPC_SYNC_MESSAGE_CONTROL1_1(PpapiMsg_ReserveInstanceId,
+ PP_Instance /* instance */,
+ bool /* usable */)
+
+// Passes the WebKit preferences to the plugin.
+IPC_MESSAGE_CONTROL1(PpapiMsg_SetPreferences,
+ ::ppapi::Preferences)
+
+// Network state notification from the browser for implementing
+// PPP_NetworkState_Dev.
+IPC_MESSAGE_CONTROL1(PpapiMsg_SetNetworkState,
+ bool /* online */)
+
+// Sent in both directions to see if the other side supports the given
+// interface.
+IPC_SYNC_MESSAGE_CONTROL1_1(PpapiMsg_SupportsInterface,
+ std::string /* interface_name */,
+ bool /* result */)
+
+IPC_MESSAGE_CONTROL2(PpapiMsg_ExecuteCallback,
+ uint32 /* serialized_callback */,
+ int32 /* param */)
+
+// Broker Process.
+
+IPC_SYNC_MESSAGE_CONTROL2_0(PpapiMsg_ConnectToPlugin,
+ PP_Instance /* instance */,
+ IPC::PlatformFileForTransit /* handle */)
+
+// PPB_Audio.
+
+// Notifies the result of the audio stream create call. This is called in
+// both error cases and in the normal success case. These cases are
+// differentiated by the result code, which is one of the standard PPAPI
+// result codes.
+//
+// The handler of this message should always close all of the handles passed
+// in, since some could be valid even in the error case.
+IPC_MESSAGE_ROUTED5(PpapiMsg_PPBAudio_NotifyAudioStreamCreated,
+ pp::proxy::HostResource /* audio_id */,
+ int32_t /* result_code (will be != PP_OK on failure) */,
+ IPC::PlatformFileForTransit /* socket_handle */,
+ base::SharedMemoryHandle /* handle */,
+ int32_t /* length */)
+
+// PPB_Broker.
+IPC_MESSAGE_ROUTED3(
+ PpapiMsg_PPBBroker_ConnectComplete,
+ pp::proxy::HostResource /* broker */,
+ IPC::PlatformFileForTransit /* handle */,
+ int32_t /* result */)
+
+// 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_FileSystem.
+IPC_MESSAGE_ROUTED2(
+ PpapiMsg_PPBFileSystem_OpenComplete,
+ pp::proxy::HostResource /* filesystem */,
+ int32_t /* result */)
+
+// PPB_Flash_NetConnector.
+IPC_MESSAGE_ROUTED5(PpapiMsg_PPBFlashNetConnector_ConnectACK,
+ pp::proxy::HostResource /* net_connector */,
+ int32_t /* result */,
+ IPC::PlatformFileForTransit /* handle */,
+ std::string /* local_addr_as_string */,
+ std::string /* remote_addr_as_string */)
+
+// PPB_Flash_TCPSocket.
+IPC_MESSAGE_ROUTED5(PpapiMsg_PPBFlashTCPSocket_ConnectACK,
+ uint32 /* plugin_dispatcher_id */,
+ uint32 /* socket_id */,
+ bool /* succeeded */,
+ PP_Flash_NetAddress /* local_addr */,
+ PP_Flash_NetAddress /* remote_addr */)
+IPC_MESSAGE_ROUTED4(PpapiMsg_PPBFlashTCPSocket_ReadACK,
+ uint32 /* plugin_dispatcher_id */,
+ uint32 /* socket_id */,
+ bool /* succeeded */,
+ std::string /* data */)
+IPC_MESSAGE_ROUTED4(PpapiMsg_PPBFlashTCPSocket_WriteACK,
+ uint32 /* plugin_dispatcher_id */,
+ uint32 /* socket_id */,
+ bool /* succeeded */,
+ int32_t /* bytes_written */)
+
+// PPB_Graphics2D.
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPBGraphics2D_FlushACK,
+ pp::proxy::HostResource /* graphics_2d */,
+ int32_t /* pp_error */)
+
+// PPB_Surface3D.
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPBSurface3D_SwapBuffersACK,
+ pp::proxy::HostResource /* surface_3d */,
+ int32_t /* pp_error */)
+
+// PPP_Class.
+IPC_SYNC_MESSAGE_ROUTED3_2(PpapiMsg_PPPClass_HasProperty,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ pp::proxy::SerializedVar /* property */,
+ pp::proxy::SerializedVar /* out_exception */,
+ bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED3_2(PpapiMsg_PPPClass_HasMethod,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ pp::proxy::SerializedVar /* method */,
+ pp::proxy::SerializedVar /* out_exception */,
+ bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED3_2(PpapiMsg_PPPClass_GetProperty,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ pp::proxy::SerializedVar /* property */,
+ pp::proxy::SerializedVar /* out_exception */,
+ pp::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_2(PpapiMsg_PPPClass_EnumerateProperties,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ std::vector<pp::proxy::SerializedVar> /* props */,
+ pp::proxy::SerializedVar /* out_exception */)
+IPC_SYNC_MESSAGE_ROUTED4_1(PpapiMsg_PPPClass_SetProperty,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ pp::proxy::SerializedVar /* name */,
+ pp::proxy::SerializedVar /* value */,
+ pp::proxy::SerializedVar /* out_exception */)
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiMsg_PPPClass_RemoveProperty,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ pp::proxy::SerializedVar /* property */,
+ pp::proxy::SerializedVar /* out_exception */)
+IPC_SYNC_MESSAGE_ROUTED4_2(PpapiMsg_PPPClass_Call,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ pp::proxy::SerializedVar /* method_name */,
+ std::vector<pp::proxy::SerializedVar> /* args */,
+ pp::proxy::SerializedVar /* out_exception */,
+ pp::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED3_2(PpapiMsg_PPPClass_Construct,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ std::vector<pp::proxy::SerializedVar> /* args */,
+ pp::proxy::SerializedVar /* out_exception */,
+ pp::proxy::SerializedVar /* result */)
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPPClass_Deallocate,
+ int64 /* ppp_class */,
+ int64 /* object */)
+
+// PPP_Graphics3D_Dev.
+IPC_MESSAGE_ROUTED1(PpapiMsg_PPPGraphics3D_ContextLost,
+ PP_Instance /* instance */)
+
+// PPP_InputEvent.
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPPInputEvent_HandleInputEvent,
+ PP_Instance /* instance */,
+ ppapi::InputEventData /* data */)
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiMsg_PPPInputEvent_HandleFilteredInputEvent,
+ PP_Instance /* instance */,
+ ppapi::InputEventData /* data */,
+ PP_Bool /* result */)
+
+// PPP_Instance.
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiMsg_PPPInstance_DidCreate,
+ PP_Instance /* instance */,
+ std::vector<std::string> /* argn */,
+ std::vector<std::string> /* argv */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_0(PpapiMsg_PPPInstance_DidDestroy,
+ PP_Instance /* instance */)
+IPC_MESSAGE_ROUTED4(PpapiMsg_PPPInstance_DidChangeView,
+ PP_Instance /* instance */,
+ PP_Rect /* position */,
+ PP_Rect /* clip */,
+ PP_Bool /* fullscreen */)
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPPInstance_DidChangeFocus,
+ PP_Instance /* instance */,
+ PP_Bool /* has_focus */)
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiMsg_PPPInstance_HandleInputEvent,
+ PP_Instance /* instance */,
+ PP_InputEvent /* event */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiMsg_PPPInstance_HandleDocumentLoad,
+ PP_Instance /* instance */,
+ pp::proxy::HostResource /* url_loader */,
+ PP_Bool /* result */)
+
+// PPP_Instance_Private.
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiMsg_PPPInstancePrivate_GetInstanceObject,
+ PP_Instance /* instance */,
+ pp::proxy::SerializedVar /* result */)
+
+// PPB_URLLoader
+// (Messages from browser to plugin to notify it of changes in state.)
+IPC_MESSAGE_ROUTED1(PpapiMsg_PPBURLLoader_UpdateProgress,
+ pp::proxy::PPBURLLoader_UpdateProgress_Params /* params */)
+IPC_MESSAGE_ROUTED3(PpapiMsg_PPBURLLoader_ReadResponseBody_Ack,
+ pp::proxy::HostResource /* loader */,
+ int32 /* result */,
+ std::string /* data */)
+
+// -----------------------------------------------------------------------------
+// These are from the plugin to the renderer.
+
+// Reply to PpapiMsg_CreateChannel. The handle will be NULL if the channel
+// could not be established. This could be because the IPC could not be created
+// for some weird reason, but more likely that the plugin failed to load or
+// initialize properly.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_ChannelCreated,
+ IPC::ChannelHandle /* handle */)
+
+// PPB_Audio.
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBAudio_Create,
+ PP_Instance /* instance_id */,
+ int32_t /* sample_rate */,
+ uint32_t /* sample_frame_count */,
+ pp::proxy::HostResource /* result */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBAudio_StartOrStop,
+ pp::proxy::HostResource /* audio_id */,
+ bool /* play */)
+
+// PPB_Broker.
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBBroker_Create,
+ PP_Instance /* instance */,
+ pp::proxy::HostResource /* result_resource */)
+IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBBroker_Connect,
+ pp::proxy::HostResource /* broker */)
+
+// PPB_Buffer.
+IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBBuffer_Create,
+ PP_Instance /* instance */,
+ uint32_t /* size */,
+ pp::proxy::HostResource /* result_resource */,
+ base::SharedMemoryHandle /* result_shm_handle */)
+
+// PPB_Console.
+IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBConsole_Log,
+ PP_Instance /* instance */,
+ int /* log_level */,
+ pp::proxy::SerializedVar /* value */)
+IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBConsole_LogWithSource,
+ PP_Instance /* instance */,
+ int /* log_level */,
+ pp::proxy::SerializedVar /* soruce */,
+ pp::proxy::SerializedVar /* value */)
+
+// PPB_Context3D.
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBContext3D_Create,
+ PP_Instance /* instance */,
+ int32_t /* config */,
+ std::vector<int32_t> /* attrib_list */,
+ pp::proxy::HostResource /* result */)
+
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBContext3D_BindSurfaces,
+ pp::proxy::HostResource /* context */,
+ pp::proxy::HostResource /* draw */,
+ pp::proxy::HostResource /* read */,
+ int32_t /* result */)
+
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBContext3D_Initialize,
+ pp::proxy::HostResource /* context */,
+ int32 /* size */,
+ base::SharedMemoryHandle /* ring_buffer */)
+
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBContext3D_GetState,
+ pp::proxy::HostResource /* context */,
+ gpu::CommandBuffer::State /* state */)
+
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBContext3D_Flush,
+ pp::proxy::HostResource /* context */,
+ int32 /* put_offset */,
+ int32 /* last_known_get */,
+ gpu::CommandBuffer::State /* state */)
+
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBContext3D_AsyncFlush,
+ pp::proxy::HostResource /* context */,
+ int32 /* put_offset */)
+
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBContext3D_CreateTransferBuffer,
+ pp::proxy::HostResource /* context */,
+ int32 /* size */,
+ int32 /* id */)
+
+IPC_SYNC_MESSAGE_ROUTED2_0(PpapiHostMsg_PPBContext3D_DestroyTransferBuffer,
+ pp::proxy::HostResource /* context */,
+ int32 /* id */)
+
+IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBContext3D_GetTransferBuffer,
+ pp::proxy::HostResource /* context */,
+ int32 /* id */,
+ base::SharedMemoryHandle /* transfer_buffer */,
+ uint32 /* size */)
+
+// PPB_Core.
+IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBCore_AddRefResource,
+ pp::proxy::HostResource)
+IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBCore_ReleaseResource,
+ pp::proxy::HostResource)
+
+// PPB_CharSet.
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBCharSet_GetDefaultCharSet,
+ PP_Instance /* instance */,
+ pp::proxy::SerializedVar /* result */)
+
+// PPB_CursorControl.
+IPC_SYNC_MESSAGE_ROUTED4_1(PpapiHostMsg_PPBCursorControl_SetCursor,
+ PP_Instance /* instance */,
+ int32_t /* type */,
+ pp::proxy::HostResource /* custom_image */,
+ PP_Point /* hot_spot */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBCursorControl_LockCursor,
+ PP_Instance /* instance */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBCursorControl_UnlockCursor,
+ PP_Instance /* instance */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBCursorControl_HasCursorLock,
+ PP_Instance /* instance */,
+ PP_Bool /* result */)
+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_FileSystem.
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBFileSystem_Create,
+ PP_Instance /* instance */,
+ int /* type */,
+ pp::proxy::HostResource /* result */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBFileSystem_Open,
+ pp::proxy::HostResource /* result */,
+ int64_t /* expected_size */)
+
+// PPB_Flash.
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBFlash_SetInstanceAlwaysOnTop,
+ PP_Instance /* instance */,
+ PP_Bool /* on_top */)
+// This has to be synchronous becuase the caller may want to composite on
+// top of the resulting text after the call is complete.
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFlash_DrawGlyphs,
+ pp::proxy::PPBFlash_DrawGlyphs_Params /* params */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBFlash_GetProxyForURL,
+ PP_Instance /* instance */,
+ std::string /* url */,
+ pp::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBFlash_Navigate,
+ pp::proxy::HostResource /* request_info */,
+ std::string /* target */,
+ bool /* from_user_action */,
+ int32_t /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_0(PpapiHostMsg_PPBFlash_RunMessageLoop,
+ PP_Instance /* instance */)
+IPC_SYNC_MESSAGE_ROUTED1_0(PpapiHostMsg_PPBFlash_QuitMessageLoop,
+ PP_Instance /* instance */)
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBFlash_GetLocalTimeZoneOffset,
+ PP_Instance /* instance */,
+ PP_Time /* t */,
+ double /* offset */)
+
+// PPB_Flash_Clipboard.
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBFlashClipboard_IsFormatAvailable,
+ PP_Instance /* instance */,
+ int /* clipboard_type */,
+ int /* format */,
+ bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBFlashClipboard_ReadPlainText,
+ PP_Instance /* instance */,
+ int /* clipboard_type */,
+ pp::proxy::SerializedVar /* result */)
+IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBFlashClipboard_WritePlainText,
+ PP_Instance /* instance */,
+ int /* clipboard_type */,
+ pp::proxy::SerializedVar /* text */)
+
+// PPB_Flash_File_FileRef.
+IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBFlashFile_FileRef_OpenFile,
+ pp::proxy::HostResource /* file_ref */,
+ int32_t /* mode */,
+ IPC::PlatformFileForTransit /* file_handle */,
+ int32_t /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_2(PpapiHostMsg_PPBFlashFile_FileRef_QueryFile,
+ pp::proxy::HostResource /* file_ref */,
+ PP_FileInfo /* info */,
+ int32_t /* result */)
+
+// PPB_Flash_File_ModuleLocal.
+IPC_SYNC_MESSAGE_ROUTED3_2(PpapiHostMsg_PPBFlashFile_ModuleLocal_OpenFile,
+ PP_Instance /* instance */,
+ std::string /* path */,
+ int32_t /* mode */,
+ IPC::PlatformFileForTransit /* file_handle */,
+ int32_t /* result */)
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBFlashFile_ModuleLocal_RenameFile,
+ PP_Instance /* instance */,
+ std::string /* path_from */,
+ std::string /* path_to */,
+ int32_t /* result */)
+IPC_SYNC_MESSAGE_ROUTED3_1(
+ PpapiHostMsg_PPBFlashFile_ModuleLocal_DeleteFileOrDir,
+ PP_Instance /* instance */,
+ std::string /* path */,
+ PP_Bool /* recursive */,
+ int32_t /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBFlashFile_ModuleLocal_CreateDir,
+ PP_Instance /* instance */,
+ std::string /* path */,
+ int32_t /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBFlashFile_ModuleLocal_QueryFile,
+ PP_Instance /* instance */,
+ std::string /* path */,
+ PP_FileInfo /* info */,
+ int32_t /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_2(
+ PpapiHostMsg_PPBFlashFile_ModuleLocal_GetDirContents,
+ PP_Instance /* instance */,
+ std::string /* path */,
+ std::vector<pp::proxy::SerializedDirEntry> /* entries */,
+ int32_t /* result */)
+
+// PPB_Flash_Menu
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBFlashMenu_Create,
+ PP_Instance /* instance */,
+ pp::proxy::SerializedFlashMenu /* menu_data */,
+ pp::proxy::HostResource /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_0(PpapiHostMsg_PPBFlashMenu_Show,
+ pp::proxy::HostResource /* menu */,
+ PP_Point /* location */)
+IPC_MESSAGE_ROUTED3(PpapiMsg_PPBFlashMenu_ShowACK,
+ pp::proxy::HostResource /* menu */,
+ int32_t /* selected_id */,
+ int32_t /* result */)
+
+// PPB_Flash_NetConnector.
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFlashNetConnector_Create,
+ PP_Instance /* instance_id */,
+ pp::proxy::HostResource /* result */)
+IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBFlashNetConnector_ConnectTcp,
+ pp::proxy::HostResource /* connector */,
+ std::string /* host */,
+ uint16_t /* port */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBFlashNetConnector_ConnectTcpAddress,
+ pp::proxy::HostResource /* connector */,
+ std::string /* net_address_as_string */)
+
+// PPB_Flash_TCPSocket.
+IPC_SYNC_MESSAGE_CONTROL2_1(PpapiHostMsg_PPBFlashTCPSocket_Create,
+ int32 /* routing_id */,
+ uint32 /* plugin_dispatcher_id */,
+ uint32 /* socket_id */)
+IPC_MESSAGE_CONTROL3(PpapiHostMsg_PPBFlashTCPSocket_Connect,
+ uint32 /* socket_id */,
+ std::string /* host */,
+ uint16_t /* port */)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_PPBFlashTCPSocket_ConnectWithNetAddress,
+ uint32 /* socket_id */,
+ PP_Flash_NetAddress /* net_addr */)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_PPBFlashTCPSocket_Read,
+ uint32 /* socket_id */,
+ int32_t /* bytes_to_read */)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_PPBFlashTCPSocket_Write,
+ uint32 /* socket_id */,
+ std::string /* data */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_PPBFlashTCPSocket_Disconnect,
+ uint32 /* socket_id */)
+
+// PPB_Font.
+IPC_SYNC_MESSAGE_CONTROL0_1(PpapiHostMsg_PPBFont_GetFontFamilies,
+ std::string /* result */)
+
+// PPB_Graphics2D.
+IPC_MESSAGE_ROUTED5(PpapiHostMsg_PPBGraphics2D_PaintImageData,
+ pp::proxy::HostResource /* graphics_2d */,
+ pp::proxy::HostResource /* image_data */,
+ PP_Point /* top_left */,
+ bool /* src_rect_specified */,
+ PP_Rect /* src_rect */)
+IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBGraphics2D_Scroll,
+ pp::proxy::HostResource /* graphics_2d */,
+ bool /* clip_specified */,
+ PP_Rect /* clip */,
+ PP_Point /* amount */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBGraphics2D_ReplaceContents,
+ pp::proxy::HostResource /* graphics_2d */,
+ pp::proxy::HostResource /* image_data */)
+IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBGraphics2D_Flush,
+ pp::proxy::HostResource /* graphics_2d */)
+
+// PPB_Instance.
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBInstance_GetWindowObject,
+ PP_Instance /* instance */,
+ pp::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBInstance_GetOwnerElementObject,
+ PP_Instance /* instance */,
+ pp::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBInstance_BindGraphics,
+ PP_Instance /* instance */,
+ pp::proxy::HostResource /* device */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBInstance_IsFullFrame,
+ PP_Instance /* instance */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBInstance_ExecuteScript,
+ PP_Instance /* instance */,
+ pp::proxy::SerializedVar /* script */,
+ pp::proxy::SerializedVar /* out_exception */,
+ pp::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBInstance_SetFullscreen,
+ PP_Instance /* instance */,
+ PP_Bool /* fullscreen */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_2(PpapiHostMsg_PPBInstance_GetScreenSize,
+ PP_Instance /* instance */,
+ PP_Bool /* result */,
+ PP_Size /* size */)
+IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBInstance_RequestInputEvents,
+ PP_Instance /* instance */,
+ bool /* is_filtering */,
+ uint32_t /* event_classes */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBInstance_ClearInputEvents,
+ PP_Instance /* instance */,
+ uint32_t /* event_classes */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBInstance_PostMessage,
+ PP_Instance /* instance */,
+ pp::proxy::SerializedVar /* message */)
+
+IPC_SYNC_MESSAGE_ROUTED3_1(
+ PpapiHostMsg_PPBPDF_GetFontFileWithFallback,
+ PP_Instance /* instance */,
+ pp::proxy::SerializedFontDescription /* description */,
+ int32_t /* charset */,
+ pp::proxy::HostResource /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_1(
+ PpapiHostMsg_PPBPDF_GetFontTableForPrivateFontFile,
+ pp::proxy::HostResource /* font_file */,
+ uint32_t /* table */,
+ std::string /* result */)
+
+// PPB_Surface3D.
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBSurface3D_Create,
+ PP_Instance /* instance */,
+ int32_t /* config */,
+ std::vector<int32_t> /* attrib_list */,
+ pp::proxy::HostResource /* result */)
+IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBSurface3D_SwapBuffers,
+ pp::proxy::HostResource /* surface_3d */)
+
+// PPB_Testing.
+IPC_SYNC_MESSAGE_ROUTED3_1(
+ PpapiHostMsg_PPBTesting_ReadImageData,
+ pp::proxy::HostResource /* device_context_2d */,
+ pp::proxy::HostResource /* image */,
+ PP_Point /* top_left */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_0(PpapiHostMsg_PPBTesting_RunMessageLoop,
+ PP_Instance /* instance */)
+IPC_SYNC_MESSAGE_ROUTED1_0(PpapiHostMsg_PPBTesting_QuitMessageLoop,
+ PP_Instance /* instance */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBTesting_GetLiveObjectsForInstance,
+ PP_Instance /* instance */,
+ uint32 /* result */)
+
+// PPB_URLLoader.
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBURLLoader_Create,
+ PP_Instance /* instance */,
+ pp::proxy::HostResource /* result */)
+IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBURLLoader_Open,
+ pp::proxy::HostResource /* loader */,
+ pp::proxy::HostResource /*request_info */,
+ uint32_t /* serialized_callback */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBURLLoader_FollowRedirect,
+ pp::proxy::HostResource /* loader */,
+ uint32_t /* serialized_callback */)
+IPC_SYNC_MESSAGE_ROUTED1_1(
+ PpapiHostMsg_PPBURLLoader_GetResponseInfo,
+ pp::proxy::HostResource /* loader */,
+ pp::proxy::HostResource /* response_info_out */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBURLLoader_ReadResponseBody,
+ pp::proxy::HostResource /* loader */,
+ int32_t /* bytes_to_read */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBURLLoader_FinishStreamingToFile,
+ pp::proxy::HostResource /* loader */,
+ uint32_t /* serialized_callback */)
+IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBURLLoader_Close,
+ pp::proxy::HostResource /* loader */)
+IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBURLLoader_GrantUniversalAccess,
+ pp::proxy::HostResource /* loader */)
+
+// PPB_URLRequestInfo.
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBURLRequestInfo_Create,
+ PP_Instance /* instance */,
+ pp::proxy::HostResource /* result */)
+IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBURLRequestInfo_SetProperty,
+ pp::proxy::HostResource /* request */,
+ int32_t /* property */,
+ pp::proxy::SerializedVar /* value */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBURLRequestInfo_AppendDataToBody,
+ pp::proxy::HostResource /* request */,
+ std::string /* data */)
+IPC_MESSAGE_ROUTED5(PpapiHostMsg_PPBURLRequestInfo_AppendFileToBody,
+ pp::proxy::HostResource /* request */,
+ pp::proxy::HostResource /* file_ref */,
+ int64_t /* start_offset */,
+ int64_t /* number_of_bytes */,
+ double /* expected_last_modified_time */)
+
+// PPB_URLResponseInfo.
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBURLResponseInfo_GetProperty,
+ pp::proxy::HostResource /* response */,
+ int32_t /* property */,
+ pp::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBURLResponseInfo_GetBodyAsFileRef,
+ pp::proxy::HostResource /* response */,
+ pp::proxy::PPBFileRef_CreateInfo /* result */)
+
+// PPB_URLUtil.
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBURLUtil_ResolveRelativeToDocument,
+ PP_Instance /* instance */,
+ pp::proxy::SerializedVar /* relative */,
+ pp::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBURLUtil_DocumentCanRequest,
+ PP_Instance /* instance */,
+ pp::proxy::SerializedVar /* relative */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBURLUtil_DocumentCanAccessDocument,
+ PP_Instance /* active */,
+ PP_Instance /* target */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBURLUtil_GetDocumentURL,
+ PP_Instance /* active */,
+ pp::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBURLUtil_GetPluginInstanceURL,
+ PP_Instance /* active */,
+ pp::proxy::SerializedVar /* result */)
+
+// PPB_Var.
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBVar_AddRefObject,
+ int64 /* object_id */,
+ int /* unused - need a return value for sync msgs */)
+IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBVar_ReleaseObject,
+ int64 /* object_id */)
+IPC_SYNC_MESSAGE_ROUTED3_2(PpapiHostMsg_PPBVar_ConvertType,
+ PP_Instance /* instance */,
+ pp::proxy::SerializedVar /* var */,
+ int /* new_type */,
+ pp::proxy::SerializedVar /* exception */,
+ pp::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_HasProperty,
+ pp::proxy::SerializedVar /* object */,
+ pp::proxy::SerializedVar /* property */,
+ pp::proxy::SerializedVar /* out_exception */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_HasMethodDeprecated,
+ pp::proxy::SerializedVar /* object */,
+ pp::proxy::SerializedVar /* method */,
+ pp::proxy::SerializedVar /* out_exception */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_GetProperty,
+ pp::proxy::SerializedVar /* object */,
+ pp::proxy::SerializedVar /* property */,
+ pp::proxy::SerializedVar /* out_exception */,
+ pp::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_DeleteProperty,
+ pp::proxy::SerializedVar /* object */,
+ pp::proxy::SerializedVar /* property */,
+ pp::proxy::SerializedVar /* out_exception */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_2(PpapiHostMsg_PPBVar_EnumerateProperties,
+ pp::proxy::SerializedVar /* object */,
+ std::vector<pp::proxy::SerializedVar> /* props */,
+ pp::proxy::SerializedVar /* out_exception */)
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBVar_SetPropertyDeprecated,
+ pp::proxy::SerializedVar /* object */,
+ pp::proxy::SerializedVar /* name */,
+ pp::proxy::SerializedVar /* value */,
+ pp::proxy::SerializedVar /* out_exception */)
+IPC_SYNC_MESSAGE_ROUTED3_2(PpapiHostMsg_PPBVar_CallDeprecated,
+ pp::proxy::SerializedVar /* object */,
+ pp::proxy::SerializedVar /* method_name */,
+ std::vector<pp::proxy::SerializedVar> /* args */,
+ pp::proxy::SerializedVar /* out_exception */,
+ pp::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_Construct,
+ pp::proxy::SerializedVar /* object */,
+ std::vector<pp::proxy::SerializedVar> /* args */,
+ pp::proxy::SerializedVar /* out_exception */,
+ pp::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_IsInstanceOfDeprecated,
+ pp::proxy::SerializedVar /* var */,
+ int64 /* object_class */,
+ int64 /* object-data */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBVar_CreateObjectDeprecated,
+ PP_Instance /* instance */,
+ int64 /* object_class */,
+ int64 /* object_data */,
+ pp::proxy::SerializedVar /* result */)
+
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_ResourceCreation_Graphics2D,
+ PP_Instance /* instance */,
+ PP_Size /* size */,
+ PP_Bool /* is_always_opaque */,
+ pp::proxy::HostResource /* result */)
+IPC_SYNC_MESSAGE_ROUTED4_3(PpapiHostMsg_ResourceCreation_ImageData,
+ PP_Instance /* instance */,
+ int32 /* format */,
+ PP_Size /* size */,
+ PP_Bool /* init_to_zero */,
+ pp::proxy::HostResource /* result_resource */,
+ std::string /* image_data_desc */,
+ pp::proxy::ImageHandle /* result */)
diff --git a/ppapi/proxy/ppapi_param_traits.cc b/ppapi/proxy/ppapi_param_traits.cc
new file mode 100644
index 0000000..87c253b
--- /dev/null
+++ b/ppapi/proxy/ppapi_param_traits.cc
@@ -0,0 +1,510 @@
+// 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/ppapi_param_traits.h"
+
+#include <string.h> // For memcpy
+
+#include "ppapi/c/pp_file_info.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/private/ppb_flash_tcp_socket.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/proxy/serialized_flash_menu.h"
+
+namespace IPC {
+
+namespace {
+
+// Deserializes a vector from IPC. This special version must be used instead
+// of the default IPC version when the vector contains a SerializedVar, either
+// directly or indirectly (i.e. a vector of objects that have a SerializedVar
+// inside them).
+//
+// The default vector deserializer does resize and then we deserialize into
+// those allocated slots. However, the implementation of vector (at least in
+// GCC's implementation), creates a new empty object using the default
+// constructor, and then sets the rest of the items to that empty one using the
+// copy constructor.
+//
+// Since we allocate the inner class when you call the default constructor and
+// transfer the inner class when you do operator=, the entire vector will end
+// up referring to the same inner class. Deserializing into this will just end
+// up overwriting the same item over and over, since all the SerializedVars
+// will refer to the same thing.
+//
+// The solution is to make a new object for each deserialized item, and then
+// add it to the vector one at a time.
+template<typename T>
+bool ReadVectorWithoutCopy(const Message* m,
+ void** iter,
+ std::vector<T>* output) {
+ // This part is just a copy of the the default ParamTraits vector Read().
+ int size;
+ // ReadLength() checks for < 0 itself.
+ if (!m->ReadLength(iter, &size))
+ return false;
+ // Resizing beforehand is not safe, see BUG 1006367 for details.
+ if (INT_MAX / sizeof(T) <= static_cast<size_t>(size))
+ return false;
+
+ output->reserve(size);
+ for (int i = 0; i < size; i++) {
+ T cur;
+ if (!ReadParam(m, iter, &cur))
+ return false;
+ output->push_back(cur);
+ }
+ return true;
+}
+
+// This serializes the vector of items to the IPC message in exactly the same
+// way as the "regular" IPC vector serializer does. But having the code here
+// saves us from having to copy this code into all ParamTraits that use the
+// ReadVectorWithoutCopy function for deserializing.
+template<typename T>
+void WriteVectorWithoutCopy(Message* m, const std::vector<T>& p) {
+ WriteParam(m, static_cast<int>(p.size()));
+ for (size_t i = 0; i < p.size(); i++)
+ WriteParam(m, p[i]);
+}
+
+} // namespace
+
+// PP_Bool ---------------------------------------------------------------------
+
+// static
+void ParamTraits<PP_Bool>::Write(Message* m, const param_type& p) {
+ ParamTraits<bool>::Write(m, PP_ToBool(p));
+}
+
+// static
+bool ParamTraits<PP_Bool>::Read(const Message* m, void** iter, param_type* r) {
+ // We specifically want to be strict here about what types of input we accept,
+ // which ParamTraits<bool> does for us. We don't want to deserialize "2" into
+ // a PP_Bool, for example.
+ bool result = false;
+ if (!ParamTraits<bool>::Read(m, iter, &result))
+ return false;
+ *r = PP_FromBool(result);
+ return true;
+}
+
+// static
+void ParamTraits<PP_Bool>::Log(const param_type& p, std::string* l) {
+}
+
+// PP_FileInfo -------------------------------------------------------------
+
+// static
+void ParamTraits<PP_FileInfo>::Write(Message* m, const param_type& p) {
+ ParamTraits<int64_t>::Write(m, p.size);
+ ParamTraits<int>::Write(m, static_cast<int>(p.type));
+ ParamTraits<int>::Write(m, static_cast<int>(p.system_type));
+ ParamTraits<double>::Write(m, p.creation_time);
+ ParamTraits<double>::Write(m, p.last_access_time);
+ ParamTraits<double>::Write(m, p.last_modified_time);
+}
+
+// static
+bool ParamTraits<PP_FileInfo>::Read(const Message* m, void** iter,
+ param_type* r) {
+ int type, system_type;
+ if (!ParamTraits<int64_t>::Read(m, iter, &r->size) ||
+ !ParamTraits<int>::Read(m, iter, &type) ||
+ !ParamTraits<int>::Read(m, iter, &system_type) ||
+ !ParamTraits<double>::Read(m, iter, &r->creation_time) ||
+ !ParamTraits<double>::Read(m, iter, &r->last_access_time) ||
+ !ParamTraits<double>::Read(m, iter, &r->last_modified_time))
+ return false;
+ if (type != PP_FILETYPE_REGULAR &&
+ type != PP_FILETYPE_DIRECTORY &&
+ type != PP_FILETYPE_OTHER)
+ return false;
+ r->type = static_cast<PP_FileType>(type);
+ if (system_type != PP_FILESYSTEMTYPE_EXTERNAL &&
+ system_type != PP_FILESYSTEMTYPE_LOCALPERSISTENT &&
+ system_type != PP_FILESYSTEMTYPE_LOCALTEMPORARY)
+ return false;
+ r->system_type = static_cast<PP_FileSystemType>(system_type);
+ return true;
+}
+
+// static
+void ParamTraits<PP_FileInfo>::Log(const param_type& p, std::string* l) {
+}
+
+// PP_Flash_NetAddress ---------------------------------------------------------
+
+// static
+void ParamTraits<PP_Flash_NetAddress>::Write(Message* m, const param_type& p) {
+ WriteParam(m, p.size);
+ m->WriteBytes(p.data, static_cast<int>(p.size));
+}
+
+// static
+bool ParamTraits<PP_Flash_NetAddress>::Read(const Message* m,
+ void** iter,
+ param_type* p) {
+ uint16 size;
+ if (!ReadParam(m, iter, &size))
+ return false;
+ if (size > sizeof(p->data))
+ return false;
+ p->size = size;
+
+ const char* data;
+ if (!m->ReadBytes(iter, &data, size))
+ return false;
+ memcpy(p->data, data, size);
+ return true;
+}
+
+// static
+void ParamTraits<PP_Flash_NetAddress>::Log(const param_type& p,
+ std::string* l) {
+ l->append("<PP_Flash_NetAddress (");
+ LogParam(p.size, l);
+ l->append(" bytes)>");
+}
+
+// PP_InputEvent ---------------------------------------------------------------
+
+// static
+void ParamTraits<PP_InputEvent>::Write(Message* m, const param_type& p) {
+ // PP_InputEvent is just POD so we can just memcpy it.
+ m->WriteData(reinterpret_cast<const char*>(&p), sizeof(PP_InputEvent));
+}
+
+// static
+bool ParamTraits<PP_InputEvent>::Read(const Message* m,
+ void** iter,
+ param_type* r) {
+ const char* data;
+ int data_size;
+ if (!m->ReadData(iter, &data, &data_size))
+ return false;
+ memcpy(r, data, sizeof(PP_InputEvent));
+ return true;
+}
+
+// static
+void ParamTraits<PP_InputEvent>::Log(const param_type& p, std::string* l) {
+}
+
+// PP_ObjectProperty -----------------------------------------------------------
+
+// static
+void ParamTraits<PP_ObjectProperty>::Write(Message* m, const param_type& p) {
+ // FIXME(brettw);
+}
+
+// static
+bool ParamTraits<PP_ObjectProperty>::Read(const Message* m,
+ void** iter,
+ param_type* r) {
+ // FIXME(brettw);
+ return true;
+}
+
+// static
+void ParamTraits<PP_ObjectProperty>::Log(const param_type& p, std::string* l) {
+}
+
+// PPBFlash_DrawGlyphs_Params --------------------------------------------------
+
+// static
+void ParamTraits<pp::proxy::PPBFlash_DrawGlyphs_Params>::Write(
+ Message* m,
+ const param_type& p) {
+ ParamTraits<PP_Instance>::Write(m, p.instance);
+ ParamTraits<pp::proxy::HostResource>::Write(m, p.image_data);
+ ParamTraits<pp::proxy::SerializedFontDescription>::Write(m, p.font_desc);
+ ParamTraits<uint32_t>::Write(m, p.color);
+ ParamTraits<PP_Point>::Write(m, p.position);
+ ParamTraits<PP_Rect>::Write(m, p.clip);
+ ParamTraits<float>::Write(m, p.transformation[0][0]);
+ ParamTraits<float>::Write(m, p.transformation[0][1]);
+ ParamTraits<float>::Write(m, p.transformation[0][2]);
+ ParamTraits<float>::Write(m, p.transformation[1][0]);
+ ParamTraits<float>::Write(m, p.transformation[1][1]);
+ ParamTraits<float>::Write(m, p.transformation[1][2]);
+ ParamTraits<float>::Write(m, p.transformation[2][0]);
+ ParamTraits<float>::Write(m, p.transformation[2][1]);
+ ParamTraits<float>::Write(m, p.transformation[2][2]);
+ ParamTraits<std::vector<uint16_t> >::Write(m, p.glyph_indices);
+ ParamTraits<std::vector<PP_Point> >::Write(m, p.glyph_advances);
+}
+
+// static
+bool ParamTraits<pp::proxy::PPBFlash_DrawGlyphs_Params>::Read(
+ const Message* m,
+ void** iter,
+ param_type* r) {
+ return
+ ParamTraits<PP_Instance>::Read(m, iter, &r->instance) &&
+ ParamTraits<pp::proxy::HostResource>::Read(m, iter,
+ &r->image_data) &&
+ ParamTraits<pp::proxy::SerializedFontDescription>::Read(m, iter,
+ &r->font_desc) &&
+ ParamTraits<uint32_t>::Read(m, iter, &r->color) &&
+ ParamTraits<PP_Point>::Read(m, iter, &r->position) &&
+ ParamTraits<PP_Rect>::Read(m, iter, &r->clip) &&
+ ParamTraits<float>::Read(m, iter, &r->transformation[0][0]) &&
+ ParamTraits<float>::Read(m, iter, &r->transformation[0][1]) &&
+ ParamTraits<float>::Read(m, iter, &r->transformation[0][2]) &&
+ ParamTraits<float>::Read(m, iter, &r->transformation[1][0]) &&
+ ParamTraits<float>::Read(m, iter, &r->transformation[1][1]) &&
+ ParamTraits<float>::Read(m, iter, &r->transformation[1][2]) &&
+ ParamTraits<float>::Read(m, iter, &r->transformation[2][0]) &&
+ ParamTraits<float>::Read(m, iter, &r->transformation[2][1]) &&
+ ParamTraits<float>::Read(m, iter, &r->transformation[2][2]) &&
+ ParamTraits<std::vector<uint16_t> >::Read(m, iter, &r->glyph_indices) &&
+ ParamTraits<std::vector<PP_Point> >::Read(m, iter, &r->glyph_advances) &&
+ r->glyph_indices.size() == r->glyph_advances.size();
+}
+
+// static
+void ParamTraits<pp::proxy::PPBFlash_DrawGlyphs_Params>::Log(
+ const param_type& p,
+ 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) {
+}
+
+// PPBURLLoader_UpdateProgress_Params ------------------------------------------
+
+// static
+void ParamTraits<pp::proxy::PPBURLLoader_UpdateProgress_Params>::Write(
+ Message* m,
+ const param_type& p) {
+ ParamTraits<PP_Instance>::Write(m, p.instance);
+ ParamTraits<pp::proxy::HostResource>::Write(m, p.resource);
+ ParamTraits<int64_t>::Write(m, p.bytes_sent);
+ ParamTraits<int64_t>::Write(m, p.total_bytes_to_be_sent);
+ ParamTraits<int64_t>::Write(m, p.bytes_received);
+ ParamTraits<int64_t>::Write(m, p.total_bytes_to_be_received);
+}
+
+// static
+bool ParamTraits<pp::proxy::PPBURLLoader_UpdateProgress_Params>::Read(
+ const Message* m,
+ void** iter,
+ param_type* r) {
+ return
+ ParamTraits<PP_Instance>::Read(m, iter, &r->instance) &&
+ ParamTraits<pp::proxy::HostResource>::Read(m, iter, &r->resource) &&
+ ParamTraits<int64_t>::Read(m, iter, &r->bytes_sent) &&
+ ParamTraits<int64_t>::Read(m, iter, &r->total_bytes_to_be_sent) &&
+ ParamTraits<int64_t>::Read(m, iter, &r->bytes_received) &&
+ ParamTraits<int64_t>::Read(m, iter, &r->total_bytes_to_be_received);
+}
+
+// static
+void ParamTraits<pp::proxy::PPBURLLoader_UpdateProgress_Params>::Log(
+ const param_type& p,
+ std::string* l) {
+}
+
+// SerializedDirEntry ----------------------------------------------------------
+
+// static
+void ParamTraits<pp::proxy::SerializedDirEntry>::Write(Message* m,
+ const param_type& p) {
+ ParamTraits<std::string>::Write(m, p.name);
+ ParamTraits<bool>::Write(m, p.is_dir);
+}
+
+// static
+bool ParamTraits<pp::proxy::SerializedDirEntry>::Read(const Message* m,
+ void** iter,
+ param_type* r) {
+ return ParamTraits<std::string>::Read(m, iter, &r->name) &&
+ ParamTraits<bool>::Read(m, iter, &r->is_dir);
+}
+
+// static
+void ParamTraits<pp::proxy::SerializedDirEntry>::Log(const param_type& p,
+ std::string* l) {
+}
+
+// pp::proxy::SerializedFontDescription ----------------------------------------
+
+// static
+void ParamTraits<pp::proxy::SerializedFontDescription>::Write(
+ Message* m,
+ const param_type& p) {
+ ParamTraits<pp::proxy::SerializedVar>::Write(m, p.face);
+ ParamTraits<int32_t>::Write(m, p.family);
+ ParamTraits<uint32_t>::Write(m, p.size);
+ ParamTraits<int32_t>::Write(m, p.weight);
+ ParamTraits<PP_Bool>::Write(m, p.italic);
+ ParamTraits<PP_Bool>::Write(m, p.small_caps);
+ ParamTraits<int32_t>::Write(m, p.letter_spacing);
+ ParamTraits<int32_t>::Write(m, p.word_spacing);
+}
+
+// static
+bool ParamTraits<pp::proxy::SerializedFontDescription>::Read(
+ const Message* m,
+ void** iter,
+ param_type* r) {
+ return
+ ParamTraits<pp::proxy::SerializedVar>::Read(m, iter, &r->face) &&
+ ParamTraits<int32_t>::Read(m, iter, &r->family) &&
+ ParamTraits<uint32_t>::Read(m, iter, &r->size) &&
+ ParamTraits<int32_t>::Read(m, iter, &r->weight) &&
+ ParamTraits<PP_Bool>::Read(m, iter, &r->italic) &&
+ ParamTraits<PP_Bool>::Read(m, iter, &r->small_caps) &&
+ ParamTraits<int32_t>::Read(m, iter, &r->letter_spacing) &&
+ ParamTraits<int32_t>::Read(m, iter, &r->word_spacing);
+}
+
+// static
+void ParamTraits<pp::proxy::SerializedFontDescription>::Log(
+ const param_type& p,
+ std::string* l) {
+}
+
+// HostResource ----------------------------------------------------------
+
+// static
+void ParamTraits<pp::proxy::HostResource>::Write(Message* m,
+ const param_type& p) {
+ ParamTraits<PP_Instance>::Write(m, p.instance());
+ ParamTraits<PP_Resource>::Write(m, p.host_resource());
+}
+
+// static
+bool ParamTraits<pp::proxy::HostResource>::Read(const Message* m,
+ void** iter,
+ param_type* r) {
+ PP_Instance instance;
+ PP_Resource resource;
+ if (!ParamTraits<PP_Instance>::Read(m, iter, &instance) ||
+ !ParamTraits<PP_Resource>::Read(m, iter, &resource))
+ return false;
+ r->SetHostResource(instance, resource);
+ return true;
+}
+
+// static
+void ParamTraits<pp::proxy::HostResource>::Log(const param_type& p,
+ std::string* l) {
+}
+
+// SerializedVar ---------------------------------------------------------------
+
+// static
+void ParamTraits<pp::proxy::SerializedVar>::Write(Message* m,
+ const param_type& p) {
+ p.WriteToMessage(m);
+}
+
+// static
+bool ParamTraits<pp::proxy::SerializedVar>::Read(const Message* m,
+ void** iter,
+ param_type* r) {
+ return r->ReadFromMessage(m, iter);
+}
+
+// static
+void ParamTraits<pp::proxy::SerializedVar>::Log(const param_type& p,
+ std::string* l) {
+}
+
+// std::vector<SerializedVar> --------------------------------------------------
+
+void ParamTraits< std::vector<pp::proxy::SerializedVar> >::Write(
+ Message* m,
+ const param_type& p) {
+ WriteVectorWithoutCopy(m, p);
+}
+
+// static
+bool ParamTraits< std::vector<pp::proxy::SerializedVar> >::Read(
+ const Message* m,
+ void** iter,
+ param_type* r) {
+ return ReadVectorWithoutCopy(m, iter, r);
+}
+
+// static
+void ParamTraits< std::vector<pp::proxy::SerializedVar> >::Log(
+ const param_type& p,
+ std::string* l) {
+}
+
+// std::vector<PPBFileRef_CreateInfo> ------------------------------------------
+
+void ParamTraits< std::vector<pp::proxy::PPBFileRef_CreateInfo> >::Write(
+ Message* m,
+ const param_type& p) {
+ WriteVectorWithoutCopy(m, p);
+}
+
+// static
+bool ParamTraits< std::vector<pp::proxy::PPBFileRef_CreateInfo> >::Read(
+ const Message* m,
+ void** iter,
+ param_type* r) {
+ return ReadVectorWithoutCopy(m, iter, r);
+}
+
+// static
+void ParamTraits< std::vector<pp::proxy::PPBFileRef_CreateInfo> >::Log(
+ const param_type& p,
+ std::string* l) {
+}
+
+// SerializedFlashMenu ---------------------------------------------------------
+
+// static
+void ParamTraits<pp::proxy::SerializedFlashMenu>::Write(Message* m,
+ const param_type& p) {
+ p.WriteToMessage(m);
+}
+
+// static
+bool ParamTraits<pp::proxy::SerializedFlashMenu>::Read(const Message* m,
+ void** iter,
+ param_type* r) {
+ return r->ReadFromMessage(m, iter);
+}
+
+// static
+void ParamTraits<pp::proxy::SerializedFlashMenu>::Log(const param_type& p,
+ std::string* l) {
+}
+
+} // namespace IPC
diff --git a/ppapi/proxy/ppapi_param_traits.h b/ppapi/proxy/ppapi_param_traits.h
new file mode 100644
index 0000000..0db47cd
--- /dev/null
+++ b/ppapi/proxy/ppapi_param_traits.h
@@ -0,0 +1,162 @@
+// 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_PPAPI_PARAM_TRAITS_H_
+#define PPAPI_PROXY_PPAPI_PARAM_TRAITS_H_
+
+#include <string>
+#include <vector>
+
+#include "ipc/ipc_message_utils.h"
+#include "ipc/ipc_platform_file.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_input_event.h"
+#include "ppapi/c/pp_rect.h"
+#include "ppapi/c/pp_var.h"
+
+struct PP_FileInfo;
+struct PP_ObjectProperty;
+struct PP_Flash_Menu;
+struct PP_Flash_NetAddress;
+
+namespace pp {
+namespace proxy {
+
+class HostResource;
+struct PPBFileRef_CreateInfo;
+struct PPBFlash_DrawGlyphs_Params;
+struct PPBURLLoader_UpdateProgress_Params;
+struct SerializedDirEntry;
+struct SerializedFontDescription;
+class SerializedFlashMenu;
+class SerializedVar;
+
+} // namespace proxy
+} // namespace pp
+
+namespace IPC {
+
+template<>
+struct ParamTraits<PP_Bool> {
+ typedef PP_Bool 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_FileInfo> {
+ typedef PP_FileInfo 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_Flash_NetAddress> {
+ typedef PP_Flash_NetAddress param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* p);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct ParamTraits<PP_InputEvent> {
+ typedef PP_InputEvent 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_ObjectProperty> {
+ typedef PP_ObjectProperty 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::PPBFlash_DrawGlyphs_Params> {
+ typedef pp::proxy::PPBFlash_DrawGlyphs_Params 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::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::PPBURLLoader_UpdateProgress_Params> {
+ typedef pp::proxy::PPBURLLoader_UpdateProgress_Params 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::SerializedDirEntry> {
+ typedef pp::proxy::SerializedDirEntry 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::SerializedFontDescription> {
+ typedef pp::proxy::SerializedFontDescription 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::HostResource> {
+ typedef pp::proxy::HostResource 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::SerializedVar> {
+ typedef pp::proxy::SerializedVar 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< std::vector<pp::proxy::SerializedVar> > {
+ typedef std::vector<pp::proxy::SerializedVar> 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< std::vector<pp::proxy::PPBFileRef_CreateInfo> > {
+ typedef std::vector<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::SerializedFlashMenu> {
+ typedef pp::proxy::SerializedFlashMenu 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);
+};
+
+} // namespace IPC
+
+#endif // PPAPI_PROXY_PPAPI_PARAM_TRAITS_H_
diff --git a/ppapi/proxy/ppapi_proxy_test.cc b/ppapi/proxy/ppapi_proxy_test.cc
new file mode 100644
index 0000000..c8bb7eb
--- /dev/null
+++ b/ppapi/proxy/ppapi_proxy_test.cc
@@ -0,0 +1,376 @@
+// 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/ppapi_proxy_test.h"
+
+#include "base/message_loop_proxy.h"
+#include "base/observer_list.h"
+#include "ipc/ipc_sync_channel.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/private/ppb_proxy_private.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/ppapi_preferences.cc"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+// HostDispatcher requires a PPB_Proxy_Private, so we always provide a fallback
+// do-nothing implementation.
+void PluginCrashed(PP_Module module) {
+ NOTREACHED();
+};
+
+PP_Instance GetInstanceForResource(PP_Resource resource) {
+ // If a test relies on this, we need to implement it.
+ NOTREACHED();
+ return 0;
+}
+
+void SetReserveInstanceIDCallback(PP_Module module,
+ PP_Bool (*is_seen)(PP_Module, PP_Instance)) {
+ // This function gets called in HostDispatcher's constructor. We simply don't
+ // worry about Instance uniqueness in tests, so we can ignore the call.
+}
+
+int32_t GetURLLoaderBufferedBytes(PP_Resource url_loader) {
+ NOTREACHED();
+ return 0;
+}
+
+void AddRefModule(PP_Module module) {}
+void ReleaseModule(PP_Module module) {}
+
+PPB_Proxy_Private ppb_proxy_private = { PluginCrashed,
+ GetInstanceForResource,
+ SetReserveInstanceIDCallback,
+ GetURLLoaderBufferedBytes,
+ AddRefModule,
+ ReleaseModule };
+
+// We allow multiple harnesses at a time to respond to 'GetInterface' calls.
+// We assume that only 1 harness's GetInterface function will ever support a
+// given interface name. In practice, there will either be only 1 GetInterface
+// handler (for PluginProxyTest or HostProxyTest), or there will be only 2
+// GetInterface handlers (for TwoWayTest). In the latter case, one handler is
+// for the PluginProxyTestHarness and should only respond for PPP interfaces,
+// and the other handler is for the HostProxyTestHarness which should only
+// ever respond for PPB interfaces.
+ObserverList<ProxyTestHarnessBase> get_interface_handlers_;
+
+const void* MockGetInterface(const char* name) {
+ ObserverList<ProxyTestHarnessBase>::Iterator it =
+ get_interface_handlers_;
+ while (ProxyTestHarnessBase* observer = it.GetNext()) {
+ const void* interface = observer->GetInterface(name);
+ if (interface)
+ return interface;
+ }
+ if (strcmp(name, PPB_PROXY_PRIVATE_INTERFACE) == 0)
+ return &ppb_proxy_private;
+ return NULL;
+}
+
+void SetUpRemoteHarness(ProxyTestHarnessBase* harness,
+ const IPC::ChannelHandle& handle,
+ base::MessageLoopProxy* ipc_message_loop_proxy,
+ base::WaitableEvent* shutdown_event,
+ base::WaitableEvent* harness_set_up) {
+ harness->SetUpHarnessWithChannel(handle, ipc_message_loop_proxy,
+ shutdown_event, false);
+ harness_set_up->Signal();
+}
+
+void TearDownRemoteHarness(ProxyTestHarnessBase* harness,
+ base::WaitableEvent* harness_torn_down) {
+ harness->TearDownHarness();
+ harness_torn_down->Signal();
+}
+
+} // namespace
+
+// ProxyTestHarnessBase --------------------------------------------------------
+
+ProxyTestHarnessBase::ProxyTestHarnessBase() : pp_module_(0x98765),
+ pp_instance_(0x12345) {
+ get_interface_handlers_.AddObserver(this);
+}
+
+ProxyTestHarnessBase::~ProxyTestHarnessBase() {
+ get_interface_handlers_.RemoveObserver(this);
+}
+
+const void* ProxyTestHarnessBase::GetInterface(const char* name) {
+ return registered_interfaces_[name];
+}
+
+void ProxyTestHarnessBase::RegisterTestInterface(const char* name,
+ const void* interface) {
+ registered_interfaces_[name] = interface;
+}
+
+bool ProxyTestHarnessBase::SupportsInterface(const char* name) {
+ sink().ClearMessages();
+
+ // IPC doesn't actually write to this when we send a message manually
+ // not actually using IPC.
+ bool unused_result = false;
+ PpapiMsg_SupportsInterface msg(name, &unused_result);
+ GetDispatcher()->OnMessageReceived(msg);
+
+ const IPC::Message* reply_msg =
+ sink().GetUniqueMessageMatching(IPC_REPLY_ID);
+ EXPECT_TRUE(reply_msg);
+ if (!reply_msg)
+ return false;
+
+ TupleTypes<PpapiMsg_SupportsInterface::ReplyParam>::ValueTuple reply_data;
+ EXPECT_TRUE(PpapiMsg_SupportsInterface::ReadReplyParam(
+ reply_msg, &reply_data));
+
+ sink().ClearMessages();
+ return reply_data.a;
+}
+
+// PluginProxyTestHarness ------------------------------------------------------
+
+PluginProxyTestHarness::PluginProxyTestHarness() {
+}
+
+PluginProxyTestHarness::~PluginProxyTestHarness() {
+}
+
+Dispatcher* PluginProxyTestHarness::GetDispatcher() {
+ return plugin_dispatcher_.get();
+}
+
+void PluginProxyTestHarness::SetUpHarness() {
+ // These must be first since the dispatcher set-up uses them.
+ PluginResourceTracker::SetInstanceForTest(&resource_tracker_);
+ PluginVarTracker::SetInstanceForTest(&var_tracker_);
+
+ plugin_dispatcher_.reset(new PluginDispatcher(
+ base::Process::Current().handle(),
+ &MockGetInterface));
+ plugin_dispatcher_->InitWithTestSink(&sink());
+ plugin_dispatcher_->DidCreateInstance(pp_instance());
+}
+
+void PluginProxyTestHarness::SetUpHarnessWithChannel(
+ const IPC::ChannelHandle& channel_handle,
+ base::MessageLoopProxy* ipc_message_loop,
+ base::WaitableEvent* shutdown_event,
+ bool is_client) {
+ // These must be first since the dispatcher set-up uses them.
+ PluginResourceTracker::SetInstanceForTest(&resource_tracker_);
+ PluginVarTracker::SetInstanceForTest(&var_tracker_);
+ plugin_delegate_mock_.Init(ipc_message_loop, shutdown_event);
+
+ plugin_dispatcher_.reset(new PluginDispatcher(
+ base::Process::Current().handle(),
+ &MockGetInterface));
+ plugin_dispatcher_->InitPluginWithChannel(&plugin_delegate_mock_,
+ channel_handle,
+ is_client);
+ plugin_dispatcher_->DidCreateInstance(pp_instance());
+}
+
+void PluginProxyTestHarness::TearDownHarness() {
+ plugin_dispatcher_->DidDestroyInstance(pp_instance());
+ plugin_dispatcher_.reset();
+
+ PluginVarTracker::SetInstanceForTest(NULL);
+ PluginResourceTracker::SetInstanceForTest(NULL);
+}
+
+base::MessageLoopProxy*
+PluginProxyTestHarness::PluginDelegateMock::GetIPCMessageLoop() {
+ return ipc_message_loop_;
+}
+
+base::WaitableEvent*
+PluginProxyTestHarness::PluginDelegateMock::GetShutdownEvent() {
+ return shutdown_event_;
+}
+
+std::set<PP_Instance>*
+PluginProxyTestHarness::PluginDelegateMock::GetGloballySeenInstanceIDSet() {
+ return &instance_id_set_;
+}
+
+ppapi::WebKitForwarding*
+PluginProxyTestHarness::PluginDelegateMock::GetWebKitForwarding() {
+ NOTREACHED();
+ return NULL;
+}
+
+void PluginProxyTestHarness::PluginDelegateMock::PostToWebKitThread(
+ const tracked_objects::Location& from_here, const base::Closure& task) {
+ NOTREACHED();
+}
+
+bool PluginProxyTestHarness::PluginDelegateMock::SendToBrowser(
+ IPC::Message* msg) {
+ NOTREACHED();
+ return false;
+}
+
+uint32 PluginProxyTestHarness::PluginDelegateMock::Register(
+ PluginDispatcher* plugin_dispatcher) {
+ return 0;
+}
+
+void PluginProxyTestHarness::PluginDelegateMock::Unregister(
+ uint32 plugin_dispatcher_id) {
+}
+
+// PluginProxyTest -------------------------------------------------------------
+
+PluginProxyTest::PluginProxyTest() {
+}
+
+PluginProxyTest::~PluginProxyTest() {
+}
+
+void PluginProxyTest::SetUp() {
+ SetUpHarness();
+}
+
+void PluginProxyTest::TearDown() {
+ TearDownHarness();
+}
+
+// HostProxyTestHarness --------------------------------------------------------
+
+HostProxyTestHarness::HostProxyTestHarness() {
+}
+
+HostProxyTestHarness::~HostProxyTestHarness() {
+}
+
+Dispatcher* HostProxyTestHarness::GetDispatcher() {
+ return host_dispatcher_.get();
+}
+
+void HostProxyTestHarness::SetUpHarness() {
+ host_dispatcher_.reset(new HostDispatcher(
+ base::Process::Current().handle(),
+ pp_module(),
+ &MockGetInterface));
+ host_dispatcher_->InitWithTestSink(&sink());
+ HostDispatcher::SetForInstance(pp_instance(), host_dispatcher_.get());
+}
+
+void HostProxyTestHarness::SetUpHarnessWithChannel(
+ const IPC::ChannelHandle& channel_handle,
+ base::MessageLoopProxy* ipc_message_loop,
+ base::WaitableEvent* shutdown_event,
+ bool is_client) {
+ delegate_mock_.Init(ipc_message_loop, shutdown_event);
+ host_dispatcher_.reset(new HostDispatcher(
+ base::Process::Current().handle(),
+ pp_module(),
+ &MockGetInterface));
+ ppapi::Preferences preferences;
+ host_dispatcher_->InitHostWithChannel(&delegate_mock_, channel_handle,
+ is_client, preferences);
+ HostDispatcher::SetForInstance(pp_instance(), host_dispatcher_.get());
+}
+
+void HostProxyTestHarness::TearDownHarness() {
+ HostDispatcher::RemoveForInstance(pp_instance());
+ host_dispatcher_.reset();
+}
+
+base::MessageLoopProxy*
+HostProxyTestHarness::DelegateMock::GetIPCMessageLoop() {
+ return ipc_message_loop_;
+}
+
+base::WaitableEvent* HostProxyTestHarness::DelegateMock::GetShutdownEvent() {
+ return shutdown_event_;
+}
+
+
+// HostProxyTest ---------------------------------------------------------------
+
+HostProxyTest::HostProxyTest() {
+}
+
+HostProxyTest::~HostProxyTest() {
+}
+
+void HostProxyTest::SetUp() {
+ SetUpHarness();
+}
+
+void HostProxyTest::TearDown() {
+ TearDownHarness();
+}
+
+// TwoWayTest ---------------------------------------------------------------
+
+TwoWayTest::TwoWayTest(TwoWayTest::TwoWayTestMode test_mode)
+ : test_mode_(test_mode),
+ io_thread_("TwoWayTest_IOThread"),
+ plugin_thread_("TwoWayTest_PluginThread"),
+ remote_harness_(NULL),
+ local_harness_(NULL),
+ channel_created_(true, false),
+ shutdown_event_(true, false) {
+ if (test_mode == TEST_PPP_INTERFACE) {
+ remote_harness_ = &plugin_;
+ local_harness_ = &host_;
+ } else {
+ remote_harness_ = &host_;
+ local_harness_ = &plugin_;
+ }
+}
+
+TwoWayTest::~TwoWayTest() {
+ shutdown_event_.Signal();
+}
+
+void TwoWayTest::SetUp() {
+ base::Thread::Options options;
+ options.message_loop_type = MessageLoop::TYPE_IO;
+ io_thread_.StartWithOptions(options);
+ plugin_thread_.Start();
+
+ IPC::ChannelHandle handle;
+ handle.name = "TwoWayTestChannel";
+
+ base::WaitableEvent remote_harness_set_up(true, false);
+ plugin_thread_.message_loop_proxy()->PostTask(
+ FROM_HERE,
+ NewRunnableFunction(&SetUpRemoteHarness,
+ remote_harness_,
+ handle,
+ io_thread_.message_loop_proxy(),
+ &shutdown_event_,
+ &remote_harness_set_up));
+ remote_harness_set_up.Wait();
+ local_harness_->SetUpHarnessWithChannel(handle,
+ io_thread_.message_loop_proxy(),
+ &shutdown_event_,
+ true); // is_client
+}
+
+void TwoWayTest::TearDown() {
+ base::WaitableEvent remote_harness_torn_down(true, false);
+ plugin_thread_.message_loop_proxy()->PostTask(
+ FROM_HERE,
+ NewRunnableFunction(&TearDownRemoteHarness,
+ remote_harness_,
+ &remote_harness_torn_down));
+ remote_harness_torn_down.Wait();
+
+ local_harness_->TearDownHarness();
+
+ io_thread_.Stop();
+}
+
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppapi_proxy_test.h b/ppapi/proxy/ppapi_proxy_test.h
new file mode 100644
index 0000000..775b75c
--- /dev/null
+++ b/ppapi/proxy/ppapi_proxy_test.h
@@ -0,0 +1,243 @@
+// 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 <map>
+#include <string>
+
+#include "base/message_loop.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "ipc/ipc_test_sink.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace pp {
+namespace proxy {
+
+// Base class for plugin and host test harnesses. Tests will not use this
+// directly. Instead, use the PluginProxyTest, HostProxyTest, or TwoWayTest.
+class ProxyTestHarnessBase {
+ public:
+ ProxyTestHarnessBase();
+ virtual ~ProxyTestHarnessBase();
+
+ PP_Module pp_module() const { return pp_module_; }
+ PP_Instance pp_instance() const { return pp_instance_; }
+ IPC::TestSink& sink() { return sink_; }
+
+ // Returns either the plugin or host dispatcher, depending on the test.
+ virtual Dispatcher* GetDispatcher() = 0;
+
+ // Set up the harness using an IPC::TestSink to capture messages.
+ virtual void SetUpHarness() = 0;
+
+ // Set up the harness using a real IPC channel.
+ virtual void SetUpHarnessWithChannel(const IPC::ChannelHandle& channel_handle,
+ base::MessageLoopProxy* ipc_message_loop,
+ base::WaitableEvent* shutdown_event,
+ bool is_client) = 0;
+
+ virtual void TearDownHarness() = 0;
+
+ // Implementation of GetInterface for the dispatcher. This will
+ // return NULL for all interfaces unless one is registered by calling
+ // RegisterTestInterface();
+ const void* GetInterface(const char* name);
+
+ // Allows the test to specify an interface implementation for a given
+ // interface name. This will be returned when any of the proxy logic
+ // requests a local interface.
+ void RegisterTestInterface(const char* name, const void* interface);
+
+ // Sends a "supports interface" message to the current dispatcher and returns
+ // true if it's supported. This is just for the convenience of tests.
+ bool SupportsInterface(const char* name);
+
+ private:
+ // Destination for IPC messages sent by the test.
+ IPC::TestSink sink_;
+
+ // The module and instance ID associated with the plugin dispatcher.
+ PP_Module pp_module_;
+ PP_Instance pp_instance_;
+
+ // Stores the data for GetInterface/RegisterTestInterface.
+ std::map<std::string, const void*> registered_interfaces_;
+};
+
+// Test harness for the plugin side of the proxy.
+class PluginProxyTestHarness : public ProxyTestHarnessBase {
+ public:
+ PluginProxyTestHarness();
+ virtual ~PluginProxyTestHarness();
+
+ PluginDispatcher* plugin_dispatcher() { return plugin_dispatcher_.get(); }
+ PluginResourceTracker& resource_tracker() { return resource_tracker_; }
+ PluginVarTracker& var_tracker() { return var_tracker_; }
+
+ // ProxyTestHarnessBase implementation.
+ virtual Dispatcher* GetDispatcher();
+ virtual void SetUpHarness();
+ virtual void SetUpHarnessWithChannel(const IPC::ChannelHandle& channel_handle,
+ base::MessageLoopProxy* ipc_message_loop,
+ base::WaitableEvent* shutdown_event,
+ bool is_client);
+ virtual void TearDownHarness();
+
+ class PluginDelegateMock : public PluginDispatcher::PluginDelegate {
+ public:
+ PluginDelegateMock() : ipc_message_loop_(NULL), shutdown_event_() {}
+ virtual ~PluginDelegateMock() {}
+
+ void Init(base::MessageLoopProxy* ipc_message_loop,
+ base::WaitableEvent* shutdown_event) {
+ ipc_message_loop_ = ipc_message_loop;
+ shutdown_event_ = shutdown_event;
+ }
+
+ // ProxyChannel::Delegate implementation.
+ virtual base::MessageLoopProxy* GetIPCMessageLoop();
+ virtual base::WaitableEvent* GetShutdownEvent();
+
+ // PluginDispatcher::PluginDelegate implementation.
+ virtual std::set<PP_Instance>* GetGloballySeenInstanceIDSet();
+ virtual ppapi::WebKitForwarding* GetWebKitForwarding();
+ virtual void PostToWebKitThread(const tracked_objects::Location& from_here,
+ const base::Closure& task);
+ virtual bool SendToBrowser(IPC::Message* msg);
+ virtual uint32 Register(PluginDispatcher* plugin_dispatcher);
+ virtual void Unregister(uint32 plugin_dispatcher_id);
+
+ private:
+ base::MessageLoopProxy* ipc_message_loop_; // Weak
+ base::WaitableEvent* shutdown_event_; // Weak
+ std::set<PP_Instance> instance_id_set_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginDelegateMock);
+ };
+
+ private:
+ PluginResourceTracker resource_tracker_;
+ PluginVarTracker var_tracker_;
+ scoped_ptr<PluginDispatcher> plugin_dispatcher_;
+ PluginDelegateMock plugin_delegate_mock_;
+};
+
+class PluginProxyTest : public PluginProxyTestHarness, public testing::Test {
+ public:
+ PluginProxyTest();
+ virtual ~PluginProxyTest();
+
+ // testing::Test implementation.
+ virtual void SetUp();
+ virtual void TearDown();
+ private:
+ MessageLoop message_loop_;
+};
+
+class HostProxyTestHarness : public ProxyTestHarnessBase {
+ public:
+ HostProxyTestHarness();
+ virtual ~HostProxyTestHarness();
+
+ HostDispatcher* host_dispatcher() { return host_dispatcher_.get(); }
+
+ // ProxyTestBase implementation.
+ virtual Dispatcher* GetDispatcher();
+ virtual void SetUpHarness();
+ virtual void SetUpHarnessWithChannel(const IPC::ChannelHandle& channel_handle,
+ base::MessageLoopProxy* ipc_message_loop,
+ base::WaitableEvent* shutdown_event,
+ bool is_client);
+ virtual void TearDownHarness();
+
+ class DelegateMock : public ProxyChannel::Delegate {
+ public:
+ DelegateMock() : ipc_message_loop_(NULL), shutdown_event_(NULL) {
+ }
+ virtual ~DelegateMock() {}
+
+ void Init(base::MessageLoopProxy* ipc_message_loop,
+ base::WaitableEvent* shutdown_event) {
+ ipc_message_loop_ = ipc_message_loop;
+ shutdown_event_ = shutdown_event;
+ }
+
+ // ProxyChannel::Delegate implementation.
+ virtual base::MessageLoopProxy* GetIPCMessageLoop();
+ virtual base::WaitableEvent* GetShutdownEvent();
+
+ private:
+ base::MessageLoopProxy* ipc_message_loop_; // Weak
+ base::WaitableEvent* shutdown_event_; // Weak
+
+ DISALLOW_COPY_AND_ASSIGN(DelegateMock);
+ };
+
+ private:
+ scoped_ptr<HostDispatcher> host_dispatcher_;
+ DelegateMock delegate_mock_;
+};
+
+class HostProxyTest : public HostProxyTestHarness, public testing::Test {
+ public:
+ HostProxyTest();
+ virtual ~HostProxyTest();
+
+ // testing::Test implementation.
+ virtual void SetUp();
+ virtual void TearDown();
+ private:
+ MessageLoop message_loop_;
+};
+
+// Use this base class to test both sides of a proxy.
+class TwoWayTest : public testing::Test {
+ public:
+ enum TwoWayTestMode {
+ TEST_PPP_INTERFACE,
+ TEST_PPB_INTERFACE
+ };
+ TwoWayTest(TwoWayTestMode test_mode);
+ virtual ~TwoWayTest();
+
+ HostProxyTestHarness& host() { return host_; }
+ PluginProxyTestHarness& plugin() { return plugin_; }
+ PP_Module pp_module() const { return host_.pp_module(); }
+ PP_Instance pp_instance() const { return host_.pp_instance(); }
+ TwoWayTestMode test_mode() { return test_mode_; }
+
+ // testing::Test implementation.
+ virtual void SetUp();
+ virtual void TearDown();
+
+ private:
+ TwoWayTestMode test_mode_;
+ HostProxyTestHarness host_;
+ PluginProxyTestHarness plugin_;
+ // In order to use sync IPC, we need to have an IO thread.
+ base::Thread io_thread_;
+ // The plugin side of the proxy runs on its own thread.
+ base::Thread plugin_thread_;
+ // The message loop for the main (host) thread.
+ MessageLoop message_loop_;
+
+ // Aliases for the host and plugin harnesses; if we're testing a PPP
+ // interface, remote_harness will point to plugin_, and local_harness
+ // will point to host_. This makes it convenient when we're starting and
+ // stopping the harnesses.
+ ProxyTestHarnessBase* remote_harness_;
+ ProxyTestHarnessBase* local_harness_;
+
+ base::WaitableEvent channel_created_;
+ base::WaitableEvent shutdown_event_;
+};
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_audio_config_proxy.cc b/ppapi/proxy/ppb_audio_config_proxy.cc
new file mode 100644
index 0000000..e8eb056
--- /dev/null
+++ b/ppapi/proxy/ppb_audio_config_proxy.cc
@@ -0,0 +1,91 @@
+// 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_audio_config_proxy.h"
+
+#include "ppapi/c/ppb_audio_config.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/audio_config_impl.h"
+#include "ppapi/thunk/thunk.h"
+
+namespace pp {
+namespace proxy {
+
+// The implementation is actually in AudioConfigImpl.
+class AudioConfig : public PluginResource,
+ public ppapi::AudioConfigImpl {
+ public:
+ // Note that you must call Init (on AudioConfigImpl) before using this class.
+ AudioConfig(const HostResource& resource);
+ virtual ~AudioConfig();
+
+ // ResourceObjectBase overrides.
+ virtual ::ppapi::thunk::PPB_AudioConfig_API* AsPPB_AudioConfig_API() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AudioConfig);
+};
+
+AudioConfig::AudioConfig(const HostResource& resource)
+ : PluginResource(resource) {
+}
+
+AudioConfig::~AudioConfig() {
+}
+
+::ppapi::thunk::PPB_AudioConfig_API* AudioConfig::AsPPB_AudioConfig_API() {
+ return this;
+}
+
+namespace {
+
+InterfaceProxy* CreateAudioConfigProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_AudioConfig_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_AudioConfig_Proxy::PPB_AudioConfig_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_AudioConfig_Proxy::~PPB_AudioConfig_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_AudioConfig_Proxy::GetInfo() {
+ static const Info info = {
+ ::ppapi::thunk::GetPPB_AudioConfig_Thunk(),
+ PPB_AUDIO_CONFIG_INTERFACE,
+ INTERFACE_ID_PPB_AUDIO_CONFIG,
+ false,
+ &CreateAudioConfigProxy,
+ };
+ return &info;
+}
+
+// static
+PP_Resource PPB_AudioConfig_Proxy::CreateProxyResource(
+ PP_Instance instance,
+ PP_AudioSampleRate sample_rate,
+ uint32_t sample_frame_count) {
+ linked_ptr<AudioConfig> object(new AudioConfig(
+ HostResource::MakeInstanceOnly(instance)));
+ if (!object->Init(sample_rate, sample_frame_count))
+ return 0;
+ return PluginResourceTracker::GetInstance()->AddResource(object);
+}
+
+bool PPB_AudioConfig_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ // There are no IPC messages for this interface.
+ NOTREACHED();
+ return false;
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_audio_config_proxy.h b/ppapi/proxy/ppb_audio_config_proxy.h
new file mode 100644
index 0000000..e8a12e8
--- /dev/null
+++ b/ppapi/proxy/ppb_audio_config_proxy.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2010 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_AUDIO_CONFIG_PROXY_H_
+#define PPAPI_PROXY_PPB_AUDIO_CONFIG_PROXY_H_
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/ppb_audio_config.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_AudioConfig;
+
+namespace pp {
+namespace proxy {
+
+class HostResource;
+
+class PPB_AudioConfig_Proxy : public InterfaceProxy {
+ public:
+ PPB_AudioConfig_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_AudioConfig_Proxy();
+
+ static const Info* GetInfo();
+
+ static PP_Resource CreateProxyResource(PP_Instance instance,
+ PP_AudioSampleRate sample_rate,
+ uint32_t sample_frame_count);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PPB_AudioConfig_Proxy);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_AUDIO_CONFIG_PROXY_H_
diff --git a/ppapi/proxy/ppb_audio_proxy.cc b/ppapi/proxy/ppb_audio_proxy.cc
new file mode 100644
index 0000000..76f3046
--- /dev/null
+++ b/ppapi/proxy/ppb_audio_proxy.cc
@@ -0,0 +1,318 @@
+// 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_audio_proxy.h"
+
+#include "base/threading/simple_thread.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_audio.h"
+#include "ppapi/c/ppb_audio_config.h"
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/c/trusted/ppb_audio_trusted.h"
+#include "ppapi/proxy/enter_proxy.h"
+#include "ppapi/proxy/interface_id.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/audio_impl.h"
+#include "ppapi/thunk/ppb_audio_config_api.h"
+#include "ppapi/thunk/ppb_audio_trusted_api.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/resource_creation_api.h"
+#include "ppapi/thunk/thunk.h"
+
+using ::ppapi::thunk::PPB_Audio_API;
+
+namespace pp {
+namespace proxy {
+
+class Audio : public PluginResource, public ppapi::AudioImpl {
+ public:
+ Audio(const HostResource& audio_id,
+ PP_Resource config_id,
+ PPB_Audio_Callback callback,
+ void* user_data);
+ virtual ~Audio();
+
+ // ResourceObjectBase overrides.
+ virtual PPB_Audio_API* AsPPB_Audio_API();
+
+ // PPB_Audio_API implementation.
+ virtual PP_Resource GetCurrentConfig() OVERRIDE;
+ virtual PP_Bool StartPlayback() OVERRIDE;
+ virtual PP_Bool StopPlayback() OVERRIDE;
+
+ private:
+ // Owning reference to the current config object. This isn't actually used,
+ // we just dish it out as requested by the plugin.
+ PP_Resource config_;
+
+ DISALLOW_COPY_AND_ASSIGN(Audio);
+};
+
+Audio::Audio(const HostResource& audio_id,
+ PP_Resource config_id,
+ PPB_Audio_Callback callback,
+ void* user_data)
+ : PluginResource(audio_id),
+ config_(config_id) {
+ SetCallback(callback, user_data);
+ PluginResourceTracker::GetInstance()->AddRefResource(config_);
+}
+
+Audio::~Audio() {
+ PluginResourceTracker::GetInstance()->ReleaseResource(config_);
+}
+
+PPB_Audio_API* Audio::AsPPB_Audio_API() {
+ return this;
+}
+
+PP_Resource Audio::GetCurrentConfig() {
+ // AddRef for the caller.
+ PluginResourceTracker::GetInstance()->AddRefResource(config_);
+ return config_;
+}
+
+PP_Bool Audio::StartPlayback() {
+ if (playing())
+ return PP_TRUE;
+ SetStartPlaybackState();
+ PluginDispatcher::GetForInstance(instance())->Send(
+ new PpapiHostMsg_PPBAudio_StartOrStop(
+ INTERFACE_ID_PPB_AUDIO, host_resource(), true));
+ return PP_TRUE;
+}
+
+PP_Bool Audio::StopPlayback() {
+ if (!playing())
+ return PP_TRUE;
+ PluginDispatcher::GetForInstance(instance())->Send(
+ new PpapiHostMsg_PPBAudio_StartOrStop(
+ INTERFACE_ID_PPB_AUDIO, host_resource(), false));
+ SetStopPlaybackState();
+ return PP_TRUE;
+}
+
+namespace {
+
+InterfaceProxy* CreateAudioProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Audio_Proxy(dispatcher, target_interface);
+}
+
+base::PlatformFile IntToPlatformFile(int32_t handle) {
+ // TODO(piman/brettw): Change trusted interface to return a PP_FileHandle,
+ // those casts are ugly.
+#if defined(OS_WIN)
+ return reinterpret_cast<HANDLE>(static_cast<intptr_t>(handle));
+#elif defined(OS_POSIX)
+ return handle;
+#else
+ #error Not implemented.
+#endif
+}
+
+} // namespace
+
+PPB_Audio_Proxy::PPB_Audio_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface),
+ callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+}
+
+PPB_Audio_Proxy::~PPB_Audio_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Audio_Proxy::GetInfo() {
+ static const Info info = {
+ ppapi::thunk::GetPPB_Audio_Thunk(),
+ PPB_AUDIO_INTERFACE,
+ INTERFACE_ID_PPB_AUDIO,
+ false,
+ &CreateAudioProxy,
+ };
+ return &info;
+}
+
+// static
+PP_Resource PPB_Audio_Proxy::CreateProxyResource(
+ PP_Instance instance_id,
+ PP_Resource config_id,
+ PPB_Audio_Callback audio_callback,
+ void* user_data) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id);
+ if (!dispatcher)
+ return 0;
+
+ ::ppapi::thunk::EnterResourceNoLock< ::ppapi::thunk::PPB_AudioConfig_API>
+ config(config_id, true);
+ if (config.failed())
+ return 0;
+
+ HostResource result;
+ dispatcher->Send(new PpapiHostMsg_PPBAudio_Create(
+ INTERFACE_ID_PPB_AUDIO, instance_id,
+ config.object()->GetSampleRate(), config.object()->GetSampleFrameCount(),
+ &result));
+ if (result.is_null())
+ return 0;
+
+ linked_ptr<Audio> object(new Audio(result, config_id,
+ audio_callback, user_data));
+ return PluginResourceTracker::GetInstance()->AddResource(object);
+}
+
+bool PPB_Audio_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Audio_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBAudio_Create, OnMsgCreate)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBAudio_StartOrStop,
+ OnMsgStartOrStop)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBAudio_NotifyAudioStreamCreated,
+ OnMsgNotifyAudioStreamCreated)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPB_Audio_Proxy::OnMsgCreate(PP_Instance instance_id,
+ int32_t sample_rate,
+ uint32_t sample_frame_count,
+ HostResource* result) {
+ ::ppapi::thunk::EnterFunction< ::ppapi::thunk::ResourceCreationAPI>
+ resource_creation(instance_id, true);
+ if (resource_creation.failed())
+ return;
+
+ // Make the resource and get the API pointer to its trusted interface.
+ result->SetHostResource(
+ instance_id,
+ resource_creation.functions()->CreateAudioTrusted(instance_id));
+ if (result->is_null())
+ return;
+ ::ppapi::thunk::EnterResourceNoLock< ::ppapi::thunk::PPB_AudioTrusted_API>
+ trusted_audio(result->host_resource(), false);
+ if (trusted_audio.failed())
+ return;
+
+ // Make an audio config object.
+ PP_Resource audio_config_res =
+ resource_creation.functions()->CreateAudioConfig(
+ instance_id, static_cast<PP_AudioSampleRate>(sample_rate),
+ sample_frame_count);
+ if (!audio_config_res)
+ return;
+
+ // Initiate opening the audio object.
+ CompletionCallback callback = callback_factory_.NewOptionalCallback(
+ &PPB_Audio_Proxy::AudioChannelConnected, *result);
+ int32_t open_error = trusted_audio.object()->OpenTrusted(
+ audio_config_res, callback.pp_completion_callback());
+ if (open_error != PP_OK_COMPLETIONPENDING)
+ callback.Run(open_error);
+
+ // Clean up the temporary audio config resource we made.
+ const PPB_Core* core = static_cast<const PPB_Core*>(
+ dispatcher()->GetLocalInterface(PPB_CORE_INTERFACE));
+ core->ReleaseResource(audio_config_res);
+}
+
+void PPB_Audio_Proxy::OnMsgStartOrStop(const HostResource& audio_id,
+ bool play) {
+ if (play)
+ ppb_audio_target()->StartPlayback(audio_id.host_resource());
+ else
+ ppb_audio_target()->StopPlayback(audio_id.host_resource());
+}
+
+// Processed in the plugin (message from host).
+void PPB_Audio_Proxy::OnMsgNotifyAudioStreamCreated(
+ const HostResource& audio_id,
+ int32_t result_code,
+ IPC::PlatformFileForTransit socket_handle,
+ base::SharedMemoryHandle handle,
+ uint32_t length) {
+ EnterPluginFromHostResource<PPB_Audio_API> enter(audio_id);
+ if (enter.failed() || result_code != PP_OK) {
+ // The caller may still have given us these handles in the failure case.
+ // The easiest way to clean these up is to just put them in the objects
+ // and then close them. This failure case is not performance critical.
+ base::SyncSocket temp_socket(
+ IPC::PlatformFileForTransitToPlatformFile(socket_handle));
+ base::SharedMemory temp_mem(handle, false);
+ } else {
+ static_cast<Audio*>(enter.object())->SetStreamInfo(
+ handle, length,
+ IPC::PlatformFileForTransitToPlatformFile(socket_handle));
+ }
+}
+
+void PPB_Audio_Proxy::AudioChannelConnected(
+ int32_t result,
+ const HostResource& resource) {
+ IPC::PlatformFileForTransit socket_handle =
+ IPC::InvalidPlatformFileForTransit();
+ base::SharedMemoryHandle shared_memory = IPC::InvalidPlatformFileForTransit();
+ uint32_t shared_memory_length = 0;
+
+ int32_t result_code = result;
+ if (result_code == PP_OK) {
+ result_code = GetAudioConnectedHandles(resource, &socket_handle,
+ &shared_memory,
+ &shared_memory_length);
+ }
+
+ // Send all the values, even on error. This simplifies some of our cleanup
+ // code since the handles will be in the other process and could be
+ // inconvenient to clean up. Our IPC code will automatically handle this for
+ // us, as long as the remote side always closes the handles it receives
+ // (in OnMsgNotifyAudioStreamCreated), even in the failure case.
+ dispatcher()->Send(new PpapiMsg_PPBAudio_NotifyAudioStreamCreated(
+ INTERFACE_ID_PPB_AUDIO, resource, result_code, socket_handle,
+ shared_memory, shared_memory_length));
+}
+
+int32_t PPB_Audio_Proxy::GetAudioConnectedHandles(
+ const HostResource& resource,
+ IPC::PlatformFileForTransit* foreign_socket_handle,
+ base::SharedMemoryHandle* foreign_shared_memory_handle,
+ uint32_t* shared_memory_length) {
+ // Get the trusted audio interface which will give us the handles.
+ ::ppapi::thunk::EnterResourceNoLock< ::ppapi::thunk::PPB_AudioTrusted_API>
+ trusted_audio(resource.host_resource(), false);
+ if (trusted_audio.failed())
+ return PP_ERROR_NOINTERFACE;
+
+ // Get the socket handle for signaling.
+ int32_t socket_handle;
+ int32_t result = trusted_audio.object()->GetSyncSocket(&socket_handle);
+ if (result != PP_OK)
+ return result;
+
+ // socket_handle doesn't belong to us: don't close it.
+ *foreign_socket_handle = dispatcher()->ShareHandleWithRemote(
+ IntToPlatformFile(socket_handle), false);
+ if (*foreign_socket_handle == IPC::InvalidPlatformFileForTransit())
+ return PP_ERROR_FAILED;
+
+ // Get the shared memory for the buffer.
+ int shared_memory_handle;
+ result = trusted_audio.object()->GetSharedMemory(&shared_memory_handle,
+ shared_memory_length);
+ if (result != PP_OK)
+ return result;
+
+ // shared_memory_handle doesn't belong to us: don't close it.
+ *foreign_shared_memory_handle = dispatcher()->ShareHandleWithRemote(
+ IntToPlatformFile(shared_memory_handle), false);
+ if (*foreign_shared_memory_handle == IPC::InvalidPlatformFileForTransit())
+ return PP_ERROR_FAILED;
+
+ return PP_OK;
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_audio_proxy.h b/ppapi/proxy/ppb_audio_proxy.h
new file mode 100644
index 0000000..e39a82d
--- /dev/null
+++ b/ppapi/proxy/ppb_audio_proxy.h
@@ -0,0 +1,92 @@
+// 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_AUDIO_PROXY_H_
+#define PPAPI_PROXY_PPB_AUDIO_PROXY_H_
+
+#include <utility>
+
+#include "base/basictypes.h"
+#include "base/shared_memory.h"
+#include "base/sync_socket.h"
+#include "ipc/ipc_platform_file.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/ppb_audio.h"
+#include "ppapi/c/ppb_audio_config.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_Audio;
+
+namespace pp {
+namespace proxy {
+
+class HostResource;
+
+class PPB_Audio_Proxy : public InterfaceProxy {
+ public:
+ PPB_Audio_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_Audio_Proxy();
+
+ static const Info* GetInfo();
+
+ // Creates an Audio object in the plugin process.
+ static PP_Resource CreateProxyResource(PP_Instance instance_id,
+ PP_Resource config_id,
+ PPB_Audio_Callback audio_callback,
+ void* user_data);
+
+
+ const PPB_Audio* ppb_audio_target() const {
+ return static_cast<const PPB_Audio*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Plugin->renderer message handlers.
+ void OnMsgCreate(PP_Instance instance_id,
+ int32_t sample_rate,
+ uint32_t sample_frame_count,
+ HostResource* result);
+ void OnMsgStartOrStop(const HostResource& audio_id, bool play);
+
+ // Renderer->plugin message handlers.
+ void OnMsgNotifyAudioStreamCreated(const HostResource& audio_id,
+ int32_t result_code,
+ IPC::PlatformFileForTransit socket_handle,
+ base::SharedMemoryHandle handle,
+ uint32_t length);
+
+ void AudioChannelConnected(int32_t result,
+ const HostResource& resource);
+
+ // In the renderer, this is called in response to a stream created message.
+ // It will retrieve the shared memory and socket handles and place them into
+ // the given out params. The return value is a PPAPI error code.
+ //
+ // The input arguments should be initialized to 0 or -1, depending on the
+ // platform's default invalid handle values. On error, some of these
+ // arguments may be written to, and others may be untouched, depending on
+ // where the error occurred.
+ int32_t GetAudioConnectedHandles(
+ const HostResource& resource,
+ IPC::PlatformFileForTransit* foreign_socket_handle,
+ base::SharedMemoryHandle* foreign_shared_memory_handle,
+ uint32_t* shared_memory_length);
+
+ CompletionCallbackFactory<PPB_Audio_Proxy,
+ ProxyNonThreadSafeRefCount> callback_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_Audio_Proxy);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_AUDIO_PROXY_H_
diff --git a/ppapi/proxy/ppb_broker_proxy.cc b/ppapi/proxy/ppb_broker_proxy.cc
new file mode 100644
index 0000000..37f8ba0
--- /dev/null
+++ b/ppapi/proxy/ppb_broker_proxy.cc
@@ -0,0 +1,281 @@
+// 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_broker_proxy.h"
+
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/trusted/ppb_broker_trusted.h"
+#include "ppapi/proxy/enter_proxy.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/thunk/ppb_broker_api.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/thunk.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+base::PlatformFile IntToPlatformFile(int32_t handle) {
+#if defined(OS_WIN)
+ return reinterpret_cast<HANDLE>(static_cast<intptr_t>(handle));
+#elif defined(OS_POSIX)
+ return handle;
+#else
+ #error Not implemented.
+#endif
+}
+
+int32_t PlatformFileToInt(base::PlatformFile handle) {
+#if defined(OS_WIN)
+ return static_cast<int32_t>(reinterpret_cast<intptr_t>(handle));
+#elif defined(OS_POSIX)
+ return handle;
+#else
+ #error Not implemented.
+#endif
+}
+
+InterfaceProxy* CreateBrokerProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Broker_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+class Broker : public ppapi::thunk::PPB_Broker_API,
+ public PluginResource {
+ public:
+ explicit Broker(const HostResource& resource);
+ virtual ~Broker();
+
+ // ResourceObjectBase overries.
+ virtual ppapi::thunk::PPB_Broker_API* AsPPB_Broker_API() OVERRIDE;
+
+ // PPB_Broker_API implementation.
+ virtual int32_t Connect(PP_CompletionCallback connect_callback) OVERRIDE;
+ virtual int32_t GetHandle(int32_t* handle) OVERRIDE;
+
+ // Called by the proxy when the host side has completed the request.
+ void ConnectComplete(IPC::PlatformFileForTransit socket_handle,
+ int32_t result);
+
+ private:
+ bool called_connect_;
+ PP_CompletionCallback current_connect_callback_;
+
+ // The plugin module owns the handle.
+ // The host side transfers ownership of the handle to the plugin side when it
+ // sends the IPC. This member holds the handle value for the plugin module
+ // to read, but the plugin side of the proxy never takes ownership.
+ base::SyncSocket::Handle socket_handle_;
+
+ DISALLOW_COPY_AND_ASSIGN(Broker);
+};
+
+Broker::Broker(const HostResource& resource)
+ : PluginResource(resource),
+ called_connect_(false),
+ current_connect_callback_(PP_MakeCompletionCallback(NULL, NULL)),
+ socket_handle_(base::kInvalidPlatformFileValue) {
+}
+
+Broker::~Broker() {
+ // Ensure the callback is always fired.
+ if (current_connect_callback_.func) {
+ // TODO(brettw) the callbacks at this level should be refactored with a
+ // more automatic tracking system like we have in the renderer.
+ MessageLoop::current()->PostTask(FROM_HERE, NewRunnableFunction(
+ current_connect_callback_.func, current_connect_callback_.user_data,
+ static_cast<int32_t>(PP_ERROR_ABORTED)));
+ }
+
+ socket_handle_ = base::kInvalidPlatformFileValue;
+}
+
+ppapi::thunk::PPB_Broker_API* Broker::AsPPB_Broker_API() {
+ return this;
+}
+
+int32_t Broker::Connect(PP_CompletionCallback connect_callback) {
+ if (!connect_callback.func) {
+ // Synchronous calls are not supported.
+ return PP_ERROR_BADARGUMENT;
+ }
+
+ if (current_connect_callback_.func)
+ return PP_ERROR_INPROGRESS;
+ else if (called_connect_)
+ return PP_ERROR_FAILED;
+
+ current_connect_callback_ = connect_callback;
+ called_connect_ = true;
+
+ bool success = GetDispatcher()->Send(new PpapiHostMsg_PPBBroker_Connect(
+ INTERFACE_ID_PPB_BROKER, host_resource()));
+ return success ? PP_OK_COMPLETIONPENDING : PP_ERROR_FAILED;
+}
+
+int32_t Broker::GetHandle(int32_t* handle) {
+ if (socket_handle_ == base::kInvalidPlatformFileValue)
+ return PP_ERROR_FAILED;
+ *handle = PlatformFileToInt(socket_handle_);
+ return PP_OK;
+}
+
+void Broker::ConnectComplete(IPC::PlatformFileForTransit socket_handle,
+ int32_t result) {
+ if (result == PP_OK) {
+ DCHECK(socket_handle_ == base::kInvalidPlatformFileValue);
+ socket_handle_ = IPC::PlatformFileForTransitToPlatformFile(socket_handle);
+ } else {
+ // The caller may still have given us a handle in the failure case.
+ // The easiest way to clean it up is to just put it in an object
+ // and then close them. This failure case is not performance critical.
+ base::SyncSocket temp_socket(
+ IPC::PlatformFileForTransitToPlatformFile(socket_handle));
+ }
+
+ if (!current_connect_callback_.func) {
+ // The handle might leak if the plugin never calls GetHandle().
+ return;
+ }
+
+ PP_RunAndClearCompletionCallback(&current_connect_callback_, result);
+}
+
+PPB_Broker_Proxy::PPB_Broker_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) ,
+ callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)){
+}
+
+PPB_Broker_Proxy::~PPB_Broker_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Broker_Proxy::GetInfo() {
+ static const Info info = {
+ ppapi::thunk::GetPPB_Broker_Thunk(),
+ PPB_BROKER_TRUSTED_INTERFACE,
+ INTERFACE_ID_PPB_BROKER,
+ true,
+ &CreateBrokerProxy,
+ };
+ return &info;
+}
+
+// static
+PP_Resource PPB_Broker_Proxy::CreateProxyResource(PP_Instance instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+
+ HostResource result;
+ dispatcher->Send(new PpapiHostMsg_PPBBroker_Create(
+ INTERFACE_ID_PPB_BROKER, instance, &result));
+ if (result.is_null())
+ return 0;
+
+ linked_ptr<Broker> object(new Broker(result));
+ return PluginResourceTracker::GetInstance()->AddResource(object);
+}
+
+bool PPB_Broker_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Broker_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBBroker_Create, OnMsgCreate)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBBroker_Connect, OnMsgConnect)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBBroker_ConnectComplete,
+ OnMsgConnectComplete)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPB_Broker_Proxy::OnMsgCreate(PP_Instance instance,
+ HostResource* result_resource) {
+ result_resource->SetHostResource(
+ instance,
+ ppb_broker_target()->CreateTrusted(instance));
+}
+
+void PPB_Broker_Proxy::OnMsgConnect(const HostResource& broker) {
+ CompletionCallback callback = callback_factory_.NewOptionalCallback(
+ &PPB_Broker_Proxy::ConnectCompleteInHost, broker);
+
+ int32_t result = ppb_broker_target()->Connect(
+ broker.host_resource(),
+ callback.pp_completion_callback());
+ if (result != PP_OK_COMPLETIONPENDING)
+ callback.Run(result);
+}
+
+// Called in the plugin to handle the connect callback.
+// The proxy owns the handle and transfers it to the Broker. At that point,
+// the plugin owns the handle and is responsible for closing it.
+// The caller guarantees that socket_handle is not valid if result is not PP_OK.
+void PPB_Broker_Proxy::OnMsgConnectComplete(
+ const HostResource& resource,
+ IPC::PlatformFileForTransit socket_handle,
+ int32_t result) {
+ DCHECK(result == PP_OK ||
+ socket_handle == IPC::InvalidPlatformFileForTransit());
+
+ EnterPluginFromHostResource<ppapi::thunk::PPB_Broker_API> enter(resource);
+ if (enter.failed()) {
+ // As in Broker::ConnectComplete, we need to close the resource on error.
+ base::SyncSocket temp_socket(
+ IPC::PlatformFileForTransitToPlatformFile(socket_handle));
+ } else {
+ static_cast<Broker*>(enter.object())->ConnectComplete(socket_handle,
+ result);
+ }
+}
+
+// Callback on the host side.
+// Transfers ownership of the handle to the plugin side. This function must
+// either successfully call the callback or close the handle.
+void PPB_Broker_Proxy::ConnectCompleteInHost(int32_t result,
+ const HostResource& broker) {
+ IPC::PlatformFileForTransit foreign_socket_handle =
+ IPC::InvalidPlatformFileForTransit();
+ if (result == PP_OK) {
+ int32_t socket_handle = PlatformFileToInt(base::kInvalidPlatformFileValue);
+ result = ppb_broker_target()->GetHandle(broker.host_resource(),
+ &socket_handle);
+ DCHECK(result == PP_OK ||
+ socket_handle == PlatformFileToInt(base::kInvalidPlatformFileValue));
+
+ if (result == PP_OK) {
+ foreign_socket_handle =
+ dispatcher()->ShareHandleWithRemote(IntToPlatformFile(socket_handle),
+ true);
+ if (foreign_socket_handle == IPC::InvalidPlatformFileForTransit()) {
+ result = PP_ERROR_FAILED;
+ // Assume the local handle was closed even if the foreign handle could
+ // not be created.
+ }
+ }
+ }
+ DCHECK(result == PP_OK ||
+ foreign_socket_handle == IPC::InvalidPlatformFileForTransit());
+
+ bool success = dispatcher()->Send(new PpapiMsg_PPBBroker_ConnectComplete(
+ INTERFACE_ID_PPB_BROKER, broker, foreign_socket_handle, result));
+
+ if (!success || result != PP_OK) {
+ // The plugin did not receive the handle, so it must be closed.
+ // The easiest way to clean it up is to just put it in an object
+ // and then close it. This failure case is not performance critical.
+ // The handle could still leak if Send succeeded but the IPC later failed.
+ base::SyncSocket temp_socket(
+ IPC::PlatformFileForTransitToPlatformFile(foreign_socket_handle));
+ }
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_broker_proxy.h b/ppapi/proxy/ppb_broker_proxy.h
new file mode 100644
index 0000000..efa9a98
--- /dev/null
+++ b/ppapi/proxy/ppb_broker_proxy.h
@@ -0,0 +1,56 @@
+// 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_PPB_BROKER_PROXY_H_
+#define PPAPI_PPB_BROKER_PROXY_H_
+
+#include "base/sync_socket.h"
+#include "ipc/ipc_platform_file.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_BrokerTrusted;
+
+namespace pp {
+namespace proxy {
+
+class HostResource;
+
+class PPB_Broker_Proxy : public InterfaceProxy {
+ public:
+ PPB_Broker_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_Broker_Proxy();
+
+ static const Info* GetInfo();
+
+ static PP_Resource CreateProxyResource(PP_Instance instance);
+
+ const PPB_BrokerTrusted* ppb_broker_target() const {
+ return static_cast<const PPB_BrokerTrusted*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgCreate(PP_Instance instance, HostResource* result_resource);
+ void OnMsgConnect(const HostResource& broker);
+ void OnMsgConnectComplete(const HostResource& broker,
+ IPC::PlatformFileForTransit foreign_socket_handle,
+ int32_t result);
+
+ void ConnectCompleteInHost(int32_t result, const HostResource& host_resource);
+
+ CompletionCallbackFactory<PPB_Broker_Proxy,
+ ProxyNonThreadSafeRefCount> callback_factory_;
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PPB_BROKER_PROXY_H_
diff --git a/ppapi/proxy/ppb_buffer_proxy.cc b/ppapi/proxy/ppb_buffer_proxy.cc
new file mode 100644
index 0000000..2e2ee90
--- /dev/null
+++ b/ppapi/proxy/ppb_buffer_proxy.cc
@@ -0,0 +1,194 @@
+// 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_buffer_proxy.h"
+
+#include <vector>
+
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/dev/ppb_buffer_dev.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/thunk/enter.h"
+#include "ppapi/thunk/ppb_buffer_api.h"
+#include "ppapi/thunk/ppb_buffer_trusted_api.h"
+#include "ppapi/thunk/thunk.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+InterfaceProxy* CreateBufferProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Buffer_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+class Buffer : public ppapi::thunk::PPB_Buffer_API,
+ public PluginResource {
+ public:
+ Buffer(const HostResource& resource,
+ const base::SharedMemoryHandle& shm_handle,
+ uint32_t size);
+ virtual ~Buffer();
+
+ // Resource overrides.
+ virtual Buffer* AsBuffer() OVERRIDE;
+
+ // ResourceObjectBase overrides.
+ virtual ppapi::thunk::PPB_Buffer_API* AsPPB_Buffer_API() OVERRIDE;
+
+ // PPB_Buffer_API implementation.
+ virtual PP_Bool Describe(uint32_t* size_in_bytes) OVERRIDE;
+ virtual PP_Bool IsMapped() OVERRIDE;
+ virtual void* Map() OVERRIDE;
+ virtual void Unmap() OVERRIDE;
+
+ private:
+ base::SharedMemory shm_;
+ uint32_t size_;
+ void* mapped_data_;
+ int map_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(Buffer);
+};
+
+Buffer::Buffer(const HostResource& resource,
+ const base::SharedMemoryHandle& shm_handle,
+ uint32_t size)
+ : PluginResource(resource),
+ shm_(shm_handle, false),
+ size_(size),
+ mapped_data_(NULL),
+ map_count_(0) {
+}
+
+Buffer::~Buffer() {
+ Unmap();
+}
+
+Buffer* Buffer::AsBuffer() {
+ return this;
+}
+
+ppapi::thunk::PPB_Buffer_API* Buffer::AsPPB_Buffer_API() {
+ return this;
+}
+
+PP_Bool Buffer::Describe(uint32_t* size_in_bytes) {
+ *size_in_bytes = size_;
+ return PP_TRUE;
+}
+
+PP_Bool Buffer::IsMapped() {
+ return PP_FromBool(!!mapped_data_);
+}
+
+void* Buffer::Map() {
+ if (map_count_++ == 0)
+ shm_.Map(size_);
+ return shm_.memory();
+}
+
+void Buffer::Unmap() {
+ if (--map_count_ == 0)
+ shm_.Unmap();
+}
+
+PPB_Buffer_Proxy::PPB_Buffer_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_Buffer_Proxy::~PPB_Buffer_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Buffer_Proxy::GetInfo() {
+ static const Info info = {
+ ppapi::thunk::GetPPB_Buffer_Thunk(),
+ PPB_BUFFER_DEV_INTERFACE,
+ INTERFACE_ID_PPB_BUFFER,
+ false,
+ &CreateBufferProxy,
+ };
+ return &info;
+}
+
+// static
+PP_Resource PPB_Buffer_Proxy::CreateProxyResource(PP_Instance instance,
+ uint32_t size) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+
+ HostResource result;
+ base::SharedMemoryHandle shm_handle = base::SharedMemory::NULLHandle();
+ dispatcher->Send(new PpapiHostMsg_PPBBuffer_Create(
+ INTERFACE_ID_PPB_BUFFER, instance, size,
+ &result, &shm_handle));
+ if (result.is_null() || !base::SharedMemory::IsHandleValid(shm_handle))
+ return 0;
+
+ linked_ptr<Buffer> object(new Buffer(result, shm_handle, size));
+ return PluginResourceTracker::GetInstance()->AddResource(object);
+}
+
+bool PPB_Buffer_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Buffer_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBBuffer_Create, OnMsgCreate)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ // TODO(brettw) handle bad messages!
+ return handled;
+}
+
+void PPB_Buffer_Proxy::OnMsgCreate(
+ PP_Instance instance,
+ uint32_t size,
+ HostResource* result_resource,
+ base::SharedMemoryHandle* result_shm_handle) {
+ // Overwritten below on success.
+ *result_shm_handle = base::SharedMemory::NULLHandle();
+ HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return;
+ PP_Resource local_buffer_resource =
+ ppb_buffer_target()->Create(instance, size);
+ if (local_buffer_resource == 0)
+ return;
+ ::ppapi::thunk::EnterResourceNoLock< ::ppapi::thunk::PPB_BufferTrusted_API>
+ trusted_buffer(local_buffer_resource, false);
+ if (trusted_buffer.failed())
+ return;
+ int local_fd;
+ if (trusted_buffer.object()->GetSharedMemory(&local_fd) != PP_OK)
+ return;
+
+ result_resource->SetHostResource(instance, local_buffer_resource);
+
+ // TODO(piman/brettw): Change trusted interface to return a PP_FileHandle,
+ // those casts are ugly.
+ base::PlatformFile platform_file =
+#if defined(OS_WIN)
+ reinterpret_cast<HANDLE>(static_cast<intptr_t>(local_fd));
+#elif defined(OS_POSIX)
+ local_fd;
+#else
+ #error Not implemented.
+#endif
+ *result_shm_handle = dispatcher->ShareHandleWithRemote(platform_file, false);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_buffer_proxy.h b/ppapi/proxy/ppb_buffer_proxy.h
new file mode 100644
index 0000000..6002950
--- /dev/null
+++ b/ppapi/proxy/ppb_buffer_proxy.h
@@ -0,0 +1,47 @@
+// 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_PPB_BUFFER_PROXY_H_
+#define PPAPI_PPB_BUFFER_PROXY_H_
+
+#include "base/shared_memory.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_Buffer_Dev;
+
+namespace pp {
+namespace proxy {
+
+class HostResource;
+
+class PPB_Buffer_Proxy : public InterfaceProxy {
+ public:
+ PPB_Buffer_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_Buffer_Proxy();
+
+ static const Info* GetInfo();
+
+ static PP_Resource CreateProxyResource(PP_Instance instance,
+ uint32_t size);
+
+ const PPB_Buffer_Dev* ppb_buffer_target() const {
+ return static_cast<const PPB_Buffer_Dev*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgCreate(PP_Instance instance,
+ uint32_t size,
+ HostResource* result_resource,
+ base::SharedMemoryHandle* result_shm_handle);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PPB_BUFFER_PROXY_H_
diff --git a/ppapi/proxy/ppb_char_set_proxy.cc b/ppapi/proxy/ppb_char_set_proxy.cc
new file mode 100644
index 0000000..4701ded
--- /dev/null
+++ b/ppapi/proxy/ppb_char_set_proxy.cc
@@ -0,0 +1,112 @@
+// 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_char_set_proxy.h"
+
+#include "base/basictypes.h"
+#include "ppapi/c/dev/ppb_char_set_dev.h"
+#include "ppapi/c/dev/ppb_memory_dev.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/shared_impl/char_set_impl.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/thunk.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+const PPB_Memory_Dev* GetMemoryDevInterface() {
+ return static_cast<const PPB_Memory_Dev*>(
+ PluginDispatcher::GetInterfaceFromDispatcher(PPB_MEMORY_DEV_INTERFACE));
+}
+
+InterfaceProxy* CreateCharSetProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_CharSet_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_CharSet_Proxy::PPB_CharSet_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_CharSet_Proxy::~PPB_CharSet_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_CharSet_Proxy::GetInfo() {
+ static const Info info = {
+ ppapi::thunk::GetPPB_CharSet_Thunk(),
+ PPB_CHAR_SET_DEV_INTERFACE,
+ INTERFACE_ID_PPB_CHAR_SET,
+ false,
+ &CreateCharSetProxy,
+ };
+ return &info;
+}
+
+ppapi::thunk::PPB_CharSet_FunctionAPI*
+PPB_CharSet_Proxy::AsPPB_CharSet_FunctionAPI() {
+ return this;
+}
+
+char* PPB_CharSet_Proxy::UTF16ToCharSet(
+ PP_Instance instance,
+ const uint16_t* utf16, uint32_t utf16_len,
+ const char* output_char_set,
+ PP_CharSet_ConversionError on_error,
+ uint32_t* output_length) {
+ return ppapi::CharSetImpl::UTF16ToCharSet(
+ GetMemoryDevInterface(), utf16, utf16_len, output_char_set, on_error,
+ output_length);
+}
+
+uint16_t* PPB_CharSet_Proxy::CharSetToUTF16(
+ PP_Instance instance,
+ const char* input, uint32_t input_len,
+ const char* input_char_set,
+ PP_CharSet_ConversionError on_error,
+ uint32_t* output_length) {
+ return ppapi::CharSetImpl::CharSetToUTF16(
+ GetMemoryDevInterface(), input, input_len, input_char_set, on_error,
+ output_length);
+}
+
+PP_Var PPB_CharSet_Proxy::GetDefaultCharSet(PP_Instance instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return PP_MakeUndefined();
+
+ ReceiveSerializedVarReturnValue result;
+ dispatcher->Send(new PpapiHostMsg_PPBCharSet_GetDefaultCharSet(
+ INTERFACE_ID_PPB_CHAR_SET, instance, &result));
+ return result.Return(dispatcher);
+}
+
+bool PPB_CharSet_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_CharSet_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCharSet_GetDefaultCharSet,
+ OnMsgGetDefaultCharSet)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPB_CharSet_Proxy::OnMsgGetDefaultCharSet(
+ PP_Instance instance,
+ SerializedVarReturnValue result) {
+ ppapi::thunk::EnterFunctionNoLock<ppapi::thunk::PPB_CharSet_FunctionAPI>
+ enter(instance, true);
+ if (enter.succeeded())
+ result.Return(dispatcher(), enter.functions()->GetDefaultCharSet(instance));
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_char_set_proxy.h b/ppapi/proxy/ppb_char_set_proxy.h
new file mode 100644
index 0000000..0f70ab5
--- /dev/null
+++ b/ppapi/proxy/ppb_char_set_proxy.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2010 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_CHAR_SET_PROXY_H_
+#define PPAPI_PROXY_PPB_CHAR_SET_PROXY_H_
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/shared_impl/function_group_base.h"
+#include "ppapi/thunk/ppb_char_set_api.h"
+
+struct PPB_CharSet_Dev;
+struct PPB_Core;
+
+namespace pp {
+namespace proxy {
+
+class SerializedVarReturnValue;
+
+class PPB_CharSet_Proxy : public ppapi::FunctionGroupBase,
+ public ppapi::thunk::PPB_CharSet_FunctionAPI,
+ public InterfaceProxy {
+ public:
+ PPB_CharSet_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_CharSet_Proxy();
+
+ static const Info* GetInfo();
+
+ // FunctionGroupBase overrides.
+ virtual ppapi::thunk::PPB_CharSet_FunctionAPI* AsPPB_CharSet_FunctionAPI()
+ OVERRIDE;
+
+ // PPB_CharSet_FunctionAPI implementation.
+ virtual char* UTF16ToCharSet(PP_Instance instance,
+ const uint16_t* utf16, uint32_t utf16_len,
+ const char* output_char_set,
+ PP_CharSet_ConversionError on_error,
+ uint32_t* output_length) OVERRIDE;
+ virtual uint16_t* CharSetToUTF16(PP_Instance instance,
+ const char* input, uint32_t input_len,
+ const char* input_char_set,
+ PP_CharSet_ConversionError on_error,
+ uint32_t* output_length) OVERRIDE;
+ virtual PP_Var GetDefaultCharSet(PP_Instance instance) OVERRIDE;
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+
+ private:
+ void OnMsgGetDefaultCharSet(PP_Instance instance,
+ SerializedVarReturnValue result);
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_CharSet_Proxy);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_CHAR_SET_PROXY_H_
diff --git a/ppapi/proxy/ppb_console_proxy.cc b/ppapi/proxy/ppb_console_proxy.cc
new file mode 100644
index 0000000..a04aacc
--- /dev/null
+++ b/ppapi/proxy/ppb_console_proxy.cc
@@ -0,0 +1,103 @@
+// 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_console_proxy.h"
+
+#include "ppapi/c/dev/ppb_console_dev.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+void Log(PP_Instance instance, PP_LogLevel_Dev level, PP_Var value) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return;
+ dispatcher->Send(new PpapiHostMsg_PPBConsole_Log(
+ INTERFACE_ID_PPB_CONSOLE, instance, static_cast<int>(level),
+ SerializedVarSendInput(dispatcher, value)));
+}
+
+void LogWithSource(PP_Instance instance,
+ PP_LogLevel_Dev level,
+ const PP_Var source,
+ const PP_Var value) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return;
+ dispatcher->Send(new PpapiHostMsg_PPBConsole_LogWithSource(
+ INTERFACE_ID_PPB_CONSOLE, instance, static_cast<int>(level),
+ SerializedVarSendInput(dispatcher, source),
+ SerializedVarSendInput(dispatcher, value)));
+}
+
+const PPB_Console_Dev console_interface = {
+ &Log,
+ &LogWithSource
+};
+
+InterfaceProxy* CreateConsoleProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Console_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_Console_Proxy::PPB_Console_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_Console_Proxy::~PPB_Console_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Console_Proxy::GetInfo() {
+ static const Info info = {
+ &console_interface,
+ PPB_CONSOLE_DEV_INTERFACE,
+ INTERFACE_ID_PPB_CONSOLE,
+ false,
+ &CreateConsoleProxy,
+ };
+ return &info;
+}
+
+bool PPB_Console_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Console_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBConsole_Log,
+ OnMsgLog)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBConsole_LogWithSource,
+ OnMsgLogWithSource)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPB_Console_Proxy::OnMsgLog(PP_Instance instance,
+ int log_level,
+ SerializedVarReceiveInput value) {
+ ppb_console_target()->Log(instance,
+ static_cast<PP_LogLevel_Dev>(log_level),
+ value.Get(dispatcher()));
+}
+
+void PPB_Console_Proxy::OnMsgLogWithSource(PP_Instance instance,
+ int log_level,
+ SerializedVarReceiveInput source,
+ SerializedVarReceiveInput value) {
+ ppb_console_target()->LogWithSource(
+ instance,
+ static_cast<PP_LogLevel_Dev>(log_level),
+ source.Get(dispatcher()),
+ value.Get(dispatcher()));
+}
+
+} // namespace proxy
+} // namespace pp
+
diff --git a/ppapi/proxy/ppb_console_proxy.h b/ppapi/proxy/ppb_console_proxy.h
new file mode 100644
index 0000000..af1c9e0
--- /dev/null
+++ b/ppapi/proxy/ppb_console_proxy.h
@@ -0,0 +1,48 @@
+// 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_CONSOLE_PROXY_H_
+#define PPAPI_PROXY_PPB_CONSOLE_PROXY_H_
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/serialized_var.h"
+
+struct PPB_Console_Dev;
+
+namespace pp {
+namespace proxy {
+
+class PPB_Console_Proxy : public InterfaceProxy {
+ public:
+ PPB_Console_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_Console_Proxy();
+
+ static const Info* GetInfo();
+
+ const PPB_Console_Dev* ppb_console_target() const {
+ return static_cast<const PPB_Console_Dev*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgLog(PP_Instance instance,
+ int log_level,
+ SerializedVarReceiveInput value);
+ void OnMsgLogWithSource(PP_Instance instance,
+ int log_level,
+ SerializedVarReceiveInput source,
+ SerializedVarReceiveInput value);
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_Console_Proxy);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_CONSOLE_PROXY_H_
diff --git a/ppapi/proxy/ppb_context_3d_proxy.cc b/ppapi/proxy/ppb_context_3d_proxy.cc
new file mode 100644
index 0000000..ff2fe93
--- /dev/null
+++ b/ppapi/proxy/ppb_context_3d_proxy.cc
@@ -0,0 +1,719 @@
+// 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_context_3d_proxy.h"
+
+#include "base/hash_tables.h"
+#include "gpu/command_buffer/client/gles2_cmd_helper.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/dev/ppb_context_3d_dev.h"
+#include "ppapi/c/dev/ppb_context_3d_trusted_dev.h"
+#include "ppapi/proxy/enter_proxy.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_surface_3d_proxy.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/resource_creation_api.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::thunk::EnterFunctionNoLock;
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_Context3D_API;
+using ppapi::thunk::PPB_Surface3D_API;
+using ppapi::thunk::ResourceCreationAPI;
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+base::SharedMemoryHandle TransportSHMHandleFromInt(Dispatcher* dispatcher,
+ int shm_handle) {
+ // TODO(piman): Change trusted interface to return a PP_FileHandle, those
+ // casts are ugly.
+ base::PlatformFile source =
+#if defined(OS_WIN)
+ reinterpret_cast<HANDLE>(static_cast<intptr_t>(shm_handle));
+#elif defined(OS_POSIX)
+ shm_handle;
+#else
+ #error Not implemented.
+#endif
+ // Don't close the handle, it doesn't belong to us.
+ return dispatcher->ShareHandleWithRemote(source, false);
+}
+
+PP_Context3DTrustedState GetErrorState() {
+ PP_Context3DTrustedState error_state = { 0 };
+ error_state.error = kGenericError;
+ return error_state;
+}
+
+gpu::CommandBuffer::State GPUStateFromPPState(
+ const PP_Context3DTrustedState& s) {
+ gpu::CommandBuffer::State state;
+ state.num_entries = s.num_entries;
+ state.get_offset = s.get_offset;
+ state.put_offset = s.put_offset;
+ state.token = s.token;
+ state.error = static_cast<gpu::error::Error>(s.error);
+ state.generation = s.generation;
+ return state;
+}
+
+// Size of the transfer buffer.
+const int32 kCommandBufferSize = 1024 * 1024;
+const int32 kTransferBufferSize = 1024 * 1024;
+
+InterfaceProxy* CreateContext3DProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Context3D_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+class PepperCommandBuffer : public gpu::CommandBuffer {
+ public:
+ PepperCommandBuffer(const HostResource& resource,
+ PluginDispatcher* dispatcher);
+ virtual ~PepperCommandBuffer();
+
+ // CommandBuffer implementation:
+ virtual bool Initialize(int32 size);
+ virtual bool Initialize(base::SharedMemory* buffer, int32 size);
+ virtual gpu::Buffer GetRingBuffer();
+ virtual State GetState();
+ virtual void Flush(int32 put_offset);
+ virtual State FlushSync(int32 put_offset, int32 last_known_get);
+ virtual void SetGetOffset(int32 get_offset);
+ virtual int32 CreateTransferBuffer(size_t size, int32 id_request);
+ virtual int32 RegisterTransferBuffer(base::SharedMemory* shared_memory,
+ size_t size,
+ int32 id_request);
+ virtual void DestroyTransferBuffer(int32 id);
+ virtual gpu::Buffer GetTransferBuffer(int32 handle);
+ virtual void SetToken(int32 token);
+ virtual void SetParseError(gpu::error::Error error);
+ virtual void SetContextLostReason(gpu::error::ContextLostReason reason);
+
+ private:
+ bool Send(IPC::Message* msg);
+ void UpdateState(const gpu::CommandBuffer::State& state);
+
+ int32 num_entries_;
+ scoped_ptr<base::SharedMemory> ring_buffer_;
+
+ typedef base::hash_map<int32, gpu::Buffer> TransferBufferMap;
+ TransferBufferMap transfer_buffers_;
+
+ State last_state_;
+
+ HostResource resource_;
+ PluginDispatcher* dispatcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperCommandBuffer);
+};
+
+PepperCommandBuffer::PepperCommandBuffer(
+ const HostResource& resource,
+ PluginDispatcher* dispatcher)
+ : num_entries_(0),
+ resource_(resource),
+ dispatcher_(dispatcher) {
+}
+
+PepperCommandBuffer::~PepperCommandBuffer() {
+ // Delete all the locally cached shared memory objects, closing the handle
+ // in this process.
+ for (TransferBufferMap::iterator it = transfer_buffers_.begin();
+ it != transfer_buffers_.end();
+ ++it) {
+ delete it->second.shared_memory;
+ it->second.shared_memory = NULL;
+ }
+}
+
+bool PepperCommandBuffer::Initialize(int32 size) {
+ DCHECK(!ring_buffer_.get());
+
+ // Initialize the service. Assuming we are sandboxed, the GPU
+ // process is responsible for duplicating the handle. This might not be true
+ // for NaCl.
+ base::SharedMemoryHandle handle;
+ if (Send(new PpapiHostMsg_PPBContext3D_Initialize(
+ INTERFACE_ID_PPB_CONTEXT_3D, resource_, size, &handle)) &&
+ base::SharedMemory::IsHandleValid(handle)) {
+ ring_buffer_.reset(new base::SharedMemory(handle, false));
+ if (ring_buffer_->Map(size)) {
+ num_entries_ = size / sizeof(gpu::CommandBufferEntry);
+ return true;
+ }
+
+ ring_buffer_.reset();
+ }
+
+ return false;
+}
+
+bool PepperCommandBuffer::Initialize(base::SharedMemory* buffer, int32 size) {
+ // Not implemented in proxy.
+ NOTREACHED();
+ return false;
+}
+
+gpu::Buffer PepperCommandBuffer::GetRingBuffer() {
+ // Return locally cached ring buffer.
+ gpu::Buffer buffer;
+ buffer.ptr = ring_buffer_->memory();
+ buffer.size = num_entries_ * sizeof(gpu::CommandBufferEntry);
+ buffer.shared_memory = ring_buffer_.get();
+ return buffer;
+}
+
+gpu::CommandBuffer::State PepperCommandBuffer::GetState() {
+ // Send will flag state with lost context if IPC fails.
+ if (last_state_.error == gpu::error::kNoError) {
+ gpu::CommandBuffer::State state;
+ if (Send(new PpapiHostMsg_PPBContext3D_GetState(
+ INTERFACE_ID_PPB_CONTEXT_3D, resource_, &state)))
+ UpdateState(state);
+ }
+
+ return last_state_;
+}
+
+void PepperCommandBuffer::Flush(int32 put_offset) {
+ if (last_state_.error != gpu::error::kNoError)
+ return;
+
+ IPC::Message* message = new PpapiHostMsg_PPBContext3D_AsyncFlush(
+ INTERFACE_ID_PPB_CONTEXT_3D, resource_, put_offset);
+
+ // Do not let a synchronous flush hold up this message. If this handler is
+ // deferred until after the synchronous flush completes, it will overwrite the
+ // cached last_state_ with out-of-date data.
+ message->set_unblock(true);
+ Send(message);
+}
+
+gpu::CommandBuffer::State PepperCommandBuffer::FlushSync(
+ int32 put_offset, int32 last_known_get) {
+ if (last_known_get == last_state_.get_offset) {
+ // Send will flag state with lost context if IPC fails.
+ if (last_state_.error == gpu::error::kNoError) {
+ gpu::CommandBuffer::State state;
+ if (Send(new PpapiHostMsg_PPBContext3D_Flush(
+ INTERFACE_ID_PPB_CONTEXT_3D, resource_, put_offset,
+ last_known_get, &state)))
+ UpdateState(state);
+ }
+ } else {
+ Flush(put_offset);
+ }
+
+ return last_state_;
+}
+
+void PepperCommandBuffer::SetGetOffset(int32 get_offset) {
+ // Not implemented in proxy.
+ NOTREACHED();
+}
+
+int32 PepperCommandBuffer::CreateTransferBuffer(size_t size, int32 id_request) {
+ if (last_state_.error == gpu::error::kNoError) {
+ int32 id;
+ if (Send(new PpapiHostMsg_PPBContext3D_CreateTransferBuffer(
+ INTERFACE_ID_PPB_CONTEXT_3D, resource_, size, &id))) {
+ return id;
+ }
+ }
+
+ return -1;
+}
+
+int32 PepperCommandBuffer::RegisterTransferBuffer(
+ base::SharedMemory* shared_memory,
+ size_t size,
+ int32 id_request) {
+ // Not implemented in proxy.
+ NOTREACHED();
+ return -1;
+}
+
+void PepperCommandBuffer::DestroyTransferBuffer(int32 id) {
+ if (last_state_.error != gpu::error::kNoError)
+ return;
+
+ // Remove the transfer buffer from the client side4 cache.
+ TransferBufferMap::iterator it = transfer_buffers_.find(id);
+ DCHECK(it != transfer_buffers_.end());
+
+ // Delete the shared memory object, closing the handle in this process.
+ delete it->second.shared_memory;
+
+ transfer_buffers_.erase(it);
+
+ Send(new PpapiHostMsg_PPBContext3D_DestroyTransferBuffer(
+ INTERFACE_ID_PPB_CONTEXT_3D, resource_, id));
+}
+
+gpu::Buffer PepperCommandBuffer::GetTransferBuffer(int32 id) {
+ if (last_state_.error != gpu::error::kNoError)
+ return gpu::Buffer();
+
+ // Check local cache to see if there is already a client side shared memory
+ // object for this id.
+ TransferBufferMap::iterator it = transfer_buffers_.find(id);
+ if (it != transfer_buffers_.end()) {
+ return it->second;
+ }
+
+ // Assuming we are in the renderer process, the service is responsible for
+ // duplicating the handle. This might not be true for NaCl.
+ base::SharedMemoryHandle handle;
+ uint32 size;
+ if (!Send(new PpapiHostMsg_PPBContext3D_GetTransferBuffer(
+ INTERFACE_ID_PPB_CONTEXT_3D, resource_, id, &handle, &size))) {
+ return gpu::Buffer();
+ }
+
+ // Cache the transfer buffer shared memory object client side.
+ scoped_ptr<base::SharedMemory> shared_memory(
+ new base::SharedMemory(handle, false));
+
+ // Map the shared memory on demand.
+ if (!shared_memory->memory()) {
+ if (!shared_memory->Map(size)) {
+ return gpu::Buffer();
+ }
+ }
+
+ gpu::Buffer buffer;
+ buffer.ptr = shared_memory->memory();
+ buffer.size = size;
+ buffer.shared_memory = shared_memory.release();
+ transfer_buffers_[id] = buffer;
+
+ return buffer;
+}
+
+void PepperCommandBuffer::SetToken(int32 token) {
+ NOTREACHED();
+}
+
+void PepperCommandBuffer::SetParseError(gpu::error::Error error) {
+ NOTREACHED();
+}
+
+void PepperCommandBuffer::SetContextLostReason(
+ gpu::error::ContextLostReason reason) {
+ NOTREACHED();
+}
+
+bool PepperCommandBuffer::Send(IPC::Message* msg) {
+ DCHECK(last_state_.error == gpu::error::kNoError);
+
+ if (dispatcher_->Send(msg))
+ return true;
+
+ last_state_.error = gpu::error::kLostContext;
+ return false;
+}
+
+void PepperCommandBuffer::UpdateState(const gpu::CommandBuffer::State& state) {
+ // Handle wraparound. It works as long as we don't have more than 2B state
+ // updates in flight across which reordering occurs.
+ if (state.generation - last_state_.generation < 0x80000000U)
+ last_state_ = state;
+}
+
+// Context3D -------------------------------------------------------------------
+
+Context3D::Context3D(const HostResource& resource)
+ : PluginResource(resource),
+ draw_(NULL),
+ read_(NULL),
+ transfer_buffer_id_(0) {
+}
+
+Context3D::~Context3D() {
+ if (draw_)
+ draw_->set_context(NULL);
+}
+
+PPB_Context3D_API* Context3D::AsPPB_Context3D_API() {
+ return this;
+}
+
+bool Context3D::CreateImplementation() {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance());
+ if (!dispatcher)
+ return false;
+
+ command_buffer_.reset(new PepperCommandBuffer(host_resource(), dispatcher));
+
+ if (!command_buffer_->Initialize(kCommandBufferSize))
+ return false;
+
+ helper_.reset(new gpu::gles2::GLES2CmdHelper(command_buffer_.get()));
+ if (!helper_->Initialize(kCommandBufferSize))
+ return false;
+
+ transfer_buffer_id_ =
+ command_buffer_->CreateTransferBuffer(kTransferBufferSize, -1);
+ if (transfer_buffer_id_ < 0)
+ return false;
+
+ gpu::Buffer transfer_buffer =
+ command_buffer_->GetTransferBuffer(transfer_buffer_id_);
+ if (!transfer_buffer.ptr)
+ return false;
+
+ gles2_impl_.reset(new gpu::gles2::GLES2Implementation(
+ helper_.get(),
+ transfer_buffer.size,
+ transfer_buffer.ptr,
+ transfer_buffer_id_,
+ false));
+
+ return true;
+}
+
+int32_t Context3D::GetAttrib(int32_t attribute, int32_t* value) {
+ // TODO(alokp): Implement me.
+ return 0;
+}
+
+int32_t Context3D::BindSurfaces(PP_Resource pp_draw, PP_Resource pp_read) {
+ // TODO(alokp): Support separate draw-read surfaces.
+ DCHECK_EQ(pp_draw, pp_read);
+ if (pp_draw != pp_read)
+ return PP_GRAPHICS3DERROR_BAD_MATCH;
+
+ EnterResourceNoLock<PPB_Surface3D_API> enter_draw(pp_draw, false);
+ EnterResourceNoLock<PPB_Surface3D_API> enter_read(pp_read, false);
+ Surface3D* draw_surface = enter_draw.succeeded() ?
+ static_cast<Surface3D*>(enter_draw.object()) : NULL;
+ Surface3D* read_surface = enter_read.succeeded() ?
+ static_cast<Surface3D*>(enter_read.object()) : NULL;
+
+ if (pp_draw && !draw_surface)
+ return PP_ERROR_BADRESOURCE;
+ if (pp_read && !read_surface)
+ return PP_ERROR_BADRESOURCE;
+ HostResource host_draw =
+ draw_surface ? draw_surface->host_resource() : HostResource();
+ HostResource host_read =
+ read_surface ? read_surface->host_resource() : HostResource();
+
+ int32_t result;
+ GetDispatcher()->Send(new PpapiHostMsg_PPBContext3D_BindSurfaces(
+ INTERFACE_ID_PPB_CONTEXT_3D,
+ host_resource(), host_draw, host_read, &result));
+ if (result != PP_OK)
+ return result;
+
+ if (draw_surface != draw_) {
+ if (draw_)
+ draw_->set_context(NULL);
+ if (draw_surface) {
+ draw_surface->set_context(this);
+ // Resize the backing texture to the size of the instance when it is
+ // bound.
+ // TODO(alokp): This should be the responsibility of plugins.
+ InstanceData* data = GetDispatcher()->GetInstanceData(instance());
+ gles2_impl()->ResizeCHROMIUM(data->position.size.width,
+ data->position.size.height);
+ }
+ draw_ = draw_surface;
+ }
+ read_ = read_surface;
+ return PP_OK;
+}
+
+int32_t Context3D::GetBoundSurfaces(PP_Resource* draw, PP_Resource* read) {
+ *draw = draw_ ? draw_->resource() : 0;
+ *read = read_ ? read_->resource() : 0;
+ return PP_OK;
+}
+
+PP_Bool Context3D::InitializeTrusted(int32_t size) {
+ // Trusted interface not implemented in the proxy.
+ return PP_FALSE;
+}
+
+PP_Bool Context3D::GetRingBuffer(int* shm_handle,
+ uint32_t* shm_size) {
+ // Trusted interface not implemented in the proxy.
+ return PP_FALSE;
+}
+
+PP_Context3DTrustedState Context3D::GetState() {
+ // Trusted interface not implemented in the proxy.
+ return GetErrorState();
+}
+
+PP_Bool Context3D::Flush(int32_t put_offset) {
+ // Trusted interface not implemented in the proxy.
+ return PP_FALSE;
+}
+
+PP_Context3DTrustedState Context3D::FlushSync(int32_t put_offset) {
+ // Trusted interface not implemented in the proxy.
+ return GetErrorState();
+}
+
+int32_t Context3D::CreateTransferBuffer(uint32_t size) {
+ // Trusted interface not implemented in the proxy.
+ return 0;
+}
+
+PP_Bool Context3D::DestroyTransferBuffer(int32_t id) {
+ // Trusted interface not implemented in the proxy.
+ return PP_FALSE;
+}
+
+PP_Bool Context3D::GetTransferBuffer(int32_t id,
+ int* shm_handle,
+ uint32_t* shm_size) {
+ // Trusted interface not implemented in the proxy.
+ return PP_FALSE;
+}
+
+PP_Context3DTrustedState Context3D::FlushSyncFast(int32_t put_offset,
+ int32_t last_known_get) {
+ // Trusted interface not implemented in the proxy.
+ return GetErrorState();
+}
+
+void* Context3D::MapTexSubImage2DCHROMIUM(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLenum access) {
+ return gles2_impl_->MapTexSubImage2DCHROMIUM(
+ target, level, xoffset, yoffset, width, height, format, type, access);
+}
+
+void Context3D::UnmapTexSubImage2DCHROMIUM(const void* mem) {
+ gles2_impl_->UnmapTexSubImage2DCHROMIUM(mem);
+}
+
+// PPB_Context3D_Proxy ---------------------------------------------------------
+
+PPB_Context3D_Proxy::PPB_Context3D_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_Context3D_Proxy::~PPB_Context3D_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Context3D_Proxy::GetInfo() {
+ static const Info info = {
+ ::ppapi::thunk::GetPPB_Context3D_Thunk(),
+ PPB_CONTEXT_3D_DEV_INTERFACE,
+ INTERFACE_ID_PPB_CONTEXT_3D,
+ false,
+ &CreateContext3DProxy,
+ };
+ return &info;
+}
+
+// static
+const InterfaceProxy::Info* PPB_Context3D_Proxy::GetTextureMappingInfo() {
+ static const Info info = {
+ ::ppapi::thunk::GetPPB_GLESChromiumTextureMapping_Thunk(),
+ PPB_GLES_CHROMIUM_TEXTURE_MAPPING_DEV_INTERFACE,
+ INTERFACE_ID_NONE, // CONTEXT_3D is the canonical one.
+ false,
+ &CreateContext3DProxy,
+ };
+ return &info;
+}
+
+// static
+PP_Resource PPB_Context3D_Proxy::Create(PP_Instance instance,
+ PP_Config3D_Dev config,
+ PP_Resource share_context,
+ const int32_t* attrib_list) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return PP_ERROR_BADARGUMENT;
+
+ // TODO(alokp): Support shared context.
+ DCHECK_EQ(0, share_context);
+ if (share_context != 0)
+ return 0;
+
+ std::vector<int32_t> attribs;
+ if (attrib_list) {
+ for (const int32_t* attr = attrib_list; attr; ++attr)
+ attribs.push_back(*attr);
+ } else {
+ attribs.push_back(0);
+ }
+
+ HostResource result;
+ dispatcher->Send(new PpapiHostMsg_PPBContext3D_Create(
+ INTERFACE_ID_PPB_CONTEXT_3D, instance, config, attribs, &result));
+
+ if (result.is_null())
+ return 0;
+ linked_ptr<Context3D> context_3d(new Context3D(result));
+ if (!context_3d->CreateImplementation())
+ return 0;
+ return PluginResourceTracker::GetInstance()->AddResource(context_3d);
+}
+
+bool PPB_Context3D_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Context3D_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBContext3D_Create,
+ OnMsgCreate)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBContext3D_BindSurfaces,
+ OnMsgBindSurfaces)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBContext3D_Initialize,
+ OnMsgInitialize)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBContext3D_GetState,
+ OnMsgGetState)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBContext3D_Flush,
+ OnMsgFlush)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBContext3D_AsyncFlush,
+ OnMsgAsyncFlush)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBContext3D_CreateTransferBuffer,
+ OnMsgCreateTransferBuffer)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBContext3D_DestroyTransferBuffer,
+ OnMsgDestroyTransferBuffer)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBContext3D_GetTransferBuffer,
+ OnMsgGetTransferBuffer)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+
+ IPC_END_MESSAGE_MAP()
+ // FIXME(brettw) handle bad messages!
+ return handled;
+}
+
+void PPB_Context3D_Proxy::OnMsgCreate(PP_Instance instance,
+ PP_Config3D_Dev config,
+ const std::vector<int32_t>& attribs,
+ HostResource* result) {
+ if (attribs.empty() || attribs.back() != 0)
+ return; // Bad message.
+ EnterFunctionNoLock<ResourceCreationAPI> enter(instance, true);
+ if (enter.succeeded()) {
+ result->SetHostResource(
+ instance,
+ enter.functions()->CreateContext3DRaw(instance, config, 0,
+ &attribs.front()));
+ }
+}
+
+void PPB_Context3D_Proxy::OnMsgBindSurfaces(const HostResource& context,
+ const HostResource& draw,
+ const HostResource& read,
+ int32_t* result) {
+ EnterHostFromHostResource<PPB_Context3D_API> enter(context);
+ if (enter.succeeded()) {
+ *result = enter.object()->BindSurfaces(draw.host_resource(),
+ read.host_resource());
+ } else {
+ *result = PP_ERROR_BADRESOURCE;
+ }
+}
+
+void PPB_Context3D_Proxy::OnMsgInitialize(
+ const HostResource& context,
+ int32 size,
+ base::SharedMemoryHandle* ring_buffer) {
+ *ring_buffer = base::SharedMemory::NULLHandle();
+ EnterHostFromHostResource<PPB_Context3D_API> enter(context);
+ if (enter.failed())
+ return;
+
+ if (!enter.object()->InitializeTrusted(size))
+ return;
+
+ int shm_handle;
+ uint32_t shm_size;
+ if (!enter.object()->GetRingBuffer(&shm_handle, &shm_size))
+ return;
+ *ring_buffer = TransportSHMHandleFromInt(dispatcher(), shm_handle);
+}
+
+void PPB_Context3D_Proxy::OnMsgGetState(const HostResource& context,
+ gpu::CommandBuffer::State* state) {
+ EnterHostFromHostResource<PPB_Context3D_API> enter(context);
+ if (enter.failed())
+ return;
+ PP_Context3DTrustedState pp_state = enter.object()->GetState();
+ *state = GPUStateFromPPState(pp_state);
+}
+
+void PPB_Context3D_Proxy::OnMsgFlush(const HostResource& context,
+ int32 put_offset,
+ int32 last_known_get,
+ gpu::CommandBuffer::State* state) {
+ EnterHostFromHostResource<PPB_Context3D_API> enter(context);
+ if (enter.failed())
+ return;
+ PP_Context3DTrustedState pp_state = enter.object()->FlushSyncFast(
+ put_offset, last_known_get);
+ *state = GPUStateFromPPState(pp_state);
+}
+
+void PPB_Context3D_Proxy::OnMsgAsyncFlush(const HostResource& context,
+ int32 put_offset) {
+ EnterHostFromHostResource<PPB_Context3D_API> enter(context);
+ if (enter.succeeded())
+ enter.object()->Flush(put_offset);
+}
+
+void PPB_Context3D_Proxy::OnMsgCreateTransferBuffer(
+ const HostResource& context,
+ int32 size,
+ int32* id) {
+ EnterHostFromHostResource<PPB_Context3D_API> enter(context);
+ if (enter.succeeded())
+ *id = enter.object()->CreateTransferBuffer(size);
+ else
+ *id = 0;
+}
+
+void PPB_Context3D_Proxy::OnMsgDestroyTransferBuffer(
+ const HostResource& context,
+ int32 id) {
+ EnterHostFromHostResource<PPB_Context3D_API> enter(context);
+ if (enter.succeeded())
+ enter.object()->DestroyTransferBuffer(id);
+}
+
+void PPB_Context3D_Proxy::OnMsgGetTransferBuffer(
+ const HostResource& context,
+ int32 id,
+ base::SharedMemoryHandle* transfer_buffer,
+ uint32* size) {
+ *transfer_buffer = base::SharedMemory::NULLHandle();
+ *size = 0;
+
+ EnterHostFromHostResource<PPB_Context3D_API> enter(context);
+ int shm_handle = 0;
+ uint32_t shm_size = 0;
+ if (enter.succeeded() &&
+ enter.object()->GetTransferBuffer(id, &shm_handle, &shm_size)) {
+ *transfer_buffer = TransportSHMHandleFromInt(dispatcher(), shm_handle);
+ *size = shm_size;
+ }
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_context_3d_proxy.h b/ppapi/proxy/ppb_context_3d_proxy.h
new file mode 100644
index 0000000..991b7a2
--- /dev/null
+++ b/ppapi/proxy/ppb_context_3d_proxy.h
@@ -0,0 +1,144 @@
+// 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_CONTEXT_3D_PROXY_H_
+#define PPAPI_PROXY_PPB_CONTEXT_3D_PROXY_H_
+
+#include <vector>
+
+#include "base/shared_memory.h"
+#include "gpu/command_buffer/common/command_buffer.h"
+#include "ppapi/c/dev/pp_graphics_3d_dev.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h"
+#include "ppapi/thunk/ppb_context_3d_api.h"
+
+struct PPB_Context3D_Dev;
+struct PPB_Context3DTrusted_Dev;
+
+namespace gpu {
+class CommandBuffer;
+
+namespace gles2 {
+class GLES2CmdHelper;
+class GLES2Implementation;
+} // namespace gles2
+
+} // namespace gpu
+
+namespace pp {
+namespace proxy {
+
+class Surface3D;
+
+class Context3D : public PluginResource,
+ public ppapi::thunk::PPB_Context3D_API {
+ public:
+ explicit Context3D(const HostResource& resource);
+ virtual ~Context3D();
+
+ // ResourceObjectBase overrides.
+ virtual ::ppapi::thunk::PPB_Context3D_API* AsPPB_Context3D_API() OVERRIDE;
+
+ gpu::gles2::GLES2Implementation* gles2_impl() const {
+ return gles2_impl_.get();
+ }
+
+ // PPB_Context3D_API implementation.
+ virtual int32_t GetAttrib(int32_t attribute, int32_t* value) OVERRIDE;
+ virtual int32_t BindSurfaces(PP_Resource draw, PP_Resource read) OVERRIDE;
+ virtual int32_t GetBoundSurfaces(PP_Resource* draw,
+ PP_Resource* read) OVERRIDE;
+ virtual PP_Bool InitializeTrusted(int32_t size) OVERRIDE;
+ virtual PP_Bool GetRingBuffer(int* shm_handle,
+ uint32_t* shm_size) OVERRIDE;
+ virtual PP_Context3DTrustedState GetState() OVERRIDE;
+ virtual PP_Bool Flush(int32_t put_offset) OVERRIDE;
+ virtual PP_Context3DTrustedState FlushSync(int32_t put_offset) OVERRIDE;
+ virtual int32_t CreateTransferBuffer(uint32_t size) OVERRIDE;
+ virtual PP_Bool DestroyTransferBuffer(int32_t id) OVERRIDE;
+ virtual PP_Bool GetTransferBuffer(int32_t id,
+ int* shm_handle,
+ uint32_t* shm_size) OVERRIDE;
+ virtual PP_Context3DTrustedState FlushSyncFast(
+ int32_t put_offset,
+ int32_t last_known_get) OVERRIDE;
+ virtual void* MapTexSubImage2DCHROMIUM(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLenum access) OVERRIDE;
+ virtual void UnmapTexSubImage2DCHROMIUM(const void* mem) OVERRIDE;
+
+ bool CreateImplementation();
+
+ private:
+ Surface3D* draw_;
+ Surface3D* read_;
+
+ scoped_ptr<gpu::CommandBuffer> command_buffer_;
+ scoped_ptr<gpu::gles2::GLES2CmdHelper> helper_;
+ int32 transfer_buffer_id_;
+ scoped_ptr<gpu::gles2::GLES2Implementation> gles2_impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(Context3D);
+};
+
+class PPB_Context3D_Proxy : public InterfaceProxy {
+ public:
+ PPB_Context3D_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_Context3D_Proxy();
+
+ static const Info* GetInfo();
+ static const Info* GetTextureMappingInfo();
+
+ static PP_Resource Create(PP_Instance instance,
+ PP_Config3D_Dev config,
+ PP_Resource share_context,
+ const int32_t* attrib_list);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ void OnMsgCreate(PP_Instance instance,
+ PP_Config3D_Dev config,
+ const std::vector<int32_t>& attribs,
+ HostResource* result);
+ void OnMsgBindSurfaces(const HostResource& context,
+ const HostResource& draw,
+ const HostResource& read,
+ int32_t* result);
+ void OnMsgInitialize(const HostResource& context,
+ int32 size,
+ base::SharedMemoryHandle* ring_buffer);
+ void OnMsgGetState(const HostResource& context,
+ gpu::CommandBuffer::State* state);
+ void OnMsgFlush(const HostResource& context,
+ int32 put_offset,
+ int32 last_known_get,
+ gpu::CommandBuffer::State* state);
+ void OnMsgAsyncFlush(const HostResource& context,
+ int32 put_offset);
+ void OnMsgCreateTransferBuffer(const HostResource& context,
+ int32 size,
+ int32* id);
+ void OnMsgDestroyTransferBuffer(const HostResource& context,
+ int32 id);
+ void OnMsgGetTransferBuffer(const HostResource& context,
+ int32 id,
+ base::SharedMemoryHandle* transfer_buffer,
+ uint32* size);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_CONTEXT_3D_PROXY_H_
diff --git a/ppapi/proxy/ppb_core_proxy.cc b/ppapi/proxy/ppb_core_proxy.cc
new file mode 100644
index 0000000..06d5974
--- /dev/null
+++ b/ppapi/proxy/ppb_core_proxy.cc
@@ -0,0 +1,138 @@
+// 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_core_proxy.h"
+
+#include <stdlib.h> // For malloc
+
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
+#include "base/time.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/time_conversion.h"
+
+using ppapi::TimeToPPTime;
+using ppapi::TimeTicksToPPTimeTicks;
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+base::MessageLoopProxy* GetMainThreadMessageLoop() {
+ static scoped_refptr<base::MessageLoopProxy> proxy(
+ base::MessageLoopProxy::CreateForCurrentThread());
+ return proxy.get();
+}
+
+void AddRefResource(PP_Resource resource) {
+ PluginResourceTracker::GetInstance()->AddRefResource(resource);
+}
+
+void ReleaseResource(PP_Resource resource) {
+ PluginResourceTracker::GetInstance()->ReleaseResource(resource);
+}
+
+void* MemAlloc(uint32_t num_bytes) {
+ return malloc(num_bytes);
+}
+
+void MemFree(void* ptr) {
+ free(ptr);
+}
+
+double GetTime() {
+ return TimeToPPTime(base::Time::Now());
+}
+
+double GetTimeTicks() {
+ return TimeTicksToPPTimeTicks(base::TimeTicks::Now());
+}
+
+void CallbackWrapper(PP_CompletionCallback callback, int32_t result) {
+ TRACE_EVENT2("ppapi proxy", "CallOnMainThread callback",
+ "Func", reinterpret_cast<void*>(callback.func),
+ "UserData", callback.user_data);
+ PP_RunCompletionCallback(&callback, result);
+}
+
+void CallOnMainThread(int delay_in_ms,
+ PP_CompletionCallback callback,
+ int32_t result) {
+ GetMainThreadMessageLoop()->PostDelayedTask(
+ FROM_HERE,
+ NewRunnableFunction(&CallbackWrapper, callback, result),
+ delay_in_ms);
+}
+
+PP_Bool IsMainThread() {
+ return PP_FromBool(GetMainThreadMessageLoop()->BelongsToCurrentThread());
+}
+
+const PPB_Core core_interface = {
+ &AddRefResource,
+ &ReleaseResource,
+ &GetTime,
+ &GetTimeTicks,
+ &CallOnMainThread,
+ &IsMainThread
+};
+
+InterfaceProxy* CreateCoreProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Core_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_Core_Proxy::PPB_Core_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_Core_Proxy::~PPB_Core_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Core_Proxy::GetInfo() {
+ static const Info info = {
+ &core_interface,
+ PPB_CORE_INTERFACE,
+ INTERFACE_ID_PPB_CORE,
+ false,
+ &CreateCoreProxy,
+ };
+ return &info;
+}
+
+bool PPB_Core_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Core_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCore_AddRefResource,
+ OnMsgAddRefResource)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCore_ReleaseResource,
+ OnMsgReleaseResource)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ // TODO(brettw) handle bad messages!
+ return handled;
+}
+
+void PPB_Core_Proxy::OnMsgAddRefResource(HostResource resource) {
+ ppb_core_target()->AddRefResource(resource.host_resource());
+}
+
+void PPB_Core_Proxy::OnMsgReleaseResource(HostResource resource) {
+ ppb_core_target()->ReleaseResource(resource.host_resource());
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_core_proxy.h b/ppapi/proxy/ppb_core_proxy.h
new file mode 100644
index 0000000..6ad8b31
--- /dev/null
+++ b/ppapi/proxy/ppb_core_proxy.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2010 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_PPB_CORE_PROXY_H_
+#define PPAPI_PPB_CORE_PROXY_H_
+
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_Core;
+
+namespace pp {
+namespace proxy {
+
+class PPB_Core_Proxy : public InterfaceProxy {
+ public:
+ PPB_Core_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_Core_Proxy();
+
+ static const Info* GetInfo();
+
+ const PPB_Core* ppb_core_target() const {
+ return reinterpret_cast<const PPB_Core*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgAddRefResource(HostResource resource);
+ void OnMsgReleaseResource(HostResource resource);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PPB_CORE_PROXY_H_
diff --git a/ppapi/proxy/ppb_crypto_proxy.cc b/ppapi/proxy/ppb_crypto_proxy.cc
new file mode 100644
index 0000000..d900800
--- /dev/null
+++ b/ppapi/proxy/ppb_crypto_proxy.cc
@@ -0,0 +1,54 @@
+// 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_crypto_proxy.h"
+
+#include "ppapi/c/dev/ppb_crypto_dev.h"
+#include "ppapi/proxy/interface_id.h"
+#include "ppapi/shared_impl/crypto_impl.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+const PPB_Crypto_Dev crypto_interface = {
+ &ppapi::CryptoImpl::GetRandomBytes
+};
+
+InterfaceProxy* CreateCryptoProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Crypto_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_Crypto_Proxy::PPB_Crypto_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+ NOTREACHED(); // See comment in the header file.
+}
+
+PPB_Crypto_Proxy::~PPB_Crypto_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Crypto_Proxy::GetInfo() {
+ static const Info info = {
+ &crypto_interface,
+ PPB_CRYPTO_DEV_INTERFACE,
+ INTERFACE_ID_PPB_CRYPTO,
+ false,
+ &CreateCryptoProxy,
+ };
+ return &info;
+}
+
+bool PPB_Crypto_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ NOTREACHED();
+ return false;
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_crypto_proxy.h b/ppapi/proxy/ppb_crypto_proxy.h
new file mode 100644
index 0000000..e801892
--- /dev/null
+++ b/ppapi/proxy/ppb_crypto_proxy.h
@@ -0,0 +1,33 @@
+// 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_CRYPTO_PROXY_H_
+#define PPAPI_PROXY_PPB_CRYPTO_PROXY_H_
+
+#include "ppapi/proxy/interface_proxy.h"
+
+namespace pp {
+namespace proxy {
+
+class PPB_Crypto_Proxy : public InterfaceProxy {
+ public:
+ // This class should not normally be instantiated since there's only one
+ // function that's implemented entirely within the plugin. However, we need
+ // to support this so the machinery for automatically handling interfaces
+ // works. As a result, this constructor will assert if it's actually used.
+ PPB_Crypto_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_Crypto_Proxy();
+
+ static const Info* GetInfo();
+
+ private:
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_Crypto_Proxy);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_CRYPTO_PROXY_H_
diff --git a/ppapi/proxy/ppb_cursor_control_proxy.cc b/ppapi/proxy/ppb_cursor_control_proxy.cc
new file mode 100644
index 0000000..993efe8
--- /dev/null
+++ b/ppapi/proxy/ppb_cursor_control_proxy.cc
@@ -0,0 +1,171 @@
+// 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_cursor_control_proxy.h"
+
+#include "ppapi/c/dev/pp_cursor_type_dev.h"
+#include "ppapi/c/dev/ppb_cursor_control_dev.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::thunk::EnterFunctionNoLock;
+using ppapi::thunk::PPB_CursorControl_FunctionAPI;
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+InterfaceProxy* CreateCursorControlProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_CursorControl_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_CursorControl_Proxy::PPB_CursorControl_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_CursorControl_Proxy::~PPB_CursorControl_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_CursorControl_Proxy::GetInfo() {
+ static const Info info = {
+ ppapi::thunk::GetPPB_CursorControl_Thunk(),
+ PPB_CURSOR_CONTROL_DEV_INTERFACE,
+ INTERFACE_ID_PPB_CURSORCONTROL,
+ false,
+ &CreateCursorControlProxy,
+ };
+ return &info;
+}
+
+ppapi::thunk::PPB_CursorControl_FunctionAPI*
+PPB_CursorControl_Proxy::AsPPB_CursorControl_FunctionAPI() {
+ return this;
+}
+
+PP_Bool PPB_CursorControl_Proxy::SetCursor(PP_Instance instance,
+ PP_CursorType_Dev type,
+ PP_Resource custom_image_id,
+ const PP_Point* hot_spot) {
+ // It's legal for the image ID to be null if the type is not custom.
+ HostResource cursor_image_resource;
+ if (type == PP_CURSORTYPE_CUSTOM) {
+ PluginResource* cursor_image = PluginResourceTracker::GetInstance()->
+ GetResourceObject(custom_image_id);
+ if (!cursor_image || cursor_image->instance() != instance)
+ return PP_FALSE;
+ cursor_image_resource = cursor_image->host_resource();
+ } else {
+ if (custom_image_id)
+ return PP_FALSE; // Image specified for a predefined type.
+ }
+
+ PP_Bool result = PP_FALSE;
+ PP_Point empty_point = { 0, 0 };
+ dispatcher()->Send(new PpapiHostMsg_PPBCursorControl_SetCursor(
+ INTERFACE_ID_PPB_CURSORCONTROL,
+ instance, static_cast<int32_t>(type), cursor_image_resource,
+ hot_spot ? *hot_spot : empty_point, &result));
+ return result;
+}
+
+PP_Bool PPB_CursorControl_Proxy::LockCursor(PP_Instance instance) {
+ PP_Bool result = PP_FALSE;
+ dispatcher()->Send(new PpapiHostMsg_PPBCursorControl_LockCursor(
+ INTERFACE_ID_PPB_CURSORCONTROL, instance, &result));
+ return result;
+}
+
+PP_Bool PPB_CursorControl_Proxy::UnlockCursor(PP_Instance instance) {
+ PP_Bool result = PP_FALSE;
+ dispatcher()->Send(new PpapiHostMsg_PPBCursorControl_UnlockCursor(
+ INTERFACE_ID_PPB_CURSORCONTROL, instance, &result));
+ return result;
+}
+
+PP_Bool PPB_CursorControl_Proxy::HasCursorLock(PP_Instance instance) {
+ PP_Bool result = PP_FALSE;
+ dispatcher()->Send(new PpapiHostMsg_PPBCursorControl_HasCursorLock(
+ INTERFACE_ID_PPB_CURSORCONTROL, instance, &result));
+ return result;
+}
+
+PP_Bool PPB_CursorControl_Proxy::CanLockCursor(PP_Instance instance) {
+ PP_Bool result = PP_FALSE;
+ dispatcher()->Send(new PpapiHostMsg_PPBCursorControl_CanLockCursor(
+ INTERFACE_ID_PPB_CURSORCONTROL, instance, &result));
+ return result;
+}
+
+bool PPB_CursorControl_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_CursorControl_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCursorControl_SetCursor,
+ OnMsgSetCursor)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCursorControl_LockCursor,
+ OnMsgLockCursor)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCursorControl_UnlockCursor,
+ OnMsgUnlockCursor)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCursorControl_HasCursorLock,
+ OnMsgHasCursorLock)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCursorControl_CanLockCursor,
+ OnMsgCanLockCursor)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ // TODO(brettw): handle bad messages!
+ return handled;
+}
+
+void PPB_CursorControl_Proxy::OnMsgSetCursor(PP_Instance instance,
+ int32_t type,
+ HostResource custom_image,
+ const PP_Point& hot_spot,
+ PP_Bool* result) {
+ EnterFunctionNoLock<PPB_CursorControl_FunctionAPI> enter(instance, true);
+ if (enter.succeeded()) {
+ *result = enter.functions()->SetCursor(
+ instance, static_cast<PP_CursorType_Dev>(type),
+ custom_image.host_resource(), &hot_spot);
+ }
+}
+
+void PPB_CursorControl_Proxy::OnMsgLockCursor(PP_Instance instance,
+ PP_Bool* result) {
+ EnterFunctionNoLock<PPB_CursorControl_FunctionAPI> enter(instance, true);
+ if (enter.succeeded())
+ *result = enter.functions()->LockCursor(instance);
+}
+
+void PPB_CursorControl_Proxy::OnMsgUnlockCursor(PP_Instance instance,
+ PP_Bool* result) {
+ EnterFunctionNoLock<PPB_CursorControl_FunctionAPI> enter(instance, true);
+ if (enter.succeeded())
+ *result = enter.functions()->UnlockCursor(instance);
+}
+
+void PPB_CursorControl_Proxy::OnMsgHasCursorLock(PP_Instance instance,
+ PP_Bool* result) {
+ EnterFunctionNoLock<PPB_CursorControl_FunctionAPI> enter(instance, true);
+ if (enter.succeeded())
+ *result = enter.functions()->HasCursorLock(instance);
+}
+
+void PPB_CursorControl_Proxy::OnMsgCanLockCursor(PP_Instance instance,
+ PP_Bool* result) {
+ EnterFunctionNoLock<PPB_CursorControl_FunctionAPI> enter(instance, true);
+ if (enter.succeeded())
+ *result = enter.functions()->CanLockCursor(instance);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_cursor_control_proxy.h b/ppapi/proxy/ppb_cursor_control_proxy.h
new file mode 100644
index 0000000..8657dc9
--- /dev/null
+++ b/ppapi/proxy/ppb_cursor_control_proxy.h
@@ -0,0 +1,70 @@
+// 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_PPB_CURSOR_CONTROL_PROXY_H_
+#define PPAPI_PPB_CURSOR_CONTROL_PROXY_H_
+
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_point.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/shared_impl/function_group_base.h"
+#include "ppapi/thunk/ppb_cursor_control_api.h"
+
+struct PPB_CursorControl_Dev;
+
+namespace pp {
+namespace proxy {
+
+class PPB_CursorControl_Proxy
+ : public ppapi::FunctionGroupBase,
+ public ppapi::thunk::PPB_CursorControl_FunctionAPI,
+ public InterfaceProxy {
+ public:
+ PPB_CursorControl_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_CursorControl_Proxy();
+
+ static const Info* GetInfo();
+
+ // FunctionGroupBase overrides.
+ ppapi::thunk::PPB_CursorControl_FunctionAPI* AsPPB_CursorControl_FunctionAPI()
+ OVERRIDE;
+
+ // PPB_CursorControl_FunctionAPI implementation.
+ virtual PP_Bool SetCursor(PP_Instance instance,
+ PP_CursorType_Dev type,
+ PP_Resource custom_image_id,
+ const PP_Point* hot_spot) OVERRIDE;
+ virtual PP_Bool LockCursor(PP_Instance instance) OVERRIDE;
+ virtual PP_Bool UnlockCursor(PP_Instance instance) OVERRIDE;
+ virtual PP_Bool HasCursorLock(PP_Instance instance) OVERRIDE;
+ virtual PP_Bool CanLockCursor(PP_Instance instance) OVERRIDE;
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+
+ private:
+ // Message handlers.
+ void OnMsgSetCursor(PP_Instance instance,
+ int32_t type,
+ HostResource custom_image,
+ const PP_Point& hot_spot,
+ PP_Bool* result);
+ void OnMsgLockCursor(PP_Instance instance,
+ PP_Bool* result);
+ void OnMsgUnlockCursor(PP_Instance instance,
+ PP_Bool* result);
+ void OnMsgHasCursorLock(PP_Instance instance,
+ PP_Bool* result);
+ void OnMsgCanLockCursor(PP_Instance instance,
+ PP_Bool* result);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PPB_CURSOR_CONTROL_PROXY_H_
diff --git a/ppapi/proxy/ppb_file_chooser_proxy.cc b/ppapi/proxy/ppb_file_chooser_proxy.cc
new file mode 100644
index 0000000..cda175f
--- /dev/null
+++ b/ppapi/proxy/ppb_file_chooser_proxy.cc
@@ -0,0 +1,243 @@
+// 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/enter_proxy.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"
+#include "ppapi/thunk/thunk.h"
+
+using ::ppapi::thunk::PPB_FileChooser_API;
+
+namespace pp {
+namespace proxy {
+
+class FileChooser : public PluginResource,
+ public PPB_FileChooser_API {
+ public:
+ FileChooser(const HostResource& resource);
+ virtual ~FileChooser();
+
+ // ResourceObjectBase overrides.
+ virtual PPB_FileChooser_API* AsPPB_FileChooser_API() OVERRIDE;
+
+ // PPB_FileChooser_API implementation.
+ virtual int32_t Show(PP_CompletionCallback callback) OVERRIDE;
+ virtual PP_Resource GetNextChosenFile() OVERRIDE;
+
+ // Handles the choose complete notification from the host.
+ void ChooseComplete(
+ int32_t result_code,
+ const std::vector<PPBFileRef_CreateInfo>& chosen_files);
+
+ private:
+ 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_;
+
+ 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) {
+ // TODO(brettw) the callbacks at this level should be refactored with a
+ // more automatic tracking system like we have in the renderer.
+ MessageLoop::current()->PostTask(FROM_HERE, NewRunnableFunction(
+ current_show_callback_.func, current_show_callback_.user_data,
+ static_cast<int32_t>(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();
+ }
+}
+
+PPB_FileChooser_API* FileChooser::AsPPB_FileChooser_API() {
+ return this;
+}
+
+int32_t FileChooser::Show(PP_CompletionCallback callback) {
+ if (current_show_callback_.func)
+ return PP_ERROR_INPROGRESS; // Can't show more than once.
+
+ current_show_callback_ = callback;
+ GetDispatcher()->Send(new PpapiHostMsg_PPBFileChooser_Show(
+ INTERFACE_ID_PPB_FILE_CHOOSER, host_resource()));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+PP_Resource FileChooser::GetNextChosenFile() {
+ if (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 = file_queue_.front();
+ file_queue_.pop();
+ return next;
+}
+
+void FileChooser::ChooseComplete(
+ int32_t result_code,
+ const std::vector<PPBFileRef_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]));
+
+ // Notify the plugin of the new data.
+ PP_RunAndClearCompletionCallback(&current_show_callback_, result_code);
+ // DANGER: May delete |this|!
+}
+
+namespace {
+
+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 = {
+ ::ppapi::thunk::GetPPB_FileChooser_Thunk(),
+ PPB_FILECHOOSER_DEV_INTERFACE,
+ INTERFACE_ID_PPB_FILE_CHOOSER,
+ false,
+ &CreateFileChooserProxy,
+ };
+ return &info;
+}
+
+// static
+PP_Resource PPB_FileChooser_Proxy::CreateProxyResource(
+ 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 ? options->accept_mime_types : std::string(),
+ &result));
+
+ if (result.is_null())
+ return 0;
+ linked_ptr<FileChooser> object(new FileChooser(result));
+ return PluginResourceTracker::GetInstance()->AddResource(object);
+}
+
+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_.NewOptionalCallback(
+ &PPB_FileChooser_Proxy::OnShowCallback, chooser);
+
+ int32_t result = ppb_file_chooser_target()->Show(
+ chooser.host_resource(), callback.pp_completion_callback());
+ if (result != PP_OK_COMPLETIONPENDING)
+ callback.Run(result);
+}
+
+void PPB_FileChooser_Proxy::OnMsgChooseComplete(
+ const HostResource& chooser,
+ int32_t result_code,
+ const std::vector<PPBFileRef_CreateInfo>& chosen_files) {
+ EnterPluginFromHostResource<PPB_FileChooser_API> enter(chooser);
+ if (enter.succeeded()) {
+ static_cast<FileChooser*>(enter.object())->ChooseComplete(
+ result_code, chosen_files);
+ }
+}
+
+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..4b83e950
--- /dev/null
+++ b/ppapi/proxy/ppb_file_chooser_proxy.h
@@ -0,0 +1,71 @@
+// 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"
+#include "ppapi/thunk/ppb_file_chooser_api.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();
+
+ static PP_Resource CreateProxyResource(
+ PP_Instance instance,
+ const PP_FileChooserOptions_Dev* options);
+
+ 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..de91996
--- /dev/null
+++ b/ppapi/proxy/ppb_file_ref_proxy.cc
@@ -0,0 +1,303 @@
+// 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/pp_errors.h"
+#include "ppapi/c/ppb_file_ref.h"
+#include "ppapi/c/private/ppb_proxy_private.h"
+#include "ppapi/proxy/enter_proxy.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"
+#include "ppapi/thunk/ppb_file_ref_api.h"
+#include "ppapi/thunk/resource_creation_api.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::thunk::EnterFunctionNoLock;
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_FileRef_API;
+using ppapi::thunk::ResourceCreationAPI;
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+InterfaceProxy* CreateFileRefProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_FileRef_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+class FileRef : public PluginResource, public PPB_FileRef_API {
+ public:
+ explicit FileRef(const PPBFileRef_CreateInfo& info);
+ virtual ~FileRef();
+
+ // ResourceObjectBase overrides.
+ virtual PPB_FileRef_API* AsPPB_FileRef_API() OVERRIDE;
+
+ // PPB_FileRef_API implementation.
+ virtual PP_FileSystemType GetFileSystemType() const OVERRIDE;
+ virtual PP_Var GetName() const OVERRIDE;
+ virtual PP_Var GetPath() const OVERRIDE;
+ virtual PP_Resource GetParent() OVERRIDE;
+ virtual int32_t MakeDirectory(PP_Bool make_ancestors,
+ PP_CompletionCallback callback) OVERRIDE;
+ virtual int32_t Touch(PP_Time last_access_time,
+ PP_Time last_modified_time,
+ PP_CompletionCallback callback) OVERRIDE;
+ virtual int32_t Delete(PP_CompletionCallback callback) OVERRIDE;
+ virtual int32_t Rename(PP_Resource new_file_ref,
+ PP_CompletionCallback callback) OVERRIDE;
+
+ private:
+ PP_FileSystemType 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>(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_);
+}
+
+PPB_FileRef_API* FileRef::AsPPB_FileRef_API() {
+ return this;
+}
+
+PP_FileSystemType FileRef::GetFileSystemType() const {
+ return file_system_type_;
+}
+
+PP_Var FileRef::GetName() const {
+ PluginVarTracker::GetInstance()->AddRef(name_);
+ return name_;
+}
+
+PP_Var FileRef::GetPath() const {
+ PluginVarTracker::GetInstance()->AddRef(path_);
+ return path_;
+}
+
+PP_Resource FileRef::GetParent() {
+ PPBFileRef_CreateInfo create_info;
+ GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_GetParent(
+ INTERFACE_ID_PPB_FILE_REF, host_resource(), &create_info));
+ return PPB_FileRef_Proxy::DeserializeFileRef(create_info);
+}
+
+int32_t FileRef::MakeDirectory(PP_Bool make_ancestors,
+ PP_CompletionCallback callback) {
+ GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_MakeDirectory(
+ INTERFACE_ID_PPB_FILE_REF, host_resource(), make_ancestors,
+ GetDispatcher()->callback_tracker().SendCallback(callback)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileRef::Touch(PP_Time last_access_time,
+ PP_Time last_modified_time,
+ PP_CompletionCallback callback) {
+ GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Touch(
+ INTERFACE_ID_PPB_FILE_REF, host_resource(),
+ last_access_time, last_modified_time,
+ GetDispatcher()->callback_tracker().SendCallback(callback)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileRef::Delete(PP_CompletionCallback callback) {
+ GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Delete(
+ INTERFACE_ID_PPB_FILE_REF, host_resource(),
+ GetDispatcher()->callback_tracker().SendCallback(callback)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileRef::Rename(PP_Resource new_file_ref,
+ PP_CompletionCallback callback) {
+ PluginResource* new_file_ref_object =
+ PluginResourceTracker::GetInstance()->GetResourceObject(new_file_ref);
+ if (!new_file_ref_object ||
+ new_file_ref_object->host_resource().instance() != instance())
+ return PP_ERROR_BADRESOURCE;
+
+ GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Rename(
+ INTERFACE_ID_PPB_FILE_REF, host_resource(),
+ new_file_ref_object->host_resource(),
+ GetDispatcher()->callback_tracker().SendCallback(callback)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+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 = {
+ ::ppapi::thunk::GetPPB_FileRef_Thunk(),
+ PPB_FILEREF_INTERFACE,
+ INTERFACE_ID_PPB_FILE_REF,
+ false,
+ &CreateFileRefProxy,
+ };
+ return &info;
+}
+
+// static
+PP_Resource PPB_FileRef_Proxy::CreateProxyResource(PP_Resource file_system,
+ const char* path) {
+ PluginResource* file_system_object =
+ PluginResourceTracker::GetInstance()->GetResourceObject(file_system);
+ if (!file_system_object)
+ return 0;
+
+ PPBFileRef_CreateInfo create_info;
+ file_system_object->GetDispatcher()->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);
+}
+
+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) {
+ EnterResourceNoLock<PPB_FileRef_API> enter(file_ref, false);
+ if (enter.failed()) {
+ NOTREACHED();
+ return;
+ }
+
+ // 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->ppb_proxy()->GetInstanceForResource(file_ref);
+
+ result->resource.SetHostResource(instance, file_ref);
+ result->file_system_type =
+ static_cast<int>(enter.object()->GetFileSystemType());
+ result->path = SerializedVarReturnValue::Convert(dispatcher(),
+ enter.object()->GetPath());
+ result->name = SerializedVarReturnValue::Convert(dispatcher(),
+ enter.object()->GetName());
+}
+
+// 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) {
+ EnterFunctionNoLock<ResourceCreationAPI> enter(file_system.instance(), true);
+ if (enter.failed())
+ return;
+ PP_Resource resource = enter.functions()->CreateFileRef(
+ 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) {
+ EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource);
+ if (enter.succeeded())
+ SerializeFileRef(enter.object()->GetParent(), result);
+}
+
+void PPB_FileRef_Proxy::OnMsgMakeDirectory(const HostResource& host_resource,
+ PP_Bool make_ancestors,
+ uint32_t serialized_callback) {
+ EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource);
+ if (enter.failed())
+ return;
+ PP_CompletionCallback callback = ReceiveCallback(serialized_callback);
+ int32_t result = enter.object()->MakeDirectory(make_ancestors, callback);
+ if (result != PP_OK_COMPLETIONPENDING)
+ 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) {
+ EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource);
+ if (enter.failed())
+ return;
+ PP_CompletionCallback callback = ReceiveCallback(serialized_callback);
+ int32_t result = enter.object()->Touch(last_access, last_modified, callback);
+ if (result != PP_OK_COMPLETIONPENDING)
+ PP_RunCompletionCallback(&callback, result);
+}
+
+void PPB_FileRef_Proxy::OnMsgDelete(const HostResource& host_resource,
+ uint32_t serialized_callback) {
+ EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource);
+ if (enter.failed())
+ return;
+ PP_CompletionCallback callback = ReceiveCallback(serialized_callback);
+ int32_t result = enter.object()->Delete(callback);
+ if (result != PP_OK_COMPLETIONPENDING)
+ PP_RunCompletionCallback(&callback, result);
+}
+
+void PPB_FileRef_Proxy::OnMsgRename(const HostResource& file_ref,
+ const HostResource& new_file_ref,
+ uint32_t serialized_callback) {
+ EnterHostFromHostResource<PPB_FileRef_API> enter(file_ref);
+ if (enter.failed())
+ return;
+ PP_CompletionCallback callback = ReceiveCallback(serialized_callback);
+ int32_t result = enter.object()->Rename(new_file_ref.host_resource(),
+ callback);
+ if (result != PP_OK_COMPLETIONPENDING)
+ 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..076bea2
--- /dev/null
+++ b/ppapi/proxy/ppb_file_ref_proxy.h
@@ -0,0 +1,85 @@
+// 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();
+
+ static PP_Resource CreateProxyResource(PP_Resource file_system,
+ const char* path);
+
+ // 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_file_system_proxy.cc b/ppapi/proxy/ppb_file_system_proxy.cc
new file mode 100644
index 0000000..1edf5d7
--- /dev/null
+++ b/ppapi/proxy/ppb_file_system_proxy.cc
@@ -0,0 +1,205 @@
+// 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_system_proxy.h"
+
+#include "base/message_loop.h"
+#include "base/task.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_file_system.h"
+#include "ppapi/proxy/enter_proxy.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"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_file_system_api.h"
+#include "ppapi/thunk/resource_creation_api.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::thunk::EnterFunctionNoLock;
+using ppapi::thunk::PPB_FileSystem_API;
+using ppapi::thunk::ResourceCreationAPI;
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+InterfaceProxy* CreateFileSystemProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_FileSystem_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+// 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 FileSystem : public PluginResource, public PPB_FileSystem_API {
+ public:
+ FileSystem(const HostResource& host_resource, PP_FileSystemType type);
+ virtual ~FileSystem();
+
+ // ResourceObjectBase override.
+ virtual PPB_FileSystem_API* AsPPB_FileSystem_API() OVERRIDE;
+
+ // PPB_FileSystem_APi implementation.
+ virtual int32_t Open(int64_t expected_size,
+ PP_CompletionCallback callback) OVERRIDE;
+ virtual PP_FileSystemType GetType() OVERRIDE;
+
+ // Called when the host has responded to our open request.
+ void OpenComplete(int32_t result);
+
+ private:
+ PP_FileSystemType type_;
+ bool called_open_;
+ PP_CompletionCallback current_open_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileSystem);
+};
+
+FileSystem::FileSystem(const HostResource& host_resource,
+ PP_FileSystemType type)
+ : PluginResource(host_resource),
+ type_(type),
+ called_open_(false),
+ current_open_callback_(PP_MakeCompletionCallback(NULL, NULL)) {
+}
+
+// TODO(brettw) this logic is duplicated with some other resource objects
+// like FileChooser. It would be nice to look at all of the different resources
+// that need callback tracking and design something that they can all re-use.
+FileSystem::~FileSystem() {
+ // Ensure the callback is always fired.
+ if (current_open_callback_.func) {
+ // TODO(brettw) the callbacks at this level should be refactored with a
+ // more automatic tracking system like we have in the renderer.
+ MessageLoop::current()->PostTask(FROM_HERE, NewRunnableFunction(
+ current_open_callback_.func, current_open_callback_.user_data,
+ static_cast<int32_t>(PP_ERROR_ABORTED)));
+ }
+}
+
+PPB_FileSystem_API* FileSystem::AsPPB_FileSystem_API() {
+ return this;
+}
+
+int32_t FileSystem::Open(int64_t expected_size,
+ PP_CompletionCallback callback) {
+ if (current_open_callback_.func)
+ return PP_ERROR_INPROGRESS;
+ if (called_open_)
+ return PP_ERROR_FAILED;
+
+ current_open_callback_ = callback;
+ called_open_ = true;
+ GetDispatcher()->Send(new PpapiHostMsg_PPBFileSystem_Open(
+ INTERFACE_ID_PPB_FILE_SYSTEM, host_resource(), expected_size));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+PP_FileSystemType FileSystem::GetType() {
+ return type_;
+}
+
+void FileSystem::OpenComplete(int32_t result) {
+ PP_RunAndClearCompletionCallback(&current_open_callback_, result);
+}
+
+PPB_FileSystem_Proxy::PPB_FileSystem_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface),
+ callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+}
+
+PPB_FileSystem_Proxy::~PPB_FileSystem_Proxy() {
+}
+
+const InterfaceProxy::Info* PPB_FileSystem_Proxy::GetInfo() {
+ static const Info info = {
+ ::ppapi::thunk::GetPPB_FileSystem_Thunk(),
+ PPB_FILESYSTEM_INTERFACE,
+ INTERFACE_ID_PPB_FILE_SYSTEM,
+ false,
+ &CreateFileSystemProxy,
+ };
+ return &info;
+}
+
+// static
+PP_Resource PPB_FileSystem_Proxy::CreateProxyResource(
+ PP_Instance instance,
+ PP_FileSystemType type) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return PP_ERROR_BADARGUMENT;
+
+ HostResource result;
+ dispatcher->Send(new PpapiHostMsg_PPBFileSystem_Create(
+ INTERFACE_ID_PPB_FILE_SYSTEM, instance, type, &result));
+ if (result.is_null())
+ return 0;
+
+ linked_ptr<FileSystem> object(new FileSystem(result, type));
+ return PluginResourceTracker::GetInstance()->AddResource(object);
+}
+
+bool PPB_FileSystem_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_FileSystem_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileSystem_Create, OnMsgCreate)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileSystem_Open, OnMsgOpen)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileSystem_OpenComplete, OnMsgOpenComplete)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPB_FileSystem_Proxy::OnMsgCreate(PP_Instance instance,
+ int type,
+ HostResource* result) {
+ EnterFunctionNoLock<ResourceCreationAPI> enter(instance, true);
+ if (enter.failed())
+ return;
+ PP_Resource resource = enter.functions()->CreateFileSystem(
+ instance, static_cast<PP_FileSystemType>(type));
+ if (!resource)
+ return; // CreateInfo default constructor initializes to 0.
+ result->SetHostResource(instance, resource);
+}
+
+void PPB_FileSystem_Proxy::OnMsgOpen(const HostResource& host_resource,
+ int64_t expected_size) {
+ EnterHostFromHostResource<PPB_FileSystem_API> enter(host_resource);
+ if (enter.failed())
+ return;
+
+ CompletionCallback callback = callback_factory_.NewOptionalCallback(
+ &PPB_FileSystem_Proxy::OpenCompleteInHost, host_resource);
+ int32_t result = enter.object()->Open(expected_size,
+ callback.pp_completion_callback());
+ if (result != PP_OK_COMPLETIONPENDING)
+ callback.Run(result);
+}
+
+// Called in the plugin to handle the open callback.
+void PPB_FileSystem_Proxy::OnMsgOpenComplete(const HostResource& host_resource,
+ int32_t result) {
+ EnterPluginFromHostResource<PPB_FileSystem_API> enter(host_resource);
+ if (enter.succeeded())
+ static_cast<FileSystem*>(enter.object())->OpenComplete(result);
+}
+
+void PPB_FileSystem_Proxy::OpenCompleteInHost(
+ int32_t result,
+ const HostResource& host_resource) {
+ dispatcher()->Send(new PpapiMsg_PPBFileSystem_OpenComplete(
+ INTERFACE_ID_PPB_FILE_SYSTEM, host_resource, result));
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_file_system_proxy.h b/ppapi/proxy/ppb_file_system_proxy.h
new file mode 100644
index 0000000..dcf94b3
--- /dev/null
+++ b/ppapi/proxy/ppb_file_system_proxy.h
@@ -0,0 +1,61 @@
+// 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_SYSTEM_PROXY_H_
+#define PPAPI_PROXY_PPB_FILE_SYSTEM_PROXY_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_time.h"
+#include "ppapi/c/ppb_file_system.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_FileSystem_Dev;
+
+namespace pp {
+namespace proxy {
+
+class HostResource;
+
+class PPB_FileSystem_Proxy : public InterfaceProxy {
+ public:
+ PPB_FileSystem_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_FileSystem_Proxy();
+
+ static const Info* GetInfo();
+
+ static PP_Resource CreateProxyResource(PP_Instance instance,
+ PP_FileSystemType type);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgCreate(PP_Instance instance,
+ int type,
+ HostResource* result);
+ void OnMsgOpen(const HostResource& filesystem,
+ int64_t expected_size);
+
+ void OnMsgOpenComplete(const HostResource& filesystem,
+ int32_t result);
+
+ void OpenCompleteInHost(int32_t result, const HostResource& host_resource);
+
+ CompletionCallbackFactory<PPB_FileSystem_Proxy,
+ ProxyNonThreadSafeRefCount> callback_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_FileSystem_Proxy);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_FILE_SYSTEM_PROXY_H_
diff --git a/ppapi/proxy/ppb_flash_clipboard_proxy.cc b/ppapi/proxy/ppb_flash_clipboard_proxy.cc
new file mode 100644
index 0000000..8dc98ff
--- /dev/null
+++ b/ppapi/proxy/ppb_flash_clipboard_proxy.cc
@@ -0,0 +1,165 @@
+// 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_flash_clipboard_proxy.h"
+
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/private/ppb_flash_clipboard.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/serialized_var.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+bool IsValidClipboardType(PP_Flash_Clipboard_Type clipboard_type) {
+ return clipboard_type == PP_FLASH_CLIPBOARD_TYPE_STANDARD ||
+ clipboard_type == PP_FLASH_CLIPBOARD_TYPE_SELECTION ||
+ clipboard_type == PP_FLASH_CLIPBOARD_TYPE_DRAG;
+}
+
+bool IsValidClipboardFormat(PP_Flash_Clipboard_Format format) {
+ // Purposely excludes |PP_FLASH_CLIPBOARD_FORMAT_INVALID|.
+ return format == PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT ||
+ format == PP_FLASH_CLIPBOARD_FORMAT_HTML;
+}
+
+PP_Bool IsFormatAvailable(PP_Instance instance_id,
+ PP_Flash_Clipboard_Type clipboard_type,
+ PP_Flash_Clipboard_Format format) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id);
+ if (!dispatcher)
+ return PP_FALSE;
+
+ if (!IsValidClipboardType(clipboard_type) || !IsValidClipboardFormat(format))
+ return PP_FALSE;
+
+ bool result = false;
+ dispatcher->Send(new PpapiHostMsg_PPBFlashClipboard_IsFormatAvailable(
+ INTERFACE_ID_PPB_FLASH_CLIPBOARD,
+ instance_id,
+ static_cast<int>(clipboard_type),
+ static_cast<int>(format),
+ &result));
+ return PP_FromBool(result);
+}
+
+PP_Var ReadPlainText(PP_Instance instance_id,
+ PP_Flash_Clipboard_Type clipboard_type) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id);
+ if (!dispatcher)
+ return PP_MakeUndefined();
+
+ if (!IsValidClipboardType(clipboard_type))
+ return PP_MakeUndefined();
+
+ ReceiveSerializedVarReturnValue result;
+ dispatcher->Send(new PpapiHostMsg_PPBFlashClipboard_ReadPlainText(
+ INTERFACE_ID_PPB_FLASH_CLIPBOARD, instance_id,
+ static_cast<int>(clipboard_type), &result));
+ return result.Return(dispatcher);
+}
+
+int32_t WritePlainText(PP_Instance instance_id,
+ PP_Flash_Clipboard_Type clipboard_type,
+ PP_Var text) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id);
+ if (!dispatcher)
+ return PP_ERROR_BADARGUMENT;
+
+ if (!IsValidClipboardType(clipboard_type))
+ return PP_ERROR_BADARGUMENT;
+
+ dispatcher->Send(new PpapiHostMsg_PPBFlashClipboard_WritePlainText(
+ INTERFACE_ID_PPB_FLASH_CLIPBOARD,
+ instance_id,
+ static_cast<int>(clipboard_type),
+ SerializedVarSendInput(dispatcher, text)));
+ // Assume success, since it allows us to avoid a sync IPC.
+ return PP_OK;
+}
+
+const PPB_Flash_Clipboard flash_clipboard_interface = {
+ &IsFormatAvailable,
+ &ReadPlainText,
+ &WritePlainText
+};
+
+InterfaceProxy* CreateFlashClipboardProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Flash_Clipboard_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_Flash_Clipboard_Proxy::PPB_Flash_Clipboard_Proxy(
+ Dispatcher* dispatcher, const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_Flash_Clipboard_Proxy::~PPB_Flash_Clipboard_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Flash_Clipboard_Proxy::GetInfo() {
+ static const Info info = {
+ &flash_clipboard_interface,
+ PPB_FLASH_CLIPBOARD_INTERFACE,
+ INTERFACE_ID_PPB_FLASH_CLIPBOARD,
+ false,
+ &CreateFlashClipboardProxy
+ };
+ return &info;
+}
+
+bool PPB_Flash_Clipboard_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Flash_Clipboard_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashClipboard_IsFormatAvailable,
+ OnMsgIsFormatAvailable)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashClipboard_ReadPlainText,
+ OnMsgReadPlainText)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashClipboard_WritePlainText,
+ OnMsgWritePlainText)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPB_Flash_Clipboard_Proxy::OnMsgIsFormatAvailable(
+ PP_Instance instance_id,
+ int clipboard_type,
+ int format,
+ bool* result) {
+ *result = PP_ToBool(ppb_flash_clipboard_target()->IsFormatAvailable(
+ instance_id,
+ static_cast<PP_Flash_Clipboard_Type>(clipboard_type),
+ static_cast<PP_Flash_Clipboard_Format>(format)));
+}
+
+void PPB_Flash_Clipboard_Proxy::OnMsgReadPlainText(
+ PP_Instance instance_id,
+ int clipboard_type,
+ SerializedVarReturnValue result) {
+ result.Return(dispatcher(),
+ ppb_flash_clipboard_target()->ReadPlainText(
+ instance_id,
+ static_cast<PP_Flash_Clipboard_Type>(clipboard_type)));
+}
+
+void PPB_Flash_Clipboard_Proxy::OnMsgWritePlainText(
+ PP_Instance instance_id,
+ int clipboard_type,
+ SerializedVarReceiveInput text) {
+ int32_t result = ppb_flash_clipboard_target()->WritePlainText(
+ instance_id,
+ static_cast<PP_Flash_Clipboard_Type>(clipboard_type),
+ text.Get(dispatcher()));
+ LOG_IF(WARNING, result != PP_OK) << "Write to clipboard failed unexpectedly.";
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_flash_clipboard_proxy.h b/ppapi/proxy/ppb_flash_clipboard_proxy.h
new file mode 100644
index 0000000..6d9604f
--- /dev/null
+++ b/ppapi/proxy/ppb_flash_clipboard_proxy.h
@@ -0,0 +1,51 @@
+// 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_FLASH_CLIPBOARD_PROXY_H_
+#define PPAPI_PROXY_PPB_FLASH_CLIPBOARD_PROXY_H_
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_Flash_Clipboard;
+
+namespace pp {
+namespace proxy {
+
+class SerializedVarReceiveInput;
+class SerializedVarReturnValue;
+
+class PPB_Flash_Clipboard_Proxy : public InterfaceProxy {
+ public:
+ PPB_Flash_Clipboard_Proxy(Dispatcher* dispatcher,
+ const void* target_interface);
+ virtual ~PPB_Flash_Clipboard_Proxy();
+
+ static const Info* GetInfo();
+
+ const PPB_Flash_Clipboard* ppb_flash_clipboard_target() const {
+ return reinterpret_cast<const PPB_Flash_Clipboard*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgIsFormatAvailable(PP_Instance instance_id,
+ int clipboard_type,
+ int format,
+ bool* result);
+ void OnMsgReadPlainText(PP_Instance instance_id,
+ int clipboard_type,
+ SerializedVarReturnValue result);
+ void OnMsgWritePlainText(PP_Instance instance_id,
+ int clipboard_type,
+ SerializedVarReceiveInput text);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_FLASH_CLIPBOARD_PROXY_H_
diff --git a/ppapi/proxy/ppb_flash_file_proxy.cc b/ppapi/proxy/ppb_flash_file_proxy.cc
new file mode 100644
index 0000000..7b6dc2d
--- /dev/null
+++ b/ppapi/proxy/ppb_flash_file_proxy.cc
@@ -0,0 +1,732 @@
+// 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_flash_file_proxy.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/message_loop_proxy.h"
+#include "base/synchronization/lock.h"
+#include "base/synchronization/waitable_event.h"
+#include "build/build_config.h"
+#include "ipc/ipc_channel_proxy.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_sync_message.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_file_info.h"
+#include "ppapi/c/private/ppb_flash_file.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+// Given an error code and a handle result from a Pepper API call, converts to a
+// PlatformFileForTransit by sharing with the other side, closing the original
+// handle, possibly also updating the error value if an error occurred.
+IPC::PlatformFileForTransit PlatformFileToPlatformFileForTransit(
+ Dispatcher* dispatcher,
+ int32_t* error,
+ base::PlatformFile file) {
+ if (*error != PP_OK)
+ return IPC::InvalidPlatformFileForTransit();
+ IPC::PlatformFileForTransit out_handle =
+ dispatcher->ShareHandleWithRemote(file, true);
+ if (out_handle == IPC::InvalidPlatformFileForTransit())
+ *error = PP_ERROR_NOACCESS;
+ return out_handle;
+}
+
+void FreeDirContents(PP_Instance /* instance */,
+ PP_DirContents_Dev* contents) {
+ for (int32_t i = 0; i < contents->count; ++i)
+ delete[] contents->entries[i].name;
+ delete[] contents->entries;
+ delete contents;
+}
+
+} // namespace
+
+// ModuleLocalThreadAdapter ----------------------------------------------------
+
+class ModuleLocalThreadAdapter
+ : public base::RefCountedThreadSafe<ModuleLocalThreadAdapter> {
+ class Filter;
+ public:
+ ModuleLocalThreadAdapter();
+
+ void AddInstanceRouting(PP_Instance instance, Dispatcher* dispatcher);
+ void ClearInstanceRouting(PP_Instance instance);
+ void ClearFilter(Dispatcher* dispatcher, Filter* filter);
+
+ bool OnModuleLocalMessageReceived(const IPC::Message& msg);
+
+ // Called on the I/O thread when the channel is being destroyed and the
+ // given message will never be issued a reply.
+ void OnModuleLocalMessageFailed(int message_id);
+
+ bool Send(PP_Instance instance, IPC::Message* msg);
+
+ private:
+ class Filter : public IPC::ChannelProxy::MessageFilter {
+ public:
+ explicit Filter(Dispatcher* dispatcher);
+ ~Filter();
+
+ void Send(IPC::Message* msg);
+
+ virtual void OnFilterAdded(IPC::Channel* channel);
+ virtual void OnFilterRemoved();
+ virtual bool OnMessageReceived(const IPC::Message& message);
+
+ private:
+ // DO NOT DEREFERENCE! This is used only for tracking.
+ Dispatcher* dispatcher_;
+
+ IPC::Channel* channel_;
+
+ // Holds the IPC messages that were sent before the channel was connected.
+ // These will be sent ASAP.
+ std::vector<IPC::Message*> pre_connect_pending_messages_;
+
+ // Holds the IDs of the sync messages we're currently waiting on for this
+ // channel. This tracking allows us to cancel those requests if the
+ // remote process crashes and we're cleaning up this filter (without just
+ // deadlocking the waiting thread(s).
+ std::set<int> pending_requests_for_filter_;
+ };
+
+ void SendFromIOThread(Dispatcher* dispatcher, IPC::Message* msg);
+
+ // Internal version of OnModuleLocalMessageFailed which assumes the lock
+ // is already held.
+ void OnModuleLocalMessageFailedLocked(int message_id);
+
+ base::Lock lock_;
+
+ scoped_refptr<base::MessageLoopProxy> main_thread_;
+
+ // Will be NULL before an instance routing is added.
+ scoped_refptr<base::MessageLoopProxy> io_thread_;
+
+ typedef std::map<PP_Instance, Dispatcher*> InstanceToDispatcher;
+ InstanceToDispatcher instance_to_dispatcher_;
+
+ // The filters are owned by the channel.
+ typedef std::map<Dispatcher*, Filter*> DispatcherToFilter;
+ DispatcherToFilter dispatcher_to_filter_;
+
+ // Tracks all messages with currently waiting threads. This does not own
+ // the pointer, the pointer lifetime is managed by Send().
+ typedef std::map<int, IPC::PendingSyncMsg*> SyncRequestMap;
+ SyncRequestMap pending_sync_requests_;
+};
+
+ModuleLocalThreadAdapter* g_module_local_thread_adapter = NULL;
+
+ModuleLocalThreadAdapter::Filter::Filter(Dispatcher* dispatcher)
+ : dispatcher_(dispatcher), channel_(NULL) {
+}
+
+ModuleLocalThreadAdapter::Filter::~Filter() {
+}
+
+void ModuleLocalThreadAdapter::Filter::Send(IPC::Message* msg) {
+ if (channel_) {
+ int message_id = IPC::SyncMessage::GetMessageId(*msg);
+ if (channel_->Send(msg))
+ pending_requests_for_filter_.insert(message_id);
+ else // Message lost, notify adapter so it can unblock.
+ g_module_local_thread_adapter->OnModuleLocalMessageFailed(message_id);
+ } else {
+ // No channel, save this message for when it's connected.
+ pre_connect_pending_messages_.push_back(msg);
+ }
+}
+
+void ModuleLocalThreadAdapter::Filter::OnFilterAdded(IPC::Channel* channel) {
+ DCHECK(!channel_);
+ channel_ = channel;
+
+ // Now that we have a channel, process all pending messages.
+ for (size_t i = 0; i < pre_connect_pending_messages_.size(); i++)
+ Send(pre_connect_pending_messages_[i]);
+ pre_connect_pending_messages_.clear();
+}
+
+void ModuleLocalThreadAdapter::Filter::OnFilterRemoved() {
+ DCHECK(channel_);
+ channel_ = NULL;
+ g_module_local_thread_adapter->ClearFilter(dispatcher_, this);
+
+ for (std::set<int>::iterator i = pending_requests_for_filter_.begin();
+ i != pending_requests_for_filter_.end(); ++i) {
+ g_module_local_thread_adapter->OnModuleLocalMessageFailed(*i);
+ }
+}
+
+bool ModuleLocalThreadAdapter::Filter::OnMessageReceived(
+ const IPC::Message& message) {
+ if (!message.is_reply() ||
+ message.routing_id() != INTERFACE_ID_PPB_FLASH_FILE_MODULELOCAL)
+ return false;
+
+ if (g_module_local_thread_adapter->OnModuleLocalMessageReceived(message)) {
+ // The message was consumed, this means we can remove the message ID from
+ // the list of messages this channel is waiting on.
+ pending_requests_for_filter_.erase(IPC::SyncMessage::GetMessageId(message));
+ return true;
+ }
+ return false;
+}
+
+ModuleLocalThreadAdapter::ModuleLocalThreadAdapter()
+ : main_thread_(base::MessageLoopProxy::CreateForCurrentThread()) {
+}
+
+void ModuleLocalThreadAdapter::AddInstanceRouting(PP_Instance instance,
+ Dispatcher* dispatcher) {
+ base::AutoLock lock(lock_);
+
+ // Now that we've had contact with a dispatcher, we can set up the IO thread.
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ if (!io_thread_.get())
+ io_thread_ = dispatcher->GetIPCMessageLoop();
+
+ // Set up the instance -> dispatcher routing.
+ DCHECK(instance_to_dispatcher_.find(instance) ==
+ instance_to_dispatcher_.end());
+ instance_to_dispatcher_[instance] = dispatcher;
+
+ DispatcherToFilter::iterator found_filter =
+ dispatcher_to_filter_.find(dispatcher);
+ if (found_filter == dispatcher_to_filter_.end()) {
+ // Need to set up a filter for this dispatcher to intercept the messages.
+ Filter* filter = new Filter(dispatcher);
+ dispatcher_to_filter_[dispatcher] = filter;
+ dispatcher->AddIOThreadMessageFilter(filter);
+ }
+}
+
+void ModuleLocalThreadAdapter::ClearInstanceRouting(PP_Instance instance) {
+ // The dispatcher->filter mapping is cleaned up by ClearFilter which is
+ // initiated by the channel.
+ instance_to_dispatcher_.erase(instance);
+}
+
+void ModuleLocalThreadAdapter::ClearFilter(Dispatcher* dispatcher,
+ Filter* filter) {
+ // DANGER! Don't dereference the dispatcher, it's just used to identify
+ // which filter to remove. The dispatcher may not even exist any more.
+ //
+ // Since the dispatcher may be gone, there's a potential for ambiguity if
+ // another one is created on the main thread before this code runs on the
+ // I/O thread. So we check that the filter matches to avoid this rare case.
+ base::AutoLock lock(lock_);
+ if (dispatcher_to_filter_[dispatcher] == filter)
+ dispatcher_to_filter_.erase(dispatcher);
+}
+
+bool ModuleLocalThreadAdapter::OnModuleLocalMessageReceived(
+ const IPC::Message& msg) {
+ base::AutoLock lock(lock_);
+
+ int message_id = IPC::SyncMessage::GetMessageId(msg);
+ SyncRequestMap::iterator found = pending_sync_requests_.find(message_id);
+ if (found == pending_sync_requests_.end()) {
+ // Not waiting for this event. This will happen for sync messages to the
+ // main thread which use the "regular" sync channel code path.
+ return false;
+ }
+
+ IPC::PendingSyncMsg& info = *found->second;
+
+ if (!msg.is_reply_error())
+ info.deserializer->SerializeOutputParameters(msg);
+ info.done_event->Signal();
+ return true;
+}
+
+void ModuleLocalThreadAdapter::OnModuleLocalMessageFailed(int message_id) {
+ base::AutoLock lock(lock_);
+ OnModuleLocalMessageFailedLocked(message_id);
+}
+
+bool ModuleLocalThreadAdapter::Send(PP_Instance instance, IPC::Message* msg) {
+ // Compute the dispatcher corresponding to this message.
+ Dispatcher* dispatcher = NULL;
+ {
+ base::AutoLock lock(lock_);
+ InstanceToDispatcher::iterator found =
+ instance_to_dispatcher_.find(instance);
+ if (found == instance_to_dispatcher_.end()) {
+ NOTREACHED();
+ delete msg;
+ return false;
+ }
+ dispatcher = found->second;
+ }
+
+ if (main_thread_->BelongsToCurrentThread()) {
+ // Easy case: We're on the same thread as the dispatcher, so we don't need
+ // a lock to access it, and we can just use the normal sync channel stuff
+ // to handle the message. Actually, we MUST use the normal sync channel
+ // stuff since there may be incoming sync messages that need processing.
+ // The code below doesn't handle any nested message loops.
+ return dispatcher->Send(msg);
+ }
+
+ // Background thread case
+ // ----------------------
+ // 1. Generate tracking info, stick in pending_sync_messages_map.
+ // 2. Kick off the request. This is done on the I/O thread.
+ // 3. Filter on the I/O thread notices reply, writes the reply data and
+ // signals the event. We block on the event while this is happening.
+ // 4. Remove tracking info.
+
+ // Generate the tracking info. and copied
+ IPC::SyncMessage* sync_msg = static_cast<IPC::SyncMessage*>(msg);
+ int message_id = IPC::SyncMessage::GetMessageId(*sync_msg);
+ base::WaitableEvent event(true, false);
+ scoped_ptr<IPC::MessageReplyDeserializer> deserializer(
+ sync_msg->GetReplyDeserializer()); // We own this pointer once retrieved.
+ IPC::PendingSyncMsg info(message_id, deserializer.get(), &event);
+
+ // Add the tracking information to our map.
+ {
+ base::AutoLock lock(lock_);
+ pending_sync_requests_[message_id] = &info;
+ }
+
+ // This is a bit dangerous. We use the dispatcher pointer as the routing
+ // ID for this message. While we don't dereference it, there is an
+ // exceedingly remote possibility that while this is going to the background
+ // thread the connection will be shut down and a new one will be created with
+ // a dispatcher at the same address. It could potentially get sent to a
+ // random place, but it should actually still work (since the Flash file
+ // operations are global).
+ io_thread_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &ModuleLocalThreadAdapter::SendFromIOThread,
+ dispatcher, msg));
+
+ // Now we block the current thread waiting for the reply.
+ event.Wait();
+
+ {
+ // Clear our tracking info for this message now that we're done.
+ base::AutoLock lock(lock_);
+ DCHECK(pending_sync_requests_.find(message_id) !=
+ pending_sync_requests_.end());
+ pending_sync_requests_.erase(message_id);
+ }
+
+ return true;
+}
+
+void ModuleLocalThreadAdapter::SendFromIOThread(Dispatcher* dispatcher,
+ IPC::Message* msg) {
+ // DO NOT DEREFERENCE DISPATCHER. Used as a lookup only.
+ base::AutoLock lock(lock_);
+ DispatcherToFilter::iterator found = dispatcher_to_filter_.find(dispatcher);
+
+ // The dispatcher could have been destroyed by the time we got here since
+ // we're on another thread. Need to unblock the caller.
+ if (found == dispatcher_to_filter_.end()) {
+ OnModuleLocalMessageFailedLocked(IPC::SyncMessage::GetMessageId(*msg));
+ delete msg;
+ return;
+ }
+
+ // Takes ownership of pointer.
+ found->second->Send(msg);
+}
+
+void ModuleLocalThreadAdapter::OnModuleLocalMessageFailedLocked(
+ int message_id) {
+ lock_.AssertAcquired();
+
+ // Unblock the thread waiting for the message that will never come.
+ SyncRequestMap::iterator found = pending_sync_requests_.find(message_id);
+ if (found == pending_sync_requests_.end()) {
+ NOTREACHED();
+ return;
+ }
+ found->second->done_event->Signal();
+}
+
+// PPB_Flash_File_ModuleLocal --------------------------------------------------
+
+namespace {
+
+bool CreateThreadAdapterForInstance(PP_Instance instance) {
+ if (!g_module_local_thread_adapter) {
+ g_module_local_thread_adapter = new ModuleLocalThreadAdapter();
+ g_module_local_thread_adapter->AddRef(); // Leaked, this object is global.
+ }
+
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher) {
+ NOTREACHED();
+ return false;
+ }
+ g_module_local_thread_adapter->AddInstanceRouting(instance, dispatcher);
+ return true;
+}
+
+void ClearThreadAdapterForInstance(PP_Instance instance) {
+ if (g_module_local_thread_adapter)
+ g_module_local_thread_adapter->ClearInstanceRouting(instance);
+}
+
+int32_t OpenModuleLocalFile(PP_Instance instance,
+ const char* path,
+ int32_t mode,
+ PP_FileHandle* file) {
+ if (!g_module_local_thread_adapter)
+ return PP_ERROR_FAILED;
+
+ int32_t result = PP_ERROR_FAILED;
+ IPC::PlatformFileForTransit transit;
+ g_module_local_thread_adapter->Send(instance,
+ new PpapiHostMsg_PPBFlashFile_ModuleLocal_OpenFile(
+ INTERFACE_ID_PPB_FLASH_FILE_MODULELOCAL,
+ instance, path, mode, &transit, &result));
+ *file = IPC::PlatformFileForTransitToPlatformFile(transit);
+ return result;
+}
+
+int32_t RenameModuleLocalFile(PP_Instance instance,
+ const char* from_path,
+ const char* to_path) {
+ if (!g_module_local_thread_adapter)
+ return PP_ERROR_FAILED;
+
+ int32_t result = PP_ERROR_FAILED;
+ g_module_local_thread_adapter->Send(instance,
+ new PpapiHostMsg_PPBFlashFile_ModuleLocal_RenameFile(
+ INTERFACE_ID_PPB_FLASH_FILE_MODULELOCAL,
+ instance, from_path, to_path, &result));
+ return result;
+}
+
+int32_t DeleteModuleLocalFileOrDir(PP_Instance instance,
+ const char* path,
+ PP_Bool recursive) {
+ if (!g_module_local_thread_adapter)
+ return PP_ERROR_FAILED;
+
+ int32_t result = PP_ERROR_FAILED;
+ g_module_local_thread_adapter->Send(instance,
+ new PpapiHostMsg_PPBFlashFile_ModuleLocal_DeleteFileOrDir(
+ INTERFACE_ID_PPB_FLASH_FILE_MODULELOCAL,
+ instance, path, recursive, &result));
+ return result;
+}
+
+int32_t CreateModuleLocalDir(PP_Instance instance, const char* path) {
+ if (!g_module_local_thread_adapter)
+ return PP_ERROR_FAILED;
+
+ int32_t result = PP_ERROR_FAILED;
+ g_module_local_thread_adapter->Send(instance,
+ new PpapiHostMsg_PPBFlashFile_ModuleLocal_CreateDir(
+ INTERFACE_ID_PPB_FLASH_FILE_MODULELOCAL, instance, path, &result));
+ return result;
+}
+
+int32_t QueryModuleLocalFile(PP_Instance instance,
+ const char* path,
+ PP_FileInfo* info) {
+ if (!g_module_local_thread_adapter)
+ return PP_ERROR_FAILED;
+
+ int32_t result = PP_ERROR_FAILED;
+ g_module_local_thread_adapter->Send(instance,
+ new PpapiHostMsg_PPBFlashFile_ModuleLocal_QueryFile(
+ INTERFACE_ID_PPB_FLASH_FILE_MODULELOCAL, instance, path,
+ info, &result));
+ return result;
+}
+
+int32_t GetModuleLocalDirContents(PP_Instance instance,
+ const char* path,
+ PP_DirContents_Dev** contents) {
+ if (!g_module_local_thread_adapter)
+ return PP_ERROR_FAILED;
+
+ int32_t result = PP_ERROR_FAILED;
+ std::vector<SerializedDirEntry> entries;
+ g_module_local_thread_adapter->Send(instance,
+ new PpapiHostMsg_PPBFlashFile_ModuleLocal_GetDirContents(
+ INTERFACE_ID_PPB_FLASH_FILE_MODULELOCAL,
+ instance, path, &entries, &result));
+
+ if (result != PP_OK)
+ return result;
+
+ // Copy the serialized dir entries to the output struct.
+ *contents = new PP_DirContents_Dev;
+ (*contents)->count = static_cast<int32_t>(entries.size());
+ (*contents)->entries = new PP_DirEntry_Dev[entries.size()];
+ for (size_t i = 0; i < entries.size(); i++) {
+ const SerializedDirEntry& source = entries[i];
+ PP_DirEntry_Dev* dest = &(*contents)->entries[i];
+
+ char* name_copy = new char[source.name.size() + 1];
+ memcpy(name_copy, source.name.c_str(), source.name.size() + 1);
+ dest->name = name_copy;
+ dest->is_dir = PP_FromBool(source.is_dir);
+ }
+
+ return result;
+}
+
+const PPB_Flash_File_ModuleLocal flash_file_modulelocal_interface = {
+ &CreateThreadAdapterForInstance,
+ &ClearThreadAdapterForInstance,
+ &OpenModuleLocalFile,
+ &RenameModuleLocalFile,
+ &DeleteModuleLocalFileOrDir,
+ &CreateModuleLocalDir,
+ &QueryModuleLocalFile,
+ &GetModuleLocalDirContents,
+ &FreeDirContents,
+};
+
+InterfaceProxy* CreateFlashFileModuleLocalProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Flash_File_ModuleLocal_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_Flash_File_ModuleLocal_Proxy::PPB_Flash_File_ModuleLocal_Proxy(
+ Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_Flash_File_ModuleLocal_Proxy::~PPB_Flash_File_ModuleLocal_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Flash_File_ModuleLocal_Proxy::GetInfo() {
+ static const Info info = {
+ &flash_file_modulelocal_interface,
+ PPB_FLASH_FILE_MODULELOCAL_INTERFACE,
+ INTERFACE_ID_PPB_FLASH_FILE_MODULELOCAL,
+ true,
+ &CreateFlashFileModuleLocalProxy,
+ };
+ return &info;
+}
+
+bool PPB_Flash_File_ModuleLocal_Proxy::OnMessageReceived(
+ const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Flash_File_ModuleLocal_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_ModuleLocal_OpenFile,
+ OnMsgOpenFile)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_ModuleLocal_RenameFile,
+ OnMsgRenameFile)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_ModuleLocal_DeleteFileOrDir,
+ OnMsgDeleteFileOrDir)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_ModuleLocal_CreateDir,
+ OnMsgCreateDir)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_ModuleLocal_QueryFile,
+ OnMsgQueryFile)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_ModuleLocal_GetDirContents,
+ OnMsgGetDirContents)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ // TODO(brettw) handle bad messages!
+ return handled;
+}
+
+void PPB_Flash_File_ModuleLocal_Proxy::OnMsgOpenFile(
+ PP_Instance instance,
+ const std::string& path,
+ int32_t mode,
+ IPC::PlatformFileForTransit* file_handle,
+ int32_t* result) {
+ base::PlatformFile file;
+ *result = ppb_flash_file_module_local_target()->
+ OpenFile(instance, path.c_str(), mode, &file);
+ *file_handle = PlatformFileToPlatformFileForTransit(
+ dispatcher(), result, file);
+}
+
+void PPB_Flash_File_ModuleLocal_Proxy::OnMsgRenameFile(
+ PP_Instance instance,
+ const std::string& from_path,
+ const std::string& to_path,
+ int32_t* result) {
+ *result = ppb_flash_file_module_local_target()->
+ RenameFile(instance, from_path.c_str(), to_path.c_str());
+}
+
+void PPB_Flash_File_ModuleLocal_Proxy::OnMsgDeleteFileOrDir(
+ PP_Instance instance,
+ const std::string& path,
+ PP_Bool recursive,
+ int32_t* result) {
+ *result = ppb_flash_file_module_local_target()->
+ DeleteFileOrDir(instance, path.c_str(), recursive);
+}
+
+void PPB_Flash_File_ModuleLocal_Proxy::OnMsgCreateDir(PP_Instance instance,
+ const std::string& path,
+ int32_t* result) {
+ *result = ppb_flash_file_module_local_target()->
+ CreateDir(instance, path.c_str());
+}
+
+void PPB_Flash_File_ModuleLocal_Proxy::OnMsgQueryFile(PP_Instance instance,
+ const std::string& path,
+ PP_FileInfo* info,
+ int32_t* result) {
+ *result = ppb_flash_file_module_local_target()->
+ QueryFile(instance, path.c_str(), info);
+}
+
+void PPB_Flash_File_ModuleLocal_Proxy::OnMsgGetDirContents(
+ PP_Instance instance,
+ const std::string& path,
+ std::vector<pp::proxy::SerializedDirEntry>* entries,
+ int32_t* result) {
+ PP_DirContents_Dev* contents = NULL;
+ *result = ppb_flash_file_module_local_target()->
+ GetDirContents(instance, path.c_str(), &contents);
+ if (*result != PP_OK)
+ return;
+
+ // Convert the list of entries to the serialized version.
+ entries->resize(contents->count);
+ for (int32_t i = 0; i < contents->count; i++) {
+ (*entries)[i].name.assign(contents->entries[i].name);
+ (*entries)[i].is_dir = PP_ToBool(contents->entries[i].is_dir);
+ }
+ ppb_flash_file_module_local_target()->FreeDirContents(instance, contents);
+}
+
+// PPB_Flash_File_FileRef ------------------------------------------------------
+
+namespace {
+
+int32_t OpenFileRefFile(PP_Resource file_ref_id,
+ int32_t mode,
+ PP_FileHandle* file) {
+ PluginResource* file_ref =
+ PluginResourceTracker::GetInstance()->GetResourceObject(file_ref_id);
+ if (!file_ref)
+ return PP_ERROR_BADRESOURCE;
+
+ PluginDispatcher* dispatcher =
+ PluginDispatcher::GetForInstance(file_ref->instance());
+ if (!dispatcher)
+ return PP_ERROR_BADARGUMENT;
+
+ int32_t result = PP_ERROR_FAILED;
+ IPC::PlatformFileForTransit transit;
+ dispatcher->Send(new PpapiHostMsg_PPBFlashFile_FileRef_OpenFile(
+ INTERFACE_ID_PPB_FLASH_FILE_FILEREF,
+ file_ref->host_resource(), mode, &transit, &result));
+ *file = IPC::PlatformFileForTransitToPlatformFile(transit);
+ return result;
+}
+
+int32_t QueryFileRefFile(PP_Resource file_ref_id,
+ PP_FileInfo* info) {
+ PluginResource* file_ref =
+ PluginResourceTracker::GetInstance()->GetResourceObject(file_ref_id);
+ if (!file_ref)
+ return PP_ERROR_BADRESOURCE;
+
+ PluginDispatcher* dispatcher =
+ PluginDispatcher::GetForInstance(file_ref->instance());
+ if (!dispatcher)
+ return PP_ERROR_BADARGUMENT;
+
+ int32_t result = PP_ERROR_FAILED;
+ dispatcher->Send(new PpapiHostMsg_PPBFlashFile_FileRef_QueryFile(
+ INTERFACE_ID_PPB_FLASH_FILE_FILEREF,
+ file_ref->host_resource(), info, &result));
+ return result;
+}
+
+const PPB_Flash_File_FileRef flash_file_fileref_interface = {
+ &OpenFileRefFile,
+ &QueryFileRefFile,
+};
+
+InterfaceProxy* CreateFlashFileFileRefProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Flash_File_FileRef_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_Flash_File_FileRef_Proxy::PPB_Flash_File_FileRef_Proxy(
+ Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_Flash_File_FileRef_Proxy::~PPB_Flash_File_FileRef_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Flash_File_FileRef_Proxy::GetInfo() {
+ static const Info info = {
+ &flash_file_fileref_interface,
+ PPB_FLASH_FILE_FILEREF_INTERFACE,
+ INTERFACE_ID_PPB_FLASH_FILE_FILEREF,
+ true,
+ &CreateFlashFileFileRefProxy,
+ };
+ return &info;
+}
+
+bool PPB_Flash_File_FileRef_Proxy::OnMessageReceived(
+ const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Flash_File_FileRef_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_FileRef_OpenFile,
+ OnMsgOpenFile)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_FileRef_QueryFile,
+ OnMsgQueryFile)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ // TODO(brettw) handle bad messages!
+ return handled;
+}
+
+void PPB_Flash_File_FileRef_Proxy::OnMsgOpenFile(
+ const HostResource& host_resource,
+ int32_t mode,
+ IPC::PlatformFileForTransit* file_handle,
+ int32_t* result) {
+ base::PlatformFile file;
+ *result = ppb_flash_file_module_local_target()->
+ OpenFile(host_resource.host_resource(), mode, &file);
+ *file_handle = PlatformFileToPlatformFileForTransit(
+ dispatcher(), result, file);
+}
+
+void PPB_Flash_File_FileRef_Proxy::OnMsgQueryFile(
+ const HostResource& host_resource,
+ PP_FileInfo* info,
+ int32_t* result) {
+ *result = ppb_flash_file_module_local_target()->
+ QueryFile(host_resource.host_resource(), info);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_flash_file_proxy.h b/ppapi/proxy/ppb_flash_file_proxy.h
new file mode 100644
index 0000000..e09ae54
--- /dev/null
+++ b/ppapi/proxy/ppb_flash_file_proxy.h
@@ -0,0 +1,98 @@
+// 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_PPB_FLASH_FILE_PROXY_H_
+#define PPAPI_PPB_FLASH_FILE_PROXY_H_
+
+#include <string>
+#include <vector>
+
+#include "ipc/ipc_platform_file.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PP_FileInfo;
+struct PPB_Flash_File_FileRef;
+struct PPB_Flash_File_ModuleLocal;
+
+namespace pp {
+namespace proxy {
+
+class HostResource;
+struct SerializedDirEntry;
+
+class PPB_Flash_File_ModuleLocal_Proxy : public InterfaceProxy {
+ public:
+ PPB_Flash_File_ModuleLocal_Proxy(Dispatcher* dispatcher,
+ const void* target_interface);
+ virtual ~PPB_Flash_File_ModuleLocal_Proxy();
+
+ static const Info* GetInfo();
+
+ const PPB_Flash_File_ModuleLocal* ppb_flash_file_module_local_target() const {
+ return static_cast<const PPB_Flash_File_ModuleLocal*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgOpenFile(PP_Instance instance,
+ const std::string& path,
+ int32_t mode,
+ IPC::PlatformFileForTransit* file_handle,
+ int32_t* result);
+ void OnMsgRenameFile(PP_Instance instance,
+ const std::string& path_from,
+ const std::string& path_to,
+ int32_t* result);
+ void OnMsgDeleteFileOrDir(PP_Instance instance,
+ const std::string& path,
+ PP_Bool recursive,
+ int32_t* result);
+ void OnMsgCreateDir(PP_Instance instance,
+ const std::string& path,
+ int32_t* result);
+ void OnMsgQueryFile(PP_Instance instance,
+ const std::string& path,
+ PP_FileInfo* info,
+ int32_t* result);
+ void OnMsgGetDirContents(PP_Instance instance,
+ const std::string& path,
+ std::vector<pp::proxy::SerializedDirEntry>* entries,
+ int32_t* result);
+};
+
+class PPB_Flash_File_FileRef_Proxy : public InterfaceProxy {
+ public:
+ PPB_Flash_File_FileRef_Proxy(Dispatcher* dispatcher,
+ const void* target_interface);
+ virtual ~PPB_Flash_File_FileRef_Proxy();
+
+ static const Info* GetInfo();
+
+ const PPB_Flash_File_FileRef* ppb_flash_file_module_local_target() const {
+ return static_cast<const PPB_Flash_File_FileRef*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgOpenFile(const HostResource& host_resource,
+ int32_t mode,
+ IPC::PlatformFileForTransit* file_handle,
+ int32_t* result);
+ void OnMsgQueryFile(const HostResource& host_resource,
+ PP_FileInfo* info,
+ int32_t* result);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PPB_FLASH_FILE_PROXY_H_
diff --git a/ppapi/proxy/ppb_flash_menu_proxy.cc b/ppapi/proxy/ppb_flash_menu_proxy.cc
new file mode 100644
index 0000000..c42c10e
--- /dev/null
+++ b/ppapi/proxy/ppb_flash_menu_proxy.cc
@@ -0,0 +1,204 @@
+// 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_flash_menu_proxy.h"
+
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/private/ppb_flash_menu.h"
+#include "ppapi/proxy/enter_proxy.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_flash_menu_api.h"
+#include "ppapi/thunk/resource_creation_api.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::thunk::EnterFunctionNoLock;
+using ppapi::thunk::PPB_Flash_Menu_API;
+using ppapi::thunk::ResourceCreationAPI;
+
+namespace pp {
+namespace proxy {
+
+class FlashMenu : public PPB_Flash_Menu_API, public PluginResource {
+ public:
+ explicit FlashMenu(const HostResource& resource);
+ virtual ~FlashMenu();
+
+ // ResourceObjectBase overrides.
+ virtual PPB_Flash_Menu_API* AsPPB_Flash_Menu_API() OVERRIDE;
+
+ // PPB_Flash_Menu_API implementation.
+ virtual int32_t Show(const PP_Point* location,
+ int32_t* selected_id,
+ PP_CompletionCallback callback) OVERRIDE;
+
+ void ShowACK(int32_t selected_id, int32_t result);
+
+ private:
+ PP_CompletionCallback callback_;
+ int32_t* selected_id_ptr_;
+
+ DISALLOW_COPY_AND_ASSIGN(FlashMenu);
+};
+
+FlashMenu::FlashMenu(const HostResource& resource)
+ : PluginResource(resource),
+ callback_(PP_BlockUntilComplete()),
+ selected_id_ptr_(NULL) {
+}
+
+FlashMenu::~FlashMenu() {
+}
+
+PPB_Flash_Menu_API* FlashMenu::AsPPB_Flash_Menu_API() {
+ return this;
+}
+
+int32_t FlashMenu::Show(const struct PP_Point* location,
+ int32_t* selected_id,
+ struct PP_CompletionCallback callback) {
+ if (callback_.func)
+ return PP_ERROR_INPROGRESS;
+
+ selected_id_ptr_ = selected_id;
+ callback_ = callback;
+
+ GetDispatcher()->Send(new PpapiHostMsg_PPBFlashMenu_Show(
+ INTERFACE_ID_PPB_FLASH_MENU, host_resource(), *location));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void FlashMenu::ShowACK(int32_t selected_id, int32_t result) {
+ *selected_id_ptr_ = selected_id;
+ PP_RunAndClearCompletionCallback(&callback_, result);
+}
+
+namespace {
+
+InterfaceProxy* CreateFlashMenuProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Flash_Menu_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_Flash_Menu_Proxy::PPB_Flash_Menu_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface),
+ callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+}
+
+PPB_Flash_Menu_Proxy::~PPB_Flash_Menu_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Flash_Menu_Proxy::GetInfo() {
+ static const Info info = {
+ ppapi::thunk::GetPPB_Flash_Menu_Thunk(),
+ PPB_FLASH_MENU_INTERFACE,
+ INTERFACE_ID_PPB_FLASH_MENU,
+ true,
+ &CreateFlashMenuProxy,
+ };
+ return &info;
+}
+
+// static
+PP_Resource PPB_Flash_Menu_Proxy::CreateProxyResource(
+ PP_Instance instance_id,
+ const PP_Flash_Menu* menu_data) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id);
+ if (!dispatcher)
+ return 0;
+
+ HostResource result;
+ pp::proxy::SerializedFlashMenu serialized_menu;
+ if (!serialized_menu.SetPPMenu(menu_data))
+ return 0;
+
+ dispatcher->Send(new PpapiHostMsg_PPBFlashMenu_Create(
+ INTERFACE_ID_PPB_FLASH_MENU, instance_id, serialized_menu, &result));
+ if (result.is_null())
+ return 0;
+
+ linked_ptr<FlashMenu> menu(new FlashMenu(result));
+ return PluginResourceTracker::GetInstance()->AddResource(menu);
+}
+
+bool PPB_Flash_Menu_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Flash_Menu_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashMenu_Create,
+ OnMsgCreate)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashMenu_Show,
+ OnMsgShow)
+
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBFlashMenu_ShowACK,
+ OnMsgShowACK)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ // FIXME(brettw) handle bad messages!
+ return handled;
+}
+
+void PPB_Flash_Menu_Proxy::OnMsgCreate(PP_Instance instance,
+ const SerializedFlashMenu& menu_data,
+ HostResource* result) {
+ EnterFunctionNoLock<ResourceCreationAPI> enter(instance, true);
+ if (enter.succeeded()) {
+ result->SetHostResource(
+ instance,
+ enter.functions()->CreateFlashMenu(instance, menu_data.pp_menu()));
+ }
+}
+
+struct PPB_Flash_Menu_Proxy::ShowRequest {
+ HostResource menu;
+ int32_t selected_id;
+};
+
+void PPB_Flash_Menu_Proxy::OnMsgShow(const HostResource& menu,
+ const PP_Point& location) {
+ ShowRequest* request = new ShowRequest;
+ request->menu = menu;
+ CompletionCallback callback = callback_factory_.NewOptionalCallback(
+ &PPB_Flash_Menu_Proxy::SendShowACKToPlugin, request);
+
+ EnterHostFromHostResource<PPB_Flash_Menu_API> enter(menu);
+ int32_t result = PP_ERROR_BADRESOURCE;
+ if (enter.succeeded()) {
+ result = enter.object()->Show(&location,
+ &request->selected_id,
+ callback.pp_completion_callback());
+ }
+ if (result != PP_OK_COMPLETIONPENDING) {
+ // There was some error, so we won't get a callback. We need to now issue
+ // the ACK to the plugin so that it hears about the error. This will also
+ // clean up the data associated with the callback.
+ callback.Run(result);
+ }
+}
+
+void PPB_Flash_Menu_Proxy::OnMsgShowACK(const HostResource& menu,
+ int32_t selected_id,
+ int32_t result) {
+ EnterPluginFromHostResource<PPB_Flash_Menu_API> enter(menu);
+ if (enter.failed())
+ return;
+ static_cast<FlashMenu*>(enter.object())->ShowACK(selected_id, result);
+}
+
+void PPB_Flash_Menu_Proxy::SendShowACKToPlugin(
+ int32_t result,
+ ShowRequest* request) {
+ dispatcher()->Send(new PpapiMsg_PPBFlashMenu_ShowACK(
+ INTERFACE_ID_PPB_FLASH_MENU,
+ request->menu,
+ request->selected_id,
+ result));
+ delete request;
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_flash_menu_proxy.h b/ppapi/proxy/ppb_flash_menu_proxy.h
new file mode 100644
index 0000000..d999905
--- /dev/null
+++ b/ppapi/proxy/ppb_flash_menu_proxy.h
@@ -0,0 +1,54 @@
+// 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_PPB_FLASH_MENU_PROXY_H_
+#define PPAPI_PPB_FLASH_MENU_PROXY_H_
+
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h"
+
+struct PP_Flash_Menu;
+struct PP_Point;
+struct PPB_Flash_Menu;
+
+namespace pp {
+namespace proxy {
+
+class SerializedFlashMenu;
+
+class PPB_Flash_Menu_Proxy : public InterfaceProxy {
+ public:
+ PPB_Flash_Menu_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_Flash_Menu_Proxy();
+
+ static const Info* GetInfo();
+
+ static PP_Resource CreateProxyResource(PP_Instance instance_id,
+ const PP_Flash_Menu* menu_data);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ struct ShowRequest;
+
+ void OnMsgCreate(PP_Instance instance_id,
+ const SerializedFlashMenu& menu_data,
+ HostResource* resource);
+ void OnMsgShow(const HostResource& menu,
+ const PP_Point& location);
+ void OnMsgShowACK(const HostResource& menu,
+ int32_t selected_id,
+ int32_t result);
+ void SendShowACKToPlugin(int32_t result, ShowRequest* request);
+
+ CompletionCallbackFactory<PPB_Flash_Menu_Proxy,
+ ProxyNonThreadSafeRefCount> callback_factory_;
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PPB_FLASH_MENU_PROXY_H_
diff --git a/ppapi/proxy/ppb_flash_net_connector_proxy.cc b/ppapi/proxy/ppb_flash_net_connector_proxy.cc
new file mode 100644
index 0000000..ba2c218
--- /dev/null
+++ b/ppapi/proxy/ppb_flash_net_connector_proxy.cc
@@ -0,0 +1,345 @@
+// 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_flash_net_connector_proxy.h"
+
+#include <algorithm>
+
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/private/ppb_flash_net_connector.h"
+#include "ppapi/proxy/enter_proxy.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"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_flash_net_connector_api.h"
+#include "ppapi/thunk/resource_creation_api.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::thunk::EnterFunctionNoLock;
+using ppapi::thunk::PPB_Flash_NetConnector_API;
+using ppapi::thunk::ResourceCreationAPI;
+
+namespace pp {
+namespace proxy {
+
+std::string NetAddressToString(const PP_Flash_NetAddress& addr) {
+ return std::string(addr.data, std::min(static_cast<size_t>(addr.size),
+ sizeof(addr.data)));
+}
+
+void StringToNetAddress(const std::string& str, PP_Flash_NetAddress* addr) {
+ addr->size = std::min(str.size(), sizeof(addr->data));
+ memcpy(addr->data, str.data(), addr->size);
+}
+
+class AbortCallbackTask : public Task {
+ public:
+ AbortCallbackTask(PP_CompletionCallback callback)
+ : callback_(callback) {}
+
+ virtual void Run() {
+ PP_RunCompletionCallback(&callback_, PP_ERROR_ABORTED);
+ }
+
+ private:
+ PP_CompletionCallback callback_;
+};
+
+class FlashNetConnector : public PPB_Flash_NetConnector_API,
+ public PluginResource {
+ public:
+ explicit FlashNetConnector(const HostResource& resource);
+ virtual ~FlashNetConnector();
+
+ // ResourceObjectBase overrides.
+ virtual PPB_Flash_NetConnector_API* AsPPB_Flash_NetConnector_API() OVERRIDE;
+
+ // PPB_Flash_NetConnector_API implementation.
+ virtual int32_t ConnectTcp(const char* host,
+ uint16_t port,
+ PP_FileHandle* socket_out,
+ PP_Flash_NetAddress* local_addr_out,
+ PP_Flash_NetAddress* remote_addr_out,
+ PP_CompletionCallback callback) OVERRIDE;
+ virtual int32_t ConnectTcpAddress(const PP_Flash_NetAddress* addr,
+ PP_FileHandle* socket_out,
+ PP_Flash_NetAddress* local_addr_out,
+ PP_Flash_NetAddress* remote_addr_out,
+ PP_CompletionCallback callback) OVERRIDE;
+
+ void ConnectComplete(int32_t result,
+ base::PlatformFile file,
+ const std::string& local_addr_as_string,
+ const std::string& remote_addr_as_string);
+
+ private:
+ // Backend for both ConnectTcp and ConnectTcpAddress. To keep things generic,
+ // the message is passed in (on error, it's deleted).
+ int32_t ConnectWithMessage(IPC::Message* msg,
+ PP_FileHandle* socket_out,
+ PP_Flash_NetAddress* local_addr_out,
+ PP_Flash_NetAddress* remote_addr_out,
+ PP_CompletionCallback callback);
+
+ PP_CompletionCallback callback_;
+ PP_FileHandle* socket_out_;
+ PP_Flash_NetAddress* local_addr_out_;
+ PP_Flash_NetAddress* remote_addr_out_;
+};
+
+FlashNetConnector::FlashNetConnector(const HostResource& resource)
+ : PluginResource(resource),
+ callback_(PP_BlockUntilComplete()),
+ local_addr_out_(NULL),
+ remote_addr_out_(NULL) {
+}
+
+FlashNetConnector::~FlashNetConnector() {
+ if (callback_.func) {
+ MessageLoop::current()->PostTask(FROM_HERE,
+ new AbortCallbackTask(callback_));
+ }
+}
+
+PPB_Flash_NetConnector_API* FlashNetConnector::AsPPB_Flash_NetConnector_API() {
+ return this;
+}
+
+int32_t FlashNetConnector::ConnectTcp(
+ const char* host,
+ uint16_t port,
+ PP_FileHandle* socket_out,
+ PP_Flash_NetAddress* local_addr_out,
+ PP_Flash_NetAddress* remote_addr_out,
+ PP_CompletionCallback callback) {
+ return ConnectWithMessage(
+ new PpapiHostMsg_PPBFlashNetConnector_ConnectTcp(
+ INTERFACE_ID_PPB_FLASH_NETCONNECTOR, host_resource(), host, port),
+ socket_out, local_addr_out, remote_addr_out, callback);
+}
+
+int32_t FlashNetConnector::ConnectTcpAddress(
+ const PP_Flash_NetAddress* addr,
+ PP_FileHandle* socket_out,
+ PP_Flash_NetAddress* local_addr_out,
+ PP_Flash_NetAddress* remote_addr_out,
+ PP_CompletionCallback callback) {
+ return ConnectWithMessage(
+ new PpapiHostMsg_PPBFlashNetConnector_ConnectTcpAddress(
+ INTERFACE_ID_PPB_FLASH_NETCONNECTOR,
+ host_resource(), NetAddressToString(*addr)),
+ socket_out, local_addr_out, remote_addr_out, callback);
+}
+
+void FlashNetConnector::ConnectComplete(
+ int32_t result,
+ base::PlatformFile file,
+ const std::string& local_addr_as_string,
+ const std::string& remote_addr_as_string) {
+ if (!callback_.func) {
+ base::ClosePlatformFile(file);
+ return;
+ }
+
+ *socket_out_ = static_cast<PP_FileHandle>(file);
+ StringToNetAddress(local_addr_as_string, local_addr_out_);
+ StringToNetAddress(remote_addr_as_string, remote_addr_out_);
+
+ PP_RunAndClearCompletionCallback(&callback_, result);
+}
+
+int32_t FlashNetConnector::ConnectWithMessage(
+ IPC::Message* msg,
+ PP_FileHandle* socket_out,
+ PP_Flash_NetAddress* local_addr_out,
+ PP_Flash_NetAddress* remote_addr_out,
+ PP_CompletionCallback callback) {
+ scoped_ptr<IPC::Message> msg_deletor(msg);
+ if (callback_.func != NULL)
+ return PP_ERROR_INPROGRESS; // Can only have one pending request.
+
+ // Send the request, it will call us back via ConnectACK.
+ GetDispatcher()->Send(msg_deletor.release());
+
+ callback_ = callback;
+ socket_out_ = socket_out;
+ local_addr_out_ = local_addr_out;
+ remote_addr_out_ = remote_addr_out;
+ return PP_OK_COMPLETIONPENDING;
+}
+
+// Contains the data that the host interface will write to so we can send it
+// to the plugin. This is created when a request is initiated, and deleted in
+// the callback handler.
+struct PPB_Flash_NetConnector_Proxy::ConnectCallbackInfo {
+ ConnectCallbackInfo(const HostResource& r) : resource(r), handle(0) {
+ local_addr.size = 0;
+ remote_addr.size = 0;
+ }
+
+ HostResource resource;
+
+ PP_FileHandle handle;
+ PP_Flash_NetAddress local_addr;
+ PP_Flash_NetAddress remote_addr;
+};
+
+namespace {
+
+InterfaceProxy* CreateFlashNetConnectorProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Flash_NetConnector_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_Flash_NetConnector_Proxy::PPB_Flash_NetConnector_Proxy(
+ Dispatcher* dispatcher, const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface),
+ callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+}
+
+PPB_Flash_NetConnector_Proxy::~PPB_Flash_NetConnector_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Flash_NetConnector_Proxy::GetInfo() {
+ static const Info info = {
+ ppapi::thunk::GetPPB_Flash_NetConnector_Thunk(),
+ PPB_FLASH_NETCONNECTOR_INTERFACE,
+ INTERFACE_ID_PPB_FLASH_NETCONNECTOR,
+ false,
+ &CreateFlashNetConnectorProxy
+ };
+ return &info;
+}
+
+// static
+PP_Resource PPB_Flash_NetConnector_Proxy::CreateProxyResource(
+ PP_Instance instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+
+ HostResource result;
+ dispatcher->Send(new PpapiHostMsg_PPBFlashNetConnector_Create(
+ INTERFACE_ID_PPB_FLASH_NETCONNECTOR, instance, &result));
+ if (result.is_null())
+ return 0;
+
+ linked_ptr<FlashNetConnector> object(new FlashNetConnector(result));
+ return PluginResourceTracker::GetInstance()->AddResource(object);
+}
+
+bool PPB_Flash_NetConnector_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Flash_NetConnector_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashNetConnector_Create,
+ OnMsgCreate)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashNetConnector_ConnectTcp,
+ OnMsgConnectTcp)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashNetConnector_ConnectTcpAddress,
+ OnMsgConnectTcpAddress)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBFlashNetConnector_ConnectACK,
+ OnMsgConnectACK)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPB_Flash_NetConnector_Proxy::OnMsgCreate(PP_Instance instance,
+ HostResource* result) {
+ EnterFunctionNoLock<ResourceCreationAPI> enter(instance, true);
+ if (enter.succeeded()) {
+ result->SetHostResource(
+ instance,
+ enter.functions()->CreateFlashNetConnector(instance));
+ }
+}
+
+void PPB_Flash_NetConnector_Proxy::OnMsgConnectTcp(
+ const HostResource& resource,
+ const std::string& host,
+ uint16_t port) {
+ ConnectCallbackInfo* info = new ConnectCallbackInfo(resource);
+ CompletionCallback callback = callback_factory_.NewOptionalCallback(
+ &PPB_Flash_NetConnector_Proxy::OnCompleteCallbackInHost, info);
+
+ EnterHostFromHostResource<PPB_Flash_NetConnector_API> enter(resource);
+ int32_t result = PP_ERROR_BADRESOURCE;
+ if (enter.succeeded()) {
+ result = enter.object()->ConnectTcp(
+ host.c_str(), port, &info->handle, &info->local_addr,
+ &info->remote_addr, callback.pp_completion_callback());
+ }
+ if (result != PP_OK_COMPLETIONPENDING)
+ OnCompleteCallbackInHost(result, info);
+}
+
+void PPB_Flash_NetConnector_Proxy::OnMsgConnectTcpAddress(
+ const HostResource& resource,
+ const std::string& net_address_as_string) {
+ ConnectCallbackInfo* info = new ConnectCallbackInfo(resource);
+ CompletionCallback callback = callback_factory_.NewOptionalCallback(
+ &PPB_Flash_NetConnector_Proxy::OnCompleteCallbackInHost, info);
+
+ PP_Flash_NetAddress net_address;
+ StringToNetAddress(net_address_as_string, &net_address);
+
+ EnterHostFromHostResource<PPB_Flash_NetConnector_API> enter(resource);
+ int32_t result = PP_ERROR_BADRESOURCE;
+ if (enter.succeeded()) {
+ result = enter.object()->ConnectTcpAddress(
+ &net_address, &info->handle, &info->local_addr, &info->remote_addr,
+ callback.pp_completion_callback());
+ }
+ if (result != PP_OK_COMPLETIONPENDING)
+ OnCompleteCallbackInHost(result, info);
+}
+
+void PPB_Flash_NetConnector_Proxy::OnMsgConnectACK(
+ const HostResource& host_resource,
+ int32_t result,
+ IPC::PlatformFileForTransit handle,
+ const std::string& load_addr_as_string,
+ const std::string& remote_addr_as_string) {
+ base::PlatformFile platform_file =
+ IPC::PlatformFileForTransitToPlatformFile(handle);
+
+ EnterPluginFromHostResource<PPB_Flash_NetConnector_API> enter(host_resource);
+ if (enter.failed()) {
+ base::ClosePlatformFile(platform_file);
+ return;
+ }
+ FlashNetConnector* object = static_cast<FlashNetConnector*>(enter.object());
+ object->ConnectComplete(result, platform_file,
+ load_addr_as_string, remote_addr_as_string);
+}
+
+void PPB_Flash_NetConnector_Proxy::OnCompleteCallbackInHost(
+ int32_t result,
+ ConnectCallbackInfo* info) {
+ // Callback must always delete the info.
+ scoped_ptr<ConnectCallbackInfo> info_deletor(info);
+
+ if (result == PP_OK) {
+ dispatcher()->Send(new PpapiMsg_PPBFlashNetConnector_ConnectACK(
+ INTERFACE_ID_PPB_FLASH_NETCONNECTOR,
+ info->resource, result,
+ dispatcher()->ShareHandleWithRemote(
+ static_cast<base::PlatformFile>(info->handle), true),
+ NetAddressToString(info->local_addr),
+ NetAddressToString(info->remote_addr)));
+ } else {
+ dispatcher()->Send(new PpapiMsg_PPBFlashNetConnector_ConnectACK(
+ INTERFACE_ID_PPB_FLASH_NETCONNECTOR,
+ info->resource, result,
+ IPC::InvalidPlatformFileForTransit(), std::string(), std::string()));
+ }
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_flash_net_connector_proxy.h b/ppapi/proxy/ppb_flash_net_connector_proxy.h
new file mode 100644
index 0000000..67647c2
--- /dev/null
+++ b/ppapi/proxy/ppb_flash_net_connector_proxy.h
@@ -0,0 +1,63 @@
+// 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_FLASH_NET_CONNECTOR_PROXY_H_
+#define PPAPI_PROXY_PPB_FLASH_NET_CONNECTOR_PROXY_H_
+
+#include "base/platform_file.h"
+#include "ipc/ipc_platform_file.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_Flash_NetConnector;
+
+namespace pp {
+namespace proxy {
+
+class HostResource;
+
+class PPB_Flash_NetConnector_Proxy : public InterfaceProxy {
+ public:
+ PPB_Flash_NetConnector_Proxy(Dispatcher* dispatcher,
+ const void* target_interface);
+ virtual ~PPB_Flash_NetConnector_Proxy();
+
+ static const Info* GetInfo();
+
+ static PP_Resource CreateProxyResource(PP_Instance instance);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ struct ConnectCallbackInfo;
+
+ // Plugin->host message handlers.
+ void OnMsgCreate(PP_Instance instance,
+ HostResource* result);
+ void OnMsgConnectTcp(const HostResource& resource,
+ const std::string& host,
+ uint16_t port);
+ void OnMsgConnectTcpAddress(const HostResource& resource_id,
+ const std::string& net_address_as_string);
+
+ // Host->plugin message handler.
+ void OnMsgConnectACK(const HostResource& host_resource,
+ int32_t result,
+ IPC::PlatformFileForTransit handle,
+ const std::string& load_addr_as_string,
+ const std::string& remote_addr_as_string);
+
+ void OnCompleteCallbackInHost(int32_t result, ConnectCallbackInfo* info);
+
+ CompletionCallbackFactory<PPB_Flash_NetConnector_Proxy,
+ ProxyNonThreadSafeRefCount> callback_factory_;
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_FLASH_NET_CONNECTOR_PROXY_H_
diff --git a/ppapi/proxy/ppb_flash_proxy.cc b/ppapi/proxy/ppb_flash_proxy.cc
new file mode 100644
index 0000000..c430b05
--- /dev/null
+++ b/ppapi/proxy/ppb_flash_proxy.cc
@@ -0,0 +1,291 @@
+// 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_flash_proxy.h"
+
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/time.h"
+#include "ppapi/c/dev/ppb_font_dev.h"
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/private/ppb_flash.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/proxy_module.h"
+#include "ppapi/proxy/serialized_var.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+void SetInstanceAlwaysOnTop(PP_Instance pp_instance, PP_Bool on_top) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(pp_instance);
+ if (dispatcher) {
+ dispatcher->Send(new PpapiHostMsg_PPBFlash_SetInstanceAlwaysOnTop(
+ INTERFACE_ID_PPB_FLASH, pp_instance, on_top));
+ }
+}
+
+PP_Bool DrawGlyphs(PP_Instance instance,
+ PP_Resource pp_image_data,
+ const PP_FontDescription_Dev* font_desc,
+ uint32_t color,
+ PP_Point position,
+ PP_Rect clip,
+ const float transformation[3][3],
+ uint32_t glyph_count,
+ const uint16_t glyph_indices[],
+ const PP_Point glyph_advances[]) {
+ PluginResource* image_data = PluginResourceTracker::GetInstance()->
+ GetResourceObject(pp_image_data);
+ if (!image_data)
+ return PP_FALSE;
+ // The instance parameter isn't strictly necessary but we check that it
+ // matches anyway.
+ if (image_data->instance() != instance)
+ return PP_FALSE;
+
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(
+ image_data->instance());
+ if (!dispatcher)
+ return PP_FALSE;
+
+ PPBFlash_DrawGlyphs_Params params;
+ params.image_data = image_data->host_resource();
+ params.font_desc.SetFromPPFontDescription(dispatcher, *font_desc, true);
+ params.color = color;
+ params.position = position;
+ params.clip = clip;
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++)
+ params.transformation[i][j] = transformation[i][j];
+ }
+
+ params.glyph_indices.insert(params.glyph_indices.begin(),
+ &glyph_indices[0],
+ &glyph_indices[glyph_count]);
+ params.glyph_advances.insert(params.glyph_advances.begin(),
+ &glyph_advances[0],
+ &glyph_advances[glyph_count]);
+
+ PP_Bool result = PP_FALSE;
+ dispatcher->Send(new PpapiHostMsg_PPBFlash_DrawGlyphs(
+ INTERFACE_ID_PPB_FLASH, params, &result));
+ return result;
+}
+
+PP_Var GetProxyForURL(PP_Instance instance, const char* url) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return PP_MakeUndefined();
+
+ ReceiveSerializedVarReturnValue result;
+ dispatcher->Send(new PpapiHostMsg_PPBFlash_GetProxyForURL(
+ INTERFACE_ID_PPB_FLASH, instance, url, &result));
+ return result.Return(dispatcher);
+}
+
+int32_t Navigate(PP_Resource request_id,
+ const char* target,
+ bool from_user_action) {
+ PluginResource* request_object =
+ PluginResourceTracker::GetInstance()->GetResourceObject(request_id);
+ if (!request_object)
+ return PP_ERROR_BADRESOURCE;
+
+ PluginDispatcher* dispatcher =
+ PluginDispatcher::GetForInstance(request_object->instance());
+ if (!dispatcher)
+ return PP_ERROR_FAILED;
+
+ int32_t result = PP_ERROR_FAILED;
+ dispatcher->Send(new PpapiHostMsg_PPBFlash_Navigate(
+ INTERFACE_ID_PPB_FLASH,
+ request_object->host_resource(), target, from_user_action,
+ &result));
+ return result;
+}
+
+void RunMessageLoop(PP_Instance instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return;
+ IPC::SyncMessage* msg = new PpapiHostMsg_PPBFlash_RunMessageLoop(
+ INTERFACE_ID_PPB_FLASH, instance);
+ msg->EnableMessagePumping();
+ dispatcher->Send(msg);
+}
+
+void QuitMessageLoop(PP_Instance instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return;
+ dispatcher->Send(new PpapiHostMsg_PPBFlash_QuitMessageLoop(
+ INTERFACE_ID_PPB_FLASH, instance));
+}
+
+double GetLocalTimeZoneOffset(PP_Instance instance, PP_Time t) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0.0;
+
+ // TODO(brettw) on Windows it should be possible to do the time calculation
+ // in-process since it doesn't need to read files on disk. This will improve
+ // performance.
+ //
+ // On Linux, it would be better to go directly to the browser process for
+ // this message rather than proxy it through some instance in a renderer.
+ double result = 0;
+ dispatcher->Send(new PpapiHostMsg_PPBFlash_GetLocalTimeZoneOffset(
+ INTERFACE_ID_PPB_FLASH, instance, t, &result));
+ return result;
+}
+
+PP_Var GetCommandLineArgs(PP_Module pp_module) {
+ const PPB_Var_Deprecated* var_deprecated =
+ static_cast<const PPB_Var_Deprecated*>(
+ PluginDispatcher::GetInterfaceFromDispatcher(
+ PPB_VAR_DEPRECATED_INTERFACE));
+ std::string args =
+ pp::proxy::ProxyModule::GetInstance()->GetFlashCommandLineArgs();
+ return var_deprecated->VarFromUtf8(pp_module, args.data(), args.length());
+}
+
+const PPB_Flash flash_interface = {
+ &SetInstanceAlwaysOnTop,
+ &DrawGlyphs,
+ &GetProxyForURL,
+ &Navigate,
+ &RunMessageLoop,
+ &QuitMessageLoop,
+ &GetLocalTimeZoneOffset,
+ &GetCommandLineArgs
+};
+
+InterfaceProxy* CreateFlashProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Flash_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_Flash_Proxy::PPB_Flash_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_Flash_Proxy::~PPB_Flash_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Flash_Proxy::GetInfo() {
+ static const Info info = {
+ &flash_interface,
+ PPB_FLASH_INTERFACE,
+ INTERFACE_ID_PPB_FLASH,
+ true,
+ &CreateFlashProxy,
+ };
+ return &info;
+}
+
+bool PPB_Flash_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ // Prevent the dispatcher from going away during a call to Navigate.
+ // This must happen OUTSIDE of OnMsgNavigate since the handling code use
+ // the dispatcher upon return of the function (sending the reply message).
+ ScopedModuleReference death_grip(dispatcher());
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Flash_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_SetInstanceAlwaysOnTop,
+ OnMsgSetInstanceAlwaysOnTop)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_DrawGlyphs,
+ OnMsgDrawGlyphs)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_GetProxyForURL,
+ OnMsgGetProxyForURL)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_Navigate, OnMsgNavigate)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_RunMessageLoop,
+ OnMsgRunMessageLoop)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_QuitMessageLoop,
+ OnMsgQuitMessageLoop)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_GetLocalTimeZoneOffset,
+ OnMsgGetLocalTimeZoneOffset)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ // TODO(brettw) handle bad messages!
+ return handled;
+}
+
+void PPB_Flash_Proxy::OnMsgSetInstanceAlwaysOnTop(
+ PP_Instance instance,
+ PP_Bool on_top) {
+ ppb_flash_target()->SetInstanceAlwaysOnTop(instance, on_top);
+}
+
+void PPB_Flash_Proxy::OnMsgDrawGlyphs(
+ const pp::proxy::PPBFlash_DrawGlyphs_Params& params,
+ PP_Bool* result) {
+ *result = PP_FALSE;
+
+ PP_FontDescription_Dev font_desc;
+ params.font_desc.SetToPPFontDescription(dispatcher(), &font_desc, false);
+
+ if (params.glyph_indices.size() != params.glyph_advances.size() ||
+ params.glyph_indices.empty())
+ return;
+
+ *result = ppb_flash_target()->DrawGlyphs(
+ 0, // Unused instance param.
+ params.image_data.host_resource(), &font_desc,
+ params.color, params.position, params.clip,
+ const_cast<float(*)[3]>(params.transformation),
+ static_cast<uint32_t>(params.glyph_indices.size()),
+ const_cast<uint16_t*>(&params.glyph_indices[0]),
+ const_cast<PP_Point*>(&params.glyph_advances[0]));
+}
+
+void PPB_Flash_Proxy::OnMsgGetProxyForURL(PP_Instance instance,
+ const std::string& url,
+ SerializedVarReturnValue result) {
+ result.Return(dispatcher(), ppb_flash_target()->GetProxyForURL(
+ instance, url.c_str()));
+}
+
+void PPB_Flash_Proxy::OnMsgNavigate(const HostResource& request_info,
+ const std::string& target,
+ bool from_user_action,
+ int32_t* result) {
+ DCHECK(!dispatcher()->IsPlugin());
+ // We need to allow re-entrancy here, because this may call into Javascript
+ // (e.g. with a "javascript:" URL), or do things like navigate away from the
+ // page, either one of which will need to re-enter into the plugin.
+ // It is safe, because it is essentially equivalent to NPN_GetURL, where Flash
+ // would expect re-entrancy. When running in-process, it does re-enter here.
+ static_cast<HostDispatcher*>(dispatcher())->set_allow_plugin_reentrancy();
+ *result = ppb_flash_target()->Navigate(request_info.host_resource(),
+ target.c_str(),
+ from_user_action);
+}
+
+void PPB_Flash_Proxy::OnMsgRunMessageLoop(PP_Instance instance) {
+ ppb_flash_target()->RunMessageLoop(instance);
+}
+
+void PPB_Flash_Proxy::OnMsgQuitMessageLoop(PP_Instance instance) {
+ ppb_flash_target()->QuitMessageLoop(instance);
+}
+
+void PPB_Flash_Proxy::OnMsgGetLocalTimeZoneOffset(PP_Instance instance,
+ PP_Time t,
+ double* result) {
+ *result = ppb_flash_target()->GetLocalTimeZoneOffset(instance, t);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_flash_proxy.h b/ppapi/proxy/ppb_flash_proxy.h
new file mode 100644
index 0000000..8316135
--- /dev/null
+++ b/ppapi/proxy/ppb_flash_proxy.h
@@ -0,0 +1,63 @@
+// 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_PPB_FLASH_PROXY_H_
+#define PPAPI_PPB_FLASH_PROXY_H_
+
+#include <string>
+#include <vector>
+
+#include "ipc/ipc_platform_file.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_time.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PP_FileInfo;
+struct PPB_Flash;
+
+namespace pp {
+namespace proxy {
+
+struct PPBFlash_DrawGlyphs_Params;
+class SerializedVarReturnValue;
+
+class PPB_Flash_Proxy : public InterfaceProxy {
+ public:
+ PPB_Flash_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_Flash_Proxy();
+
+ static const Info* GetInfo();
+
+ const PPB_Flash* ppb_flash_target() const {
+ return static_cast<const PPB_Flash*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgSetInstanceAlwaysOnTop(PP_Instance instance,
+ PP_Bool on_top);
+ void OnMsgDrawGlyphs(const pp::proxy::PPBFlash_DrawGlyphs_Params& params,
+ PP_Bool* result);
+ void OnMsgGetProxyForURL(PP_Instance instance,
+ const std::string& url,
+ SerializedVarReturnValue result);
+ void OnMsgNavigate(const HostResource& request_info,
+ const std::string& target,
+ bool from_user_action,
+ int32_t* result);
+ void OnMsgRunMessageLoop(PP_Instance instance);
+ void OnMsgQuitMessageLoop(PP_Instance instance);
+ void OnMsgGetLocalTimeZoneOffset(PP_Instance instance, PP_Time t,
+ double* result);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PPB_FLASH_PROXY_H_
diff --git a/ppapi/proxy/ppb_flash_tcp_socket_proxy.cc b/ppapi/proxy/ppb_flash_tcp_socket_proxy.cc
new file mode 100644
index 0000000..6a6ab50
--- /dev/null
+++ b/ppapi/proxy/ppb_flash_tcp_socket_proxy.cc
@@ -0,0 +1,439 @@
+// 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_flash_tcp_socket_proxy.h"
+
+#include <algorithm>
+#include <cstring>
+#include <map>
+
+#include "base/logging.h"
+#include "base/memory/linked_ptr.h"
+#include "base/message_loop.h"
+#include "base/scoped_ptr.h"
+#include "base/task.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/thunk/ppb_flash_tcp_socket_api.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::thunk::PPB_Flash_TCPSocket_API;
+
+namespace pp {
+namespace proxy {
+
+const int32_t kFlashTCPSocketMaxReadSize = 1024 * 1024;
+const int32_t kFlashTCPSocketMaxWriteSize = 1024 * 1024;
+
+class FlashTCPSocket;
+
+namespace {
+
+typedef std::map<uint32, FlashTCPSocket*> IDToSocketMap;
+IDToSocketMap* g_id_to_socket = NULL;
+
+class AbortCallbackTask : public Task {
+ public:
+ explicit AbortCallbackTask(PP_CompletionCallback callback)
+ : callback_(callback) {}
+ virtual ~AbortCallbackTask() {}
+ virtual void Run() {
+ if (callback_.func)
+ PP_RunCompletionCallback(&callback_, PP_ERROR_ABORTED);
+ }
+
+ private:
+ PP_CompletionCallback callback_;
+};
+
+InterfaceProxy* CreateFlashTCPSocketProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Flash_TCPSocket_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+class FlashTCPSocket : public PPB_Flash_TCPSocket_API,
+ public PluginResource {
+ public:
+ FlashTCPSocket(const HostResource& resource, uint32 socket_id);
+ virtual ~FlashTCPSocket();
+
+ // ResourceObjectBase overrides.
+ virtual PPB_Flash_TCPSocket_API* AsPPB_Flash_TCPSocket_API() OVERRIDE;
+
+ // PPB_Flash_TCPSocket_API implementation.
+ virtual int32_t Connect(const char* host,
+ uint16_t port,
+ PP_CompletionCallback callback) OVERRIDE;
+ virtual int32_t ConnectWithNetAddress(
+ const PP_Flash_NetAddress* addr,
+ PP_CompletionCallback callback) OVERRIDE;
+ virtual PP_Bool GetLocalAddress(PP_Flash_NetAddress* local_addr) OVERRIDE;
+ virtual PP_Bool GetRemoteAddress(PP_Flash_NetAddress* remote_addr) OVERRIDE;
+ virtual int32_t InitiateSSL(const char* server_name,
+ PP_CompletionCallback callback) OVERRIDE;
+ virtual int32_t Read(char* buffer,
+ int32_t bytes_to_read,
+ PP_CompletionCallback callback) OVERRIDE;
+ virtual int32_t Write(const char* buffer,
+ int32_t bytes_to_write,
+ PP_CompletionCallback callback) OVERRIDE;
+ virtual void Disconnect() OVERRIDE;
+
+ // Notifications from the proxy.
+ void OnConnectCompleted(bool succeeded,
+ const PP_Flash_NetAddress& local_addr,
+ const PP_Flash_NetAddress& remote_addr);
+ void OnReadCompleted(bool succeeded, const std::string& data);
+ void OnWriteCompleted(bool succeeded, int32_t bytes_written);
+
+ private:
+ enum ConnectionState {
+ // Before a connection is successfully established (including a connect
+ // request is pending or a previous connect request failed).
+ BEFORE_CONNECT,
+ CONNECTED,
+ DISCONNECTED
+ };
+
+ // Backend for both Connect() and ConnectWithNetAddress(). To keep things
+ // generic, the message is passed in (on error, it's deleted).
+ int32_t ConnectWithMessage(IPC::Message* msg,
+ PP_CompletionCallback callback);
+
+ void PostAbortAndClearIfNecessary(PP_CompletionCallback* callback);
+
+ uint32 socket_id_;
+ ConnectionState connection_state_;
+
+ PP_CompletionCallback connect_callback_;
+ PP_CompletionCallback read_callback_;
+ PP_CompletionCallback write_callback_;
+
+ char* read_buffer_;
+ int32_t bytes_to_read_;
+
+ PP_Flash_NetAddress local_addr_;
+ PP_Flash_NetAddress remote_addr_;
+
+ DISALLOW_COPY_AND_ASSIGN(FlashTCPSocket);
+};
+
+FlashTCPSocket::FlashTCPSocket(const HostResource& resource, uint32 socket_id)
+ : PluginResource(resource),
+ socket_id_(socket_id),
+ connection_state_(BEFORE_CONNECT),
+ connect_callback_(PP_BlockUntilComplete()),
+ read_callback_(PP_BlockUntilComplete()),
+ write_callback_(PP_BlockUntilComplete()),
+ read_buffer_(NULL),
+ bytes_to_read_(-1) {
+ DCHECK(socket_id != 0);
+
+ local_addr_.size = 0;
+ memset(local_addr_.data, 0, sizeof(local_addr_.data));
+ remote_addr_.size = 0;
+ memset(remote_addr_.data, 0, sizeof(remote_addr_.data));
+
+ if (!g_id_to_socket)
+ g_id_to_socket = new IDToSocketMap();
+ DCHECK(g_id_to_socket->find(socket_id) == g_id_to_socket->end());
+ (*g_id_to_socket)[socket_id] = this;
+}
+
+FlashTCPSocket::~FlashTCPSocket() {
+ Disconnect();
+}
+
+PPB_Flash_TCPSocket_API* FlashTCPSocket::AsPPB_Flash_TCPSocket_API() {
+ return this;
+}
+
+int32_t FlashTCPSocket::Connect(const char* host,
+ uint16_t port,
+ PP_CompletionCallback callback) {
+ if (!host)
+ return PP_ERROR_BADARGUMENT;
+
+ return ConnectWithMessage(
+ new PpapiHostMsg_PPBFlashTCPSocket_Connect(socket_id_, host, port),
+ callback);
+}
+
+int32_t FlashTCPSocket::ConnectWithNetAddress(
+ const PP_Flash_NetAddress* addr,
+ PP_CompletionCallback callback) {
+ if (!addr)
+ return PP_ERROR_BADARGUMENT;
+
+ return ConnectWithMessage(
+ new PpapiHostMsg_PPBFlashTCPSocket_ConnectWithNetAddress(
+ socket_id_, *addr),
+ callback);
+}
+
+PP_Bool FlashTCPSocket::GetLocalAddress(PP_Flash_NetAddress* local_addr) {
+ if (connection_state_ != CONNECTED || !local_addr)
+ return PP_FALSE;
+
+ *local_addr = local_addr_;
+ return PP_TRUE;
+}
+
+PP_Bool FlashTCPSocket::GetRemoteAddress(PP_Flash_NetAddress* remote_addr) {
+ if (connection_state_ != CONNECTED || !remote_addr)
+ return PP_FALSE;
+
+ *remote_addr = remote_addr_;
+ return PP_TRUE;
+}
+
+int32_t FlashTCPSocket::InitiateSSL(const char* server_name,
+ PP_CompletionCallback callback) {
+ // TODO(yzshen): add it.
+ return PP_ERROR_FAILED;
+}
+
+int32_t FlashTCPSocket::Read(char* buffer,
+ int32_t bytes_to_read,
+ PP_CompletionCallback callback) {
+ if (!buffer || bytes_to_read <= 0 || !callback.func)
+ return PP_ERROR_BADARGUMENT;
+
+ if (connection_state_ != CONNECTED)
+ return PP_ERROR_FAILED;
+ if (read_callback_.func)
+ return PP_ERROR_INPROGRESS;
+
+ read_buffer_ = buffer;
+ bytes_to_read_ = std::min(bytes_to_read, kFlashTCPSocketMaxReadSize);
+ read_callback_ = callback;
+
+ // Send the request, the browser will call us back via ReadACK.
+ GetDispatcher()->SendToBrowser(
+ new PpapiHostMsg_PPBFlashTCPSocket_Read(socket_id_, bytes_to_read_));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FlashTCPSocket::Write(const char* buffer,
+ int32_t bytes_to_write,
+ PP_CompletionCallback callback) {
+ if (!buffer || bytes_to_write <= 0 || !callback.func)
+ return PP_ERROR_BADARGUMENT;
+
+ if (connection_state_ != CONNECTED)
+ return PP_ERROR_FAILED;
+ if (write_callback_.func)
+ return PP_ERROR_INPROGRESS;
+
+ if (bytes_to_write > kFlashTCPSocketMaxWriteSize)
+ bytes_to_write = kFlashTCPSocketMaxWriteSize;
+
+ write_callback_ = callback;
+
+ // Send the request, the browser will call us back via WriteACK.
+ GetDispatcher()->SendToBrowser(
+ new PpapiHostMsg_PPBFlashTCPSocket_Write(
+ socket_id_, std::string(buffer, bytes_to_write)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void FlashTCPSocket::Disconnect() {
+ if (connection_state_ == DISCONNECTED)
+ return;
+
+ connection_state_ = DISCONNECTED;
+ // After removed from the mapping, this object won't receive any notfications
+ // from the proxy.
+ DCHECK(g_id_to_socket->find(socket_id_) != g_id_to_socket->end());
+ g_id_to_socket->erase(socket_id_);
+
+ GetDispatcher()->SendToBrowser(
+ new PpapiHostMsg_PPBFlashTCPSocket_Disconnect(socket_id_));
+ socket_id_ = 0;
+
+ PostAbortAndClearIfNecessary(&connect_callback_);
+ PostAbortAndClearIfNecessary(&read_callback_);
+ PostAbortAndClearIfNecessary(&write_callback_);
+ read_buffer_ = NULL;
+ bytes_to_read_ = -1;
+}
+
+void FlashTCPSocket::OnConnectCompleted(
+ bool succeeded,
+ const PP_Flash_NetAddress& local_addr,
+ const PP_Flash_NetAddress& remote_addr) {
+ if (connection_state_ != BEFORE_CONNECT || !connect_callback_.func) {
+ NOTREACHED();
+ return;
+ }
+
+ if (succeeded) {
+ local_addr_ = local_addr;
+ remote_addr_ = remote_addr;
+ connection_state_ = CONNECTED;
+ }
+ PP_RunAndClearCompletionCallback(&connect_callback_,
+ succeeded ? PP_OK : PP_ERROR_FAILED);
+}
+
+void FlashTCPSocket::OnReadCompleted(bool succeeded, const std::string& data) {
+ if (!read_callback_.func || !read_buffer_) {
+ NOTREACHED();
+ return;
+ }
+
+ if (succeeded) {
+ CHECK_LE(static_cast<int32_t>(data.size()), bytes_to_read_);
+ if (!data.empty())
+ memcpy(read_buffer_, data.c_str(), data.size());
+ }
+ read_buffer_ = NULL;
+ bytes_to_read_ = -1;
+
+ PP_RunAndClearCompletionCallback(
+ &read_callback_,
+ succeeded ? static_cast<int32_t>(data.size()) :
+ static_cast<int32_t>(PP_ERROR_FAILED));
+}
+
+void FlashTCPSocket::OnWriteCompleted(bool succeeded, int32_t bytes_written) {
+ if (!write_callback_.func || (succeeded && bytes_written < 0)) {
+ NOTREACHED();
+ return;
+ }
+
+ PP_RunAndClearCompletionCallback(
+ &write_callback_,
+ succeeded ? bytes_written : static_cast<int32_t>(PP_ERROR_FAILED));
+}
+
+int32_t FlashTCPSocket::ConnectWithMessage(IPC::Message* msg,
+ PP_CompletionCallback callback) {
+ scoped_ptr<IPC::Message> msg_deletor(msg);
+ if (!callback.func)
+ return PP_ERROR_BADARGUMENT;
+ if (connection_state_ != BEFORE_CONNECT)
+ return PP_ERROR_FAILED;
+ if (connect_callback_.func)
+ return PP_ERROR_INPROGRESS; // Can only have one pending request.
+
+ connect_callback_ = callback;
+ // Send the request, the browser will call us back via ConnectACK.
+ GetDispatcher()->SendToBrowser(msg_deletor.release());
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void FlashTCPSocket::PostAbortAndClearIfNecessary(
+ PP_CompletionCallback* callback) {
+ DCHECK(callback);
+
+ if (callback->func) {
+ MessageLoop::current()->PostTask(FROM_HERE,
+ new AbortCallbackTask(*callback));
+ *callback = PP_BlockUntilComplete();
+ }
+}
+
+PPB_Flash_TCPSocket_Proxy::PPB_Flash_TCPSocket_Proxy(
+ Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_Flash_TCPSocket_Proxy::~PPB_Flash_TCPSocket_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Flash_TCPSocket_Proxy::GetInfo() {
+ static const Info info = {
+ ::ppapi::thunk::GetPPB_Flash_TCPSocket_Thunk(),
+ PPB_FLASH_TCPSOCKET_INTERFACE,
+ INTERFACE_ID_PPB_FLASH_TCPSOCKET,
+ false,
+ &CreateFlashTCPSocketProxy,
+ };
+ return &info;
+}
+
+// static
+PP_Resource PPB_Flash_TCPSocket_Proxy::CreateProxyResource(
+ PP_Instance instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+
+ uint32 socket_id = 0;
+ dispatcher->SendToBrowser(new PpapiHostMsg_PPBFlashTCPSocket_Create(
+ INTERFACE_ID_PPB_FLASH_TCPSOCKET, dispatcher->plugin_dispatcher_id(),
+ &socket_id));
+ if (socket_id == 0)
+ return 0;
+
+ linked_ptr<FlashTCPSocket> object(new FlashTCPSocket(
+ HostResource::MakeInstanceOnly(instance), socket_id));
+ return PluginResourceTracker::GetInstance()->AddResource(object);
+}
+
+bool PPB_Flash_TCPSocket_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Flash_TCPSocket_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBFlashTCPSocket_ConnectACK, OnMsgConnectACK)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBFlashTCPSocket_ReadACK, OnMsgReadACK)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBFlashTCPSocket_WriteACK, OnMsgWriteACK)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPB_Flash_TCPSocket_Proxy::OnMsgConnectACK(
+ uint32 /* plugin_dispatcher_id */,
+ uint32 socket_id,
+ bool succeeded,
+ const PP_Flash_NetAddress& local_addr,
+ const PP_Flash_NetAddress& remote_addr) {
+ if (!g_id_to_socket) {
+ NOTREACHED();
+ return;
+ }
+ IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id);
+ if (iter == g_id_to_socket->end())
+ return;
+ iter->second->OnConnectCompleted(succeeded, local_addr, remote_addr);
+}
+
+void PPB_Flash_TCPSocket_Proxy::OnMsgReadACK(uint32 /* plugin_dispatcher_id */,
+ uint32 socket_id,
+ bool succeeded,
+ const std::string& data) {
+ if (!g_id_to_socket) {
+ NOTREACHED();
+ return;
+ }
+ IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id);
+ if (iter == g_id_to_socket->end())
+ return;
+ iter->second->OnReadCompleted(succeeded, data);
+}
+
+void PPB_Flash_TCPSocket_Proxy::OnMsgWriteACK(uint32 /* plugin_dispatcher_id */,
+ uint32 socket_id,
+ bool succeeded,
+ int32_t bytes_written) {
+ if (!g_id_to_socket) {
+ NOTREACHED();
+ return;
+ }
+ IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id);
+ if (iter == g_id_to_socket->end())
+ return;
+ iter->second->OnWriteCompleted(succeeded, bytes_written);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_flash_tcp_socket_proxy.h b/ppapi/proxy/ppb_flash_tcp_socket_proxy.h
new file mode 100644
index 0000000..aac9bbd
--- /dev/null
+++ b/ppapi/proxy/ppb_flash_tcp_socket_proxy.h
@@ -0,0 +1,61 @@
+// 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_FLASH_TCP_SOCKET_PROXY_H_
+#define PPAPI_PROXY_PPB_FLASH_TCP_SOCKET_PROXY_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/private/ppb_flash_tcp_socket.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+namespace pp {
+namespace proxy {
+
+// The maximum number of bytes that each PpapiHostMsg_PPBFlashTCPSocket_Read
+// message is allowed to request.
+extern const int32_t kFlashTCPSocketMaxReadSize;
+// The maximum number of bytes that each PpapiHostMsg_PPBFlashTCPSocket_Write
+// message is allowed to carry.
+extern const int32_t kFlashTCPSocketMaxWriteSize;
+
+class PPB_Flash_TCPSocket_Proxy : public InterfaceProxy {
+ public:
+ PPB_Flash_TCPSocket_Proxy(Dispatcher* dispatcher,
+ const void* target_interface);
+ virtual ~PPB_Flash_TCPSocket_Proxy();
+
+ static const Info* GetInfo();
+
+ static PP_Resource CreateProxyResource(PP_Instance instance);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Browser->plugin message handlers.
+ void OnMsgConnectACK(uint32 plugin_dispatcher_id,
+ uint32 socket_id,
+ bool succeeded,
+ const PP_Flash_NetAddress& local_addr,
+ const PP_Flash_NetAddress& remote_addr);
+ void OnMsgReadACK(uint32 plugin_dispatcher_id,
+ uint32 socket_id,
+ bool succeeded,
+ const std::string& data);
+ void OnMsgWriteACK(uint32 plugin_dispatcher_id,
+ uint32 socket_id,
+ bool succeeded,
+ int32_t bytes_written);
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_Flash_TCPSocket_Proxy);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_FLASH_TCP_SOCKET_PROXY_H_
diff --git a/ppapi/proxy/ppb_font_proxy.cc b/ppapi/proxy/ppb_font_proxy.cc
new file mode 100644
index 0000000..38b00e2
--- /dev/null
+++ b/ppapi/proxy/ppb_font_proxy.cc
@@ -0,0 +1,233 @@
+// 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_font_proxy.h"
+
+#include "base/bind.h"
+#include "base/debug/trace_event.h"
+#include "ppapi/c/dev/ppb_font_dev.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_image_data_proxy.h"
+#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/shared_impl/ppapi_preferences.h"
+#include "ppapi/shared_impl/resource_object_base.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_image_data_api.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_ImageData_API;
+using ppapi::WebKitForwarding;
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+bool PPTextRunToTextRun(const PP_TextRun_Dev* run,
+ WebKitForwarding::Font::TextRun* output) {
+ const std::string* str = PluginVarTracker::GetInstance()->GetExistingString(
+ run->text);
+ if (!str)
+ return false;
+
+ output->text = *str;
+ output->rtl = PP_ToBool(run->rtl);
+ output->override_direction = PP_ToBool(run->override_direction);
+ return true;
+}
+
+InterfaceProxy* CreateFontProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Font_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_Font_Proxy::PPB_Font_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_Font_Proxy::~PPB_Font_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Font_Proxy::GetInfo() {
+ static const Info info = {
+ ::ppapi::thunk::GetPPB_Font_Thunk(),
+ PPB_FONT_DEV_INTERFACE,
+ INTERFACE_ID_PPB_FONT,
+ false,
+ &CreateFontProxy,
+ };
+ return &info;
+}
+
+::ppapi::thunk::PPB_Font_FunctionAPI* PPB_Font_Proxy::AsPPB_Font_FunctionAPI() {
+ return this;
+}
+
+PP_Var PPB_Font_Proxy::GetFontFamilies(PP_Instance instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return PP_MakeUndefined();
+
+ // Assume the font families don't change, so we can cache the result globally.
+ static std::string families;
+ if (families.empty()) {
+ dispatcher->SendToBrowser(
+ new PpapiHostMsg_PPBFont_GetFontFamilies(&families));
+ }
+
+ PP_Var result;
+ result.type = PP_VARTYPE_STRING;
+ result.value.as_id = PluginVarTracker::GetInstance()->MakeString(families);
+ return result;
+}
+
+bool PPB_Font_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ // There aren't any font messages.
+ NOTREACHED();
+ return false;
+}
+
+Font::Font(const HostResource& resource,
+ const PP_FontDescription_Dev& desc)
+ : PluginResource(resource),
+ webkit_event_(false, false) {
+ TRACE_EVENT0("ppapi proxy", "Font::Font");
+ const std::string* face = PluginVarTracker::GetInstance()->GetExistingString(
+ desc.face);
+
+ WebKitForwarding* forwarding = GetDispatcher()->GetWebKitForwarding();
+
+ WebKitForwarding::Font* result = NULL;
+ RunOnWebKitThread(base::Bind(&WebKitForwarding::CreateFontForwarding,
+ base::Unretained(forwarding),
+ &webkit_event_, desc,
+ face ? *face : std::string(),
+ GetDispatcher()->preferences(),
+ &result));
+ font_forwarding_.reset(result);
+}
+
+Font::~Font() {
+}
+
+ppapi::thunk::PPB_Font_API* Font::AsPPB_Font_API() {
+ return this;
+}
+
+Font* Font::AsFont() {
+ return this;
+}
+
+PP_Bool Font::Describe(PP_FontDescription_Dev* description,
+ PP_FontMetrics_Dev* metrics) {
+ TRACE_EVENT0("ppapi proxy", "Font::Describe");
+ std::string face;
+ PP_Bool result = PP_FALSE;
+ RunOnWebKitThread(base::Bind(&WebKitForwarding::Font::Describe,
+ base::Unretained(font_forwarding_.get()),
+ &webkit_event_, description, &face, metrics,
+ &result));
+
+ if (result == PP_TRUE) {
+ description->face.type = PP_VARTYPE_STRING;
+ description->face.value.as_id =
+ PluginVarTracker::GetInstance()->MakeString(face);
+ } else {
+ description->face.type = PP_VARTYPE_UNDEFINED;
+ }
+ return result;
+}
+
+PP_Bool Font::DrawTextAt(PP_Resource pp_image_data,
+ const PP_TextRun_Dev* text,
+ const PP_Point* position,
+ uint32_t color,
+ const PP_Rect* clip,
+ PP_Bool image_data_is_opaque) {
+ TRACE_EVENT0("ppapi proxy", "Font::DrawTextAt");
+ // Convert to an ImageData object.
+ EnterResourceNoLock<PPB_ImageData_API> enter(pp_image_data, true);
+ if (enter.failed())
+ return PP_FALSE;
+ ImageData* image_data = static_cast<ImageData*>(enter.object());
+
+ skia::PlatformCanvas* canvas = image_data->mapped_canvas();
+ bool needs_unmapping = false;
+ if (!canvas) {
+ needs_unmapping = true;
+ image_data->Map();
+ canvas = image_data->mapped_canvas();
+ if (!canvas)
+ return PP_FALSE; // Failure mapping.
+ }
+
+ WebKitForwarding::Font::TextRun run;
+ if (!PPTextRunToTextRun(text, &run)) {
+ if (needs_unmapping)
+ image_data->Unmap();
+ return PP_FALSE;
+ }
+ RunOnWebKitThread(base::Bind(
+ &WebKitForwarding::Font::DrawTextAt,
+ base::Unretained(font_forwarding_.get()),
+ &webkit_event_,
+ WebKitForwarding::Font::DrawTextParams(canvas, run, position, color,
+ clip, image_data_is_opaque)));
+
+ if (needs_unmapping)
+ image_data->Unmap();
+ return PP_TRUE;
+}
+
+int32_t Font::MeasureText(const PP_TextRun_Dev* text) {
+ TRACE_EVENT0("ppapi proxy", "Font::MeasureText");
+ WebKitForwarding::Font::TextRun run;
+ if (!PPTextRunToTextRun(text, &run))
+ return -1;
+ int32_t result = -1;
+ RunOnWebKitThread(base::Bind(&WebKitForwarding::Font::MeasureText,
+ base::Unretained(font_forwarding_.get()),
+ &webkit_event_, run, &result));
+ return result;
+}
+
+uint32_t Font::CharacterOffsetForPixel(const PP_TextRun_Dev* text,
+ int32_t pixel_position) {
+ TRACE_EVENT0("ppapi proxy", "Font::CharacterOffsetForPixel");
+ WebKitForwarding::Font::TextRun run;
+ if (!PPTextRunToTextRun(text, &run))
+ return -1;
+ uint32_t result = -1;
+ RunOnWebKitThread(base::Bind(&WebKitForwarding::Font::CharacterOffsetForPixel,
+ base::Unretained(font_forwarding_.get()),
+ &webkit_event_, run, pixel_position, &result));
+ return result;
+}
+
+int32_t Font::PixelOffsetForCharacter(const PP_TextRun_Dev* text,
+ uint32_t char_offset) {
+ TRACE_EVENT0("ppapi proxy", "Font::PixelOffsetForCharacter");
+ WebKitForwarding::Font::TextRun run;
+ if (!PPTextRunToTextRun(text, &run))
+ return -1;
+ int32_t result = -1;
+ RunOnWebKitThread(base::Bind(&WebKitForwarding::Font::PixelOffsetForCharacter,
+ base::Unretained(font_forwarding_.get()),
+ &webkit_event_, run, char_offset, &result));
+ return result;
+}
+
+void Font::RunOnWebKitThread(const base::Closure& task) {
+ GetDispatcher()->PostToWebKitThread(FROM_HERE, task);
+ webkit_event_.Wait();
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_font_proxy.h b/ppapi/proxy/ppb_font_proxy.h
new file mode 100644
index 0000000..32893ea
--- /dev/null
+++ b/ppapi/proxy/ppb_font_proxy.h
@@ -0,0 +1,92 @@
+// 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_FONT_PROXY_H_
+#define PPAPI_PROXY_PPB_FONT_PROXY_H_
+
+#include "base/basictypes.h"
+#include "base/synchronization/waitable_event.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/shared_impl/webkit_forwarding.h"
+#include "ppapi/thunk/ppb_font_api.h"
+
+struct PPB_Font_Dev;
+
+namespace pp {
+namespace proxy {
+
+class SerializedVarReturnValue;
+
+class PPB_Font_Proxy : public ppapi::FunctionGroupBase,
+ public ppapi::thunk::PPB_Font_FunctionAPI,
+ public InterfaceProxy {
+ public:
+ PPB_Font_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_Font_Proxy();
+
+ static const Info* GetInfo();
+
+ // FunctionGroupBase overrides.
+ virtual ppapi::thunk::PPB_Font_FunctionAPI* AsPPB_Font_FunctionAPI() OVERRIDE;
+
+ // PPB_Font_FunctionAPI implementation.
+ virtual PP_Var GetFontFamilies(PP_Instance instance) OVERRIDE;
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PPB_Font_Proxy);
+};
+
+class Font : public PluginResource,
+ public ppapi::thunk::PPB_Font_API {
+ public:
+ // Note that there isn't a "real" resource in the renderer backing a font,
+ // it lives entirely in the plugin process. So the resource ID in the host
+ // resource should be 0. However, various code assumes the instance in the
+ // host resource is valid (this is how resources are associated with
+ // instances), so that should be set.
+ Font(const HostResource& resource, const PP_FontDescription_Dev& desc);
+ virtual ~Font();
+
+ // ResourceObjectBase.
+ virtual ppapi::thunk::PPB_Font_API* AsPPB_Font_API() OVERRIDE;
+
+ // PluginResource overrides.
+ virtual Font* AsFont() OVERRIDE;
+
+ // PPB_Font_API implementation.
+ virtual PP_Bool Describe(PP_FontDescription_Dev* description,
+ PP_FontMetrics_Dev* metrics) OVERRIDE;
+ virtual PP_Bool DrawTextAt(PP_Resource image_data,
+ const PP_TextRun_Dev* text,
+ const PP_Point* position,
+ uint32_t color,
+ const PP_Rect* clip,
+ PP_Bool image_data_is_opaque) OVERRIDE;
+ virtual int32_t MeasureText(const PP_TextRun_Dev* text) OVERRIDE;
+ virtual uint32_t CharacterOffsetForPixel(const PP_TextRun_Dev* text,
+ int32_t pixel_position) OVERRIDE;
+ virtual int32_t PixelOffsetForCharacter(const PP_TextRun_Dev* text,
+ uint32_t char_offset) OVERRIDE;
+
+ private:
+ // Posts the given closure to the WebKit thread and waits on the
+ // webkit_event_ for the task to continue.
+ void RunOnWebKitThread(const base::Closure& task);
+
+ base::WaitableEvent webkit_event_;
+
+ scoped_ptr<ppapi::WebKitForwarding::Font> font_forwarding_;
+
+ DISALLOW_COPY_AND_ASSIGN(Font);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_FONT_PROXY_H_
diff --git a/ppapi/proxy/ppb_graphics_2d_proxy.cc b/ppapi/proxy/ppb_graphics_2d_proxy.cc
new file mode 100644
index 0000000..0f8a247
--- /dev/null
+++ b/ppapi/proxy/ppb_graphics_2d_proxy.cc
@@ -0,0 +1,270 @@
+// 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_graphics_2d_proxy.h"
+
+#include <string.h> // For memset.
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/ppb_graphics_2d.h"
+#include "ppapi/proxy/enter_proxy.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_graphics_2d_api.h"
+#include "ppapi/thunk/thunk.h"
+
+using ::ppapi::thunk::PPB_Graphics2D_API;
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+InterfaceProxy* CreateGraphics2DProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Graphics2D_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+class Graphics2D : public PluginResource,
+ public ::ppapi::thunk::PPB_Graphics2D_API {
+ public:
+ Graphics2D(const HostResource& host_resource,
+ const PP_Size& size,
+ PP_Bool is_always_opaque);
+ virtual ~Graphics2D();
+
+ // ResourceObjectBase.
+ virtual PPB_Graphics2D_API* AsPPB_Graphics2D_API();
+
+ // PPB_Graphics_2D_API.
+ PP_Bool Describe(PP_Size* size, PP_Bool* is_always_opaque);
+ void PaintImageData(PP_Resource image_data,
+ const PP_Point* top_left,
+ const PP_Rect* src_rect);
+ void Scroll(const PP_Rect* clip_rect,
+ const PP_Point* amount);
+ void ReplaceContents(PP_Resource image_data);
+ int32_t Flush(PP_CompletionCallback callback);
+
+ // Notification that the host has sent an ACK for a pending Flush.
+ void FlushACK(int32_t result_code);
+
+ private:
+ PP_Size size_;
+ PP_Bool is_always_opaque_;
+
+ // In the plugin, this is the current callback set for Flushes. When the
+ // callback function pointer is non-NULL, we're waiting for a flush ACK.
+ PP_CompletionCallback current_flush_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(Graphics2D);
+};
+
+Graphics2D::Graphics2D(const HostResource& host_resource,
+ const PP_Size& size,
+ PP_Bool is_always_opaque)
+ : PluginResource(host_resource),
+ size_(size),
+ is_always_opaque_(is_always_opaque),
+ current_flush_callback_(PP_BlockUntilComplete()) {
+}
+
+Graphics2D::~Graphics2D() {
+}
+
+PPB_Graphics2D_API* Graphics2D::AsPPB_Graphics2D_API() {
+ return this;
+}
+
+PP_Bool Graphics2D::Describe(PP_Size* size, PP_Bool* is_always_opaque) {
+ *size = size_;
+ *is_always_opaque = is_always_opaque_;
+ return PP_TRUE;
+}
+
+void Graphics2D::PaintImageData(PP_Resource image_data,
+ const PP_Point* top_left,
+ const PP_Rect* src_rect) {
+ PluginResource* image_object = PluginResourceTracker::GetInstance()->
+ GetResourceObject(image_data);
+ //if (!image_object || instance() != image_object->instance())
+ // return;
+
+ PP_Rect dummy;
+ memset(&dummy, 0, sizeof(PP_Rect));
+ GetDispatcher()->Send(new PpapiHostMsg_PPBGraphics2D_PaintImageData(
+ INTERFACE_ID_PPB_GRAPHICS_2D, host_resource(),
+ image_object->host_resource(), *top_left, !!src_rect,
+ src_rect ? *src_rect : dummy));
+}
+
+void Graphics2D::Scroll(const PP_Rect* clip_rect,
+ const PP_Point* amount) {
+ PP_Rect dummy;
+ memset(&dummy, 0, sizeof(PP_Rect));
+ GetDispatcher()->Send(new PpapiHostMsg_PPBGraphics2D_Scroll(
+ INTERFACE_ID_PPB_GRAPHICS_2D, host_resource(),
+ !!clip_rect, clip_rect ? *clip_rect : dummy, *amount));
+}
+
+void Graphics2D::ReplaceContents(PP_Resource image_data) {
+ PluginResource* image_object = PluginResourceTracker::GetInstance()->
+ GetResourceObject(image_data);
+ if (!image_object || instance() != image_object->instance())
+ return;
+
+ GetDispatcher()->Send(new PpapiHostMsg_PPBGraphics2D_ReplaceContents(
+ INTERFACE_ID_PPB_GRAPHICS_2D, host_resource(),
+ image_object->host_resource()));
+}
+
+int32_t Graphics2D::Flush(PP_CompletionCallback callback) {
+ // For now, disallow blocking calls. We'll need to add support for other
+ // threads to this later.
+ if (!callback.func)
+ return PP_ERROR_BADARGUMENT;
+
+ if (current_flush_callback_.func)
+ return PP_ERROR_INPROGRESS; // Can't have >1 flush pending.
+ current_flush_callback_ = callback;
+
+ GetDispatcher()->Send(new PpapiHostMsg_PPBGraphics2D_Flush(
+ INTERFACE_ID_PPB_GRAPHICS_2D, host_resource()));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void Graphics2D::FlushACK(int32_t result_code) {
+ PP_RunAndClearCompletionCallback(&current_flush_callback_, result_code);
+}
+
+PPB_Graphics2D_Proxy::PPB_Graphics2D_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface),
+ callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+}
+
+PPB_Graphics2D_Proxy::~PPB_Graphics2D_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Graphics2D_Proxy::GetInfo() {
+ static const Info info = {
+ ::ppapi::thunk::GetPPB_Graphics2D_Thunk(),
+ PPB_GRAPHICS_2D_INTERFACE,
+ INTERFACE_ID_PPB_GRAPHICS_2D,
+ false,
+ &CreateGraphics2DProxy,
+ };
+ return &info;
+}
+
+// static
+PP_Resource PPB_Graphics2D_Proxy::CreateProxyResource(
+ PP_Instance instance,
+ const PP_Size& size,
+ PP_Bool is_always_opaque) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+
+ HostResource result;
+ dispatcher->Send(new PpapiHostMsg_ResourceCreation_Graphics2D(
+ INTERFACE_ID_RESOURCE_CREATION, instance, size, is_always_opaque,
+ &result));
+ if (result.is_null())
+ return 0;
+ linked_ptr<Graphics2D> graphics_2d(new Graphics2D(result, size,
+ is_always_opaque));
+ return PluginResourceTracker::GetInstance()->AddResource(graphics_2d);
+}
+
+bool PPB_Graphics2D_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Graphics2D_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_PaintImageData,
+ OnMsgPaintImageData)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_Scroll,
+ OnMsgScroll)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_ReplaceContents,
+ OnMsgReplaceContents)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics2D_Flush,
+ OnMsgFlush)
+
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBGraphics2D_FlushACK,
+ OnMsgFlushACK)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ // FIXME(brettw) handle bad messages!
+ return handled;
+}
+
+void PPB_Graphics2D_Proxy::OnMsgPaintImageData(
+ const HostResource& graphics_2d,
+ const HostResource& image_data,
+ const PP_Point& top_left,
+ bool src_rect_specified,
+ const PP_Rect& src_rect) {
+ EnterHostFromHostResource<PPB_Graphics2D_API> enter(graphics_2d);
+ if (enter.failed())
+ return;
+ enter.object()->PaintImageData(image_data.host_resource(), &top_left,
+ src_rect_specified ? &src_rect : NULL);
+}
+
+void PPB_Graphics2D_Proxy::OnMsgScroll(const HostResource& graphics_2d,
+ bool clip_specified,
+ const PP_Rect& clip,
+ const PP_Point& amount) {
+ EnterHostFromHostResource<PPB_Graphics2D_API> enter(graphics_2d);
+ if (enter.failed())
+ return;
+ enter.object()->Scroll(clip_specified ? &clip : NULL, &amount);
+}
+
+void PPB_Graphics2D_Proxy::OnMsgReplaceContents(
+ const HostResource& graphics_2d,
+ const HostResource& image_data) {
+ EnterHostFromHostResource<PPB_Graphics2D_API> enter(graphics_2d);
+ if (enter.failed())
+ return;
+ enter.object()->ReplaceContents(image_data.host_resource());
+}
+
+void PPB_Graphics2D_Proxy::OnMsgFlush(const HostResource& graphics_2d) {
+ CompletionCallback callback = callback_factory_.NewOptionalCallback(
+ &PPB_Graphics2D_Proxy::SendFlushACKToPlugin, graphics_2d);
+ int32_t result = ppb_graphics_2d_target()->Flush(
+ graphics_2d.host_resource(), callback.pp_completion_callback());
+ if (result != PP_OK_COMPLETIONPENDING) {
+ // There was some error, so we won't get a flush callback. We need to now
+ // issue the ACK to the plugin hears about the error. This will also clean
+ // up the data associated with the callback.
+ callback.Run(result);
+ }
+}
+
+void PPB_Graphics2D_Proxy::OnMsgFlushACK(const HostResource& host_resource,
+ int32_t pp_error) {
+ EnterPluginFromHostResource<PPB_Graphics2D_API> enter(host_resource);
+ if (enter.succeeded())
+ static_cast<Graphics2D*>(enter.object())->FlushACK(pp_error);
+}
+
+void PPB_Graphics2D_Proxy::SendFlushACKToPlugin(
+ int32_t result,
+ const HostResource& graphics_2d) {
+ dispatcher()->Send(new PpapiMsg_PPBGraphics2D_FlushACK(
+ INTERFACE_ID_PPB_GRAPHICS_2D, graphics_2d, result));
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_graphics_2d_proxy.h b/ppapi/proxy/ppb_graphics_2d_proxy.h
new file mode 100644
index 0000000..9be7f83
--- /dev/null
+++ b/ppapi/proxy/ppb_graphics_2d_proxy.h
@@ -0,0 +1,76 @@
+// 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_PPB_GRAPHICS_2D_PROXY_H_
+#define PPAPI_PPB_GRAPHICS_2D_PROXY_H_
+
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_size.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/cpp/completion_callback.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h"
+
+struct PPB_Graphics2D;
+struct PP_Point;
+struct PP_Rect;
+
+namespace pp {
+namespace proxy {
+
+class PPB_Graphics2D_Proxy : public InterfaceProxy {
+ public:
+ PPB_Graphics2D_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_Graphics2D_Proxy();
+
+ static const Info* GetInfo();
+
+ static PP_Resource CreateProxyResource(PP_Instance instance,
+ const PP_Size& size,
+ PP_Bool is_always_opaque);
+
+ const PPB_Graphics2D* ppb_graphics_2d_target() const {
+ return static_cast<const PPB_Graphics2D*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Plugin->renderer message handlers.
+ void OnMsgPaintImageData(const HostResource& graphics_2d,
+ const HostResource& image_data,
+ const PP_Point& top_left,
+ bool src_rect_specified,
+ const PP_Rect& src_rect);
+ void OnMsgScroll(const HostResource& graphics_2d,
+ bool clip_specified,
+ const PP_Rect& clip,
+ const PP_Point& amount);
+ void OnMsgReplaceContents(const HostResource& graphics_2d,
+ const HostResource& image_data);
+ void OnMsgFlush(const HostResource& graphics_2d);
+
+ // Renderer->plugin message handlers.
+ void OnMsgFlushACK(const HostResource& graphics_2d,
+ int32_t pp_error);
+
+ // Called in the renderer to send the given flush ACK to the plugin.
+ void SendFlushACKToPlugin(int32_t result,
+ const HostResource& graphics_2d);
+
+ CompletionCallbackFactory<PPB_Graphics2D_Proxy,
+ ProxyNonThreadSafeRefCount> callback_factory_;
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PPB_GRAPHICS_2D_PROXY_H_
diff --git a/ppapi/proxy/ppb_image_data_proxy.cc b/ppapi/proxy/ppb_image_data_proxy.cc
new file mode 100644
index 0000000..18f9e02
--- /dev/null
+++ b/ppapi/proxy/ppb_image_data_proxy.cc
@@ -0,0 +1,138 @@
+// 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_image_data_proxy.h"
+
+#include <string.h> // For memcpy
+
+#include <vector>
+
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/thunk/thunk.h"
+#include "skia/ext/platform_canvas.h"
+#include "ui/gfx/surface/transport_dib.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+InterfaceProxy* CreateImageDataProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_ImageData_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+// PPB_ImageData_Proxy ---------------------------------------------------------
+
+PPB_ImageData_Proxy::PPB_ImageData_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_ImageData_Proxy::~PPB_ImageData_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_ImageData_Proxy::GetInfo() {
+ static const Info info = {
+ ::ppapi::thunk::GetPPB_ImageData_Thunk(),
+ PPB_IMAGEDATA_INTERFACE,
+ INTERFACE_ID_PPB_IMAGE_DATA,
+ false,
+ &CreateImageDataProxy,
+ };
+ return &info;
+}
+
+bool PPB_ImageData_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ return false;
+}
+
+// ImageData -------------------------------------------------------------------
+
+ImageData::ImageData(const HostResource& resource,
+ const PP_ImageDataDesc& desc,
+ ImageHandle handle)
+ : PluginResource(resource),
+ desc_(desc) {
+#if defined(OS_WIN)
+ transport_dib_.reset(TransportDIB::CreateWithHandle(handle));
+#else
+ transport_dib_.reset(TransportDIB::Map(handle));
+#endif
+}
+
+ImageData::~ImageData() {
+}
+
+::ppapi::thunk::PPB_ImageData_API* ImageData::AsPPB_ImageData_API() {
+ return this;
+}
+
+ImageData* ImageData::AsImageData() {
+ return this;
+}
+
+PP_Bool ImageData::Describe(PP_ImageDataDesc* desc) {
+ memcpy(desc, &desc_, sizeof(PP_ImageDataDesc));
+ return PP_TRUE;
+}
+
+void* ImageData::Map() {
+ if (!mapped_canvas_.get()) {
+ mapped_canvas_.reset(transport_dib_->GetPlatformCanvas(desc_.size.width,
+ desc_.size.height));
+ if (!mapped_canvas_.get())
+ return NULL;
+ }
+ const SkBitmap& bitmap =
+ skia::GetTopDevice(*mapped_canvas_)->accessBitmap(true);
+
+ bitmap.lockPixels();
+ return bitmap.getAddr(0, 0);
+}
+
+void ImageData::Unmap() {
+ // TODO(brettw) have a way to unmap a TransportDIB. Currently this isn't
+ // possible since deleting the TransportDIB also frees all the handles.
+ // We need to add a method to TransportDIB to release the handles.
+}
+
+int32_t ImageData::GetSharedMemory(int* /* handle */,
+ uint32_t* /* byte_count */) {
+ // Not supported in the proxy (this method is for actually implementing the
+ // proxy in the host).
+ return PP_ERROR_NOACCESS;
+}
+
+#if defined(OS_WIN)
+const ImageHandle ImageData::NullHandle = NULL;
+#elif defined(OS_MACOSX)
+const ImageHandle ImageData::NullHandle = ImageHandle();
+#else
+const ImageHandle ImageData::NullHandle = 0;
+#endif
+
+ImageHandle ImageData::HandleFromInt(int32_t i) {
+#if defined(OS_WIN)
+ return reinterpret_cast<ImageHandle>(i);
+#elif defined(OS_MACOSX)
+ return ImageHandle(i, false);
+#else
+ return static_cast<ImageHandle>(i);
+#endif
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_image_data_proxy.h b/ppapi/proxy/ppb_image_data_proxy.h
new file mode 100644
index 0000000..23cf442
--- /dev/null
+++ b/ppapi/proxy/ppb_image_data_proxy.h
@@ -0,0 +1,90 @@
+// 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_PPB_IMAGE_DATA_PROXY_H_
+#define PPAPI_PPB_IMAGE_DATA_PROXY_H_
+
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_size.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/serialized_structs.h"
+#include "ppapi/shared_impl/image_data_impl.h"
+#include "ppapi/thunk/ppb_image_data_api.h"
+
+struct PPB_ImageData;
+class TransportDIB;
+
+namespace skia {
+class PlatformCanvas;
+}
+
+namespace pp {
+namespace proxy {
+
+class HostResource;
+
+class PPB_ImageData_Proxy : public InterfaceProxy {
+ public:
+ PPB_ImageData_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_ImageData_Proxy();
+
+ static const Info* GetInfo();
+
+ const PPB_ImageData* ppb_image_data_target() const {
+ return static_cast<const PPB_ImageData*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+};
+
+class ImageData : public PluginResource,
+ public ::ppapi::thunk::PPB_ImageData_API,
+ public ppapi::ImageDataImpl {
+ public:
+ ImageData(const HostResource& resource,
+ const PP_ImageDataDesc& desc,
+ ImageHandle handle);
+ virtual ~ImageData();
+
+ // ResourceObjectBase overrides.
+ virtual ::ppapi::thunk::PPB_ImageData_API* AsPPB_ImageData_API() OVERRIDE;
+
+ // Resource overrides.
+ virtual ImageData* AsImageData() OVERRIDE;
+
+ // PPB_ImageData API.
+ virtual PP_Bool Describe(PP_ImageDataDesc* desc) OVERRIDE;
+ virtual void* Map() OVERRIDE;
+ virtual void Unmap() OVERRIDE;
+ virtual int32_t GetSharedMemory(int* handle, uint32_t* byte_count) OVERRIDE;
+
+ skia::PlatformCanvas* mapped_canvas() const { return mapped_canvas_.get(); }
+
+ const PP_ImageDataDesc& desc() const { return desc_; }
+
+ static const ImageHandle NullHandle;
+ static ImageHandle HandleFromInt(int32_t i);
+
+ private:
+ PP_ImageDataDesc desc_;
+
+ scoped_ptr<TransportDIB> transport_dib_;
+
+ // Null when the image isn't mapped.
+ scoped_ptr<skia::PlatformCanvas> mapped_canvas_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImageData);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PPB_IMAGE_DATA_PROXY_H_
diff --git a/ppapi/proxy/ppb_input_event_proxy.cc b/ppapi/proxy/ppb_input_event_proxy.cc
new file mode 100644
index 0000000..d5c6f4b
--- /dev/null
+++ b/ppapi/proxy/ppb_input_event_proxy.cc
@@ -0,0 +1,102 @@
+// 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_input_event_proxy.h"
+
+#include "ppapi/c/ppb_audio_config.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/input_event_impl.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::InputEventData;
+using ppapi::InputEventImpl;
+using ppapi::thunk::PPB_InputEvent_API;
+
+namespace pp {
+namespace proxy {
+
+// The implementation is actually in InputEventImpl.
+class InputEvent : public PluginResource, public InputEventImpl {
+ public:
+ InputEvent(const HostResource& resource, const InputEventData& data);
+ virtual ~InputEvent();
+
+ // ResourceObjectBase overrides.
+ virtual PPB_InputEvent_API* AsPPB_InputEvent_API() OVERRIDE;
+
+ // InputEventImpl overrides.
+ virtual PP_Var StringToPPVar(const std::string& str) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InputEvent);
+};
+
+InputEvent::InputEvent(const HostResource& resource, const InputEventData& data)
+ : PluginResource(resource),
+ InputEventImpl(data) {
+}
+
+InputEvent::~InputEvent() {
+}
+
+PPB_InputEvent_API* InputEvent::AsPPB_InputEvent_API() {
+ return this;
+}
+
+PP_Var InputEvent::StringToPPVar(const std::string& str) {
+ PP_Var ret;
+ ret.type = PP_VARTYPE_STRING;
+ ret.value.as_id = PluginVarTracker::GetInstance()->MakeString(str);
+ return ret;
+}
+
+namespace {
+
+InterfaceProxy* CreateInputEventProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_InputEvent_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_InputEvent_Proxy::PPB_InputEvent_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_InputEvent_Proxy::~PPB_InputEvent_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_InputEvent_Proxy::GetInfo() {
+ static const Info info = {
+ ::ppapi::thunk::GetPPB_InputEvent_Thunk(),
+ PPB_INPUT_EVENT_INTERFACE,
+ INTERFACE_ID_NONE,
+ false,
+ &CreateInputEventProxy,
+ };
+ return &info;
+}
+
+// static
+PP_Resource PPB_InputEvent_Proxy::CreateProxyResource(
+ PP_Instance instance,
+ const InputEventData& data) {
+ linked_ptr<InputEvent> object(new InputEvent(
+ HostResource::MakeInstanceOnly(instance), data));
+ return PluginResourceTracker::GetInstance()->AddResource(object);
+}
+
+bool PPB_InputEvent_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ // There are no IPC messages for this interface.
+ NOTREACHED();
+ return false;
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_input_event_proxy.h b/ppapi/proxy/ppb_input_event_proxy.h
new file mode 100644
index 0000000..bd80535
--- /dev/null
+++ b/ppapi/proxy/ppb_input_event_proxy.h
@@ -0,0 +1,40 @@
+// 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_INPUT_EVENT_PROXY_H_
+#define PPAPI_PROXY_PPB_INPUT_EVENT_PROXY_H_
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/shared_impl/input_event_impl.h"
+
+namespace ppapi {
+struct InputEventData;
+}
+
+namespace pp {
+namespace proxy {
+
+class PPB_InputEvent_Proxy : public InterfaceProxy {
+ public:
+ PPB_InputEvent_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_InputEvent_Proxy();
+
+ static const Info* GetInfo();
+
+ static PP_Resource CreateProxyResource(PP_Instance instance,
+ const ppapi::InputEventData& data);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PPB_InputEvent_Proxy);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_INPUT_EVENT_PROXY_H_
diff --git a/ppapi/proxy/ppb_instance_proxy.cc b/ppapi/proxy/ppb_instance_proxy.cc
new file mode 100644
index 0000000..7bb6ba1
--- /dev/null
+++ b/ppapi/proxy/ppb_instance_proxy.cc
@@ -0,0 +1,367 @@
+// 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_instance_proxy.h"
+
+#include "ppapi/c/dev/ppb_fullscreen_dev.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_instance.h"
+#include "ppapi/c/ppb_messaging.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/thunk.h"
+
+// Windows headers interfere with this file.
+#ifdef PostMessage
+#undef PostMessage
+#endif
+
+using ppapi::thunk::EnterFunctionNoLock;
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_Instance_FunctionAPI;
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+InterfaceProxy* CreateInstanceProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Instance_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_Instance_Proxy::PPB_Instance_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_Instance_Proxy::~PPB_Instance_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Instance_Proxy::GetInfo0_5() {
+ static const Info info = {
+ ppapi::thunk::GetPPB_Instance_1_0_Thunk(),
+ PPB_INSTANCE_INTERFACE_0_5,
+ INTERFACE_ID_NONE, // 1_0 is the canonical one.
+ false,
+ &CreateInstanceProxy,
+ };
+ return &info;
+}
+
+// static
+const InterfaceProxy::Info* PPB_Instance_Proxy::GetInfo1_0() {
+ static const Info info = {
+ ppapi::thunk::GetPPB_Instance_1_0_Thunk(),
+ PPB_INSTANCE_INTERFACE_1_0,
+ INTERFACE_ID_PPB_INSTANCE,
+ false,
+ &CreateInstanceProxy,
+ };
+ return &info;
+}
+
+// static
+const InterfaceProxy::Info* PPB_Instance_Proxy::GetInfoMessaging() {
+ static const Info info = {
+ ppapi::thunk::GetPPB_Messaging_Thunk(),
+ PPB_MESSAGING_INTERFACE,
+ INTERFACE_ID_NONE, // 1_0 is the canonical one.
+ false,
+ &CreateInstanceProxy,
+ };
+ return &info;
+}
+
+// static
+const InterfaceProxy::Info* PPB_Instance_Proxy::GetInfoPrivate() {
+ static const Info info = {
+ ppapi::thunk::GetPPB_Instance_Private_Thunk(),
+ PPB_INSTANCE_PRIVATE_INTERFACE,
+ INTERFACE_ID_NONE, // 1_0 is the canonical one.
+ false,
+ &CreateInstanceProxy,
+ };
+ return &info;
+}
+
+// static
+const InterfaceProxy::Info* PPB_Instance_Proxy::GetInfoFullscreen() {
+ static const Info info = {
+ ppapi::thunk::GetPPB_Fullscreen_Thunk(),
+ PPB_FULLSCREEN_DEV_INTERFACE,
+ INTERFACE_ID_NONE, // 1_0 is the canonical one.
+ false,
+ &CreateInstanceProxy,
+ };
+ return &info;
+}
+
+bool PPB_Instance_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ // Prevent the dispatcher from going away during a call to ExecuteScript.
+ // This must happen OUTSIDE of ExecuteScript since the SerializedVars use
+ // the dispatcher upon return of the function (converting the
+ // SerializedVarReturnValue/OutParam to a SerializedVar in the destructor).
+ ScopedModuleReference death_grip(dispatcher());
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Instance_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetWindowObject,
+ OnMsgGetWindowObject)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetOwnerElementObject,
+ OnMsgGetOwnerElementObject)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_BindGraphics,
+ OnMsgBindGraphics)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_IsFullFrame,
+ OnMsgIsFullFrame)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_ExecuteScript,
+ OnMsgExecuteScript)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_PostMessage,
+ OnMsgPostMessage)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SetFullscreen,
+ OnMsgSetFullscreen)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetScreenSize,
+ OnMsgGetScreenSize)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_RequestInputEvents,
+ OnMsgRequestInputEvents)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_ClearInputEvents,
+ OnMsgClearInputEvents)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+PPB_Instance_FunctionAPI* PPB_Instance_Proxy::AsPPB_Instance_FunctionAPI() {
+ return this;
+}
+
+PP_Bool PPB_Instance_Proxy::BindGraphics(PP_Instance instance,
+ PP_Resource device) {
+ PluginResource* object =
+ PluginResourceTracker::GetInstance()->GetResourceObject(device);
+ if (!object || object->instance() != instance)
+ return PP_FALSE;
+
+ PP_Bool result = PP_FALSE;
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_BindGraphics(
+ INTERFACE_ID_PPB_INSTANCE, instance, object->host_resource(),
+ &result));
+ return result;
+}
+
+PP_Bool PPB_Instance_Proxy::IsFullFrame(PP_Instance instance) {
+ PP_Bool result = PP_FALSE;
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_IsFullFrame(
+ INTERFACE_ID_PPB_INSTANCE, instance, &result));
+ return result;
+}
+
+PP_Var PPB_Instance_Proxy::GetWindowObject(PP_Instance instance) {
+ ReceiveSerializedVarReturnValue result;
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetWindowObject(
+ INTERFACE_ID_PPB_INSTANCE, instance, &result));
+ return result.Return(dispatcher());
+}
+
+PP_Var PPB_Instance_Proxy::GetOwnerElementObject(PP_Instance instance) {
+ ReceiveSerializedVarReturnValue result;
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetOwnerElementObject(
+ INTERFACE_ID_PPB_INSTANCE, instance, &result));
+ return result.Return(dispatcher());
+}
+
+PP_Var PPB_Instance_Proxy::ExecuteScript(PP_Instance instance,
+ PP_Var script,
+ PP_Var* exception) {
+ ReceiveSerializedException se(dispatcher(), exception);
+ if (se.IsThrown())
+ return PP_MakeUndefined();
+
+ ReceiveSerializedVarReturnValue result;
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_ExecuteScript(
+ INTERFACE_ID_PPB_INSTANCE, instance,
+ SerializedVarSendInput(dispatcher(), script), &se, &result));
+ return result.Return(dispatcher());
+}
+
+PP_Bool PPB_Instance_Proxy::IsFullscreen(PP_Instance instance) {
+ InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
+ GetInstanceData(instance);
+ if (!data)
+ return PP_FALSE;
+ return data->fullscreen;
+}
+
+PP_Bool PPB_Instance_Proxy::SetFullscreen(PP_Instance instance,
+ PP_Bool fullscreen) {
+ PP_Bool result = PP_FALSE;
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_SetFullscreen(
+ INTERFACE_ID_PPB_INSTANCE, instance, fullscreen, &result));
+ return result;
+}
+
+PP_Bool PPB_Instance_Proxy::GetScreenSize(PP_Instance instance,
+ PP_Size* size) {
+ PP_Bool result = PP_FALSE;
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetScreenSize(
+ INTERFACE_ID_PPB_INSTANCE, instance, &result, size));
+ return result;
+}
+
+int32_t PPB_Instance_Proxy::RequestInputEvents(PP_Instance instance,
+ uint32_t event_classes) {
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_RequestInputEvents(
+ INTERFACE_ID_PPB_INSTANCE, instance, false, event_classes));
+
+ // We always register for the classes we can handle, this function validates
+ // the flags so we can notify it if anything was invalid, without requiring
+ // a sync reply.
+ return ValidateRequestInputEvents(false, event_classes);
+}
+
+int32_t PPB_Instance_Proxy::RequestFilteringInputEvents(
+ PP_Instance instance,
+ uint32_t event_classes) {
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_RequestInputEvents(
+ INTERFACE_ID_PPB_INSTANCE, instance, true, event_classes));
+
+ // We always register for the classes we can handle, this function validates
+ // the flags so we can notify it if anything was invalid, without requiring
+ // a sync reply.
+ return ValidateRequestInputEvents(true, event_classes);
+}
+
+void PPB_Instance_Proxy::ClearInputEventRequest(PP_Instance instance,
+ uint32_t event_classes) {
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_ClearInputEvents(
+ INTERFACE_ID_PPB_INSTANCE, instance, event_classes));
+}
+
+void PPB_Instance_Proxy::ZoomChanged(PP_Instance instance,
+ double factor) {
+ // Not proxied yet.
+ NOTIMPLEMENTED();
+}
+
+void PPB_Instance_Proxy::ZoomLimitsChanged(PP_Instance instance,
+ double minimum_factor,
+ double maximium_factor) {
+ // Not proxied yet.
+ NOTIMPLEMENTED();
+}
+
+void PPB_Instance_Proxy::PostMessage(PP_Instance instance,
+ PP_Var message) {
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_PostMessage(
+ INTERFACE_ID_PPB_INSTANCE,
+ instance, SerializedVarSendInput(dispatcher(), message)));
+}
+
+void PPB_Instance_Proxy::OnMsgGetWindowObject(
+ PP_Instance instance,
+ SerializedVarReturnValue result) {
+ EnterFunctionNoLock<PPB_Instance_FunctionAPI> enter(instance, false);
+ if (enter.succeeded())
+ result.Return(dispatcher(), enter.functions()->GetWindowObject(instance));
+}
+
+void PPB_Instance_Proxy::OnMsgGetOwnerElementObject(
+ PP_Instance instance,
+ SerializedVarReturnValue result) {
+ EnterFunctionNoLock<PPB_Instance_FunctionAPI> enter(instance, false);
+ if (enter.succeeded()) {
+ result.Return(dispatcher(),
+ enter.functions()->GetOwnerElementObject(instance));
+ }
+}
+
+void PPB_Instance_Proxy::OnMsgBindGraphics(PP_Instance instance,
+ HostResource device,
+ PP_Bool* result) {
+ EnterFunctionNoLock<PPB_Instance_FunctionAPI> enter(instance, false);
+ if (enter.succeeded()) {
+ *result = enter.functions()->BindGraphics(instance,
+ device.host_resource());
+ }
+}
+
+void PPB_Instance_Proxy::OnMsgIsFullFrame(PP_Instance instance,
+ PP_Bool* result) {
+ EnterFunctionNoLock<PPB_Instance_FunctionAPI> enter(instance, false);
+ if (enter.succeeded())
+ *result = enter.functions()->IsFullFrame(instance);
+}
+
+void PPB_Instance_Proxy::OnMsgExecuteScript(
+ PP_Instance instance,
+ SerializedVarReceiveInput script,
+ SerializedVarOutParam out_exception,
+ SerializedVarReturnValue result) {
+ EnterFunctionNoLock<PPB_Instance_FunctionAPI> enter(instance, false);
+ if (enter.failed())
+ return;
+
+ if (dispatcher()->IsPlugin())
+ NOTREACHED();
+ else
+ static_cast<HostDispatcher*>(dispatcher())->set_allow_plugin_reentrancy();
+
+ result.Return(dispatcher(), enter.functions()->ExecuteScript(
+ instance,
+ script.Get(dispatcher()),
+ out_exception.OutParam(dispatcher())));
+}
+
+void PPB_Instance_Proxy::OnMsgSetFullscreen(PP_Instance instance,
+ PP_Bool fullscreen,
+ PP_Bool* result) {
+ EnterFunctionNoLock<PPB_Instance_FunctionAPI> enter(instance, false);
+ if (enter.succeeded())
+ *result = enter.functions()->SetFullscreen(instance, fullscreen);
+}
+
+void PPB_Instance_Proxy::OnMsgGetScreenSize(PP_Instance instance,
+ PP_Bool* result,
+ PP_Size* size) {
+ EnterFunctionNoLock<PPB_Instance_FunctionAPI> enter(instance, false);
+ if (enter.succeeded())
+ *result = enter.functions()->GetScreenSize(instance, size);
+}
+
+void PPB_Instance_Proxy::OnMsgRequestInputEvents(PP_Instance instance,
+ bool is_filtering,
+ uint32_t event_classes) {
+ EnterFunctionNoLock<PPB_Instance_FunctionAPI> enter(instance, false);
+ if (enter.succeeded()) {
+ if (is_filtering)
+ enter.functions()->RequestFilteringInputEvents(instance, event_classes);
+ else
+ enter.functions()->RequestInputEvents(instance, event_classes);
+ }
+}
+
+void PPB_Instance_Proxy::OnMsgClearInputEvents(PP_Instance instance,
+ uint32_t event_classes) {
+ EnterFunctionNoLock<PPB_Instance_FunctionAPI> enter(instance, false);
+ if (enter.succeeded())
+ enter.functions()->ClearInputEventRequest(instance, event_classes);
+}
+
+void PPB_Instance_Proxy::OnMsgPostMessage(PP_Instance instance,
+ SerializedVarReceiveInput message) {
+ EnterFunctionNoLock<PPB_Instance_FunctionAPI> enter(instance, false);
+ if (enter.succeeded())
+ enter.functions()->PostMessage(instance, message.Get(dispatcher()));
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_instance_proxy.h b/ppapi/proxy/ppb_instance_proxy.h
new file mode 100644
index 0000000..fc2dac3
--- /dev/null
+++ b/ppapi/proxy/ppb_instance_proxy.h
@@ -0,0 +1,101 @@
+// 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_INSTANCE_PROXY_H_
+#define PPAPI_PROXY_PPB_INSTANCE_PROXY_H_
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/shared_impl/function_group_base.h"
+#include "ppapi/shared_impl/instance_impl.h"
+#include "ppapi/thunk/ppb_instance_api.h"
+
+namespace pp {
+namespace proxy {
+
+class SerializedVarReceiveInput;
+class SerializedVarOutParam;
+class SerializedVarReturnValue;
+
+class PPB_Instance_Proxy : public InterfaceProxy,
+ public ppapi::InstanceImpl,
+ public ppapi::FunctionGroupBase,
+ public ppapi::thunk::PPB_Instance_FunctionAPI {
+ public:
+ PPB_Instance_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_Instance_Proxy();
+
+ static const Info* GetInfo0_5();
+ static const Info* GetInfo1_0();
+ static const Info* GetInfoMessaging();
+ static const Info* GetInfoPrivate();
+ static const Info* GetInfoFullscreen();
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ // FunctionGroupBase overrides.
+ ppapi::thunk::PPB_Instance_FunctionAPI* AsPPB_Instance_FunctionAPI() OVERRIDE;
+
+ // PPB_Instance_FunctionAPI implementation.
+ virtual PP_Bool BindGraphics(PP_Instance instance,
+ PP_Resource device) OVERRIDE;
+ virtual PP_Bool IsFullFrame(PP_Instance instance) OVERRIDE;
+ virtual PP_Var GetWindowObject(PP_Instance instance) OVERRIDE;
+ virtual PP_Var GetOwnerElementObject(PP_Instance instance) OVERRIDE;
+ virtual PP_Var ExecuteScript(PP_Instance instance,
+ PP_Var script,
+ PP_Var* exception) OVERRIDE;
+ virtual PP_Bool IsFullscreen(PP_Instance instance) OVERRIDE;
+ virtual PP_Bool SetFullscreen(PP_Instance instance,
+ PP_Bool fullscreen) OVERRIDE;
+ virtual PP_Bool GetScreenSize(PP_Instance instance, PP_Size* size) OVERRIDE;
+ virtual int32_t RequestInputEvents(PP_Instance instance,
+ uint32_t event_classes) OVERRIDE;
+ virtual int32_t RequestFilteringInputEvents(PP_Instance instance,
+ uint32_t event_classes) OVERRIDE;
+ virtual void ClearInputEventRequest(PP_Instance instance,
+ uint32_t event_classes) OVERRIDE;
+ virtual void ZoomChanged(PP_Instance instance, double factor) OVERRIDE;
+ virtual void ZoomLimitsChanged(PP_Instance instance,
+ double minimum_factor,
+ double maximium_factor) OVERRIDE;
+ virtual void PostMessage(PP_Instance instance, PP_Var message) OVERRIDE;
+
+ private:
+ // Message handlers.
+ void OnMsgGetWindowObject(PP_Instance instance,
+ SerializedVarReturnValue result);
+ void OnMsgGetOwnerElementObject(PP_Instance instance,
+ SerializedVarReturnValue result);
+ void OnMsgBindGraphics(PP_Instance instance,
+ HostResource device,
+ PP_Bool* result);
+ void OnMsgIsFullFrame(PP_Instance instance, PP_Bool* result);
+ void OnMsgExecuteScript(PP_Instance instance,
+ SerializedVarReceiveInput script,
+ SerializedVarOutParam out_exception,
+ SerializedVarReturnValue result);
+ void OnMsgSetFullscreen(PP_Instance instance,
+ PP_Bool fullscreen,
+ PP_Bool* result);
+ void OnMsgGetScreenSize(PP_Instance instance,
+ PP_Bool* result,
+ PP_Size* size);
+ void OnMsgRequestInputEvents(PP_Instance instance,
+ bool is_filtering,
+ uint32_t event_classes);
+ void OnMsgClearInputEvents(PP_Instance instance,
+ uint32_t event_classes);
+ void OnMsgPostMessage(PP_Instance instance,
+ SerializedVarReceiveInput message);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_INSTANCE_PROXY_H_
diff --git a/ppapi/proxy/ppb_memory_proxy.cc b/ppapi/proxy/ppb_memory_proxy.cc
new file mode 100644
index 0000000..616e789
--- /dev/null
+++ b/ppapi/proxy/ppb_memory_proxy.cc
@@ -0,0 +1,64 @@
+// 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_memory_proxy.h"
+
+#include "ppapi/c/dev/ppb_memory_dev.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+// PPB_Memory_Dev plugin -------------------------------------------------------
+
+void* MemAlloc(uint32_t num_bytes) {
+ return malloc(num_bytes);
+}
+
+void MemFree(void *ptr) {
+ free(ptr);
+}
+
+const PPB_Memory_Dev memory_dev_interface = {
+ &MemAlloc,
+ &MemFree
+};
+
+InterfaceProxy* CreateMemoryProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Memory_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_Memory_Proxy::PPB_Memory_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_Memory_Proxy::~PPB_Memory_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Memory_Proxy::GetInfo() {
+ static const Info info = {
+ &memory_dev_interface,
+ PPB_MEMORY_DEV_INTERFACE,
+ INTERFACE_ID_PPB_MEMORY,
+ false,
+ &CreateMemoryProxy,
+ };
+ return &info;
+}
+
+bool PPB_Memory_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ // All PPB_Memory_Dev calls are handled locally; there is no need to send or
+ // receive messages here.
+ return false;
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_memory_proxy.h b/ppapi/proxy/ppb_memory_proxy.h
new file mode 100644
index 0000000..503dd70
--- /dev/null
+++ b/ppapi/proxy/ppb_memory_proxy.h
@@ -0,0 +1,36 @@
+// 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_PPB_MEMORY_PROXY_H_
+#define PPAPI_PPB_MEMORY_PROXY_H_
+
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_Memory_Dev;
+
+namespace pp {
+namespace proxy {
+
+class PPB_Memory_Proxy : public InterfaceProxy {
+ public:
+ PPB_Memory_Proxy(Dispatcher* dispatcher,
+ const void* target_interface);
+ virtual ~PPB_Memory_Proxy();
+
+ static const Info* GetInfo();
+
+ const PPB_Memory_Dev* ppb_memory_target() const {
+ return static_cast<const PPB_Memory_Dev*>(target_interface());
+ }
+
+ // InterfaceProxy implementation. In this case, no messages are sent or
+ // received, so this always returns false.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PPB_MEMORY_PROXY_H_
diff --git a/ppapi/proxy/ppb_opengles2_proxy.cc b/ppapi/proxy/ppb_opengles2_proxy.cc
new file mode 100644
index 0000000..ce301c6
--- /dev/null
+++ b/ppapi/proxy/ppb_opengles2_proxy.cc
@@ -0,0 +1,939 @@
+// 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.
+
+// This file is auto-generated from
+// gpu/command_buffer/build_gles2_cmd_buffer.py
+// DO NOT EDIT!
+
+#include "ppapi/proxy/ppb_opengles2_proxy.h"
+
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/dev/ppb_opengles_dev.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppb_context_3d_proxy.h"
+#include "ppapi/shared_impl/resource_object_base.h"
+#include "ppapi/shared_impl/tracker_base.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+gpu::gles2::GLES2Implementation* GetGLES(PP_Resource context) {
+ ppapi::ResourceObjectBase* base =
+ ppapi::TrackerBase::Get()->GetResourceAPI(context);
+ DCHECK(base->AsPPB_Context3D_API());
+ return static_cast<Context3D*>(base)->gles2_impl();
+}
+
+void ActiveTexture(PP_Resource context_id, GLenum texture) {
+ GetGLES(context_id)->ActiveTexture(texture);
+}
+
+void AttachShader(PP_Resource context_id, GLuint program, GLuint shader) {
+ GetGLES(context_id)->AttachShader(program, shader);
+}
+
+void BindAttribLocation(
+ PP_Resource context_id, GLuint program, GLuint index, const char* name) {
+ GetGLES(context_id)->BindAttribLocation(program, index, name);
+}
+
+void BindBuffer(PP_Resource context_id, GLenum target, GLuint buffer) {
+ GetGLES(context_id)->BindBuffer(target, buffer);
+}
+
+void BindFramebuffer(
+ PP_Resource context_id, GLenum target, GLuint framebuffer) {
+ GetGLES(context_id)->BindFramebuffer(target, framebuffer);
+}
+
+void BindRenderbuffer(
+ PP_Resource context_id, GLenum target, GLuint renderbuffer) {
+ GetGLES(context_id)->BindRenderbuffer(target, renderbuffer);
+}
+
+void BindTexture(PP_Resource context_id, GLenum target, GLuint texture) {
+ GetGLES(context_id)->BindTexture(target, texture);
+}
+
+void BlendColor(
+ PP_Resource context_id, GLclampf red, GLclampf green, GLclampf blue,
+ GLclampf alpha) {
+ GetGLES(context_id)->BlendColor(red, green, blue, alpha);
+}
+
+void BlendEquation(PP_Resource context_id, GLenum mode) {
+ GetGLES(context_id)->BlendEquation(mode);
+}
+
+void BlendEquationSeparate(
+ PP_Resource context_id, GLenum modeRGB, GLenum modeAlpha) {
+ GetGLES(context_id)->BlendEquationSeparate(modeRGB, modeAlpha);
+}
+
+void BlendFunc(PP_Resource context_id, GLenum sfactor, GLenum dfactor) {
+ GetGLES(context_id)->BlendFunc(sfactor, dfactor);
+}
+
+void BlendFuncSeparate(
+ PP_Resource context_id, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha,
+ GLenum dstAlpha) {
+ GetGLES(context_id)->BlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+
+void BufferData(
+ PP_Resource context_id, GLenum target, GLsizeiptr size, const void* data,
+ GLenum usage) {
+ GetGLES(context_id)->BufferData(target, size, data, usage);
+}
+
+void BufferSubData(
+ PP_Resource context_id, GLenum target, GLintptr offset, GLsizeiptr size,
+ const void* data) {
+ GetGLES(context_id)->BufferSubData(target, offset, size, data);
+}
+
+GLenum CheckFramebufferStatus(PP_Resource context_id, GLenum target) {
+ return GetGLES(context_id)->CheckFramebufferStatus(target);
+}
+
+void Clear(PP_Resource context_id, GLbitfield mask) {
+ GetGLES(context_id)->Clear(mask);
+}
+
+void ClearColor(
+ PP_Resource context_id, GLclampf red, GLclampf green, GLclampf blue,
+ GLclampf alpha) {
+ GetGLES(context_id)->ClearColor(red, green, blue, alpha);
+}
+
+void ClearDepthf(PP_Resource context_id, GLclampf depth) {
+ GetGLES(context_id)->ClearDepthf(depth);
+}
+
+void ClearStencil(PP_Resource context_id, GLint s) {
+ GetGLES(context_id)->ClearStencil(s);
+}
+
+void ColorMask(
+ PP_Resource context_id, GLboolean red, GLboolean green, GLboolean blue,
+ GLboolean alpha) {
+ GetGLES(context_id)->ColorMask(red, green, blue, alpha);
+}
+
+void CompileShader(PP_Resource context_id, GLuint shader) {
+ GetGLES(context_id)->CompileShader(shader);
+}
+
+void CompressedTexImage2D(
+ PP_Resource context_id, GLenum target, GLint level, GLenum internalformat,
+ GLsizei width, GLsizei height, GLint border, GLsizei imageSize,
+ const void* data) {
+ GetGLES(
+ context_id)->CompressedTexImage2D(
+ target, level, internalformat, width, height, border, imageSize,
+ data);
+}
+
+void CompressedTexSubImage2D(
+ PP_Resource context_id, GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLsizei width, GLsizei height, GLenum format,
+ GLsizei imageSize, const void* data) {
+ GetGLES(
+ context_id)->CompressedTexSubImage2D(
+ target, level, xoffset, yoffset, width, height, format, imageSize,
+ data);
+}
+
+void CopyTexImage2D(
+ PP_Resource context_id, GLenum target, GLint level, GLenum internalformat,
+ GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
+ GetGLES(
+ context_id)->CopyTexImage2D(
+ target, level, internalformat, x, y, width, height, border);
+}
+
+void CopyTexSubImage2D(
+ PP_Resource context_id, GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
+ GetGLES(
+ context_id)->CopyTexSubImage2D(
+ target, level, xoffset, yoffset, x, y, width, height);
+}
+
+GLuint CreateProgram(PP_Resource context_id) {
+ return GetGLES(context_id)->CreateProgram();
+}
+
+GLuint CreateShader(PP_Resource context_id, GLenum type) {
+ return GetGLES(context_id)->CreateShader(type);
+}
+
+void CullFace(PP_Resource context_id, GLenum mode) {
+ GetGLES(context_id)->CullFace(mode);
+}
+
+void DeleteBuffers(PP_Resource context_id, GLsizei n, const GLuint* buffers) {
+ GetGLES(context_id)->DeleteBuffers(n, buffers);
+}
+
+void DeleteFramebuffers(
+ PP_Resource context_id, GLsizei n, const GLuint* framebuffers) {
+ GetGLES(context_id)->DeleteFramebuffers(n, framebuffers);
+}
+
+void DeleteProgram(PP_Resource context_id, GLuint program) {
+ GetGLES(context_id)->DeleteProgram(program);
+}
+
+void DeleteRenderbuffers(
+ PP_Resource context_id, GLsizei n, const GLuint* renderbuffers) {
+ GetGLES(context_id)->DeleteRenderbuffers(n, renderbuffers);
+}
+
+void DeleteShader(PP_Resource context_id, GLuint shader) {
+ GetGLES(context_id)->DeleteShader(shader);
+}
+
+void DeleteTextures(
+ PP_Resource context_id, GLsizei n, const GLuint* textures) {
+ GetGLES(context_id)->DeleteTextures(n, textures);
+}
+
+void DepthFunc(PP_Resource context_id, GLenum func) {
+ GetGLES(context_id)->DepthFunc(func);
+}
+
+void DepthMask(PP_Resource context_id, GLboolean flag) {
+ GetGLES(context_id)->DepthMask(flag);
+}
+
+void DepthRangef(PP_Resource context_id, GLclampf zNear, GLclampf zFar) {
+ GetGLES(context_id)->DepthRangef(zNear, zFar);
+}
+
+void DetachShader(PP_Resource context_id, GLuint program, GLuint shader) {
+ GetGLES(context_id)->DetachShader(program, shader);
+}
+
+void Disable(PP_Resource context_id, GLenum cap) {
+ GetGLES(context_id)->Disable(cap);
+}
+
+void DisableVertexAttribArray(PP_Resource context_id, GLuint index) {
+ GetGLES(context_id)->DisableVertexAttribArray(index);
+}
+
+void DrawArrays(
+ PP_Resource context_id, GLenum mode, GLint first, GLsizei count) {
+ GetGLES(context_id)->DrawArrays(mode, first, count);
+}
+
+void DrawElements(
+ PP_Resource context_id, GLenum mode, GLsizei count, GLenum type,
+ const void* indices) {
+ GetGLES(context_id)->DrawElements(mode, count, type, indices);
+}
+
+void Enable(PP_Resource context_id, GLenum cap) {
+ GetGLES(context_id)->Enable(cap);
+}
+
+void EnableVertexAttribArray(PP_Resource context_id, GLuint index) {
+ GetGLES(context_id)->EnableVertexAttribArray(index);
+}
+
+void Finish(PP_Resource context_id) {
+ GetGLES(context_id)->Finish();
+}
+
+void Flush(PP_Resource context_id) {
+ GetGLES(context_id)->Flush();
+}
+
+void FramebufferRenderbuffer(
+ PP_Resource context_id, GLenum target, GLenum attachment,
+ GLenum renderbuffertarget, GLuint renderbuffer) {
+ GetGLES(
+ context_id)->FramebufferRenderbuffer(
+ target, attachment, renderbuffertarget, renderbuffer);
+}
+
+void FramebufferTexture2D(
+ PP_Resource context_id, GLenum target, GLenum attachment, GLenum textarget,
+ GLuint texture, GLint level) {
+ GetGLES(
+ context_id)->FramebufferTexture2D(
+ target, attachment, textarget, texture, level);
+}
+
+void FrontFace(PP_Resource context_id, GLenum mode) {
+ GetGLES(context_id)->FrontFace(mode);
+}
+
+void GenBuffers(PP_Resource context_id, GLsizei n, GLuint* buffers) {
+ GetGLES(context_id)->GenBuffers(n, buffers);
+}
+
+void GenerateMipmap(PP_Resource context_id, GLenum target) {
+ GetGLES(context_id)->GenerateMipmap(target);
+}
+
+void GenFramebuffers(PP_Resource context_id, GLsizei n, GLuint* framebuffers) {
+ GetGLES(context_id)->GenFramebuffers(n, framebuffers);
+}
+
+void GenRenderbuffers(
+ PP_Resource context_id, GLsizei n, GLuint* renderbuffers) {
+ GetGLES(context_id)->GenRenderbuffers(n, renderbuffers);
+}
+
+void GenTextures(PP_Resource context_id, GLsizei n, GLuint* textures) {
+ GetGLES(context_id)->GenTextures(n, textures);
+}
+
+void GetActiveAttrib(
+ PP_Resource context_id, GLuint program, GLuint index, GLsizei bufsize,
+ GLsizei* length, GLint* size, GLenum* type, char* name) {
+ GetGLES(
+ context_id)->GetActiveAttrib(
+ program, index, bufsize, length, size, type, name);
+}
+
+void GetActiveUniform(
+ PP_Resource context_id, GLuint program, GLuint index, GLsizei bufsize,
+ GLsizei* length, GLint* size, GLenum* type, char* name) {
+ GetGLES(
+ context_id)->GetActiveUniform(
+ program, index, bufsize, length, size, type, name);
+}
+
+void GetAttachedShaders(
+ PP_Resource context_id, GLuint program, GLsizei maxcount, GLsizei* count,
+ GLuint* shaders) {
+ GetGLES(context_id)->GetAttachedShaders(program, maxcount, count, shaders);
+}
+
+GLint GetAttribLocation(
+ PP_Resource context_id, GLuint program, const char* name) {
+ return GetGLES(context_id)->GetAttribLocation(program, name);
+}
+
+void GetBooleanv(PP_Resource context_id, GLenum pname, GLboolean* params) {
+ GetGLES(context_id)->GetBooleanv(pname, params);
+}
+
+void GetBufferParameteriv(
+ PP_Resource context_id, GLenum target, GLenum pname, GLint* params) {
+ GetGLES(context_id)->GetBufferParameteriv(target, pname, params);
+}
+
+GLenum GetError(PP_Resource context_id) {
+ return GetGLES(context_id)->GetError();
+}
+
+void GetFloatv(PP_Resource context_id, GLenum pname, GLfloat* params) {
+ GetGLES(context_id)->GetFloatv(pname, params);
+}
+
+void GetFramebufferAttachmentParameteriv(
+ PP_Resource context_id, GLenum target, GLenum attachment, GLenum pname,
+ GLint* params) {
+ GetGLES(
+ context_id)->GetFramebufferAttachmentParameteriv(
+ target, attachment, pname, params);
+}
+
+void GetIntegerv(PP_Resource context_id, GLenum pname, GLint* params) {
+ GetGLES(context_id)->GetIntegerv(pname, params);
+}
+
+void GetProgramiv(
+ PP_Resource context_id, GLuint program, GLenum pname, GLint* params) {
+ GetGLES(context_id)->GetProgramiv(program, pname, params);
+}
+
+void GetProgramInfoLog(
+ PP_Resource context_id, GLuint program, GLsizei bufsize, GLsizei* length,
+ char* infolog) {
+ GetGLES(context_id)->GetProgramInfoLog(program, bufsize, length, infolog);
+}
+
+void GetRenderbufferParameteriv(
+ PP_Resource context_id, GLenum target, GLenum pname, GLint* params) {
+ GetGLES(context_id)->GetRenderbufferParameteriv(target, pname, params);
+}
+
+void GetShaderiv(
+ PP_Resource context_id, GLuint shader, GLenum pname, GLint* params) {
+ GetGLES(context_id)->GetShaderiv(shader, pname, params);
+}
+
+void GetShaderInfoLog(
+ PP_Resource context_id, GLuint shader, GLsizei bufsize, GLsizei* length,
+ char* infolog) {
+ GetGLES(context_id)->GetShaderInfoLog(shader, bufsize, length, infolog);
+}
+
+void GetShaderPrecisionFormat(
+ PP_Resource context_id, GLenum shadertype, GLenum precisiontype,
+ GLint* range, GLint* precision) {
+ GetGLES(
+ context_id)->GetShaderPrecisionFormat(
+ shadertype, precisiontype, range, precision);
+}
+
+void GetShaderSource(
+ PP_Resource context_id, GLuint shader, GLsizei bufsize, GLsizei* length,
+ char* source) {
+ GetGLES(context_id)->GetShaderSource(shader, bufsize, length, source);
+}
+
+const GLubyte* GetString(PP_Resource context_id, GLenum name) {
+ return GetGLES(context_id)->GetString(name);
+}
+
+void GetTexParameterfv(
+ PP_Resource context_id, GLenum target, GLenum pname, GLfloat* params) {
+ GetGLES(context_id)->GetTexParameterfv(target, pname, params);
+}
+
+void GetTexParameteriv(
+ PP_Resource context_id, GLenum target, GLenum pname, GLint* params) {
+ GetGLES(context_id)->GetTexParameteriv(target, pname, params);
+}
+
+void GetUniformfv(
+ PP_Resource context_id, GLuint program, GLint location, GLfloat* params) {
+ GetGLES(context_id)->GetUniformfv(program, location, params);
+}
+
+void GetUniformiv(
+ PP_Resource context_id, GLuint program, GLint location, GLint* params) {
+ GetGLES(context_id)->GetUniformiv(program, location, params);
+}
+
+GLint GetUniformLocation(
+ PP_Resource context_id, GLuint program, const char* name) {
+ return GetGLES(context_id)->GetUniformLocation(program, name);
+}
+
+void GetVertexAttribfv(
+ PP_Resource context_id, GLuint index, GLenum pname, GLfloat* params) {
+ GetGLES(context_id)->GetVertexAttribfv(index, pname, params);
+}
+
+void GetVertexAttribiv(
+ PP_Resource context_id, GLuint index, GLenum pname, GLint* params) {
+ GetGLES(context_id)->GetVertexAttribiv(index, pname, params);
+}
+
+void GetVertexAttribPointerv(
+ PP_Resource context_id, GLuint index, GLenum pname, void** pointer) {
+ GetGLES(context_id)->GetVertexAttribPointerv(index, pname, pointer);
+}
+
+void Hint(PP_Resource context_id, GLenum target, GLenum mode) {
+ GetGLES(context_id)->Hint(target, mode);
+}
+
+GLboolean IsBuffer(PP_Resource context_id, GLuint buffer) {
+ return GetGLES(context_id)->IsBuffer(buffer);
+}
+
+GLboolean IsEnabled(PP_Resource context_id, GLenum cap) {
+ return GetGLES(context_id)->IsEnabled(cap);
+}
+
+GLboolean IsFramebuffer(PP_Resource context_id, GLuint framebuffer) {
+ return GetGLES(context_id)->IsFramebuffer(framebuffer);
+}
+
+GLboolean IsProgram(PP_Resource context_id, GLuint program) {
+ return GetGLES(context_id)->IsProgram(program);
+}
+
+GLboolean IsRenderbuffer(PP_Resource context_id, GLuint renderbuffer) {
+ return GetGLES(context_id)->IsRenderbuffer(renderbuffer);
+}
+
+GLboolean IsShader(PP_Resource context_id, GLuint shader) {
+ return GetGLES(context_id)->IsShader(shader);
+}
+
+GLboolean IsTexture(PP_Resource context_id, GLuint texture) {
+ return GetGLES(context_id)->IsTexture(texture);
+}
+
+void LineWidth(PP_Resource context_id, GLfloat width) {
+ GetGLES(context_id)->LineWidth(width);
+}
+
+void LinkProgram(PP_Resource context_id, GLuint program) {
+ GetGLES(context_id)->LinkProgram(program);
+}
+
+void PixelStorei(PP_Resource context_id, GLenum pname, GLint param) {
+ GetGLES(context_id)->PixelStorei(pname, param);
+}
+
+void PolygonOffset(PP_Resource context_id, GLfloat factor, GLfloat units) {
+ GetGLES(context_id)->PolygonOffset(factor, units);
+}
+
+void ReadPixels(
+ PP_Resource context_id, GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, void* pixels) {
+ GetGLES(context_id)->ReadPixels(x, y, width, height, format, type, pixels);
+}
+
+void ReleaseShaderCompiler(PP_Resource context_id) {
+ GetGLES(context_id)->ReleaseShaderCompiler();
+}
+
+void RenderbufferStorage(
+ PP_Resource context_id, GLenum target, GLenum internalformat, GLsizei width,
+ GLsizei height) {
+ GetGLES(
+ context_id)->RenderbufferStorage(target, internalformat, width, height);
+}
+
+void SampleCoverage(PP_Resource context_id, GLclampf value, GLboolean invert) {
+ GetGLES(context_id)->SampleCoverage(value, invert);
+}
+
+void Scissor(
+ PP_Resource context_id, GLint x, GLint y, GLsizei width, GLsizei height) {
+ GetGLES(context_id)->Scissor(x, y, width, height);
+}
+
+void ShaderBinary(
+ PP_Resource context_id, GLsizei n, const GLuint* shaders,
+ GLenum binaryformat, const void* binary, GLsizei length) {
+ GetGLES(context_id)->ShaderBinary(n, shaders, binaryformat, binary, length);
+}
+
+void ShaderSource(
+ PP_Resource context_id, GLuint shader, GLsizei count, const char** str,
+ const GLint* length) {
+ GetGLES(context_id)->ShaderSource(shader, count, str, length);
+}
+
+void StencilFunc(PP_Resource context_id, GLenum func, GLint ref, GLuint mask) {
+ GetGLES(context_id)->StencilFunc(func, ref, mask);
+}
+
+void StencilFuncSeparate(
+ PP_Resource context_id, GLenum face, GLenum func, GLint ref, GLuint mask) {
+ GetGLES(context_id)->StencilFuncSeparate(face, func, ref, mask);
+}
+
+void StencilMask(PP_Resource context_id, GLuint mask) {
+ GetGLES(context_id)->StencilMask(mask);
+}
+
+void StencilMaskSeparate(PP_Resource context_id, GLenum face, GLuint mask) {
+ GetGLES(context_id)->StencilMaskSeparate(face, mask);
+}
+
+void StencilOp(
+ PP_Resource context_id, GLenum fail, GLenum zfail, GLenum zpass) {
+ GetGLES(context_id)->StencilOp(fail, zfail, zpass);
+}
+
+void StencilOpSeparate(
+ PP_Resource context_id, GLenum face, GLenum fail, GLenum zfail,
+ GLenum zpass) {
+ GetGLES(context_id)->StencilOpSeparate(face, fail, zfail, zpass);
+}
+
+void TexImage2D(
+ PP_Resource context_id, GLenum target, GLint level, GLint internalformat,
+ GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type,
+ const void* pixels) {
+ GetGLES(
+ context_id)->TexImage2D(
+ target, level, internalformat, width, height, border, format, type,
+ pixels);
+}
+
+void TexParameterf(
+ PP_Resource context_id, GLenum target, GLenum pname, GLfloat param) {
+ GetGLES(context_id)->TexParameterf(target, pname, param);
+}
+
+void TexParameterfv(
+ PP_Resource context_id, GLenum target, GLenum pname,
+ const GLfloat* params) {
+ GetGLES(context_id)->TexParameterfv(target, pname, params);
+}
+
+void TexParameteri(
+ PP_Resource context_id, GLenum target, GLenum pname, GLint param) {
+ GetGLES(context_id)->TexParameteri(target, pname, param);
+}
+
+void TexParameteriv(
+ PP_Resource context_id, GLenum target, GLenum pname, const GLint* params) {
+ GetGLES(context_id)->TexParameteriv(target, pname, params);
+}
+
+void TexSubImage2D(
+ PP_Resource context_id, GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type,
+ const void* pixels) {
+ GetGLES(
+ context_id)->TexSubImage2D(
+ target, level, xoffset, yoffset, width, height, format, type,
+ pixels);
+}
+
+void Uniform1f(PP_Resource context_id, GLint location, GLfloat x) {
+ GetGLES(context_id)->Uniform1f(location, x);
+}
+
+void Uniform1fv(
+ PP_Resource context_id, GLint location, GLsizei count, const GLfloat* v) {
+ GetGLES(context_id)->Uniform1fv(location, count, v);
+}
+
+void Uniform1i(PP_Resource context_id, GLint location, GLint x) {
+ GetGLES(context_id)->Uniform1i(location, x);
+}
+
+void Uniform1iv(
+ PP_Resource context_id, GLint location, GLsizei count, const GLint* v) {
+ GetGLES(context_id)->Uniform1iv(location, count, v);
+}
+
+void Uniform2f(PP_Resource context_id, GLint location, GLfloat x, GLfloat y) {
+ GetGLES(context_id)->Uniform2f(location, x, y);
+}
+
+void Uniform2fv(
+ PP_Resource context_id, GLint location, GLsizei count, const GLfloat* v) {
+ GetGLES(context_id)->Uniform2fv(location, count, v);
+}
+
+void Uniform2i(PP_Resource context_id, GLint location, GLint x, GLint y) {
+ GetGLES(context_id)->Uniform2i(location, x, y);
+}
+
+void Uniform2iv(
+ PP_Resource context_id, GLint location, GLsizei count, const GLint* v) {
+ GetGLES(context_id)->Uniform2iv(location, count, v);
+}
+
+void Uniform3f(
+ PP_Resource context_id, GLint location, GLfloat x, GLfloat y, GLfloat z) {
+ GetGLES(context_id)->Uniform3f(location, x, y, z);
+}
+
+void Uniform3fv(
+ PP_Resource context_id, GLint location, GLsizei count, const GLfloat* v) {
+ GetGLES(context_id)->Uniform3fv(location, count, v);
+}
+
+void Uniform3i(
+ PP_Resource context_id, GLint location, GLint x, GLint y, GLint z) {
+ GetGLES(context_id)->Uniform3i(location, x, y, z);
+}
+
+void Uniform3iv(
+ PP_Resource context_id, GLint location, GLsizei count, const GLint* v) {
+ GetGLES(context_id)->Uniform3iv(location, count, v);
+}
+
+void Uniform4f(
+ PP_Resource context_id, GLint location, GLfloat x, GLfloat y, GLfloat z,
+ GLfloat w) {
+ GetGLES(context_id)->Uniform4f(location, x, y, z, w);
+}
+
+void Uniform4fv(
+ PP_Resource context_id, GLint location, GLsizei count, const GLfloat* v) {
+ GetGLES(context_id)->Uniform4fv(location, count, v);
+}
+
+void Uniform4i(
+ PP_Resource context_id, GLint location, GLint x, GLint y, GLint z,
+ GLint w) {
+ GetGLES(context_id)->Uniform4i(location, x, y, z, w);
+}
+
+void Uniform4iv(
+ PP_Resource context_id, GLint location, GLsizei count, const GLint* v) {
+ GetGLES(context_id)->Uniform4iv(location, count, v);
+}
+
+void UniformMatrix2fv(
+ PP_Resource context_id, GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat* value) {
+ GetGLES(context_id)->UniformMatrix2fv(location, count, transpose, value);
+}
+
+void UniformMatrix3fv(
+ PP_Resource context_id, GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat* value) {
+ GetGLES(context_id)->UniformMatrix3fv(location, count, transpose, value);
+}
+
+void UniformMatrix4fv(
+ PP_Resource context_id, GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat* value) {
+ GetGLES(context_id)->UniformMatrix4fv(location, count, transpose, value);
+}
+
+void UseProgram(PP_Resource context_id, GLuint program) {
+ GetGLES(context_id)->UseProgram(program);
+}
+
+void ValidateProgram(PP_Resource context_id, GLuint program) {
+ GetGLES(context_id)->ValidateProgram(program);
+}
+
+void VertexAttrib1f(PP_Resource context_id, GLuint indx, GLfloat x) {
+ GetGLES(context_id)->VertexAttrib1f(indx, x);
+}
+
+void VertexAttrib1fv(
+ PP_Resource context_id, GLuint indx, const GLfloat* values) {
+ GetGLES(context_id)->VertexAttrib1fv(indx, values);
+}
+
+void VertexAttrib2f(
+ PP_Resource context_id, GLuint indx, GLfloat x, GLfloat y) {
+ GetGLES(context_id)->VertexAttrib2f(indx, x, y);
+}
+
+void VertexAttrib2fv(
+ PP_Resource context_id, GLuint indx, const GLfloat* values) {
+ GetGLES(context_id)->VertexAttrib2fv(indx, values);
+}
+
+void VertexAttrib3f(
+ PP_Resource context_id, GLuint indx, GLfloat x, GLfloat y, GLfloat z) {
+ GetGLES(context_id)->VertexAttrib3f(indx, x, y, z);
+}
+
+void VertexAttrib3fv(
+ PP_Resource context_id, GLuint indx, const GLfloat* values) {
+ GetGLES(context_id)->VertexAttrib3fv(indx, values);
+}
+
+void VertexAttrib4f(
+ PP_Resource context_id, GLuint indx, GLfloat x, GLfloat y, GLfloat z,
+ GLfloat w) {
+ GetGLES(context_id)->VertexAttrib4f(indx, x, y, z, w);
+}
+
+void VertexAttrib4fv(
+ PP_Resource context_id, GLuint indx, const GLfloat* values) {
+ GetGLES(context_id)->VertexAttrib4fv(indx, values);
+}
+
+void VertexAttribPointer(
+ PP_Resource context_id, GLuint indx, GLint size, GLenum type,
+ GLboolean normalized, GLsizei stride, const void* ptr) {
+ GetGLES(
+ context_id)->VertexAttribPointer(
+ indx, size, type, normalized, stride, ptr);
+}
+
+void Viewport(
+ PP_Resource context_id, GLint x, GLint y, GLsizei width, GLsizei height) {
+ GetGLES(context_id)->Viewport(x, y, width, height);
+}
+
+void SetLatchCHROMIUM(PP_Resource context_id, GLuint latch_id) {
+ GetGLES(context_id)->SetLatchCHROMIUM(latch_id);
+}
+
+void WaitLatchCHROMIUM(PP_Resource context_id, GLuint latch_id) {
+ GetGLES(context_id)->WaitLatchCHROMIUM(latch_id);
+}
+
+const struct PPB_OpenGLES2_Dev opengles2_interface = {
+ &ActiveTexture,
+ &AttachShader,
+ &BindAttribLocation,
+ &BindBuffer,
+ &BindFramebuffer,
+ &BindRenderbuffer,
+ &BindTexture,
+ &BlendColor,
+ &BlendEquation,
+ &BlendEquationSeparate,
+ &BlendFunc,
+ &BlendFuncSeparate,
+ &BufferData,
+ &BufferSubData,
+ &CheckFramebufferStatus,
+ &Clear,
+ &ClearColor,
+ &ClearDepthf,
+ &ClearStencil,
+ &ColorMask,
+ &CompileShader,
+ &CompressedTexImage2D,
+ &CompressedTexSubImage2D,
+ &CopyTexImage2D,
+ &CopyTexSubImage2D,
+ &CreateProgram,
+ &CreateShader,
+ &CullFace,
+ &DeleteBuffers,
+ &DeleteFramebuffers,
+ &DeleteProgram,
+ &DeleteRenderbuffers,
+ &DeleteShader,
+ &DeleteTextures,
+ &DepthFunc,
+ &DepthMask,
+ &DepthRangef,
+ &DetachShader,
+ &Disable,
+ &DisableVertexAttribArray,
+ &DrawArrays,
+ &DrawElements,
+ &Enable,
+ &EnableVertexAttribArray,
+ &Finish,
+ &Flush,
+ &FramebufferRenderbuffer,
+ &FramebufferTexture2D,
+ &FrontFace,
+ &GenBuffers,
+ &GenerateMipmap,
+ &GenFramebuffers,
+ &GenRenderbuffers,
+ &GenTextures,
+ &GetActiveAttrib,
+ &GetActiveUniform,
+ &GetAttachedShaders,
+ &GetAttribLocation,
+ &GetBooleanv,
+ &GetBufferParameteriv,
+ &GetError,
+ &GetFloatv,
+ &GetFramebufferAttachmentParameteriv,
+ &GetIntegerv,
+ &GetProgramiv,
+ &GetProgramInfoLog,
+ &GetRenderbufferParameteriv,
+ &GetShaderiv,
+ &GetShaderInfoLog,
+ &GetShaderPrecisionFormat,
+ &GetShaderSource,
+ &GetString,
+ &GetTexParameterfv,
+ &GetTexParameteriv,
+ &GetUniformfv,
+ &GetUniformiv,
+ &GetUniformLocation,
+ &GetVertexAttribfv,
+ &GetVertexAttribiv,
+ &GetVertexAttribPointerv,
+ &Hint,
+ &IsBuffer,
+ &IsEnabled,
+ &IsFramebuffer,
+ &IsProgram,
+ &IsRenderbuffer,
+ &IsShader,
+ &IsTexture,
+ &LineWidth,
+ &LinkProgram,
+ &PixelStorei,
+ &PolygonOffset,
+ &ReadPixels,
+ &ReleaseShaderCompiler,
+ &RenderbufferStorage,
+ &SampleCoverage,
+ &Scissor,
+ &ShaderBinary,
+ &ShaderSource,
+ &StencilFunc,
+ &StencilFuncSeparate,
+ &StencilMask,
+ &StencilMaskSeparate,
+ &StencilOp,
+ &StencilOpSeparate,
+ &TexImage2D,
+ &TexParameterf,
+ &TexParameterfv,
+ &TexParameteri,
+ &TexParameteriv,
+ &TexSubImage2D,
+ &Uniform1f,
+ &Uniform1fv,
+ &Uniform1i,
+ &Uniform1iv,
+ &Uniform2f,
+ &Uniform2fv,
+ &Uniform2i,
+ &Uniform2iv,
+ &Uniform3f,
+ &Uniform3fv,
+ &Uniform3i,
+ &Uniform3iv,
+ &Uniform4f,
+ &Uniform4fv,
+ &Uniform4i,
+ &Uniform4iv,
+ &UniformMatrix2fv,
+ &UniformMatrix3fv,
+ &UniformMatrix4fv,
+ &UseProgram,
+ &ValidateProgram,
+ &VertexAttrib1f,
+ &VertexAttrib1fv,
+ &VertexAttrib2f,
+ &VertexAttrib2fv,
+ &VertexAttrib3f,
+ &VertexAttrib3fv,
+ &VertexAttrib4f,
+ &VertexAttrib4fv,
+ &VertexAttribPointer,
+ &Viewport
+};
+
+
+InterfaceProxy* CreateOpenGLES2Proxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_OpenGLES2_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_OpenGLES2_Proxy::PPB_OpenGLES2_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_OpenGLES2_Proxy::~PPB_OpenGLES2_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_OpenGLES2_Proxy::GetInfo() {
+ static const Info info = {
+ &opengles2_interface,
+ PPB_OPENGLES2_DEV_INTERFACE,
+ INTERFACE_ID_PPB_OPENGLES2,
+ false,
+ &CreateOpenGLES2Proxy,
+ };
+ return &info;
+}
+
+bool PPB_OpenGLES2_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ return false;
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_opengles2_proxy.h b/ppapi/proxy/ppb_opengles2_proxy.h
new file mode 100644
index 0000000..d4ea6f9
--- /dev/null
+++ b/ppapi/proxy/ppb_opengles2_proxy.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2010 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_PPB_OPENGLES2_PROXY_H_
+#define PPAPI_PPB_OPENGLES2_PROXY_H_
+
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_OpenGLES2_Dev;
+
+namespace pp {
+namespace proxy {
+
+class PPB_OpenGLES2_Proxy : public InterfaceProxy {
+ public:
+ PPB_OpenGLES2_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_OpenGLES2_Proxy();
+
+ static const Info* GetInfo();
+
+ const PPB_OpenGLES2_Dev* ppb_gles2_target() const {
+ return reinterpret_cast<const PPB_OpenGLES2_Dev*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PPB_OPENGLES2_PROXY_H_
diff --git a/ppapi/proxy/ppb_pdf_proxy.cc b/ppapi/proxy/ppb_pdf_proxy.cc
new file mode 100644
index 0000000..f7dbb28
--- /dev/null
+++ b/ppapi/proxy/ppb_pdf_proxy.cc
@@ -0,0 +1,186 @@
+// 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_pdf_proxy.h"
+
+#include <string.h> // For memcpy.
+
+#include <map>
+
+#include "base/logging.h"
+#include "base/memory/linked_ptr.h"
+#include "build/build_config.h"
+#include "ppapi/c/private/ppb_pdf.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace pp {
+namespace proxy {
+
+class PrivateFontFile : public PluginResource {
+ public:
+ PrivateFontFile(const HostResource& resource) : PluginResource(resource) {
+ }
+ virtual ~PrivateFontFile() {}
+
+ // Resource overrides.
+ virtual PrivateFontFile* AsPrivateFontFile() { return this; }
+
+ // Sees if we have a cache of the font table and returns a pointer to it.
+ // Returns NULL if we don't have it.
+ std::string* GetFontTable(uint32_t table) const;
+
+ std::string* AddFontTable(uint32_t table, const std::string& contents);
+
+ private:
+ typedef std::map<uint32_t, linked_ptr<std::string> > FontTableMap;
+ FontTableMap font_tables_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrivateFontFile);
+};
+
+std::string* PrivateFontFile::GetFontTable(uint32_t table) const {
+ FontTableMap::const_iterator found = font_tables_.find(table);
+ if (found == font_tables_.end())
+ return NULL;
+ return found->second.get();
+}
+
+std::string* PrivateFontFile::AddFontTable(uint32_t table,
+ const std::string& contents) {
+ linked_ptr<std::string> heap_string(new std::string(contents));
+ font_tables_[table] = heap_string;
+ return heap_string.get();
+}
+
+namespace {
+
+PP_Resource GetFontFileWithFallback(
+ PP_Instance instance,
+ const PP_FontDescription_Dev* description,
+ PP_PrivateFontCharset charset) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+
+ SerializedFontDescription desc;
+ desc.SetFromPPFontDescription(dispatcher, *description, true);
+
+ HostResource result;
+ dispatcher->Send(new PpapiHostMsg_PPBPDF_GetFontFileWithFallback(
+ INTERFACE_ID_PPB_PDF, instance, desc, charset, &result));
+ if (result.is_null())
+ return 0;
+
+ linked_ptr<PrivateFontFile> object(new PrivateFontFile(result));
+ return PluginResourceTracker::GetInstance()->AddResource(object);
+}
+
+bool GetFontTableForPrivateFontFile(PP_Resource font_file,
+ uint32_t table,
+ void* output,
+ uint32_t* output_length) {
+ PrivateFontFile* object = PluginResource::GetAs<PrivateFontFile>(font_file);
+ if (!object)
+ return false;
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(
+ object->instance());
+ if (!dispatcher)
+ return false;
+
+ std::string* contents = object->GetFontTable(table);
+ if (!contents) {
+ std::string deserialized;
+ dispatcher->Send(new PpapiHostMsg_PPBPDF_GetFontTableForPrivateFontFile(
+ INTERFACE_ID_PPB_PDF, object->host_resource(), table, &deserialized));
+ if (deserialized.empty())
+ return false;
+ contents = object->AddFontTable(table, deserialized);
+ }
+
+ *output_length = static_cast<uint32_t>(contents->size());
+ if (output)
+ memcpy(output, contents->c_str(), *output_length);
+ return true;
+}
+
+const PPB_PDF pdf_interface = {
+ NULL, // &GetLocalizedString,
+ NULL, // &GetResourceImage,
+ &GetFontFileWithFallback,
+ &GetFontTableForPrivateFontFile,
+};
+
+InterfaceProxy* CreatePDFProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_PDF_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_PDF_Proxy::PPB_PDF_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_PDF_Proxy::~PPB_PDF_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_PDF_Proxy::GetInfo() {
+ static const Info info = {
+ &pdf_interface,
+ PPB_PDF_INTERFACE,
+ INTERFACE_ID_PPB_PDF,
+ true,
+ &CreatePDFProxy,
+ };
+ return &info;
+}
+
+bool PPB_PDF_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_PDF_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBPDF_GetFontFileWithFallback,
+ OnMsgGetFontFileWithFallback)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBPDF_GetFontTableForPrivateFontFile,
+ OnMsgGetFontTableForPrivateFontFile)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ // TODO(brettw): handle bad messages!
+ return handled;
+}
+
+void PPB_PDF_Proxy::OnMsgGetFontFileWithFallback(
+ PP_Instance instance,
+ const SerializedFontDescription& in_desc,
+ int32_t charset,
+ HostResource* result) {
+ PP_FontDescription_Dev desc;
+ in_desc.SetToPPFontDescription(dispatcher(), &desc, false);
+ result->SetHostResource(instance,
+ ppb_pdf_target()->GetFontFileWithFallback(
+ instance, &desc, static_cast<PP_PrivateFontCharset>(charset)));
+}
+
+void PPB_PDF_Proxy::OnMsgGetFontTableForPrivateFontFile(
+ const HostResource& font_file,
+ uint32_t table,
+ std::string* result) {
+ // TODO(brettw): It would be nice not to copy here. At least on Linux,
+ // we can map the font file into shared memory and read it that way.
+ uint32_t table_length = 0;
+ if (!ppb_pdf_target()->GetFontTableForPrivateFontFile(
+ font_file.host_resource(), table, NULL, &table_length))
+ return;
+
+ result->resize(table_length);
+ ppb_pdf_target()->GetFontTableForPrivateFontFile(font_file.host_resource(),
+ table, const_cast<char*>(result->c_str()), &table_length);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_pdf_proxy.h b/ppapi/proxy/ppb_pdf_proxy.h
new file mode 100644
index 0000000..dbafd2d
--- /dev/null
+++ b/ppapi/proxy/ppb_pdf_proxy.h
@@ -0,0 +1,47 @@
+// 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_PPB_PDF_PROXY_H_
+#define PPAPI_PPB_PDF_PROXY_H_
+
+#include "ppapi/c/pp_module.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_PDF;
+
+namespace pp {
+namespace proxy {
+
+struct SerializedFontDescription;
+
+class PPB_PDF_Proxy : public InterfaceProxy {
+ public:
+ PPB_PDF_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_PDF_Proxy();
+
+ static const Info* GetInfo();
+
+ const PPB_PDF* ppb_pdf_target() const {
+ return static_cast<const PPB_PDF*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgGetFontFileWithFallback(PP_Module module,
+ const SerializedFontDescription& desc,
+ int32_t charset,
+ HostResource* result);
+ void OnMsgGetFontTableForPrivateFontFile(const HostResource& font_file,
+ uint32_t table,
+ std::string* result);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PPB_PDF_PROXY_H_
diff --git a/ppapi/proxy/ppb_surface_3d_proxy.cc b/ppapi/proxy/ppb_surface_3d_proxy.cc
new file mode 100644
index 0000000..c0288d0
--- /dev/null
+++ b/ppapi/proxy/ppb_surface_3d_proxy.cc
@@ -0,0 +1,210 @@
+// 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_surface_3d_proxy.h"
+
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/dev/ppb_surface_3d_dev.h"
+#include "ppapi/proxy/enter_proxy.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_context_3d_proxy.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/resource_creation_api.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::thunk::EnterFunctionNoLock;
+using ppapi::thunk::PPB_Surface3D_API;
+using ppapi::thunk::ResourceCreationAPI;
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+InterfaceProxy* CreateSurface3DProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Surface3D_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+// Surface3D -------------------------------------------------------------------
+
+Surface3D::Surface3D(const HostResource& host_resource)
+ : PluginResource(host_resource),
+ resource_(0),
+ context_(NULL),
+ current_flush_callback_(PP_BlockUntilComplete()) {
+}
+
+Surface3D::~Surface3D() {
+ if (context_)
+ context_->BindSurfaces(0, 0);
+}
+
+PPB_Surface3D_API* Surface3D::AsPPB_Surface3D_API() {
+ return this;
+}
+
+int32_t Surface3D::SetAttrib(int32_t attribute, int32_t value) {
+ // TODO(alokp): Implement me.
+ return 0;
+}
+
+int32_t Surface3D::GetAttrib(int32_t attribute, int32_t* value) {
+ // TODO(alokp): Implement me.
+ return 0;
+}
+
+int32_t Surface3D::SwapBuffers(PP_CompletionCallback callback) {
+ // For now, disallow blocking calls. We'll need to add support for other
+ // threads to this later.
+ if (!callback.func)
+ return PP_ERROR_BADARGUMENT;
+
+ if (is_flush_pending())
+ return PP_ERROR_INPROGRESS; // Can't have >1 flush pending.
+
+ if (!context_)
+ return PP_ERROR_FAILED;
+
+ current_flush_callback_ = callback;
+
+ IPC::Message* msg = new PpapiHostMsg_PPBSurface3D_SwapBuffers(
+ INTERFACE_ID_PPB_SURFACE_3D, host_resource());
+ msg->set_unblock(true);
+ GetDispatcher()->Send(msg);
+
+ context_->gles2_impl()->SwapBuffers();
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void Surface3D::SwapBuffersACK(int32_t pp_error) {
+ PP_RunAndClearCompletionCallback(&current_flush_callback_, pp_error);
+}
+
+// PPB_Surface3D_Proxy ---------------------------------------------------------
+
+PPB_Surface3D_Proxy::PPB_Surface3D_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface),
+ callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+}
+
+PPB_Surface3D_Proxy::~PPB_Surface3D_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Surface3D_Proxy::GetInfo() {
+ static const Info info = {
+ ::ppapi::thunk::GetPPB_Surface3D_Thunk(),
+ PPB_SURFACE_3D_DEV_INTERFACE,
+ INTERFACE_ID_PPB_SURFACE_3D,
+ false,
+ &CreateSurface3DProxy,
+ };
+ return &info;
+}
+
+// static
+PP_Resource PPB_Surface3D_Proxy::CreateProxyResource(
+ PP_Instance instance,
+ PP_Config3D_Dev config,
+ const int32_t* attrib_list) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return PP_ERROR_BADARGUMENT;
+
+ std::vector<int32_t> attribs;
+ if (attrib_list) {
+ const int32_t* attr = attrib_list;
+ while(*attr != PP_GRAPHICS3DATTRIB_NONE) {
+ attribs.push_back(*(attr++)); // Attribute.
+ attribs.push_back(*(attr++)); // Value.
+ }
+ }
+ attribs.push_back(PP_GRAPHICS3DATTRIB_NONE); // Always terminate.
+
+ HostResource result;
+ dispatcher->Send(new PpapiHostMsg_PPBSurface3D_Create(
+ INTERFACE_ID_PPB_SURFACE_3D, instance, config, attribs, &result));
+
+ if (result.is_null())
+ return 0;
+ linked_ptr<Surface3D> surface_3d(new Surface3D(result));
+ PP_Resource resource =
+ PluginResourceTracker::GetInstance()->AddResource(surface_3d);
+ surface_3d->set_resource(resource);
+ return resource;
+}
+
+bool PPB_Surface3D_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Surface3D_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBSurface3D_Create,
+ OnMsgCreate)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBSurface3D_SwapBuffers,
+ OnMsgSwapBuffers)
+
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBSurface3D_SwapBuffersACK,
+ OnMsgSwapBuffersACK)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ // FIXME(brettw) handle bad messages!
+ return handled;
+}
+
+void PPB_Surface3D_Proxy::OnMsgCreate(PP_Instance instance,
+ PP_Config3D_Dev config,
+ const std::vector<int32_t>& attribs,
+ HostResource* result) {
+ if (attribs.empty() ||
+ attribs.size() % 2 != 1 ||
+ attribs.back() != PP_GRAPHICS3DATTRIB_NONE)
+ return; // Bad message.
+
+ EnterFunctionNoLock<ResourceCreationAPI> enter(instance, true);
+ if (enter.succeeded()) {
+ result->SetHostResource(
+ instance,
+ enter.functions()->CreateSurface3D(instance, config, &attribs.front()));
+ }
+}
+
+void PPB_Surface3D_Proxy::OnMsgSwapBuffers(const HostResource& surface_3d) {
+ CompletionCallback callback = callback_factory_.NewOptionalCallback(
+ &PPB_Surface3D_Proxy::SendSwapBuffersACKToPlugin, surface_3d);
+
+ EnterHostFromHostResource<PPB_Surface3D_API> enter(surface_3d);
+ int32_t result = PP_ERROR_BADRESOURCE;
+ if (enter.succeeded())
+ result = enter.object()->SwapBuffers(callback.pp_completion_callback());
+ if (result != PP_OK_COMPLETIONPENDING) {
+ // There was some error, so we won't get a flush callback. We need to now
+ // issue the ACK to the plugin hears about the error. This will also clean
+ // up the data associated with the callback.
+ callback.Run(result);
+ }
+}
+
+void PPB_Surface3D_Proxy::OnMsgSwapBuffersACK(const HostResource& resource,
+ int32_t pp_error) {
+ EnterPluginFromHostResource<PPB_Surface3D_API> enter(resource);
+ if (enter.succeeded())
+ static_cast<Surface3D*>(enter.object())->SwapBuffersACK(pp_error);
+}
+
+void PPB_Surface3D_Proxy::SendSwapBuffersACKToPlugin(
+ int32_t result,
+ const HostResource& surface_3d) {
+ dispatcher()->Send(new PpapiMsg_PPBSurface3D_SwapBuffersACK(
+ INTERFACE_ID_PPB_SURFACE_3D, surface_3d, result));
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_surface_3d_proxy.h b/ppapi/proxy/ppb_surface_3d_proxy.h
new file mode 100644
index 0000000..f44ad76
--- /dev/null
+++ b/ppapi/proxy/ppb_surface_3d_proxy.h
@@ -0,0 +1,102 @@
+// 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_PPB_SURFACE_3D_PROXY_H_
+#define PPAPI_PPB_SURFACE_3D_PROXY_H_
+
+#include <vector>
+
+#include "ppapi/c/dev/pp_graphics_3d_dev.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/cpp/completion_callback.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h"
+#include "ppapi/thunk/ppb_surface_3d_api.h"
+
+struct PPB_Surface3D_Dev;
+
+namespace pp {
+namespace proxy {
+
+class Context3D;
+
+class Surface3D : public PluginResource,
+ public ppapi::thunk::PPB_Surface3D_API {
+ public:
+ explicit Surface3D(const HostResource& host_resource);
+ virtual ~Surface3D();
+
+ // ResourceObjectBase overrides.
+ virtual PPB_Surface3D_API* AsPPB_Surface3D_API() OVERRIDE;
+
+ // PPB_Surface3D_API implementation.
+ virtual int32_t SetAttrib(int32_t attribute, int32_t value) OVERRIDE;
+ virtual int32_t GetAttrib(int32_t attribute, int32_t* value) OVERRIDE;
+ virtual int32_t SwapBuffers(PP_CompletionCallback callback) OVERRIDE;
+
+ void SwapBuffersACK(int32_t pp_error);
+
+ bool is_flush_pending() const { return !!current_flush_callback_.func; }
+
+ PP_CompletionCallback current_flush_callback() const {
+ return current_flush_callback_;
+ }
+
+ void set_context(Context3D* context) {
+ context_ = context;
+ }
+
+ Context3D* context() const { return context_; }
+
+ void set_resource(PP_Resource resource) { resource_ = resource; }
+ PP_Resource resource() const { return resource_; }
+
+ private:
+ PP_Resource resource_;
+ Context3D* context_;
+
+ // In the plugin, this is the current callback set for Flushes. When the
+ // callback function pointer is non-NULL, we're waiting for a flush ACK.
+ PP_CompletionCallback current_flush_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(Surface3D);
+};
+
+class PPB_Surface3D_Proxy : public InterfaceProxy {
+ public:
+ PPB_Surface3D_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_Surface3D_Proxy();
+
+ static const Info* GetInfo();
+
+ static PP_Resource CreateProxyResource(PP_Instance instance,
+ PP_Config3D_Dev config,
+ const int32_t* attrib_list);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgCreate(PP_Instance instance,
+ PP_Config3D_Dev config,
+ const std::vector<int32_t>& attribs,
+ HostResource* result);
+ void OnMsgSwapBuffers(const HostResource& surface);
+ // Renderer->plugin message handlers.
+ void OnMsgSwapBuffersACK(const HostResource& surface, int32_t pp_error);
+
+ void SendSwapBuffersACKToPlugin(int32_t result,
+ const HostResource& surface_3d);
+
+ CompletionCallbackFactory<PPB_Surface3D_Proxy,
+ ProxyNonThreadSafeRefCount> callback_factory_;
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PPB_SURFACE_3D_PROXY_H_
diff --git a/ppapi/proxy/ppb_testing_proxy.cc b/ppapi/proxy/ppb_testing_proxy.cc
new file mode 100644
index 0000000..593ed7d
--- /dev/null
+++ b/ppapi/proxy/ppb_testing_proxy.cc
@@ -0,0 +1,146 @@
+// 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_testing_proxy.h"
+
+#include "base/message_loop.h"
+#include "ppapi/c/dev/ppb_testing_dev.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+PP_Bool ReadImageData(PP_Resource graphics_2d,
+ PP_Resource image,
+ const PP_Point* top_left) {
+ PluginResource* image_object = PluginResourceTracker::GetInstance()->
+ GetResourceObject(image);
+ if (!image_object)
+ return PP_FALSE;
+ PluginResource* graphics_2d_object =
+ PluginResourceTracker::GetInstance()->GetResourceObject(graphics_2d);
+ if (!graphics_2d_object ||
+ image_object->instance() != graphics_2d_object->instance())
+ return PP_FALSE;
+
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(
+ image_object->instance());
+ if (!dispatcher)
+ return PP_FALSE;
+
+ PP_Bool result = PP_FALSE;
+ dispatcher->Send(new PpapiHostMsg_PPBTesting_ReadImageData(
+ INTERFACE_ID_PPB_TESTING, graphics_2d_object->host_resource(),
+ image_object->host_resource(), *top_left, &result));
+ return result;
+}
+
+void RunMessageLoop(PP_Instance instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return;
+ IPC::SyncMessage* msg = new PpapiHostMsg_PPBTesting_RunMessageLoop(
+ INTERFACE_ID_PPB_TESTING, instance);
+ msg->EnableMessagePumping();
+ dispatcher->Send(msg);
+}
+
+void QuitMessageLoop(PP_Instance instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return;
+ dispatcher->Send(new PpapiHostMsg_PPBTesting_QuitMessageLoop(
+ INTERFACE_ID_PPB_TESTING, instance));
+}
+
+uint32_t GetLiveObjectsForInstance(PP_Instance instance_id) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id);
+ if (!dispatcher)
+ return static_cast<uint32_t>(-1);
+
+ uint32_t result = 0;
+ dispatcher->Send(new PpapiHostMsg_PPBTesting_GetLiveObjectsForInstance(
+ INTERFACE_ID_PPB_TESTING, instance_id, &result));
+ return result;
+}
+
+const PPB_Testing_Dev testing_interface = {
+ &ReadImageData,
+ &RunMessageLoop,
+ &QuitMessageLoop,
+ &GetLiveObjectsForInstance
+};
+
+InterfaceProxy* CreateTestingProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Testing_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_Testing_Proxy::PPB_Testing_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_Testing_Proxy::~PPB_Testing_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Testing_Proxy::GetInfo() {
+ static const Info info = {
+ &testing_interface,
+ PPB_TESTING_DEV_INTERFACE,
+ INTERFACE_ID_PPB_TESTING,
+ false,
+ &CreateTestingProxy,
+ };
+ return &info;
+}
+
+bool PPB_Testing_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Testing_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTesting_ReadImageData,
+ OnMsgReadImageData)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTesting_RunMessageLoop,
+ OnMsgRunMessageLoop)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTesting_QuitMessageLoop,
+ OnMsgQuitMessageLoop)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTesting_GetLiveObjectsForInstance,
+ OnMsgGetLiveObjectsForInstance)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPB_Testing_Proxy::OnMsgReadImageData(
+ const HostResource& device_context_2d,
+ const HostResource& image,
+ const PP_Point& top_left,
+ PP_Bool* result) {
+ *result = ppb_testing_target()->ReadImageData(
+ device_context_2d.host_resource(), image.host_resource(), &top_left);
+}
+
+void PPB_Testing_Proxy::OnMsgRunMessageLoop(PP_Instance instance) {
+ ppb_testing_target()->RunMessageLoop(instance);
+}
+
+void PPB_Testing_Proxy::OnMsgQuitMessageLoop(PP_Instance instance) {
+ ppb_testing_target()->QuitMessageLoop(instance);
+}
+
+void PPB_Testing_Proxy::OnMsgGetLiveObjectsForInstance(PP_Instance instance,
+ uint32_t* result) {
+ *result = ppb_testing_target()->GetLiveObjectsForInstance(instance);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_testing_proxy.h b/ppapi/proxy/ppb_testing_proxy.h
new file mode 100644
index 0000000..352a2ae
--- /dev/null
+++ b/ppapi/proxy/ppb_testing_proxy.h
@@ -0,0 +1,50 @@
+// 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_TESTING_PROXY_H_
+#define PPAPI_PROXY_PPB_TESTING_PROXY_H_
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PP_Point;
+struct PPB_Testing_Dev;
+
+namespace pp {
+namespace proxy {
+
+class PPB_Testing_Proxy : public InterfaceProxy {
+ public:
+ PPB_Testing_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_Testing_Proxy();
+
+ static const Info* GetInfo();
+
+ const PPB_Testing_Dev* ppb_testing_target() const {
+ return static_cast<const PPB_Testing_Dev*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgReadImageData(const HostResource& device_context_2d,
+ const HostResource& image,
+ const PP_Point& top_left,
+ PP_Bool* result);
+ void OnMsgRunMessageLoop(PP_Instance instance);
+ void OnMsgQuitMessageLoop(PP_Instance instance);
+ void OnMsgGetLiveObjectsForInstance(PP_Instance instance, uint32_t* result);
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_Testing_Proxy);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_TESTING_PROXY_H_
diff --git a/ppapi/proxy/ppb_url_loader_proxy.cc b/ppapi/proxy/ppb_url_loader_proxy.cc
new file mode 100644
index 0000000..b2d6276
--- /dev/null
+++ b/ppapi/proxy/ppb_url_loader_proxy.cc
@@ -0,0 +1,595 @@
+// 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_url_loader_proxy.h"
+
+#include <algorithm>
+#include <deque>
+#include <vector>
+
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/ppb_url_loader.h"
+#include "ppapi/c/private/ppb_proxy_private.h"
+#include "ppapi/c/trusted/ppb_url_loader_trusted.h"
+#include "ppapi/proxy/enter_proxy.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_url_response_info_proxy.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_url_loader_api.h"
+#include "ppapi/thunk/resource_creation_api.h"
+#include "ppapi/thunk/thunk.h"
+
+#if defined(OS_LINUX)
+#include <sys/shm.h>
+#endif
+
+using ppapi::thunk::EnterFunctionNoLock;
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_URLLoader_API;
+using ppapi::thunk::ResourceCreationAPI;
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+// The maximum size we'll read into the plugin without being explicitly
+// asked for a larger buffer.
+const int32_t kMaxReadBufferSize = 16777216; // 16MB
+
+// Called in the renderer when the byte counts have changed. We send a message
+// to the plugin to synchronize its counts so it can respond to status polls
+// from the plugin.
+void UpdateResourceLoadStatus(PP_Instance pp_instance,
+ PP_Resource pp_resource,
+ int64 bytes_sent,
+ int64 total_bytes_to_be_sent,
+ int64 bytes_received,
+ int64 total_bytes_to_be_received) {
+ Dispatcher* dispatcher = HostDispatcher::GetForInstance(pp_instance);
+ if (!dispatcher)
+ return;
+
+ PPBURLLoader_UpdateProgress_Params params;
+ params.instance = pp_instance;
+ params.resource.SetHostResource(pp_instance, pp_resource);
+ params.bytes_sent = bytes_sent;
+ params.total_bytes_to_be_sent = total_bytes_to_be_sent;
+ params.bytes_received = bytes_received;
+ params.total_bytes_to_be_received = total_bytes_to_be_received;
+ dispatcher->Send(new PpapiMsg_PPBURLLoader_UpdateProgress(
+ INTERFACE_ID_PPB_URL_LOADER, params));
+}
+
+InterfaceProxy* CreateURLLoaderProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_URLLoader_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+// URLLoader -------------------------------------------------------------------
+
+class URLLoader : public PluginResource, public PPB_URLLoader_API {
+ public:
+ URLLoader(const HostResource& resource);
+ virtual ~URLLoader();
+
+ // ResourceObjectBase overrides.
+ virtual PPB_URLLoader_API* AsPPB_URLLoader_API() OVERRIDE;
+
+ // PPB_URLLoader_API implementation.
+ virtual int32_t Open(PP_Resource request_id,
+ PP_CompletionCallback callback) OVERRIDE;
+ virtual int32_t FollowRedirect(PP_CompletionCallback callback) OVERRIDE;
+ virtual PP_Bool GetUploadProgress(int64_t* bytes_sent,
+ int64_t* total_bytes_to_be_sent) OVERRIDE;
+ virtual PP_Bool GetDownloadProgress(
+ int64_t* bytes_received,
+ int64_t* total_bytes_to_be_received) OVERRIDE;
+ virtual PP_Resource GetResponseInfo() OVERRIDE;
+ virtual int32_t ReadResponseBody(void* buffer,
+ int32_t bytes_to_read,
+ PP_CompletionCallback callback) OVERRIDE;
+ virtual int32_t FinishStreamingToFile(
+ PP_CompletionCallback callback) OVERRIDE;
+ virtual void Close() OVERRIDE;
+ virtual void GrantUniversalAccess() OVERRIDE;
+ virtual void SetStatusCallback(
+ PP_URLLoaderTrusted_StatusCallback cb) OVERRIDE;
+
+ // Called when the browser has new up/download progress to report.
+ void UpdateProgress(const PPBURLLoader_UpdateProgress_Params& params);
+
+ // Called when the browser responds to our ReadResponseBody request.
+ void ReadResponseBodyAck(int32 result, const std::string& data);
+
+ private:
+ // Reads the give bytes out of the buffer_, placing them in the given output
+ // buffer, and removes the bytes from the buffer.
+ //
+ // The size must be not more than the current size of the buffer.
+ void PopBuffer(void* output_buffer, int32_t output_size);
+
+ // Initialized to -1. Will be set to nonnegative values by the UpdateProgress
+ // message when the values are known.
+ int64_t bytes_sent_;
+ int64_t total_bytes_to_be_sent_;
+ int64_t bytes_received_;
+ int64_t total_bytes_to_be_received_;
+
+ // When an asynchronous read is pending, this will contain the callback and
+ // the buffer to put the data.
+ PP_CompletionCallback current_read_callback_;
+ void* current_read_buffer_;
+ int32_t current_read_buffer_size_;
+
+ // A buffer of all the data that's been sent to us from the host that we
+ // have yet to send out to the plugin.
+ std::deque<char> buffer_;
+
+ // Cached copy of the response info. When nonzero, we're holding a reference
+ // to this resource.
+ PP_Resource response_info_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(URLLoader);
+};
+
+URLLoader::URLLoader(const HostResource& resource)
+ : PluginResource(resource),
+ bytes_sent_(-1),
+ total_bytes_to_be_sent_(-1),
+ bytes_received_(-1),
+ total_bytes_to_be_received_(-1),
+ current_read_callback_(PP_MakeCompletionCallback(NULL, NULL)),
+ current_read_buffer_(NULL),
+ current_read_buffer_size_(0),
+ response_info_(0) {
+}
+
+URLLoader::~URLLoader() {
+ // Always need to fire completion callbacks to prevent a leak in the plugin.
+ if (current_read_callback_.func) {
+ // TODO(brettw) the callbacks at this level should be refactored with a
+ // more automatic tracking system like we have in the renderer.
+ MessageLoop::current()->PostTask(FROM_HERE, NewRunnableFunction(
+ current_read_callback_.func, current_read_callback_.user_data,
+ static_cast<int32_t>(PP_ERROR_ABORTED)));
+ }
+
+ if (response_info_)
+ PluginResourceTracker::GetInstance()->ReleaseResource(response_info_);
+}
+
+PPB_URLLoader_API* URLLoader::AsPPB_URLLoader_API() {
+ return this;
+}
+
+int32_t URLLoader::Open(PP_Resource request_id,
+ PP_CompletionCallback callback) {
+ PluginResource* request_object =
+ PluginResourceTracker::GetInstance()->GetResourceObject(request_id);
+ if (!request_object)
+ return PP_ERROR_BADARGUMENT;
+
+ // TODO(brettw) http://crbug.com/86279: SendCallback doesn't ensure that
+ // the proper callback semantics happen if the object is deleted.
+ GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_Open(
+ INTERFACE_ID_PPB_URL_LOADER, host_resource(),
+ request_object->host_resource(),
+ GetDispatcher()->callback_tracker().SendCallback(callback)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t URLLoader::FollowRedirect(PP_CompletionCallback callback) {
+ // TODO(brettw) http://crbug.com/86279: SendCallback doesn't ensure that
+ // the proper callback semantics happen if the object is deleted.
+ GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_FollowRedirect(
+ INTERFACE_ID_PPB_URL_LOADER, host_resource(),
+ GetDispatcher()->callback_tracker().SendCallback(callback)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+PP_Bool URLLoader::GetUploadProgress(int64_t* bytes_sent,
+ int64_t* total_bytes_to_be_sent) {
+ if (bytes_sent_ == -1) {
+ *bytes_sent = 0;
+ *total_bytes_to_be_sent = 0;
+ return PP_FALSE;
+ }
+ *bytes_sent = bytes_sent_;
+ *total_bytes_to_be_sent = total_bytes_to_be_sent_;
+ return PP_TRUE;
+}
+
+PP_Bool URLLoader::GetDownloadProgress(
+ int64_t* bytes_received,
+ int64_t* total_bytes_to_be_received) {
+ if (bytes_received_ == -1) {
+ *bytes_received = 0;
+ *total_bytes_to_be_received = 0;
+ return PP_FALSE;
+ }
+ *bytes_received = bytes_received_;
+ *total_bytes_to_be_received = total_bytes_to_be_received_;
+ return PP_TRUE;
+}
+
+PP_Resource URLLoader::GetResponseInfo() {
+ if (!response_info_) {
+ HostResource response_id;
+ GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_GetResponseInfo(
+ INTERFACE_ID_PPB_URL_LOADER, host_resource(), &response_id));
+ if (response_id.is_null())
+ return 0;
+
+ response_info_ = PPB_URLResponseInfo_Proxy::CreateResponseForResource(
+ response_id);
+ }
+
+ // The caller expects to get a ref, and we want to keep holding ours.
+ PluginResourceTracker::GetInstance()->AddRefResource(response_info_);
+ return response_info_;
+}
+
+int32_t URLLoader::ReadResponseBody(void* buffer,
+ int32_t bytes_to_read,
+ PP_CompletionCallback callback) {
+ if (!buffer || bytes_to_read <= 0)
+ return PP_ERROR_BADARGUMENT; // Must specify an output buffer.
+ if (current_read_callback_.func)
+ return PP_ERROR_INPROGRESS; // Can only have one request pending.
+
+ // Currently we don't support sync calls to read. We'll need to revisit
+ // how this works when we allow blocking calls (from background threads).
+ if (!callback.func)
+ return PP_ERROR_BADARGUMENT;
+
+ if (static_cast<size_t>(bytes_to_read) <= buffer_.size()) {
+ // Special case: we've buffered enough data to be able to synchronously
+ // return data to the caller. Do so without making IPCs.
+ PopBuffer(buffer, bytes_to_read);
+ return bytes_to_read;
+ }
+
+ current_read_callback_ = callback;
+ current_read_buffer_ = buffer;
+ current_read_buffer_size_ = bytes_to_read;
+
+ GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_ReadResponseBody(
+ INTERFACE_ID_PPB_URL_LOADER, host_resource(), bytes_to_read));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t URLLoader::FinishStreamingToFile(PP_CompletionCallback callback) {
+ GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_FinishStreamingToFile(
+ INTERFACE_ID_PPB_URL_LOADER, host_resource(),
+ GetDispatcher()->callback_tracker().SendCallback(callback)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void URLLoader::Close() {
+ GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_Close(
+ INTERFACE_ID_PPB_URL_LOADER, host_resource()));
+}
+
+void URLLoader::GrantUniversalAccess() {
+ GetDispatcher()->Send(
+ new PpapiHostMsg_PPBURLLoader_GrantUniversalAccess(
+ INTERFACE_ID_PPB_URL_LOADER, host_resource()));
+}
+
+void URLLoader::SetStatusCallback(
+ PP_URLLoaderTrusted_StatusCallback cb) {
+ // Not implemented in the proxied version, this is for implementing the
+ // proxy itself in the host.
+}
+
+void URLLoader::UpdateProgress(
+ const PPBURLLoader_UpdateProgress_Params& params) {
+ bytes_sent_ = params.bytes_sent;
+ total_bytes_to_be_sent_ = params.total_bytes_to_be_sent;
+ bytes_received_ = params.bytes_received;
+ total_bytes_to_be_received_ = params.total_bytes_to_be_received;
+}
+
+void URLLoader::ReadResponseBodyAck(int32 result, const std::string& data) {
+ if (!current_read_callback_.func || !current_read_buffer_) {
+ NOTREACHED();
+ return;
+ }
+
+ // Append the data we requested to the internal buffer.
+ // TODO(brettw) avoid double-copying data that's coming from IPC and going
+ // into the plugin buffer (we can skip the internal buffer in this case).
+ buffer_.insert(buffer_.end(), data.begin(), data.end());
+
+ if (result >= 0) {
+ // Fill the user buffer. We may get fewer bytes than requested in the
+ // case of stream end.
+ int32_t bytes_to_return = std::min(current_read_buffer_size_,
+ static_cast<int32_t>(buffer_.size()));
+ PopBuffer(current_read_buffer_, bytes_to_return);
+ result = bytes_to_return;
+ }
+
+ // The plugin should be able to make a new request from their callback, so
+ // we have to clear our copy first.
+ PP_RunAndClearCompletionCallback(&current_read_callback_, result);
+}
+
+void URLLoader::PopBuffer(void* output_buffer, int32_t output_size) {
+ CHECK(output_size <= static_cast<int32_t>(buffer_.size()));
+ std::copy(buffer_.begin(),
+ buffer_.begin() + output_size,
+ static_cast<char*>(output_buffer));
+ buffer_.erase(buffer_.begin(),
+ buffer_.begin() + output_size);
+}
+
+// PPB_URLLoader_Proxy ---------------------------------------------------------
+
+struct PPB_URLLoader_Proxy::ReadCallbackInfo {
+ HostResource resource;
+ std::string read_buffer;
+};
+
+PPB_URLLoader_Proxy::PPB_URLLoader_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface),
+ callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
+ host_urlloader_trusted_interface_(NULL) {
+}
+
+PPB_URLLoader_Proxy::~PPB_URLLoader_Proxy() {
+}
+
+// static
+PP_Resource PPB_URLLoader_Proxy::TrackPluginResource(
+ const HostResource& url_loader_resource) {
+ linked_ptr<URLLoader> object(new URLLoader(url_loader_resource));
+ return PluginResourceTracker::GetInstance()->AddResource(object);
+}
+
+// static
+const InterfaceProxy::Info* PPB_URLLoader_Proxy::GetInfo() {
+ static const Info info = {
+ ::ppapi::thunk::GetPPB_URLLoader_Thunk(),
+ PPB_URLLOADER_INTERFACE,
+ INTERFACE_ID_PPB_URL_LOADER,
+ false,
+ &CreateURLLoaderProxy,
+ };
+ return &info;
+}
+
+// static
+const InterfaceProxy::Info* PPB_URLLoader_Proxy::GetTrustedInfo() {
+ static const Info info = {
+ ::ppapi::thunk::GetPPB_URLLoaderTrusted_Thunk(),
+ PPB_URLLOADERTRUSTED_INTERFACE,
+ INTERFACE_ID_NONE, // URL_LOADER is the canonical one.
+ false,
+ &CreateURLLoaderProxy
+ };
+ return &info;
+}
+
+// static
+PP_Resource PPB_URLLoader_Proxy::CreateProxyResource(PP_Instance pp_instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(pp_instance);
+ if (!dispatcher)
+ return 0;
+
+ HostResource result;
+ dispatcher->Send(new PpapiHostMsg_PPBURLLoader_Create(
+ INTERFACE_ID_PPB_URL_LOADER, pp_instance, &result));
+ if (result.is_null())
+ return 0;
+ return PPB_URLLoader_Proxy::TrackPluginResource(result);
+}
+
+bool PPB_URLLoader_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_URLLoader_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_Create,
+ OnMsgCreate)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_Open,
+ OnMsgOpen)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_FollowRedirect,
+ OnMsgFollowRedirect)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_GetResponseInfo,
+ OnMsgGetResponseInfo)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_ReadResponseBody,
+ OnMsgReadResponseBody)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_FinishStreamingToFile,
+ OnMsgFinishStreamingToFile)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_Close,
+ OnMsgClose)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_GrantUniversalAccess,
+ OnMsgGrantUniversalAccess)
+
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBURLLoader_UpdateProgress,
+ OnMsgUpdateProgress)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBURLLoader_ReadResponseBody_Ack,
+ OnMsgReadResponseBodyAck)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ // TODO(brettw) handle bad messages!
+ return handled;
+}
+
+void PPB_URLLoader_Proxy::PrepareURLLoaderForSendingToPlugin(
+ PP_Resource resource) {
+ // So the plugin can query load status, we need to register our status
+ // callback before sending any URLLoader to the plugin.
+ EnterResourceNoLock<PPB_URLLoader_API> enter(resource, false);
+ if (enter.succeeded())
+ enter.object()->SetStatusCallback(&UpdateResourceLoadStatus);
+ else
+ NOTREACHED(); // Only called internally, resource should be valid.
+}
+
+void PPB_URLLoader_Proxy::OnMsgCreate(PP_Instance instance,
+ HostResource* result) {
+ EnterFunctionNoLock<ResourceCreationAPI> enter(instance, true);
+ if (enter.succeeded()) {
+ result->SetHostResource(instance,
+ enter.functions()->CreateURLLoader(instance));
+ PrepareURLLoaderForSendingToPlugin(result->host_resource());
+ }
+}
+
+void PPB_URLLoader_Proxy::OnMsgOpen(const HostResource& loader,
+ const HostResource& request_info,
+ uint32_t serialized_callback) {
+ EnterHostFromHostResource<PPB_URLLoader_API> enter(loader);
+ PP_CompletionCallback callback = ReceiveCallback(serialized_callback);
+ int32_t result = PP_ERROR_BADRESOURCE;
+ if (enter.succeeded())
+ result = enter.object()->Open(request_info.host_resource(), callback);
+ if (result != PP_OK_COMPLETIONPENDING)
+ PP_RunCompletionCallback(&callback, result);
+ // TODO(brettw) bug 73236 register for the status callbacks.
+}
+
+void PPB_URLLoader_Proxy::OnMsgFollowRedirect(
+ const HostResource& loader,
+ uint32_t serialized_callback) {
+ EnterHostFromHostResource<PPB_URLLoader_API> enter(loader);
+ PP_CompletionCallback callback = ReceiveCallback(serialized_callback);
+ int32_t result = PP_ERROR_BADRESOURCE;
+ if (enter.succeeded())
+ result = enter.object()->FollowRedirect(callback);
+ if (result != PP_OK_COMPLETIONPENDING)
+ PP_RunCompletionCallback(&callback, result);
+}
+
+void PPB_URLLoader_Proxy::OnMsgGetResponseInfo(const HostResource& loader,
+ HostResource* result) {
+ EnterHostFromHostResource<PPB_URLLoader_API> enter(loader);
+ if (enter.succeeded()) {
+ result->SetHostResource(loader.instance(),
+ enter.object()->GetResponseInfo());
+ }
+}
+
+void PPB_URLLoader_Proxy::OnMsgReadResponseBody(
+ const HostResource& loader,
+ int32_t bytes_to_read) {
+ // The plugin could be sending us malicious messages, don't accept negative
+ // sizes.
+ if (bytes_to_read < 0) {
+ // TODO(brettw) kill plugin.
+ bytes_to_read = 0;
+ }
+
+ // Read more than requested if there are bytes available for synchronous
+ // reading. This prevents us from getting too far behind due to IPC message
+ // latency. Any extra data will get buffered in the plugin.
+ int32_t synchronously_available_bytes =
+ static_cast<HostDispatcher*>(dispatcher())->ppb_proxy()->
+ GetURLLoaderBufferedBytes(loader.host_resource());
+ if (bytes_to_read < kMaxReadBufferSize) {
+ // Grow the amount to read so we read ahead synchronously, if possible.
+ bytes_to_read =
+ std::max(bytes_to_read,
+ std::min(synchronously_available_bytes, kMaxReadBufferSize));
+ }
+
+ // This heap object will get deleted by the callback handler.
+ // TODO(brettw) this will be leaked if the plugin closes the resource!
+ // (Also including the plugin unloading and having the resource implicitly
+ // destroyed. Depending on the cleanup ordering, we may not need the weak
+ // pointer here.)
+ ReadCallbackInfo* info = new ReadCallbackInfo;
+ info->resource = loader;
+ // TODO(brettw) have a way to check for out-of-memory.
+ info->read_buffer.resize(bytes_to_read);
+
+ CompletionCallback callback = callback_factory_.NewOptionalCallback(
+ &PPB_URLLoader_Proxy::OnReadCallback, info);
+
+ EnterHostFromHostResource<PPB_URLLoader_API> enter(loader);
+ int32_t result = PP_ERROR_BADRESOURCE;
+ if (enter.succeeded()) {
+ result = enter.object()->ReadResponseBody(
+ const_cast<char*>(info->read_buffer.c_str()),
+ bytes_to_read, callback.pp_completion_callback());
+ }
+ if (result != PP_OK_COMPLETIONPENDING) {
+ // Send error (or perhaps success for synchronous reads) back to plugin.
+ // The callback function is already set up to do this and also delete the
+ // callback info.
+ callback.Run(result);
+ }
+}
+
+void PPB_URLLoader_Proxy::OnMsgFinishStreamingToFile(
+ const HostResource& loader,
+ uint32_t serialized_callback) {
+ EnterHostFromHostResource<PPB_URLLoader_API> enter(loader);
+ PP_CompletionCallback callback = ReceiveCallback(serialized_callback);
+ int32_t result = PP_ERROR_BADRESOURCE;
+ if (enter.succeeded())
+ result = enter.object()->FinishStreamingToFile(callback);
+ if (result != PP_OK_COMPLETIONPENDING)
+ PP_RunCompletionCallback(&callback, result);
+}
+
+void PPB_URLLoader_Proxy::OnMsgClose(const HostResource& loader) {
+ EnterHostFromHostResource<PPB_URLLoader_API> enter(loader);
+ if (enter.succeeded())
+ enter.object()->Close();
+}
+
+void PPB_URLLoader_Proxy::OnMsgGrantUniversalAccess(
+ const HostResource& loader) {
+ EnterHostFromHostResource<PPB_URLLoader_API> enter(loader);
+ if (enter.succeeded())
+ enter.object()->GrantUniversalAccess();
+}
+
+// Called in the Plugin.
+void PPB_URLLoader_Proxy::OnMsgUpdateProgress(
+ const PPBURLLoader_UpdateProgress_Params& params) {
+ EnterPluginFromHostResource<PPB_URLLoader_API> enter(params.resource);
+ if (enter.succeeded())
+ static_cast<URLLoader*>(enter.object())->UpdateProgress(params);
+}
+
+// Called in the Plugin.
+void PPB_URLLoader_Proxy::OnMsgReadResponseBodyAck(
+ const HostResource& host_resource,
+ int32 result,
+ const std::string& data) {
+ EnterPluginFromHostResource<PPB_URLLoader_API> enter(host_resource);
+ if (enter.succeeded())
+ static_cast<URLLoader*>(enter.object())->ReadResponseBodyAck(result, data);
+}
+
+void PPB_URLLoader_Proxy::OnReadCallback(int32_t result,
+ ReadCallbackInfo* info) {
+ int32_t bytes_read = 0;
+ if (result > 0)
+ bytes_read = result; // Positive results indicate bytes read.
+ info->read_buffer.resize(bytes_read);
+
+ dispatcher()->Send(new PpapiMsg_PPBURLLoader_ReadResponseBody_Ack(
+ INTERFACE_ID_PPB_URL_LOADER, info->resource, result, info->read_buffer));
+
+ delete info;
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_url_loader_proxy.h b/ppapi/proxy/ppb_url_loader_proxy.h
new file mode 100644
index 0000000..0ff7b7e
--- /dev/null
+++ b/ppapi/proxy/ppb_url_loader_proxy.h
@@ -0,0 +1,100 @@
+// 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_PPB_URL_LOADER_PROXY_H_
+#define PPAPI_PPB_URL_LOADER_PROXY_H_
+
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_size.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/cpp/completion_callback.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h"
+
+struct PPB_URLLoader;
+struct PPB_URLLoaderTrusted;
+
+namespace pp {
+namespace proxy {
+
+struct PPBURLLoader_UpdateProgress_Params;
+
+class PPB_URLLoader_Proxy : public InterfaceProxy {
+ public:
+ PPB_URLLoader_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_URLLoader_Proxy();
+
+ static const Info* GetInfo();
+ static const Info* GetTrustedInfo();
+
+ static PP_Resource CreateProxyResource(PP_Instance instance);
+
+ // URLLoader objects are normally allocated by the Create function, but
+ // they are also provided to PPP_Instance.OnMsgHandleDocumentLoad. This
+ // function allows the proxy for DocumentLoad to create the correct plugin
+ // proxied info for the given browser-supplied URLLoader resource ID.
+ static PP_Resource TrackPluginResource(
+ const HostResource& url_loader_resource);
+
+ const PPB_URLLoader* ppb_url_loader_target() const {
+ return reinterpret_cast<const PPB_URLLoader*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ // URLLoader objects are sent from places other than just URLLoader.Create,
+ // in particular when doing a full-frame plugin. This function does the
+ // necessary setup in the host before the resource is sent. Call this any
+ // time you're sending a new URLLoader that the plugin hasn't seen yet.
+ void PrepareURLLoaderForSendingToPlugin(PP_Resource resource);
+
+ private:
+ // Data associated with callbacks for ReadResponseBody.
+ struct ReadCallbackInfo;
+
+ // Plugin->renderer message handlers.
+ void OnMsgCreate(PP_Instance instance,
+ HostResource* result);
+ void OnMsgOpen(const HostResource& loader,
+ const HostResource& request_info,
+ uint32_t serialized_callback);
+ void OnMsgFollowRedirect(const HostResource& loader,
+ uint32_t serialized_callback);
+ void OnMsgGetResponseInfo(const HostResource& loader,
+ HostResource* result);
+ void OnMsgReadResponseBody(const HostResource& loader,
+ int32_t bytes_to_read);
+ void OnMsgFinishStreamingToFile(const HostResource& loader,
+ uint32_t serialized_callback);
+ void OnMsgClose(const HostResource& loader);
+ void OnMsgGrantUniversalAccess(const HostResource& loader);
+
+ // Renderer->plugin message handlers.
+ void OnMsgUpdateProgress(
+ const PPBURLLoader_UpdateProgress_Params& params);
+ void OnMsgReadResponseBodyAck(const HostResource& pp_resource,
+ int32_t result,
+ const std::string& data);
+
+ // Handles callbacks for read complete messages. Takes ownership of the info
+ // pointer.
+ void OnReadCallback(int32_t result, ReadCallbackInfo* info);
+
+ CompletionCallbackFactory<PPB_URLLoader_Proxy,
+ ProxyNonThreadSafeRefCount> callback_factory_;
+
+ // Valid only in the host, this lazily-initialized pointer indicates the
+ // URLLoaderTrusted interface.
+ const PPB_URLLoaderTrusted* host_urlloader_trusted_interface_;
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PPB_URL_LOADER_PROXY_H_
diff --git a/ppapi/proxy/ppb_url_request_info_proxy.cc b/ppapi/proxy/ppb_url_request_info_proxy.cc
new file mode 100644
index 0000000..9d545a2
--- /dev/null
+++ b/ppapi/proxy/ppb_url_request_info_proxy.cc
@@ -0,0 +1,206 @@
+// 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_url_request_info_proxy.h"
+
+#include "ppapi/c/ppb_url_request_info.h"
+#include "ppapi/proxy/enter_proxy.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/thunk/ppb_url_request_info_api.h"
+#include "ppapi/thunk/resource_creation_api.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::thunk::EnterFunctionNoLock;
+using ppapi::thunk::PPB_URLRequestInfo_API;
+using ppapi::thunk::ResourceCreationAPI;
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+InterfaceProxy* CreateURLRequestInfoProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_URLRequestInfo_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+class URLRequestInfo : public PluginResource,
+ public PPB_URLRequestInfo_API {
+ public:
+ URLRequestInfo(const HostResource& resource);
+ virtual ~URLRequestInfo();
+
+ virtual PPB_URLRequestInfo_API* AsPPB_URLRequestInfo_API() OVERRIDE;
+
+ // PPB_URLRequestInfo_API implementation.
+ virtual PP_Bool SetProperty(PP_URLRequestProperty property,
+ PP_Var var) OVERRIDE;
+ virtual PP_Bool AppendDataToBody(const void* data, uint32_t len) OVERRIDE;
+ virtual PP_Bool AppendFileToBody(
+ PP_Resource file_ref,
+ int64_t start_offset,
+ int64_t number_of_bytes,
+ PP_Time expected_last_modified_time) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(URLRequestInfo);
+};
+
+URLRequestInfo::URLRequestInfo(const HostResource& resource)
+ : PluginResource(resource) {
+}
+
+URLRequestInfo::~URLRequestInfo() {
+}
+
+PPB_URLRequestInfo_API* URLRequestInfo::AsPPB_URLRequestInfo_API() {
+ return this;
+}
+
+PP_Bool URLRequestInfo::SetProperty(PP_URLRequestProperty property,
+ PP_Var var) {
+ GetDispatcher()->Send(new PpapiHostMsg_PPBURLRequestInfo_SetProperty(
+ INTERFACE_ID_PPB_URL_REQUEST_INFO, host_resource(),
+ static_cast<int32_t>(property),
+ SerializedVarSendInput(GetDispatcher(), var)));
+
+ // TODO(brettw) do some validation on the types. We should be able to tell on
+ // the plugin side whether the request will succeed or fail in the renderer.
+ return PP_TRUE;
+}
+
+PP_Bool URLRequestInfo::AppendDataToBody(const void* data, uint32_t len) {
+ GetDispatcher()->Send(new PpapiHostMsg_PPBURLRequestInfo_AppendDataToBody(
+ INTERFACE_ID_PPB_URL_REQUEST_INFO, host_resource(),
+ std::string(static_cast<const char*>(data), len)));
+
+ // TODO(brettw) do some validation. We should be able to tell on the plugin
+ // side whether the request will succeed or fail in the renderer.
+ return PP_TRUE;
+}
+
+PP_Bool URLRequestInfo::AppendFileToBody(PP_Resource file_ref,
+ int64_t start_offset,
+ int64_t number_of_bytes,
+ PP_Time expected_last_modified_time) {
+ PluginResource* file_ref_object =
+ PluginResourceTracker::GetInstance()->GetResourceObject(file_ref);
+ if (!file_ref_object)
+ return PP_FALSE;
+
+ GetDispatcher()->Send(new PpapiHostMsg_PPBURLRequestInfo_AppendFileToBody(
+ INTERFACE_ID_PPB_URL_REQUEST_INFO, host_resource(),
+ file_ref_object->host_resource(),
+ start_offset, number_of_bytes, expected_last_modified_time));
+
+ // TODO(brettw) do some validation. We should be able to tell on the plugin
+ // side whether the request will succeed or fail in the renderer.
+ return PP_TRUE;
+}
+
+// PPB_URLRequestInfo_Proxy ----------------------------------------------------
+
+PPB_URLRequestInfo_Proxy::PPB_URLRequestInfo_Proxy(
+ Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_URLRequestInfo_Proxy::~PPB_URLRequestInfo_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_URLRequestInfo_Proxy::GetInfo() {
+ static const Info info = {
+ ::ppapi::thunk::GetPPB_URLRequestInfo_Thunk(),
+ PPB_URLREQUESTINFO_INTERFACE,
+ INTERFACE_ID_PPB_URL_REQUEST_INFO,
+ false,
+ &CreateURLRequestInfoProxy,
+ };
+ return &info;
+}
+
+// static
+PP_Resource PPB_URLRequestInfo_Proxy::CreateProxyResource(
+ PP_Instance instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+
+ HostResource result;
+ dispatcher->Send(new PpapiHostMsg_PPBURLRequestInfo_Create(
+ INTERFACE_ID_PPB_URL_REQUEST_INFO, instance, &result));
+ if (result.is_null())
+ return 0;
+
+ linked_ptr<URLRequestInfo> object(new URLRequestInfo(result));
+ return PluginResourceTracker::GetInstance()->AddResource(object);
+}
+
+bool PPB_URLRequestInfo_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_URLRequestInfo_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLRequestInfo_Create, OnMsgCreate)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLRequestInfo_SetProperty,
+ OnMsgSetProperty)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLRequestInfo_AppendDataToBody,
+ OnMsgAppendDataToBody)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLRequestInfo_AppendFileToBody,
+ OnMsgAppendFileToBody)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ // TODO(brettw): handle bad messages.
+ return handled;
+}
+
+void PPB_URLRequestInfo_Proxy::OnMsgCreate(
+ PP_Instance instance,
+ HostResource* result) {
+ EnterFunctionNoLock<ResourceCreationAPI> enter(instance, true);
+ if (enter.succeeded()) {
+ result->SetHostResource(instance,
+ enter.functions()->CreateURLRequestInfo(instance));
+ }
+}
+
+void PPB_URLRequestInfo_Proxy::OnMsgSetProperty(
+ HostResource request,
+ int32_t property,
+ SerializedVarReceiveInput value) {
+ EnterHostFromHostResource<PPB_URLRequestInfo_API> enter(request);
+ if (enter.succeeded()) {
+ enter.object()->SetProperty(static_cast<PP_URLRequestProperty>(property),
+ value.Get(dispatcher()));
+ }
+}
+
+void PPB_URLRequestInfo_Proxy::OnMsgAppendDataToBody(
+ HostResource request,
+ const std::string& data) {
+ EnterHostFromHostResource<PPB_URLRequestInfo_API> enter(request);
+ if (enter.succeeded())
+ enter.object()->AppendDataToBody(data.c_str(), data.size());
+}
+
+void PPB_URLRequestInfo_Proxy::OnMsgAppendFileToBody(
+ HostResource request,
+ HostResource file_ref,
+ int64_t start_offset,
+ int64_t number_of_bytes,
+ double expected_last_modified_time) {
+ EnterHostFromHostResource<PPB_URLRequestInfo_API> enter(request);
+ if (enter.succeeded()) {
+ enter.object()->AppendFileToBody(
+ file_ref.host_resource(), start_offset, number_of_bytes,
+ expected_last_modified_time);
+ }
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_url_request_info_proxy.h b/ppapi/proxy/ppb_url_request_info_proxy.h
new file mode 100644
index 0000000..5bfb4d4
--- /dev/null
+++ b/ppapi/proxy/ppb_url_request_info_proxy.h
@@ -0,0 +1,54 @@
+// 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_URL_REQUEST_INFO_PROXY_H_
+#define PPAPI_PROXY_PPB_URL_REQUEST_INFO_PROXY_H_
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_URLRequestInfo;
+
+namespace pp {
+namespace proxy {
+
+class SerializedVarReceiveInput;
+
+class PPB_URLRequestInfo_Proxy : public InterfaceProxy {
+ public:
+ PPB_URLRequestInfo_Proxy(Dispatcher* dispatcher,
+ const void* target_interface);
+ virtual ~PPB_URLRequestInfo_Proxy();
+
+ static const Info* GetInfo();
+
+ static PP_Resource CreateProxyResource(PP_Instance instance);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgCreate(PP_Instance instance, HostResource* result);
+ void OnMsgSetProperty(HostResource request,
+ int32_t property,
+ SerializedVarReceiveInput value);
+ void OnMsgAppendDataToBody(HostResource request,
+ const std::string& data);
+ void OnMsgAppendFileToBody(HostResource request,
+ HostResource file_ref,
+ int64_t start_offset,
+ int64_t number_of_bytes,
+ double expected_last_modified_time);
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_URLRequestInfo_Proxy);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_URL_REQUEST_INFO_PROXY_H_
diff --git a/ppapi/proxy/ppb_url_response_info_proxy.cc b/ppapi/proxy/ppb_url_response_info_proxy.cc
new file mode 100644
index 0000000..7d6f17d
--- /dev/null
+++ b/ppapi/proxy/ppb_url_response_info_proxy.cc
@@ -0,0 +1,153 @@
+// 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_url_response_info_proxy.h"
+
+#include "ppapi/c/ppb_url_response_info.h"
+#include "ppapi/proxy/enter_proxy.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"
+#include "ppapi/thunk/ppb_url_response_info_api.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::thunk::PPB_URLResponseInfo_API;
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+InterfaceProxy* CreateURLResponseInfoProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_URLResponseInfo_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+// URLResponseInfo -------------------------------------------------------------
+
+class URLResponseInfo : public PluginResource,
+ public PPB_URLResponseInfo_API {
+ public:
+ URLResponseInfo(const HostResource& resource);
+ virtual ~URLResponseInfo();
+
+ // ResourceObjectBase override.
+ virtual PPB_URLResponseInfo_API* AsPPB_URLResponseInfo_API() OVERRIDE;
+
+ // PPB_URLResponseInfo_API implementation.
+ virtual PP_Var GetProperty(PP_URLResponseProperty property) OVERRIDE;
+ virtual PP_Resource GetBodyAsFileRef() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(URLResponseInfo);
+};
+
+URLResponseInfo::URLResponseInfo(const HostResource& resource)
+ : PluginResource(resource) {
+}
+
+URLResponseInfo::~URLResponseInfo() {
+}
+
+PPB_URLResponseInfo_API* URLResponseInfo::AsPPB_URLResponseInfo_API() {
+ return this;
+}
+
+PP_Var URLResponseInfo::GetProperty(PP_URLResponseProperty property) {
+ ReceiveSerializedVarReturnValue result;
+ GetDispatcher()->Send(new PpapiHostMsg_PPBURLResponseInfo_GetProperty(
+ INTERFACE_ID_PPB_URL_RESPONSE_INFO, host_resource(), property, &result));
+ return result.Return(GetDispatcher());
+}
+
+PP_Resource URLResponseInfo::GetBodyAsFileRef() {
+ // This could be more efficient by having the host automatically send us the
+ // file ref when the request is streaming to a file and it's in the state
+ // where the file is ready. This will prevent us from having to do this sync
+ // IPC here.
+ PPBFileRef_CreateInfo create_info;
+ GetDispatcher()->Send(new PpapiHostMsg_PPBURLResponseInfo_GetBodyAsFileRef(
+ INTERFACE_ID_PPB_URL_RESPONSE_INFO, host_resource(), &create_info));
+ return PPB_FileRef_Proxy::DeserializeFileRef(create_info);
+}
+
+// PPB_URLResponseInfo_Proxy ---------------------------------------------------
+
+PPB_URLResponseInfo_Proxy::PPB_URLResponseInfo_Proxy(
+ Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_URLResponseInfo_Proxy::~PPB_URLResponseInfo_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_URLResponseInfo_Proxy::GetInfo() {
+ static const Info info = {
+ ppapi::thunk::GetPPB_URLResponseInfo_Thunk(),
+ PPB_URLRESPONSEINFO_INTERFACE,
+ INTERFACE_ID_PPB_URL_RESPONSE_INFO,
+ false,
+ &CreateURLResponseInfoProxy,
+ };
+ return &info;
+}
+
+// static
+PP_Resource PPB_URLResponseInfo_Proxy::CreateResponseForResource(
+ const HostResource& resource) {
+ linked_ptr<URLResponseInfo> object(new URLResponseInfo(resource));
+ return PluginResourceTracker::GetInstance()->AddResource(object);
+}
+
+bool PPB_URLResponseInfo_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_URLResponseInfo_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLResponseInfo_GetProperty,
+ OnMsgGetProperty)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLResponseInfo_GetBodyAsFileRef,
+ OnMsgGetBodyAsFileRef)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ // TODO(brettw): handle bad messages.
+ return handled;
+}
+
+void PPB_URLResponseInfo_Proxy::OnMsgGetProperty(
+ const HostResource& response,
+ int32_t property,
+ SerializedVarReturnValue result) {
+ EnterHostFromHostResource<PPB_URLResponseInfo_API> enter(response);
+ PP_Var result_var = PP_MakeUndefined();
+ if (enter.succeeded()) {
+ result_var = enter.object()->GetProperty(
+ static_cast<PP_URLResponseProperty>(property));
+ }
+ result.Return(dispatcher(), result_var);
+}
+
+void PPB_URLResponseInfo_Proxy::OnMsgGetBodyAsFileRef(
+ const HostResource& response,
+ PPBFileRef_CreateInfo* result) {
+ EnterHostFromHostResource<PPB_URLResponseInfo_API> enter(response);
+ PP_Resource file_ref = 0;
+ if (enter.succeeded())
+ file_ref = enter.object()->GetBodyAsFileRef();
+
+ // Use the FileRef proxy to serialize.
+ 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));
+ file_ref_proxy->SerializeFileRef(file_ref, result);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_url_response_info_proxy.h b/ppapi/proxy/ppb_url_response_info_proxy.h
new file mode 100644
index 0000000..ed6fb43
--- /dev/null
+++ b/ppapi/proxy/ppb_url_response_info_proxy.h
@@ -0,0 +1,55 @@
+// 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_URL_RESPONSE_INFO_PROXY_H_
+#define PPAPI_PROXY_PPB_URL_RESPONSE_INFO_PROXY_H_
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_URLResponseInfo;
+
+namespace pp {
+namespace proxy {
+
+struct PPBFileRef_CreateInfo;
+class SerializedVarReturnValue;
+
+class PPB_URLResponseInfo_Proxy : public InterfaceProxy {
+ public:
+ PPB_URLResponseInfo_Proxy(Dispatcher* dispatcher,
+ const void* target_interface);
+ virtual ~PPB_URLResponseInfo_Proxy();
+
+ static const Info* GetInfo();
+
+ // URLResponseInfo objects are actually created and returned by the
+ // URLLoader. This function allows the URLLoader to convert a new
+ // HostResource representing a response info to a properly tracked
+ // URLReponseInfo PluginResource. Returns the plugin resource ID for the
+ // new resource.
+ static PP_Resource CreateResponseForResource(const HostResource& resource);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgGetProperty(const HostResource& response,
+ int32_t property,
+ SerializedVarReturnValue result);
+ void OnMsgGetBodyAsFileRef(const HostResource& response,
+ PPBFileRef_CreateInfo* result);
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_URLResponseInfo_Proxy);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_URL_RESPONSE_INFO_PROXY_H_
diff --git a/ppapi/proxy/ppb_url_util_proxy.cc b/ppapi/proxy/ppb_url_util_proxy.cc
new file mode 100644
index 0000000..b59ef3c
--- /dev/null
+++ b/ppapi/proxy/ppb_url_util_proxy.cc
@@ -0,0 +1,228 @@
+// 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_url_util_proxy.h"
+
+#include "base/basictypes.h"
+#include "ppapi/c/dev/ppb_url_util_dev.h"
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/url_util_impl.h"
+
+namespace pp {
+namespace proxy {
+
+using ppapi::URLUtilImpl;
+
+namespace {
+
+URLUtilImpl::VarFromUtf8 GetVarFromUtf8() {
+ const PPB_Var_Deprecated* var_deprecated =
+ static_cast<const PPB_Var_Deprecated*>(
+ PluginDispatcher::GetInterfaceFromDispatcher(
+ PPB_VAR_DEPRECATED_INTERFACE));
+ return var_deprecated->VarFromUtf8;
+}
+
+const std::string* GetStringFromVar(PP_Var var) {
+ return PluginVarTracker::GetInstance()->GetExistingString(var);
+}
+
+PP_Var Canonicalize(PP_Var url,
+ PP_URLComponents_Dev* components) {
+ return URLUtilImpl::Canonicalize(&GetStringFromVar, GetVarFromUtf8(),
+ 0, url, components);
+}
+
+// Helper function for the functions below that optionally take a components
+// structure. It's annoying to serialze the large PP_URLComponents structure
+// and this data often isn't needed.
+//
+// To avoid this, we instead just parse the result again in the plugin, which
+// this function does if the given URL is valid and the components are
+// non-NULL. The URL var will be returned.
+PP_Var ConvertComponentsAndReturnURL(PP_Var url,
+ PP_URLComponents_Dev* components) {
+ if (!components)
+ return url; // Common case - plugin doesn't care about parsing.
+
+ const std::string* url_string = GetStringFromVar(url);
+ if (!url_string)
+ return url;
+
+ PP_Var result = Canonicalize(url, components);
+ PluginVarTracker::GetInstance()->Release(url);
+ return result;
+}
+
+PP_Var ResolveRelativeToURL(PP_Var base_url,
+ PP_Var relative,
+ PP_URLComponents_Dev* components) {
+ return URLUtilImpl::ResolveRelativeToURL(&GetStringFromVar, GetVarFromUtf8(),
+ 0, base_url, relative, components);
+}
+
+PP_Var ResolveRelativeToDocument(PP_Instance instance,
+ PP_Var relative_string,
+ PP_URLComponents_Dev* components) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return PP_MakeNull();
+
+ ReceiveSerializedVarReturnValue result;
+ dispatcher->Send(new PpapiHostMsg_PPBURLUtil_ResolveRelativeToDocument(
+ INTERFACE_ID_PPB_URL_UTIL, instance,
+ SerializedVarSendInput(dispatcher, relative_string),
+ &result));
+ return ConvertComponentsAndReturnURL(result.Return(dispatcher), components);
+}
+
+PP_Bool IsSameSecurityOrigin(PP_Var url_a, PP_Var url_b) {
+ return URLUtilImpl::IsSameSecurityOrigin(&GetStringFromVar, url_a, url_b);
+}
+
+PP_Bool DocumentCanRequest(PP_Instance instance, PP_Var url) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return PP_FALSE;
+
+ PP_Bool result = PP_FALSE;
+ dispatcher->Send(new PpapiHostMsg_PPBURLUtil_DocumentCanRequest(
+ INTERFACE_ID_PPB_URL_UTIL, instance,
+ SerializedVarSendInput(dispatcher, url),
+ &result));
+ return result;
+}
+
+PP_Bool DocumentCanAccessDocument(PP_Instance active, PP_Instance target) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(active);
+ if (!dispatcher)
+ return PP_FALSE;
+
+ PP_Bool result = PP_FALSE;
+ dispatcher->Send(new PpapiHostMsg_PPBURLUtil_DocumentCanAccessDocument(
+ INTERFACE_ID_PPB_URL_UTIL, active, target, &result));
+ return result;
+}
+
+PP_Var GetDocumentURL(PP_Instance instance,
+ struct PP_URLComponents_Dev* components) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return PP_MakeNull();
+
+ ReceiveSerializedVarReturnValue result;
+ dispatcher->Send(new PpapiHostMsg_PPBURLUtil_GetDocumentURL(
+ INTERFACE_ID_PPB_URL_UTIL, instance, &result));
+ return ConvertComponentsAndReturnURL(result.Return(dispatcher), components);
+}
+
+PP_Var GetPluginInstanceURL(PP_Instance instance,
+ struct PP_URLComponents_Dev* components) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return PP_MakeNull();
+
+ ReceiveSerializedVarReturnValue result;
+ dispatcher->Send(new PpapiHostMsg_PPBURLUtil_GetPluginInstanceURL(
+ INTERFACE_ID_PPB_URL_UTIL, instance, &result));
+ return ConvertComponentsAndReturnURL(result.Return(dispatcher), components);
+}
+
+const PPB_URLUtil_Dev url_util_interface = {
+ &Canonicalize,
+ &ResolveRelativeToURL,
+ &ResolveRelativeToDocument,
+ &IsSameSecurityOrigin,
+ &DocumentCanRequest,
+ &DocumentCanAccessDocument,
+ &GetDocumentURL,
+ &GetPluginInstanceURL
+};
+
+InterfaceProxy* CreateURLUtilProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_URLUtil_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_URLUtil_Proxy::PPB_URLUtil_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_URLUtil_Proxy::~PPB_URLUtil_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_URLUtil_Proxy::GetInfo() {
+ static const Info info = {
+ &url_util_interface,
+ PPB_URLUTIL_DEV_INTERFACE,
+ INTERFACE_ID_PPB_URL_UTIL,
+ false,
+ &CreateURLUtilProxy,
+ };
+ return &info;
+}
+
+bool PPB_URLUtil_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_URLUtil_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLUtil_ResolveRelativeToDocument,
+ OnMsgResolveRelativeToDocument)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLUtil_DocumentCanRequest,
+ OnMsgDocumentCanRequest)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLUtil_DocumentCanAccessDocument,
+ OnMsgDocumentCanAccessDocument)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLUtil_GetDocumentURL,
+ OnMsgGetDocumentURL)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLUtil_GetPluginInstanceURL,
+ OnMsgGetPluginInstanceURL)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPB_URLUtil_Proxy::OnMsgResolveRelativeToDocument(
+ PP_Instance instance,
+ SerializedVarReceiveInput relative,
+ SerializedVarReturnValue result) {
+ result.Return(dispatcher(),
+ ppb_url_util_target()->ResolveRelativeToDocument(
+ instance, relative.Get(dispatcher()), NULL));
+}
+
+void PPB_URLUtil_Proxy::OnMsgDocumentCanRequest(PP_Instance instance,
+ SerializedVarReceiveInput url,
+ PP_Bool* result) {
+ *result = ppb_url_util_target()->DocumentCanRequest(instance,
+ url.Get(dispatcher()));
+}
+
+void PPB_URLUtil_Proxy::OnMsgDocumentCanAccessDocument(PP_Instance active,
+ PP_Instance target,
+ PP_Bool* result) {
+ *result = ppb_url_util_target()->DocumentCanAccessDocument(
+ active, target);
+}
+
+void PPB_URLUtil_Proxy::OnMsgGetDocumentURL(PP_Instance instance,
+ SerializedVarReturnValue result) {
+ result.Return(dispatcher(),
+ ppb_url_util_target()->GetDocumentURL(instance, NULL));
+}
+
+void PPB_URLUtil_Proxy::OnMsgGetPluginInstanceURL(
+ PP_Instance instance, SerializedVarReturnValue result) {
+ result.Return(dispatcher(),
+ ppb_url_util_target()->GetPluginInstanceURL(instance, NULL));
+}
+
+} // namespace proxy
+} // namespace pp
+
diff --git a/ppapi/proxy/ppb_url_util_proxy.h b/ppapi/proxy/ppb_url_util_proxy.h
new file mode 100644
index 0000000..548d2ef
--- /dev/null
+++ b/ppapi/proxy/ppb_url_util_proxy.h
@@ -0,0 +1,54 @@
+// 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_URL_UTIL_PROXY_H_
+#define PPAPI_PROXY_PPB_URL_UTIL_PROXY_H_
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/serialized_var.h"
+
+struct PPB_URLUtil_Dev;
+
+namespace pp {
+namespace proxy {
+
+class PPB_URLUtil_Proxy : public InterfaceProxy {
+ public:
+ PPB_URLUtil_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_URLUtil_Proxy();
+
+ static const Info* GetInfo();
+
+ const PPB_URLUtil_Dev* ppb_url_util_target() const {
+ return static_cast<const PPB_URLUtil_Dev*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgResolveRelativeToDocument(PP_Instance instance,
+ SerializedVarReceiveInput relative,
+ SerializedVarReturnValue result);
+ void OnMsgDocumentCanRequest(PP_Instance instance,
+ SerializedVarReceiveInput url,
+ PP_Bool* result);
+ void OnMsgDocumentCanAccessDocument(PP_Instance active,
+ PP_Instance target,
+ PP_Bool* result);
+ void OnMsgGetDocumentURL(PP_Instance instance,
+ SerializedVarReturnValue result);
+ void OnMsgGetPluginInstanceURL(PP_Instance instance,
+ SerializedVarReturnValue result);
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_URLUtil_Proxy);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_URL_UTIL_PROXY_H_
+
diff --git a/ppapi/proxy/ppb_var_deprecated_proxy.cc b/ppapi/proxy/ppb_var_deprecated_proxy.cc
new file mode 100644
index 0000000..652bdc8
--- /dev/null
+++ b/ppapi/proxy/ppb_var_deprecated_proxy.cc
@@ -0,0 +1,523 @@
+// 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_var_deprecated_proxy.h"
+
+#include <stdlib.h> // For malloc
+
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/task.h"
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppp_class_proxy.h"
+#include "ppapi/proxy/serialized_var.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+// Used to do get the set-up information for calling a var object. If the
+// exception is set, returns NULL. Otherwise, computes the dispatcher for the
+// given var object. If the var is not a valid object, returns NULL and sets
+// the exception.
+PluginDispatcher* CheckExceptionAndGetDispatcher(const PP_Var& object,
+ PP_Var* exception) {
+ // If an exception is already set, we don't need to do anything, just return
+ // an error to the caller.
+ if (exception && exception->type != PP_VARTYPE_UNDEFINED)
+ return NULL;
+
+ PluginVarTracker* tracker = PluginVarTracker::GetInstance();
+ PluginDispatcher* dispatcher = tracker->DispatcherForPluginObject(object);
+ if (dispatcher)
+ return dispatcher;
+
+ // The object is invalid. This means we can't figure out which dispatcher
+ // to use, which is OK because the call will fail anyway. Set the exception.
+ if (exception) {
+ exception->type = PP_VARTYPE_STRING;
+ exception->value.as_id =
+ tracker->MakeString("Attempting to use an invalid object");
+ }
+ return NULL;
+}
+
+// PPP_Var_Deprecated plugin ---------------------------------------------------
+
+void AddRefVar(PP_Var var) {
+ PluginVarTracker::GetInstance()->AddRef(var);
+}
+
+void ReleaseVar(PP_Var var) {
+ PluginVarTracker::GetInstance()->Release(var);
+}
+
+PP_Var VarFromUtf8(PP_Module module, const char* data, uint32_t len) {
+ PP_Var ret = {};
+ ret.type = PP_VARTYPE_STRING;
+ ret.value.as_id = PluginVarTracker::GetInstance()->MakeString(
+ data, len);
+ return ret;
+}
+
+const char* VarToUtf8(PP_Var var, uint32_t* len) {
+ const std::string* str =
+ PluginVarTracker::GetInstance()->GetExistingString(var);
+ if (str) {
+ *len = static_cast<uint32_t>(str->size());
+ return str->c_str();
+ }
+ *len = 0;
+ return NULL;
+}
+
+bool HasProperty(PP_Var var,
+ PP_Var name,
+ PP_Var* exception) {
+ Dispatcher* dispatcher = CheckExceptionAndGetDispatcher(var, exception);
+ if (!dispatcher)
+ return false;
+
+ ReceiveSerializedException se(dispatcher, exception);
+ PP_Bool result = PP_FALSE;
+ if (!se.IsThrown()) {
+ dispatcher->Send(new PpapiHostMsg_PPBVar_HasProperty(
+ INTERFACE_ID_PPB_VAR_DEPRECATED,
+ SerializedVarSendInput(dispatcher, var),
+ SerializedVarSendInput(dispatcher, name), &se, &result));
+ }
+ return PP_ToBool(result);
+}
+
+bool HasMethod(PP_Var var,
+ PP_Var name,
+ PP_Var* exception) {
+ Dispatcher* dispatcher = CheckExceptionAndGetDispatcher(var, exception);
+ if (!dispatcher)
+ return false;
+
+ ReceiveSerializedException se(dispatcher, exception);
+ PP_Bool result = PP_FALSE;
+ if (!se.IsThrown()) {
+ dispatcher->Send(new PpapiHostMsg_PPBVar_HasMethodDeprecated(
+ INTERFACE_ID_PPB_VAR_DEPRECATED,
+ SerializedVarSendInput(dispatcher, var),
+ SerializedVarSendInput(dispatcher, name), &se, &result));
+ }
+ return PP_ToBool(result);
+}
+
+PP_Var GetProperty(PP_Var var,
+ PP_Var name,
+ PP_Var* exception) {
+ Dispatcher* dispatcher = CheckExceptionAndGetDispatcher(var, exception);
+ if (!dispatcher)
+ return PP_MakeUndefined();
+
+ ReceiveSerializedException se(dispatcher, exception);
+ ReceiveSerializedVarReturnValue result;
+ if (!se.IsThrown()) {
+ dispatcher->Send(new PpapiHostMsg_PPBVar_GetProperty(
+ INTERFACE_ID_PPB_VAR_DEPRECATED,
+ SerializedVarSendInput(dispatcher, var),
+ SerializedVarSendInput(dispatcher, name), &se, &result));
+ }
+ return result.Return(dispatcher);
+}
+
+void EnumerateProperties(PP_Var var,
+ uint32_t* property_count,
+ PP_Var** properties,
+ PP_Var* exception) {
+ Dispatcher* dispatcher = CheckExceptionAndGetDispatcher(var, exception);
+ if (!dispatcher) {
+ *property_count = 0;
+ *properties = NULL;
+ return;
+ }
+
+ ReceiveSerializedVarVectorOutParam out_vector(dispatcher,
+ property_count, properties);
+ ReceiveSerializedException se(dispatcher, exception);
+ if (!se.IsThrown()) {
+ dispatcher->Send(new PpapiHostMsg_PPBVar_EnumerateProperties(
+ INTERFACE_ID_PPB_VAR_DEPRECATED,
+ SerializedVarSendInput(dispatcher, var),
+ out_vector.OutParam(), &se));
+ }
+}
+
+void SetProperty(PP_Var var,
+ PP_Var name,
+ PP_Var value,
+ PP_Var* exception) {
+ Dispatcher* dispatcher = CheckExceptionAndGetDispatcher(var, exception);
+ if (!dispatcher)
+ return;
+
+ ReceiveSerializedException se(dispatcher, exception);
+ if (!se.IsThrown()) {
+ dispatcher->Send(new PpapiHostMsg_PPBVar_SetPropertyDeprecated(
+ INTERFACE_ID_PPB_VAR_DEPRECATED,
+ SerializedVarSendInput(dispatcher, var),
+ SerializedVarSendInput(dispatcher, name),
+ SerializedVarSendInput(dispatcher, value), &se));
+ }
+}
+
+void RemoveProperty(PP_Var var,
+ PP_Var name,
+ PP_Var* exception) {
+ Dispatcher* dispatcher = CheckExceptionAndGetDispatcher(var, exception);
+ if (!dispatcher)
+ return;
+
+ ReceiveSerializedException se(dispatcher, exception);
+ PP_Bool result = PP_FALSE;
+ if (!se.IsThrown()) {
+ dispatcher->Send(new PpapiHostMsg_PPBVar_DeleteProperty(
+ INTERFACE_ID_PPB_VAR_DEPRECATED,
+ SerializedVarSendInput(dispatcher, var),
+ SerializedVarSendInput(dispatcher, name), &se, &result));
+ }
+}
+
+PP_Var Call(PP_Var object,
+ PP_Var method_name,
+ uint32_t argc,
+ PP_Var* argv,
+ PP_Var* exception) {
+ Dispatcher* dispatcher = CheckExceptionAndGetDispatcher(object, exception);
+ if (!dispatcher)
+ return PP_MakeUndefined();
+
+ ReceiveSerializedVarReturnValue result;
+ ReceiveSerializedException se(dispatcher, exception);
+ if (!se.IsThrown()) {
+ std::vector<SerializedVar> argv_vect;
+ SerializedVarSendInput::ConvertVector(dispatcher, argv, argc, &argv_vect);
+
+ dispatcher->Send(new PpapiHostMsg_PPBVar_CallDeprecated(
+ INTERFACE_ID_PPB_VAR_DEPRECATED,
+ SerializedVarSendInput(dispatcher, object),
+ SerializedVarSendInput(dispatcher, method_name), argv_vect,
+ &se, &result));
+ }
+ return result.Return(dispatcher);
+}
+
+PP_Var Construct(PP_Var object,
+ uint32_t argc,
+ PP_Var* argv,
+ PP_Var* exception) {
+ Dispatcher* dispatcher = CheckExceptionAndGetDispatcher(object, exception);
+ if (!dispatcher)
+ return PP_MakeUndefined();
+
+ ReceiveSerializedVarReturnValue result;
+ ReceiveSerializedException se(dispatcher, exception);
+ if (!se.IsThrown()) {
+ std::vector<SerializedVar> argv_vect;
+ SerializedVarSendInput::ConvertVector(dispatcher, argv, argc, &argv_vect);
+
+ dispatcher->Send(new PpapiHostMsg_PPBVar_Construct(
+ INTERFACE_ID_PPB_VAR_DEPRECATED,
+ SerializedVarSendInput(dispatcher, object),
+ argv_vect, &se, &result));
+ }
+ return result.Return(dispatcher);
+}
+
+bool IsInstanceOf(PP_Var var,
+ const PPP_Class_Deprecated* ppp_class,
+ void** ppp_class_data) {
+ Dispatcher* dispatcher = CheckExceptionAndGetDispatcher(var, NULL);
+ if (!dispatcher)
+ return false;
+
+ PP_Bool result = PP_FALSE;
+ int64 class_int = static_cast<int64>(reinterpret_cast<intptr_t>(ppp_class));
+ int64 class_data_int = 0;
+ dispatcher->Send(new PpapiHostMsg_PPBVar_IsInstanceOfDeprecated(
+ INTERFACE_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var),
+ class_int, &class_data_int, &result));
+ *ppp_class_data =
+ reinterpret_cast<void*>(static_cast<intptr_t>(class_data_int));
+ return PP_ToBool(result);
+}
+
+PP_Var CreateObject(PP_Instance instance,
+ const PPP_Class_Deprecated* ppp_class,
+ void* ppp_class_data) {
+ Dispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return PP_MakeUndefined();
+
+ ReceiveSerializedVarReturnValue result;
+ int64 class_int = static_cast<int64>(reinterpret_cast<intptr_t>(ppp_class));
+ int64 data_int =
+ static_cast<int64>(reinterpret_cast<intptr_t>(ppp_class_data));
+ dispatcher->Send(new PpapiHostMsg_PPBVar_CreateObjectDeprecated(
+ INTERFACE_ID_PPB_VAR_DEPRECATED, instance, class_int, data_int,
+ &result));
+ return result.Return(dispatcher);
+}
+
+const PPB_Var_Deprecated var_deprecated_interface = {
+ &AddRefVar,
+ &ReleaseVar,
+ &VarFromUtf8,
+ &VarToUtf8,
+ &HasProperty,
+ &HasMethod,
+ &GetProperty,
+ &EnumerateProperties,
+ &SetProperty,
+ &RemoveProperty,
+ &Call,
+ &Construct,
+ &IsInstanceOf,
+ &CreateObject
+};
+
+InterfaceProxy* CreateVarDeprecatedProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Var_Deprecated_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_Var_Deprecated_Proxy::PPB_Var_Deprecated_Proxy(
+ Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface),
+ task_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+}
+
+PPB_Var_Deprecated_Proxy::~PPB_Var_Deprecated_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Var_Deprecated_Proxy::GetInfo() {
+ static const Info info = {
+ &var_deprecated_interface,
+ PPB_VAR_DEPRECATED_INTERFACE,
+ INTERFACE_ID_PPB_VAR_DEPRECATED,
+ false,
+ &CreateVarDeprecatedProxy,
+ };
+ return &info;
+}
+
+bool PPB_Var_Deprecated_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ // Prevent the dispatcher from going away during a call to Call or other
+ // function that could mutate the DOM. This must happen OUTSIDE of
+ // the message handlers since the SerializedVars use the dispatcher upon
+ // return of the function (converting the SerializedVarReturnValue/OutParam
+ // to a SerializedVar in the destructor).
+ ScopedModuleReference death_grip(dispatcher());
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Var_Deprecated_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_AddRefObject, OnMsgAddRefObject)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_ReleaseObject, OnMsgReleaseObject)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_HasProperty,
+ OnMsgHasProperty)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_HasMethodDeprecated,
+ OnMsgHasMethodDeprecated)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_GetProperty,
+ OnMsgGetProperty)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_DeleteProperty,
+ OnMsgDeleteProperty)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_EnumerateProperties,
+ OnMsgEnumerateProperties)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_SetPropertyDeprecated,
+ OnMsgSetPropertyDeprecated)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_CallDeprecated,
+ OnMsgCallDeprecated)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_Construct,
+ OnMsgConstruct)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_IsInstanceOfDeprecated,
+ OnMsgIsInstanceOfDeprecated)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_CreateObjectDeprecated,
+ OnMsgCreateObjectDeprecated)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ // TODO(brettw) handle bad messages!
+ return handled;
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgAddRefObject(int64 object_id,
+ int* /* unused */) {
+ PP_Var var;
+ var.type = PP_VARTYPE_OBJECT;
+ var.value.as_id = object_id;
+ ppb_var_target()->AddRef(var);
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgReleaseObject(int64 object_id) {
+ // Ok, so this is super subtle.
+ // When the browser side sends a sync IPC message that returns a var, and the
+ // plugin wants to give ownership of that var to the browser, dropping all
+ // references, it may call ReleaseObject right after returning the result.
+ // However, the IPC system doesn't enforce strict ordering of messages in that
+ // case, where a message that is set to unblock (e.g. a sync message, or in
+ // our case all messages coming from the plugin) that is sent *after* the
+ // result may be dispatched on the browser side *before* the sync send
+ // returned (see ipc_sync_channel.cc). In this case, that means it could
+ // release the object before it is AddRef'ed on the browser side.
+ // To work around this, we post a task here, that will not execute before
+ // control goes back to the main message loop, that will ensure the sync send
+ // has returned and the browser side can take its reference before we Release.
+ // Note: if the instance is gone by the time the task is executed, then it
+ // will Release the objects itself and this Release will be a NOOP (aside of a
+ // spurious warning).
+ // TODO(piman): See if we can fix the IPC code to enforce strict ordering, and
+ // then remove this.
+ MessageLoop::current()->PostNonNestableTask(FROM_HERE,
+ task_factory_.NewRunnableMethod(
+ &PPB_Var_Deprecated_Proxy::DoReleaseObject, object_id));
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgHasProperty(
+ SerializedVarReceiveInput var,
+ SerializedVarReceiveInput name,
+ SerializedVarOutParam exception,
+ PP_Bool* result) {
+ SetAllowPluginReentrancy();
+ *result = PP_FromBool(ppb_var_target()->HasProperty(
+ var.Get(dispatcher()),
+ name.Get(dispatcher()),
+ exception.OutParam(dispatcher())));
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgHasMethodDeprecated(
+ SerializedVarReceiveInput var,
+ SerializedVarReceiveInput name,
+ SerializedVarOutParam exception,
+ PP_Bool* result) {
+ SetAllowPluginReentrancy();
+ *result = PP_FromBool(ppb_var_target()->HasMethod(
+ var.Get(dispatcher()),
+ name.Get(dispatcher()),
+ exception.OutParam(dispatcher())));
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgGetProperty(
+ SerializedVarReceiveInput var,
+ SerializedVarReceiveInput name,
+ SerializedVarOutParam exception,
+ SerializedVarReturnValue result) {
+ SetAllowPluginReentrancy();
+ result.Return(dispatcher(), ppb_var_target()->GetProperty(
+ var.Get(dispatcher()), name.Get(dispatcher()),
+ exception.OutParam(dispatcher())));
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgEnumerateProperties(
+ SerializedVarReceiveInput var,
+ SerializedVarVectorOutParam props,
+ SerializedVarOutParam exception) {
+ SetAllowPluginReentrancy();
+ ppb_var_target()->GetAllPropertyNames(var.Get(dispatcher()),
+ props.CountOutParam(), props.ArrayOutParam(dispatcher()),
+ exception.OutParam(dispatcher()));
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgSetPropertyDeprecated(
+ SerializedVarReceiveInput var,
+ SerializedVarReceiveInput name,
+ SerializedVarReceiveInput value,
+ SerializedVarOutParam exception) {
+ SetAllowPluginReentrancy();
+ ppb_var_target()->SetProperty(var.Get(dispatcher()),
+ name.Get(dispatcher()),
+ value.Get(dispatcher()),
+ exception.OutParam(dispatcher()));
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgDeleteProperty(
+ SerializedVarReceiveInput var,
+ SerializedVarReceiveInput name,
+ SerializedVarOutParam exception,
+ PP_Bool* result) {
+ SetAllowPluginReentrancy();
+ ppb_var_target()->RemoveProperty(var.Get(dispatcher()),
+ name.Get(dispatcher()),
+ exception.OutParam(dispatcher()));
+ // This deprecated function doesn't actually return a value, but we re-use
+ // the message from the non-deprecated interface with the return value.
+ *result = PP_TRUE;
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgCallDeprecated(
+ SerializedVarReceiveInput object,
+ SerializedVarReceiveInput method_name,
+ SerializedVarVectorReceiveInput arg_vector,
+ SerializedVarOutParam exception,
+ SerializedVarReturnValue result) {
+ SetAllowPluginReentrancy();
+ uint32_t arg_count = 0;
+ PP_Var* args = arg_vector.Get(dispatcher(), &arg_count);
+ result.Return(dispatcher(), ppb_var_target()->Call(
+ object.Get(dispatcher()),
+ method_name.Get(dispatcher()),
+ arg_count, args,
+ exception.OutParam(dispatcher())));
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgConstruct(
+ SerializedVarReceiveInput var,
+ SerializedVarVectorReceiveInput arg_vector,
+ SerializedVarOutParam exception,
+ SerializedVarReturnValue result) {
+ SetAllowPluginReentrancy();
+ uint32_t arg_count = 0;
+ PP_Var* args = arg_vector.Get(dispatcher(), &arg_count);
+ result.Return(dispatcher(), ppb_var_target()->Construct(
+ var.Get(dispatcher()), arg_count, args,
+ exception.OutParam(dispatcher())));
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgIsInstanceOfDeprecated(
+ pp::proxy::SerializedVarReceiveInput var,
+ int64 ppp_class,
+ int64* ppp_class_data,
+ PP_Bool* result) {
+ // TODO(brettw) write this.
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgCreateObjectDeprecated(
+ PP_Instance instance,
+ int64 ppp_class,
+ int64 class_data,
+ SerializedVarReturnValue result) {
+ SetAllowPluginReentrancy();
+ result.Return(dispatcher(), PPP_Class_Proxy::CreateProxiedObject(
+ ppb_var_target(), dispatcher(), instance, ppp_class, class_data));
+}
+
+void PPB_Var_Deprecated_Proxy::SetAllowPluginReentrancy() {
+ if (dispatcher()->IsPlugin())
+ NOTREACHED();
+ else
+ static_cast<HostDispatcher*>(dispatcher())->set_allow_plugin_reentrancy();
+}
+
+void PPB_Var_Deprecated_Proxy::DoReleaseObject(int64 object_id) {
+ PP_Var var;
+ var.type = PP_VARTYPE_OBJECT;
+ var.value.as_id = object_id;
+ ppb_var_target()->Release(var);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_var_deprecated_proxy.h b/ppapi/proxy/ppb_var_deprecated_proxy.h
new file mode 100644
index 0000000..1e6a70c
--- /dev/null
+++ b/ppapi/proxy/ppb_var_deprecated_proxy.h
@@ -0,0 +1,104 @@
+// 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_PPB_VAR_DEPRECATED_PROXY_H_
+#define PPAPI_PPB_VAR_DEPRECATED_PROXY_H_
+
+#include <vector>
+
+#include "base/task.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_Var_Deprecated;
+
+namespace pp {
+namespace proxy {
+
+class SerializedVar;
+class SerializedVarArray;
+class SerializedVarReceiveInput;
+class SerializedVarVectorOutParam;
+class SerializedVarVectorReceiveInput;
+class SerializedVarOutParam;
+class SerializedVarReturnValue;
+
+class PPB_Var_Deprecated_Proxy : public InterfaceProxy {
+ public:
+ PPB_Var_Deprecated_Proxy(Dispatcher* dispatcher,
+ const void* target_interface);
+ virtual ~PPB_Var_Deprecated_Proxy();
+
+ static const Info* GetInfo();
+
+ const PPB_Var_Deprecated* ppb_var_target() const {
+ return static_cast<const PPB_Var_Deprecated*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgAddRefObject(int64 object_id, int* unused);
+ void OnMsgReleaseObject(int64 object_id);
+ void OnMsgHasProperty(SerializedVarReceiveInput var,
+ SerializedVarReceiveInput name,
+ SerializedVarOutParam exception,
+ PP_Bool* result);
+ void OnMsgHasMethodDeprecated(SerializedVarReceiveInput var,
+ SerializedVarReceiveInput name,
+ SerializedVarOutParam exception,
+ PP_Bool* result);
+ void OnMsgGetProperty(SerializedVarReceiveInput var,
+ SerializedVarReceiveInput name,
+ SerializedVarOutParam exception,
+ SerializedVarReturnValue result);
+ void OnMsgEnumerateProperties(
+ SerializedVarReceiveInput var,
+ SerializedVarVectorOutParam props,
+ SerializedVarOutParam exception);
+ void OnMsgSetPropertyDeprecated(SerializedVarReceiveInput var,
+ SerializedVarReceiveInput name,
+ SerializedVarReceiveInput value,
+ SerializedVarOutParam exception);
+ void OnMsgDeleteProperty(SerializedVarReceiveInput var,
+ SerializedVarReceiveInput name,
+ SerializedVarOutParam exception,
+ PP_Bool* result);
+ void OnMsgCall(SerializedVarReceiveInput object,
+ SerializedVarReceiveInput this_object,
+ SerializedVarReceiveInput method_name,
+ SerializedVarVectorReceiveInput arg_vector,
+ SerializedVarOutParam exception,
+ SerializedVarReturnValue result);
+ void OnMsgCallDeprecated(SerializedVarReceiveInput object,
+ SerializedVarReceiveInput method_name,
+ SerializedVarVectorReceiveInput arg_vector,
+ SerializedVarOutParam exception,
+ SerializedVarReturnValue result);
+ void OnMsgConstruct(SerializedVarReceiveInput var,
+ SerializedVarVectorReceiveInput arg_vector,
+ SerializedVarOutParam exception,
+ SerializedVarReturnValue result);
+ void OnMsgIsInstanceOfDeprecated(pp::proxy::SerializedVarReceiveInput var,
+ int64 ppp_class,
+ int64* ppp_class_data,
+ PP_Bool* result);
+ void OnMsgCreateObjectDeprecated(PP_Instance instance,
+ int64 ppp_class,
+ int64 ppp_class_data,
+ SerializedVarReturnValue result);
+
+ // Call in the host for messages that can be reentered.
+ void SetAllowPluginReentrancy();
+
+ void DoReleaseObject(int64 object_id);
+ ScopedRunnableMethodFactory<PPB_Var_Deprecated_Proxy> task_factory_;
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PPB_VAR_DEPRECATED_PROXY_H_
diff --git a/ppapi/proxy/ppb_var_proxy.cc b/ppapi/proxy/ppb_var_proxy.cc
new file mode 100644
index 0000000..063d4d3
--- /dev/null
+++ b/ppapi/proxy/ppb_var_proxy.cc
@@ -0,0 +1,85 @@
+// 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_var_proxy.h"
+
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+// PPP_Var plugin --------------------------------------------------------------
+
+void AddRefVar(PP_Var var) {
+ PluginVarTracker::GetInstance()->AddRef(var);
+}
+
+void ReleaseVar(PP_Var var) {
+ PluginVarTracker::GetInstance()->Release(var);
+}
+
+PP_Var VarFromUtf8(PP_Module module, const char* data, uint32_t len) {
+ PP_Var ret = {};
+ ret.type = PP_VARTYPE_STRING;
+ ret.value.as_id = PluginVarTracker::GetInstance()->MakeString(data, len);
+ return ret;
+}
+
+const char* VarToUtf8(PP_Var var, uint32_t* len) {
+ const std::string* str =
+ PluginVarTracker::GetInstance()->GetExistingString(var);
+ if (str) {
+ *len = static_cast<uint32_t>(str->size());
+ return str->c_str();
+ }
+ *len = 0;
+ return NULL;
+}
+
+const PPB_Var var_interface = {
+ &AddRefVar,
+ &ReleaseVar,
+ &VarFromUtf8,
+ &VarToUtf8
+};
+
+InterfaceProxy* CreateVarProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_Var_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPB_Var_Proxy::PPB_Var_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_Var_Proxy::~PPB_Var_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Var_Proxy::GetInfo() {
+ static const Info info = {
+ &var_interface,
+ PPB_VAR_INTERFACE,
+ INTERFACE_ID_PPB_VAR,
+ false,
+ &CreateVarProxy,
+ };
+ return &info;
+}
+
+bool PPB_Var_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ // All PPB_Var calls are handled locally; there is no need to send or receive
+ // messages here.
+ return false;
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_var_proxy.h b/ppapi/proxy/ppb_var_proxy.h
new file mode 100644
index 0000000..e527aab
--- /dev/null
+++ b/ppapi/proxy/ppb_var_proxy.h
@@ -0,0 +1,36 @@
+// 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_PPB_VAR_PROXY_H_
+#define PPAPI_PPB_VAR_PROXY_H_
+
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_Var;
+
+namespace pp {
+namespace proxy {
+
+class PPB_Var_Proxy : public InterfaceProxy {
+ public:
+ PPB_Var_Proxy(Dispatcher* dispatcher,
+ const void* target_interface);
+ virtual ~PPB_Var_Proxy();
+
+ static const Info* GetInfo();
+
+ const PPB_Var* ppb_var_target() const {
+ return static_cast<const PPB_Var*>(target_interface());
+ }
+
+ // InterfaceProxy implementation. In this case, no messages are sent or
+ // received, so this always returns false.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PPB_VAR_PROXY_H_
diff --git a/ppapi/proxy/ppp_class_proxy.cc b/ppapi/proxy/ppp_class_proxy.cc
new file mode 100644
index 0000000..0a020cc
--- /dev/null
+++ b/ppapi/proxy/ppp_class_proxy.cc
@@ -0,0 +1,298 @@
+// Copyright (c) 2010 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/ppp_class_proxy.h"
+
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/dev/ppp_class_deprecated.h"
+#include "ppapi/proxy/dispatcher.h"
+#include "ppapi/proxy/interface_id.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/serialized_var.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+// PPP_Class in the browser implementation -------------------------------------
+
+// Represents a plugin-implemented class in the browser process. This just
+// stores the data necessary to call back the plugin.
+struct ObjectProxy {
+ ObjectProxy(Dispatcher* d, int64 p, int64 ud)
+ : dispatcher(d),
+ ppp_class(p),
+ user_data(ud) {
+ }
+
+ Dispatcher* dispatcher;
+ int64 ppp_class;
+ int64 user_data;
+};
+
+ObjectProxy* ToObjectProxy(void* data) {
+ return reinterpret_cast<ObjectProxy*>(data);
+}
+
+bool HasProperty(void* object, PP_Var name, PP_Var* exception) {
+ ObjectProxy* obj = ToObjectProxy(object);
+ bool result = false;
+ ReceiveSerializedException se(obj->dispatcher, exception);
+ obj->dispatcher->Send(new PpapiMsg_PPPClass_HasProperty(
+ INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
+ SerializedVarSendInput(obj->dispatcher, name), &se, &result));
+ return result;
+}
+
+bool HasMethod(void* object, PP_Var name, PP_Var* exception) {
+ ObjectProxy* obj = ToObjectProxy(object);
+ bool result = false;
+ ReceiveSerializedException se(obj->dispatcher, exception);
+ obj->dispatcher->Send(new PpapiMsg_PPPClass_HasMethod(
+ INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
+ SerializedVarSendInput(obj->dispatcher, name), &se, &result));
+ return result;
+}
+
+PP_Var GetProperty(void* object,
+ PP_Var name,
+ PP_Var* exception) {
+ ObjectProxy* obj = ToObjectProxy(object);
+ ReceiveSerializedException se(obj->dispatcher, exception);
+ ReceiveSerializedVarReturnValue result;
+ obj->dispatcher->Send(new PpapiMsg_PPPClass_GetProperty(
+ INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
+ SerializedVarSendInput(obj->dispatcher, name), &se, &result));
+ return result.Return(obj->dispatcher);
+}
+
+void GetAllPropertyNames(void* object,
+ uint32_t* property_count,
+ PP_Var** properties,
+ PP_Var* exception) {
+ NOTIMPLEMENTED();
+ // TODO(brettw) implement this.
+}
+
+void SetProperty(void* object,
+ PP_Var name,
+ PP_Var value,
+ PP_Var* exception) {
+ ObjectProxy* obj = ToObjectProxy(object);
+ ReceiveSerializedException se(obj->dispatcher, exception);
+ obj->dispatcher->Send(new PpapiMsg_PPPClass_SetProperty(
+ INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
+ SerializedVarSendInput(obj->dispatcher, name),
+ SerializedVarSendInput(obj->dispatcher, value), &se));
+}
+
+void RemoveProperty(void* object,
+ PP_Var name,
+ PP_Var* exception) {
+ ObjectProxy* obj = ToObjectProxy(object);
+ ReceiveSerializedException se(obj->dispatcher, exception);
+ obj->dispatcher->Send(new PpapiMsg_PPPClass_RemoveProperty(
+ INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
+ SerializedVarSendInput(obj->dispatcher, name), &se));
+}
+
+PP_Var Call(void* object,
+ PP_Var method_name,
+ uint32_t argc,
+ PP_Var* argv,
+ PP_Var* exception) {
+ ObjectProxy* obj = ToObjectProxy(object);
+
+ ReceiveSerializedVarReturnValue result;
+ ReceiveSerializedException se(obj->dispatcher, exception);
+ std::vector<SerializedVar> argv_vect;
+ SerializedVarSendInput::ConvertVector(obj->dispatcher, argv, argc,
+ &argv_vect);
+
+ obj->dispatcher->Send(new PpapiMsg_PPPClass_Call(
+ INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
+ SerializedVarSendInput(obj->dispatcher, method_name), argv_vect,
+ &se, &result));
+ return result.Return(obj->dispatcher);
+}
+
+PP_Var Construct(void* object,
+ uint32_t argc,
+ PP_Var* argv,
+ PP_Var* exception) {
+ ObjectProxy* obj = ToObjectProxy(object);
+
+ ReceiveSerializedVarReturnValue result;
+ ReceiveSerializedException se(obj->dispatcher, exception);
+ std::vector<SerializedVar> argv_vect;
+ SerializedVarSendInput::ConvertVector(obj->dispatcher, argv, argc,
+ &argv_vect);
+
+ obj->dispatcher->Send(new PpapiMsg_PPPClass_Construct(
+ INTERFACE_ID_PPP_CLASS,
+ obj->ppp_class, obj->user_data, argv_vect, &se, &result));
+ return result.Return(obj->dispatcher);
+}
+
+void Deallocate(void* object) {
+ ObjectProxy* obj = ToObjectProxy(object);
+ obj->dispatcher->Send(new PpapiMsg_PPPClass_Deallocate(
+ INTERFACE_ID_PPP_CLASS, obj->ppp_class, obj->user_data));
+ delete obj;
+}
+
+const PPP_Class_Deprecated class_interface = {
+ &HasProperty,
+ &HasMethod,
+ &GetProperty,
+ &GetAllPropertyNames,
+ &SetProperty,
+ &RemoveProperty,
+ &Call,
+ &Construct,
+ &Deallocate
+};
+
+// Plugin helper functions -----------------------------------------------------
+
+// Converts an int64 object from IPC to a PPP_Class* for calling into the
+// plugin's implementation.
+const PPP_Class_Deprecated* ToPPPClass(int64 value) {
+ return reinterpret_cast<const PPP_Class_Deprecated*>(
+ static_cast<intptr_t>(value));
+}
+
+// Converts an int64 object from IPC to a void* for calling into the plugin's
+// implementation as the user data.
+void* ToUserData(int64 value) {
+ return reinterpret_cast<void*>(static_cast<intptr_t>(value));
+}
+
+} // namespace
+
+// PPP_Class_Proxy -------------------------------------------------------------
+
+PPP_Class_Proxy::PPP_Class_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher, NULL) {
+}
+
+PPP_Class_Proxy::~PPP_Class_Proxy() {
+}
+
+// static
+PP_Var PPP_Class_Proxy::CreateProxiedObject(const PPB_Var_Deprecated* var,
+ Dispatcher* dispatcher,
+ PP_Module module_id,
+ int64 ppp_class,
+ int64 class_data) {
+ ObjectProxy* object_proxy = new ObjectProxy(dispatcher,
+ ppp_class, class_data);
+ return var->CreateObject(module_id, &class_interface, object_proxy);
+}
+
+bool PPP_Class_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPP_Class_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_HasProperty,
+ OnMsgHasProperty)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_HasMethod,
+ OnMsgHasMethod)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_GetProperty,
+ OnMsgGetProperty)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_EnumerateProperties,
+ OnMsgEnumerateProperties)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_SetProperty,
+ OnMsgSetProperty)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_Call,
+ OnMsgCall)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_Construct,
+ OnMsgConstruct)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_Deallocate,
+ OnMsgDeallocate)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPP_Class_Proxy::OnMsgHasProperty(int64 ppp_class, int64 object,
+ SerializedVarReceiveInput property,
+ SerializedVarOutParam exception,
+ bool* result) {
+ *result = ToPPPClass(ppp_class)->HasProperty(ToUserData(object),
+ property.Get(dispatcher()), exception.OutParam(dispatcher()));
+}
+
+void PPP_Class_Proxy::OnMsgHasMethod(int64 ppp_class, int64 object,
+ SerializedVarReceiveInput property,
+ SerializedVarOutParam exception,
+ bool* result) {
+ *result = ToPPPClass(ppp_class)->HasMethod(ToUserData(object),
+ property.Get(dispatcher()), exception.OutParam(dispatcher()));
+}
+
+void PPP_Class_Proxy::OnMsgGetProperty(int64 ppp_class, int64 object,
+ SerializedVarReceiveInput property,
+ SerializedVarOutParam exception,
+ SerializedVarReturnValue result) {
+ result.Return(dispatcher(), ToPPPClass(ppp_class)->GetProperty(
+ ToUserData(object), property.Get(dispatcher()),
+ exception.OutParam(dispatcher())));
+}
+
+void PPP_Class_Proxy::OnMsgEnumerateProperties(
+ int64 ppp_class, int64 object,
+ std::vector<pp::proxy::SerializedVar>* props,
+ SerializedVarOutParam exception) {
+ NOTIMPLEMENTED();
+ // TODO(brettw) implement this.
+}
+
+void PPP_Class_Proxy::OnMsgSetProperty(int64 ppp_class, int64 object,
+ SerializedVarReceiveInput property,
+ SerializedVarReceiveInput value,
+ SerializedVarOutParam exception) {
+ ToPPPClass(ppp_class)->SetProperty(
+ ToUserData(object), property.Get(dispatcher()), value.Get(dispatcher()),
+ exception.OutParam(dispatcher()));
+}
+
+void PPP_Class_Proxy::OnMsgRemoveProperty(int64 ppp_class, int64 object,
+ SerializedVarReceiveInput property,
+ SerializedVarOutParam exception) {
+ ToPPPClass(ppp_class)->RemoveProperty(
+ ToUserData(object), property.Get(dispatcher()),
+ exception.OutParam(dispatcher()));
+}
+
+void PPP_Class_Proxy::OnMsgCall(
+ int64 ppp_class, int64 object,
+ SerializedVarReceiveInput method_name,
+ SerializedVarVectorReceiveInput arg_vector,
+ SerializedVarOutParam exception,
+ SerializedVarReturnValue result) {
+ uint32_t arg_count = 0;
+ PP_Var* args = arg_vector.Get(dispatcher(), &arg_count);
+ result.Return(dispatcher(), ToPPPClass(ppp_class)->Call(
+ ToUserData(object), method_name.Get(dispatcher()),
+ arg_count, args, exception.OutParam(dispatcher())));
+}
+
+void PPP_Class_Proxy::OnMsgConstruct(
+ int64 ppp_class, int64 object,
+ SerializedVarVectorReceiveInput arg_vector,
+ SerializedVarOutParam exception,
+ SerializedVarReturnValue result) {
+ uint32_t arg_count = 0;
+ PP_Var* args = arg_vector.Get(dispatcher(), &arg_count);
+ result.Return(dispatcher(), ToPPPClass(ppp_class)->Construct(
+ ToUserData(object), arg_count, args, exception.OutParam(dispatcher())));
+}
+
+void PPP_Class_Proxy::OnMsgDeallocate(int64 ppp_class, int64 object) {
+ ToPPPClass(ppp_class)->Deallocate(ToUserData(object));
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppp_class_proxy.h b/ppapi/proxy/ppp_class_proxy.h
new file mode 100644
index 0000000..2cba23d
--- /dev/null
+++ b/ppapi/proxy/ppp_class_proxy.h
@@ -0,0 +1,87 @@
+// Copyright (c) 2010 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_PPP_CLASS_PROXY_H_
+#define PPAPI_PROXY_PPP_CLASS_PROXY_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_Var_Deprecated;
+struct PPP_Class_Deprecated;
+
+namespace pp {
+namespace proxy {
+
+class SerializedVar;
+class SerializedVarReceiveInput;
+class SerializedVarVectorReceiveInput;
+class SerializedVarOutParam;
+class SerializedVarReturnValue;
+
+class PPP_Class_Proxy : public InterfaceProxy {
+ public:
+ // PPP_Class isn't a normal interface that you can query for, so this
+ // constructor doesn't take an interface pointer.
+ PPP_Class_Proxy(Dispatcher* dispatcher);
+ virtual ~PPP_Class_Proxy();
+
+ // Creates a proxied object in the browser process. This takes the browser's
+ // PPB_Var_Deprecated interface to use to create the object. The class and
+ static PP_Var CreateProxiedObject(const PPB_Var_Deprecated* var,
+ Dispatcher* dispatcher,
+ PP_Module module_id,
+ int64 ppp_class,
+ int64 class_data);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // IPC message handlers.
+ void OnMsgHasProperty(int64 ppp_class, int64 object,
+ SerializedVarReceiveInput property,
+ SerializedVarOutParam exception,
+ bool* result);
+ void OnMsgHasMethod(int64 ppp_class, int64 object,
+ SerializedVarReceiveInput property,
+ SerializedVarOutParam exception,
+ bool* result);
+ void OnMsgGetProperty(int64 ppp_class, int64 object,
+ SerializedVarReceiveInput property,
+ SerializedVarOutParam exception,
+ SerializedVarReturnValue result);
+ void OnMsgEnumerateProperties(
+ int64 ppp_class, int64 object,
+ std::vector<pp::proxy::SerializedVar>* props,
+ SerializedVarOutParam exception);
+ void OnMsgSetProperty(int64 ppp_class, int64 object,
+ SerializedVarReceiveInput property,
+ SerializedVarReceiveInput value,
+ SerializedVarOutParam exception);
+ void OnMsgRemoveProperty(int64 ppp_class, int64 object,
+ SerializedVarReceiveInput property,
+ SerializedVarOutParam exception);
+ void OnMsgCall(int64 ppp_class, int64 object,
+ SerializedVarReceiveInput method_name,
+ SerializedVarVectorReceiveInput arg_vector,
+ SerializedVarOutParam exception,
+ SerializedVarReturnValue result);
+ void OnMsgConstruct(int64 ppp_class, int64 object,
+ SerializedVarVectorReceiveInput arg_vector,
+ SerializedVarOutParam exception,
+ SerializedVarReturnValue result);
+ void OnMsgDeallocate(int64 ppp_class, int64 object);
+
+ DISALLOW_COPY_AND_ASSIGN(PPP_Class_Proxy);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPP_CLASS_PROXY_H_
diff --git a/ppapi/proxy/ppp_graphics_3d_proxy.cc b/ppapi/proxy/ppp_graphics_3d_proxy.cc
new file mode 100644
index 0000000..ef31e92b
--- /dev/null
+++ b/ppapi/proxy/ppp_graphics_3d_proxy.cc
@@ -0,0 +1,70 @@
+// 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/ppp_graphics_3d_proxy.h"
+
+#include "ppapi/c/dev/ppp_graphics_3d_dev.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+void ContextLost(PP_Instance instance) {
+ HostDispatcher::GetForInstance(instance)->Send(
+ new PpapiMsg_PPPGraphics3D_ContextLost(INTERFACE_ID_PPP_GRAPHICS_3D_DEV,
+ instance));
+}
+
+static const PPP_Graphics3D_Dev graphics_3d_interface = {
+ &ContextLost
+};
+
+InterfaceProxy* CreateGraphics3DProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPP_Graphics3D_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPP_Graphics3D_Proxy::PPP_Graphics3D_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPP_Graphics3D_Proxy::~PPP_Graphics3D_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPP_Graphics3D_Proxy::GetInfo() {
+ static const Info info = {
+ &graphics_3d_interface,
+ PPP_GRAPHICS_3D_DEV_INTERFACE,
+ INTERFACE_ID_PPP_GRAPHICS_3D_DEV,
+ false,
+ &CreateGraphics3DProxy,
+ };
+ return &info;
+}
+
+bool PPP_Graphics3D_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPP_Graphics3D_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPGraphics3D_ContextLost,
+ OnMsgContextLost)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPP_Graphics3D_Proxy::OnMsgContextLost(PP_Instance instance) {
+ if (ppp_graphics_3d_target())
+ ppp_graphics_3d_target()->Graphics3DContextLost(instance);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppp_graphics_3d_proxy.h b/ppapi/proxy/ppp_graphics_3d_proxy.h
new file mode 100644
index 0000000..41c400a
--- /dev/null
+++ b/ppapi/proxy/ppp_graphics_3d_proxy.h
@@ -0,0 +1,39 @@
+// 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_PPP_GRAPHICS_3D_PROXY_H_
+#define PPAPI_PROXY_PPP_GRAPHICS_3D_PROXY_H_
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPP_Graphics3D_Dev;
+
+namespace pp {
+namespace proxy {
+
+class PPP_Graphics3D_Proxy : public InterfaceProxy {
+ public:
+ PPP_Graphics3D_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPP_Graphics3D_Proxy();
+
+ static const Info* GetInfo();
+
+ const PPP_Graphics3D_Dev* ppp_graphics_3d_target() const {
+ return reinterpret_cast<const PPP_Graphics3D_Dev*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgContextLost(PP_Instance instance);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPP_GRAPHICS_3D_PROXY_H_
diff --git a/ppapi/proxy/ppp_input_event_proxy.cc b/ppapi/proxy/ppp_input_event_proxy.cc
new file mode 100644
index 0000000..1a1945d
--- /dev/null
+++ b/ppapi/proxy/ppp_input_event_proxy.cc
@@ -0,0 +1,115 @@
+// 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/ppp_input_event_proxy.h"
+
+#include <algorithm>
+
+#include "ppapi/c/ppp_input_event.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_input_event_proxy.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_input_event_api.h"
+
+using ppapi::InputEventData;
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_InputEvent_API;
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+PP_Bool HandleInputEvent(PP_Instance instance, PP_Resource input_event) {
+ EnterResourceNoLock<PPB_InputEvent_API> enter(input_event, false);
+ if (enter.failed()) {
+ NOTREACHED();
+ return PP_FALSE;
+ }
+ const InputEventData& data = enter.object()->GetInputEventData();
+ HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ if (!dispatcher) {
+ NOTREACHED();
+ return PP_FALSE;
+ }
+
+ // Need to send different messages depending on whether filtering is needed.
+ PP_Bool result = PP_FALSE;
+ if (data.is_filtered) {
+ dispatcher->Send(new PpapiMsg_PPPInputEvent_HandleFilteredInputEvent(
+ INTERFACE_ID_PPP_INPUT_EVENT, instance, data, &result));
+ } else {
+ dispatcher->Send(new PpapiMsg_PPPInputEvent_HandleInputEvent(
+ INTERFACE_ID_PPP_INPUT_EVENT, instance, data));
+ }
+ return result;
+}
+
+static const PPP_InputEvent input_event_interface = {
+ &HandleInputEvent
+};
+
+InterfaceProxy* CreateInputEventProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPP_InputEvent_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPP_InputEvent_Proxy::PPP_InputEvent_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPP_InputEvent_Proxy::~PPP_InputEvent_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPP_InputEvent_Proxy::GetInfo() {
+ static const Info info = {
+ &input_event_interface,
+ PPP_INPUT_EVENT_INTERFACE,
+ INTERFACE_ID_PPP_INPUT_EVENT,
+ false,
+ &CreateInputEventProxy,
+ };
+ return &info;
+}
+
+bool PPP_InputEvent_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPP_InputEvent_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInputEvent_HandleInputEvent,
+ OnMsgHandleInputEvent)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInputEvent_HandleFilteredInputEvent,
+ OnMsgHandleFilteredInputEvent)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPP_InputEvent_Proxy::OnMsgHandleInputEvent(PP_Instance instance,
+ const InputEventData& data) {
+ PP_Resource event_resource = PPB_InputEvent_Proxy::CreateProxyResource(
+ instance, data);
+ ppp_input_event_target()->HandleInputEvent(instance, event_resource);
+ PluginResourceTracker::GetInstance()->ReleaseResource(event_resource);
+}
+
+void PPP_InputEvent_Proxy::OnMsgHandleFilteredInputEvent(
+ PP_Instance instance,
+ const InputEventData& data,
+ PP_Bool* result) {
+ PP_Resource event_resource = PPB_InputEvent_Proxy::CreateProxyResource(
+ instance, data);
+ *result = ppp_input_event_target()->HandleInputEvent(instance,
+ event_resource);
+ PluginResourceTracker::GetInstance()->ReleaseResource(event_resource);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppp_input_event_proxy.h b/ppapi/proxy/ppp_input_event_proxy.h
new file mode 100644
index 0000000..b294aa5
--- /dev/null
+++ b/ppapi/proxy/ppp_input_event_proxy.h
@@ -0,0 +1,46 @@
+// 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_PPP_INPUT_EVENT_PROXY_H_
+#define PPAPI_PROXY_PPP_INPUT_EVENT_PROXY_H_
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPP_InputEvent;
+
+namespace ppapi {
+struct InputEventData;
+}
+
+namespace pp {
+namespace proxy {
+
+class PPP_InputEvent_Proxy : public InterfaceProxy {
+ public:
+ PPP_InputEvent_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPP_InputEvent_Proxy();
+
+ static const Info* GetInfo();
+
+ const PPP_InputEvent* ppp_input_event_target() const {
+ return static_cast<const PPP_InputEvent*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgHandleInputEvent(PP_Instance instance,
+ const ppapi::InputEventData& data);
+ void OnMsgHandleFilteredInputEvent(PP_Instance instance,
+ const ppapi::InputEventData& data,
+ PP_Bool* result);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPP_INPUT_EVENT_PROXY_H_
diff --git a/ppapi/proxy/ppp_instance_private_proxy.cc b/ppapi/proxy/ppp_instance_private_proxy.cc
new file mode 100644
index 0000000..20beb8a
--- /dev/null
+++ b/ppapi/proxy/ppp_instance_private_proxy.cc
@@ -0,0 +1,78 @@
+// 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/ppp_instance_private_proxy.h"
+
+#include <algorithm>
+
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/private/ppp_instance_private.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+PP_Var GetInstanceObject(PP_Instance instance) {
+ Dispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ ReceiveSerializedVarReturnValue result;
+ dispatcher->Send(new PpapiMsg_PPPInstancePrivate_GetInstanceObject(
+ INTERFACE_ID_PPP_INSTANCE_PRIVATE, instance, &result));
+ return result.Return(dispatcher);
+}
+
+static const PPP_Instance_Private instance_private_interface = {
+ &GetInstanceObject
+};
+
+InterfaceProxy* CreateInstancePrivateProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPP_Instance_Private_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
+PPP_Instance_Private_Proxy::PPP_Instance_Private_Proxy(
+ Dispatcher* dispatcher, const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPP_Instance_Private_Proxy::~PPP_Instance_Private_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPP_Instance_Private_Proxy::GetInfo() {
+ static const Info info = {
+ &instance_private_interface,
+ PPP_INSTANCE_PRIVATE_INTERFACE,
+ INTERFACE_ID_PPP_INSTANCE_PRIVATE,
+ false,
+ &CreateInstancePrivateProxy,
+ };
+ return &info;
+}
+
+bool PPP_Instance_Private_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPP_Instance_Private_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstancePrivate_GetInstanceObject,
+ OnMsgGetInstanceObject)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPP_Instance_Private_Proxy::OnMsgGetInstanceObject(
+ PP_Instance instance,
+ SerializedVarReturnValue result) {
+ result.Return(dispatcher(),
+ ppp_instance_private_target()->GetInstanceObject(instance));
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppp_instance_private_proxy.h b/ppapi/proxy/ppp_instance_private_proxy.h
new file mode 100644
index 0000000..1df2e44
--- /dev/null
+++ b/ppapi/proxy/ppp_instance_private_proxy.h
@@ -0,0 +1,45 @@
+// 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_PPP_INSTANCE_PRIVATE_PROXY_H_
+#define PPAPI_PROXY_PPP_INSTANCE_PRIVATE_PROXY_H_
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPP_Instance_Private;
+
+namespace pp {
+namespace proxy {
+
+class SerializedVarReturnValue;
+
+class PPP_Instance_Private_Proxy : public InterfaceProxy {
+ public:
+ PPP_Instance_Private_Proxy(Dispatcher* dispatcher,
+ const void* target_interface);
+ virtual ~PPP_Instance_Private_Proxy();
+
+ static const Info* GetInfo();
+
+ const PPP_Instance_Private* ppp_instance_private_target() const {
+ return reinterpret_cast<const PPP_Instance_Private*>(target_interface());
+ }
+
+ private:
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ // Message handlers.
+ void OnMsgGetInstanceObject(PP_Instance instance,
+ SerializedVarReturnValue result);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPP_INSTANCE_PRIVATE_PROXY_H_
diff --git a/ppapi/proxy/ppp_instance_proxy.cc b/ppapi/proxy/ppp_instance_proxy.cc
new file mode 100644
index 0000000..99dcaab
--- /dev/null
+++ b/ppapi/proxy/ppp_instance_proxy.cc
@@ -0,0 +1,250 @@
+// 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/ppp_instance_proxy.h"
+
+#include <algorithm>
+
+#include "ppapi/c/dev/ppb_fullscreen_dev.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/c/ppp_instance.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_url_loader_proxy.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+PP_Bool DidCreate(PP_Instance instance,
+ uint32_t argc,
+ const char* argn[],
+ const char* argv[]) {
+ std::vector<std::string> argn_vect;
+ std::vector<std::string> argv_vect;
+ for (uint32_t i = 0; i < argc; i++) {
+ argn_vect.push_back(std::string(argn[i]));
+ argv_vect.push_back(std::string(argv[i]));
+ }
+
+ PP_Bool result = PP_FALSE;
+ HostDispatcher::GetForInstance(instance)->Send(
+ new PpapiMsg_PPPInstance_DidCreate(INTERFACE_ID_PPP_INSTANCE, instance,
+ argn_vect, argv_vect, &result));
+ return result;
+}
+
+void DidDestroy(PP_Instance instance) {
+ HostDispatcher::GetForInstance(instance)->Send(
+ new PpapiMsg_PPPInstance_DidDestroy(INTERFACE_ID_PPP_INSTANCE, instance));
+}
+
+void DidChangeView(PP_Instance instance,
+ const PP_Rect* position,
+ const PP_Rect* clip) {
+ HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ const PPB_Fullscreen_Dev* fullscreen_interface =
+ static_cast<const PPB_Fullscreen_Dev*>(
+ dispatcher->GetLocalInterface(PPB_FULLSCREEN_DEV_INTERFACE));
+ DCHECK(fullscreen_interface);
+ PP_Bool fullscreen = fullscreen_interface->IsFullscreen(instance);
+ dispatcher->Send(
+ new PpapiMsg_PPPInstance_DidChangeView(INTERFACE_ID_PPP_INSTANCE,
+ instance, *position, *clip,
+ fullscreen));
+}
+
+void DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {
+ HostDispatcher::GetForInstance(instance)->Send(
+ new PpapiMsg_PPPInstance_DidChangeFocus(INTERFACE_ID_PPP_INSTANCE,
+ instance, has_focus));
+}
+
+PP_Bool HandleInputEvent(PP_Instance instance,
+ const PP_InputEvent* event) {
+ PP_Bool result = PP_FALSE;
+ IPC::Message* msg = new PpapiMsg_PPPInstance_HandleInputEvent(
+ INTERFACE_ID_PPP_INSTANCE, instance, *event, &result);
+ // Make this message not unblock, to avoid re-entrancy problems when the
+ // plugin does a synchronous call to the renderer. This will force any
+ // synchronous calls from the plugin to complete before processing this
+ // message. We avoid deadlock by never un-setting the unblock flag on messages
+ // from the plugin to the renderer.
+ msg->set_unblock(false);
+ HostDispatcher::GetForInstance(instance)->Send(msg);
+ return result;
+}
+
+PP_Bool HandleDocumentLoad(PP_Instance instance,
+ PP_Resource url_loader) {
+ PP_Bool result = PP_FALSE;
+ HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+
+ // Set up the URLLoader for proxying.
+
+ PPB_URLLoader_Proxy* url_loader_proxy = static_cast<PPB_URLLoader_Proxy*>(
+ dispatcher->GetOrCreatePPBInterfaceProxy(INTERFACE_ID_PPB_URL_LOADER));
+ url_loader_proxy->PrepareURLLoaderForSendingToPlugin(url_loader);
+
+ // PluginResourceTracker in the plugin process assumes that resources that it
+ // tracks have been addrefed on behalf of the plugin at the renderer side. So
+ // we explicitly do it for |url_loader| here.
+ //
+ // Please also see comments in PPP_Instance_Proxy::OnMsgHandleDocumentLoad()
+ // about releasing of this extra reference.
+ const PPB_Core* core = reinterpret_cast<const PPB_Core*>(
+ dispatcher->GetLocalInterface(PPB_CORE_INTERFACE));
+ if (!core) {
+ NOTREACHED();
+ return PP_FALSE;
+ }
+ core->AddRefResource(url_loader);
+
+ HostResource serialized_loader;
+ serialized_loader.SetHostResource(instance, url_loader);
+ dispatcher->Send(new PpapiMsg_PPPInstance_HandleDocumentLoad(
+ INTERFACE_ID_PPP_INSTANCE, instance, serialized_loader, &result));
+ return result;
+}
+
+static const PPP_Instance_0_5 instance_interface_0_5 = {
+ &DidCreate,
+ &DidDestroy,
+ &DidChangeView,
+ &DidChangeFocus,
+ &HandleInputEvent,
+ &HandleDocumentLoad
+};
+
+template <class PPP_Instance_Type>
+InterfaceProxy* CreateInstanceProxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPP_Instance_Proxy(
+ dispatcher,
+ static_cast<const PPP_Instance_Type*>(target_interface));
+}
+
+} // namespace
+
+PPP_Instance_Proxy::~PPP_Instance_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPP_Instance_Proxy::GetInfo0_5() {
+ static const Info info = {
+ &instance_interface_0_5,
+ PPP_INSTANCE_INTERFACE_0_5,
+ INTERFACE_ID_PPP_INSTANCE,
+ false,
+ &CreateInstanceProxy<PPP_Instance_0_5>,
+ };
+ return &info;
+}
+
+bool PPP_Instance_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPP_Instance_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidCreate,
+ OnMsgDidCreate)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidDestroy,
+ OnMsgDidDestroy)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeView,
+ OnMsgDidChangeView)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeFocus,
+ OnMsgDidChangeFocus)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_HandleInputEvent,
+ OnMsgHandleInputEvent)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_HandleDocumentLoad,
+ OnMsgHandleDocumentLoad)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPP_Instance_Proxy::OnMsgDidCreate(
+ PP_Instance instance,
+ const std::vector<std::string>& argn,
+ const std::vector<std::string>& argv,
+ PP_Bool* result) {
+ *result = PP_FALSE;
+ if (argn.size() != argv.size())
+ return;
+
+ // Set up the routing associating this new instance with the dispatcher we
+ // just got the message from. This must be done before calling into the
+ // plugin so it can in turn call PPAPI functions.
+ PluginDispatcher* plugin_dispatcher =
+ static_cast<PluginDispatcher*>(dispatcher());
+ plugin_dispatcher->DidCreateInstance(instance);
+
+ // Make sure the arrays always have at least one element so we can take the
+ // address below.
+ std::vector<const char*> argn_array(
+ std::max(static_cast<size_t>(1), argn.size()));
+ std::vector<const char*> argv_array(
+ std::max(static_cast<size_t>(1), argn.size()));
+ for (size_t i = 0; i < argn.size(); i++) {
+ argn_array[i] = argn[i].c_str();
+ argv_array[i] = argv[i].c_str();
+ }
+
+ DCHECK(combined_interface_.get());
+ *result = combined_interface_->DidCreate(instance,
+ static_cast<uint32_t>(argn.size()),
+ &argn_array[0], &argv_array[0]);
+}
+
+void PPP_Instance_Proxy::OnMsgDidDestroy(PP_Instance instance) {
+ combined_interface_->DidDestroy(instance);
+ static_cast<PluginDispatcher*>(dispatcher())->DidDestroyInstance(instance);
+}
+
+void PPP_Instance_Proxy::OnMsgDidChangeView(PP_Instance instance,
+ const PP_Rect& position,
+ const PP_Rect& clip,
+ PP_Bool fullscreen) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return;
+ InstanceData* data = dispatcher->GetInstanceData(instance);
+ if (!data)
+ return;
+ data->position = position;
+ data->fullscreen = fullscreen;
+ combined_interface_->DidChangeView(instance, &position, &clip);
+}
+
+void PPP_Instance_Proxy::OnMsgDidChangeFocus(PP_Instance instance,
+ PP_Bool has_focus) {
+ combined_interface_->DidChangeFocus(instance, has_focus);
+}
+
+void PPP_Instance_Proxy::OnMsgHandleInputEvent(PP_Instance instance,
+ const PP_InputEvent& event,
+ PP_Bool* result) {
+ *result = combined_interface_->HandleInputEvent(instance, &event);
+}
+
+void PPP_Instance_Proxy::OnMsgHandleDocumentLoad(PP_Instance instance,
+ const HostResource& url_loader,
+ PP_Bool* result) {
+ PP_Resource plugin_loader =
+ PPB_URLLoader_Proxy::TrackPluginResource(url_loader);
+ *result = combined_interface_->HandleDocumentLoad(instance, plugin_loader);
+
+ // This balances the one reference that TrackPluginResource() initialized it
+ // with. The plugin will normally take an additional reference which will keep
+ // the resource alive in the plugin (and the one reference in the renderer
+ // representing all plugin references).
+ // Once all references at the plugin side are released, the renderer side will
+ // be notified and release the reference added in HandleDocumentLoad() above.
+ PluginResourceTracker::GetInstance()->ReleaseResource(plugin_loader);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppp_instance_proxy.h b/ppapi/proxy/ppp_instance_proxy.h
new file mode 100644
index 0000000..9448332
--- /dev/null
+++ b/ppapi/proxy/ppp_instance_proxy.h
@@ -0,0 +1,72 @@
+// 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_PPP_INSTANCE_PROXY_H_
+#define PPAPI_PROXY_PPP_INSTANCE_PROXY_H_
+
+#include <string>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/shared_impl/ppp_instance_combined.h"
+
+struct PP_InputEvent;
+struct PP_Rect;
+
+namespace pp {
+namespace proxy {
+
+class SerializedVarReturnValue;
+
+class PPP_Instance_Proxy : public InterfaceProxy {
+ public:
+ template <class PPP_Instance_Type>
+ PPP_Instance_Proxy(Dispatcher* dispatcher,
+ const PPP_Instance_Type* target_interface)
+ : InterfaceProxy(dispatcher, static_cast<const void*>(target_interface)),
+ combined_interface_(
+ new ::ppapi::PPP_Instance_Combined(*target_interface)) {
+ }
+ virtual ~PPP_Instance_Proxy();
+
+ // Return the info for the 0.5 (latest, canonical) version of the interface.
+ static const Info* GetInfo0_5();
+
+ ::ppapi::PPP_Instance_Combined* ppp_instance_target() const {
+ return combined_interface_.get();
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgDidCreate(PP_Instance instance,
+ const std::vector<std::string>& argn,
+ const std::vector<std::string>& argv,
+ PP_Bool* result);
+ void OnMsgDidDestroy(PP_Instance instance);
+ void OnMsgDidChangeView(PP_Instance instance,
+ const PP_Rect& position,
+ const PP_Rect& clip,
+ PP_Bool fullscreen);
+ void OnMsgDidChangeFocus(PP_Instance instance, PP_Bool has_focus);
+ void OnMsgHandleInputEvent(PP_Instance instance,
+ const PP_InputEvent& event,
+ PP_Bool* result);
+ void OnMsgHandleDocumentLoad(PP_Instance instance,
+ const HostResource& url_loader,
+ PP_Bool* result);
+ scoped_ptr< ::ppapi::PPP_Instance_Combined> combined_interface_;
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPP_INSTANCE_PROXY_H_
diff --git a/ppapi/proxy/ppp_instance_proxy_test.cc b/ppapi/proxy/ppp_instance_proxy_test.cc
new file mode 100644
index 0000000..00d776b
--- /dev/null
+++ b/ppapi/proxy/ppp_instance_proxy_test.cc
@@ -0,0 +1,208 @@
+// 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 "base/synchronization/waitable_event.h"
+#include "ipc/ipc_message_utils.h"
+#include "ppapi/c/dev/ppb_fullscreen_dev.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/c/ppb_url_loader.h"
+#include "ppapi/c/ppp_instance.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+// This is a poor man's mock of PPP_Instance using global variables. Eventually
+// we should generalize making PPAPI interface mocks by using IDL or macro/
+// template magic.
+PP_Instance received_instance;
+uint32_t received_argc;
+std::vector<std::string> received_argn;
+std::vector<std::string> received_argv;
+PP_Bool bool_to_return;
+PP_Bool DidCreate(PP_Instance instance, uint32_t argc, const char* argn[],
+ const char* argv[]) {
+ received_instance = instance;
+ received_argc = argc;
+ received_argn.clear();
+ received_argn.insert(received_argn.begin(), argn, argn + argc);
+ received_argv.clear();
+ received_argv.insert(received_argv.begin(), argv, argv + argc);
+ return bool_to_return;
+}
+
+void DidDestroy(PP_Instance instance) {
+ received_instance = instance;
+}
+
+PP_Rect received_position;
+PP_Rect received_clip;
+// DidChangeView is asynchronous. We wait until the call has completed before
+// proceeding on to the next test.
+base::WaitableEvent did_change_view_called(false, false);
+void DidChangeView(PP_Instance instance, const PP_Rect* position,
+ const PP_Rect* clip) {
+ received_instance = instance;
+ received_position = *position;
+ received_clip = *clip;
+ did_change_view_called.Signal();
+}
+
+PP_Bool received_has_focus;
+base::WaitableEvent did_change_focus_called(false, false);
+void DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {
+ received_instance = instance;
+ received_has_focus = has_focus;
+ did_change_focus_called.Signal();
+}
+
+PP_InputEvent received_event;
+PP_Bool HandleInputEvent(PP_Instance instance, const PP_InputEvent* event) {
+ received_instance = instance;
+ memcpy(&received_event, event, sizeof(*event));;
+ return bool_to_return;
+}
+
+PP_Bool HandleDocumentLoad(PP_Instance instance, PP_Resource url_loader) {
+ // This one requires use of the PPB_URLLoader proxy and PPB_Core, plus a
+ // resource tracker for the url_loader resource.
+ // TODO(dmichael): Mock those out and test this function.
+ NOTREACHED();
+ return PP_FALSE;
+}
+
+PP_Var var_to_return;
+PP_Var GetInstanceObject(PP_Instance instance) {
+ received_instance = instance;
+ return var_to_return;
+}
+
+// Clear all the 'received' values for our mock. Call this before you expect
+// one of the functions to be invoked. TODO(dmichael): It would be better to
+// have a flag also for each function, so we know the right one got called.
+void ResetReceived() {
+ received_instance = 0;
+ received_argc = 0;
+ received_argn.clear();
+ received_argv.clear();
+ memset(&received_position, 0, sizeof(received_position));
+ memset(&received_clip, 0, sizeof(received_clip));
+ received_has_focus = PP_FALSE;
+ memset(&received_event, 0, sizeof(received_event));
+}
+
+PPP_Instance_0_5 ppp_instance_0_5 = {
+ &DidCreate,
+ &DidDestroy,
+ &DidChangeView,
+ &DidChangeFocus,
+ &HandleInputEvent,
+ &HandleDocumentLoad
+};
+
+// PPP_Instance_Proxy::DidChangeView relies on PPB_FullscreenDev being
+// available with a valid implementation of IsFullScreen, so we mock it.
+PP_Bool IsFullscreen(PP_Instance instance) {
+ return PP_FALSE;
+}
+PPB_Fullscreen_Dev ppb_fullscreen_dev = { &IsFullscreen };
+
+} // namespace
+
+class PPP_Instance_ProxyTest : public TwoWayTest {
+ public:
+ PPP_Instance_ProxyTest()
+ : TwoWayTest(TwoWayTest::TEST_PPP_INTERFACE) {
+ }
+};
+
+TEST_F(PPP_Instance_ProxyTest, PPPInstance0_5) {
+ plugin().RegisterTestInterface(PPP_INSTANCE_INTERFACE_0_5, &ppp_instance_0_5);
+ host().RegisterTestInterface(PPB_FULLSCREEN_DEV_INTERFACE,
+ &ppb_fullscreen_dev);
+
+ // Grab the host-side proxy for the 0.5 interface.
+ const PPP_Instance_0_5* ppp_instance = static_cast<const PPP_Instance_0_5*>(
+ host().host_dispatcher()->GetProxiedInterface(
+ PPP_INSTANCE_INTERFACE_0_5));
+
+ // Call each function in turn, make sure we get the expected values and
+ // returns.
+ //
+ // We don't test DidDestroy, because it has the side-effect of removing the
+ // PP_Instance from the PluginDispatcher, which will cause a failure later
+ // when the test is torn down.
+ PP_Instance expected_instance = pp_instance();
+ std::vector<std::string> expected_argn, expected_argv;
+ expected_argn.push_back("Hello");
+ expected_argn.push_back("world.");
+ expected_argv.push_back("elloHay");
+ expected_argv.push_back("orldway.");
+ std::vector<const char*> argn_to_pass, argv_to_pass;
+ CHECK(expected_argn.size() == expected_argv.size());
+ for (size_t i = 0; i < expected_argn.size(); ++i) {
+ argn_to_pass.push_back(expected_argn[i].c_str());
+ argv_to_pass.push_back(expected_argv[i].c_str());
+ }
+ uint32_t expected_argc = expected_argn.size();
+ bool_to_return = PP_TRUE;
+ ResetReceived();
+ EXPECT_EQ(bool_to_return, ppp_instance->DidCreate(expected_instance,
+ expected_argc,
+ &argn_to_pass[0],
+ &argv_to_pass[0]));
+ EXPECT_EQ(received_instance, expected_instance);
+ EXPECT_EQ(received_argc, expected_argc);
+ EXPECT_EQ(received_argn, expected_argn);
+ EXPECT_EQ(received_argv, expected_argv);
+
+ PP_Rect expected_position = { {1, 2}, {3, 4} };
+ PP_Rect expected_clip = { {5, 6}, {7, 8} };
+ ResetReceived();
+ ppp_instance->DidChangeView(expected_instance, &expected_position,
+ &expected_clip);
+ did_change_view_called.Wait();
+ EXPECT_EQ(received_instance, expected_instance);
+ EXPECT_EQ(received_position.point.x, expected_position.point.x);
+ EXPECT_EQ(received_position.point.y, expected_position.point.y);
+ EXPECT_EQ(received_position.size.width, expected_position.size.width);
+ EXPECT_EQ(received_position.size.height, expected_position.size.height);
+ EXPECT_EQ(received_clip.point.x, expected_clip.point.x);
+ EXPECT_EQ(received_clip.point.y, expected_clip.point.y);
+ EXPECT_EQ(received_clip.size.width, expected_clip.size.width);
+ EXPECT_EQ(received_clip.size.height, expected_clip.size.height);
+
+ PP_Bool expected_has_focus = PP_TRUE;
+ ResetReceived();
+ ppp_instance->DidChangeFocus(expected_instance, expected_has_focus);
+ did_change_focus_called.Wait();
+ EXPECT_EQ(received_instance, expected_instance);
+ EXPECT_EQ(received_has_focus, expected_has_focus);
+
+ PP_InputEvent expected_event = { PP_INPUTEVENT_TYPE_KEYDOWN, // type
+ 0, // padding
+ 1.0, // time_stamp
+ { { 2, 3 } } }; // u (as PP_InputEvent_Key)
+ ResetReceived();
+ EXPECT_EQ(bool_to_return,
+ ppp_instance->HandleInputEvent(expected_instance, &expected_event));
+ EXPECT_EQ(received_instance, expected_instance);
+ ASSERT_EQ(received_event.type, expected_event.type);
+ // Ignore padding; it's okay if it's not serialized.
+ EXPECT_EQ(received_event.time_stamp, expected_event.time_stamp);
+ EXPECT_EQ(received_event.u.key.modifier, expected_event.u.key.modifier);
+ EXPECT_EQ(received_event.u.key.key_code, expected_event.u.key.key_code);
+
+ // TODO(dmichael): Need to mock out a resource Tracker to be able to test
+ // HandleResourceLoad. It also requires
+ // PPB_Core.AddRefResource and for PPB_URLLoader to be
+ // registered.
+}
+
+} // namespace proxy
+} // namespace pp
+
diff --git a/ppapi/proxy/proxy_channel.cc b/ppapi/proxy/proxy_channel.cc
new file mode 100644
index 0000000..d304dca
--- /dev/null
+++ b/ppapi/proxy/proxy_channel.cc
@@ -0,0 +1,69 @@
+// 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/proxy_channel.h"
+
+#include "ipc/ipc_platform_file.h"
+#include "ipc/ipc_test_sink.h"
+
+namespace pp {
+namespace proxy {
+
+ProxyChannel::ProxyChannel(base::ProcessHandle remote_process_handle)
+ : delegate_(NULL),
+ remote_process_handle_(remote_process_handle),
+ test_sink_(NULL) {
+}
+
+ProxyChannel::~ProxyChannel() {
+}
+
+bool ProxyChannel::InitWithChannel(Delegate* delegate,
+ const IPC::ChannelHandle& channel_handle,
+ bool is_client) {
+ delegate_ = delegate;
+ IPC::Channel::Mode mode = is_client ? IPC::Channel::MODE_CLIENT
+ : IPC::Channel::MODE_SERVER;
+ channel_.reset(new IPC::SyncChannel(channel_handle, mode, this,
+ delegate->GetIPCMessageLoop(), false,
+ delegate->GetShutdownEvent()));
+ return true;
+}
+
+void ProxyChannel::InitWithTestSink(IPC::TestSink* test_sink) {
+ DCHECK(!test_sink_);
+ test_sink_ = test_sink;
+}
+
+void ProxyChannel::OnChannelError() {
+ channel_.reset();
+}
+
+#if defined(OS_POSIX)
+int ProxyChannel::GetRendererFD() {
+ DCHECK(channel());
+ return channel()->GetClientFileDescriptor();
+}
+#endif
+
+IPC::PlatformFileForTransit ProxyChannel::ShareHandleWithRemote(
+ base::PlatformFile handle,
+ bool should_close_source) {
+ return IPC::GetFileHandleForProcess(handle, remote_process_handle_,
+ should_close_source);
+}
+
+bool ProxyChannel::Send(IPC::Message* msg) {
+ if (test_sink_)
+ return test_sink_->Send(msg);
+ if (channel_.get())
+ return channel_->Send(msg);
+
+ // Remote side crashed, drop this message.
+ delete msg;
+ return false;
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/proxy_channel.h b/ppapi/proxy/proxy_channel.h
new file mode 100644
index 0000000..3dbb977
--- /dev/null
+++ b/ppapi/proxy/proxy_channel.h
@@ -0,0 +1,110 @@
+// 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_PROXY_CHANNEL_H_
+#define PPAPI_PROXY_PROXY_CHANNEL_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/process.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_platform_file.h"
+#include "ipc/ipc_sync_channel.h"
+
+namespace base {
+class MessageLoopProxy;
+class WaitableEvent;
+}
+
+namespace IPC {
+class TestSink;
+}
+
+namespace pp {
+namespace proxy {
+
+class VarSerializationRules;
+
+class ProxyChannel : public IPC::Channel::Listener,
+ public IPC::Message::Sender {
+ public:
+ typedef void (*ShutdownModuleFunc)();
+
+ class Delegate {
+ public:
+ // Returns the dedicated message loop for processing IPC requests.
+ virtual base::MessageLoopProxy* GetIPCMessageLoop() = 0;
+
+ // Returns the event object that becomes signalled when the main thread's
+ // message loop exits.
+ virtual base::WaitableEvent* GetShutdownEvent() = 0;
+ };
+
+ virtual ~ProxyChannel();
+
+ // Alternative to InitWithChannel() for unit tests that want to send all
+ // messages sent via this channel to the given test sink. The test sink
+ // must outlive this class.
+ void InitWithTestSink(IPC::TestSink* test_sink);
+
+ // Shares a file handle (HANDLE / file descriptor) with the remote side. It
+ // returns a handle that should be sent in exactly one IPC message. Upon
+ // receipt, the remote side then owns that handle. Note: if sending the
+ // message fails, the returned handle is properly closed by the IPC system. If
+ // should_close_source is set to true, the original handle is closed by this
+ // operation and should not be used again.
+ IPC::PlatformFileForTransit ShareHandleWithRemote(
+ base::PlatformFile handle,
+ bool should_close_source);
+
+ // IPC::Message::Sender implementation.
+ virtual bool Send(IPC::Message* msg);
+
+ // IPC::Channel::Listener implementation.
+ virtual void OnChannelError();
+
+ // Will be NULL in some unit tests and if the remote side has crashed.
+ IPC::SyncChannel* channel() const {
+ return channel_.get();
+ }
+
+#if defined(OS_POSIX)
+ int GetRendererFD();
+#endif
+
+ protected:
+ ProxyChannel(base::ProcessHandle remote_process_handle);
+
+ // You must call this function before anything else. Returns true on success.
+ // The delegate pointer must outlive this class, ownership is not
+ // transferred.
+ virtual bool InitWithChannel(Delegate* delegate,
+ const IPC::ChannelHandle& channel_handle,
+ bool is_client);
+
+ ProxyChannel::Delegate* delegate() const {
+ return delegate_;
+ }
+
+ private:
+ // Non-owning pointer. Guaranteed non-NULL after init is called.
+ ProxyChannel::Delegate* delegate_;
+
+ base::ProcessHandle remote_process_handle_; // See getter above.
+
+ // When we're unit testing, this will indicate the sink for the messages to
+ // be deposited so they can be inspected by the test. When non-NULL, this
+ // indicates that the channel should not be used.
+ IPC::TestSink* test_sink_;
+
+ // Will be null for some tests when there is a test_sink_, and if the
+ // remote side has crashed.
+ scoped_ptr<IPC::SyncChannel> channel_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProxyChannel);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PROXY_CHANNEL_H_
diff --git a/ppapi/proxy/proxy_module.cc b/ppapi/proxy/proxy_module.cc
new file mode 100644
index 0000000..94de0c1
--- /dev/null
+++ b/ppapi/proxy/proxy_module.cc
@@ -0,0 +1,32 @@
+// 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/proxy_module.h"
+
+#include "base/memory/singleton.h"
+
+namespace pp {
+namespace proxy {
+
+ProxyModule::ProxyModule() {
+}
+
+ProxyModule::~ProxyModule() {
+}
+
+// static
+ProxyModule* ProxyModule::GetInstance() {
+ return Singleton<ProxyModule>::get();
+}
+
+const std::string& ProxyModule::GetFlashCommandLineArgs() {
+ return flash_command_line_args_;
+}
+
+void ProxyModule::SetFlashCommandLineArgs(const std::string& args) {
+ flash_command_line_args_ = args;
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/proxy_module.h b/ppapi/proxy/proxy_module.h
new file mode 100644
index 0000000..304f24f
--- /dev/null
+++ b/ppapi/proxy/proxy_module.h
@@ -0,0 +1,45 @@
+// 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_PROXY_MODULE_H_
+#define PPAPI_PROXY_PROXY_MODULE_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+
+template<typename T> struct DefaultSingletonTraits;
+
+namespace pp {
+namespace proxy {
+
+class PluginDispatcher;
+class PluginResource;
+
+class ProxyModule {
+ public:
+ // The global singleton getter.
+ static ProxyModule* GetInstance();
+
+ // TODO(viettrungluu): Generalize this for use with other plugins if it proves
+ // necessary. (Currently, we can't do this easily, since we can't tell from
+ // |PpapiPluginMain()| which plugin will be loaded.)
+ const std::string& GetFlashCommandLineArgs();
+ void SetFlashCommandLineArgs(const std::string& args);
+
+ private:
+ friend struct DefaultSingletonTraits<ProxyModule>;
+
+ std::string flash_command_line_args_;
+
+ ProxyModule();
+ ~ProxyModule();
+
+ DISALLOW_COPY_AND_ASSIGN(ProxyModule);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PROXY_MODULE_H_
diff --git a/ppapi/proxy/proxy_non_thread_safe_ref_count.h b/ppapi/proxy/proxy_non_thread_safe_ref_count.h
new file mode 100644
index 0000000..cfcb720
--- /dev/null
+++ b/ppapi/proxy/proxy_non_thread_safe_ref_count.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2010 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_NON_THREAD_SAFE_REF_COUNT_H_
+#define PPAPI_PROXY_PROXY_NON_THREAD_SAFE_REF_COUNT_H_
+
+#include "base/message_loop.h"
+#include "ppapi/cpp/completion_callback.h"
+
+namespace pp {
+namespace proxy {
+
+// This class is just like ppapi/cpp/non_thread_safe_ref_count.h but rather
+// than using pp::Module::core (which doesn't exist), it uses Chrome threads
+// which do.
+class ProxyNonThreadSafeRefCount {
+ public:
+ ProxyNonThreadSafeRefCount() : ref_(0) {
+#ifndef NDEBUG
+ message_loop_ = MessageLoop::current();
+#endif
+ }
+
+ ~ProxyNonThreadSafeRefCount() {
+ PP_DCHECK(message_loop_ == MessageLoop::current());
+ }
+
+ int32_t AddRef() {
+ PP_DCHECK(message_loop_ == MessageLoop::current());
+ return ++ref_;
+ }
+
+ int32_t Release() {
+ PP_DCHECK(message_loop_ == MessageLoop::current());
+ return --ref_;
+ }
+
+ private:
+ int32_t ref_;
+#ifndef NDEBUG
+ MessageLoop* message_loop_;
+#endif
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PROXY_NON_THREAD_SAFE_REF_COUNT_H_
diff --git a/ppapi/proxy/resource_creation_proxy.cc b/ppapi/proxy/resource_creation_proxy.cc
new file mode 100644
index 0000000..20e6735
--- /dev/null
+++ b/ppapi/proxy/resource_creation_proxy.cc
@@ -0,0 +1,316 @@
+// 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/resource_creation_proxy.h"
+
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_size.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/proxy/interface_id.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/c/trusted/ppb_image_data_trusted.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_audio_config_proxy.h"
+#include "ppapi/proxy/ppb_audio_proxy.h"
+#include "ppapi/proxy/ppb_buffer_proxy.h"
+#include "ppapi/proxy/ppb_broker_proxy.h"
+#include "ppapi/proxy/ppb_context_3d_proxy.h"
+#include "ppapi/proxy/ppb_file_chooser_proxy.h"
+#include "ppapi/proxy/ppb_file_ref_proxy.h"
+#include "ppapi/proxy/ppb_file_system_proxy.h"
+#include "ppapi/proxy/ppb_flash_menu_proxy.h"
+#include "ppapi/proxy/ppb_flash_net_connector_proxy.h"
+#include "ppapi/proxy/ppb_flash_tcp_socket_proxy.h"
+#include "ppapi/proxy/ppb_font_proxy.h"
+#include "ppapi/proxy/ppb_graphics_2d_proxy.h"
+#include "ppapi/proxy/ppb_image_data_proxy.h"
+#include "ppapi/proxy/ppb_surface_3d_proxy.h"
+#include "ppapi/proxy/ppb_url_loader_proxy.h"
+#include "ppapi/proxy/ppb_url_request_info_proxy.h"
+#include "ppapi/shared_impl/font_impl.h"
+#include "ppapi/shared_impl/function_group_base.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_image_data_api.h"
+
+using ppapi::thunk::ResourceCreationAPI;
+
+namespace pp {
+namespace proxy {
+
+ResourceCreationProxy::ResourceCreationProxy(Dispatcher* dispatcher)
+ : dispatcher_(dispatcher) {
+}
+
+ResourceCreationProxy::~ResourceCreationProxy() {
+}
+
+ResourceCreationAPI* ResourceCreationProxy::AsResourceCreationAPI() {
+ return this;
+}
+
+PP_Resource ResourceCreationProxy::CreateAudio(
+ PP_Instance instance,
+ PP_Resource config_id,
+ PPB_Audio_Callback audio_callback,
+ void* user_data) {
+ return PPB_Audio_Proxy::CreateProxyResource(instance, config_id,
+ audio_callback, user_data);
+}
+
+PP_Resource ResourceCreationProxy::CreateAudioConfig(
+ PP_Instance instance,
+ PP_AudioSampleRate sample_rate,
+ uint32_t sample_frame_count) {
+ return PPB_AudioConfig_Proxy::CreateProxyResource(
+ instance, sample_rate, sample_frame_count);
+}
+
+PP_Resource ResourceCreationProxy::CreateAudioTrusted(PP_Instance instance) {
+ // Proxied plugins can't created trusted audio devices.
+ return 0;
+}
+
+PP_Resource ResourceCreationProxy::CreateBroker(PP_Instance instance) {
+ return PPB_Broker_Proxy::CreateProxyResource(instance);
+}
+
+PP_Resource ResourceCreationProxy::CreateBuffer(PP_Instance instance,
+ uint32_t size) {
+ return PPB_Buffer_Proxy::CreateProxyResource(instance, size);
+}
+
+PP_Resource ResourceCreationProxy::CreateContext3D(
+ PP_Instance instance,
+ PP_Config3D_Dev config,
+ PP_Resource share_context,
+ const int32_t* attrib_list) {
+ return PPB_Context3D_Proxy::Create(instance, config, share_context,
+ attrib_list);
+}
+
+PP_Resource ResourceCreationProxy::CreateContext3DRaw(
+ PP_Instance instance,
+ PP_Config3D_Dev config,
+ PP_Resource share_context,
+ const int32_t* attrib_list) {
+ // Not proxied. The raw creation function is used only in the implementation
+ // of the proxy on the host side.
+ return 0;
+}
+
+PP_Resource ResourceCreationProxy::CreateDirectoryReader(
+ PP_Resource directory_ref) {
+ NOTIMPLEMENTED(); // Not proxied yet.
+ return 0;
+}
+
+PP_Resource ResourceCreationProxy::CreateFileChooser(
+ PP_Instance instance,
+ const PP_FileChooserOptions_Dev* options) {
+ return PPB_FileChooser_Proxy::CreateProxyResource(instance, options);
+}
+
+PP_Resource ResourceCreationProxy::CreateFileIO(PP_Instance instance) {
+ NOTIMPLEMENTED(); // Not proxied yet.
+ return 0;
+}
+
+PP_Resource ResourceCreationProxy::CreateFileRef(PP_Resource file_system,
+ const char* path) {
+ return PPB_FileRef_Proxy::CreateProxyResource(file_system, path);
+}
+
+PP_Resource ResourceCreationProxy::CreateFileSystem(
+ PP_Instance instance,
+ PP_FileSystemType type) {
+ return PPB_FileSystem_Proxy::CreateProxyResource(instance, type);
+}
+
+PP_Resource ResourceCreationProxy::CreateFlashMenu(
+ PP_Instance instance,
+ const PP_Flash_Menu* menu_data) {
+ return PPB_Flash_Menu_Proxy::CreateProxyResource(instance, menu_data);
+}
+
+PP_Resource ResourceCreationProxy::CreateFlashNetConnector(
+ PP_Instance instance) {
+ return PPB_Flash_NetConnector_Proxy::CreateProxyResource(instance);
+}
+
+PP_Resource ResourceCreationProxy::CreateFlashTCPSocket(
+ PP_Instance instance) {
+ return PPB_Flash_TCPSocket_Proxy::CreateProxyResource(instance);
+}
+
+PP_Resource ResourceCreationProxy::CreateFontObject(
+ PP_Instance instance,
+ const PP_FontDescription_Dev* description) {
+ if (!ppapi::FontImpl::IsPPFontDescriptionValid(*description))
+ return 0;
+
+ linked_ptr<Font> object(new Font(HostResource::MakeInstanceOnly(instance),
+ *description));
+ return PluginResourceTracker::GetInstance()->AddResource(object);
+}
+
+PP_Resource ResourceCreationProxy::CreateGraphics2D(PP_Instance instance,
+ const PP_Size& size,
+ PP_Bool is_always_opaque) {
+ return PPB_Graphics2D_Proxy::CreateProxyResource(instance, size,
+ is_always_opaque);
+}
+
+PP_Resource ResourceCreationProxy::CreateImageData(PP_Instance instance,
+ PP_ImageDataFormat format,
+ const PP_Size& size,
+ PP_Bool init_to_zero) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+
+ HostResource result;
+ std::string image_data_desc;
+ ImageHandle image_handle = ImageData::NullHandle;
+ dispatcher->Send(new PpapiHostMsg_ResourceCreation_ImageData(
+ INTERFACE_ID_RESOURCE_CREATION, instance, format, size, init_to_zero,
+ &result, &image_data_desc, &image_handle));
+
+ if (result.is_null() || image_data_desc.size() != sizeof(PP_ImageDataDesc))
+ return 0;
+
+ // We serialize the PP_ImageDataDesc just by copying to a string.
+ PP_ImageDataDesc desc;
+ memcpy(&desc, image_data_desc.data(), sizeof(PP_ImageDataDesc));
+
+ linked_ptr<ImageData> object(new ImageData(result, desc, image_handle));
+ return PluginResourceTracker::GetInstance()->AddResource(object);
+}
+
+PP_Resource ResourceCreationProxy::CreateGraphics3D(
+ PP_Instance instance,
+ PP_Config3D_Dev config,
+ PP_Resource share_context,
+ const int32_t* attrib_list) {
+ NOTIMPLEMENTED(); // Not proxied yet.
+ return 0;
+}
+
+PP_Resource ResourceCreationProxy::CreateScrollbar(PP_Instance instance,
+ PP_Bool vertical) {
+ NOTIMPLEMENTED(); // Not proxied yet.
+ return 0;
+}
+
+PP_Resource ResourceCreationProxy::CreateSurface3D(
+ PP_Instance instance,
+ PP_Config3D_Dev config,
+ const int32_t* attrib_list) {
+ return PPB_Surface3D_Proxy::CreateProxyResource(instance, config,
+ attrib_list);
+}
+
+PP_Resource ResourceCreationProxy::CreateTransport(PP_Instance instance,
+ const char* name,
+ const char* proto) {
+ NOTIMPLEMENTED(); // Not proxied yet.
+ return 0;
+}
+
+PP_Resource ResourceCreationProxy::CreateURLLoader(PP_Instance instance) {
+ return PPB_URLLoader_Proxy::CreateProxyResource(instance);
+}
+
+PP_Resource ResourceCreationProxy::CreateURLRequestInfo(PP_Instance instance) {
+ return PPB_URLRequestInfo_Proxy::CreateProxyResource(instance);
+}
+
+PP_Resource ResourceCreationProxy::CreateVideoDecoder(PP_Instance instance) {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+PP_Resource ResourceCreationProxy::CreateVideoLayer(
+ PP_Instance instance,
+ PP_VideoLayerMode_Dev mode) {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+bool ResourceCreationProxy::Send(IPC::Message* msg) {
+ return dispatcher_->Send(msg);
+}
+
+bool ResourceCreationProxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(ResourceCreationProxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_ResourceCreation_Graphics2D,
+ OnMsgCreateGraphics2D)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_ResourceCreation_ImageData,
+ OnMsgCreateImageData)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void ResourceCreationProxy::OnMsgCreateGraphics2D(PP_Instance instance,
+ const PP_Size& size,
+ PP_Bool is_always_opaque,
+ HostResource* result) {
+ ppapi::thunk::EnterFunction<ResourceCreationAPI> enter(instance, false);
+ if (enter.succeeded()) {
+ result->SetHostResource(instance, enter.functions()->CreateGraphics2D(
+ instance, size, is_always_opaque));
+ }
+}
+
+void ResourceCreationProxy::OnMsgCreateImageData(
+ PP_Instance instance,
+ int32_t format,
+ const PP_Size& size,
+ PP_Bool init_to_zero,
+ HostResource* result,
+ std::string* image_data_desc,
+ ImageHandle* result_image_handle) {
+ *result_image_handle = ImageData::NullHandle;
+
+ ppapi::thunk::EnterFunction<ResourceCreationAPI> enter(instance, false);
+ if (enter.failed())
+ return;
+
+ PP_Resource resource = enter.functions()->CreateImageData(
+ instance, static_cast<PP_ImageDataFormat>(format), size, init_to_zero);
+ if (!resource)
+ return;
+ result->SetHostResource(instance, resource);
+
+ // Get the description, it's just serialized as a string.
+ ppapi::thunk::EnterResourceNoLock<ppapi::thunk::PPB_ImageData_API>
+ enter_resource(resource, false);
+ PP_ImageDataDesc desc;
+ if (enter_resource.object()->Describe(&desc) == PP_TRUE) {
+ image_data_desc->resize(sizeof(PP_ImageDataDesc));
+ memcpy(&(*image_data_desc)[0], &desc, sizeof(PP_ImageDataDesc));
+ }
+
+ // Get the shared memory handle.
+ const PPB_ImageDataTrusted* trusted =
+ reinterpret_cast<const PPB_ImageDataTrusted*>(
+ dispatcher_->GetLocalInterface(PPB_IMAGEDATA_TRUSTED_INTERFACE));
+ uint32_t byte_count = 0;
+ if (trusted) {
+ int32_t handle;
+ if (trusted->GetSharedMemory(resource, &handle, &byte_count) == PP_OK) {
+#if defined(OS_WIN)
+ pp::proxy::ImageHandle ih = ImageData::HandleFromInt(handle);
+ *result_image_handle = dispatcher_->ShareHandleWithRemote(ih, false);
+#else
+ *result_image_handle = ImageData::HandleFromInt(handle);
+#endif
+ }
+ }
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/resource_creation_proxy.h b/ppapi/proxy/resource_creation_proxy.h
new file mode 100644
index 0000000..e6b609f
--- /dev/null
+++ b/ppapi/proxy/resource_creation_proxy.h
@@ -0,0 +1,126 @@
+// 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_RESOURCE_CREATION_PROXY_H_
+#define PPAPI_PROXY_RESOURCE_CREATION_PROXY_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "ipc/ipc_channel.h"
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/serialized_structs.h"
+#include "ppapi/shared_impl/function_group_base.h"
+#include "ppapi/thunk/resource_creation_api.h"
+
+struct PP_Size;
+
+namespace pp {
+namespace proxy {
+
+class HostResource;
+class Dispatcher;
+
+class ResourceCreationProxy : public ::ppapi::FunctionGroupBase,
+ public ::ppapi::thunk::ResourceCreationAPI,
+ public ::IPC::Channel::Listener,
+ public IPC::Message::Sender {
+ public:
+ explicit ResourceCreationProxy(Dispatcher* dispatcher);
+ virtual ~ResourceCreationProxy();
+
+ virtual ::ppapi::thunk::ResourceCreationAPI* AsResourceCreationAPI() OVERRIDE;
+
+ // ResourceCreationAPI (called in plugin).
+ virtual PP_Resource CreateAudio(PP_Instance instance,
+ PP_Resource config_id,
+ PPB_Audio_Callback audio_callback,
+ void* user_data) OVERRIDE;
+ virtual PP_Resource CreateAudioConfig(PP_Instance instance,
+ PP_AudioSampleRate sample_rate,
+ uint32_t sample_frame_count) OVERRIDE;
+ virtual PP_Resource CreateAudioTrusted(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateBroker(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateBuffer(PP_Instance instance,
+ uint32_t size) OVERRIDE;
+ virtual PP_Resource CreateContext3D(PP_Instance instance,
+ PP_Config3D_Dev config,
+ PP_Resource share_context,
+ const int32_t* attrib_list) OVERRIDE;
+ virtual PP_Resource CreateContext3DRaw(PP_Instance instance,
+ PP_Config3D_Dev config,
+ PP_Resource share_context,
+ const int32_t* attrib_list) OVERRIDE;
+ virtual PP_Resource CreateDirectoryReader(PP_Resource directory_ref) OVERRIDE;
+ virtual PP_Resource CreateFileChooser(
+ PP_Instance instance,
+ const PP_FileChooserOptions_Dev* options) OVERRIDE;
+ virtual PP_Resource CreateFileIO(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateFileRef(PP_Resource file_system,
+ const char* path) OVERRIDE;
+ virtual PP_Resource CreateFileSystem(PP_Instance instance,
+ PP_FileSystemType type) OVERRIDE;
+ virtual PP_Resource CreateFlashMenu(PP_Instance instance,
+ const PP_Flash_Menu* menu_data) OVERRIDE;
+ virtual PP_Resource CreateFlashNetConnector(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateFlashTCPSocket(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateFontObject(
+ PP_Instance instance,
+ const PP_FontDescription_Dev* description) OVERRIDE;
+ virtual PP_Resource CreateGraphics2D(PP_Instance pp_instance,
+ const PP_Size& size,
+ PP_Bool is_always_opaque) OVERRIDE;
+ virtual PP_Resource CreateGraphics3D(PP_Instance instance,
+ PP_Config3D_Dev config,
+ PP_Resource share_context,
+ const int32_t* attrib_list) OVERRIDE;
+ virtual PP_Resource CreateImageData(PP_Instance instance,
+ PP_ImageDataFormat format,
+ const PP_Size& size,
+ PP_Bool init_to_zero) OVERRIDE;
+ virtual PP_Resource CreateScrollbar(PP_Instance instance,
+ PP_Bool vertical) OVERRIDE;
+ virtual PP_Resource CreateSurface3D(PP_Instance instance,
+ PP_Config3D_Dev config,
+ const int32_t* attrib_list) OVERRIDE;
+ virtual PP_Resource CreateTransport(PP_Instance instance,
+ const char* name,
+ const char* proto) OVERRIDE;
+ virtual PP_Resource CreateURLLoader(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateURLRequestInfo(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateVideoDecoder(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateVideoLayer(PP_Instance instance,
+ PP_VideoLayerMode_Dev mode) OVERRIDE;
+
+ virtual bool Send(IPC::Message* msg) OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+
+ private:
+ // IPC message handlers (called in browser).
+ void OnMsgCreateAudio(PP_Instance instance,
+ int32_t sample_rate,
+ uint32_t sample_frame_count,
+ HostResource* result);
+ void OnMsgCreateGraphics2D(PP_Instance instance,
+ const PP_Size& size,
+ PP_Bool is_always_opaque,
+ HostResource* result);
+ void OnMsgCreateImageData(PP_Instance instance,
+ int32_t format,
+ const PP_Size& size,
+ PP_Bool init_to_zero,
+ HostResource* result,
+ std::string* image_data_desc,
+ ImageHandle* result_image_handle);
+
+ Dispatcher* dispatcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResourceCreationProxy);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_RESOURCE_CREATION_PROXY_H_
diff --git a/ppapi/proxy/run_all_unittests.cc b/ppapi/proxy/run_all_unittests.cc
new file mode 100644
index 0000000..7fd6ef2
--- /dev/null
+++ b/ppapi/proxy/run_all_unittests.cc
@@ -0,0 +1,9 @@
+// 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 "base/test/test_suite.h"
+
+int main(int argc, char** argv) {
+ return base::TestSuite(argc, argv).Run();
+}
diff --git a/ppapi/proxy/serialized_flash_menu.cc b/ppapi/proxy/serialized_flash_menu.cc
new file mode 100644
index 0000000..c7ef5ab
--- /dev/null
+++ b/ppapi/proxy/serialized_flash_menu.cc
@@ -0,0 +1,172 @@
+// 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/serialized_flash_menu.h"
+
+#include "ipc/ipc_message.h"
+#include "ppapi/c/private/ppb_flash_menu.h"
+#include "ppapi/proxy/ppapi_param_traits.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+// Maximum depth of submenus allowed (e.g., 1 indicates that submenus are
+// allowed, but not sub-submenus).
+const int kMaxMenuDepth = 2;
+
+bool CheckMenu(int depth, const PP_Flash_Menu* menu);
+void FreeMenu(const PP_Flash_Menu* menu);
+void WriteMenu(IPC::Message* m, const PP_Flash_Menu* menu);
+PP_Flash_Menu* ReadMenu(int depth, const IPC::Message* m, void** iter);
+
+bool CheckMenuItem(int depth, const PP_Flash_MenuItem* item) {
+ if (item->type == PP_FLASH_MENUITEM_TYPE_SUBMENU)
+ return CheckMenu(depth, item->submenu);
+ return true;
+}
+
+bool CheckMenu(int depth, const PP_Flash_Menu* menu) {
+ if (depth > kMaxMenuDepth || !menu)
+ return false;
+ ++depth;
+
+ if (menu->count && !menu->items)
+ return false;
+
+ for (uint32_t i = 0; i < menu->count; ++i) {
+ if (!CheckMenuItem(depth, menu->items + i))
+ return false;
+ }
+ return true;
+}
+
+void WriteMenuItem(IPC::Message* m, const PP_Flash_MenuItem* menu_item) {
+ PP_Flash_MenuItem_Type type = menu_item->type;
+ m->WriteUInt32(type);
+ m->WriteString(menu_item->name ? menu_item->name : "");
+ m->WriteInt(menu_item->id);
+ IPC::ParamTraits<PP_Bool>::Write(m, menu_item->enabled);
+ IPC::ParamTraits<PP_Bool>::Write(m, menu_item->checked);
+ if (type == PP_FLASH_MENUITEM_TYPE_SUBMENU)
+ WriteMenu(m, menu_item->submenu);
+}
+
+void WriteMenu(IPC::Message* m, const PP_Flash_Menu* menu) {
+ m->WriteUInt32(menu->count);
+ for (uint32_t i = 0; i < menu->count; ++i)
+ WriteMenuItem(m, menu->items + i);
+}
+
+void FreeMenuItem(const PP_Flash_MenuItem* menu_item) {
+ if (menu_item->name)
+ delete [] menu_item->name;
+ if (menu_item->submenu)
+ FreeMenu(menu_item->submenu);
+}
+
+void FreeMenu(const PP_Flash_Menu* menu) {
+ if (menu->items) {
+ for (uint32_t i = 0; i < menu->count; ++i)
+ FreeMenuItem(menu->items + i);
+ delete [] menu->items;
+ }
+ delete menu;
+}
+
+bool ReadMenuItem(int depth,
+ const IPC::Message* m,
+ void** iter,
+ PP_Flash_MenuItem* menu_item) {
+ uint32_t type;
+ if (!m->ReadUInt32(iter, &type))
+ return false;
+ if (type > PP_FLASH_MENUITEM_TYPE_SUBMENU)
+ return false;
+ menu_item->type = static_cast<PP_Flash_MenuItem_Type>(type);
+ std::string name;
+ if (!m->ReadString(iter, &name))
+ return false;
+ menu_item->name = new char[name.size() + 1];
+ std::copy(name.begin(), name.end(), menu_item->name);
+ menu_item->name[name.size()] = 0;
+ if (!m->ReadInt(iter, &menu_item->id))
+ return false;
+ if (!IPC::ParamTraits<PP_Bool>::Read(m, iter, &menu_item->enabled))
+ return false;
+ if (!IPC::ParamTraits<PP_Bool>::Read(m, iter, &menu_item->checked))
+ return false;
+ if (type == PP_FLASH_MENUITEM_TYPE_SUBMENU) {
+ menu_item->submenu = ReadMenu(depth, m, iter);
+ if (!menu_item->submenu)
+ return false;
+ }
+ return true;
+}
+
+PP_Flash_Menu* ReadMenu(int depth, const IPC::Message* m, void** iter) {
+ if (depth > kMaxMenuDepth)
+ return NULL;
+ ++depth;
+
+ PP_Flash_Menu* menu = new PP_Flash_Menu;
+ menu->items = NULL;
+
+ if (!m->ReadUInt32(iter, &menu->count)) {
+ FreeMenu(menu);
+ return NULL;
+ }
+
+ if (menu->count == 0)
+ return menu;
+
+ menu->items = new PP_Flash_MenuItem[menu->count];
+ memset(menu->items, 0, sizeof(PP_Flash_MenuItem) * menu->count);
+ for (uint32_t i = 0; i < menu->count; ++i) {
+ if (!ReadMenuItem(depth, m, iter, menu->items + i)) {
+ FreeMenu(menu);
+ return NULL;
+ }
+ }
+ return menu;
+}
+
+} // anonymous namespace
+
+SerializedFlashMenu::SerializedFlashMenu()
+ : pp_menu_(NULL),
+ own_menu_(false) {
+}
+
+SerializedFlashMenu::~SerializedFlashMenu() {
+ if (own_menu_)
+ FreeMenu(pp_menu_);
+}
+
+bool SerializedFlashMenu::SetPPMenu(const PP_Flash_Menu* menu) {
+ DCHECK(!pp_menu_);
+ if (!CheckMenu(0, menu))
+ return false;
+ pp_menu_ = menu;
+ own_menu_ = false;
+ return true;
+}
+
+
+void SerializedFlashMenu::WriteToMessage(IPC::Message* m) const {
+ WriteMenu(m, pp_menu_);
+}
+
+bool SerializedFlashMenu::ReadFromMessage(const IPC::Message* m, void** iter) {
+ DCHECK(!pp_menu_);
+ pp_menu_ = ReadMenu(0, m, iter);
+ if (!pp_menu_)
+ return false;
+
+ own_menu_ = true;
+ return true;
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/serialized_flash_menu.h b/ppapi/proxy/serialized_flash_menu.h
new file mode 100644
index 0000000..84b7bb9
--- /dev/null
+++ b/ppapi/proxy/serialized_flash_menu.h
@@ -0,0 +1,44 @@
+// 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_SERIALIZED_FLASH_MENU_H_
+#define PPAPI_PROXY_SERIALIZED_FLASH_MENU_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+
+struct PP_Flash_Menu;
+
+namespace IPC {
+class Message;
+}
+
+namespace pp {
+namespace proxy {
+
+class SerializedFlashMenu {
+ public:
+ SerializedFlashMenu();
+ ~SerializedFlashMenu();
+
+ bool SetPPMenu(const PP_Flash_Menu* menu);
+
+ const PP_Flash_Menu* pp_menu() const { return pp_menu_; }
+
+ void WriteToMessage(IPC::Message* m) const;
+ bool ReadFromMessage(const IPC::Message* m, void** iter);
+
+ private:
+ const PP_Flash_Menu* pp_menu_;
+ bool own_menu_;
+ DISALLOW_COPY_AND_ASSIGN(SerializedFlashMenu);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_SERIALIZED_FLASH_MENU_H_
diff --git a/ppapi/proxy/serialized_structs.cc b/ppapi/proxy/serialized_structs.cc
new file mode 100644
index 0000000..71c7376
--- /dev/null
+++ b/ppapi/proxy/serialized_structs.cc
@@ -0,0 +1,85 @@
+// 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/serialized_structs.h"
+
+#include "ppapi/c/dev/ppb_font_dev.h"
+#include "ppapi/c/pp_file_info.h"
+#include "ppapi/c/pp_rect.h"
+
+namespace pp {
+namespace proxy {
+
+SerializedFontDescription::SerializedFontDescription()
+ : face(),
+ family(0),
+ size(0),
+ weight(0),
+ italic(PP_FALSE),
+ small_caps(PP_FALSE),
+ letter_spacing(0),
+ word_spacing(0) {
+}
+
+SerializedFontDescription::~SerializedFontDescription() {}
+
+void SerializedFontDescription::SetFromPPFontDescription(
+ Dispatcher* dispatcher,
+ const PP_FontDescription_Dev& desc,
+ bool source_owns_ref) {
+ if (source_owns_ref)
+ face = SerializedVarSendInput(dispatcher, desc.face);
+ else
+ SerializedVarReturnValue(&face).Return(dispatcher, desc.face);
+
+ family = desc.family;
+ size = desc.size;
+ weight = desc.weight;
+ italic = desc.italic;
+ small_caps = desc.small_caps;
+ letter_spacing = desc.letter_spacing;
+ word_spacing = desc.word_spacing;
+}
+
+void SerializedFontDescription::SetToPPFontDescription(
+ Dispatcher* dispatcher,
+ PP_FontDescription_Dev* desc,
+ bool dest_owns_ref) const {
+ if (dest_owns_ref) {
+ ReceiveSerializedVarReturnValue face_return_value;
+ *static_cast<SerializedVar*>(&face_return_value) = face;
+ desc->face = face_return_value.Return(dispatcher);
+ } else {
+ desc->face = SerializedVarReceiveInput(face).Get(dispatcher);
+ }
+
+ desc->family = static_cast<PP_FontFamily_Dev>(family);
+ desc->size = size;
+ desc->weight = static_cast<PP_FontWeight_Dev>(weight);
+ desc->italic = italic;
+ desc->small_caps = small_caps;
+ desc->letter_spacing = letter_spacing;
+ 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(),
+ color(0) {
+ clip.point.x = 0;
+ clip.point.y = 0;
+ clip.size.height = 0;
+ clip.size.width = 0;
+ position.x = 0;
+ position.y = 0;
+}
+
+PPBFlash_DrawGlyphs_Params::~PPBFlash_DrawGlyphs_Params() {}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/serialized_structs.h b/ppapi/proxy/serialized_structs.h
new file mode 100644
index 0000000..516d53d
--- /dev/null
+++ b/ppapi/proxy/serialized_structs.h
@@ -0,0 +1,128 @@
+// 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_SERIALIZED_STRUCTS_H_
+#define PPAPI_PROXY_SERIALIZED_STRUCTS_H_
+
+#include <string>
+#include <vector>
+
+#include "base/shared_memory.h"
+#include "build/build_config.h"
+#include "ipc/ipc_platform_file.h"
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_point.h"
+#include "ppapi/c/pp_rect.h"
+#include "ppapi/proxy/host_resource.h"
+#include "ppapi/proxy/serialized_var.h"
+
+struct PP_FontDescription_Dev;
+
+namespace pp {
+namespace proxy {
+
+class Dispatcher;
+
+// PP_FontDescript_Dev has to be redefined with a SerializedVar in place of
+// the PP_Var used for the face name.
+struct SerializedFontDescription {
+ SerializedFontDescription();
+ ~SerializedFontDescription();
+
+ // Converts a PP_FontDescription_Dev to a SerializedFontDescription.
+ //
+ // If source_owns_ref is true, the reference owned by the
+ // PP_FontDescription_Dev will be unchanged and the caller is responsible for
+ // freeing it. When false, the SerializedFontDescription will take ownership
+ // of the ref. This is the difference between serializing as an input value
+ // (owns_ref = true) and an output value (owns_ref = true).
+ void SetFromPPFontDescription(Dispatcher* dispatcher,
+ const PP_FontDescription_Dev& desc,
+ bool source_owns_ref);
+
+ // Converts to a PP_FontDescription_Dev. The face name will have one ref
+ // assigned to it on behalf of the caller.
+ //
+ // If dest_owns_ref is set, the resulting PP_FontDescription_Dev will keep a
+ // reference to any strings we made on its behalf even when the
+ // SerializedFontDescription goes away. When false, ownership of the ref will
+ // stay with the SerializedFontDescription and the PP_FontDescription_Dev
+ // will just refer to that one. This is the difference between deserializing
+ // as an input value (owns_ref = false) and an output value (owns_ref = true).
+ void SetToPPFontDescription(Dispatcher* dispatcher,
+ PP_FontDescription_Dev* desc,
+ bool dest_owns_ref) const;
+
+ pp::proxy::SerializedVar face;
+ int32_t family;
+ uint32_t size;
+ int32_t weight;
+ PP_Bool italic;
+ PP_Bool small_caps;
+ int32_t letter_spacing;
+ int32_t word_spacing;
+};
+
+struct SerializedDirEntry {
+ std::string name;
+ 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 values.
+ SerializedVar path;
+ SerializedVar name;
+};
+
+struct PPBFlash_DrawGlyphs_Params {
+ PPBFlash_DrawGlyphs_Params();
+ ~PPBFlash_DrawGlyphs_Params();
+
+ PP_Instance instance;
+ HostResource image_data;
+ SerializedFontDescription font_desc;
+ uint32_t color;
+ PP_Point position;
+ PP_Rect clip;
+ float transformation[3][3];
+ std::vector<uint16_t> glyph_indices;
+ std::vector<PP_Point> glyph_advances;
+};
+
+struct PPBAudio_NotifyAudioStreamCreated_Params {
+ pp::proxy::HostResource audio_id;
+ int32_t result_code; // Will be != PP_OK on failure
+ IPC::PlatformFileForTransit socket_handle;
+ base::SharedMemoryHandle handle;
+ int32_t length;
+};
+
+struct PPBURLLoader_UpdateProgress_Params {
+ PP_Instance instance;
+ pp::proxy::HostResource resource;
+ int64_t bytes_sent;
+ int64_t total_bytes_to_be_sent;
+ int64_t bytes_received;
+ int64_t total_bytes_to_be_received;
+};
+
+#if defined(OS_WIN)
+typedef HANDLE ImageHandle;
+#elif defined(OS_MACOSX)
+typedef base::SharedMemoryHandle ImageHandle;
+#else
+// On X Windows this is a SysV shared memory key.
+typedef int ImageHandle;
+#endif
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_SERIALIZED_STRUCTS_H_
diff --git a/ppapi/proxy/serialized_var.cc b/ppapi/proxy/serialized_var.cc
new file mode 100644
index 0000000..786cc9e
--- /dev/null
+++ b/ppapi/proxy/serialized_var.cc
@@ -0,0 +1,536 @@
+// 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/serialized_var.h"
+
+#include "base/logging.h"
+#include "ipc/ipc_message_utils.h"
+#include "ppapi/proxy/dispatcher.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/ppapi_param_traits.h"
+#include "ppapi/proxy/var_serialization_rules.h"
+
+namespace pp {
+namespace proxy {
+
+// SerializedVar::Inner --------------------------------------------------------
+
+SerializedVar::Inner::Inner()
+ : serialization_rules_(NULL),
+ var_(PP_MakeUndefined()),
+ cleanup_mode_(CLEANUP_NONE),
+ dispatcher_for_end_send_pass_ref_(NULL) {
+#ifndef NDEBUG
+ has_been_serialized_ = false;
+ has_been_deserialized_ = false;
+#endif
+}
+
+SerializedVar::Inner::Inner(VarSerializationRules* serialization_rules)
+ : serialization_rules_(serialization_rules),
+ var_(PP_MakeUndefined()),
+ cleanup_mode_(CLEANUP_NONE),
+ dispatcher_for_end_send_pass_ref_(NULL) {
+#ifndef NDEBUG
+ has_been_serialized_ = false;
+ has_been_deserialized_ = false;
+#endif
+}
+
+SerializedVar::Inner::Inner(VarSerializationRules* serialization_rules,
+ const PP_Var& var)
+ : serialization_rules_(serialization_rules),
+ var_(var),
+ cleanup_mode_(CLEANUP_NONE),
+ dispatcher_for_end_send_pass_ref_(NULL) {
+#ifndef NDEBUG
+ has_been_serialized_ = false;
+ has_been_deserialized_ = false;
+#endif
+}
+
+SerializedVar::Inner::~Inner() {
+ switch (cleanup_mode_) {
+ case END_SEND_PASS_REF:
+ DCHECK(dispatcher_for_end_send_pass_ref_);
+ serialization_rules_->EndSendPassRef(var_,
+ dispatcher_for_end_send_pass_ref_);
+ break;
+ case END_RECEIVE_CALLER_OWNED:
+ serialization_rules_->EndReceiveCallerOwned(var_);
+ break;
+ default:
+ break;
+ }
+}
+
+PP_Var SerializedVar::Inner::GetVar() const {
+ DCHECK(serialization_rules_);
+
+ // If we're a string var, we should have already converted the string value
+ // to a var ID.
+ DCHECK(var_.type != PP_VARTYPE_STRING || var_.value.as_id != 0);
+ return var_;
+}
+
+PP_Var SerializedVar::Inner::GetIncompleteVar() const {
+ DCHECK(serialization_rules_);
+ return var_;
+}
+
+void SerializedVar::Inner::SetVar(PP_Var var) {
+ // Sanity check, when updating the var we should have received a
+ // serialization rules pointer already.
+ DCHECK(serialization_rules_);
+ var_ = var;
+}
+
+const std::string& SerializedVar::Inner::GetString() const {
+ DCHECK(serialization_rules_);
+ return string_value_;
+}
+
+std::string* SerializedVar::Inner::GetStringPtr() {
+ DCHECK(serialization_rules_);
+ return &string_value_;
+}
+
+void SerializedVar::Inner::WriteToMessage(IPC::Message* m) const {
+ // When writing to the IPC messages, a serization rules handler should
+ // always have been set.
+ //
+ // When sending a message, it should be difficult to trigger this if you're
+ // using the SerializedVarSendInput class and giving a non-NULL dispatcher.
+ // Make sure you're using the proper "Send" helper class.
+ //
+ // It should be more common to see this when handling an incoming message
+ // that returns a var. This means the message handler didn't write to the
+ // output parameter, or possibly you used the wrong helper class
+ // (normally SerializedVarReturnValue).
+ DCHECK(serialization_rules_);
+
+#ifndef NDEBUG
+ // We should only be serializing something once.
+ DCHECK(!has_been_serialized_);
+ has_been_serialized_ = true;
+#endif
+
+ // If the var is not a string type, we should not have ended up with any
+ // string data.
+ DCHECK(var_.type == PP_VARTYPE_STRING || string_value_.empty());
+
+ m->WriteInt(static_cast<int>(var_.type));
+ switch (var_.type) {
+ case PP_VARTYPE_UNDEFINED:
+ case PP_VARTYPE_NULL:
+ // These don't need any data associated with them other than the type we
+ // just serialized.
+ break;
+ case PP_VARTYPE_BOOL:
+ m->WriteBool(PP_ToBool(var_.value.as_bool));
+ break;
+ case PP_VARTYPE_INT32:
+ m->WriteInt(var_.value.as_int);
+ break;
+ case PP_VARTYPE_DOUBLE:
+ IPC::ParamTraits<double>::Write(m, var_.value.as_double);
+ break;
+ case PP_VARTYPE_STRING:
+ // TODO(brettw) in the case of an invalid string ID, it would be nice
+ // to send something to the other side such that a 0 ID would be
+ // generated there. Then the function implementing the interface can
+ // handle the invalid string as if it was in process rather than seeing
+ // what looks like a valid empty string.
+ m->WriteString(string_value_);
+ break;
+ case PP_VARTYPE_OBJECT:
+ m->WriteInt64(var_.value.as_id);
+ break;
+ case PP_VARTYPE_ARRAY:
+ case PP_VARTYPE_DICTIONARY:
+ // TODO(brettw) when these are supported, implement this.
+ NOTIMPLEMENTED();
+ break;
+ }
+}
+
+bool SerializedVar::Inner::ReadFromMessage(const IPC::Message* m, void** iter) {
+#ifndef NDEBUG
+ // We should only deserialize something once or will end up with leaked
+ // references.
+ //
+ // One place this has happened in the past is using
+ // std::vector<SerializedVar>.resize(). If you're doing this manually instead
+ // of using the helper classes for handling in/out vectors of vars, be
+ // sure you use the same pattern as the SerializedVarVector classes.
+ DCHECK(!has_been_deserialized_);
+ has_been_deserialized_ = true;
+#endif
+
+ // When reading, the dispatcher should be set when we get a Deserialize
+ // call (which will supply a dispatcher).
+ int type;
+ if (!m->ReadInt(iter, &type))
+ return false;
+
+ bool success = false;
+ switch (type) {
+ case PP_VARTYPE_UNDEFINED:
+ case PP_VARTYPE_NULL:
+ // These don't have any data associated with them other than the type we
+ // just serialized.
+ success = true;
+ break;
+ case PP_VARTYPE_BOOL: {
+ bool bool_value;
+ success = m->ReadBool(iter, &bool_value);
+ var_.value.as_bool = PP_FromBool(bool_value);
+ break;
+ }
+ case PP_VARTYPE_INT32:
+ success = m->ReadInt(iter, &var_.value.as_int);
+ break;
+ case PP_VARTYPE_DOUBLE:
+ success = IPC::ParamTraits<double>::Read(m, iter, &var_.value.as_double);
+ break;
+ case PP_VARTYPE_STRING:
+ success = m->ReadString(iter, &string_value_);
+ var_.value.as_id = 0;
+ break;
+ case PP_VARTYPE_OBJECT:
+ success = m->ReadInt64(iter, &var_.value.as_id);
+ break;
+ case PP_VARTYPE_ARRAY:
+ case PP_VARTYPE_DICTIONARY:
+ // TODO(brettw) when these types are supported, implement this.
+ NOTIMPLEMENTED();
+ break;
+ default:
+ // Leave success as false.
+ break;
+ }
+
+ // All success cases get here. We avoid writing the type above so that the
+ // output param is untouched (defaults to VARTYPE_UNDEFINED) even in the
+ // failure case.
+ if (success)
+ var_.type = static_cast<PP_VarType>(type);
+ return success;
+}
+
+void SerializedVar::Inner::SetCleanupModeToEndSendPassRef(
+ Dispatcher* dispatcher) {
+ DCHECK(dispatcher);
+ DCHECK(!dispatcher_for_end_send_pass_ref_);
+ dispatcher_for_end_send_pass_ref_ = dispatcher;
+ cleanup_mode_ = END_SEND_PASS_REF;
+}
+
+void SerializedVar::Inner::SetCleanupModeToEndReceiveCallerOwned() {
+ cleanup_mode_ = END_RECEIVE_CALLER_OWNED;
+}
+
+// SerializedVar ---------------------------------------------------------------
+
+SerializedVar::SerializedVar() : inner_(new Inner) {
+}
+
+SerializedVar::SerializedVar(VarSerializationRules* serialization_rules)
+ : inner_(new Inner(serialization_rules)) {
+}
+
+SerializedVar::SerializedVar(VarSerializationRules* serialization_rules,
+ const PP_Var& var)
+ : inner_(new Inner(serialization_rules, var)) {
+}
+
+SerializedVar::~SerializedVar() {
+}
+
+// SerializedVarSendInput ------------------------------------------------------
+
+SerializedVarSendInput::SerializedVarSendInput(Dispatcher* dispatcher,
+ const PP_Var& var)
+ : SerializedVar(dispatcher->serialization_rules()) {
+ inner_->SetVar(dispatcher->serialization_rules()->SendCallerOwned(
+ var, inner_->GetStringPtr()));
+}
+
+// static
+void SerializedVarSendInput::ConvertVector(Dispatcher* dispatcher,
+ const PP_Var* input,
+ size_t input_count,
+ std::vector<SerializedVar>* output) {
+ output->resize(input_count);
+ for (size_t i = 0; i < input_count; i++) {
+ SerializedVar& cur = (*output)[i];
+ cur = SerializedVar(dispatcher->serialization_rules());
+ cur.inner_->SetVar(dispatcher->serialization_rules()->SendCallerOwned(
+ input[i], cur.inner_->GetStringPtr()));
+ }
+}
+
+// ReceiveSerializedVarReturnValue ---------------------------------------------
+
+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(
+ inner_->GetIncompleteVar(), inner_->GetString(), dispatcher));
+ return inner_->GetVar();
+}
+
+// ReceiveSerializedException --------------------------------------------------
+
+ReceiveSerializedException::ReceiveSerializedException(Dispatcher* dispatcher,
+ PP_Var* exception)
+ : SerializedVar(dispatcher->serialization_rules()),
+ dispatcher_(dispatcher),
+ exception_(exception) {
+}
+
+ReceiveSerializedException::~ReceiveSerializedException() {
+ if (exception_) {
+ // When an output exception is specified, it will take ownership of the
+ // reference.
+ inner_->SetVar(inner_->serialization_rules()->ReceivePassRef(
+ inner_->GetIncompleteVar(), inner_->GetString(), dispatcher_));
+ *exception_ = inner_->GetVar();
+ } else {
+ // When no output exception is specified, the browser thinks we have a ref
+ // to an object that we don't want (this will happen only in the plugin
+ // since the browser will always specify an out exception for the plugin to
+ // write into).
+ //
+ // Strings don't need this handling since we can just avoid creating a
+ // Var from the std::string in the first place.
+ if (inner_->GetVar().type == PP_VARTYPE_OBJECT)
+ inner_->serialization_rules()->ReleaseObjectRef(inner_->GetVar());
+ }
+}
+
+bool ReceiveSerializedException::IsThrown() const {
+ return exception_ && exception_->type != PP_VARTYPE_UNDEFINED;
+}
+
+// ReceiveSerializedVarVectorOutParam ------------------------------------------
+
+ReceiveSerializedVarVectorOutParam::ReceiveSerializedVarVectorOutParam(
+ Dispatcher* dispatcher,
+ uint32_t* output_count,
+ PP_Var** output)
+ : dispatcher_(dispatcher),
+ output_count_(output_count),
+ output_(output) {
+}
+
+ReceiveSerializedVarVectorOutParam::~ReceiveSerializedVarVectorOutParam() {
+ *output_count_ = static_cast<uint32_t>(vector_.size());
+ if (!vector_.size()) {
+ *output_ = NULL;
+ return;
+ }
+
+ *output_ = static_cast<PP_Var*>(malloc(vector_.size() * sizeof(PP_Var)));
+ for (size_t i = 0; i < vector_.size(); i++) {
+ // Here we just mimic what happens when returning a value.
+ ReceiveSerializedVarReturnValue converted;
+ SerializedVar* serialized = &converted;
+ *serialized = vector_[i];
+ (*output_)[i] = converted.Return(dispatcher_);
+ }
+}
+
+std::vector<SerializedVar>* ReceiveSerializedVarVectorOutParam::OutParam() {
+ return &vector_;
+}
+
+// SerializedVarReceiveInput ---------------------------------------------------
+
+SerializedVarReceiveInput::SerializedVarReceiveInput(
+ const SerializedVar& serialized)
+ : serialized_(serialized),
+ dispatcher_(NULL),
+ var_(PP_MakeUndefined()) {
+}
+
+SerializedVarReceiveInput::~SerializedVarReceiveInput() {
+}
+
+PP_Var SerializedVarReceiveInput::Get(Dispatcher* dispatcher) {
+ serialized_.inner_->set_serialization_rules(
+ dispatcher->serialization_rules());
+
+ // Ensure that when the serialized var goes out of scope it cleans up the
+ // stuff we're making in BeginReceiveCallerOwned.
+ serialized_.inner_->SetCleanupModeToEndReceiveCallerOwned();
+
+ serialized_.inner_->SetVar(
+ serialized_.inner_->serialization_rules()->BeginReceiveCallerOwned(
+ serialized_.inner_->GetIncompleteVar(),
+ serialized_.inner_->GetStringPtr(),
+ dispatcher));
+ return serialized_.inner_->GetVar();
+}
+
+// SerializedVarVectorReceiveInput ---------------------------------------------
+
+SerializedVarVectorReceiveInput::SerializedVarVectorReceiveInput(
+ const std::vector<SerializedVar>& serialized)
+ : serialized_(serialized) {
+}
+
+SerializedVarVectorReceiveInput::~SerializedVarVectorReceiveInput() {
+ for (size_t i = 0; i < deserialized_.size(); i++) {
+ serialized_[i].inner_->serialization_rules()->EndReceiveCallerOwned(
+ deserialized_[i]);
+ }
+}
+
+PP_Var* SerializedVarVectorReceiveInput::Get(Dispatcher* dispatcher,
+ uint32_t* array_size) {
+ deserialized_.resize(serialized_.size());
+ for (size_t i = 0; i < serialized_.size(); i++) {
+ // The vector must be able to clean themselves up after this call is
+ // torn down.
+ serialized_[i].inner_->set_serialization_rules(
+ dispatcher->serialization_rules());
+
+ serialized_[i].inner_->SetVar(
+ serialized_[i].inner_->serialization_rules()->BeginReceiveCallerOwned(
+ serialized_[i].inner_->GetIncompleteVar(),
+ serialized_[i].inner_->GetStringPtr(),
+ dispatcher));
+ deserialized_[i] = serialized_[i].inner_->GetVar();
+ }
+
+ *array_size = static_cast<uint32_t>(serialized_.size());
+ return deserialized_.empty() ? NULL : &deserialized_[0];
+}
+
+// SerializedVarReturnValue ----------------------------------------------------
+
+SerializedVarReturnValue::SerializedVarReturnValue(SerializedVar* serialized)
+ : serialized_(serialized) {
+}
+
+void SerializedVarReturnValue::Return(Dispatcher* dispatcher,
+ const PP_Var& var) {
+ serialized_->inner_->set_serialization_rules(
+ dispatcher->serialization_rules());
+
+ // Var must clean up after our BeginSendPassRef call.
+ serialized_->inner_->SetCleanupModeToEndSendPassRef(dispatcher);
+
+ serialized_->inner_->SetVar(
+ dispatcher->serialization_rules()->BeginSendPassRef(
+ var,
+ 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)
+ : serialized_(serialized),
+ writable_var_(PP_MakeUndefined()),
+ dispatcher_(NULL) {
+}
+
+SerializedVarOutParam::~SerializedVarOutParam() {
+ if (serialized_->inner_->serialization_rules()) {
+ // When unset, OutParam wasn't called. We'll just leave the var untouched
+ // in that case.
+ serialized_->inner_->SetVar(
+ serialized_->inner_->serialization_rules()->BeginSendPassRef(
+ writable_var_, serialized_->inner_->GetStringPtr()));
+
+ // Normally the current object will be created on the stack to wrap a
+ // SerializedVar and won't have a scope around the actual IPC send. So we
+ // need to tell the SerializedVar to do the begin/end send pass ref calls.
+ serialized_->inner_->SetCleanupModeToEndSendPassRef(dispatcher_);
+ }
+}
+
+PP_Var* SerializedVarOutParam::OutParam(Dispatcher* dispatcher) {
+ dispatcher_ = dispatcher;
+ serialized_->inner_->set_serialization_rules(
+ dispatcher->serialization_rules());
+ return &writable_var_;
+}
+
+// SerializedVarVectorOutParam -------------------------------------------------
+
+SerializedVarVectorOutParam::SerializedVarVectorOutParam(
+ std::vector<SerializedVar>* serialized)
+ : dispatcher_(NULL),
+ serialized_(serialized),
+ count_(0),
+ array_(NULL) {
+}
+
+SerializedVarVectorOutParam::~SerializedVarVectorOutParam() {
+ DCHECK(dispatcher_);
+
+ // Convert the array written by the pepper code to the serialized structure.
+ // Note we can't use resize here, we have to allocate a new SerializedVar
+ // for each serialized item. See ParamTraits<vector<SerializedVar>>::Read.
+ serialized_->reserve(count_);
+ for (uint32_t i = 0; i < count_; i++) {
+ // Just mimic what we do for regular OutParams.
+ SerializedVar var;
+ SerializedVarOutParam out(&var);
+ *out.OutParam(dispatcher_) = array_[i];
+ serialized_->push_back(var);
+ }
+
+ // When returning arrays, the pepper code expects the caller to take
+ // ownership of the array.
+ free(array_);
+}
+
+PP_Var** SerializedVarVectorOutParam::ArrayOutParam(Dispatcher* dispatcher) {
+ DCHECK(!dispatcher_); // Should only be called once.
+ dispatcher_ = dispatcher;
+ return &array_;
+}
+
+SerializedVarTestConstructor::SerializedVarTestConstructor(
+ const PP_Var& pod_var) {
+ DCHECK(pod_var.type != PP_VARTYPE_STRING);
+ inner_->SetVar(pod_var);
+}
+
+SerializedVarTestConstructor::SerializedVarTestConstructor(
+ const std::string& str) {
+ PP_Var string_var = {};
+ string_var.type = PP_VARTYPE_STRING;
+ string_var.value.as_id = 0;
+ inner_->SetVar(string_var);
+ *inner_->GetStringPtr() = str;
+}
+
+SerializedVarTestReader::SerializedVarTestReader(const SerializedVar& var)
+ : SerializedVar(var) {
+}
+
+} // namespace proxy
+} // namespace pp
+
diff --git a/ppapi/proxy/serialized_var.h b/ppapi/proxy/serialized_var.h
new file mode 100644
index 0000000..3f74a28
--- /dev/null
+++ b/ppapi/proxy/serialized_var.h
@@ -0,0 +1,455 @@
+// 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_SERIALIZED_VAR_H_
+#define PPAPI_PROXY_SERIALIZED_VAR_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "ppapi/c/pp_var.h"
+
+namespace IPC {
+class Message;
+}
+
+namespace pp {
+namespace proxy {
+
+class Dispatcher;
+class VarSerializationRules;
+
+// This class encapsulates a var so that we can serialize and deserialize it
+// The problem is that for strings, serialization and deserialization requires
+// knowledge from outside about how to get at or create a string. So this
+// object groups the var with a dispatcher so that string values can be set or
+// gotten.
+//
+// Declare IPC messages as using this type, but don't use it directly (it has
+// no useful public methods). Instead, instantiate one of the helper classes
+// below which are conveniently named for each use case to prevent screwups.
+//
+// Design background
+// -----------------
+// This is sadly super complicated. The IPC system needs a consistent type to
+// use for sending and receiving vars (this is a SerializedVar). But there are
+// different combinations of reference counting for sending and receiving
+// objects and for dealing with strings
+//
+// This makes SerializedVar complicated and easy to mess up. To make it
+// reasonable to use all functions are protected and there are a use-specific
+// classes that encapsulate exactly one type of use in a way that typically
+// won't compile if you do the wrong thing.
+//
+// The IPC system is designed to pass things around and will make copies in
+// some cases, so our system must be designed so that this stuff will work.
+// This is challenging when the SerializedVar must to some cleanup after the
+// message is sent. To work around this, we create an inner class using a
+// linked_ptr so all copies of a SerializedVar can share and we can guarantee
+// that the actual data will get cleaned up on shutdown.
+//
+// Constness
+// ---------
+// SerializedVar basically doesn't support const. Everything is mutable and
+// most functions are declared const. This unfortunateness is because of the
+// way the IPC system works. When deserializing, it will have a const
+// SerializedVar in a Tuple and this will be given to the function. We kind of
+// want to modify that to convert strings and do refcounting.
+//
+// The helper classes used for accessing the SerializedVar have more reasonable
+// behavior and will enforce that you don't do stupid things.
+class SerializedVar {
+ public:
+ SerializedVar();
+ ~SerializedVar();
+
+ // Backend implementation for IPC::ParamTraits<SerializedVar>.
+ void WriteToMessage(IPC::Message* m) const {
+ inner_->WriteToMessage(m);
+ }
+ bool ReadFromMessage(const IPC::Message* m, void** iter) {
+ return inner_->ReadFromMessage(m, iter);
+ }
+
+ protected:
+ friend class SerializedVarReceiveInput;
+ friend class SerializedVarReturnValue;
+ friend class SerializedVarOutParam;
+ friend class SerializedVarSendInput;
+ friend class SerializedVarTestConstructor;
+ friend class SerializedVarVectorReceiveInput;
+
+ class Inner : public base::RefCounted<Inner> {
+ public:
+ Inner();
+ Inner(VarSerializationRules* serialization_rules);
+ Inner(VarSerializationRules* serialization_rules, const PP_Var& var);
+ ~Inner();
+
+ VarSerializationRules* serialization_rules() {
+ return serialization_rules_;
+ }
+ void set_serialization_rules(VarSerializationRules* serialization_rules) {
+ serialization_rules_ = serialization_rules;
+ }
+
+ // See outer class's declarations above.
+ PP_Var GetVar() const;
+ PP_Var GetIncompleteVar() const;
+ void SetVar(PP_Var var);
+ const std::string& GetString() const;
+ std::string* GetStringPtr();
+
+ void WriteToMessage(IPC::Message* m) const;
+ bool ReadFromMessage(const IPC::Message* m, void** iter);
+
+ // Sets the cleanup mode. See the CleanupMode enum below. These functions
+ // are not just a simple setter in order to require that the appropriate
+ // data is set along with the corresponding mode.
+ void SetCleanupModeToEndSendPassRef(Dispatcher* dispatcher);
+ void SetCleanupModeToEndReceiveCallerOwned();
+
+ private:
+ enum CleanupMode {
+ // The serialized var won't do anything special in the destructor
+ // (default).
+ CLEANUP_NONE,
+
+ // The serialized var will call EndSendPassRef in the destructor.
+ END_SEND_PASS_REF,
+
+ // The serialized var will call EndReceiveCallerOwned in the destructor.
+ END_RECEIVE_CALLER_OWNED
+ };
+
+ // Rules for serializing and deserializing vars for this process type.
+ // This may be NULL, but must be set before trying to serialize to IPC when
+ // sending, or before converting back to a PP_Var when receiving.
+ VarSerializationRules* serialization_rules_;
+
+ // If this is set to VARTYPE_STRING and the 'value.id' is 0, then the
+ // string_value_ contains the string. This means that the caller hasn't
+ // called Deserialize with a valid Dispatcher yet, which is how we can
+ // convert the serialized string value to a PP_Var string ID.
+ //
+ // This var may not be complete until the serialization rules are set when
+ // reading from IPC since we'll need that to convert the string_value to
+ // a string ID. Before this, the as_id will be 0 for VARTYPE_STRING.
+ PP_Var var_;
+
+ // Holds the literal string value to/from IPC. This will be valid of the
+ // var_ is VARTYPE_STRING.
+ std::string string_value_;
+
+ CleanupMode cleanup_mode_;
+
+ // The dispatcher saved for the call to EndSendPassRef for the cleanup.
+ // This is only valid when cleanup_mode == END_SEND_PASS_REF.
+ Dispatcher* dispatcher_for_end_send_pass_ref_;
+
+#ifndef NDEBUG
+ // When being sent or received over IPC, we should only be serialized or
+ // deserialized once. These flags help us assert this is true.
+ mutable bool has_been_serialized_;
+ mutable bool has_been_deserialized_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(Inner);
+ };
+
+ SerializedVar(VarSerializationRules* serialization_rules);
+ SerializedVar(VarSerializationRules* serialization, const PP_Var& var);
+
+ mutable scoped_refptr<Inner> inner_;
+};
+
+// Helpers for message sending side --------------------------------------------
+
+// For sending a value to the remote side.
+//
+// Example for API:
+// void MyFunction(PP_Var)
+// IPC message:
+// IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar);
+// Sender would be:
+// void MyFunctionProxy(PP_Var param) {
+// Send(new MyFunctionMsg(SerializedVarSendInput(param));
+// }
+class SerializedVarSendInput : public SerializedVar {
+ public:
+ SerializedVarSendInput(Dispatcher* dispatcher, const PP_Var& var);
+
+ // Helper function for serializing a vector of input vars for serialization.
+ static void ConvertVector(Dispatcher* dispatcher,
+ const PP_Var* input,
+ size_t input_count,
+ std::vector<SerializedVar>* output);
+
+ private:
+ // Disallow the empty constructor, but keep the default copy constructor
+ // which is required to send the object to the IPC system.
+ SerializedVarSendInput();
+};
+
+// For the calling side of a function returning a var. The sending side uses
+// SerializedVarReturnValue.
+//
+// Example for API:
+// PP_Var MyFunction()
+// IPC message:
+// IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
+// Message handler would be:
+// PP_Var MyFunctionProxy() {
+// ReceiveSerializedVarReturnValue result;
+// Send(new MyFunctionMsg(&result));
+// return result.Return(dispatcher());
+// }
+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. 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:
+ DISALLOW_COPY_AND_ASSIGN(ReceiveSerializedVarReturnValue);
+};
+
+// Example for API:
+// "void MyFunction(PP_Var* exception);"
+// IPC message:
+// IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
+// Message handler would be:
+// void OnMsgMyFunction(PP_Var* exception) {
+// ReceiveSerializedException se(dispatcher(), exception)
+// Send(new PpapiHostMsg_Foo(&se));
+// }
+class ReceiveSerializedException : public SerializedVar {
+ public:
+ ReceiveSerializedException(Dispatcher* dispatcher, PP_Var* exception);
+ ~ReceiveSerializedException();
+
+ // Returns true if the exception passed in the constructor is set. Check
+ // this before actually issuing the IPC.
+ bool IsThrown() const;
+
+ private:
+ Dispatcher* dispatcher_;
+
+ // The input/output exception we're wrapping. May be NULL.
+ PP_Var* exception_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedException);
+};
+
+// Helper class for when we're returning a vector of Vars. When it goes out
+// of scope it will automatically convert the vector filled by the IPC layer
+// into the array specified by the constructor params.
+//
+// Example for API:
+// "void MyFunction(uint32_t* count, PP_Var** vars);"
+// IPC message:
+// IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, std::vector<SerializedVar>);
+// Proxy function:
+// void MyFunction(uint32_t* count, PP_Var** vars) {
+// ReceiveSerializedVarVectorOutParam vect(dispatcher, count, vars);
+// Send(new MyMsg(vect.OutParam()));
+// }
+class ReceiveSerializedVarVectorOutParam {
+ public:
+ ReceiveSerializedVarVectorOutParam(Dispatcher* dispatcher,
+ uint32_t* output_count,
+ PP_Var** output);
+ ~ReceiveSerializedVarVectorOutParam();
+
+ std::vector<SerializedVar>* OutParam();
+
+ private:
+ Dispatcher* dispatcher_;
+ uint32_t* output_count_;
+ PP_Var** output_;
+
+ std::vector<SerializedVar> vector_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedVarVectorOutParam);
+};
+
+// Helpers for message receiving side ------------------------------------------
+
+// For receiving a value from the remote side.
+//
+// Example for API:
+// void MyFunction(PP_Var)
+// IPC message:
+// IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar);
+// Message handler would be:
+// void OnMsgMyFunction(SerializedVarReceiveInput param) {
+// MyFunction(param.Get());
+// }
+class SerializedVarReceiveInput {
+ public:
+ // We rely on the implicit constructor here since the IPC layer will call
+ // us with a SerializedVar. Pass this object by value, the copy constructor
+ // will pass along the pointer (as cheap as passing a pointer arg).
+ SerializedVarReceiveInput(const SerializedVar& serialized);
+ ~SerializedVarReceiveInput();
+
+ PP_Var Get(Dispatcher* dispatcher);
+
+ private:
+ const SerializedVar& serialized_;
+
+ // Since the SerializedVar is const, we can't set its dispatcher (which is
+ // OK since we don't need to). But since we need it for our own uses, we
+ // track it here. Will be NULL before Get() is called.
+ Dispatcher* dispatcher_;
+ PP_Var var_;
+};
+
+// For receiving an input vector of vars from the remote side.
+//
+// Example:
+// OnMsgMyFunction(SerializedVarVectorReceiveInput vector) {
+// uint32_t size;
+// PP_Var* array = vector.Get(dispatcher, &size);
+// MyFunction(size, array);
+// }
+class SerializedVarVectorReceiveInput {
+ public:
+ SerializedVarVectorReceiveInput(const std::vector<SerializedVar>& serialized);
+ ~SerializedVarVectorReceiveInput();
+
+ // Only call Get() once. It will return a pointer to the converted array and
+ // place the array size in the out param. Will return NULL when the array is
+ // empty.
+ PP_Var* Get(Dispatcher* dispatcher, uint32_t* array_size);
+
+ private:
+ const std::vector<SerializedVar>& serialized_;
+
+ // Filled by Get().
+ std::vector<PP_Var> deserialized_;
+};
+
+// For the receiving side of a function returning a var. The calling side uses
+// ReceiveSerializedVarReturnValue.
+//
+// Example for API:
+// PP_Var MyFunction()
+// IPC message:
+// IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
+// Message handler would be:
+// void OnMsgMyFunction(SerializedVarReturnValue result) {
+// result.Return(dispatcher(), MyFunction());
+// }
+class SerializedVarReturnValue {
+ public:
+ // We rely on the implicit constructor here since the IPC layer will call
+ // us with a SerializedVar*. Pass this object by value, the copy constructor
+ // will pass along the pointer (as cheap as passing a pointer arg).
+ SerializedVarReturnValue(SerializedVar* serialized);
+
+ 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_;
+};
+
+// For writing an out param to the remote side.
+//
+// Example for API:
+// "void MyFunction(PP_Var* out);"
+// IPC message:
+// IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
+// Message handler would be:
+// void OnMsgMyFunction(SerializedVarOutParam out_param) {
+// MyFunction(out_param.OutParam(dispatcher()));
+// }
+class SerializedVarOutParam {
+ public:
+ // We rely on the implicit constructor here since the IPC layer will call
+ // us with a SerializedVar*. Pass this object by value, the copy constructor
+ // will pass along the pointer (as cheap as passing a pointer arg).
+ SerializedVarOutParam(SerializedVar* serialized);
+ ~SerializedVarOutParam();
+
+ // Call this function only once. The caller should write its result to the
+ // returned var pointer before this class goes out of scope. The var's
+ // initial value will be VARTYPE_UNDEFINED.
+ PP_Var* OutParam(Dispatcher* dispatcher);
+
+ private:
+ SerializedVar* serialized_;
+
+ // This is the value actually written by the code and returned by OutParam.
+ // We'll write this into serialized_ in our destructor.
+ PP_Var writable_var_;
+
+ Dispatcher* dispatcher_;
+};
+
+// For returning an array of PP_Vars to the other side and transferring
+// ownership.
+//
+class SerializedVarVectorOutParam {
+ public:
+ SerializedVarVectorOutParam(std::vector<SerializedVar>* serialized);
+ ~SerializedVarVectorOutParam();
+
+ uint32_t* CountOutParam() { return &count_; }
+ PP_Var** ArrayOutParam(Dispatcher* dispatcher);
+
+ private:
+ Dispatcher* dispatcher_;
+ std::vector<SerializedVar>* serialized_;
+
+ uint32_t count_;
+ PP_Var* array_;
+};
+
+// For tests that just want to construct a SerializedVar for giving it to one
+// of the other classes.
+class SerializedVarTestConstructor : public SerializedVar {
+ public:
+ // For POD-types and objects.
+ explicit SerializedVarTestConstructor(const PP_Var& pod_var);
+
+ // For strings.
+ explicit SerializedVarTestConstructor(const std::string& str);
+};
+
+// For tests that want to read what's in a SerializedVar.
+class SerializedVarTestReader : public SerializedVar {
+ public:
+ explicit SerializedVarTestReader(const SerializedVar& var);
+
+ // The "incomplete" var is the one sent over the wire. Strings and object
+ // IDs have not yet been converted, so this is the thing that tests will
+ // actually want to check.
+ PP_Var GetIncompleteVar() const { return inner_->GetIncompleteVar(); }
+
+ const std::string& GetString() const { return inner_->GetString(); }
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_SERIALIZED_VAR_H_
+
diff --git a/ppapi/proxy/serialized_var_unittest.cc b/ppapi/proxy/serialized_var_unittest.cc
new file mode 100644
index 0000000..3cc4e61
--- /dev/null
+++ b/ppapi/proxy/serialized_var_unittest.cc
@@ -0,0 +1,74 @@
+// 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/ppapi_proxy_test.h"
+
+#include "ppapi/proxy/serialized_var.h"
+
+namespace pp {
+namespace proxy {
+
+namespace {
+
+PP_Var MakeStringVar(int64_t string_id) {
+ PP_Var ret;
+ ret.type = PP_VARTYPE_STRING;
+ ret.value.as_id = string_id;
+ return ret;
+}
+
+PP_Var MakeObjectVar(int64_t object_id) {
+ PP_Var ret;
+ ret.type = PP_VARTYPE_OBJECT;
+ ret.value.as_id = object_id;
+ return ret;
+}
+
+class SerializedVarTest : public PluginProxyTest {
+ public:
+ SerializedVarTest() {}
+};
+
+} // namespace
+
+// Tests output arguments.
+TEST_F(SerializedVarTest, PluginSerializedVarOutParam) {
+ PP_Var host_object = MakeObjectVar(0x31337);
+
+ // Start tracking this object in the plugin.
+ PP_Var plugin_object = var_tracker().ReceiveObjectPassRef(
+ host_object, plugin_dispatcher());
+ EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
+
+ {
+ SerializedVar sv;
+ {
+ // The "OutParam" does its work in its destructor, it will write the
+ // information to the SerializedVar we passed in the constructor.
+ SerializedVarOutParam out_param(&sv);
+ *out_param.OutParam(plugin_dispatcher()) = plugin_object;
+ }
+
+ // The object should have transformed the plugin object back to the host
+ // object ID. Nothing in the var tracker should have changed yet, and no
+ // messages should have been sent.
+ SerializedVarTestReader reader(sv);
+ EXPECT_EQ(host_object.value.as_id, reader.GetIncompleteVar().value.as_id);
+ EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
+ EXPECT_EQ(0u, sink().message_count());
+ }
+
+ // The out param should have done an "end send pass ref" on the plugin
+ // var serialization rules, which should have in turn released the reference
+ // in the var tracker. Since we only had one reference, this should have sent
+ // a release to the browser.
+ EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_object));
+ EXPECT_EQ(1u, sink().message_count());
+
+ // We don't bother validating that message since it's nontrivial and the
+ // PluginVarTracker test has cases that cover that this message is correct.
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/var_serialization_rules.h b/ppapi/proxy/var_serialization_rules.h
new file mode 100644
index 0000000..38698ae
--- /dev/null
+++ b/ppapi/proxy/var_serialization_rules.h
@@ -0,0 +1,93 @@
+// Copyright (c) 2010 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_VAR_SERIALIZATION_RULES_H_
+#define PPAPI_PROXY_VAR_SERIALIZATION_RULES_H_
+
+#include "ppapi/c/pp_var.h"
+
+#include <string>
+
+namespace pp {
+namespace proxy {
+
+class Dispatcher;
+
+// Encapsulates the rules for serializing and deserializing vars to and from
+// the local process. The renderer and the plugin process each have separate
+// bookkeeping rules.
+class VarSerializationRules {
+ public:
+ virtual ~VarSerializationRules() {}
+
+ // Caller-owned calls --------------------------------------------------------
+ //
+ // A caller-owned call is when doing a function call with a "normal" input
+ // argument. The caller has a reference to the var, and the caller is
+ // responsible for freeing that reference.
+
+ // Prepares the given var for sending to the callee. If the var is a string,
+ // the value of that string will be placed in *str_val. If the var is not
+ // a string, str_val will be untouched and may be NULL. The return value will
+ // be the var valid for the host process.
+ virtual PP_Var SendCallerOwned(const PP_Var& var, std::string* str_val) = 0;
+
+ // When receiving a caller-owned variable, normally we don't have to do
+ // anything. However, in the case of strings, we need to deserialize the
+ // string from IPC, create a new PP_Var string in the local process, call the
+ // function, and then destroy the temporary string. These two functions
+ // handle that process
+ //
+ // BeginReceiveCallerOwned takes a var from IPC and an optional pointer to
+ // the deserialized string (which will be used only when var is a
+ // VARTYPE_STRING and may be NULL otherwise) and returns a new var
+ // representing the input in the local process.
+ //
+ // EndReceiveCallerOwned destroys the string created by Begin* and does
+ // nothing otherwise. It should be called with the result of Begin*.
+ virtual PP_Var BeginReceiveCallerOwned(const PP_Var& var,
+ const std::string* str_val,
+ Dispatcher* dispatcher) = 0;
+ virtual void EndReceiveCallerOwned(const PP_Var& var) = 0;
+
+ // Passinag refs -------------------------------------------------------------
+ //
+ // A pass-ref transfer is when ownership of a reference is passed from
+ // onen side to the other. Normally, this happens via return values and
+ // output arguments, as for exceptions. The code generating the value
+ // (the function returning it in the case of a return value) will AddRef
+ // the var on behalf of the consumer of the value. Responsibility for
+ // Release is on the consumer (the caller of the function in the case of a
+ // return value).
+
+ // Creates a var in the context of the local process from the given
+ // deserialized var and deserialized string (which will be used only when var
+ // is a VARTYPE_STRING and may be NULL otherwise). The input var/string
+ // should be the result of calling SendPassRef in the remote process. The
+ // return value is the var valid in the plugin process.
+ virtual PP_Var ReceivePassRef(const PP_Var& var,
+ const std::string& str_val,
+ Dispatcher* dispatcher) = 0;
+
+ // Prepares a var to be sent to the remote side. One local reference will
+ // be passed to the remote side. Call Begin* before doing the send and End*
+ // after doing the send. See SendCallerOwned for a description of the string.
+ //
+ // The return value from BeginSendPassRef will be the var valid for the host
+ // process. This same value must be passed to EndSendPassRef.
+ virtual PP_Var BeginSendPassRef(const PP_Var& var, std::string* str_val) = 0;
+ virtual void EndSendPassRef(const PP_Var& var, Dispatcher* dispatcher) = 0;
+
+ // ---------------------------------------------------------------------------
+
+ virtual void ReleaseObjectRef(const PP_Var& var) = 0;
+
+ protected:
+ VarSerializationRules() {}
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_VAR_SERIALIZATION_RULES_H_