summaryrefslogtreecommitdiff
path: root/chromium/ppapi/proxy
diff options
context:
space:
mode:
authorZeno Albisser <zeno.albisser@digia.com>2013-08-15 21:46:11 +0200
committerZeno Albisser <zeno.albisser@digia.com>2013-08-15 21:46:11 +0200
commit679147eead574d186ebf3069647b4c23e8ccace6 (patch)
treefc247a0ac8ff119f7c8550879ebb6d3dd8d1ff69 /chromium/ppapi/proxy
downloadqtwebengine-chromium-679147eead574d186ebf3069647b4c23e8ccace6.tar.gz
Initial import.
Diffstat (limited to 'chromium/ppapi/proxy')
-rw-r--r--chromium/ppapi/proxy/DEPS22
-rw-r--r--chromium/ppapi/proxy/OWNERS11
-rw-r--r--chromium/ppapi/proxy/audio_input_resource.cc314
-rw-r--r--chromium/ppapi/proxy/audio_input_resource.h145
-rw-r--r--chromium/ppapi/proxy/broker_dispatcher.cc99
-rw-r--r--chromium/ppapi/proxy/broker_dispatcher.h65
-rw-r--r--chromium/ppapi/proxy/broker_resource.cc32
-rw-r--r--chromium/ppapi/proxy/broker_resource.h35
-rw-r--r--chromium/ppapi/proxy/browser_font_singleton_resource.cc38
-rw-r--r--chromium/ppapi/proxy/browser_font_singleton_resource.h42
-rw-r--r--chromium/ppapi/proxy/connection.h52
-rw-r--r--chromium/ppapi/proxy/content_decryptor_private_serializer.h57
-rw-r--r--chromium/ppapi/proxy/device_enumeration_resource_helper.cc223
-rw-r--r--chromium/ppapi/proxy/device_enumeration_resource_helper.h88
-rw-r--r--chromium/ppapi/proxy/device_enumeration_resource_helper_unittest.cc409
-rw-r--r--chromium/ppapi/proxy/dispatch_reply_message.h164
-rw-r--r--chromium/ppapi/proxy/dispatcher.cc86
-rw-r--r--chromium/ppapi/proxy/dispatcher.h124
-rw-r--r--chromium/ppapi/proxy/enter_proxy.h204
-rw-r--r--chromium/ppapi/proxy/ext_crx_file_system_private_resource.cc80
-rw-r--r--chromium/ppapi/proxy/ext_crx_file_system_private_resource.h68
-rw-r--r--chromium/ppapi/proxy/extensions_common_resource.cc139
-rw-r--r--chromium/ppapi/proxy/extensions_common_resource.h68
-rw-r--r--chromium/ppapi/proxy/file_chooser_resource.cc149
-rw-r--r--chromium/ppapi/proxy/file_chooser_resource.h85
-rw-r--r--chromium/ppapi/proxy/file_chooser_resource_unittest.cc146
-rw-r--r--chromium/ppapi/proxy/file_io_resource.cc451
-rw-r--r--chromium/ppapi/proxy/file_io_resource.h146
-rw-r--r--chromium/ppapi/proxy/file_ref_resource.cc279
-rw-r--r--chromium/ppapi/proxy/file_ref_resource.h107
-rw-r--r--chromium/ppapi/proxy/file_system_resource.cc79
-rw-r--r--chromium/ppapi/proxy/file_system_resource.h58
-rw-r--r--chromium/ppapi/proxy/flash_clipboard_resource.cc156
-rw-r--r--chromium/ppapi/proxy/flash_clipboard_resource.h50
-rw-r--r--chromium/ppapi/proxy/flash_drm_resource.cc100
-rw-r--r--chromium/ppapi/proxy/flash_drm_resource.h55
-rw-r--r--chromium/ppapi/proxy/flash_file_resource.cc230
-rw-r--r--chromium/ppapi/proxy/flash_file_resource.h73
-rw-r--r--chromium/ppapi/proxy/flash_font_file_resource.cc82
-rw-r--r--chromium/ppapi/proxy/flash_font_file_resource.h61
-rw-r--r--chromium/ppapi/proxy/flash_fullscreen_resource.cc46
-rw-r--r--chromium/ppapi/proxy/flash_fullscreen_resource.h43
-rw-r--r--chromium/ppapi/proxy/flash_menu_resource.cc97
-rw-r--r--chromium/ppapi/proxy/flash_menu_resource.h57
-rw-r--r--chromium/ppapi/proxy/flash_resource.cc256
-rw-r--r--chromium/ppapi/proxy/flash_resource.h75
-rw-r--r--chromium/ppapi/proxy/flash_resource_unittest.cc71
-rw-r--r--chromium/ppapi/proxy/gamepad_resource.cc116
-rw-r--r--chromium/ppapi/proxy/gamepad_resource.h60
-rw-r--r--chromium/ppapi/proxy/graphics_2d_resource.cc147
-rw-r--r--chromium/ppapi/proxy/graphics_2d_resource.h62
-rw-r--r--chromium/ppapi/proxy/handle_converter.cc285
-rw-r--r--chromium/ppapi/proxy/handle_converter.h62
-rw-r--r--chromium/ppapi/proxy/host_dispatcher.cc277
-rw-r--r--chromium/ppapi/proxy/host_dispatcher.h156
-rw-r--r--chromium/ppapi/proxy/host_resolver_private_resource.cc57
-rw-r--r--chromium/ppapi/proxy/host_resolver_private_resource.h46
-rw-r--r--chromium/ppapi/proxy/host_resolver_resource.cc85
-rw-r--r--chromium/ppapi/proxy/host_resolver_resource.h43
-rw-r--r--chromium/ppapi/proxy/host_resolver_resource_base.cc132
-rw-r--r--chromium/ppapi/proxy/host_resolver_resource_base.h74
-rw-r--r--chromium/ppapi/proxy/host_var_serialization_rules.cc58
-rw-r--r--chromium/ppapi/proxy/host_var_serialization_rules.h39
-rw-r--r--chromium/ppapi/proxy/interface_list.cc392
-rw-r--r--chromium/ppapi/proxy/interface_list.h105
-rw-r--r--chromium/ppapi/proxy/interface_proxy.cc25
-rw-r--r--chromium/ppapi/proxy/interface_proxy.h68
-rw-r--r--chromium/ppapi/proxy/locking_resource_releaser.h41
-rw-r--r--chromium/ppapi/proxy/mock_resource.cc18
-rw-r--r--chromium/ppapi/proxy/mock_resource.h26
-rw-r--r--chromium/ppapi/proxy/net_address_resource.cc81
-rw-r--r--chromium/ppapi/proxy/net_address_resource.h56
-rw-r--r--chromium/ppapi/proxy/network_proxy_resource.cc66
-rw-r--r--chromium/ppapi/proxy/network_proxy_resource.h45
-rw-r--r--chromium/ppapi/proxy/pdf_resource.cc192
-rw-r--r--chromium/ppapi/proxy/pdf_resource.h67
-rw-r--r--chromium/ppapi/proxy/pdf_resource_unittest.cc206
-rw-r--r--chromium/ppapi/proxy/plugin_array_buffer_var.cc110
-rw-r--r--chromium/ppapi/proxy/plugin_array_buffer_var.h51
-rw-r--r--chromium/ppapi/proxy/plugin_dispatcher.cc369
-rw-r--r--chromium/ppapi/proxy/plugin_dispatcher.h226
-rw-r--r--chromium/ppapi/proxy/plugin_dispatcher_unittest.cc87
-rw-r--r--chromium/ppapi/proxy/plugin_globals.cc202
-rw-r--r--chromium/ppapi/proxy/plugin_globals.h173
-rw-r--r--chromium/ppapi/proxy/plugin_main_nacl.cc296
-rw-r--r--chromium/ppapi/proxy/plugin_message_filter.cc61
-rw-r--r--chromium/ppapi/proxy/plugin_message_filter.h57
-rw-r--r--chromium/ppapi/proxy/plugin_proxy_delegate.h50
-rw-r--r--chromium/ppapi/proxy/plugin_resource.cc160
-rw-r--r--chromium/ppapi/proxy/plugin_resource.h253
-rw-r--r--chromium/ppapi/proxy/plugin_resource_callback.h52
-rw-r--r--chromium/ppapi/proxy/plugin_resource_tracker.cc72
-rw-r--r--chromium/ppapi/proxy/plugin_resource_tracker.h53
-rw-r--r--chromium/ppapi/proxy/plugin_resource_tracker_unittest.cc71
-rw-r--r--chromium/ppapi/proxy/plugin_var_serialization_rules.cc120
-rw-r--r--chromium/ppapi/proxy/plugin_var_serialization_rules.h54
-rw-r--r--chromium/ppapi/proxy/plugin_var_tracker.cc410
-rw-r--r--chromium/ppapi/proxy/plugin_var_tracker.h205
-rw-r--r--chromium/ppapi/proxy/plugin_var_tracker_unittest.cc248
-rw-r--r--chromium/ppapi/proxy/ppapi_command_buffer_proxy.cc259
-rw-r--r--chromium/ppapi/proxy/ppapi_command_buffer_proxy.h75
-rw-r--r--chromium/ppapi/proxy/ppapi_message_utils.h131
-rw-r--r--chromium/ppapi/proxy/ppapi_messages.cc34
-rw-r--r--chromium/ppapi/proxy/ppapi_messages.h2060
-rw-r--r--chromium/ppapi/proxy/ppapi_param_traits.cc740
-rw-r--r--chromium/ppapi/proxy/ppapi_param_traits.h209
-rw-r--r--chromium/ppapi/proxy/ppapi_perftests.cc10
-rw-r--r--chromium/ppapi/proxy/ppapi_proxy_export.h29
-rw-r--r--chromium/ppapi/proxy/ppapi_proxy_test.cc592
-rw-r--r--chromium/ppapi/proxy/ppapi_proxy_test.h372
-rw-r--r--chromium/ppapi/proxy/ppb_audio_proxy.cc349
-rw-r--r--chromium/ppapi/proxy/ppb_audio_proxy.h87
-rw-r--r--chromium/ppapi/proxy/ppb_broker_proxy.cc235
-rw-r--r--chromium/ppapi/proxy/ppb_broker_proxy.h50
-rw-r--r--chromium/ppapi/proxy/ppb_buffer_proxy.cc156
-rw-r--r--chromium/ppapi/proxy/ppb_buffer_proxy.h76
-rw-r--r--chromium/ppapi/proxy/ppb_core_proxy.cc131
-rw-r--r--chromium/ppapi/proxy/ppb_core_proxy.h44
-rw-r--r--chromium/ppapi/proxy/ppb_file_ref_proxy.cc549
-rw-r--r--chromium/ppapi/proxy/ppb_file_ref_proxy.h138
-rw-r--r--chromium/ppapi/proxy/ppb_flash_message_loop_proxy.cc165
-rw-r--r--chromium/ppapi/proxy/ppb_flash_message_loop_proxy.h54
-rw-r--r--chromium/ppapi/proxy/ppb_graphics_3d_proxy.cc497
-rw-r--r--chromium/ppapi/proxy/ppb_graphics_3d_proxy.h124
-rw-r--r--chromium/ppapi/proxy/ppb_image_data_proxy.cc707
-rw-r--r--chromium/ppapi/proxy/ppb_image_data_proxy.h192
-rw-r--r--chromium/ppapi/proxy/ppb_instance_proxy.cc1277
-rw-r--r--chromium/ppapi/proxy/ppb_instance_proxy.h276
-rw-r--r--chromium/ppapi/proxy/ppb_message_loop_proxy.cc274
-rw-r--r--chromium/ppapi/proxy/ppb_message_loop_proxy.h111
-rw-r--r--chromium/ppapi/proxy/ppb_network_monitor_private_proxy.cc156
-rw-r--r--chromium/ppapi/proxy/ppb_network_monitor_private_proxy.h63
-rw-r--r--chromium/ppapi/proxy/ppb_tcp_socket_private_proxy.cc263
-rw-r--r--chromium/ppapi/proxy/ppb_tcp_socket_private_proxy.h69
-rw-r--r--chromium/ppapi/proxy/ppb_tcp_socket_proxy.cc299
-rw-r--r--chromium/ppapi/proxy/ppb_tcp_socket_proxy.h57
-rw-r--r--chromium/ppapi/proxy/ppb_testing_proxy.cc229
-rw-r--r--chromium/ppapi/proxy/ppb_testing_proxy.h57
-rw-r--r--chromium/ppapi/proxy/ppb_var_deprecated_proxy.cc538
-rw-r--r--chromium/ppapi/proxy/ppb_var_deprecated_proxy.h102
-rw-r--r--chromium/ppapi/proxy/ppb_var_unittest.cc241
-rw-r--r--chromium/ppapi/proxy/ppb_video_decoder_proxy.cc320
-rw-r--r--chromium/ppapi/proxy/ppb_video_decoder_proxy.h78
-rw-r--r--chromium/ppapi/proxy/ppb_x509_certificate_private_proxy.cc74
-rw-r--r--chromium/ppapi/proxy/ppb_x509_certificate_private_proxy.h36
-rw-r--r--chromium/ppapi/proxy/ppp_class_proxy.cc396
-rw-r--r--chromium/ppapi/proxy/ppp_class_proxy.h100
-rw-r--r--chromium/ppapi/proxy/ppp_content_decryptor_private_proxy.cc581
-rw-r--r--chromium/ppapi/proxy/ppp_content_decryptor_private_proxy.h74
-rw-r--r--chromium/ppapi/proxy/ppp_graphics_3d_proxy.cc81
-rw-r--r--chromium/ppapi/proxy/ppp_graphics_3d_proxy.h41
-rw-r--r--chromium/ppapi/proxy/ppp_input_event_proxy.cc123
-rw-r--r--chromium/ppapi/proxy/ppp_input_event_proxy.h47
-rw-r--r--chromium/ppapi/proxy/ppp_instance_private_proxy.cc89
-rw-r--r--chromium/ppapi/proxy/ppp_instance_private_proxy.h46
-rw-r--r--chromium/ppapi/proxy/ppp_instance_private_proxy_unittest.cc210
-rw-r--r--chromium/ppapi/proxy/ppp_instance_proxy.cc256
-rw-r--r--chromium/ppapi/proxy/ppp_instance_proxy.h63
-rw-r--r--chromium/ppapi/proxy/ppp_instance_proxy_unittest.cc197
-rw-r--r--chromium/ppapi/proxy/ppp_messaging_proxy.cc103
-rw-r--r--chromium/ppapi/proxy/ppp_messaging_proxy.h44
-rw-r--r--chromium/ppapi/proxy/ppp_messaging_proxy_perftest.cc88
-rw-r--r--chromium/ppapi/proxy/ppp_messaging_proxy_unittest.cc136
-rw-r--r--chromium/ppapi/proxy/ppp_mouse_lock_proxy.cc87
-rw-r--r--chromium/ppapi/proxy/ppp_mouse_lock_proxy.h41
-rw-r--r--chromium/ppapi/proxy/ppp_printing_proxy.cc214
-rw-r--r--chromium/ppapi/proxy/ppp_printing_proxy.h57
-rw-r--r--chromium/ppapi/proxy/ppp_text_input_proxy.cc81
-rw-r--r--chromium/ppapi/proxy/ppp_text_input_proxy.h42
-rw-r--r--chromium/ppapi/proxy/ppp_video_decoder_proxy.cc184
-rw-r--r--chromium/ppapi/proxy/ppp_video_decoder_proxy.h53
-rw-r--r--chromium/ppapi/proxy/printing_resource.cc58
-rw-r--r--chromium/ppapi/proxy/printing_resource.h46
-rw-r--r--chromium/ppapi/proxy/printing_resource_unittest.cc102
-rw-r--r--chromium/ppapi/proxy/proxy_array_output.cc21
-rw-r--r--chromium/ppapi/proxy/proxy_array_output.h138
-rw-r--r--chromium/ppapi/proxy/proxy_channel.cc92
-rw-r--r--chromium/ppapi/proxy/proxy_channel.h126
-rw-r--r--chromium/ppapi/proxy/proxy_completion_callback_factory.h87
-rw-r--r--chromium/ppapi/proxy/proxy_module.cc32
-rw-r--r--chromium/ppapi/proxy/proxy_module.h43
-rw-r--r--chromium/ppapi/proxy/proxy_object_var.cc38
-rw-r--r--chromium/ppapi/proxy/proxy_object_var.h58
-rw-r--r--chromium/ppapi/proxy/raw_var_data.cc665
-rw-r--r--chromium/ppapi/proxy/raw_var_data.h261
-rw-r--r--chromium/ppapi/proxy/raw_var_data_unittest.cc189
-rw-r--r--chromium/ppapi/proxy/resource_creation_proxy.cc464
-rw-r--r--chromium/ppapi/proxy/resource_creation_proxy.h191
-rw-r--r--chromium/ppapi/proxy/resource_message_params.cc204
-rw-r--r--chromium/ppapi/proxy/resource_message_params.h211
-rw-r--r--chromium/ppapi/proxy/resource_message_test_sink.cc130
-rw-r--r--chromium/ppapi/proxy/resource_message_test_sink.h99
-rw-r--r--chromium/ppapi/proxy/run_all_unittests.cc9
-rw-r--r--chromium/ppapi/proxy/serialized_flash_menu.cc181
-rw-r--r--chromium/ppapi/proxy/serialized_flash_menu.h46
-rw-r--r--chromium/ppapi/proxy/serialized_handle.cc143
-rw-r--r--chromium/ppapi/proxy/serialized_handle.h150
-rw-r--r--chromium/ppapi/proxy/serialized_structs.cc133
-rw-r--r--chromium/ppapi/proxy/serialized_structs.h133
-rw-r--r--chromium/ppapi/proxy/serialized_var.cc467
-rw-r--r--chromium/ppapi/proxy/serialized_var.h502
-rw-r--r--chromium/ppapi/proxy/serialized_var_unittest.cc354
-rw-r--r--chromium/ppapi/proxy/talk_resource.cc114
-rw-r--r--chromium/ppapi/proxy/talk_resource.h60
-rw-r--r--chromium/ppapi/proxy/talk_resource_unittest.cc173
-rw-r--r--chromium/ppapi/proxy/tcp_server_socket_private_resource.cc138
-rw-r--r--chromium/ppapi/proxy/tcp_server_socket_private_resource.h69
-rw-r--r--chromium/ppapi/proxy/truetype_font_resource.cc130
-rw-r--r--chromium/ppapi/proxy/truetype_font_resource.h73
-rw-r--r--chromium/ppapi/proxy/truetype_font_singleton_resource.cc122
-rw-r--r--chromium/ppapi/proxy/truetype_font_singleton_resource.h65
-rw-r--r--chromium/ppapi/proxy/udp_socket_private_resource.cc83
-rw-r--r--chromium/ppapi/proxy/udp_socket_private_resource.h51
-rw-r--r--chromium/ppapi/proxy/udp_socket_resource.cc86
-rw-r--r--chromium/ppapi/proxy/udp_socket_resource.h50
-rw-r--r--chromium/ppapi/proxy/udp_socket_resource_base.cc301
-rw-r--r--chromium/ppapi/proxy/udp_socket_resource_base.h103
-rw-r--r--chromium/ppapi/proxy/url_loader_resource.cc392
-rw-r--r--chromium/ppapi/proxy/url_loader_resource.h146
-rw-r--r--chromium/ppapi/proxy/url_request_info_resource.cc215
-rw-r--r--chromium/ppapi/proxy/url_request_info_resource.h55
-rw-r--r--chromium/ppapi/proxy/url_response_info_resource.cc73
-rw-r--r--chromium/ppapi/proxy/url_response_info_resource.h54
-rw-r--r--chromium/ppapi/proxy/var_serialization_rules.h89
-rw-r--r--chromium/ppapi/proxy/video_capture_resource.cc240
-rw-r--r--chromium/ppapi/proxy/video_capture_resource.h99
-rw-r--r--chromium/ppapi/proxy/video_destination_resource.cc102
-rw-r--r--chromium/ppapi/proxy/video_destination_resource.h56
-rw-r--r--chromium/ppapi/proxy/video_source_resource.cc120
-rw-r--r--chromium/ppapi/proxy/video_source_resource.h67
-rw-r--r--chromium/ppapi/proxy/websocket_resource.cc494
-rw-r--r--chromium/ppapi/proxy/websocket_resource.h157
-rw-r--r--chromium/ppapi/proxy/websocket_resource_unittest.cc169
233 files changed, 37522 insertions, 0 deletions
diff --git a/chromium/ppapi/proxy/DEPS b/chromium/ppapi/proxy/DEPS
new file mode 100644
index 00000000000..e56cd3def11
--- /dev/null
+++ b/chromium/ppapi/proxy/DEPS
@@ -0,0 +1,22 @@
+include_rules = [
+ "+base",
+ "+components/tracing",
+ "+gpu",
+ "+ipc",
+ "+media/audio",
+ "+skia",
+ "+ui/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 (and the output traits it depends on).
+ "-ppapi/cpp",
+ "+ppapi/cpp/completion_callback.h",
+ "+ppapi/cpp/output_traits.h",
+
+ # The untrusted build references the NaCl integrated runtime (IRT).
+ "+native_client/src/shared",
+ "+native_client/src/untrusted"
+]
+
diff --git a/chromium/ppapi/proxy/OWNERS b/chromium/ppapi/proxy/OWNERS
new file mode 100644
index 00000000000..7d2c40a5e8b
--- /dev/null
+++ b/chromium/ppapi/proxy/OWNERS
@@ -0,0 +1,11 @@
+piman@chromium.org
+
+# Changes to IPC messages require a security review to avoid introducing
+# new sandbox escapes.
+per-file *_messages*.h=set noparent
+per-file *_messages*.h=cdn@chromium.org
+per-file *_messages*.h=cevans@chromium.org
+per-file *_messages*.h=jln@chromium.org
+per-file *_messages*.h=jschuh@chromium.org
+per-file *_messages*.h=palmer@chromium.org
+per-file *_messages*.h=tsepez@chromium.org
diff --git a/chromium/ppapi/proxy/audio_input_resource.cc b/chromium/ppapi/proxy/audio_input_resource.cc
new file mode 100644
index 00000000000..4a7afff1a2c
--- /dev/null
+++ b/chromium/ppapi/proxy/audio_input_resource.cc
@@ -0,0 +1,314 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/audio_input_resource.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "ipc/ipc_platform_file.h"
+#include "media/audio/audio_parameters.h"
+#include "media/audio/shared_memory_util.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/resource_message_params.h"
+#include "ppapi/proxy/serialized_handle.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/ppb_audio_config_shared.h"
+#include "ppapi/shared_impl/resource_tracker.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_audio_config_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+AudioInputResource::AudioInputResource(
+ Connection connection,
+ PP_Instance instance)
+ : PluginResource(connection, instance),
+ open_state_(BEFORE_OPEN),
+ capturing_(false),
+ shared_memory_size_(0),
+ audio_input_callback_0_2_(NULL),
+ audio_input_callback_(NULL),
+ user_data_(NULL),
+ enumeration_helper_(this),
+ bytes_per_second_(0) {
+ SendCreate(RENDERER, PpapiHostMsg_AudioInput_Create());
+}
+
+AudioInputResource::~AudioInputResource() {
+ Close();
+}
+
+thunk::PPB_AudioInput_API* AudioInputResource::AsPPB_AudioInput_API() {
+ return this;
+}
+
+void AudioInputResource::OnReplyReceived(
+ const ResourceMessageReplyParams& params,
+ const IPC::Message& msg) {
+ if (!enumeration_helper_.HandleReply(params, msg))
+ PluginResource::OnReplyReceived(params, msg);
+}
+
+int32_t AudioInputResource::EnumerateDevices0_2(
+ PP_Resource* devices,
+ scoped_refptr<TrackedCallback> callback) {
+ return enumeration_helper_.EnumerateDevices0_2(devices, callback);
+}
+
+int32_t AudioInputResource::EnumerateDevices(
+ const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback) {
+ return enumeration_helper_.EnumerateDevices(output, callback);
+}
+
+int32_t AudioInputResource::MonitorDeviceChange(
+ PP_MonitorDeviceChangeCallback callback,
+ void* user_data) {
+ return enumeration_helper_.MonitorDeviceChange(callback, user_data);
+}
+
+int32_t AudioInputResource::Open0_2(
+ PP_Resource device_ref,
+ PP_Resource config,
+ PPB_AudioInput_Callback_0_2 audio_input_callback_0_2,
+ void* user_data,
+ scoped_refptr<TrackedCallback> callback) {
+ return CommonOpen(device_ref, config, audio_input_callback_0_2, NULL,
+ user_data, callback);
+}
+
+int32_t AudioInputResource::Open(PP_Resource device_ref,
+ PP_Resource config,
+ PPB_AudioInput_Callback audio_input_callback,
+ void* user_data,
+ scoped_refptr<TrackedCallback> callback) {
+ return CommonOpen(device_ref, config, NULL, audio_input_callback, user_data,
+ callback);
+}
+
+PP_Resource AudioInputResource::GetCurrentConfig() {
+ // AddRef for the caller.
+ if (config_.get())
+ PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(config_);
+ return config_;
+}
+
+PP_Bool AudioInputResource::StartCapture() {
+ if (open_state_ == CLOSED || (open_state_ == BEFORE_OPEN &&
+ !TrackedCallback::IsPending(open_callback_))) {
+ return PP_FALSE;
+ }
+ if (capturing_)
+ return PP_TRUE;
+
+ capturing_ = true;
+ // Return directly if the audio input device hasn't been opened. Capturing
+ // will be started once the open operation is completed.
+ if (open_state_ == BEFORE_OPEN)
+ return PP_TRUE;
+
+ StartThread();
+
+ Post(RENDERER, PpapiHostMsg_AudioInput_StartOrStop(true));
+ return PP_TRUE;
+}
+
+PP_Bool AudioInputResource::StopCapture() {
+ if (open_state_ == CLOSED)
+ return PP_FALSE;
+ if (!capturing_)
+ return PP_TRUE;
+
+ // If the audio input device hasn't been opened, set |capturing_| to false and
+ // return directly.
+ if (open_state_ == BEFORE_OPEN) {
+ capturing_ = false;
+ return PP_TRUE;
+ }
+
+ Post(RENDERER, PpapiHostMsg_AudioInput_StartOrStop(false));
+
+ StopThread();
+ capturing_ = false;
+
+ return PP_TRUE;
+}
+
+void AudioInputResource::Close() {
+ if (open_state_ == CLOSED)
+ return;
+
+ open_state_ = CLOSED;
+ Post(RENDERER, PpapiHostMsg_AudioInput_Close());
+ StopThread();
+
+ if (TrackedCallback::IsPending(open_callback_))
+ open_callback_->PostAbort();
+}
+
+void AudioInputResource::LastPluginRefWasDeleted() {
+ enumeration_helper_.LastPluginRefWasDeleted();
+}
+
+void AudioInputResource::OnPluginMsgOpenReply(
+ const ResourceMessageReplyParams& params) {
+ if (open_state_ == BEFORE_OPEN && params.result() == PP_OK) {
+ IPC::PlatformFileForTransit socket_handle_for_transit =
+ IPC::InvalidPlatformFileForTransit();
+ params.TakeSocketHandleAtIndex(0, &socket_handle_for_transit);
+ base::SyncSocket::Handle socket_handle =
+ IPC::PlatformFileForTransitToPlatformFile(socket_handle_for_transit);
+ CHECK(socket_handle != base::SyncSocket::kInvalidHandle);
+
+ SerializedHandle serialized_shared_memory_handle =
+ params.TakeHandleOfTypeAtIndex(1, SerializedHandle::SHARED_MEMORY);
+ CHECK(serialized_shared_memory_handle.IsHandleValid());
+
+ // See the comment in pepper_audio_input_host.cc about how we must call
+ // TotalSharedMemorySizeInBytes to get the actual size of the buffer. Here,
+ // we must call PacketSizeInBytes to get back the size of the audio buffer,
+ // excluding the bytes that audio uses for book-keeping.
+ size_t shared_memory_size = media::PacketSizeInBytes(
+ serialized_shared_memory_handle.size());
+
+ open_state_ = OPENED;
+ SetStreamInfo(serialized_shared_memory_handle.shmem(), shared_memory_size,
+ socket_handle);
+ } else {
+ capturing_ = false;
+ }
+
+ // The callback may have been aborted by Close().
+ if (TrackedCallback::IsPending(open_callback_))
+ open_callback_->Run(params.result());
+}
+
+void AudioInputResource::SetStreamInfo(
+ base::SharedMemoryHandle shared_memory_handle,
+ size_t shared_memory_size,
+ base::SyncSocket::Handle socket_handle) {
+ socket_.reset(new base::CancelableSyncSocket(socket_handle));
+ shared_memory_.reset(new base::SharedMemory(shared_memory_handle, false));
+ shared_memory_size_ = shared_memory_size;
+
+ if (!shared_memory_->Map(shared_memory_size_)) {
+ PpapiGlobals::Get()->LogWithSource(
+ pp_instance(),
+ PP_LOGLEVEL_WARNING,
+ std::string(),
+ "Failed to map shared memory for PPB_AudioInput_Shared.");
+ }
+
+ // There is a pending capture request before SetStreamInfo().
+ if (capturing_) {
+ // Set |capturing_| to false so that the state looks consistent to
+ // StartCapture(), which will reset it to true.
+ capturing_ = false;
+ StartCapture();
+ }
+}
+
+void AudioInputResource::StartThread() {
+ // Don't start the thread unless all our state is set up correctly.
+ if ((!audio_input_callback_0_2_ && !audio_input_callback_) ||
+ !socket_.get() || !capturing_ || !shared_memory_->memory()) {
+ return;
+ }
+ DCHECK(!audio_input_thread_.get());
+ audio_input_thread_.reset(new base::DelegateSimpleThread(
+ this, "plugin_audio_input_thread"));
+ audio_input_thread_->Start();
+}
+
+void AudioInputResource::StopThread() {
+ // Shut down the socket to escape any hanging |Receive|s.
+ if (socket_.get())
+ socket_->Shutdown();
+ if (audio_input_thread_.get()) {
+ audio_input_thread_->Join();
+ audio_input_thread_.reset();
+ }
+}
+
+void AudioInputResource::Run() {
+ // The shared memory represents AudioInputBufferParameters and the actual data
+ // buffer.
+ media::AudioInputBuffer* buffer =
+ static_cast<media::AudioInputBuffer*>(shared_memory_->memory());
+ uint32_t data_buffer_size =
+ shared_memory_size_ - sizeof(media::AudioInputBufferParameters);
+ int pending_data;
+
+ while (sizeof(pending_data) == socket_->Receive(&pending_data,
+ sizeof(pending_data)) &&
+ pending_data >= 0) {
+ // While closing the stream, we may receive buffers whose size is different
+ // from |data_buffer_size|.
+ CHECK_LE(buffer->params.size, data_buffer_size);
+ if (buffer->params.size > 0) {
+ if (audio_input_callback_) {
+ PP_TimeDelta latency =
+ static_cast<double>(pending_data) / bytes_per_second_;
+ audio_input_callback_(&buffer->audio[0], buffer->params.size, latency,
+ user_data_);
+ } else {
+ audio_input_callback_0_2_(&buffer->audio[0], buffer->params.size,
+ user_data_);
+ }
+ }
+ }
+}
+
+int32_t AudioInputResource::CommonOpen(
+ PP_Resource device_ref,
+ PP_Resource config,
+ PPB_AudioInput_Callback_0_2 audio_input_callback_0_2,
+ PPB_AudioInput_Callback audio_input_callback,
+ void* user_data,
+ scoped_refptr<TrackedCallback> callback) {
+ std::string device_id;
+ // |device_id| remains empty if |device_ref| is 0, which means the default
+ // device.
+ if (device_ref != 0) {
+ thunk::EnterResourceNoLock<thunk::PPB_DeviceRef_API> enter_device_ref(
+ device_ref, true);
+ if (enter_device_ref.failed())
+ return PP_ERROR_BADRESOURCE;
+ device_id = enter_device_ref.object()->GetDeviceRefData().id;
+ }
+
+ if (TrackedCallback::IsPending(open_callback_))
+ return PP_ERROR_INPROGRESS;
+ if (open_state_ != BEFORE_OPEN)
+ return PP_ERROR_FAILED;
+
+ if (!audio_input_callback_0_2 && !audio_input_callback)
+ return PP_ERROR_BADARGUMENT;
+ thunk::EnterResourceNoLock<thunk::PPB_AudioConfig_API> enter_config(config,
+ true);
+ if (enter_config.failed())
+ return PP_ERROR_BADARGUMENT;
+
+ config_ = config;
+ audio_input_callback_0_2_ = audio_input_callback_0_2;
+ audio_input_callback_ = audio_input_callback;
+ user_data_ = user_data;
+ open_callback_ = callback;
+ bytes_per_second_ = kAudioInputChannels * (kBitsPerAudioInputSample / 8) *
+ enter_config.object()->GetSampleRate();
+
+ PpapiHostMsg_AudioInput_Open msg(
+ device_id, enter_config.object()->GetSampleRate(),
+ enter_config.object()->GetSampleFrameCount());
+ Call<PpapiPluginMsg_AudioInput_OpenReply>(
+ RENDERER, msg,
+ base::Bind(&AudioInputResource::OnPluginMsgOpenReply,
+ base::Unretained(this)));
+ return PP_OK_COMPLETIONPENDING;
+}
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/audio_input_resource.h b/chromium/ppapi/proxy/audio_input_resource.h
new file mode 100644
index 00000000000..84785d08052
--- /dev/null
+++ b/chromium/ppapi/proxy/audio_input_resource.h
@@ -0,0 +1,145 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_AUDIO_INPUT_RESOURCE_H_
+#define PPAPI_PROXY_AUDIO_INPUT_RESOURCE_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/shared_memory.h"
+#include "base/sync_socket.h"
+#include "base/threading/simple_thread.h"
+#include "ppapi/proxy/device_enumeration_resource_helper.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/shared_impl/scoped_pp_resource.h"
+#include "ppapi/thunk/ppb_audio_input_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class ResourceMessageReplyParams;
+
+class AudioInputResource : public PluginResource,
+ public thunk::PPB_AudioInput_API,
+ public base::DelegateSimpleThread::Delegate {
+ public:
+ AudioInputResource(Connection connection, PP_Instance instance);
+ virtual ~AudioInputResource();
+
+ // Resource overrides.
+ virtual thunk::PPB_AudioInput_API* AsPPB_AudioInput_API() OVERRIDE;
+ virtual void OnReplyReceived(const ResourceMessageReplyParams& params,
+ const IPC::Message& msg) OVERRIDE;
+
+ // PPB_AudioInput_API implementation.
+ virtual int32_t EnumerateDevices0_2(
+ PP_Resource* devices,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t EnumerateDevices(
+ const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t MonitorDeviceChange(
+ PP_MonitorDeviceChangeCallback callback,
+ void* user_data) OVERRIDE;
+ virtual int32_t Open0_2(PP_Resource device_ref,
+ PP_Resource config,
+ PPB_AudioInput_Callback_0_2 audio_input_callback_0_2,
+ void* user_data,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Open(PP_Resource device_ref,
+ PP_Resource config,
+ PPB_AudioInput_Callback audio_input_callback,
+ void* user_data,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual PP_Resource GetCurrentConfig() OVERRIDE;
+ virtual PP_Bool StartCapture() OVERRIDE;
+ virtual PP_Bool StopCapture() OVERRIDE;
+ virtual void Close() OVERRIDE;
+
+ protected:
+ // Resource override.
+ virtual void LastPluginRefWasDeleted() OVERRIDE;
+
+ private:
+ enum OpenState {
+ BEFORE_OPEN,
+ OPENED,
+ CLOSED
+ };
+
+ void OnPluginMsgOpenReply(const ResourceMessageReplyParams& params);
+
+ // Sets the shared memory and socket handles. This will automatically start
+ // capture if we're currently set to capture.
+ void SetStreamInfo(base::SharedMemoryHandle shared_memory_handle,
+ size_t shared_memory_size,
+ base::SyncSocket::Handle socket_handle);
+
+ // Starts execution of the audio input thread.
+ void StartThread();
+
+ // Stops execution of the audio input thread.
+ void StopThread();
+
+ // DelegateSimpleThread::Delegate implementation.
+ // Run on the audio input thread.
+ virtual void Run() OVERRIDE;
+
+ int32_t CommonOpen(PP_Resource device_ref,
+ PP_Resource config,
+ PPB_AudioInput_Callback_0_2 audio_input_callback_0_2,
+ PPB_AudioInput_Callback audio_input_callback,
+ void* user_data,
+ scoped_refptr<TrackedCallback> callback);
+
+ OpenState open_state_;
+
+ // True if capturing the stream.
+ bool capturing_;
+
+ // Socket used to notify us when new samples are available. This pointer is
+ // created in SetStreamInfo().
+ scoped_ptr<base::CancelableSyncSocket> socket_;
+
+ // Sample buffer in shared memory. This pointer is created in
+ // SetStreamInfo(). The memory is only mapped when the audio thread is
+ // created.
+ scoped_ptr<base::SharedMemory> shared_memory_;
+
+ // The size of the sample buffer in bytes.
+ size_t shared_memory_size_;
+
+ // When the callback is set, this thread is spawned for calling it.
+ scoped_ptr<base::DelegateSimpleThread> audio_input_thread_;
+
+ // Callback to call when new samples are available.
+ PPB_AudioInput_Callback_0_2 audio_input_callback_0_2_;
+ PPB_AudioInput_Callback audio_input_callback_;
+
+ // User data pointer passed verbatim to the callback function.
+ void* user_data_;
+
+ // The callback is not directly passed to OnPluginMsgOpenReply() because we
+ // would like to be able to cancel it early in Close().
+ scoped_refptr<TrackedCallback> open_callback_;
+
+ // Owning reference to the current config object. This isn't actually used,
+ // we just dish it out as requested by the plugin.
+ ScopedPPResource config_;
+
+ DeviceEnumerationResourceHelper enumeration_helper_;
+
+ // The data size (in bytes) of one second of audio input. Used to calculate
+ // latency.
+ size_t bytes_per_second_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioInputResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_AUDIO_INPUT_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/broker_dispatcher.cc b/chromium/ppapi/proxy/broker_dispatcher.cc
new file mode 100644
index 00000000000..7187852ba26
--- /dev/null
+++ b/chromium/ppapi/proxy/broker_dispatcher.cc
@@ -0,0 +1,99 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/broker_dispatcher.h"
+
+#include "base/sync_socket.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/platform_file.h"
+
+namespace ppapi {
+namespace proxy {
+
+BrokerDispatcher::BrokerDispatcher(PP_ConnectInstance_Func connect_instance)
+ : connect_instance_(connect_instance) {
+}
+
+BrokerDispatcher::~BrokerDispatcher() {
+}
+
+bool BrokerDispatcher::InitBrokerWithChannel(
+ ProxyChannel::Delegate* delegate,
+ base::ProcessId peer_pid,
+ const IPC::ChannelHandle& channel_handle,
+ bool is_client) {
+ return ProxyChannel::InitWithChannel(delegate, peer_pid, 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) {
+ if (handle == IPC::InvalidPlatformFileForTransit()) {
+ *result = PP_ERROR_FAILED;
+ } else {
+ base::SyncSocket::Handle socket_handle =
+ IPC::PlatformFileForTransitToPlatformFile(handle);
+
+ if (connect_instance_) {
+ *result = connect_instance_(instance,
+ ppapi::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);
+ }
+ }
+}
+
+BrokerHostDispatcher::BrokerHostDispatcher()
+ : BrokerDispatcher(NULL) {
+}
+
+void BrokerHostDispatcher::OnChannelError() {
+ DVLOG(1) << "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(
+ PP_ConnectInstance_Func connect_instance)
+ : BrokerDispatcher(connect_instance) {
+}
+
+void BrokerSideDispatcher::OnChannelError() {
+ DVLOG(1) << "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 ppapi
diff --git a/chromium/ppapi/proxy/broker_dispatcher.h b/chromium/ppapi/proxy/broker_dispatcher.h
new file mode 100644
index 00000000000..2da4a472ced
--- /dev/null
+++ b/chromium/ppapi/proxy/broker_dispatcher.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_BROKER_DISPATCHER_H_
+#define PPAPI_PROXY_BROKER_DISPATCHER_H_
+
+#include "base/compiler_specific.h"
+#include "ppapi/c/trusted/ppp_broker.h"
+#include "ppapi/proxy/proxy_channel.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT 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,
+ base::ProcessId peer_pid,
+ const IPC::ChannelHandle& channel_handle,
+ bool is_client);
+
+ // IPC::Listener implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+
+ protected:
+ // You must call InitBrokerWithChannel after the constructor.
+ explicit BrokerDispatcher(PP_ConnectInstance_Func connect_instance);
+
+ void OnMsgConnectToPlugin(PP_Instance instance,
+ IPC::PlatformFileForTransit handle,
+ int32_t* result);
+
+ PP_ConnectInstance_Func connect_instance_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BrokerDispatcher);
+};
+
+// The dispatcher for the browser side of the broker channel.
+class PPAPI_PROXY_EXPORT BrokerHostDispatcher : public BrokerDispatcher {
+ public:
+ BrokerHostDispatcher();
+
+ // IPC::Listener implementation.
+ virtual void OnChannelError() OVERRIDE;
+};
+
+// The dispatcher for the broker side of the broker channel.
+class PPAPI_PROXY_EXPORT BrokerSideDispatcher : public BrokerDispatcher {
+ public:
+ explicit BrokerSideDispatcher(PP_ConnectInstance_Func connect_instance);
+
+ // IPC::Listener implementation.
+ virtual void OnChannelError() OVERRIDE;
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_BROKER_DISPATCHER_H_
diff --git a/chromium/ppapi/proxy/broker_resource.cc b/chromium/ppapi/proxy/broker_resource.cc
new file mode 100644
index 00000000000..4fac07e54c3
--- /dev/null
+++ b/chromium/ppapi/proxy/broker_resource.cc
@@ -0,0 +1,32 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/broker_resource.h"
+
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace ppapi {
+namespace proxy {
+
+BrokerResource::BrokerResource(Connection connection, PP_Instance instance)
+ : PluginResource(connection, instance) {
+ SendCreate(BROWSER, PpapiHostMsg_Broker_Create());
+}
+
+BrokerResource::~BrokerResource() {
+}
+
+thunk::PPB_Broker_Instance_API* BrokerResource::AsPPB_Broker_Instance_API() {
+ return this;
+}
+
+PP_Bool BrokerResource::IsAllowed() {
+ int32_t result =
+ SyncCall<IPC::Message>(BROWSER, PpapiHostMsg_Broker_IsAllowed());
+ return PP_FromBool(result == PP_OK);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/broker_resource.h b/chromium/ppapi/proxy/broker_resource.h
new file mode 100644
index 00000000000..48d804174e3
--- /dev/null
+++ b/chromium/ppapi/proxy/broker_resource.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_BROKER_RESOURCE_H_
+#define PPAPI_PROXY_BROKER_RESOURCE_H_
+
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/thunk/ppb_broker_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class BrokerResource
+ : public PluginResource,
+ public thunk::PPB_Broker_Instance_API {
+ public:
+ BrokerResource(Connection connection, PP_Instance instance);
+ virtual ~BrokerResource();
+
+ // Resource override.
+ virtual thunk::PPB_Broker_Instance_API* AsPPB_Broker_Instance_API() OVERRIDE;
+
+ // thunk::PPB_Broker_Instance_API implementation.
+ virtual PP_Bool IsAllowed() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BrokerResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_BROKER_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/browser_font_singleton_resource.cc b/chromium/ppapi/proxy/browser_font_singleton_resource.cc
new file mode 100644
index 00000000000..0805126d2ca
--- /dev/null
+++ b/chromium/ppapi/proxy/browser_font_singleton_resource.cc
@@ -0,0 +1,38 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/browser_font_singleton_resource.h"
+
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+namespace proxy {
+
+BrowserFontSingletonResource::BrowserFontSingletonResource(
+ Connection connection,
+ PP_Instance instance)
+ : PluginResource(connection, instance) {
+ SendCreate(BROWSER, PpapiHostMsg_BrowserFontSingleton_Create());
+}
+
+BrowserFontSingletonResource::~BrowserFontSingletonResource() {
+}
+
+thunk::PPB_BrowserFont_Singleton_API*
+BrowserFontSingletonResource::AsPPB_BrowserFont_Singleton_API() {
+ return this;
+}
+
+PP_Var BrowserFontSingletonResource::GetFontFamilies(PP_Instance instance) {
+ if (families_.empty()) {
+ SyncCall<PpapiPluginMsg_BrowserFontSingleton_GetFontFamiliesReply>(
+ BROWSER, PpapiHostMsg_BrowserFontSingleton_GetFontFamilies(),
+ &families_);
+ }
+ return StringVar::StringToPPVar(families_);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/browser_font_singleton_resource.h b/chromium/ppapi/proxy/browser_font_singleton_resource.h
new file mode 100644
index 00000000000..50b88dcbb29
--- /dev/null
+++ b/chromium/ppapi/proxy/browser_font_singleton_resource.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_BROWSER_FONT_SINGLETON_RESOURCE_H_
+#define PPAPI_PROXY_BROWSER_FONT_SINGLETON_RESOURCE_H_
+
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/thunk/ppb_browser_font_singleton_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+// This handles the singleton calls (that don't take a PP_Resource parameter)
+// on the browser font interface
+class BrowserFontSingletonResource
+ : public PluginResource,
+ public thunk::PPB_BrowserFont_Singleton_API {
+ public:
+ BrowserFontSingletonResource(Connection connection, PP_Instance instance);
+ virtual ~BrowserFontSingletonResource();
+
+ // Resource override.
+ virtual thunk::PPB_BrowserFont_Singleton_API*
+ AsPPB_BrowserFont_Singleton_API() OVERRIDE;
+
+ // thunk::PPB_BrowserFontSingleton_API implementation.
+ virtual PP_Var GetFontFamilies(PP_Instance instance) OVERRIDE;
+
+ private:
+ // Lazily-filled-in list of font families.
+ std::string families_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserFontSingletonResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_BROWSER_FONT_SINGLETON_RESOURCE_H_
+
diff --git a/chromium/ppapi/proxy/connection.h b/chromium/ppapi/proxy/connection.h
new file mode 100644
index 00000000000..13cbbc6fcf4
--- /dev/null
+++ b/chromium/ppapi/proxy/connection.h
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_CONNECTION_H_
+#define PPAPI_PROXY_CONNECTION_H_
+
+#include "ipc/ipc_message.h"
+
+namespace IPC {
+class Sender;
+}
+
+namespace ppapi {
+namespace proxy {
+
+// This struct holds the channels that a resource uses to send message to the
+// browser and renderer.
+struct Connection {
+ Connection() : browser_sender(0),
+ renderer_sender(0),
+ in_process(false),
+ browser_sender_routing_id(MSG_ROUTING_NONE) {
+ }
+ Connection(IPC::Sender* browser, IPC::Sender* renderer)
+ : browser_sender(browser),
+ renderer_sender(renderer),
+ in_process(false),
+ browser_sender_routing_id(MSG_ROUTING_NONE) {
+ }
+ Connection(IPC::Sender* browser, IPC::Sender* renderer, int routing_id)
+ : browser_sender(browser),
+ renderer_sender(renderer),
+ in_process(true),
+ browser_sender_routing_id(routing_id) {
+ }
+
+ IPC::Sender* browser_sender;
+ IPC::Sender* renderer_sender;
+ bool in_process;
+ // We need to use a routing ID when a plugin is in-process, and messages are
+ // sent back from the browser to the renderer. This is so that messages are
+ // routed to the proper RenderViewImpl.
+ int browser_sender_routing_id;
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+
+#endif // PPAPI_PROXY_CONNECTION_H_
+
diff --git a/chromium/ppapi/proxy/content_decryptor_private_serializer.h b/chromium/ppapi/proxy/content_decryptor_private_serializer.h
new file mode 100644
index 00000000000..249b01cace3
--- /dev/null
+++ b/chromium/ppapi/proxy/content_decryptor_private_serializer.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_CONTENT_DECRYPTOR_PRIVATE_SERIALIZER_H_
+#define PPAPI_PROXY_CONTENT_DECRYPTOR_PRIVATE_SERIALIZER_H_
+
+#include <cstring>
+#include <string>
+
+#include "ppapi/c/private/pp_content_decryptor.h"
+
+namespace ppapi {
+namespace proxy {
+
+// Serialization/deserialization utility functions for storing/extracting
+// PP_DecryptedBlockInfo, PP_EncryptedBlockInfo, and PP_DecompressedFrameInfo
+// structs within std::string's for passing through IPC. Both functions return
+// true upon success, and false upon failure.
+//
+// Note, these functions check the size of |block_info| against the size of
+// the "serialized" data stored within |serialized_block_info|, and will report
+// failure if expectations are not met. Use of CHECK/DCHECK has been avoided
+// because the functions are intended for use on both sides of the IPC proxy.
+
+template <typename T>
+bool SerializeBlockInfo(const T& block_info,
+ std::string* serialized_block_info) {
+ if (!serialized_block_info)
+ return false;
+
+ serialized_block_info->assign(reinterpret_cast<const char*>(&block_info),
+ sizeof(block_info));
+
+ if (serialized_block_info->size() != sizeof(block_info))
+ return false;
+
+ return true;
+}
+
+template <typename T>
+bool DeserializeBlockInfo(const std::string& serialized_block_info,
+ T* block_info) {
+ if (!block_info)
+ return false;
+
+ if (serialized_block_info.size() != sizeof(*block_info))
+ return false;
+
+ std::memcpy(block_info, serialized_block_info.data(), sizeof(*block_info));
+ return true;
+}
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_CONTENT_DECRYPTOR_PRIVATE_SERIALIZER_H_
diff --git a/chromium/ppapi/proxy/device_enumeration_resource_helper.cc b/chromium/ppapi/proxy/device_enumeration_resource_helper.cc
new file mode 100644
index 00000000000..e8d63e1dbdf
--- /dev/null
+++ b/chromium/ppapi/proxy/device_enumeration_resource_helper.cc
@@ -0,0 +1,223 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/device_enumeration_resource_helper.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_message_macros.h"
+#include "ppapi/c/pp_array_output.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/dispatch_reply_message.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/resource_message_params.h"
+#include "ppapi/shared_impl/array_writer.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/ppb_device_ref_shared.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/resource_tracker.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+
+namespace ppapi {
+namespace proxy {
+
+DeviceEnumerationResourceHelper::DeviceEnumerationResourceHelper(
+ PluginResource* owner)
+ : owner_(owner),
+ pending_enumerate_devices_(false),
+ monitor_callback_id_(0),
+ monitor_user_data_(NULL) {
+}
+
+DeviceEnumerationResourceHelper::~DeviceEnumerationResourceHelper() {
+}
+
+int32_t DeviceEnumerationResourceHelper::EnumerateDevices0_2(
+ PP_Resource* devices,
+ scoped_refptr<TrackedCallback> callback) {
+ if (pending_enumerate_devices_)
+ return PP_ERROR_INPROGRESS;
+ if (!devices)
+ return PP_ERROR_BADARGUMENT;
+
+ pending_enumerate_devices_ = true;
+ PpapiHostMsg_DeviceEnumeration_EnumerateDevices msg;
+ owner_->Call<PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply>(
+ PluginResource::RENDERER, msg,
+ base::Bind(
+ &DeviceEnumerationResourceHelper::OnPluginMsgEnumerateDevicesReply0_2,
+ AsWeakPtr(), devices, callback));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t DeviceEnumerationResourceHelper::EnumerateDevices(
+ const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback) {
+ if (pending_enumerate_devices_)
+ return PP_ERROR_INPROGRESS;
+
+ pending_enumerate_devices_ = true;
+ PpapiHostMsg_DeviceEnumeration_EnumerateDevices msg;
+ owner_->Call<PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply>(
+ PluginResource::RENDERER, msg,
+ base::Bind(
+ &DeviceEnumerationResourceHelper::OnPluginMsgEnumerateDevicesReply,
+ AsWeakPtr(), output, callback));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t DeviceEnumerationResourceHelper::EnumerateDevicesSync(
+ const PP_ArrayOutput& output) {
+ std::vector<DeviceRefData> devices;
+ int32_t result =
+ owner_->SyncCall<PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply>(
+ PluginResource::RENDERER,
+ PpapiHostMsg_DeviceEnumeration_EnumerateDevices(),
+ &devices);
+
+ if (result == PP_OK)
+ result = WriteToArrayOutput(devices, output);
+
+ return result;
+}
+
+int32_t DeviceEnumerationResourceHelper::MonitorDeviceChange(
+ PP_MonitorDeviceChangeCallback callback,
+ void* user_data) {
+ monitor_callback_id_++;
+ monitor_user_data_ = user_data;
+ if (callback) {
+ monitor_callback_.reset(
+ ThreadAwareCallback<PP_MonitorDeviceChangeCallback>::Create(callback));
+ if (!monitor_callback_.get())
+ return PP_ERROR_NO_MESSAGE_LOOP;
+
+ owner_->Post(PluginResource::RENDERER,
+ PpapiHostMsg_DeviceEnumeration_MonitorDeviceChange(
+ monitor_callback_id_));
+ } else {
+ monitor_callback_.reset(NULL);
+
+ owner_->Post(PluginResource::RENDERER,
+ PpapiHostMsg_DeviceEnumeration_StopMonitoringDeviceChange());
+ }
+ return PP_OK;
+}
+
+bool DeviceEnumerationResourceHelper::HandleReply(
+ const ResourceMessageReplyParams& params,
+ const IPC::Message& msg) {
+ IPC_BEGIN_MESSAGE_MAP(DeviceEnumerationResourceHelper, msg)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
+ PpapiPluginMsg_DeviceEnumeration_NotifyDeviceChange,
+ OnPluginMsgNotifyDeviceChange)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(return false)
+ IPC_END_MESSAGE_MAP()
+
+ return true;
+}
+
+void DeviceEnumerationResourceHelper::LastPluginRefWasDeleted() {
+ // Make sure that no further notifications are sent to the plugin.
+ monitor_callback_id_++;
+ monitor_callback_.reset(NULL);
+ monitor_user_data_ = NULL;
+
+ // There is no need to do anything with pending callback of
+ // EnumerateDevices(), because OnPluginMsgEnumerateDevicesReply*() will handle
+ // that properly.
+}
+
+void DeviceEnumerationResourceHelper::OnPluginMsgEnumerateDevicesReply0_2(
+ PP_Resource* devices_resource,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const std::vector<DeviceRefData>& devices) {
+ pending_enumerate_devices_ = false;
+
+ // We shouldn't access |devices_resource| if the callback has been called,
+ // which is possible if the last plugin reference to the corresponding
+ // resource has gone away, and the callback has been aborted.
+ if (!TrackedCallback::IsPending(callback))
+ return;
+
+ if (params.result() == PP_OK) {
+ *devices_resource = PPB_DeviceRef_Shared::CreateResourceArray(
+ OBJECT_IS_PROXY, owner_->pp_instance(), devices);
+ }
+
+ callback->Run(params.result());
+}
+
+void DeviceEnumerationResourceHelper::OnPluginMsgEnumerateDevicesReply(
+ const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const std::vector<DeviceRefData>& devices) {
+ pending_enumerate_devices_ = false;
+
+ // We shouldn't access |output| if the callback has been called, which is
+ // possible if the last plugin reference to the corresponding resource has
+ // gone away, and the callback has been aborted.
+ if (!TrackedCallback::IsPending(callback))
+ return;
+
+ int32_t result = params.result();
+ if (result == PP_OK)
+ result = WriteToArrayOutput(devices, output);
+
+ callback->Run(result);
+}
+
+void DeviceEnumerationResourceHelper::OnPluginMsgNotifyDeviceChange(
+ const ResourceMessageReplyParams& /* params */,
+ uint32_t callback_id,
+ const std::vector<DeviceRefData>& devices) {
+ if (monitor_callback_id_ != callback_id) {
+ // A new callback or NULL has been set.
+ return;
+ }
+
+ CHECK(monitor_callback_.get());
+
+ scoped_ptr<PP_Resource[]> elements;
+ uint32_t size = devices.size();
+ if (size > 0) {
+ elements.reset(new PP_Resource[size]);
+ for (size_t index = 0; index < size; ++index) {
+ PPB_DeviceRef_Shared* device_object = new PPB_DeviceRef_Shared(
+ OBJECT_IS_PROXY, owner_->pp_instance(), devices[index]);
+ elements[index] = device_object->GetReference();
+ }
+ }
+
+ monitor_callback_->RunOnTargetThread(monitor_user_data_, size,
+ elements.get());
+ for (size_t index = 0; index < size; ++index)
+ PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(elements[index]);
+}
+
+int32_t DeviceEnumerationResourceHelper::WriteToArrayOutput(
+ const std::vector<DeviceRefData>& devices,
+ const PP_ArrayOutput& output) {
+ ArrayWriter writer(output);
+ if (!writer.is_valid())
+ return PP_ERROR_BADARGUMENT;
+
+ std::vector<scoped_refptr<Resource> > device_resources;
+ for (size_t i = 0; i < devices.size(); ++i) {
+ device_resources.push_back(new PPB_DeviceRef_Shared(
+ OBJECT_IS_PROXY, owner_->pp_instance(), devices[i]));
+ }
+ if (!writer.StoreResourceVector(device_resources))
+ return PP_ERROR_FAILED;
+
+ return PP_OK;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/device_enumeration_resource_helper.h b/chromium/ppapi/proxy/device_enumeration_resource_helper.h
new file mode 100644
index 00000000000..a2574ec6461
--- /dev/null
+++ b/chromium/ppapi/proxy/device_enumeration_resource_helper.h
@@ -0,0 +1,88 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_DEVICE_ENUMERATION_RESOURCE_HELPER_H_
+#define PPAPI_PROXY_DEVICE_ENUMERATION_RESOURCE_HELPER_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "ppapi/c/dev/ppb_device_ref_dev.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/thread_aware_callback.h"
+
+namespace IPC {
+class Message;
+}
+
+struct PP_ArrayOutput;
+
+namespace ppapi {
+
+struct DeviceRefData;
+class TrackedCallback;
+
+namespace proxy {
+
+class PluginResource;
+class ResourceMessageReplyParams;
+
+class PPAPI_PROXY_EXPORT DeviceEnumerationResourceHelper
+ : public base::SupportsWeakPtr<DeviceEnumerationResourceHelper> {
+ public:
+ // |owner| must outlive this object.
+ explicit DeviceEnumerationResourceHelper(PluginResource* owner);
+ ~DeviceEnumerationResourceHelper();
+
+ int32_t EnumerateDevices0_2(PP_Resource* devices,
+ scoped_refptr<TrackedCallback> callback);
+ int32_t EnumerateDevices(const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback);
+ int32_t EnumerateDevicesSync(const PP_ArrayOutput& output);
+ int32_t MonitorDeviceChange(PP_MonitorDeviceChangeCallback callback,
+ void* user_data);
+
+ // Returns true if the message has been handled.
+ bool HandleReply(const ResourceMessageReplyParams& params,
+ const IPC::Message& msg);
+
+ void LastPluginRefWasDeleted();
+
+ private:
+ void OnPluginMsgEnumerateDevicesReply0_2(
+ PP_Resource* devices_resource,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const std::vector<DeviceRefData>& devices);
+ void OnPluginMsgEnumerateDevicesReply(
+ const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const std::vector<DeviceRefData>& devices);
+ void OnPluginMsgNotifyDeviceChange(const ResourceMessageReplyParams& params,
+ uint32_t callback_id,
+ const std::vector<DeviceRefData>& devices);
+
+ int32_t WriteToArrayOutput(const std::vector<DeviceRefData>& devices,
+ const PP_ArrayOutput& output);
+
+ // Not owned by this object.
+ PluginResource* owner_;
+
+ bool pending_enumerate_devices_;
+
+ uint32_t monitor_callback_id_;
+ scoped_ptr<ThreadAwareCallback<PP_MonitorDeviceChangeCallback> >
+ monitor_callback_;
+ void* monitor_user_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceEnumerationResourceHelper);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_DEVICE_ENUMERATION_RESOURCE_HELPER_H_
diff --git a/chromium/ppapi/proxy/device_enumeration_resource_helper_unittest.cc b/chromium/ppapi/proxy/device_enumeration_resource_helper_unittest.cc
new file mode 100644
index 00000000000..56c09d7966c
--- /dev/null
+++ b/chromium/ppapi/proxy/device_enumeration_resource_helper_unittest.cc
@@ -0,0 +1,409 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/device_enumeration_resource_helper.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+#include "ppapi/proxy/ppapi_message_utils.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+#include "ppapi/shared_impl/ppb_device_ref_shared.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_device_ref_api.h"
+#include "ppapi/thunk/thunk.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+typedef PluginProxyTest DeviceEnumerationResourceHelperTest;
+
+Connection GetConnection(PluginProxyTestHarness* harness) {
+ CHECK(harness->GetGlobals()->IsPluginGlobals());
+
+ return Connection(
+ static_cast<PluginGlobals*>(harness->GetGlobals())->GetBrowserSender(),
+ harness->plugin_dispatcher());
+}
+
+bool CompareDeviceRef(PluginVarTracker* var_tracker,
+ PP_Resource resource,
+ const DeviceRefData& expected) {
+ thunk::EnterResourceNoLock<thunk::PPB_DeviceRef_API> enter(resource, true);
+ if (enter.failed())
+ return false;
+
+ if (expected.type != enter.object()->GetType())
+ return false;
+
+ PP_Var name_pp_var = enter.object()->GetName();
+ bool result = false;
+ do {
+ Var* name_var = var_tracker->GetVar(name_pp_var);
+ if (!name_var)
+ break;
+ StringVar* name_string_var = name_var->AsStringVar();
+ if (!name_string_var)
+ break;
+ if (expected.name != name_string_var->value())
+ break;
+
+ result = true;
+ } while (false);
+ var_tracker->ReleaseVar(name_pp_var);
+ return result;
+}
+
+class TestResource : public PluginResource {
+ public:
+ TestResource(Connection connection, PP_Instance instance)
+ : PluginResource(connection, instance),
+ device_enumeration_(this) {
+ }
+
+ virtual ~TestResource() {}
+
+ virtual void OnReplyReceived(const ResourceMessageReplyParams& params,
+ const IPC::Message& msg) OVERRIDE {
+ if (!device_enumeration_.HandleReply(params, msg))
+ PluginResource::OnReplyReceived(params, msg);
+ }
+
+ DeviceEnumerationResourceHelper& device_enumeration() {
+ return device_enumeration_;
+ }
+
+ private:
+ DeviceEnumerationResourceHelper device_enumeration_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestResource);
+};
+
+class TestCallback {
+ public:
+ TestCallback() : called_(false), result_(PP_ERROR_FAILED) {
+ }
+ ~TestCallback() {
+ CHECK(called_);
+ }
+
+ PP_CompletionCallback MakeCompletionCallback() {
+ return PP_MakeCompletionCallback(&CompletionCallbackBody, this);
+ }
+
+ bool called() const { return called_; }
+ int32_t result() const { return result_; }
+
+ private:
+ static void CompletionCallbackBody(void* user_data, int32_t result) {
+ TestCallback* callback = static_cast<TestCallback*>(user_data);
+
+ CHECK(!callback->called_);
+ callback->called_ = true;
+ callback->result_ = result;
+ }
+
+ bool called_;
+ int32_t result_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestCallback);
+};
+
+class TestArrayOutput {
+ public:
+ explicit TestArrayOutput(PluginResourceTracker* resource_tracker)
+ : data_(NULL),
+ count_(0),
+ resource_tracker_(resource_tracker) {
+ }
+
+ ~TestArrayOutput() {
+ if (count_ > 0) {
+ for (size_t i = 0; i < count_; ++i)
+ resource_tracker_->ReleaseResource(data_[i]);
+ delete [] data_;
+ }
+ }
+
+ PP_ArrayOutput MakeArrayOutput() {
+ PP_ArrayOutput array_output = { &GetDataBuffer, this };
+ return array_output;
+ }
+
+ const PP_Resource* data() const { return data_; }
+ uint32_t count() const { return count_; }
+
+ private:
+ static void* GetDataBuffer(void* user_data,
+ uint32_t element_count,
+ uint32_t element_size) {
+ CHECK_EQ(element_size, sizeof(PP_Resource));
+
+ TestArrayOutput* output = static_cast<TestArrayOutput*>(user_data);
+ CHECK(!output->data_);
+
+ output->count_ = element_count;
+ if (element_count > 0)
+ output->data_ = new PP_Resource[element_count];
+ else
+ output->data_ = NULL;
+
+ return output->data_;
+ }
+
+ PP_Resource* data_;
+ uint32_t count_;
+ PluginResourceTracker* resource_tracker_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestArrayOutput);
+};
+
+class TestMonitorDeviceChange {
+ public:
+ explicit TestMonitorDeviceChange(PluginVarTracker* var_tracker)
+ : called_(false),
+ same_as_expected_(false),
+ var_tracker_(var_tracker) {
+ }
+
+ ~TestMonitorDeviceChange() {}
+
+ void SetExpectedResult(const std::vector<DeviceRefData>& expected) {
+ called_ = false;
+ same_as_expected_ = false;
+ expected_ = expected;
+ }
+
+ bool called() const { return called_; }
+
+ bool same_as_expected() const { return same_as_expected_; }
+
+ static void MonitorDeviceChangeCallback(void* user_data,
+ uint32_t device_count,
+ const PP_Resource devices[]) {
+ ProxyAutoLock lock;
+ TestMonitorDeviceChange* helper =
+ static_cast<TestMonitorDeviceChange*>(user_data);
+ CHECK(!helper->called_);
+
+ helper->called_ = true;
+ helper->same_as_expected_ = false;
+ if (device_count != helper->expected_.size())
+ return;
+ for (size_t i = 0; i < device_count; ++i) {
+ if (!CompareDeviceRef(helper->var_tracker_, devices[i],
+ helper->expected_[i])) {
+ return;
+ }
+ }
+ helper->same_as_expected_ = true;
+ }
+
+ private:
+ bool called_;
+ bool same_as_expected_;
+ std::vector<DeviceRefData> expected_;
+ PluginVarTracker* var_tracker_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestMonitorDeviceChange);
+};
+
+} // namespace
+
+TEST_F(DeviceEnumerationResourceHelperTest, EnumerateDevices) {
+ ProxyAutoLock lock;
+
+ scoped_refptr<TestResource> resource(
+ new TestResource(GetConnection(this), pp_instance()));
+ DeviceEnumerationResourceHelper& device_enumeration =
+ resource->device_enumeration();
+
+ TestArrayOutput output(&resource_tracker());
+ TestCallback callback;
+ scoped_refptr<TrackedCallback> tracked_callback(
+ new TrackedCallback(resource.get(), callback.MakeCompletionCallback()));
+ int32_t result = device_enumeration.EnumerateDevices(output.MakeArrayOutput(),
+ tracked_callback);
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
+
+ // Should have sent an EnumerateDevices message.
+ ResourceMessageCallParams params;
+ IPC::Message msg;
+ ASSERT_TRUE(sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_DeviceEnumeration_EnumerateDevices::ID, &params, &msg));
+
+ // Synthesize a response.
+ ResourceMessageReplyParams reply_params(params.pp_resource(),
+ params.sequence());
+ reply_params.set_result(PP_OK);
+ std::vector<DeviceRefData> data;
+ DeviceRefData data_item;
+ data_item.type = PP_DEVICETYPE_DEV_AUDIOCAPTURE;
+ data_item.name = "name_1";
+ data_item.id = "id_1";
+ data.push_back(data_item);
+ data_item.type = PP_DEVICETYPE_DEV_VIDEOCAPTURE;
+ data_item.name = "name_2";
+ data_item.id = "id_2";
+ data.push_back(data_item);
+
+ {
+ ProxyAutoUnlock unlock;
+ ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(
+ PpapiPluginMsg_ResourceReply(
+ reply_params,
+ PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply(data))));
+ }
+ EXPECT_TRUE(callback.called());
+ EXPECT_EQ(PP_OK, callback.result());
+ EXPECT_EQ(2U, output.count());
+ for (size_t i = 0; i < output.count(); ++i)
+ EXPECT_TRUE(CompareDeviceRef(&var_tracker(), output.data()[i], data[i]));
+}
+
+TEST_F(DeviceEnumerationResourceHelperTest, MonitorDeviceChange) {
+ ProxyAutoLock lock;
+
+ scoped_refptr<TestResource> resource(
+ new TestResource(GetConnection(this), pp_instance()));
+ DeviceEnumerationResourceHelper& device_enumeration =
+ resource->device_enumeration();
+
+ TestMonitorDeviceChange helper(&var_tracker());
+
+ int32_t result = device_enumeration.MonitorDeviceChange(
+ &TestMonitorDeviceChange::MonitorDeviceChangeCallback, &helper);
+ ASSERT_EQ(PP_OK, result);
+
+ // Should have sent a MonitorDeviceChange message.
+ ResourceMessageCallParams params;
+ IPC::Message msg;
+ ASSERT_TRUE(sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_DeviceEnumeration_MonitorDeviceChange::ID, &params, &msg));
+ sink().ClearMessages();
+
+ uint32_t callback_id = 0;
+ ASSERT_TRUE(UnpackMessage<PpapiHostMsg_DeviceEnumeration_MonitorDeviceChange>(
+ msg, &callback_id));
+
+ ResourceMessageReplyParams reply_params(params.pp_resource(), 0);
+ reply_params.set_result(PP_OK);
+ std::vector<DeviceRefData> data;
+
+ helper.SetExpectedResult(data);
+
+ {
+ ProxyAutoUnlock unlock;
+ // Synthesize a response with no device.
+ ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(
+ PpapiPluginMsg_ResourceReply(
+ reply_params,
+ PpapiPluginMsg_DeviceEnumeration_NotifyDeviceChange(
+ callback_id, data))));
+ }
+ EXPECT_TRUE(helper.called() && helper.same_as_expected());
+
+ DeviceRefData data_item;
+ data_item.type = PP_DEVICETYPE_DEV_AUDIOCAPTURE;
+ data_item.name = "name_1";
+ data_item.id = "id_1";
+ data.push_back(data_item);
+ data_item.type = PP_DEVICETYPE_DEV_VIDEOCAPTURE;
+ data_item.name = "name_2";
+ data_item.id = "id_2";
+ data.push_back(data_item);
+
+ helper.SetExpectedResult(data);
+
+ {
+ ProxyAutoUnlock unlock;
+ // Synthesize a response with some devices.
+ ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(
+ PpapiPluginMsg_ResourceReply(
+ reply_params,
+ PpapiPluginMsg_DeviceEnumeration_NotifyDeviceChange(
+ callback_id, data))));
+ }
+ EXPECT_TRUE(helper.called() && helper.same_as_expected());
+
+ TestMonitorDeviceChange helper2(&var_tracker());
+
+ result = device_enumeration.MonitorDeviceChange(
+ &TestMonitorDeviceChange::MonitorDeviceChangeCallback, &helper2);
+ ASSERT_EQ(PP_OK, result);
+
+ // Should have sent another MonitorDeviceChange message.
+ ResourceMessageCallParams params2;
+ IPC::Message msg2;
+ ASSERT_TRUE(sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_DeviceEnumeration_MonitorDeviceChange::ID, &params2, &msg2));
+ sink().ClearMessages();
+
+ uint32_t callback_id2 = 0;
+ ASSERT_TRUE(UnpackMessage<PpapiHostMsg_DeviceEnumeration_MonitorDeviceChange>(
+ msg2, &callback_id2));
+
+ helper.SetExpectedResult(data);
+ helper2.SetExpectedResult(data);
+ {
+ ProxyAutoUnlock unlock;
+ // |helper2| should receive the result while |helper| shouldn't.
+ ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(
+ PpapiPluginMsg_ResourceReply(
+ reply_params,
+ PpapiPluginMsg_DeviceEnumeration_NotifyDeviceChange(
+ callback_id2, data))));
+ }
+ EXPECT_TRUE(helper2.called() && helper2.same_as_expected());
+ EXPECT_FALSE(helper.called());
+
+ helper.SetExpectedResult(data);
+ helper2.SetExpectedResult(data);
+ {
+ ProxyAutoUnlock unlock;
+ // Even if a message with |callback_id| arrives. |helper| shouldn't receive
+ // the result.
+ ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(
+ PpapiPluginMsg_ResourceReply(
+ reply_params,
+ PpapiPluginMsg_DeviceEnumeration_NotifyDeviceChange(
+ callback_id, data))));
+ }
+ EXPECT_FALSE(helper2.called());
+ EXPECT_FALSE(helper.called());
+
+ result = device_enumeration.MonitorDeviceChange(NULL, NULL);
+ ASSERT_EQ(PP_OK, result);
+
+ // Should have sent a StopMonitoringDeviceChange message.
+ ResourceMessageCallParams params3;
+ IPC::Message msg3;
+ ASSERT_TRUE(sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_DeviceEnumeration_StopMonitoringDeviceChange::ID,
+ &params3, &msg3));
+ sink().ClearMessages();
+
+ helper2.SetExpectedResult(data);
+ {
+ ProxyAutoUnlock unlock;
+ // |helper2| shouldn't receive any result any more.
+ ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(
+ PpapiPluginMsg_ResourceReply(
+ reply_params,
+ PpapiPluginMsg_DeviceEnumeration_NotifyDeviceChange(
+ callback_id2, data))));
+ }
+ EXPECT_FALSE(helper2.called());
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/dispatch_reply_message.h b/chromium/ppapi/proxy/dispatch_reply_message.h
new file mode 100644
index 00000000000..a380cdcf97b
--- /dev/null
+++ b/chromium/ppapi/proxy/dispatch_reply_message.h
@@ -0,0 +1,164 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file provides infrastructure for dispatching messasges from host
+// resource, inlcuding reply messages or unsolicited replies. Normal IPC Reply
+// handlers can't take extra parameters. We want to take a
+// ResourceMessageReplyParams as a parameter.
+
+#ifndef PPAPI_PROXY_DISPATCH_REPLY_MESSAGE_H_
+#define PPAPI_PROXY_DISPATCH_REPLY_MESSAGE_H_
+
+#include "base/callback.h"
+#include "base/profiler/scoped_profile.h" // For TRACK_RUN_IN_IPC_HANDLER.
+#include "ipc/ipc_message_macros.h"
+#include "ppapi/c/pp_errors.h"
+
+namespace ppapi {
+namespace proxy {
+
+class ResourceMessageReplyParams;
+
+template <class ObjT, class Method>
+inline void DispatchResourceReply(ObjT* obj, Method method,
+ const ResourceMessageReplyParams& params,
+ const Tuple0& arg) {
+ (obj->*method)(params);
+}
+
+template <class ObjT, class Method, class A>
+inline void DispatchResourceReply(ObjT* obj, Method method,
+ const ResourceMessageReplyParams& params,
+ const Tuple1<A>& arg) {
+ (obj->*method)(params, arg.a);
+}
+
+template<class ObjT, class Method, class A, class B>
+inline void DispatchResourceReply(ObjT* obj, Method method,
+ const ResourceMessageReplyParams& params,
+ const Tuple2<A, B>& arg) {
+ (obj->*method)(params, arg.a, arg.b);
+}
+
+template<class ObjT, class Method, class A, class B, class C>
+inline void DispatchResourceReply(ObjT* obj, Method method,
+ const ResourceMessageReplyParams& params,
+ const Tuple3<A, B, C>& arg) {
+ (obj->*method)(params, arg.a, arg.b, arg.c);
+}
+
+template<class ObjT, class Method, class A, class B, class C, class D>
+inline void DispatchResourceReply(ObjT* obj, Method method,
+ const ResourceMessageReplyParams& params,
+ const Tuple4<A, B, C, D>& arg) {
+ (obj->*method)(params, arg.a, arg.b, arg.c, arg.d);
+}
+
+template<class ObjT, class Method, class A, class B, class C, class D, class E>
+inline void DispatchResourceReply(ObjT* obj, Method method,
+ const ResourceMessageReplyParams& params,
+ const Tuple5<A, B, C, D, E>& arg) {
+ (obj->*method)(params, arg.a, arg.b, arg.c, arg.d, arg.e);
+}
+
+// Used to dispatch resource replies. In most cases, you should not call this
+// function to dispatch a resource reply manually, but instead use
+// |PluginResource::CallBrowser|/|PluginResource::CallRenderer| with a
+// |base::Callback| which will be called when a reply message is received
+// (see plugin_resource.h).
+//
+// This function will call your callback with the nested reply message's
+// parameters on success. On failure, your callback will be called with each
+// parameter having its default constructed value.
+//
+// Resource replies are a bit weird in that the host will automatically
+// generate a reply in error cases (when the call handler returns error rather
+// than returning "completion pending"). This makes it more convenient to write
+// the call message handlers. But this also means that the reply handler has to
+// handle both the success case (when all of the reply message paramaters are
+// specified) and the error case (when the nested reply message is empty).
+// In both cases the resource will want to issue completion callbacks to the
+// plugin.
+//
+// This function handles the error case by calling your reply handler with the
+// default value for each paramater in the error case. In most situations this
+// will be the right thing. You should always dispatch completion callbacks
+// using the result code present in the ResourceMessageReplyParams.
+template<class MsgClass, class ObjT, class Method>
+void DispatchResourceReplyOrDefaultParams(
+ ObjT* obj,
+ Method method,
+ const ResourceMessageReplyParams& reply_params,
+ const IPC::Message& msg) {
+ typename MsgClass::Schema::Param msg_params;
+ // We either expect the nested message type to match, or that there is no
+ // nested message. No nested message indicates a default reply sent from
+ // the host: when the resource message handler returns an error, a reply
+ // is implicitly sent with no nested message.
+ DCHECK(msg.type() == MsgClass::ID || msg.type() == 0)
+ << "Resource reply message of unexpected type.";
+ if (msg.type() == MsgClass::ID && MsgClass::Read(&msg, &msg_params)) {
+ // Message type matches and the parameters were successfully read.
+ DispatchResourceReply(obj, method, reply_params, msg_params);
+ } else {
+ // The nested message is empty because the host handler didn't explicitly
+ // send a reply (likely), or you screwed up and didn't use the correct
+ // message type when calling this function (you should have hit the
+ // assertion above, Einstein).
+ //
+ // Dispatch the reply function with the default parameters. We explicitly
+ // use a new Params() structure since if the Read failed due to an invalid
+ // message, the params could have been partially filled in.
+ DispatchResourceReply(obj, method, reply_params,
+ typename MsgClass::Schema::Param());
+ }
+}
+
+// Template specialization for |Callback|s that only accept a
+// |ResourceMessageReplyParams|. In this case |msg| shouldn't contain any
+// arguments, so just call the |method| with the |reply_params|.
+template<class MsgClass, class Method>
+void DispatchResourceReplyOrDefaultParams(
+ base::Callback<void(const ResourceMessageReplyParams&)>* obj,
+ Method method,
+ const ResourceMessageReplyParams& reply_params,
+ const IPC::Message& msg) {
+ DCHECK(msg.type() == MsgClass::ID || msg.type() == 0)
+ << "Resource reply message of unexpected type.";
+ (obj->*method)(reply_params);
+}
+
+// Note that this only works for message with 1 or more parameters. For
+// 0-parameter messages you need to use the _0 version below (since there are
+// no params in the message).
+#define PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(msg_class, member_func) \
+ case msg_class::ID: { \
+ msg_class::Schema::Param p; \
+ if (msg_class::Read(&ipc_message__, &p)) { \
+ ppapi::proxy::DispatchResourceReply( \
+ this, \
+ &_IpcMessageHandlerClass::member_func, \
+ params, p); \
+ } else { \
+ NOTREACHED(); \
+ } \
+ break; \
+ }
+
+#define PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_0(msg_class, member_func) \
+ case msg_class::ID: { \
+ member_func(params); \
+ break; \
+ }
+
+#define PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(code) \
+ default: { \
+ code; \
+ } \
+ break;
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_DISPATCH_REPLY_MESSAGE_H_
diff --git a/chromium/ppapi/proxy/dispatcher.cc b/chromium/ppapi/proxy/dispatcher.cc
new file mode 100644
index 00000000000..3b18932447a
--- /dev/null
+++ b/chromium/ppapi/proxy/dispatcher.cc
@@ -0,0 +1,86 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/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/proxy/ppapi_messages.h"
+#include "ppapi/proxy/var_serialization_rules.h"
+
+namespace ppapi {
+namespace proxy {
+
+Dispatcher::Dispatcher(PP_GetInterface_Func local_get_interface,
+ const PpapiPermissions& permissions)
+ : local_get_interface_(local_get_interface),
+ permissions_(permissions) {
+}
+
+Dispatcher::~Dispatcher() {
+}
+
+void Dispatcher::AddFilter(IPC::Listener* listener) {
+ filters_.push_back(listener);
+}
+
+InterfaceProxy* Dispatcher::GetInterfaceProxy(ApiID id) {
+ InterfaceProxy* proxy = proxies_[id].get();
+ if (!proxy) {
+ // Handle the first time for a given API by creating the proxy for it.
+ InterfaceProxy::Factory factory =
+ InterfaceList::GetInstance()->GetFactoryForID(id);
+ if (!factory) {
+ NOTREACHED();
+ return NULL;
+ }
+ proxy = factory(this);
+ DCHECK(proxy);
+ proxies_[id].reset(proxy);
+ }
+ return proxy;
+}
+
+base::MessageLoopProxy* Dispatcher::GetIPCMessageLoop() {
+ return delegate()->GetIPCMessageLoop();
+}
+
+void Dispatcher::AddIOThreadMessageFilter(
+ IPC::ChannelProxy::MessageFilter* filter) {
+ // Our filter is refcounted. The channel will call the destruct method on the
+ // filter when the channel is done with it, so the corresponding Release()
+ // happens there.
+ channel()->AddFilter(filter);
+}
+
+bool Dispatcher::OnMessageReceived(const IPC::Message& msg) {
+ if (msg.routing_id() <= 0 || msg.routing_id() >= API_ID_COUNT) {
+ OnInvalidMessageReceived();
+ return true;
+ }
+
+ InterfaceProxy* proxy = GetInterfaceProxy(
+ static_cast<ApiID>(msg.routing_id()));
+ if (!proxy) {
+ NOTREACHED();
+ return true;
+ }
+ return proxy->OnMessageReceived(msg);
+}
+
+void Dispatcher::SetSerializationRules(
+ VarSerializationRules* var_serialization_rules) {
+ serialization_rules_ = var_serialization_rules;
+}
+
+void Dispatcher::OnInvalidMessageReceived() {
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/dispatcher.h b/chromium/ppapi/proxy/dispatcher.h
new file mode 100644
index 00000000000..7bb2c7ec2a7
--- /dev/null
+++ b/chromium/ppapi/proxy/dispatcher.h
@@ -0,0 +1,124 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_DISPATCHER_H_
+#define PPAPI_PROXY_DISPATCHER_H_
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.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/c/ppp.h"
+#include "ppapi/proxy/proxy_channel.h"
+#include "ppapi/proxy/interface_list.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+#include "ppapi/shared_impl/api_id.h"
+
+namespace ppapi {
+
+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 PPAPI_PROXY_EXPORT Dispatcher : public ProxyChannel {
+ public:
+ 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;
+
+ void AddFilter(IPC::Listener* listener);
+
+ VarSerializationRules* serialization_rules() const {
+ return serialization_rules_.get();
+ }
+
+ // Returns a non-owning pointer to the interface proxy for the given ID, or
+ // NULL if the ID isn't found. This will create the proxy if it hasn't been
+ // created so far.
+ InterfaceProxy* GetInterfaceProxy(ApiID id);
+
+ // 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.
+ 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::Listener implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+
+ PP_GetInterface_Func local_get_interface() const {
+ return local_get_interface_;
+ }
+
+ const PpapiPermissions& permissions() const { return permissions_; }
+
+ protected:
+ explicit Dispatcher(PP_GetInterface_Func local_get_interface,
+ const PpapiPermissions& permissions);
+
+ // Setter for the derived classes to set the appropriate var serialization.
+ // Takes one reference of the given pointer, which must be on the heap.
+ void SetSerializationRules(VarSerializationRules* var_serialization_rules);
+
+ // Called when an invalid message is received from the remote site. The
+ // default implementation does nothing, derived classes can override.
+ virtual void OnInvalidMessageReceived();
+
+ protected:
+ std::vector<IPC::Listener*> filters_;
+
+ private:
+ friend class HostDispatcherTest;
+ friend class PluginDispatcherTest;
+
+ // Lists all lazily-created interface proxies.
+ scoped_ptr<InterfaceProxy> proxies_[API_ID_COUNT];
+
+ bool disallow_trusted_interfaces_;
+
+ PP_GetInterface_Func local_get_interface_;
+
+ scoped_refptr<VarSerializationRules> serialization_rules_;
+
+ PpapiPermissions permissions_;
+
+ DISALLOW_COPY_AND_ASSIGN(Dispatcher);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_DISPATCHER_H_
diff --git a/chromium/ppapi/proxy/enter_proxy.h b/chromium/ppapi/proxy/enter_proxy.h
new file mode 100644
index 00000000000..4ad67b136c3
--- /dev/null
+++ b/chromium/ppapi/proxy/enter_proxy.h
@@ -0,0 +1,204 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_ENTER_PROXY_H_
+#define PPAPI_PROXY_ENTER_PROXY_H_
+
+#include "base/logging.h"
+#include "ppapi/cpp/completion_callback.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/thunk/enter.h"
+
+namespace ppapi {
+
+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 thunk::EnterResourceNoLock<ResourceT> {
+ public:
+ explicit EnterPluginFromHostResource(const HostResource& host_resource)
+ : thunk::EnterResourceNoLock<ResourceT>(
+ PluginGlobals::Get()->plugin_resource_tracker()->
+ 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 thunk::EnterResourceNoLock<ResourceT> {
+ public:
+ explicit EnterHostFromHostResource(const HostResource& host_resource)
+ : 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()));
+ }
+
+ EnterHostFromHostResource(const HostResource& host_resource,
+ const pp::CompletionCallback& callback)
+ : thunk::EnterResourceNoLock<ResourceT>(host_resource.host_resource(),
+ callback.pp_completion_callback(),
+ 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()));
+ }
+};
+
+// Enters a resource and forces a completion callback to be issued.
+//
+// This is used when implementing the host (renderer) side of a resource
+// function that issues a completion callback. In all cases, we need to issue
+// the callback to avoid hanging the plugin.
+//
+// This class automatically constructs a callback with the given factory
+// calling the given method. The method will generally be the one that sends
+// the message to trigger the completion callback in the plugin process.
+//
+// It will automatically issue the callback with PP_ERROR_NOINTERFACE if the
+// host resource is invalid (i.e. failed() is set). In all other cases you
+// should call SetResult(), which will issue the callback immediately if the
+// result value isn't PP_OK_COMPLETIONPENDING. In the "completion pending"
+// case, it's assumed the function the proxy is calling will take responsibility
+// of executing the callback (returned by callback()).
+//
+// Example:
+// EnterHostFromHostResourceForceCallback<PPB_Foo_API> enter(
+// resource, callback_factory_, &MyClass::SendResult, resource);
+// if (enter.failed())
+// return; // SendResult automatically called with PP_ERROR_BADRESOURCE.
+// enter.SetResult(enter.object()->DoFoo(enter.callback()));
+//
+// Where DoFoo's signature looks like this:
+// int32_t DoFoo(PP_CompletionCallback callback);
+// And SendResult's implementation looks like this:
+// void MyClass::SendResult(int32_t result, const HostResource& res) {
+// Send(new FooMsg_FooComplete(..., result, res));
+// }
+template<typename ResourceT>
+class EnterHostFromHostResourceForceCallback
+ : public EnterHostFromHostResource<ResourceT> {
+ public:
+ EnterHostFromHostResourceForceCallback(
+ const HostResource& host_resource,
+ const pp::CompletionCallback& callback)
+ : EnterHostFromHostResource<ResourceT>(host_resource, callback),
+ needs_running_(true) {
+ }
+
+ // For callbacks that take no parameters except the "int32_t result". Most
+ // implementations will use the 1-extra-argument constructor below.
+ template<class CallbackFactory, typename Method>
+ EnterHostFromHostResourceForceCallback(
+ const HostResource& host_resource,
+ CallbackFactory& factory,
+ Method method)
+ : EnterHostFromHostResource<ResourceT>(host_resource,
+ factory.NewOptionalCallback(method)),
+ needs_running_(true) {
+ if (this->failed())
+ RunCallback(PP_ERROR_BADRESOURCE);
+ }
+
+ // For callbacks that take an extra parameter as a closure.
+ template<class CallbackFactory, typename Method, typename A>
+ EnterHostFromHostResourceForceCallback(
+ const HostResource& host_resource,
+ CallbackFactory& factory,
+ Method method,
+ const A& a)
+ : EnterHostFromHostResource<ResourceT>(host_resource,
+ factory.NewOptionalCallback(method, a)),
+ needs_running_(true) {
+ if (this->failed())
+ RunCallback(PP_ERROR_BADRESOURCE);
+ }
+
+ // For callbacks that take two extra parameters as a closure.
+ template<class CallbackFactory, typename Method, typename A, typename B>
+ EnterHostFromHostResourceForceCallback(
+ const HostResource& host_resource,
+ CallbackFactory& factory,
+ Method method,
+ const A& a,
+ const B& b)
+ : EnterHostFromHostResource<ResourceT>(host_resource,
+ factory.NewOptionalCallback(method, a, b)),
+ needs_running_(true) {
+ if (this->failed())
+ RunCallback(PP_ERROR_BADRESOURCE);
+ }
+
+ // For callbacks that take three extra parameters as a closure.
+ template<class CallbackFactory, typename Method, typename A, typename B,
+ typename C>
+ EnterHostFromHostResourceForceCallback(
+ const HostResource& host_resource,
+ CallbackFactory& factory,
+ Method method,
+ const A& a,
+ const B& b,
+ const C& c)
+ : EnterHostFromHostResource<ResourceT>(host_resource,
+ factory.NewOptionalCallback(method, a, b, c)),
+ needs_running_(true) {
+ if (this->failed())
+ RunCallback(PP_ERROR_BADRESOURCE);
+ }
+
+ ~EnterHostFromHostResourceForceCallback() {
+ if (needs_running_) {
+ NOTREACHED() << "Should always call SetResult except in the "
+ "initialization failed case.";
+ RunCallback(PP_ERROR_FAILED);
+ }
+ }
+
+ void SetResult(int32_t result) {
+ DCHECK(needs_running_) << "Don't call SetResult when there already is one.";
+ if (result != PP_OK_COMPLETIONPENDING)
+ RunCallback(result);
+ needs_running_ = false;
+ // Either we already ran the callback, or it will be run asynchronously. We
+ // clear the callback so it isn't accidentally run again (and because
+ // EnterBase checks that the callback has been cleared).
+ this->ClearCallback();
+ }
+
+ private:
+ void RunCallback(int32_t result) {
+ DCHECK(needs_running_);
+ needs_running_ = false;
+ this->callback()->Run(result);
+ this->ClearCallback();
+ }
+
+ bool needs_running_;
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_ENTER_PROXY_H_
diff --git a/chromium/ppapi/proxy/ext_crx_file_system_private_resource.cc b/chromium/ppapi/proxy/ext_crx_file_system_private_resource.cc
new file mode 100644
index 00000000000..f0de598c2de
--- /dev/null
+++ b/chromium/ppapi/proxy/ext_crx_file_system_private_resource.cc
@@ -0,0 +1,80 @@
+// Copyright (c) 2013 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/ext_crx_file_system_private_resource.h"
+
+#include "base/bind.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/resource_message_params.h"
+#include "ppapi/shared_impl/host_resource.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/enter.h"
+
+namespace ppapi {
+namespace proxy {
+
+ExtCrxFileSystemPrivateResource::ExtCrxFileSystemPrivateResource(
+ Connection connection, PP_Instance instance)
+ : PluginResource(connection, instance), called_open_(false) {
+ SendCreate(BROWSER, PpapiHostMsg_Ext_CrxFileSystem_Create());
+}
+
+ExtCrxFileSystemPrivateResource::~ExtCrxFileSystemPrivateResource() {
+}
+
+thunk::PPB_Ext_CrxFileSystem_Private_API*
+ExtCrxFileSystemPrivateResource::AsPPB_Ext_CrxFileSystem_Private_API() {
+ return this;
+}
+
+int32_t ExtCrxFileSystemPrivateResource::Open(
+ PP_Instance /* unused */,
+ PP_Resource* file_system_resource,
+ scoped_refptr<TrackedCallback> callback) {
+ if (called_open_)
+ return PP_ERROR_FAILED;
+ called_open_ = true;
+
+ if (!file_system_resource)
+ return PP_ERROR_BADARGUMENT;
+
+ Call<PpapiPluginMsg_Ext_CrxFileSystem_BrowserOpenReply>(BROWSER,
+ PpapiHostMsg_Ext_CrxFileSystem_BrowserOpen(),
+ base::Bind(&ExtCrxFileSystemPrivateResource::OnBrowserOpenComplete, this,
+ file_system_resource,
+ callback));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void ExtCrxFileSystemPrivateResource::OnBrowserOpenComplete(
+ PP_Resource* file_system_resource,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const std::string& fsid) {
+ if (!TrackedCallback::IsPending(callback))
+ return;
+
+ if (params.result() != PP_OK) {
+ callback->Run(params.result());
+ return;
+ }
+
+ thunk::EnterResourceCreationNoLock enter(pp_instance());
+ if (enter.failed()) {
+ callback->Run(enter.retval());
+ return;
+ }
+
+ *file_system_resource = enter.functions()->CreateIsolatedFileSystem(
+ pp_instance(), fsid.c_str());
+ if (*file_system_resource != 0) {
+ callback->Run(PP_OK);
+ } else {
+ callback->Run(PP_ERROR_FAILED);
+ }
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ext_crx_file_system_private_resource.h b/chromium/ppapi/proxy/ext_crx_file_system_private_resource.h
new file mode 100644
index 00000000000..5f2887a7181
--- /dev/null
+++ b/chromium/ppapi/proxy/ext_crx_file_system_private_resource.h
@@ -0,0 +1,68 @@
+// Copyright (c) 2013 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.
+//
+// CRX filesystem is a filesystem that allows an extension to read its own
+// package directory tree. See ppapi/examples/crxfs for example.
+//
+// IMPLEMENTATION
+//
+// The implementation involves both browser and renderer. In order to provide
+// readonly access to CRX filesystem (i.e. extension directory), we create an
+// "isolated filesystem" pointing to current extension directory in browser.
+// Then browser grants read permission to renderer, and tells plugin the
+// filesystem id, or fsid.
+//
+// Once the plugin receives the fsid, it creates a PPB_FileSystem and forwards
+// the fsid to PepperFileSystemHost in order to construct root url.
+
+#ifndef PPAPI_PROXY_EXT_CRX_FILE_SYSTEM_PRIVATE_RESOURCE_H_
+#define PPAPI_PROXY_EXT_CRX_FILE_SYSTEM_PRIVATE_RESOURCE_H_
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/thunk/ppb_ext_crx_file_system_private_api.h"
+
+namespace ppapi {
+
+class TrackedCallback;
+
+namespace proxy {
+
+class ResourceMessageReplyParams;
+
+class PPAPI_PROXY_EXPORT ExtCrxFileSystemPrivateResource
+ : public PluginResource,
+ public thunk::PPB_Ext_CrxFileSystem_Private_API {
+ public:
+ ExtCrxFileSystemPrivateResource(Connection connection, PP_Instance instance);
+ virtual ~ExtCrxFileSystemPrivateResource();
+
+ // Resource overrides.
+ virtual thunk::PPB_Ext_CrxFileSystem_Private_API*
+ AsPPB_Ext_CrxFileSystem_Private_API() OVERRIDE;
+
+ // PPB_Ext_CrxFileSystem_Private_API implementation.
+ virtual int32_t Open(PP_Instance instance,
+ PP_Resource* file_system_resource,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+
+ private:
+ void OnBrowserOpenComplete(PP_Resource* file_system_resource,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const std::string& fsid);
+
+ bool called_open_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtCrxFileSystemPrivateResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_EXT_CRX_FILE_SYSTEM_PRIVATE_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/extensions_common_resource.cc b/chromium/ppapi/proxy/extensions_common_resource.cc
new file mode 100644
index 00000000000..40d03f97822
--- /dev/null
+++ b/chromium/ppapi/proxy/extensions_common_resource.cc
@@ -0,0 +1,139 @@
+// Copyright (c) 2013 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/extensions_common_resource.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/resource_message_params.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/shared_impl/var_value_conversions.h"
+
+namespace ppapi {
+namespace proxy {
+
+ExtensionsCommonResource::ExtensionsCommonResource(Connection connection,
+ PP_Instance instance)
+ : PluginResource(connection, instance) {
+ SendCreate(RENDERER, PpapiHostMsg_ExtensionsCommon_Create());
+ SendCreate(BROWSER, PpapiHostMsg_ExtensionsCommon_Create());
+}
+
+ExtensionsCommonResource::~ExtensionsCommonResource() {
+}
+
+thunk::ExtensionsCommon_API*
+ExtensionsCommonResource::AsExtensionsCommon_API() {
+ return this;
+}
+
+int32_t ExtensionsCommonResource::CallRenderer(
+ const std::string& request_name,
+ const std::vector<PP_Var>& input_args,
+ const std::vector<PP_Var*>& output_args,
+ scoped_refptr<TrackedCallback> callback) {
+ return CommonCall(RENDERER, request_name, input_args, output_args, callback);
+}
+
+void ExtensionsCommonResource::PostRenderer(const std::string& request_name,
+ const std::vector<PP_Var>& args) {
+ CommonPost(RENDERER, request_name, args);
+}
+
+int32_t ExtensionsCommonResource::CallBrowser(
+ const std::string& request_name,
+ const std::vector<PP_Var>& input_args,
+ const std::vector<PP_Var*>& output_args,
+ scoped_refptr<TrackedCallback> callback) {
+ return CommonCall(BROWSER, request_name, input_args, output_args, callback);
+}
+
+void ExtensionsCommonResource::PostBrowser(const std::string& request_name,
+ const std::vector<PP_Var>& args) {
+ CommonPost(BROWSER, request_name, args);
+}
+
+int32_t ExtensionsCommonResource::CommonCall(
+ Destination dest,
+ const std::string& request_name,
+ const std::vector<PP_Var>& input_args,
+ const std::vector<PP_Var*>& output_args,
+ scoped_refptr<TrackedCallback> callback) {
+ // TODO(yzshen): CreateValueFromVar() doesn't generate null fields for
+ // dictionary values. That is the expected behavior for most APIs. If later we
+ // want to support APIs that require to preserve null fields in dictionaries,
+ // we should change the behavior to always preserve null fields at the plugin
+ // side, and figure out whether they should be stripped at the renderer side.
+ scoped_ptr<base::ListValue> input_args_value(
+ CreateListValueFromVarVector(input_args));
+ if (!input_args_value.get()) {
+ LOG(WARNING) << "Failed to convert PP_Var input arguments.";
+ return PP_ERROR_BADARGUMENT;
+ }
+
+ PluginResource::Call<PpapiPluginMsg_ExtensionsCommon_CallReply>(
+ dest,
+ PpapiHostMsg_ExtensionsCommon_Call(request_name, *input_args_value),
+ base::Bind(&ExtensionsCommonResource::OnPluginMsgCallReply,
+ base::Unretained(this), output_args, callback));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void ExtensionsCommonResource::CommonPost(Destination dest,
+ const std::string& request_name,
+ const std::vector<PP_Var>& args) {
+ scoped_ptr<base::ListValue> args_value(CreateListValueFromVarVector(args));
+ if (!args_value.get()) {
+ LOG(WARNING) << "Failed to convert PP_Var input arguments.";
+ return;
+ }
+
+ PluginResource::Post(
+ dest, PpapiHostMsg_ExtensionsCommon_Post(request_name, *args_value));
+}
+
+void ExtensionsCommonResource::OnPluginMsgCallReply(
+ const std::vector<PP_Var*>& output_args,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const base::ListValue& output) {
+ // |output_args| may be invalid and shouldn't be accessed if the callback has
+ // been called.
+ if (!TrackedCallback::IsPending(callback))
+ return;
+
+ int32_t result = params.result();
+
+ // If the size doesn't match, something must be really wrong.
+ CHECK_EQ(output_args.size(), output.GetSize());
+
+ std::vector<PP_Var> output_vars;
+ if (CreateVarVectorFromListValue(output, &output_vars)) {
+ DCHECK_EQ(output_args.size(), output_vars.size());
+ std::vector<PP_Var>::const_iterator src_iter = output_vars.begin();
+ std::vector<PP_Var*>::const_iterator dest_iter = output_args.begin();
+ for (; src_iter != output_vars.end() && dest_iter != output_args.end();
+ ++src_iter, ++dest_iter) {
+ **dest_iter = *src_iter;
+ }
+ } else {
+ NOTREACHED();
+ result = PP_ERROR_FAILED;
+ for (std::vector<PP_Var*>::const_iterator dest_iter = output_args.begin();
+ dest_iter != output_args.end();
+ ++dest_iter) {
+ **dest_iter = PP_MakeUndefined();
+ }
+ }
+
+ callback->Run(result);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/extensions_common_resource.h b/chromium/ppapi/proxy/extensions_common_resource.h
new file mode 100644
index 00000000000..b3ec366a0d9
--- /dev/null
+++ b/chromium/ppapi/proxy/extensions_common_resource.h
@@ -0,0 +1,68 @@
+// Copyright (c) 2013 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_EXTENSIONS_COMMON_RESOURCE_H_
+#define PPAPI_PROXY_EXTENSIONS_COMMON_RESOURCE_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/thunk/extensions_common_api.h"
+
+namespace base {
+class ListValue;
+}
+
+namespace ppapi {
+namespace proxy {
+
+class ResourceMessageReplyParams;
+
+class ExtensionsCommonResource : public PluginResource,
+ public thunk::ExtensionsCommon_API {
+ public:
+ ExtensionsCommonResource(Connection connection, PP_Instance instance);
+ virtual ~ExtensionsCommonResource();
+
+ // Resource overrides.
+ virtual thunk::ExtensionsCommon_API* AsExtensionsCommon_API() OVERRIDE;
+
+ // ExtensionsCommon_API implementation.
+ virtual int32_t CallRenderer(
+ const std::string& request_name,
+ const std::vector<PP_Var>& input_args,
+ const std::vector<PP_Var*>& output_args,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual void PostRenderer(const std::string& request_name,
+ const std::vector<PP_Var>& args) OVERRIDE;
+ virtual int32_t CallBrowser(const std::string& request_name,
+ const std::vector<PP_Var>& input_args,
+ const std::vector<PP_Var*>& output_args,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual void PostBrowser(const std::string& request_name,
+ const std::vector<PP_Var>& args) OVERRIDE;
+
+ private:
+ int32_t CommonCall(Destination dest,
+ const std::string& request_name,
+ const std::vector<PP_Var>& input_args,
+ const std::vector<PP_Var*>& output_args,
+ scoped_refptr<TrackedCallback> callback);
+ void CommonPost(Destination dest,
+ const std::string& request_name,
+ const std::vector<PP_Var>& args);
+
+ void OnPluginMsgCallReply(const std::vector<PP_Var*>& output_args,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const base::ListValue& output);
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionsCommonResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_EXTENSIONS_COMMON_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/file_chooser_resource.cc b/chromium/ppapi/proxy/file_chooser_resource.cc
new file mode 100644
index 00000000000..ebd545cfc38
--- /dev/null
+++ b/chromium/ppapi/proxy/file_chooser_resource.cc
@@ -0,0 +1,149 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/file_chooser_resource.h"
+
+#include "base/bind.h"
+#include "base/strings/string_split.h"
+#include "ipc/ipc_message.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/dispatch_reply_message.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_file_ref_proxy.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+namespace proxy {
+
+FileChooserResource::FileChooserResource(Connection connection,
+ PP_Instance instance,
+ PP_FileChooserMode_Dev mode,
+ const std::string& accept_types)
+ : PluginResource(connection, instance),
+ mode_(mode) {
+ PopulateAcceptTypes(accept_types, &accept_types_);
+}
+
+FileChooserResource::~FileChooserResource() {
+}
+
+thunk::PPB_FileChooser_API* FileChooserResource::AsPPB_FileChooser_API() {
+ return this;
+}
+
+int32_t FileChooserResource::Show(const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback) {
+ return ShowWithoutUserGesture(PP_FALSE, PP_MakeUndefined(), output, callback);
+}
+
+int32_t FileChooserResource::ShowWithoutUserGesture(
+ PP_Bool save_as,
+ PP_Var suggested_file_name,
+ const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback) {
+ int32_t result = ShowInternal(save_as, suggested_file_name, callback);
+ if (result == PP_OK_COMPLETIONPENDING)
+ output_.set_pp_array_output(output);
+ return result;
+}
+
+int32_t FileChooserResource::Show0_5(scoped_refptr<TrackedCallback> callback) {
+ return ShowInternal(PP_FALSE, PP_MakeUndefined(), callback);
+}
+
+PP_Resource FileChooserResource::GetNextChosenFile() {
+ if (file_queue_.empty())
+ return 0;
+
+ // Return the next resource in the queue. It will already have been addrefed
+ // (they're currently owned by the FileChooser) and returning it transfers
+ // ownership of that reference to the plugin.
+ PP_Resource next = file_queue_.front();
+ file_queue_.pop();
+ return next;
+}
+
+int32_t FileChooserResource::ShowWithoutUserGesture0_5(
+ PP_Bool save_as,
+ PP_Var suggested_file_name,
+ scoped_refptr<TrackedCallback> callback) {
+ return ShowInternal(save_as, suggested_file_name, callback);
+}
+
+// static
+void FileChooserResource::PopulateAcceptTypes(
+ const std::string& input,
+ std::vector<std::string>* output) {
+ if (input.empty())
+ return;
+
+ std::vector<std::string> type_list;
+ base::SplitString(input, ',', &type_list);
+ output->reserve(type_list.size());
+
+ for (size_t i = 0; i < type_list.size(); ++i) {
+ std::string type = type_list[i];
+ TrimWhitespaceASCII(type, TRIM_ALL, &type);
+
+ // If the type is a single character, it definitely cannot be valid. In the
+ // case of a file extension it would be a single ".". In the case of a MIME
+ // type it would just be a "/".
+ if (type.length() < 2)
+ continue;
+ if (type.find_first_of('/') == std::string::npos && type[0] != '.')
+ continue;
+ StringToLowerASCII(&type);
+ output->push_back(type);
+ }
+}
+
+void FileChooserResource::OnPluginMsgShowReply(
+ const ResourceMessageReplyParams& params,
+ const std::vector<PPB_FileRef_CreateInfo>& chosen_files) {
+ if (output_.is_valid()) {
+ // Using v0.6 of the API with the output array.
+ std::vector<PP_Resource> files;
+ for (size_t i = 0; i < chosen_files.size(); i++)
+ files.push_back(PPB_FileRef_Proxy::DeserializeFileRef(chosen_files[i]));
+ output_.StoreResourceVector(files);
+ } else {
+ // Convert each of the passed in file infos to resources. These will be
+ // owned by the FileChooser object until they're passed to the plugin.
+ DCHECK(file_queue_.empty());
+ for (size_t i = 0; i < chosen_files.size(); i++) {
+ file_queue_.push(PPB_FileRef_Proxy::DeserializeFileRef(
+ chosen_files[i]));
+ }
+ }
+
+ // Notify the plugin of the new data.
+ callback_->Run(params.result());
+ // DANGER: May delete |this|!
+}
+
+int32_t FileChooserResource::ShowInternal(
+ PP_Bool save_as,
+ const PP_Var& suggested_file_name,
+ scoped_refptr<TrackedCallback> callback) {
+ if (TrackedCallback::IsPending(callback_))
+ return PP_ERROR_INPROGRESS;
+
+ if (!sent_create_to_renderer())
+ SendCreate(RENDERER, PpapiHostMsg_FileChooser_Create());
+
+ callback_ = callback;
+ StringVar* sugg_str = StringVar::FromPPVar(suggested_file_name);
+
+ PpapiHostMsg_FileChooser_Show msg(
+ PP_ToBool(save_as),
+ mode_ == PP_FILECHOOSERMODE_OPENMULTIPLE,
+ sugg_str ? sugg_str->value() : std::string(),
+ accept_types_);
+ Call<PpapiPluginMsg_FileChooser_ShowReply>(RENDERER, msg,
+ base::Bind(&FileChooserResource::OnPluginMsgShowReply, this));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/file_chooser_resource.h b/chromium/ppapi/proxy/file_chooser_resource.h
new file mode 100644
index 00000000000..58331db7f4f
--- /dev/null
+++ b/chromium/ppapi/proxy/file_chooser_resource.h
@@ -0,0 +1,85 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_FILE_CHOOSER_RESOURCE_H_
+#define PPAPI_PROXY_FILE_CHOOSER_RESOURCE_H_
+
+#include <queue>
+#include <string>
+#include <vector>
+
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/array_writer.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/ppb_file_chooser_api.h"
+
+namespace ppapi {
+
+struct PPB_FileRef_CreateInfo;
+
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT FileChooserResource
+ : public PluginResource,
+ public NON_EXPORTED_BASE(thunk::PPB_FileChooser_API) {
+ public:
+ FileChooserResource(Connection connection,
+ PP_Instance instance,
+ PP_FileChooserMode_Dev mode,
+ const std::string& accept_types);
+ virtual ~FileChooserResource();
+
+ // Resource overrides.
+ virtual thunk::PPB_FileChooser_API* AsPPB_FileChooser_API() OVERRIDE;
+
+ // PPB_FileChooser_API.
+ virtual int32_t Show(const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t ShowWithoutUserGesture(
+ PP_Bool save_as,
+ PP_Var suggested_file_name,
+ const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Show0_5(scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual PP_Resource GetNextChosenFile() OVERRIDE;
+ virtual int32_t ShowWithoutUserGesture0_5(
+ PP_Bool save_as,
+ PP_Var suggested_file_name,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+
+ // Parses the accept string into the given vector.
+ static void PopulateAcceptTypes(const std::string& input,
+ std::vector<std::string>* output);
+
+ private:
+ void OnPluginMsgShowReply(
+ const ResourceMessageReplyParams& params,
+ const std::vector<PPB_FileRef_CreateInfo>& chosen_files);
+
+ int32_t ShowInternal(PP_Bool save_as,
+ const PP_Var& suggested_file_name,
+ scoped_refptr<TrackedCallback> callback);
+
+ PP_FileChooserMode_Dev mode_;
+ std::vector<std::string> accept_types_;
+
+ // When using v0.6 of the API, contains the array output info.
+ ArrayWriter output_;
+
+ // When using v0.5 of the API, contains all files returned by the current
+ // show callback that haven't yet been given to the plugin. The plugin will
+ // repeatedly call us to get the next file, and we'll vend those out of this
+ // queue, removing them when ownership has transferred to the plugin.
+ std::queue<PP_Resource> file_queue_;
+
+ scoped_refptr<TrackedCallback> callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileChooserResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_FILE_CHOOSER_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/file_chooser_resource_unittest.cc b/chromium/ppapi/proxy/file_chooser_resource_unittest.cc
new file mode 100644
index 00000000000..a5801eed161
--- /dev/null
+++ b/chromium/ppapi/proxy/file_chooser_resource_unittest.cc
@@ -0,0 +1,146 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop/message_loop.h"
+#include "ppapi/c/dev/ppb_file_chooser_dev.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/file_chooser_resource.h"
+#include "ppapi/proxy/locking_resource_releaser.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/scoped_pp_var.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/thunk.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+typedef PluginProxyTest FileChooserResourceTest;
+
+void* GetFileRefDataBuffer(void* user_data,
+ uint32_t element_count,
+ uint32_t element_size) {
+ EXPECT_TRUE(element_size == sizeof(PP_Resource));
+ std::vector<PP_Resource>* output =
+ static_cast<std::vector<PP_Resource>*>(user_data);
+ output->resize(element_count);
+ if (element_count > 0)
+ return &(*output)[0];
+ return NULL;
+}
+
+void DoNothingCallback(void* user_data, int32_t result) {
+}
+
+// Calls PopulateAcceptTypes and verifies that the resulting array contains
+// the given values. The values may be NULL if there aren't expected to be
+// that many results.
+bool CheckParseAcceptType(const std::string& input,
+ const char* expected1,
+ const char* expected2) {
+ std::vector<std::string> output;
+ FileChooserResource::PopulateAcceptTypes(input, &output);
+
+ const size_t kCount = 2;
+ const char* expected[kCount] = { expected1, expected2 };
+
+ for (size_t i = 0; i < kCount; i++) {
+ if (!expected[i])
+ return i == output.size();
+ if (output.size() <= i)
+ return false;
+ if (output[i] != expected[i])
+ return false;
+ }
+
+ return output.size() == kCount;
+}
+
+} // namespace
+
+// Does a full test of Show() and reply functionality in the plugin side using
+// the public C interfaces.
+TEST_F(FileChooserResourceTest, Show) {
+ const PPB_FileChooser_Dev_0_6* chooser_iface =
+ thunk::GetPPB_FileChooser_Dev_0_6_Thunk();
+ LockingResourceReleaser res(
+ chooser_iface->Create(pp_instance(), PP_FILECHOOSERMODE_OPEN,
+ PP_MakeUndefined()));
+
+ std::vector<PP_Resource> dest;
+ PP_ArrayOutput output;
+ output.GetDataBuffer = &GetFileRefDataBuffer;
+ output.user_data = &dest;
+
+ int32_t result = chooser_iface->Show(
+ res.get(), output, PP_MakeCompletionCallback(&DoNothingCallback, NULL));
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
+
+ // Should have sent a "show" message.
+ ResourceMessageCallParams params;
+ IPC::Message msg;
+ ASSERT_TRUE(sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_FileChooser_Show::ID, &params, &msg));
+
+ ResourceMessageReplyParams reply_params(params.pp_resource(),
+ params.sequence());
+ reply_params.set_result(PP_OK);
+
+ // Synthesize a response with one file ref in it. Note that it must have a
+ // host resource value set or deserialization will fail. Since there isn't
+ // actually a host, this can be whatever we want.
+ std::vector<PPB_FileRef_CreateInfo> create_info_array;
+ PPB_FileRef_CreateInfo create_info;
+ create_info.resource.SetHostResource(pp_instance(), 123);
+ create_info.path = "foo/bar";
+ create_info.name = "baz";
+ create_info_array.push_back(create_info);
+ ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(
+ PpapiPluginMsg_ResourceReply(reply_params,
+ PpapiPluginMsg_FileChooser_ShowReply(create_info_array))));
+
+ // Should have populated our vector.
+ ASSERT_EQ(1u, dest.size());
+ LockingResourceReleaser dest_deletor(dest[0]); // Ensure it's cleaned up.
+
+ const PPB_FileRef_1_0* file_ref_iface = thunk::GetPPB_FileRef_1_0_Thunk();
+ EXPECT_EQ(PP_FILESYSTEMTYPE_EXTERNAL,
+ file_ref_iface->GetFileSystemType(dest[0]));
+
+ PP_Var name_var(file_ref_iface->GetName(dest[0]));
+ {
+ ProxyAutoLock lock;
+ ScopedPPVar release_name_var(ScopedPPVar::PassRef(), name_var);
+ EXPECT_VAR_IS_STRING(create_info.name, name_var);
+ }
+ // Path should be undefined since it's external filesystem.
+ PP_Var path_var(file_ref_iface->GetPath(dest[0]));
+ {
+ ProxyAutoLock lock;
+ ScopedPPVar release_path_var(ScopedPPVar::PassRef(), path_var);
+ EXPECT_EQ(PP_VARTYPE_UNDEFINED, path_var.type);
+ }
+}
+
+TEST_F(FileChooserResourceTest, PopulateAcceptTypes) {
+ EXPECT_TRUE(CheckParseAcceptType(std::string(), NULL, NULL));
+ EXPECT_TRUE(CheckParseAcceptType("/", NULL, NULL));
+ EXPECT_TRUE(CheckParseAcceptType(".", NULL, NULL));
+ EXPECT_TRUE(CheckParseAcceptType(",, , ", NULL, NULL));
+
+ EXPECT_TRUE(CheckParseAcceptType("app/txt", "app/txt", NULL));
+ EXPECT_TRUE(CheckParseAcceptType("app/txt,app/pdf", "app/txt", "app/pdf"));
+ EXPECT_TRUE(CheckParseAcceptType(" app/txt , app/pdf ",
+ "app/txt", "app/pdf"));
+
+ // No dot or slash ones should be skipped.
+ EXPECT_TRUE(CheckParseAcceptType("foo", NULL, NULL));
+ EXPECT_TRUE(CheckParseAcceptType("foo,.txt", ".txt", NULL));
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/file_io_resource.cc b/chromium/ppapi/proxy/file_io_resource.cc
new file mode 100644
index 00000000000..76ee51c4e9c
--- /dev/null
+++ b/chromium/ppapi/proxy/file_io_resource.cc
@@ -0,0 +1,451 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/file_io_resource.h"
+
+#include "base/bind.h"
+#include "base/task_runner_util.h"
+#include "ipc/ipc_message.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/array_writer.h"
+#include "ppapi/shared_impl/file_type_conversion.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/resource_tracker.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_file_ref_api.h"
+
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_FileIO_API;
+using ppapi::thunk::PPB_FileRef_API;
+
+namespace {
+
+// We must allocate a buffer sized according to the request of the plugin. To
+// reduce the chance of out-of-memory errors, we cap the read size to 32MB.
+// This is OK since the API specifies that it may perform a partial read.
+static const int32_t kMaxReadSize = 32 * 1024 * 1024; // 32MB
+
+// An adapter to let Read() share the same implementation with ReadToArray().
+void* DummyGetDataBuffer(void* user_data, uint32_t count, uint32_t size) {
+ return user_data;
+}
+
+// File thread task to close the file handle.
+void DoClose(base::PlatformFile file) {
+ base::ClosePlatformFile(file);
+}
+
+} // namespace
+
+namespace ppapi {
+namespace proxy {
+
+FileIOResource::QueryOp::QueryOp(PP_FileHandle file_handle)
+ : file_handle_(file_handle) {
+}
+
+FileIOResource::QueryOp::~QueryOp() {
+}
+
+int32_t FileIOResource::QueryOp::DoWork() {
+ return base::GetPlatformFileInfo(file_handle_, &file_info_) ?
+ PP_OK : PP_ERROR_FAILED;
+}
+
+FileIOResource::ReadOp::ReadOp(PP_FileHandle file_handle,
+ int64_t offset,
+ int32_t bytes_to_read)
+ : file_handle_(file_handle),
+ offset_(offset),
+ bytes_to_read_(bytes_to_read) {
+}
+
+FileIOResource::ReadOp::~ReadOp() {
+}
+
+int32_t FileIOResource::ReadOp::DoWork() {
+ DCHECK(!buffer_.get());
+ buffer_.reset(new char[bytes_to_read_]);
+ return base::ReadPlatformFile(
+ file_handle_, offset_, buffer_.get(), bytes_to_read_);
+}
+
+FileIOResource::FileIOResource(Connection connection, PP_Instance instance)
+ : PluginResource(connection, instance),
+ file_handle_(base::kInvalidPlatformFileValue),
+ file_system_type_(PP_FILESYSTEMTYPE_INVALID) {
+ SendCreate(RENDERER, PpapiHostMsg_FileIO_Create());
+}
+
+FileIOResource::~FileIOResource() {
+ CloseFileHandle();
+}
+
+PPB_FileIO_API* FileIOResource::AsPPB_FileIO_API() {
+ return this;
+}
+
+int32_t FileIOResource::Open(PP_Resource file_ref,
+ int32_t open_flags,
+ scoped_refptr<TrackedCallback> callback) {
+ EnterResourceNoLock<PPB_FileRef_API> enter(file_ref, true);
+ if (enter.failed())
+ return PP_ERROR_BADRESOURCE;
+
+ PPB_FileRef_API* file_ref_api = enter.object();
+ PP_FileSystemType type = file_ref_api->GetFileSystemType();
+ if (type != PP_FILESYSTEMTYPE_LOCALPERSISTENT &&
+ type != PP_FILESYSTEMTYPE_LOCALTEMPORARY &&
+ type != PP_FILESYSTEMTYPE_EXTERNAL &&
+ type != PP_FILESYSTEMTYPE_ISOLATED) {
+ NOTREACHED();
+ return PP_ERROR_FAILED;
+ }
+ file_system_type_ = type;
+
+ int32_t rv = state_manager_.CheckOperationState(
+ FileIOStateManager::OPERATION_EXCLUSIVE, false);
+ if (rv != PP_OK)
+ return rv;
+
+ Call<PpapiPluginMsg_FileIO_OpenReply>(RENDERER,
+ PpapiHostMsg_FileIO_Open(
+ enter.resource()->host_resource().host_resource(),
+ open_flags),
+ base::Bind(&FileIOResource::OnPluginMsgOpenFileComplete, this,
+ callback));
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileIOResource::Query(PP_FileInfo* info,
+ scoped_refptr<TrackedCallback> callback) {
+ int32_t rv = state_manager_.CheckOperationState(
+ FileIOStateManager::OPERATION_EXCLUSIVE, true);
+ if (rv != PP_OK)
+ return rv;
+ if (!info)
+ return PP_ERROR_BADARGUMENT;
+ if (file_handle_ == base::kInvalidPlatformFileValue)
+ return PP_ERROR_FAILED;
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ scoped_refptr<QueryOp> query_op(new QueryOp(file_handle_));
+
+ // If the callback is blocking, perform the task on the calling thread.
+ if (callback->is_blocking()) {
+ int32_t result;
+ {
+ // Release the proxy lock while making a potentially slow file call.
+ ProxyAutoUnlock unlock;
+ result = query_op->DoWork();
+ }
+ return OnQueryComplete(query_op, info, result);
+ }
+
+ // For the non-blocking case, post a task to the file thread and add a
+ // completion task to write the result.
+ base::PostTaskAndReplyWithResult(
+ PpapiGlobals::Get()->GetFileTaskRunner(pp_instance()),
+ FROM_HERE,
+ Bind(&FileIOResource::QueryOp::DoWork, query_op),
+ RunWhileLocked(Bind(&TrackedCallback::Run, callback)));
+ callback->set_completion_task(
+ Bind(&FileIOResource::OnQueryComplete, this, query_op, info));
+
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileIOResource::Touch(PP_Time last_access_time,
+ PP_Time last_modified_time,
+ scoped_refptr<TrackedCallback> callback) {
+ int32_t rv = state_manager_.CheckOperationState(
+ FileIOStateManager::OPERATION_EXCLUSIVE, true);
+ if (rv != PP_OK)
+ return rv;
+
+ Call<PpapiPluginMsg_FileIO_GeneralReply>(RENDERER,
+ PpapiHostMsg_FileIO_Touch(last_access_time, last_modified_time),
+ base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
+ callback));
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileIOResource::Read(int64_t offset,
+ char* buffer,
+ int32_t bytes_to_read,
+ scoped_refptr<TrackedCallback> callback) {
+ int32_t rv = state_manager_.CheckOperationState(
+ FileIOStateManager::OPERATION_READ, true);
+ if (rv != PP_OK)
+ return rv;
+
+ PP_ArrayOutput output_adapter;
+ output_adapter.GetDataBuffer = &DummyGetDataBuffer;
+ output_adapter.user_data = buffer;
+ return ReadValidated(offset, bytes_to_read, output_adapter, callback);
+}
+
+int32_t FileIOResource::ReadToArray(int64_t offset,
+ int32_t max_read_length,
+ PP_ArrayOutput* array_output,
+ scoped_refptr<TrackedCallback> callback) {
+ DCHECK(array_output);
+ int32_t rv = state_manager_.CheckOperationState(
+ FileIOStateManager::OPERATION_READ, true);
+ if (rv != PP_OK)
+ return rv;
+
+ return ReadValidated(offset, max_read_length, *array_output, callback);
+}
+
+int32_t FileIOResource::Write(int64_t offset,
+ const char* buffer,
+ int32_t bytes_to_write,
+ scoped_refptr<TrackedCallback> callback) {
+ int32_t rv = state_manager_.CheckOperationState(
+ FileIOStateManager::OPERATION_WRITE, true);
+ if (rv != PP_OK)
+ return rv;
+
+ // TODO(brettw) it would be nice to use a shared memory buffer for large
+ // writes rather than having to copy to a string (which will involve a number
+ // of extra copies to serialize over IPC).
+ Call<PpapiPluginMsg_FileIO_GeneralReply>(RENDERER,
+ PpapiHostMsg_FileIO_Write(offset, std::string(buffer, bytes_to_write)),
+ base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
+ callback));
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_WRITE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileIOResource::SetLength(int64_t length,
+ scoped_refptr<TrackedCallback> callback) {
+ int32_t rv = state_manager_.CheckOperationState(
+ FileIOStateManager::OPERATION_EXCLUSIVE, true);
+ if (rv != PP_OK)
+ return rv;
+
+ Call<PpapiPluginMsg_FileIO_GeneralReply>(RENDERER,
+ PpapiHostMsg_FileIO_SetLength(length),
+ base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
+ callback));
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileIOResource::Flush(scoped_refptr<TrackedCallback> callback) {
+ int32_t rv = state_manager_.CheckOperationState(
+ FileIOStateManager::OPERATION_EXCLUSIVE, true);
+ if (rv != PP_OK)
+ return rv;
+
+ Call<PpapiPluginMsg_FileIO_GeneralReply>(RENDERER,
+ PpapiHostMsg_FileIO_Flush(),
+ base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
+ callback));
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void FileIOResource::Close() {
+ CloseFileHandle();
+ Post(RENDERER, PpapiHostMsg_FileIO_Close());
+}
+
+int32_t FileIOResource::GetOSFileDescriptor() {
+ int32_t file_descriptor;
+ // Only available when running in process.
+ SyncCall<PpapiPluginMsg_FileIO_GetOSFileDescriptorReply>(
+ RENDERER, PpapiHostMsg_FileIO_GetOSFileDescriptor(), &file_descriptor);
+ return file_descriptor;
+}
+
+int32_t FileIOResource::RequestOSFileHandle(
+ PP_FileHandle* handle,
+ scoped_refptr<TrackedCallback> callback) {
+ int32_t rv = state_manager_.CheckOperationState(
+ FileIOStateManager::OPERATION_EXCLUSIVE, true);
+ if (rv != PP_OK)
+ return rv;
+
+ Call<PpapiPluginMsg_FileIO_RequestOSFileHandleReply>(RENDERER,
+ PpapiHostMsg_FileIO_RequestOSFileHandle(),
+ base::Bind(&FileIOResource::OnPluginMsgRequestOSFileHandleComplete, this,
+ callback, handle));
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileIOResource::WillWrite(int64_t offset,
+ int32_t bytes_to_write,
+ scoped_refptr<TrackedCallback> callback) {
+ Call<PpapiPluginMsg_FileIO_GeneralReply>(RENDERER,
+ PpapiHostMsg_FileIO_WillWrite(offset, bytes_to_write),
+ base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, callback));
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileIOResource::WillSetLength(int64_t length,
+ scoped_refptr<TrackedCallback> callback) {
+ Call<PpapiPluginMsg_FileIO_GeneralReply>(RENDERER,
+ PpapiHostMsg_FileIO_WillSetLength(length),
+ base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, callback));
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileIOResource::ReadValidated(int64_t offset,
+ int32_t bytes_to_read,
+ const PP_ArrayOutput& array_output,
+ scoped_refptr<TrackedCallback> callback) {
+ if (bytes_to_read < 0)
+ return PP_ERROR_FAILED;
+ if (file_handle_ == base::kInvalidPlatformFileValue)
+ return PP_ERROR_FAILED;
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ);
+
+ bytes_to_read = std::min(bytes_to_read, kMaxReadSize);
+ scoped_refptr<ReadOp> read_op(
+ new ReadOp(file_handle_, offset, bytes_to_read));
+ if (callback->is_blocking()) {
+ int32_t result;
+ {
+ // Release the proxy lock while making a potentially slow file call.
+ ProxyAutoUnlock unlock;
+ result = read_op->DoWork();
+ }
+ return OnReadComplete(read_op, array_output, result);
+ }
+
+ // For the non-blocking case, post a task to the file thread.
+ base::PostTaskAndReplyWithResult(
+ PpapiGlobals::Get()->GetFileTaskRunner(pp_instance()),
+ FROM_HERE,
+ Bind(&FileIOResource::ReadOp::DoWork, read_op),
+ RunWhileLocked(Bind(&TrackedCallback::Run, callback)));
+ callback->set_completion_task(
+ Bind(&FileIOResource::OnReadComplete, this, read_op, array_output));
+
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void FileIOResource::CloseFileHandle() {
+ if (file_handle_ != base::kInvalidPlatformFileValue) {
+ // Close our local fd on the file thread.
+ base::TaskRunner* file_task_runner =
+ PpapiGlobals::Get()->GetFileTaskRunner(pp_instance());
+ file_task_runner->PostTask(FROM_HERE,
+ base::Bind(&DoClose, file_handle_));
+
+ file_handle_ = base::kInvalidPlatformFileValue;
+ }
+}
+
+int32_t FileIOResource::OnQueryComplete(scoped_refptr<QueryOp> query_op,
+ PP_FileInfo* info,
+ int32_t result) {
+ DCHECK(state_manager_.get_pending_operation() ==
+ FileIOStateManager::OPERATION_EXCLUSIVE);
+
+ if (result == PP_OK) {
+ // This writes the file info into the plugin's PP_FileInfo struct.
+ ppapi::PlatformFileInfoToPepperFileInfo(query_op->file_info(),
+ file_system_type_,
+ info);
+ }
+ state_manager_.SetOperationFinished();
+ return result;
+}
+
+int32_t FileIOResource::OnReadComplete(scoped_refptr<ReadOp> read_op,
+ PP_ArrayOutput array_output,
+ int32_t result) {
+ DCHECK(state_manager_.get_pending_operation() ==
+ FileIOStateManager::OPERATION_READ);
+ if (result >= 0) {
+ ArrayWriter output;
+ output.set_pp_array_output(array_output);
+ if (output.is_valid())
+ output.StoreArray(read_op->buffer(), result);
+ else
+ result = PP_ERROR_FAILED;
+ } else {
+ // The read operation failed.
+ result = PP_ERROR_FAILED;
+ }
+ state_manager_.SetOperationFinished();
+ return result;
+}
+
+void FileIOResource::OnPluginMsgGeneralComplete(
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params) {
+ DCHECK(state_manager_.get_pending_operation() ==
+ FileIOStateManager::OPERATION_EXCLUSIVE ||
+ state_manager_.get_pending_operation() ==
+ FileIOStateManager::OPERATION_WRITE);
+ // End this operation now, so the user's callback can execute another FileIO
+ // operation, assuming there are no other pending operations.
+ state_manager_.SetOperationFinished();
+ callback->Run(params.result());
+}
+
+void FileIOResource::OnPluginMsgOpenFileComplete(
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params) {
+ DCHECK(state_manager_.get_pending_operation() ==
+ FileIOStateManager::OPERATION_EXCLUSIVE);
+ if (params.result() == PP_OK)
+ state_manager_.SetOpenSucceed();
+
+ int32_t result = params.result();
+ IPC::PlatformFileForTransit transit_file;
+ if ((result == PP_OK) && params.TakeFileHandleAtIndex(0, &transit_file))
+ file_handle_ = IPC::PlatformFileForTransitToPlatformFile(transit_file);
+ // End this operation now, so the user's callback can execute another FileIO
+ // operation, assuming there are no other pending operations.
+ state_manager_.SetOperationFinished();
+ callback->Run(result);
+}
+
+void FileIOResource::OnPluginMsgRequestOSFileHandleComplete(
+ scoped_refptr<TrackedCallback> callback,
+ PP_FileHandle* output_handle,
+ const ResourceMessageReplyParams& params) {
+ DCHECK(state_manager_.get_pending_operation() ==
+ FileIOStateManager::OPERATION_EXCLUSIVE);
+
+ if (!TrackedCallback::IsPending(callback)) {
+ state_manager_.SetOperationFinished();
+ return;
+ }
+
+ int32_t result = params.result();
+ IPC::PlatformFileForTransit transit_file;
+ if (!params.TakeFileHandleAtIndex(0, &transit_file))
+ result = PP_ERROR_FAILED;
+ *output_handle = IPC::PlatformFileForTransitToPlatformFile(transit_file);
+
+ // End this operation now, so the user's callback can execute another FileIO
+ // operation, assuming there are no other pending operations.
+ state_manager_.SetOperationFinished();
+ callback->Run(result);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/file_io_resource.h b/chromium/ppapi/proxy/file_io_resource.h
new file mode 100644
index 00000000000..1a888d199d6
--- /dev/null
+++ b/chromium/ppapi/proxy/file_io_resource.h
@@ -0,0 +1,146 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_FILE_IO_RESOURCE_H_
+#define PPAPI_PROXY_FILE_IO_RESOURCE_H_
+
+#include <string>
+
+#include "ppapi/c/private/pp_file_handle.h"
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/file_io_state_manager.h"
+#include "ppapi/thunk/ppb_file_io_api.h"
+
+namespace ppapi {
+
+class TrackedCallback;
+
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT FileIOResource
+ : public PluginResource,
+ public thunk::PPB_FileIO_API {
+ public:
+ FileIOResource(Connection connection, PP_Instance instance);
+ virtual ~FileIOResource();
+
+ // Resource overrides.
+ virtual thunk::PPB_FileIO_API* AsPPB_FileIO_API() OVERRIDE;
+
+ // PPB_FileIO_API implementation.
+ virtual int32_t Open(PP_Resource file_ref,
+ int32_t open_flags,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Query(PP_FileInfo* info,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Touch(PP_Time last_access_time,
+ PP_Time last_modified_time,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Read(int64_t offset,
+ char* buffer,
+ int32_t bytes_to_read,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t ReadToArray(int64_t offset,
+ int32_t max_read_length,
+ PP_ArrayOutput* array_output,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Write(int64_t offset,
+ const char* buffer,
+ int32_t bytes_to_write,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t SetLength(int64_t length,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Flush(scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual void Close() OVERRIDE;
+ virtual int32_t GetOSFileDescriptor() OVERRIDE;
+ virtual int32_t RequestOSFileHandle(
+ PP_FileHandle* handle,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t WillWrite(int64_t offset,
+ int32_t bytes_to_write,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t WillSetLength(
+ int64_t length,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+
+ private:
+ // Class to perform file query operations across multiple threads.
+ class QueryOp : public base::RefCountedThreadSafe<QueryOp> {
+ public:
+ explicit QueryOp(PP_FileHandle file_handle);
+
+ // Queries the file. Called on the file thread (non-blocking) or the plugin
+ // thread (blocking). This should not be called when we hold the proxy lock.
+ int32_t DoWork();
+
+ const base::PlatformFileInfo& file_info() const { return file_info_; }
+
+ private:
+ friend class base::RefCountedThreadSafe<QueryOp>;
+ ~QueryOp();
+
+ PP_FileHandle file_handle_;
+ base::PlatformFileInfo file_info_;
+ };
+
+ // Class to perform file read operations across multiple threads.
+ class ReadOp : public base::RefCountedThreadSafe<ReadOp> {
+ public:
+ ReadOp(PP_FileHandle file_handle, int64_t offset, int32_t bytes_to_read);
+
+ // Reads the file. Called on the file thread (non-blocking) or the plugin
+ // thread (blocking). This should not be called when we hold the proxy lock.
+ int32_t DoWork();
+
+ char* buffer() const { return buffer_.get(); }
+
+ private:
+ friend class base::RefCountedThreadSafe<ReadOp>;
+ ~ReadOp();
+
+ PP_FileHandle file_handle_;
+ int64_t offset_;
+ int32_t bytes_to_read_;
+ scoped_ptr<char[]> buffer_;
+ };
+
+ int32_t ReadValidated(int64_t offset,
+ int32_t bytes_to_read,
+ const PP_ArrayOutput& array_output,
+ scoped_refptr<TrackedCallback> callback);
+
+ void CloseFileHandle();
+
+
+ // Completion tasks for file operations that are done in the plugin.
+ int32_t OnQueryComplete(scoped_refptr<QueryOp> query_op,
+ PP_FileInfo* info,
+ int32_t result);
+ int32_t OnReadComplete(scoped_refptr<ReadOp> read_op,
+ PP_ArrayOutput array_output,
+ int32_t result);
+
+ // Reply message handlers for operations that are done in the host.
+ void OnPluginMsgGeneralComplete(scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params);
+ void OnPluginMsgOpenFileComplete(scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params);
+ void OnPluginMsgRequestOSFileHandleComplete(
+ scoped_refptr<TrackedCallback> callback,
+ PP_FileHandle* output_handle,
+ const ResourceMessageReplyParams& params);
+
+ PP_FileHandle file_handle_;
+ PP_FileSystemType file_system_type_;
+ FileIOStateManager state_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileIOResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_FILE_IO_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/file_ref_resource.cc b/chromium/ppapi/proxy/file_ref_resource.cc
new file mode 100644
index 00000000000..4c098a567a9
--- /dev/null
+++ b/chromium/ppapi/proxy/file_ref_resource.cc
@@ -0,0 +1,279 @@
+// Copyright 2013 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/file_ref_resource.h"
+
+#include "ppapi/c/pp_directory_entry.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/array_writer.h"
+#include "ppapi/shared_impl/file_ref_util.h"
+#include "ppapi/shared_impl/resource.h"
+#include "ppapi/shared_impl/resource_tracker.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_file_system_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+FileRefResource::FileRefResource(
+ Connection connection,
+ PP_Instance instance,
+ const FileRef_CreateInfo& create_info)
+ : PluginResource(connection, instance),
+ create_info_(create_info),
+ file_system_resource_(create_info.file_system_plugin_resource) {
+ if (create_info_.file_system_type != PP_FILESYSTEMTYPE_EXTERNAL) {
+ // If path ends with a slash, then normalize it away unless path is
+ // the root path.
+ int path_size = create_info_.internal_path.size();
+ if (path_size > 1 && create_info_.internal_path.at(path_size - 1) == '/')
+ create_info_.internal_path.erase(path_size - 1, 1);
+
+ path_var_ = new StringVar(create_info_.internal_path);
+
+ create_info_.display_name = GetNameForInternalFilePath(
+ create_info_.internal_path);
+ }
+ name_var_ = new StringVar(create_info_.display_name);
+
+ if (create_info_.pending_host_resource_id != 0) {
+ AttachToPendingHost(BROWSER, create_info_.pending_host_resource_id);
+ } else {
+ CHECK(create_info_.file_system_type != PP_FILESYSTEMTYPE_EXTERNAL);
+ SendCreate(BROWSER, PpapiHostMsg_FileRef_CreateInternal(
+ create_info.file_system_plugin_resource,
+ create_info.internal_path));
+ }
+}
+
+FileRefResource::~FileRefResource() {
+}
+
+//static
+PP_Resource FileRefResource::CreateFileRef(
+ Connection connection,
+ PP_Instance instance,
+ const FileRef_CreateInfo& create_info) {
+ // If we have a valid file_system resource, ensure that its type matches that
+ // of the fs_type parameter.
+ if (create_info.file_system_plugin_resource != 0) {
+ thunk::EnterResourceNoLock<thunk::PPB_FileSystem_API> enter(
+ create_info.file_system_plugin_resource, true);
+ if (enter.failed())
+ return 0;
+ if (enter.object()->GetType() != create_info.file_system_type) {
+ NOTREACHED() << "file system type mismatch with resource";
+ return 0;
+ }
+ }
+
+ if (create_info.file_system_type == PP_FILESYSTEMTYPE_LOCALPERSISTENT ||
+ create_info.file_system_type == PP_FILESYSTEMTYPE_LOCALTEMPORARY) {
+ if (!IsValidInternalPath(create_info.internal_path))
+ return 0;
+ }
+ return (new FileRefResource(connection,
+ instance,
+ create_info))->GetReference();
+}
+
+thunk::PPB_FileRef_API* FileRefResource::AsPPB_FileRef_API() {
+ // TODO: return "this" once we update PPB_FileRef_API.
+ NOTREACHED();
+ return NULL;
+}
+
+PP_FileSystemType FileRefResource::GetFileSystemType() const {
+ return create_info_.file_system_type;
+}
+
+PP_Var FileRefResource::GetName() const {
+ return name_var_->GetPPVar();
+}
+
+PP_Var FileRefResource::GetPath() const {
+ if (create_info_.file_system_type == PP_FILESYSTEMTYPE_EXTERNAL)
+ return PP_MakeUndefined();
+ return path_var_->GetPPVar();
+}
+
+PP_Resource FileRefResource::GetParent() {
+ if (create_info_.file_system_type == PP_FILESYSTEMTYPE_EXTERNAL)
+ return 0;
+
+ size_t pos = create_info_.internal_path.rfind('/');
+ CHECK(pos != std::string::npos);
+ if (pos == 0)
+ pos++;
+ std::string parent_path = create_info_.internal_path.substr(0, pos);
+
+ ppapi::FileRef_CreateInfo parent_info;
+ parent_info.file_system_type = create_info_.file_system_type;
+ parent_info.internal_path = parent_path;
+ parent_info.display_name = GetNameForInternalFilePath(parent_path);
+ parent_info.file_system_plugin_resource =
+ create_info_.file_system_plugin_resource;
+
+ return (new FileRefResource(connection(),
+ pp_instance(),
+ parent_info))->GetReference();
+}
+
+int32_t FileRefResource::MakeDirectory(
+ PP_Bool make_ancestors,
+ scoped_refptr<TrackedCallback> callback) {
+ Call<PpapiPluginMsg_FileRef_MakeDirectoryReply>(
+ BROWSER,
+ PpapiHostMsg_FileRef_MakeDirectory(PP_TRUE == make_ancestors),
+ base::Bind(&FileRefResource::RunTrackedCallback, this, callback));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileRefResource::Touch(PP_Time last_access_time,
+ PP_Time last_modified_time,
+ scoped_refptr<TrackedCallback> callback) {
+ Call<PpapiPluginMsg_FileRef_TouchReply>(
+ BROWSER,
+ PpapiHostMsg_FileRef_Touch(last_access_time,
+ last_modified_time),
+ base::Bind(&FileRefResource::RunTrackedCallback, this, callback));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileRefResource::Delete(scoped_refptr<TrackedCallback> callback) {
+ Call<PpapiPluginMsg_FileRef_DeleteReply>(
+ BROWSER,
+ PpapiHostMsg_FileRef_Delete(),
+ base::Bind(&FileRefResource::RunTrackedCallback, this, callback));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileRefResource::Rename(PP_Resource new_file_ref,
+ scoped_refptr<TrackedCallback> callback) {
+ Call<PpapiPluginMsg_FileRef_RenameReply>(
+ BROWSER,
+ PpapiHostMsg_FileRef_Rename(new_file_ref),
+ base::Bind(&FileRefResource::RunTrackedCallback, this, callback));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileRefResource::Query(PP_FileInfo* info,
+ scoped_refptr<TrackedCallback> callback) {
+ if (info == NULL)
+ return PP_ERROR_BADARGUMENT;
+
+ Call<PpapiPluginMsg_FileRef_QueryReply>(
+ BROWSER,
+ PpapiHostMsg_FileRef_Query(),
+ base::Bind(&FileRefResource::OnQueryReply, this, info, callback));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileRefResource::ReadDirectoryEntries(
+ const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback) {
+ Call<PpapiPluginMsg_FileRef_ReadDirectoryEntriesReply>(
+ BROWSER,
+ PpapiHostMsg_FileRef_ReadDirectoryEntries(),
+ base::Bind(&FileRefResource::OnDirectoryEntriesReply,
+ this, output, callback));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+/*
+const FileRef_CreateInfo& FileRefResource::GetCreateInfo() const {
+ return create_info_;
+}
+*/
+const PPB_FileRef_CreateInfo& FileRefResource::GetCreateInfo() const {
+ // FIXME
+ NOTREACHED();
+ PPB_FileRef_CreateInfo *info = new PPB_FileRef_CreateInfo();
+ return *info;
+}
+
+// TODO(teravest): Remove this when we are finished moving to the new proxy.
+int32_t FileRefResource::QueryInHost(linked_ptr<PP_FileInfo> info,
+ scoped_refptr<TrackedCallback> callback) {
+ NOTREACHED();
+ return PP_ERROR_FAILED;
+}
+
+// TODO(teravest): Remove this when we are finished moving to the new proxy.
+int32_t FileRefResource::ReadDirectoryEntriesInHost(
+ linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
+ linked_ptr<std::vector<PP_FileType> > file_types,
+ scoped_refptr<TrackedCallback> callback) {
+ NOTREACHED();
+ return PP_ERROR_FAILED;
+}
+
+PP_Var FileRefResource::GetAbsolutePath() {
+ if (!absolute_path_var_.get()) {
+ std::string absolute_path;
+ int32_t result = SyncCall<PpapiPluginMsg_FileRef_GetAbsolutePathReply>(
+ BROWSER, PpapiHostMsg_FileRef_GetAbsolutePath(), &absolute_path);
+ if (result != PP_OK)
+ return PP_MakeUndefined();
+ absolute_path_var_ = new StringVar(absolute_path);
+ }
+ return absolute_path_var_->GetPPVar();
+}
+
+void FileRefResource::RunTrackedCallback(
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params) {
+ if (TrackedCallback::IsPending(callback))
+ callback->Run(params.result());
+}
+
+void FileRefResource::OnQueryReply(
+ PP_FileInfo* out_info,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const PP_FileInfo& info) {
+ if (!TrackedCallback::IsPending(callback))
+ return;
+
+ if (params.result() == PP_OK)
+ *out_info = info;
+ callback->Run(params.result());
+}
+
+void FileRefResource::OnDirectoryEntriesReply(
+ const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const std::vector<ppapi::FileRef_CreateInfo>& infos,
+ const std::vector<PP_FileType>& file_types) {
+ if (!TrackedCallback::IsPending(callback))
+ return;
+
+ if (params.result() == PP_OK) {
+ ArrayWriter writer(output);
+ if (!writer.is_valid()) {
+ callback->Run(PP_ERROR_BADARGUMENT);
+ return;
+ }
+
+ std::vector<PP_DirectoryEntry> entries;
+ for (size_t i = 0; i < infos.size(); ++i) {
+ PP_DirectoryEntry entry;
+ entry.file_ref = FileRefResource::CreateFileRef(connection(),
+ pp_instance(),
+ infos[i]);
+ entry.file_type = file_types[i];
+ entries.push_back(entry);
+ }
+
+ writer.StoreVector(entries);
+ }
+ callback->Run(params.result());
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/file_ref_resource.h b/chromium/ppapi/proxy/file_ref_resource.h
new file mode 100644
index 00000000000..82570fbc09c
--- /dev/null
+++ b/chromium/ppapi/proxy/file_ref_resource.h
@@ -0,0 +1,107 @@
+// Copyright 2013 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 "base/memory/scoped_ptr.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_time.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/file_ref_create_info.h"
+#include "ppapi/shared_impl/scoped_pp_resource.h"
+#include "ppapi/thunk/ppb_file_ref_api.h"
+
+namespace ppapi {
+class StringVar;
+
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT FileRefResource
+ : public PluginResource,
+ public thunk::PPB_FileRef_API {
+ public:
+ static PP_Resource CreateFileRef(Connection connection,
+ PP_Instance instance,
+ const FileRef_CreateInfo& info);
+
+ virtual ~FileRefResource();
+
+ // Resource implementation.
+ virtual thunk::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,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Touch(PP_Time last_access_time,
+ PP_Time last_modified_time,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Delete(scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Rename(PP_Resource new_file_ref,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Query(PP_FileInfo* info,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t ReadDirectoryEntries(
+ const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual const PPB_FileRef_CreateInfo& GetCreateInfo() const OVERRIDE;
+ virtual int32_t QueryInHost(linked_ptr<PP_FileInfo> info,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t ReadDirectoryEntriesInHost(
+ linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
+ linked_ptr<std::vector<PP_FileType> > file_types,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+
+ // Private API
+ virtual PP_Var GetAbsolutePath() OVERRIDE;
+
+ private:
+ FileRefResource(Connection connection,
+ PP_Instance instance,
+ const FileRef_CreateInfo& info);
+
+ void RunTrackedCallback(scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params);
+
+ void OnQueryReply(PP_FileInfo* out_info,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const PP_FileInfo& info);
+
+ void OnDirectoryEntriesReply(
+ const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const std::vector<ppapi::FileRef_CreateInfo>& infos,
+ const std::vector<PP_FileType>& file_types);
+
+ // Populated after creation.
+ FileRef_CreateInfo create_info_;
+
+ // Some file ref operations may fail if the the file system resource inside
+ // create_info_ is destroyed. Therefore, we explicitly hold a reference to
+ // the file system resource to make sure it outlives the file ref.
+ ScopedPPResource file_system_resource_;
+
+ scoped_refptr<StringVar> name_var_;
+ scoped_refptr<StringVar> path_var_;
+ scoped_refptr<StringVar> absolute_path_var_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileRefResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPB_FILE_REF_PROXY_H_
diff --git a/chromium/ppapi/proxy/file_system_resource.cc b/chromium/ppapi/proxy/file_system_resource.cc
new file mode 100644
index 00000000000..5acac00964b
--- /dev/null
+++ b/chromium/ppapi/proxy/file_system_resource.cc
@@ -0,0 +1,79 @@
+// Copyright (c) 2013 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/file_system_resource.h"
+
+#include "base/bind.h"
+#include "ipc/ipc_message.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+
+using ppapi::thunk::PPB_FileSystem_API;
+
+namespace ppapi {
+namespace proxy {
+
+FileSystemResource::FileSystemResource(Connection connection,
+ PP_Instance instance,
+ PP_FileSystemType type)
+ : PluginResource(connection, instance),
+ type_(type),
+ called_open_(false),
+ callback_count_(0) {
+ DCHECK(type_ != PP_FILESYSTEMTYPE_INVALID);
+ // TODO(teravest): Temporarily create hosts in both the browser and renderer
+ // while we move file related hosts to the browser.
+ SendCreate(RENDERER, PpapiHostMsg_FileSystem_Create(type_));
+ SendCreate(BROWSER, PpapiHostMsg_FileSystem_Create(type_));
+}
+
+FileSystemResource::~FileSystemResource() {
+}
+
+PPB_FileSystem_API* FileSystemResource::AsPPB_FileSystem_API() {
+ return this;
+}
+
+int32_t FileSystemResource::Open(int64_t expected_size,
+ scoped_refptr<TrackedCallback> callback) {
+ if (called_open_)
+ return PP_ERROR_FAILED;
+ called_open_ = true;
+
+ Call<PpapiPluginMsg_FileSystem_OpenReply>(RENDERER,
+ PpapiHostMsg_FileSystem_Open(expected_size),
+ base::Bind(&FileSystemResource::OpenComplete,
+ this,
+ callback));
+ Call<PpapiPluginMsg_FileSystem_OpenReply>(BROWSER,
+ PpapiHostMsg_FileSystem_Open(expected_size),
+ base::Bind(&FileSystemResource::OpenComplete,
+ this,
+ callback));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+PP_FileSystemType FileSystemResource::GetType() {
+ return type_;
+}
+
+void FileSystemResource::InitIsolatedFileSystem(const char* fsid) {
+ Post(RENDERER,
+ PpapiHostMsg_FileSystem_InitIsolatedFileSystem(std::string(fsid)));
+ Post(BROWSER,
+ PpapiHostMsg_FileSystem_InitIsolatedFileSystem(std::string(fsid)));
+}
+
+void FileSystemResource::OpenComplete(
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params) {
+ ++callback_count_;
+ // Received callback from browser and renderer.
+ if (callback_count_ == 2)
+ callback->Run(params.result());
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/file_system_resource.h b/chromium/ppapi/proxy/file_system_resource.h
new file mode 100644
index 00000000000..b104db32420
--- /dev/null
+++ b/chromium/ppapi/proxy/file_system_resource.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2013 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_FILE_SYSTEM_RESOURCE_H_
+#define PPAPI_PROXY_FILE_SYSTEM_RESOURCE_H_
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "ppapi/c/pp_file_info.h"
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/proxy/resource_message_params.h"
+#include "ppapi/thunk/ppb_file_system_api.h"
+
+namespace ppapi {
+
+class TrackedCallback;
+
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT FileSystemResource
+ : public PluginResource,
+ public NON_EXPORTED_BASE(thunk::PPB_FileSystem_API) {
+ public:
+ FileSystemResource(Connection connection,
+ PP_Instance instance,
+ PP_FileSystemType type);
+ virtual ~FileSystemResource();
+
+ // Resource overrides.
+ virtual thunk::PPB_FileSystem_API* AsPPB_FileSystem_API() OVERRIDE;
+
+ // PPB_FileSystem_API implementation.
+ virtual int32_t Open(int64_t expected_size,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual PP_FileSystemType GetType() OVERRIDE;
+
+ void InitIsolatedFileSystem(const char* fsid);
+ private:
+
+ // Called when the host has responded to our open request.
+ void OpenComplete(scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params);
+
+ PP_FileSystemType type_;
+ bool called_open_;
+ uint32_t callback_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileSystemResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_FILE_SYSTEM_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/flash_clipboard_resource.cc b/chromium/ppapi/proxy/flash_clipboard_resource.cc
new file mode 100644
index 00000000000..5f064023f35
--- /dev/null
+++ b/chromium/ppapi/proxy/flash_clipboard_resource.cc
@@ -0,0 +1,156 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/flash_clipboard_resource.h"
+
+#include "ipc/ipc_message.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/shared_impl/var_tracker.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+// Returns whether the given clipboard type is valid.
+bool IsValidClipboardType(PP_Flash_Clipboard_Type type) {
+ return type == PP_FLASH_CLIPBOARD_TYPE_STANDARD ||
+ type == PP_FLASH_CLIPBOARD_TYPE_SELECTION;
+}
+
+// Convert a PP_Var to/from a string which is transmitted to the pepper host.
+// These functions assume the format is valid.
+bool PPVarToClipboardString(int32_t format,
+ const PP_Var& var,
+ std::string* string_out) {
+ if (format == PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT ||
+ format == PP_FLASH_CLIPBOARD_FORMAT_HTML) {
+ StringVar* string_var = StringVar::FromPPVar(var);
+ if (!string_var)
+ return false;
+ *string_out = string_var->value();
+ return true;
+ } else {
+ // All other formats are expected to be array buffers.
+ ArrayBufferVar* array_buffer_var = ArrayBufferVar::FromPPVar(var);
+ if (!array_buffer_var)
+ return false;
+ *string_out = std::string(static_cast<const char*>(array_buffer_var->Map()),
+ array_buffer_var->ByteLength());
+ return true;
+ }
+}
+
+PP_Var ClipboardStringToPPVar(int32_t format,
+ const std::string& string) {
+ if (format == PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT ||
+ format == PP_FLASH_CLIPBOARD_FORMAT_HTML) {
+ return StringVar::StringToPPVar(string);
+ } else {
+ // All other formats are expected to be array buffers.
+ return PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
+ string.size(), string.data());
+ }
+}
+} // namespace
+
+FlashClipboardResource::FlashClipboardResource(
+ Connection connection, PP_Instance instance)
+ : PluginResource(connection, instance) {
+ SendCreate(BROWSER, PpapiHostMsg_FlashClipboard_Create());
+}
+
+FlashClipboardResource::~FlashClipboardResource() {
+}
+
+thunk::PPB_Flash_Clipboard_API*
+FlashClipboardResource::AsPPB_Flash_Clipboard_API() {
+ return this;
+}
+
+uint32_t FlashClipboardResource::RegisterCustomFormat(
+ PP_Instance instance,
+ const char* format_name) {
+ // Check to see if the format has already been registered.
+ uint32_t format = clipboard_formats_.GetFormatID(format_name);
+ if (format != PP_FLASH_CLIPBOARD_FORMAT_INVALID)
+ return format;
+ int32_t result =
+ SyncCall<PpapiPluginMsg_FlashClipboard_RegisterCustomFormatReply>(
+ BROWSER,
+ PpapiHostMsg_FlashClipboard_RegisterCustomFormat(format_name),
+ &format);
+ if (result != PP_OK || format == PP_FLASH_CLIPBOARD_FORMAT_INVALID)
+ return PP_FLASH_CLIPBOARD_FORMAT_INVALID;
+ clipboard_formats_.SetRegisteredFormat(format_name, format);
+ return format;
+}
+
+PP_Bool FlashClipboardResource::IsFormatAvailable(
+ PP_Instance instance,
+ PP_Flash_Clipboard_Type clipboard_type,
+ uint32_t format) {
+ if (IsValidClipboardType(clipboard_type) &&
+ (FlashClipboardFormatRegistry::IsValidPredefinedFormat(format) ||
+ clipboard_formats_.IsFormatRegistered(format))) {
+ int32_t result = SyncCall<IPC::Message>(BROWSER,
+ PpapiHostMsg_FlashClipboard_IsFormatAvailable(clipboard_type, format));
+ return result == PP_OK ? PP_TRUE : PP_FALSE;
+ }
+ return PP_FALSE;
+}
+
+PP_Var FlashClipboardResource::ReadData(
+ PP_Instance instance,
+ PP_Flash_Clipboard_Type clipboard_type,
+ uint32_t format) {
+ std::string value;
+ int32_t result =
+ SyncCall<PpapiPluginMsg_FlashClipboard_ReadDataReply>(
+ BROWSER,
+ PpapiHostMsg_FlashClipboard_ReadData(clipboard_type, format),
+ &value);
+ if (result != PP_OK)
+ return PP_MakeUndefined();
+
+ return ClipboardStringToPPVar(format, value);
+}
+
+int32_t FlashClipboardResource::WriteData(
+ PP_Instance instance,
+ PP_Flash_Clipboard_Type clipboard_type,
+ uint32_t data_item_count,
+ const uint32_t formats[],
+ const PP_Var data_items[]) {
+ if (!IsValidClipboardType(clipboard_type))
+ return PP_ERROR_BADARGUMENT;
+ std::vector<uint32_t> formats_vector;
+ std::vector<std::string> data_items_vector;
+ for (size_t i = 0; i < data_item_count; ++i) {
+ if (!clipboard_formats_.IsFormatRegistered(formats[i]) &&
+ !FlashClipboardFormatRegistry::IsValidPredefinedFormat(formats[i])) {
+ return PP_ERROR_BADARGUMENT;
+ }
+ formats_vector.push_back(formats[i]);
+ std::string string;
+ if (!PPVarToClipboardString(formats[i], data_items[i], &string))
+ return PP_ERROR_BADARGUMENT;
+ data_items_vector.push_back(string);
+ }
+
+ Post(BROWSER,
+ PpapiHostMsg_FlashClipboard_WriteData(
+ static_cast<uint32_t>(clipboard_type),
+ formats_vector,
+ data_items_vector));
+
+ // Assume success, since it allows us to avoid a sync IPC.
+ return PP_OK;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/flash_clipboard_resource.h b/chromium/ppapi/proxy/flash_clipboard_resource.h
new file mode 100644
index 00000000000..fdb7e79a48e
--- /dev/null
+++ b/chromium/ppapi/proxy/flash_clipboard_resource.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_FLASH_CLIPBOARD_RESOURCE_H_
+#define PPAPI_PROXY_FLASH_CLIPBOARD_RESOURCE_H_
+
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/shared_impl/flash_clipboard_format_registry.h"
+#include "ppapi/thunk/ppb_flash_clipboard_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class FlashClipboardResource
+ : public PluginResource,
+ public NON_EXPORTED_BASE(thunk::PPB_Flash_Clipboard_API) {
+ public:
+ FlashClipboardResource(Connection connection, PP_Instance instance);
+ virtual ~FlashClipboardResource();
+
+ // Resource implementation.
+ virtual thunk::PPB_Flash_Clipboard_API* AsPPB_Flash_Clipboard_API() OVERRIDE;
+
+ // PPB_Flash_Clipboard_API implementation.
+ virtual uint32_t RegisterCustomFormat(PP_Instance instance,
+ const char* format_name) OVERRIDE;
+ virtual PP_Bool IsFormatAvailable(PP_Instance instance,
+ PP_Flash_Clipboard_Type clipboard_type,
+ uint32_t format) OVERRIDE;
+ virtual PP_Var ReadData(PP_Instance instance,
+ PP_Flash_Clipboard_Type clipboard_type,
+ uint32_t format) OVERRIDE;
+ virtual int32_t WriteData(PP_Instance instance,
+ PP_Flash_Clipboard_Type clipboard_type,
+ uint32_t data_item_count,
+ const uint32_t formats[],
+ const PP_Var data_items[]) OVERRIDE;
+
+ private:
+ FlashClipboardFormatRegistry clipboard_formats_;
+
+ DISALLOW_COPY_AND_ASSIGN(FlashClipboardResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_FLASH_CLIPBOARD_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/flash_drm_resource.cc b/chromium/ppapi/proxy/flash_drm_resource.cc
new file mode 100644
index 00000000000..a4be23beb8a
--- /dev/null
+++ b/chromium/ppapi/proxy/flash_drm_resource.cc
@@ -0,0 +1,100 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/flash_drm_resource.h"
+
+#include "base/bind.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/dispatch_reply_message.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_file_ref_proxy.h"
+#include "ppapi/shared_impl/ppb_file_ref_shared.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+namespace proxy {
+
+FlashDRMResource::FlashDRMResource(Connection connection,
+ PP_Instance instance)
+ : PluginResource(connection, instance) {
+ SendCreate(BROWSER, PpapiHostMsg_FlashDRM_Create());
+ SendCreate(RENDERER, PpapiHostMsg_FlashDRM_Create());
+}
+
+FlashDRMResource::~FlashDRMResource() {
+}
+
+thunk::PPB_Flash_DRM_API* FlashDRMResource::AsPPB_Flash_DRM_API() {
+ return this;
+}
+
+int32_t FlashDRMResource::GetDeviceID(PP_Var* id,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!id)
+ return PP_ERROR_BADARGUMENT;
+
+ *id = PP_MakeUndefined();
+
+ Call<PpapiPluginMsg_FlashDRM_GetDeviceIDReply>(
+ BROWSER,
+ PpapiHostMsg_FlashDRM_GetDeviceID(),
+ base::Bind(&FlashDRMResource::OnPluginMsgGetDeviceIDReply, this,
+ id, callback));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+PP_Bool FlashDRMResource::GetHmonitor(int64_t* hmonitor) {
+ int64_t hmonitor_out;
+ int32_t result = SyncCall<PpapiPluginMsg_FlashDRM_GetHmonitorReply>(
+ BROWSER,
+ PpapiHostMsg_FlashDRM_GetHmonitor(),
+ &hmonitor_out);
+ if (result != PP_OK)
+ return PP_FALSE;
+ *hmonitor = hmonitor_out;
+ return PP_TRUE;
+}
+
+int32_t FlashDRMResource::GetVoucherFile(
+ PP_Resource* file_ref,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!file_ref)
+ return PP_ERROR_BADARGUMENT;
+
+ *file_ref = 0;
+
+ Call<PpapiPluginMsg_FlashDRM_GetVoucherFileReply>(
+ RENDERER,
+ PpapiHostMsg_FlashDRM_GetVoucherFile(),
+ base::Bind(&FlashDRMResource::OnPluginMsgGetVoucherFileReply, this,
+ file_ref, callback));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void FlashDRMResource::OnPluginMsgGetDeviceIDReply(
+ PP_Var* dest,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const std::string& id) {
+ if (TrackedCallback::IsPending(callback)) {
+ if (params.result() == PP_OK)
+ *dest = StringVar::StringToPPVar(id);
+ callback->Run(params.result());
+ }
+}
+
+void FlashDRMResource::OnPluginMsgGetVoucherFileReply(
+ PP_Resource* dest,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const PPB_FileRef_CreateInfo& file_info) {
+ if (TrackedCallback::IsPending(callback)) {
+ if (params.result() == PP_OK)
+ *dest = PPB_FileRef_Proxy::DeserializeFileRef(file_info);
+ callback->Run(params.result());
+ }
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/flash_drm_resource.h b/chromium/ppapi/proxy/flash_drm_resource.h
new file mode 100644
index 00000000000..12c71e82817
--- /dev/null
+++ b/chromium/ppapi/proxy/flash_drm_resource.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_FLASH_DRM_RESOURCE_H_
+#define PPAPI_PROXY_FLASH_DRM_RESOURCE_H_
+
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/ppb_flash_drm_api.h"
+
+namespace ppapi {
+struct PPB_FileRef_CreateInfo;
+}
+
+namespace ppapi {
+namespace proxy {
+
+class FlashDRMResource
+ : public PluginResource,
+ public thunk::PPB_Flash_DRM_API {
+ public:
+ FlashDRMResource(Connection connection,
+ PP_Instance instance);
+ virtual ~FlashDRMResource();
+
+ // Resource override.
+ virtual thunk::PPB_Flash_DRM_API* AsPPB_Flash_DRM_API() OVERRIDE;
+
+ // PPB_Flash_DRM_API implementation.
+ virtual int32_t GetDeviceID(PP_Var* id,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual PP_Bool GetHmonitor(int64_t* hmonitor) OVERRIDE;
+ virtual int32_t GetVoucherFile(
+ PP_Resource* file_ref,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+
+ private:
+ void OnPluginMsgGetDeviceIDReply(PP_Var* dest,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const std::string& id);
+ void OnPluginMsgGetVoucherFileReply(PP_Resource* dest,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const PPB_FileRef_CreateInfo& file_info);
+
+ DISALLOW_COPY_AND_ASSIGN(FlashDRMResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_FLASH_DRM_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/flash_file_resource.cc b/chromium/ppapi/proxy/flash_file_resource.cc
new file mode 100644
index 00000000000..1387eb7c58b
--- /dev/null
+++ b/chromium/ppapi/proxy/flash_file_resource.cc
@@ -0,0 +1,230 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/flash_file_resource.h"
+
+#include "base/files/file_path.h"
+#include "ipc/ipc_message.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/file_type_conversion.h"
+#include "ppapi/shared_impl/scoped_pp_var.h"
+#include "ppapi/shared_impl/time_conversion.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/enter.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+// Returns the path that a PPB_FileRef resource references as long as it is an
+// PP_FILESYSTEMTYPE_EXTERNAL path. Returns an empty string on error.
+std::string GetPathFromFileRef(PP_Resource file_ref) {
+ thunk::EnterResourceNoLock<thunk::PPB_FileRef_API> enter(file_ref, true);
+ if (enter.failed())
+ return std::string();
+ if (enter.object()->GetFileSystemType() != PP_FILESYSTEMTYPE_EXTERNAL)
+ return std::string();
+ ScopedPPVar var(ScopedPPVar::PassRef(), enter.object()->GetAbsolutePath());
+ StringVar* string_var = StringVar::FromPPVar(var.get());
+ if (!string_var)
+ return std::string();
+ return string_var->value();
+}
+
+} // namespace
+
+FlashFileResource::FlashFileResource(Connection connection,
+ PP_Instance instance)
+ : PluginResource(connection, instance) {
+ SendCreate(BROWSER, PpapiHostMsg_FlashFile_Create());
+}
+
+FlashFileResource::~FlashFileResource() {
+}
+
+thunk::PPB_Flash_File_API* FlashFileResource::AsPPB_Flash_File_API() {
+ return this;
+}
+
+int32_t FlashFileResource::OpenFile(PP_Instance /*instance*/,
+ const char* path,
+ int32_t mode,
+ PP_FileHandle* file) {
+ return OpenFileHelper(path, PepperFilePath::DOMAIN_MODULE_LOCAL, mode, file);
+}
+
+int32_t FlashFileResource::RenameFile(PP_Instance /*instance*/,
+ const char* path_from,
+ const char* path_to) {
+ PepperFilePath pepper_from(PepperFilePath::DOMAIN_MODULE_LOCAL,
+ base::FilePath::FromUTF8Unsafe(path_from));
+ PepperFilePath pepper_to(PepperFilePath::DOMAIN_MODULE_LOCAL,
+ base::FilePath::FromUTF8Unsafe(path_to));
+
+ int32_t error = SyncCall<IPC::Message>(
+ BROWSER, PpapiHostMsg_FlashFile_RenameFile(pepper_from, pepper_to));
+
+ return error;
+}
+
+int32_t FlashFileResource::DeleteFileOrDir(PP_Instance /*instance*/,
+ const char* path,
+ PP_Bool recursive) {
+ PepperFilePath pepper_path(PepperFilePath::DOMAIN_MODULE_LOCAL,
+ base::FilePath::FromUTF8Unsafe(path));
+
+ int32_t error = SyncCall<IPC::Message>(
+ BROWSER, PpapiHostMsg_FlashFile_DeleteFileOrDir(pepper_path,
+ PP_ToBool(recursive)));
+
+ return error;
+}
+
+int32_t FlashFileResource::CreateDir(PP_Instance /*instance*/,
+ const char* path) {
+ PepperFilePath pepper_path(PepperFilePath::DOMAIN_MODULE_LOCAL,
+ base::FilePath::FromUTF8Unsafe(path));
+
+ int32_t error = SyncCall<IPC::Message>(BROWSER,
+ PpapiHostMsg_FlashFile_CreateDir(pepper_path));
+
+ return error;
+}
+
+int32_t FlashFileResource::QueryFile(PP_Instance /*instance*/,
+ const char* path,
+ PP_FileInfo* info) {
+ return QueryFileHelper(path, PepperFilePath::DOMAIN_MODULE_LOCAL, info);
+}
+
+int32_t FlashFileResource::GetDirContents(PP_Instance /*instance*/,
+ const char* path,
+ PP_DirContents_Dev** contents) {
+ ppapi::DirContents entries;
+ PepperFilePath pepper_path(PepperFilePath::DOMAIN_MODULE_LOCAL,
+ base::FilePath::FromUTF8Unsafe(path));
+
+ int32_t error = SyncCall<PpapiPluginMsg_FlashFile_GetDirContentsReply>(
+ BROWSER, PpapiHostMsg_FlashFile_GetDirContents(pepper_path), &entries);
+
+ if (error == PP_OK) {
+ // 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 ppapi::DirEntry& source = entries[i];
+ PP_DirEntry_Dev* dest = &(*contents)->entries[i];
+ std::string name = source.name.AsUTF8Unsafe();
+ char* name_copy = new char[name.size() + 1];
+ memcpy(name_copy, name.c_str(), name.size() + 1);
+ dest->name = name_copy;
+ dest->is_dir = PP_FromBool(source.is_dir);
+ }
+ }
+
+ return error;
+}
+
+void FlashFileResource::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;
+}
+
+int32_t FlashFileResource::CreateTemporaryFile(PP_Instance /*instance*/,
+ PP_FileHandle* file) {
+ if (!file)
+ return PP_ERROR_BADARGUMENT;
+
+ IPC::Message unused;
+ ResourceMessageReplyParams reply_params;
+ int32_t error = GenericSyncCall(BROWSER,
+ PpapiHostMsg_FlashFile_CreateTemporaryFile(), &unused, &reply_params);
+ if (error != PP_OK)
+ return error;
+
+ IPC::PlatformFileForTransit transit_file;
+ if (!reply_params.TakeFileHandleAtIndex(0, &transit_file))
+ return PP_ERROR_FAILED;
+
+ *file = IPC::PlatformFileForTransitToPlatformFile(transit_file);
+ return PP_OK;
+}
+
+int32_t FlashFileResource::OpenFileRef(PP_Instance /*instance*/,
+ PP_Resource file_ref,
+ int32_t mode,
+ PP_FileHandle* file) {
+ return OpenFileHelper(GetPathFromFileRef(file_ref),
+ PepperFilePath::DOMAIN_ABSOLUTE, mode, file);
+}
+
+int32_t FlashFileResource::QueryFileRef(PP_Instance /*instance*/,
+ PP_Resource file_ref,
+ PP_FileInfo* info) {
+ return QueryFileHelper(GetPathFromFileRef(file_ref),
+ PepperFilePath::DOMAIN_ABSOLUTE, info);
+}
+
+int32_t FlashFileResource::OpenFileHelper(const std::string& path,
+ PepperFilePath::Domain domain_type,
+ int32_t mode,
+ PP_FileHandle* file) {
+ if (path.empty() ||
+ !ppapi::PepperFileOpenFlagsToPlatformFileFlags(mode, NULL) ||
+ !file)
+ return PP_ERROR_BADARGUMENT;
+
+ PepperFilePath pepper_path(domain_type, base::FilePath::FromUTF8Unsafe(path));
+
+ IPC::Message unused;
+ ResourceMessageReplyParams reply_params;
+ int32_t error = GenericSyncCall(BROWSER,
+ PpapiHostMsg_FlashFile_OpenFile(pepper_path, mode), &unused,
+ &reply_params);
+ if (error != PP_OK)
+ return error;
+
+ IPC::PlatformFileForTransit transit_file;
+ if (!reply_params.TakeFileHandleAtIndex(0, &transit_file))
+ return PP_ERROR_FAILED;
+
+ *file = IPC::PlatformFileForTransitToPlatformFile(transit_file);
+ return PP_OK;
+}
+
+int32_t FlashFileResource::QueryFileHelper(const std::string& path,
+ PepperFilePath::Domain domain_type,
+ PP_FileInfo* info) {
+ if (path.empty() || !info)
+ return PP_ERROR_BADARGUMENT;
+
+ base::PlatformFileInfo file_info;
+ PepperFilePath pepper_path(domain_type, base::FilePath::FromUTF8Unsafe(path));
+
+ int32_t error = SyncCall<PpapiPluginMsg_FlashFile_QueryFileReply>(BROWSER,
+ PpapiHostMsg_FlashFile_QueryFile(pepper_path), &file_info);
+
+ if (error == PP_OK) {
+ info->size = file_info.size;
+ info->creation_time = TimeToPPTime(file_info.creation_time);
+ info->last_access_time = TimeToPPTime(file_info.last_accessed);
+ info->last_modified_time = TimeToPPTime(file_info.last_modified);
+ info->system_type = PP_FILESYSTEMTYPE_EXTERNAL;
+ if (file_info.is_directory)
+ info->type = PP_FILETYPE_DIRECTORY;
+ else
+ info->type = PP_FILETYPE_REGULAR;
+ }
+
+ return error;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/flash_file_resource.h b/chromium/ppapi/proxy/flash_file_resource.h
new file mode 100644
index 00000000000..f8c4b18815b
--- /dev/null
+++ b/chromium/ppapi/proxy/flash_file_resource.h
@@ -0,0 +1,73 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_FLASH_FILE_RESOURCE_H_
+#define PPAPI_PROXY_FLASH_FILE_RESOURCE_H_
+
+#include <string>
+
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/shared_impl/file_path.h"
+#include "ppapi/thunk/ppb_flash_file_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class FlashFileResource
+ : public PluginResource,
+ public thunk::PPB_Flash_File_API {
+ public:
+ FlashFileResource(Connection connection, PP_Instance instance);
+ virtual ~FlashFileResource();
+
+ // Resource overrides.
+ virtual thunk::PPB_Flash_File_API* AsPPB_Flash_File_API() OVERRIDE;
+
+ // PPB_Flash_Functions_API.
+ virtual int32_t OpenFile(PP_Instance instance,
+ const char* path,
+ int32_t mode,
+ PP_FileHandle* file) OVERRIDE;
+ virtual int32_t RenameFile(PP_Instance instance,
+ const char* path_from,
+ const char* path_to) OVERRIDE;
+ virtual int32_t DeleteFileOrDir(PP_Instance instance,
+ const char* path,
+ PP_Bool recursive) OVERRIDE;
+ virtual int32_t CreateDir(PP_Instance instance, const char* path) OVERRIDE;
+ virtual int32_t QueryFile(PP_Instance instance,
+ const char* path,
+ PP_FileInfo* info) OVERRIDE;
+ virtual int32_t GetDirContents(PP_Instance instance,
+ const char* path,
+ PP_DirContents_Dev** contents) OVERRIDE;
+ virtual void FreeDirContents(PP_Instance instance,
+ PP_DirContents_Dev* contents) OVERRIDE;
+ virtual int32_t CreateTemporaryFile(PP_Instance instance,
+ PP_FileHandle* file) OVERRIDE;
+ virtual int32_t OpenFileRef(PP_Instance instance,
+ PP_Resource file_ref,
+ int32_t mode,
+ PP_FileHandle* file) OVERRIDE;
+ virtual int32_t QueryFileRef(PP_Instance instance,
+ PP_Resource file_ref,
+ PP_FileInfo* info) OVERRIDE;
+
+ private:
+ int32_t OpenFileHelper(const std::string& path,
+ PepperFilePath::Domain domain_type,
+ int32_t mode,
+ PP_FileHandle* file);
+ int32_t QueryFileHelper(const std::string& path,
+ PepperFilePath::Domain domain_type,
+ PP_FileInfo* info);
+
+ DISALLOW_COPY_AND_ASSIGN(FlashFileResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_FLASH_FILE_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/flash_font_file_resource.cc b/chromium/ppapi/proxy/flash_font_file_resource.cc
new file mode 100644
index 00000000000..86caf1fff98
--- /dev/null
+++ b/chromium/ppapi/proxy/flash_font_file_resource.cc
@@ -0,0 +1,82 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/flash_font_file_resource.h"
+
+#include <cstring>
+
+#include "ppapi/c/dev/ppb_font_dev.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace ppapi {
+namespace proxy {
+
+FlashFontFileResource::FlashFontFileResource(
+ Connection connection,
+ PP_Instance instance,
+ const PP_BrowserFont_Trusted_Description* description,
+ PP_PrivateFontCharset charset)
+ : PluginResource(connection, instance),
+ charset_(charset) {
+ description_.SetFromPPBrowserFontDescription(*description);
+}
+
+FlashFontFileResource::~FlashFontFileResource() {
+}
+
+thunk::PPB_Flash_FontFile_API*
+ FlashFontFileResource::AsPPB_Flash_FontFile_API() {
+ return this;
+}
+
+PP_Bool FlashFontFileResource::GetFontTable(uint32_t table,
+ void* output,
+ uint32_t* output_length) {
+ if (!output_length)
+ return PP_FALSE;
+
+ if (!sent_create_to_renderer()) {
+ SendCreate(
+ RENDERER, PpapiHostMsg_FlashFontFile_Create(description_, charset_));
+ }
+
+ std::string* contents = GetFontTable(table);
+ if (!contents) {
+ std::string out_contents;
+ int32_t result = SyncCall<PpapiPluginMsg_FlashFontFile_GetFontTableReply>(
+ RENDERER, PpapiHostMsg_FlashFontFile_GetFontTable(table),
+ &out_contents);
+ if (result != PP_OK)
+ return PP_FALSE;
+
+ contents = AddFontTable(table, out_contents);
+ }
+
+ // If we are going to copy the data into |output|, it must be big enough.
+ if (output && *output_length < contents->size())
+ return PP_FALSE;
+
+ *output_length = static_cast<uint32_t>(contents->size());
+ if (output)
+ memcpy(output, contents->c_str(), *output_length);
+ return PP_TRUE;
+}
+
+std::string* FlashFontFileResource::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* FlashFontFileResource::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 proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/flash_font_file_resource.h b/chromium/ppapi/proxy/flash_font_file_resource.h
new file mode 100644
index 00000000000..5bc633a4fe6
--- /dev/null
+++ b/chromium/ppapi/proxy/flash_font_file_resource.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_FLASH_FONT_FILE_RESOURCE_H_
+#define PPAPI_PROXY_FLASH_FONT_FILE_RESOURCE_H_
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/linked_ptr.h"
+#include "ppapi/c/private/pp_private_font_charset.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/serialized_structs.h"
+#include "ppapi/thunk/ppb_flash_font_file_api.h"
+
+struct PP_BrowserFont_Trusted_Description;
+
+namespace ppapi {
+namespace proxy {
+
+// TODO(yzshen): write unittest and browser test.
+class FlashFontFileResource : public PluginResource,
+ public thunk::PPB_Flash_FontFile_API {
+ public:
+ FlashFontFileResource(Connection connection,
+ PP_Instance instance,
+ const PP_BrowserFont_Trusted_Description* description,
+ PP_PrivateFontCharset charset);
+ virtual ~FlashFontFileResource();
+
+ // Resource overrides.
+ virtual thunk::PPB_Flash_FontFile_API* AsPPB_Flash_FontFile_API() OVERRIDE;
+
+ // PPB_Flash_FontFile_API.
+ virtual PP_Bool GetFontTable(uint32_t table,
+ void* output,
+ uint32_t* output_length) OVERRIDE;
+
+ private:
+ // 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);
+
+ typedef std::map<uint32_t, linked_ptr<std::string> > FontTableMap;
+ FontTableMap font_tables_;
+
+ SerializedFontDescription description_;
+ PP_PrivateFontCharset charset_;
+
+ DISALLOW_COPY_AND_ASSIGN(FlashFontFileResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_FLASH_FONT_FILE_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/flash_fullscreen_resource.cc b/chromium/ppapi/proxy/flash_fullscreen_resource.cc
new file mode 100644
index 00000000000..90a68fcf6b5
--- /dev/null
+++ b/chromium/ppapi/proxy/flash_fullscreen_resource.cc
@@ -0,0 +1,46 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/flash_fullscreen_resource.h"
+
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace ppapi {
+namespace proxy {
+
+FlashFullscreenResource::FlashFullscreenResource(Connection connection,
+ PP_Instance instance)
+ : PluginResource(connection, instance),
+ is_fullscreen_(PP_FALSE) {
+}
+
+FlashFullscreenResource::~FlashFullscreenResource() {
+}
+
+thunk::PPB_Flash_Fullscreen_API*
+FlashFullscreenResource::AsPPB_Flash_Fullscreen_API() {
+ return this;
+}
+
+PP_Bool FlashFullscreenResource::IsFullscreen(PP_Instance instance) {
+ return is_fullscreen_;
+}
+
+PP_Bool FlashFullscreenResource::SetFullscreen(PP_Instance instance,
+ PP_Bool fullscreen) {
+ if (!sent_create_to_renderer())
+ SendCreate(RENDERER, PpapiHostMsg_FlashFullscreen_Create());
+ int32_t result = SyncCall<IPC::Message>(RENDERER,
+ PpapiHostMsg_FlashFullscreen_SetFullscreen(PP_ToBool(fullscreen)));
+ return PP_FromBool(result == PP_OK);
+}
+
+void FlashFullscreenResource::SetLocalIsFullscreen(PP_Instance instance,
+ PP_Bool is_fullscreen) {
+ is_fullscreen_ = is_fullscreen;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/flash_fullscreen_resource.h b/chromium/ppapi/proxy/flash_fullscreen_resource.h
new file mode 100644
index 00000000000..c6d5ccbed53
--- /dev/null
+++ b/chromium/ppapi/proxy/flash_fullscreen_resource.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_FLASH_FULLSCREEN_RESOURCE_H_
+#define PPAPI_PROXY_FLASH_FULLSCREEN_RESOURCE_H_
+
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/thunk/ppb_flash_fullscreen_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class FlashFullscreenResource
+ : public PluginResource,
+ public thunk::PPB_Flash_Fullscreen_API {
+ public:
+ FlashFullscreenResource(Connection connection,
+ PP_Instance instance);
+ virtual ~FlashFullscreenResource();
+
+ // Resource overrides.
+ virtual thunk::PPB_Flash_Fullscreen_API*
+ AsPPB_Flash_Fullscreen_API() OVERRIDE;
+
+ // PPB_Flash_Fullscreen_API implementation.
+ virtual PP_Bool IsFullscreen(PP_Instance instance) OVERRIDE;
+ virtual PP_Bool SetFullscreen(PP_Instance instance,
+ PP_Bool fullscreen) OVERRIDE;
+ virtual void SetLocalIsFullscreen(PP_Instance instance,
+ PP_Bool is_fullscreen) OVERRIDE;
+
+ private:
+ PP_Bool is_fullscreen_;
+
+ DISALLOW_COPY_AND_ASSIGN(FlashFullscreenResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_FLASH_FULLSCREEN_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/flash_menu_resource.cc b/chromium/ppapi/proxy/flash_menu_resource.cc
new file mode 100644
index 00000000000..1c3b7f03729
--- /dev/null
+++ b/chromium/ppapi/proxy/flash_menu_resource.cc
@@ -0,0 +1,97 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/flash_menu_resource.h"
+
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/serialized_flash_menu.h"
+
+namespace ppapi {
+namespace proxy {
+
+FlashMenuResource::FlashMenuResource(Connection connection,
+ PP_Instance instance)
+ : PluginResource(connection, instance),
+ selected_id_dest_(NULL) {
+}
+
+FlashMenuResource::~FlashMenuResource() {
+}
+
+bool FlashMenuResource::Initialize(const PP_Flash_Menu* menu_data) {
+ SerializedFlashMenu serialized_menu;
+ if (!menu_data || !serialized_menu.SetPPMenu(menu_data))
+ return false;
+ SendCreate(RENDERER, PpapiHostMsg_FlashMenu_Create(serialized_menu));
+ return true;
+}
+
+thunk::PPB_Flash_Menu_API* FlashMenuResource::AsPPB_Flash_Menu_API() {
+ return this;
+}
+
+int32_t FlashMenuResource::Show(
+ const PP_Point* location,
+ int32_t* selected_id,
+ scoped_refptr<TrackedCallback> callback) {
+ if (TrackedCallback::IsPending(callback_))
+ return PP_ERROR_INPROGRESS;
+
+ selected_id_dest_ = selected_id;
+ callback_ = callback;
+
+ // This must be a sync message even though we don't care about the result.
+ // The actual reply will be sent asynchronously in the future. This sync
+ // request is due to the following deadlock:
+ //
+ // 1. Flash sends a show request to the renderer.
+ // 2. The show handler in the renderer (in the case of full screen) requests
+ // the window rect which is a sync message to the browser. This causes
+ // a nested message loop to be spun up in the renderer.
+ // 3. Flash expects context menus to be synchronous so it starts a nested
+ // message loop. This creates a second nested message loop in both the
+ // plugin and renderer process.
+ // 4. The browser sends the window rect reply to unblock the renderer, but
+ // it's in the second nested message loop and the reply will *not*
+ // unblock this loop.
+ // 5. The second loop won't exit until the message loop is complete, but
+ // that can't start until the first one exits.
+ //
+ // Having this message sync forces the sync request from the renderer to the
+ // browser for the window rect will complete before Flash can run a nested
+ // message loop to wait for the result of the menu.
+ SyncCall<IPC::Message>(RENDERER, PpapiHostMsg_FlashMenu_Show(*location));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void FlashMenuResource::OnReplyReceived(
+ const proxy::ResourceMessageReplyParams& params,
+ const IPC::Message& msg) {
+ // Because the Show call is synchronous but we ignore the sync result, we
+ // can't use the normal reply dispatch and have to do it manually here.
+ switch (msg.type()) {
+ case PpapiPluginMsg_FlashMenu_ShowReply::ID: {
+ int32_t selected_id;
+ if (ppapi::UnpackMessage<PpapiPluginMsg_FlashMenu_ShowReply>(
+ msg, &selected_id))
+ OnShowReply(params, selected_id);
+ break;
+ }
+ }
+}
+
+void FlashMenuResource::OnShowReply(
+ const proxy::ResourceMessageReplyParams& params,
+ int32_t selected_id) {
+ if (!TrackedCallback::IsPending(callback_))
+ return;
+
+ *selected_id_dest_ = selected_id;
+ selected_id_dest_ = NULL;
+ callback_->Run(params.result());
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/flash_menu_resource.h b/chromium/ppapi/proxy/flash_menu_resource.h
new file mode 100644
index 00000000000..46b227a6f75
--- /dev/null
+++ b/chromium/ppapi/proxy/flash_menu_resource.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_FLASH_MENU_RESOURCE_H_
+#define PPAPI_PROXY_FLASH_MENU_RESOURCE_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/ppb_flash_menu_api.h"
+
+struct PP_Flash_Menu;
+
+namespace ppapi {
+namespace proxy {
+
+class FlashMenuResource
+ : public PluginResource,
+ public thunk::PPB_Flash_Menu_API {
+ public:
+ // You must call Initialize after construction.
+ FlashMenuResource(Connection connection, PP_Instance instance);
+ virtual ~FlashMenuResource();
+
+ // Returns true on success. False means that this object can not be used.
+ // This has to be separate from the constructor because the menu data could
+ // be invalid.
+ bool Initialize(const PP_Flash_Menu* menu_data);
+
+ // Resource overrides.
+ virtual thunk::PPB_Flash_Menu_API* AsPPB_Flash_Menu_API() OVERRIDE;
+
+ // PPB_Flash_Menu_API.
+ virtual int32_t Show(const PP_Point* location,
+ int32_t* selected_id,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+
+ private:
+ virtual void OnReplyReceived(const proxy::ResourceMessageReplyParams& params,
+ const IPC::Message& msg) OVERRIDE;
+
+ void OnShowReply(
+ const proxy::ResourceMessageReplyParams& params,
+ int32_t selected_id);
+
+ int* selected_id_dest_;
+ scoped_refptr<TrackedCallback> callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(FlashMenuResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_FLASH_MENU_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/flash_resource.cc b/chromium/ppapi/proxy/flash_resource.cc
new file mode 100644
index 00000000000..26a80ae8222
--- /dev/null
+++ b/chromium/ppapi/proxy/flash_resource.cc
@@ -0,0 +1,256 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/flash_resource.h"
+
+#include <cmath>
+
+#include "base/containers/mru_cache.h"
+#include "base/debug/crash_logging.h"
+#include "base/lazy_instance.h"
+#include "base/time/time.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/private/ppb_flash.h"
+#include "ppapi/c/trusted/ppb_browser_font_trusted.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/serialized_structs.h"
+#include "ppapi/shared_impl/ppapi_preferences.h"
+#include "ppapi/shared_impl/scoped_pp_var.h"
+#include "ppapi/shared_impl/time_conversion.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_url_request_info_api.h"
+
+using ppapi::thunk::EnterResourceNoLock;
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+struct LocalTimeZoneOffsetEntry {
+ base::TimeTicks expiration;
+ double offset;
+};
+
+class LocalTimeZoneOffsetCache
+ : public base::MRUCache<PP_Time, LocalTimeZoneOffsetEntry> {
+ public:
+ LocalTimeZoneOffsetCache()
+ : base::MRUCache<PP_Time, LocalTimeZoneOffsetEntry>(kCacheSize) {}
+ private:
+ static const size_t kCacheSize = 100;
+};
+
+base::LazyInstance<LocalTimeZoneOffsetCache>::Leaky
+ g_local_time_zone_offset_cache = LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+FlashResource::FlashResource(Connection connection,
+ PP_Instance instance,
+ PluginDispatcher* plugin_dispatcher)
+ : PluginResource(connection, instance),
+ plugin_dispatcher_(plugin_dispatcher) {
+ SendCreate(RENDERER, PpapiHostMsg_Flash_Create());
+ SendCreate(BROWSER, PpapiHostMsg_Flash_Create());
+}
+
+FlashResource::~FlashResource() {
+}
+
+thunk::PPB_Flash_Functions_API* FlashResource::AsPPB_Flash_Functions_API() {
+ return this;
+}
+
+PP_Var FlashResource::GetProxyForURL(PP_Instance instance,
+ const std::string& url) {
+ std::string proxy;
+ int32_t result = SyncCall<PpapiPluginMsg_Flash_GetProxyForURLReply>(RENDERER,
+ PpapiHostMsg_Flash_GetProxyForURL(url), &proxy);
+
+ if (result == PP_OK)
+ return StringVar::StringToPPVar(proxy);
+ return PP_MakeUndefined();
+}
+
+void FlashResource::UpdateActivity(PP_Instance instance) {
+ Post(BROWSER, PpapiHostMsg_Flash_UpdateActivity());
+}
+
+PP_Bool FlashResource::SetCrashData(PP_Instance instance,
+ PP_FlashCrashKey key,
+ PP_Var value) {
+ StringVar* url_string_var(StringVar::FromPPVar(value));
+ if (!url_string_var)
+ return PP_FALSE;
+ switch (key) {
+ case PP_FLASHCRASHKEY_URL: {
+ PluginGlobals::Get()->SetActiveURL(url_string_var->value());
+ return PP_TRUE;
+ }
+ case PP_FLASHCRASHKEY_RESOURCE_URL: {
+ base::debug::SetCrashKeyValue("subresource_url", url_string_var->value());
+ return PP_TRUE;
+ }
+ }
+ return PP_FALSE;
+}
+
+double FlashResource::GetLocalTimeZoneOffset(PP_Instance instance,
+ PP_Time t) {
+ LocalTimeZoneOffsetCache& cache = g_local_time_zone_offset_cache.Get();
+
+ // Get the minimum PP_Time value that shares the same minute as |t|.
+ // Use cached offset if cache hasn't expired and |t| is in the same minute as
+ // the time for the cached offset (assume offsets change on minute
+ // boundaries).
+ PP_Time t_minute_base = floor(t / 60.0) * 60.0;
+ LocalTimeZoneOffsetCache::iterator iter = cache.Get(t_minute_base);
+ base::TimeTicks now = base::TimeTicks::Now();
+ if (iter != cache.end() && now < iter->second.expiration)
+ return iter->second.offset;
+
+ // Cache the local offset for ten seconds, since it's slow on XP and Linux.
+ // Note that TimeTicks does not continue counting across sleep/resume on all
+ // platforms. This may be acceptable for 10 seconds, but if in the future this
+ // is changed to one minute or more, then we should consider using base::Time.
+ const int64 kMaxCachedLocalOffsetAgeInSeconds = 10;
+ base::TimeDelta expiration_delta =
+ base::TimeDelta::FromSeconds(kMaxCachedLocalOffsetAgeInSeconds);
+
+ LocalTimeZoneOffsetEntry cache_entry;
+ cache_entry.expiration = now + expiration_delta;
+ cache_entry.offset = 0.0;
+
+ // We can't do the conversion here on Linux because the localtime calls
+ // require filesystem access prohibited by the sandbox.
+ // TODO(shess): Figure out why OSX needs the access, the sandbox warmup should
+ // handle it. http://crbug.com/149006
+#if defined(OS_LINUX) || defined(OS_MACOSX)
+ int32_t result = SyncCall<PpapiPluginMsg_Flash_GetLocalTimeZoneOffsetReply>(
+ BROWSER,
+ PpapiHostMsg_Flash_GetLocalTimeZoneOffset(PPTimeToTime(t)),
+ &cache_entry.offset);
+ if (result != PP_OK)
+ cache_entry.offset = 0.0;
+#else
+ cache_entry.offset = PPGetLocalTimeZoneOffset(PPTimeToTime(t));
+#endif
+
+ cache.Put(t_minute_base, cache_entry);
+ return cache_entry.offset;
+}
+
+PP_Var FlashResource::GetSetting(PP_Instance instance,
+ PP_FlashSetting setting) {
+ switch (setting) {
+ case PP_FLASHSETTING_3DENABLED:
+ return PP_MakeBool(PP_FromBool(
+ plugin_dispatcher_->preferences().is_3d_supported));
+ case PP_FLASHSETTING_INCOGNITO:
+ return PP_MakeBool(PP_FromBool(plugin_dispatcher_->incognito()));
+ case PP_FLASHSETTING_STAGE3DENABLED:
+ return PP_MakeBool(PP_FromBool(
+ plugin_dispatcher_->preferences().is_stage3d_supported));
+ case PP_FLASHSETTING_STAGE3DBASELINEENABLED:
+ return PP_MakeBool(PP_FromBool(
+ plugin_dispatcher_->preferences().is_stage3d_baseline_supported));
+ case PP_FLASHSETTING_LANGUAGE:
+ return StringVar::StringToPPVar(
+ PluginGlobals::Get()->GetUILanguage());
+ case PP_FLASHSETTING_NUMCORES:
+ return PP_MakeInt32(
+ plugin_dispatcher_->preferences().number_of_cpu_cores);
+ case PP_FLASHSETTING_LSORESTRICTIONS: {
+ int32_t restrictions;
+ int32_t result =
+ SyncCall<PpapiPluginMsg_Flash_GetLocalDataRestrictionsReply>(BROWSER,
+ PpapiHostMsg_Flash_GetLocalDataRestrictions(), &restrictions);
+ if (result != PP_OK)
+ return PP_MakeInt32(PP_FLASHLSORESTRICTIONS_NONE);
+ return PP_MakeInt32(restrictions);
+ }
+ }
+ return PP_MakeUndefined();
+}
+
+void FlashResource::SetInstanceAlwaysOnTop(PP_Instance instance,
+ PP_Bool on_top) {
+ Post(RENDERER, PpapiHostMsg_Flash_SetInstanceAlwaysOnTop(PP_ToBool(on_top)));
+}
+
+PP_Bool FlashResource::DrawGlyphs(
+ PP_Instance instance,
+ PP_Resource pp_image_data,
+ const PP_BrowserFont_Trusted_Description* font_desc,
+ uint32_t color,
+ const PP_Point* position,
+ const PP_Rect* clip,
+ const float transformation[3][3],
+ PP_Bool allow_subpixel_aa,
+ uint32_t glyph_count,
+ const uint16_t glyph_indices[],
+ const PP_Point glyph_advances[]) {
+ EnterResourceNoLock<thunk::PPB_ImageData_API> enter(pp_image_data, true);
+ if (enter.failed())
+ return PP_FALSE;
+ // The instance parameter isn't strictly necessary but we check that it
+ // matches anyway.
+ if (enter.resource()->pp_instance() != instance)
+ return PP_FALSE;
+
+ PPBFlash_DrawGlyphs_Params params;
+ params.image_data = enter.resource()->host_resource();
+ params.font_desc.SetFromPPBrowserFontDescription(*font_desc);
+ 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.allow_subpixel_aa = allow_subpixel_aa;
+
+ 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]);
+
+ // This has to be synchronous because the caller may want to composite on
+ // top of the resulting text after the call is complete.
+ int32_t result = SyncCall<IPC::Message>(RENDERER,
+ PpapiHostMsg_Flash_DrawGlyphs(params));
+ return PP_FromBool(result == PP_OK);
+}
+
+int32_t FlashResource::Navigate(PP_Instance instance,
+ PP_Resource request_info,
+ const char* target,
+ PP_Bool from_user_action) {
+ EnterResourceNoLock<thunk::PPB_URLRequestInfo_API> enter(request_info,
+ true);
+ if (enter.failed())
+ return PP_ERROR_BADRESOURCE;
+ return SyncCall<IPC::Message>(RENDERER, PpapiHostMsg_Flash_Navigate(
+ enter.object()->GetData(), target, PP_ToBool(from_user_action)));
+}
+
+PP_Bool FlashResource::IsRectTopmost(PP_Instance instance,
+ const PP_Rect* rect) {
+ int32_t result = SyncCall<IPC::Message>(RENDERER,
+ PpapiHostMsg_Flash_IsRectTopmost(*rect));
+ return PP_FromBool(result == PP_OK);
+}
+
+void FlashResource::InvokePrinting(PP_Instance instance) {
+ Post(RENDERER, PpapiHostMsg_Flash_InvokePrinting());
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/flash_resource.h b/chromium/ppapi/proxy/flash_resource.h
new file mode 100644
index 00000000000..cfb6b1e7123
--- /dev/null
+++ b/chromium/ppapi/proxy/flash_resource.h
@@ -0,0 +1,75 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_FLASH_RESOURCE_H_
+#define PPAPI_PROXY_FLASH_RESOURCE_H_
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/private/ppb_flash.h"
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/thunk/ppb_flash_functions_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PluginDispatcher;
+
+class FlashResource
+ : public PluginResource,
+ public thunk::PPB_Flash_Functions_API {
+ public:
+ FlashResource(Connection connection,
+ PP_Instance instance,
+ PluginDispatcher* plugin_dispatcher);
+ virtual ~FlashResource();
+
+ // Resource override.
+ virtual thunk::PPB_Flash_Functions_API* AsPPB_Flash_Functions_API() OVERRIDE;
+
+ // PPB_Flash_Functions_API implementation.
+ virtual PP_Var GetProxyForURL(PP_Instance instance,
+ const std::string& url) OVERRIDE;
+ virtual void UpdateActivity(PP_Instance instance) OVERRIDE;
+ virtual PP_Bool SetCrashData(PP_Instance instance,
+ PP_FlashCrashKey key,
+ PP_Var value) OVERRIDE;
+ virtual double GetLocalTimeZoneOffset(PP_Instance instance,
+ PP_Time t) OVERRIDE;
+ virtual PP_Var GetSetting(PP_Instance instance,
+ PP_FlashSetting setting) OVERRIDE;
+ virtual void SetInstanceAlwaysOnTop(PP_Instance instance,
+ PP_Bool on_top) OVERRIDE;
+ virtual PP_Bool DrawGlyphs(
+ PP_Instance instance,
+ PP_Resource pp_image_data,
+ const PP_BrowserFont_Trusted_Description* font_desc,
+ uint32_t color,
+ const PP_Point* position,
+ const PP_Rect* clip,
+ const float transformation[3][3],
+ PP_Bool allow_subpixel_aa,
+ uint32_t glyph_count,
+ const uint16_t glyph_indices[],
+ const PP_Point glyph_advances[]) OVERRIDE;
+ virtual int32_t Navigate(PP_Instance instance,
+ PP_Resource request_info,
+ const char* target,
+ PP_Bool from_user_action) OVERRIDE;
+ virtual PP_Bool IsRectTopmost(PP_Instance instance,
+ const PP_Rect* rect) OVERRIDE;
+ virtual void InvokePrinting(PP_Instance instance) OVERRIDE;
+
+ private:
+ // Non-owning pointer to the PluginDispatcher that owns this object.
+ PluginDispatcher* plugin_dispatcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(FlashResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_FLASH_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/flash_resource_unittest.cc b/chromium/ppapi/proxy/flash_resource_unittest.cc
new file mode 100644
index 00000000000..1a5e7c644d4
--- /dev/null
+++ b/chromium/ppapi/proxy/flash_resource_unittest.cc
@@ -0,0 +1,71 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/c/dev/ppb_video_capture_dev.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/private/ppb_flash.h"
+#include "ppapi/proxy/locking_resource_releaser.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+#include "ppapi/thunk/thunk.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+typedef PluginProxyTest FlashResourceTest;
+
+void* Unused(void* user_data, uint32_t element_count, uint32_t element_size) {
+ return NULL;
+}
+
+} // namespace
+
+// Does a test of EnumerateVideoCaptureDevices() and reply functionality in
+// the plugin side using the public C interfaces.
+TEST_F(FlashResourceTest, EnumerateVideoCaptureDevices) {
+ // TODO(raymes): This doesn't actually check that the data is converted from
+ // |ppapi::DeviceRefData| to |PPB_DeviceRef| correctly, just that the right
+ // messages are sent.
+
+ // Set up a sync call handler that should return this message.
+ std::vector<ppapi::DeviceRefData> reply_device_ref_data;
+ int32_t expected_result = PP_OK;
+ PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply reply_msg(
+ reply_device_ref_data);
+ ResourceSyncCallHandler enumerate_video_devices_handler(
+ &sink(),
+ PpapiHostMsg_DeviceEnumeration_EnumerateDevices::ID,
+ expected_result,
+ reply_msg);
+ sink().AddFilter(&enumerate_video_devices_handler);
+
+ // Set up the arguments to the call.
+ LockingResourceReleaser video_capture(
+ ::ppapi::thunk::GetPPB_VideoCapture_Dev_0_3_Thunk()->Create(
+ pp_instance()));
+ std::vector<PP_Resource> unused;
+ PP_ArrayOutput output;
+ output.GetDataBuffer = &Unused;
+ output.user_data = &unused;
+
+ // Make the call.
+ const PPB_Flash_12_6* flash_iface = ::ppapi::thunk::GetPPB_Flash_12_6_Thunk();
+ int32_t actual_result = flash_iface->EnumerateVideoCaptureDevices(
+ pp_instance(), video_capture.get(), output);
+
+ // Check the result is as expected.
+ EXPECT_EQ(expected_result, actual_result);
+
+ // Should have sent an "DeviceEnumeration_EnumerateDevices" message.
+ ASSERT_TRUE(enumerate_video_devices_handler.last_handled_msg().type() ==
+ PpapiHostMsg_DeviceEnumeration_EnumerateDevices::ID);
+
+ // Remove the filter or it will be destroyed before the sink() is destroyed.
+ sink().RemoveFilter(&enumerate_video_devices_handler);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/gamepad_resource.cc b/chromium/ppapi/proxy/gamepad_resource.cc
new file mode 100644
index 00000000000..1cfc0419705
--- /dev/null
+++ b/chromium/ppapi/proxy/gamepad_resource.cc
@@ -0,0 +1,116 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/gamepad_resource.h"
+
+#include <string.h>
+
+#include "base/bind.h"
+#include "base/threading/platform_thread.h"
+#include "ppapi/proxy/dispatch_reply_message.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/ppb_gamepad_shared.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+// This is the read logic from content/common/gamepad_seqlock.h
+base::subtle::Atomic32 ReadBegin(const base::subtle::Atomic32* sequence) {
+ base::subtle::Atomic32 version;
+ for (;;) {
+ version = base::subtle::NoBarrier_Load(sequence);
+
+ // If the counter is even, then the associated data might be in a
+ // consistent state, so we can try to read.
+ if ((version & 1) == 0)
+ break;
+
+ // Otherwise, the writer is in the middle of an update. Retry the read.
+ base::PlatformThread::YieldCurrentThread();
+ }
+ return version;
+}
+
+bool ReadRetry(const base::subtle::Atomic32* sequence,
+ base::subtle::Atomic32 version) {
+ // If the sequence number was updated then a read should be re-attempted.
+ // -- Load fence, read membarrier
+ return base::subtle::Release_Load(sequence) != version;
+}
+
+} // namespace
+
+GamepadResource::GamepadResource(Connection connection, PP_Instance instance)
+ : PluginResource(connection, instance),
+ buffer_(NULL) {
+ memset(&last_read_, 0, sizeof(last_read_));
+
+ SendCreate(BROWSER, PpapiHostMsg_Gamepad_Create());
+ Call<PpapiPluginMsg_Gamepad_SendMemory>(
+ BROWSER,
+ PpapiHostMsg_Gamepad_RequestMemory(),
+ base::Bind(&GamepadResource::OnPluginMsgSendMemory, this));
+}
+
+GamepadResource::~GamepadResource() {
+}
+
+thunk::PPB_Gamepad_API* GamepadResource::AsPPB_Gamepad_API() {
+ return this;
+}
+
+void GamepadResource::Sample(PP_Instance /* instance */,
+ PP_GamepadsSampleData* data) {
+ if (!buffer_) {
+ // Browser hasn't sent back our shared memory, give the plugin gamepad
+ // data corresponding to "not connected".
+ memset(data, 0, sizeof(PP_GamepadsSampleData));
+ return;
+ }
+
+ // ==========
+ // DANGER
+ // ==========
+ //
+ // This logic is duplicated in the renderer as well. If you change it, that
+ // also needs to be in sync. See gamepad_shared_memory_reader.cc.
+
+ // Only try to read this many times before failing to avoid waiting here
+ // very long in case of contention with the writer.
+ const int kMaximumContentionCount = 10;
+ int contention_count = -1;
+ base::subtle::Atomic32 version;
+ WebKitGamepads read_into;
+ do {
+ version = ReadBegin(&buffer_->sequence);
+ memcpy(&read_into, &buffer_->buffer, sizeof(read_into));
+ ++contention_count;
+ if (contention_count == kMaximumContentionCount)
+ break;
+ } while (ReadRetry(&buffer_->sequence, version));
+
+ // In the event of a read failure, just leave the last read data as-is (the
+ // hardware thread is taking unusally long).
+ if (contention_count < kMaximumContentionCount)
+ ConvertWebKitGamepadData(read_into, &last_read_);
+
+ memcpy(data, &last_read_, sizeof(PP_GamepadsSampleData));
+}
+
+void GamepadResource::OnPluginMsgSendMemory(
+ const ResourceMessageReplyParams& params) {
+ // On failure, the handle will be null and the CHECK below will be tripped.
+ base::SharedMemoryHandle handle = base::SharedMemory::NULLHandle();
+ params.TakeSharedMemoryHandleAtIndex(0, &handle);
+
+ shared_memory_.reset(new base::SharedMemory(handle, true));
+ CHECK(shared_memory_->Map(sizeof(ContentGamepadHardwareBuffer)));
+ buffer_ = static_cast<const ContentGamepadHardwareBuffer*>(
+ shared_memory_->memory());
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/gamepad_resource.h b/chromium/ppapi/proxy/gamepad_resource.h
new file mode 100644
index 00000000000..1a1de3cf5e6
--- /dev/null
+++ b/chromium/ppapi/proxy/gamepad_resource.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_GAMEPAD_RESOURCE_H_
+#define PPAPI_PROXY_GAMEPAD_RESOURCE_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/shared_memory.h"
+#include "ppapi/c/ppb_gamepad.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/ppb_gamepad_shared.h"
+#include "ppapi/thunk/ppb_gamepad_api.h"
+
+struct PP_GamepadsSampleData;
+
+namespace base {
+class SharedMemory;
+}
+
+namespace ppapi {
+namespace proxy {
+
+// This class is a bit weird. It isn't a true resource from the plugin's
+// perspective. But we need to make requests to the browser and get replies.
+// It's more convenient to do this as a resource, so the instance just
+// maintains an internal lazily instantiated copy of this resource.
+class PPAPI_PROXY_EXPORT GamepadResource
+ : public PluginResource,
+ public thunk::PPB_Gamepad_API {
+ public:
+ GamepadResource(Connection connection, PP_Instance instance);
+ virtual ~GamepadResource();
+
+ // Resource implementation.
+ virtual thunk::PPB_Gamepad_API* AsPPB_Gamepad_API() OVERRIDE;
+
+ // PPB_Gamepad_API.
+ virtual void Sample(PP_Instance instance,
+ PP_GamepadsSampleData* data) OVERRIDE;
+
+ private:
+ void OnPluginMsgSendMemory(const ResourceMessageReplyParams& params);
+
+ scoped_ptr<base::SharedMemory> shared_memory_;
+ const ContentGamepadHardwareBuffer* buffer_;
+
+ // Last data returned so we can use this in the event of a read failure.
+ PP_GamepadsSampleData last_read_;
+
+ DISALLOW_COPY_AND_ASSIGN(GamepadResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_GAMEPAD_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/graphics_2d_resource.cc b/chromium/ppapi/proxy/graphics_2d_resource.cc
new file mode 100644
index 00000000000..3bad2e4e13c
--- /dev/null
+++ b/chromium/ppapi/proxy/graphics_2d_resource.cc
@@ -0,0 +1,147 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/graphics_2d_resource.h"
+
+#include "ppapi/c/pp_bool.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/ppb_graphics_2d.h"
+#include "ppapi/proxy/dispatch_reply_message.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/resource_tracker.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_image_data_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+Graphics2DResource::Graphics2DResource(Connection connection,
+ PP_Instance instance,
+ const PP_Size& size,
+ PP_Bool is_always_opaque)
+ : PluginResource(connection, instance),
+ size_(size),
+ is_always_opaque_(is_always_opaque),
+ scale_(1.0f) {
+ // These checks are copied from PPB_ImageData_Impl::Init to make tests passed.
+ // Let's remove/refactor this when start to refactor ImageData.
+ bool bad_args = size.width <= 0 || size.height <= 0 ||
+ static_cast<int64>(size.width) * static_cast<int64>(size.height) >=
+ std::numeric_limits<int32>::max() / 4;
+ if (!bad_args && !sent_create_to_renderer()) {
+ SendCreate(RENDERER,
+ PpapiHostMsg_Graphics2D_Create(size, is_always_opaque));
+ }
+}
+
+Graphics2DResource::~Graphics2DResource() {
+}
+
+PP_Bool Graphics2DResource::Describe(PP_Size* size, PP_Bool* is_always_opaque) {
+ *size = size_;
+ *is_always_opaque = is_always_opaque_;
+ return PP_TRUE;
+}
+
+thunk::PPB_Graphics2D_API* Graphics2DResource::AsPPB_Graphics2D_API() {
+ return this;
+}
+
+void Graphics2DResource::PaintImageData(PP_Resource image_data,
+ const PP_Point* top_left,
+ const PP_Rect* src_rect) {
+ Resource* image_object =
+ PpapiGlobals::Get()->GetResourceTracker()->GetResource(image_data);
+ if (!image_object || pp_instance() != image_object->pp_instance()) {
+ Log(PP_LOGLEVEL_ERROR,
+ "Graphics2DResource.PaintImageData: Bad image resource.");
+ return;
+ }
+
+ PP_Rect dummy;
+ memset(&dummy, 0, sizeof(PP_Rect));
+ Post(RENDERER, PpapiHostMsg_Graphics2D_PaintImageData(
+ image_object->host_resource(), *top_left,
+ !!src_rect, src_rect ? *src_rect : dummy));
+}
+
+void Graphics2DResource::Scroll(const PP_Rect* clip_rect,
+ const PP_Point* amount) {
+ PP_Rect dummy;
+ memset(&dummy, 0, sizeof(PP_Rect));
+ Post(RENDERER, PpapiHostMsg_Graphics2D_Scroll(
+ !!clip_rect, clip_rect ? *clip_rect : dummy, *amount));
+}
+
+void Graphics2DResource::ReplaceContents(PP_Resource image_data) {
+ thunk::EnterResourceNoLock<thunk::PPB_ImageData_API> enter_image(
+ image_data, true);
+ if (enter_image.failed())
+ return;
+
+ // Check that the PP_Instance matches.
+ Resource* image_object =
+ PpapiGlobals::Get()->GetResourceTracker()->GetResource(image_data);
+ if (!image_object || pp_instance() != image_object->pp_instance()) {
+ Log(PP_LOGLEVEL_ERROR,
+ "Graphics2DResource.PaintImageData: Bad image resource.");
+ return;
+ }
+ enter_image.object()->SetIsCandidateForReuse();
+
+ Post(RENDERER, PpapiHostMsg_Graphics2D_ReplaceContents(
+ image_object->host_resource()));
+}
+
+PP_Bool Graphics2DResource::SetScale(float scale) {
+ if (scale <= 0.0f)
+ return PP_FALSE;
+ Post(RENDERER, PpapiHostMsg_Graphics2D_Dev_SetScale(scale));
+ scale_ = scale;
+ return PP_TRUE;
+}
+
+float Graphics2DResource::GetScale() {
+ return scale_;
+}
+
+int32_t Graphics2DResource::Flush(scoped_refptr<TrackedCallback> callback) {
+ // If host is not even created, return failure immediately. This can happen
+ // when failed to initialize (in constructor).
+ if (!sent_create_to_renderer())
+ return PP_ERROR_FAILED;
+
+ if (TrackedCallback::IsPending(current_flush_callback_))
+ return PP_ERROR_INPROGRESS; // Can't have >1 flush pending.
+ current_flush_callback_ = callback;
+
+ Call<PpapiPluginMsg_Graphics2D_FlushAck>(
+ RENDERER,
+ PpapiHostMsg_Graphics2D_Flush(),
+ base::Bind(&Graphics2DResource::OnPluginMsgFlushACK, this));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+bool Graphics2DResource::ReadImageData(PP_Resource image,
+ const PP_Point* top_left) {
+ if (!top_left)
+ return false;
+ int32_t result = SyncCall<PpapiPluginMsg_Graphics2D_ReadImageDataAck>(
+ RENDERER,
+ PpapiHostMsg_Graphics2D_ReadImageData(image, *top_left));
+ return result == PP_OK;
+}
+
+void Graphics2DResource::OnPluginMsgFlushACK(
+ const ResourceMessageReplyParams& params) {
+ current_flush_callback_->Run(params.result());
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/graphics_2d_resource.h b/chromium/ppapi/proxy/graphics_2d_resource.h
new file mode 100644
index 00000000000..b7ec30c710d
--- /dev/null
+++ b/chromium/ppapi/proxy/graphics_2d_resource.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_GRAPHICS_2D_RESOURCE_H_
+#define PPAPI_PROXY_GRAPHICS_2D_RESOURCE_H_
+
+#include "base/compiler_specific.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/thunk/ppb_graphics_2d_api.h"
+
+namespace ppapi {
+
+class TrackedCallback;
+
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT Graphics2DResource
+ : public PluginResource,
+ public NON_EXPORTED_BASE(thunk::PPB_Graphics2D_API) {
+ public:
+ Graphics2DResource(Connection connection,
+ PP_Instance instance,
+ const PP_Size& size,
+ PP_Bool is_always_opaque);
+
+ virtual ~Graphics2DResource();
+
+ // Resource overrides.
+ virtual thunk::PPB_Graphics2D_API* AsPPB_Graphics2D_API() OVERRIDE;
+
+ // PPB_Graphics2D_API overrides.
+ virtual PP_Bool Describe(PP_Size* size, PP_Bool* is_always_opaque) OVERRIDE;
+ virtual void PaintImageData(PP_Resource image_data,
+ const PP_Point* top_left,
+ const PP_Rect* src_rect) OVERRIDE;
+ virtual void Scroll(const PP_Rect* clip_rect,
+ const PP_Point* amount) OVERRIDE;
+ virtual void ReplaceContents(PP_Resource image_data) OVERRIDE;
+ virtual PP_Bool SetScale(float scale) OVERRIDE;
+ virtual float GetScale() OVERRIDE;
+ virtual int32_t Flush(scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual bool ReadImageData(PP_Resource image,
+ const PP_Point* top_left) OVERRIDE;
+
+ private:
+ void OnPluginMsgFlushACK(const ResourceMessageReplyParams& params);
+
+ const PP_Size size_;
+ const PP_Bool is_always_opaque_;
+ float scale_;
+
+ scoped_refptr<TrackedCallback> current_flush_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(Graphics2DResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_GRAPHICS_2D_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/handle_converter.cc b/chromium/ppapi/proxy/handle_converter.cc
new file mode 100644
index 00000000000..534a8ae5945
--- /dev/null
+++ b/chromium/ppapi/proxy/handle_converter.cc
@@ -0,0 +1,285 @@
+// Copyright (c) 2013 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/handle_converter.h"
+
+#include <vector>
+#include "base/bind.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_message_macros.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/resource_message_params.h"
+#include "ppapi/proxy/serialized_handle.h"
+#include "ppapi/proxy/serialized_var.h"
+
+class NaClDescImcShm;
+
+namespace IPC {
+class Message;
+}
+
+namespace {
+
+void WriteHandle(int handle_index,
+ const ppapi::proxy::SerializedHandle& handle,
+ IPC::Message* message) {
+ ppapi::proxy::SerializedHandle::WriteHeader(handle.header(), message);
+
+ // Now write the handle itself in POSIX style.
+ message->WriteBool(true); // valid == true
+ message->WriteInt(handle_index);
+}
+
+typedef std::vector<ppapi::proxy::SerializedHandle> Handles;
+
+// We define overloads for catching SerializedHandles so that we can share
+// them correctly to the untrusted side.
+// See ConvertHandlesImpl for how these get used.
+void ConvertHandlesInParam(const ppapi::proxy::SerializedHandle& handle,
+ Handles* handles,
+ IPC::Message* msg,
+ int* handle_index) {
+ handles->push_back(handle);
+ if (msg)
+ WriteHandle((*handle_index)++, handle, msg);
+}
+
+void HandleWriter(int* handle_index,
+ IPC::Message* m,
+ const ppapi::proxy::SerializedHandle& handle) {
+ WriteHandle((*handle_index)++, handle, m);
+}
+
+void ConvertHandlesInParam(const ppapi::proxy::SerializedVar& var,
+ Handles* handles,
+ IPC::Message* msg,
+ int* handle_index) {
+ std::vector<ppapi::proxy::SerializedHandle*> var_handles = var.GetHandles();
+ if (var_handles.empty())
+ return;
+
+ for (size_t i = 0; i < var_handles.size(); ++i)
+ handles->push_back(*var_handles[i]);
+ if (msg)
+ var.WriteDataToMessage(msg, base::Bind(&HandleWriter, handle_index));
+}
+
+// For PpapiMsg_ResourceReply and the reply to PpapiHostMsg_ResourceSyncCall,
+// the handles are carried inside the ResourceMessageReplyParams.
+// NOTE: We only translate handles from host->NaCl. The only kind of
+// ResourceMessageParams that travels this direction is
+// ResourceMessageReplyParams, so that's the only one we need to handle.
+void ConvertHandlesInParam(
+ const ppapi::proxy::ResourceMessageReplyParams& params,
+ Handles* handles,
+ IPC::Message* msg,
+ int* handle_index) {
+ // First, if we need to rewrite the message parameters, write everything
+ // before the handles (there's nothing after the handles).
+ if (msg) {
+ params.WriteReplyHeader(msg);
+ // IPC writes the vector length as an int before the contents of the
+ // vector.
+ msg->WriteInt(static_cast<int>(params.handles().size()));
+ }
+ for (Handles::const_iterator iter = params.handles().begin();
+ iter != params.handles().end();
+ ++iter) {
+ // ConvertHandle will write each handle to |msg|, if necessary.
+ ConvertHandlesInParam(*iter, handles, msg, handle_index);
+ }
+ // Tell ResourceMessageReplyParams that we have taken the handles, so it
+ // shouldn't close them. The NaCl runtime will take ownership of them.
+ params.ConsumeHandles();
+}
+
+// This overload is to catch all types other than SerializedHandle or
+// ResourceMessageReplyParams. On Windows, |msg| will be a valid pointer, and we
+// must write |param| to it.
+template <class T>
+void ConvertHandlesInParam(const T& param,
+ Handles* /* handles */,
+ IPC::Message* msg,
+ int* /* handle_index */) {
+ // It's not a handle, so just write to the output message, if necessary.
+ if (msg)
+ IPC::WriteParam(msg, param);
+}
+
+// These just break apart the given tuple and run ConvertHandle over each param.
+// The idea is to extract any handles in the tuple, while writing all data to
+// msg (if msg is valid). The msg will only be valid on Windows, where we need
+// to re-write all of the message parameters, writing the handles in POSIX style
+// for NaCl.
+template <class A>
+void ConvertHandlesImpl(const Tuple1<A>& t1, Handles* handles,
+ IPC::Message* msg) {
+ int handle_index = 0;
+ ConvertHandlesInParam(t1.a, handles, msg, &handle_index);
+}
+template <class A, class B>
+void ConvertHandlesImpl(const Tuple2<A, B>& t1, Handles* handles,
+ IPC::Message* msg) {
+ int handle_index = 0;
+ ConvertHandlesInParam(t1.a, handles, msg, &handle_index);
+ ConvertHandlesInParam(t1.b, handles, msg, &handle_index);
+}
+template <class A, class B, class C>
+void ConvertHandlesImpl(const Tuple3<A, B, C>& t1, Handles* handles,
+ IPC::Message* msg) {
+ int handle_index = 0;
+ ConvertHandlesInParam(t1.a, handles, msg, &handle_index);
+ ConvertHandlesInParam(t1.b, handles, msg, &handle_index);
+ ConvertHandlesInParam(t1.c, handles, msg, &handle_index);
+}
+template <class A, class B, class C, class D>
+void ConvertHandlesImpl(const Tuple4<A, B, C, D>& t1, Handles* handles,
+ IPC::Message* msg) {
+ int handle_index = 0;
+ ConvertHandlesInParam(t1.a, handles, msg, &handle_index);
+ ConvertHandlesInParam(t1.b, handles, msg, &handle_index);
+ ConvertHandlesInParam(t1.c, handles, msg, &handle_index);
+ ConvertHandlesInParam(t1.d, handles, msg, &handle_index);
+}
+
+template <class MessageType>
+class HandleConverterImpl {
+ public:
+ explicit HandleConverterImpl(const IPC::Message* msg)
+ : msg_(static_cast<const MessageType*>(msg)) {
+ }
+ bool ConvertMessage(Handles* handles, IPC::Message* out_msg) {
+ typename TupleTypes<typename MessageType::Schema::Param>::ValueTuple params;
+ if (!MessageType::Read(msg_, &params))
+ return false;
+ ConvertHandlesImpl(params, handles, out_msg);
+ return true;
+ }
+
+ bool ConvertReply(Handles* handles, IPC::SyncMessage* out_msg) {
+ typename TupleTypes<typename MessageType::Schema::ReplyParam>::ValueTuple
+ params;
+ if (!MessageType::ReadReplyParam(msg_, &params))
+ return false;
+ // If we need to rewrite the message (i.e., on Windows), we need to make
+ // sure we write the message id first.
+ if (out_msg) {
+ out_msg->set_reply();
+ int id = IPC::SyncMessage::GetMessageId(*msg_);
+ out_msg->WriteInt(id);
+ }
+ ConvertHandlesImpl(params, handles, out_msg);
+ return true;
+ }
+ // TODO(dmichael): Add ConvertSyncMessage for outgoing sync messages, if we
+ // ever pass handles in one of those.
+
+ private:
+ const MessageType* msg_;
+};
+
+} // namespace
+
+#define CASE_FOR_MESSAGE(MESSAGE_TYPE) \
+ case MESSAGE_TYPE::ID: { \
+ HandleConverterImpl<MESSAGE_TYPE> extractor(&msg); \
+ if (!extractor.ConvertMessage(handles, new_msg_ptr->get())) \
+ return false; \
+ break; \
+ }
+#define CASE_FOR_REPLY(MESSAGE_TYPE) \
+ case MESSAGE_TYPE::ID: { \
+ HandleConverterImpl<MESSAGE_TYPE> extractor(&msg); \
+ if (!extractor.ConvertReply( \
+ handles, \
+ static_cast<IPC::SyncMessage*>(new_msg_ptr->get()))) \
+ return false; \
+ break; \
+ }
+
+namespace ppapi {
+namespace proxy {
+
+class SerializedHandle;
+
+HandleConverter::HandleConverter() {
+}
+
+bool HandleConverter::ConvertNativeHandlesToPosix(
+ const IPC::Message& msg,
+ std::vector<SerializedHandle>* handles,
+ scoped_ptr<IPC::Message>* new_msg_ptr) {
+ DCHECK(handles);
+ DCHECK(new_msg_ptr);
+ DCHECK(!new_msg_ptr->get());
+
+ // In Windows, we need to re-write the contents of the message. This is
+ // because in Windows IPC code, native HANDLE values are serialized in the
+ // body of the message.
+ //
+ // In POSIX, we only serialize an index in to a FileDescriptorSet, and the
+ // actual file descriptors are sent out-of-band. So on Windows, to make a
+ // message that's compatible with Windows, we need to write a new message that
+ // has simple indices in the message body instead of the HANDLEs.
+ //
+ // NOTE: This means on Windows, new_msg_ptr's serialized contents are not
+ // compatible with Windows IPC deserialization code; it is intended to be
+ // passed to NaCl.
+#if defined(OS_WIN)
+ new_msg_ptr->reset(
+ new IPC::Message(msg.routing_id(), msg.type(), msg.priority()));
+#else
+ // Even on POSIX, we have to rewrite messages to create channels, because
+ // these contain a handle with an invalid (place holder) descriptor. The
+ // message sending code sees this and doesn't pass the descriptor over
+ // correctly.
+ if (msg.type() == PpapiMsg_CreateNaClChannel::ID) {
+ new_msg_ptr->reset(
+ new IPC::Message(msg.routing_id(), msg.type(), msg.priority()));
+ }
+#endif
+
+ switch (msg.type()) {
+ CASE_FOR_MESSAGE(PpapiMsg_CreateNaClChannel)
+ CASE_FOR_MESSAGE(PpapiMsg_PPBAudio_NotifyAudioStreamCreated)
+ CASE_FOR_MESSAGE(PpapiMsg_PPPMessaging_HandleMessage)
+ CASE_FOR_MESSAGE(PpapiPluginMsg_ResourceReply)
+ case IPC_REPLY_ID: {
+ int id = IPC::SyncMessage::GetMessageId(msg);
+ PendingSyncMsgMap::iterator iter(pending_sync_msgs_.find(id));
+ if (iter == pending_sync_msgs_.end()) {
+ NOTREACHED();
+ return false;
+ }
+ uint32_t type = iter->second;
+ pending_sync_msgs_.erase(iter);
+ switch (type) {
+ CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_GetTransferBuffer)
+ CASE_FOR_REPLY(PpapiHostMsg_PPBImageData_CreateSimple)
+ CASE_FOR_REPLY(PpapiHostMsg_ResourceSyncCall)
+ CASE_FOR_REPLY(PpapiHostMsg_SharedMemory_CreateSharedMemory)
+ default:
+ // Do nothing for messages we don't know.
+ break;
+ }
+ break;
+ }
+ default:
+ // Do nothing for messages we don't know.
+ break;
+ }
+ return true;
+}
+
+void HandleConverter::RegisterSyncMessageForReply(const IPC::Message& msg) {
+ DCHECK(msg.is_sync());
+
+ int msg_id = IPC::SyncMessage::GetMessageId(msg);
+ DCHECK(pending_sync_msgs_.find(msg_id) == pending_sync_msgs_.end());
+
+ pending_sync_msgs_[msg_id] = msg.type();
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/handle_converter.h b/chromium/ppapi/proxy/handle_converter.h
new file mode 100644
index 00000000000..456ee8db71c
--- /dev/null
+++ b/chromium/ppapi/proxy/handle_converter.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2013 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_HANDLE_CONVERTER_H_
+#define PPAPI_PROXY_HANDLE_CONVERTER_H_
+
+#include <map>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+
+namespace IPC {
+class Message;
+}
+
+namespace ppapi {
+namespace proxy {
+
+class SerializedHandle;
+
+class PPAPI_PROXY_EXPORT HandleConverter {
+ public:
+ HandleConverter();
+
+ // Convert the native handles in |msg| to NaCl style.
+ // In some cases (e.g., Windows), we need to re-write the contents of the
+ // message; in those cases, |new_msg_ptr| will be set to the new message.
+ // If |msg| is already in a good form for NaCl, |new_msg_ptr| is left NULL.
+ // See the explanation in the body of the method.
+ //
+ // In either case, all the handles in |msg| are extracted into |handles| so
+ // that they can be converted to NaClDesc handles.
+ // See chrome/nacl/nacl_ipc_adapter.cc for where this gets used.
+ bool ConvertNativeHandlesToPosix(const IPC::Message& msg,
+ std::vector<SerializedHandle>* handles,
+ scoped_ptr<IPC::Message>* new_msg_ptr);
+
+ // This method informs HandleConverter that a sync message is being sent so
+ // that it can associate reply messages with their type.
+ //
+ // Users of HandleConverter must call this when they send a synchronous
+ // message, otherwise HandleConverter won't be able to convert handles in
+ // replies.
+ void RegisterSyncMessageForReply(const IPC::Message& msg);
+
+ private:
+ // When we send a synchronous message (from untrusted to trusted), we store
+ // its type here, so that later we can associate the reply with its type
+ // and potentially translate handles in the message.
+ typedef std::map<int, uint32> PendingSyncMsgMap;
+ PendingSyncMsgMap pending_sync_msgs_;
+
+ DISALLOW_COPY_AND_ASSIGN(HandleConverter);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_HANDLE_CONVERTER_H_
diff --git a/chromium/ppapi/proxy/host_dispatcher.cc b/chromium/ppapi/proxy/host_dispatcher.cc
new file mode 100644
index 00000000000..cea7ab31f08
--- /dev/null
+++ b/chromium/ppapi/proxy/host_dispatcher.cc
@@ -0,0 +1,277 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/host_dispatcher.h"
+
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "ppapi/c/private/ppb_proxy_private.h"
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/proxy/host_var_serialization_rules.h"
+#include "ppapi/proxy/interface_list.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/resource_creation_proxy.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+
+namespace ppapi {
+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(PP_Module module,
+ PP_GetInterface_Func local_get_interface,
+ SyncMessageStatusReceiver* sync_status,
+ const PpapiPermissions& permissions)
+ : Dispatcher(local_get_interface, permissions),
+ sync_status_(sync_status),
+ 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;
+
+ SetSerializationRules(new HostVarSerializationRules);
+
+ ppb_proxy_ = reinterpret_cast<const PPB_Proxy_Private*>(
+ local_get_interface(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,
+ base::ProcessId peer_pid,
+ const IPC::ChannelHandle& channel_handle,
+ bool is_client,
+ const ppapi::Preferences& preferences) {
+ if (!Dispatcher::InitWithChannel(delegate, peer_pid, channel_handle,
+ is_client))
+ return false;
+ AddIOThreadMessageFilter(sync_status_.get());
+
+ 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);
+
+ if (msg->is_sync()) {
+ // Don't allow sending sync messages during module shutdown. Seee the "else"
+ // block below for why.
+ CHECK(!PP_ToBool(ppb_proxy()->IsInModuleDestructor(pp_module())));
+
+ // Prevent the dispatcher from going away during sync calls. Scenarios
+ // where this could happen include a Send for a sync message which while
+ // waiting for the reply, dispatches an incoming ExecuteScript call which
+ // destroys the plugin module and in turn the dispatcher.
+ ScopedModuleReference scoped_ref(this);
+
+ sync_status_->BeginBlockOnSyncMessage();
+ bool result = Dispatcher::Send(msg);
+ sync_status_->EndBlockOnSyncMessage();
+
+ return result;
+ } else {
+ // We don't want to have a scoped ref for async message cases since since
+ // async messages are sent during module desruction. In this case, the
+ // module will have a 0 refcount and addrefing and releasing it will
+ // reenter the destructor and it will crash.
+ return Dispatcher::Send(msg);
+ }
+}
+
+bool HostDispatcher::OnMessageReceived(const IPC::Message& msg) {
+ // Prevent the dispatcher from going away during a message handler. This must
+ // be at the outermost scope so it's released last.
+ ScopedModuleReference death_grip(this);
+
+ 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;
+
+ for (size_t i = 0; i < filters_.size(); i++) {
+ if (filters_[i]->OnMessageReceived(msg))
+ return true;
+ }
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(HostDispatcher, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_LogWithSource, OnHostMsgLogWithSource)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ if (handled)
+ return true;
+ return Dispatcher::OnMessageReceived(msg);
+
+ // Note: |this| may be deleted once the death_grip goes out of scope!
+}
+
+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& iface_name) {
+ const void* proxied_interface =
+ InterfaceList::GetInstance()->GetInterfaceForPPP(iface_name);
+ if (!proxied_interface)
+ return NULL; // Don't have a proxy for this interface, don't query further.
+
+ PluginSupportedMap::iterator iter(plugin_supported_.find(iface_name));
+ if (iter == plugin_supported_.end()) {
+ // Need to query. Cache the result so we only do this once.
+ bool supported = false;
+
+ bool previous_reentrancy_value = allow_plugin_reentrancy_;
+ allow_plugin_reentrancy_ = true;
+ Send(new PpapiMsg_SupportsInterface(iface_name, &supported));
+ allow_plugin_reentrancy_ = previous_reentrancy_value;
+
+ std::pair<PluginSupportedMap::iterator, bool> iter_success_pair;
+ iter_success_pair = plugin_supported_.insert(
+ PluginSupportedMap::value_type(iface_name, supported));
+ iter = iter_success_pair.first;
+ }
+ if (iter->second)
+ return proxied_interface;
+ return NULL;
+}
+
+void HostDispatcher::OnInvalidMessageReceived() {
+ // TODO(brettw) bug 95345 kill the plugin when an invalid message is
+ // received.
+}
+
+void HostDispatcher::OnHostMsgLogWithSource(PP_Instance instance,
+ int int_log_level,
+ const std::string& source,
+ const std::string& value) {
+ PP_LogLevel level = static_cast<PP_LogLevel>(int_log_level);
+ if (instance) {
+ PpapiGlobals::Get()->LogWithSource(instance, level, source, value);
+ } else {
+ PpapiGlobals::Get()->BroadcastLogWithSource(pp_module_, level,
+ source, value);
+ }
+}
+
+// ScopedModuleReference -------------------------------------------------------
+
+ScopedModuleReference::ScopedModuleReference(Dispatcher* dispatcher)
+ : dispatcher_(NULL) {
+ if (!dispatcher->IsPlugin()) {
+ dispatcher_ = static_cast<HostDispatcher*>(dispatcher);
+ dispatcher_->ppb_proxy()->AddRefModule(dispatcher_->pp_module());
+ }
+}
+
+ScopedModuleReference::~ScopedModuleReference() {
+ if (dispatcher_)
+ dispatcher_->ppb_proxy()->ReleaseModule(dispatcher_->pp_module());
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/host_dispatcher.h b/chromium/ppapi/proxy/host_dispatcher.h
new file mode 100644
index 00000000000..ebd6ef96587
--- /dev/null
+++ b/chromium/ppapi/proxy/host_dispatcher.h
@@ -0,0 +1,156 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_HOST_DISPATCHER_H_
+#define PPAPI_PROXY_HOST_DISPATCHER_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/process/process.h"
+#include "ipc/ipc_channel_proxy.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/dispatcher.h"
+
+struct PPB_Proxy_Private;
+
+namespace ppapi {
+
+struct Preferences;
+
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT HostDispatcher : public Dispatcher {
+ public:
+ // This interface receives notifications about sync messages being sent by
+ // the dispatcher to the plugin process. It is used to detect a hung plugin.
+ //
+ // Note that there can be nested sync messages, so the begin/end status
+ // actually represents a stack of blocking messages.
+ class SyncMessageStatusReceiver : public IPC::ChannelProxy::MessageFilter {
+ public:
+ // Notification that a sync message is about to be sent out.
+ virtual void BeginBlockOnSyncMessage() = 0;
+
+ // Notification that a sync message reply was received and the dispatcher
+ // is no longer blocked on a sync message.
+ virtual void EndBlockOnSyncMessage() = 0;
+
+ protected:
+ virtual ~SyncMessageStatusReceiver() {}
+ };
+
+ // Constructor for the renderer side. This will take a reference to the
+ // SyncMessageStatusReceiver.
+ //
+ // You must call InitHostWithChannel after the constructor.
+ HostDispatcher(PP_Module module,
+ PP_GetInterface_Func local_get_interface,
+ SyncMessageStatusReceiver* sync_status,
+ const PpapiPermissions& permissions);
+ ~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,
+ base::ProcessId peer_pid,
+ const IPC::ChannelHandle& channel_handle,
+ bool is_client,
+ const 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::Listener.
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ virtual void OnChannelError() OVERRIDE;
+
+ // 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& iface_name);
+
+ // See the value below. Call this when processing a scripting message from
+ // the plugin that can be reentered. This is set to false at the beginning
+ // of processing of each message from the plugin.
+ 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_; }
+
+ protected:
+ // Overridden from Dispatcher.
+ virtual void OnInvalidMessageReceived();
+
+ private:
+ void OnHostMsgLogWithSource(PP_Instance instance,
+ int int_log_level,
+ const std::string& source,
+ const std::string& value);
+
+ scoped_refptr<SyncMessageStatusReceiver> sync_status_;
+
+ PP_Module pp_module_;
+
+ // 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.
+ typedef base::hash_map<std::string, bool> PluginSupportedMap;
+ PluginSupportedMap plugin_supported_;
+
+ // 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 class does nothing if used on the plugin side.
+class ScopedModuleReference {
+ public:
+ explicit ScopedModuleReference(Dispatcher* dispatcher);
+ ~ScopedModuleReference();
+
+ private:
+ HostDispatcher* dispatcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedModuleReference);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_HOST_DISPATCHER_H_
diff --git a/chromium/ppapi/proxy/host_resolver_private_resource.cc b/chromium/ppapi/proxy/host_resolver_private_resource.cc
new file mode 100644
index 00000000000..10ff06a9382
--- /dev/null
+++ b/chromium/ppapi/proxy/host_resolver_private_resource.cc
@@ -0,0 +1,57 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/host_resolver_private_resource.h"
+
+#include "ppapi/proxy/net_address_resource.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+
+namespace ppapi {
+namespace proxy {
+
+HostResolverPrivateResource::HostResolverPrivateResource(Connection connection,
+ PP_Instance instance)
+ : HostResolverResourceBase(connection, instance, true) {
+}
+
+HostResolverPrivateResource::~HostResolverPrivateResource() {
+}
+
+thunk::PPB_HostResolver_Private_API*
+HostResolverPrivateResource::AsPPB_HostResolver_Private_API() {
+ return this;
+}
+
+int32_t HostResolverPrivateResource::Resolve(
+ const char* host,
+ uint16_t port,
+ const PP_HostResolver_Private_Hint* hint,
+ scoped_refptr<TrackedCallback> callback) {
+ return ResolveImpl(host, port, hint, callback);
+}
+
+PP_Var HostResolverPrivateResource::GetCanonicalName() {
+ return GetCanonicalNameImpl();
+}
+
+uint32_t HostResolverPrivateResource::GetSize() {
+ return GetSizeImpl();
+}
+
+bool HostResolverPrivateResource::GetNetAddress(
+ uint32_t index,
+ PP_NetAddress_Private* address) {
+ if (!address)
+ return false;
+
+ scoped_refptr<NetAddressResource> addr_resource = GetNetAddressImpl(index);
+ if (!addr_resource.get())
+ return false;
+
+ *address = addr_resource->GetNetAddressPrivate();
+ return true;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/host_resolver_private_resource.h b/chromium/ppapi/proxy/host_resolver_private_resource.h
new file mode 100644
index 00000000000..8281a1f9d3c
--- /dev/null
+++ b/chromium/ppapi/proxy/host_resolver_private_resource.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_HOST_RESOLVER_PRIVATE_RESOURCE_H_
+#define PPAPI_PROXY_HOST_RESOLVER_PRIVATE_RESOURCE_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ppapi/proxy/host_resolver_resource_base.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/thunk/ppb_host_resolver_private_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT HostResolverPrivateResource
+ : public HostResolverResourceBase,
+ public thunk::PPB_HostResolver_Private_API {
+ public:
+ HostResolverPrivateResource(Connection connection,
+ PP_Instance instance);
+ virtual ~HostResolverPrivateResource();
+
+ // PluginResource overrides.
+ virtual thunk::PPB_HostResolver_Private_API*
+ AsPPB_HostResolver_Private_API() OVERRIDE;
+
+ // PPB_HostResolver_Private_API implementation.
+ virtual int32_t Resolve(const char* host,
+ uint16_t port,
+ const PP_HostResolver_Private_Hint* hint,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual PP_Var GetCanonicalName() OVERRIDE;
+ virtual uint32_t GetSize() OVERRIDE;
+ virtual bool GetNetAddress(uint32_t index,
+ PP_NetAddress_Private* address) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HostResolverPrivateResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_HOST_RESOLVER_PRIVATE_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/host_resolver_resource.cc b/chromium/ppapi/proxy/host_resolver_resource.cc
new file mode 100644
index 00000000000..a2898566f7f
--- /dev/null
+++ b/chromium/ppapi/proxy/host_resolver_resource.cc
@@ -0,0 +1,85 @@
+// Copyright 2013 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_resolver_resource.h"
+
+#include "base/logging.h"
+#include "ppapi/c/private/ppb_host_resolver_private.h"
+#include "ppapi/proxy/net_address_resource.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+PP_HostResolver_Private_Hint ConvertToHostResolverPrivateHint(
+ const PP_HostResolver_Hint& hint) {
+ PP_HostResolver_Private_Hint private_hint;
+ switch (hint.family) {
+ case PP_NETADDRESS_FAMILY_UNSPECIFIED:
+ private_hint.family = PP_NETADDRESSFAMILY_PRIVATE_UNSPECIFIED;
+ break;
+ case PP_NETADDRESS_FAMILY_IPV4:
+ private_hint.family = PP_NETADDRESSFAMILY_PRIVATE_IPV4;
+ break;
+ case PP_NETADDRESS_FAMILY_IPV6:
+ private_hint.family = PP_NETADDRESSFAMILY_PRIVATE_IPV6;
+ break;
+ default:
+ NOTREACHED();
+ private_hint.family = PP_NETADDRESSFAMILY_PRIVATE_UNSPECIFIED;
+ }
+
+ private_hint.flags = 0;
+ if (hint.flags & PP_HOSTRESOLVER_FLAG_CANONNAME)
+ private_hint.flags |= PP_HOST_RESOLVER_PRIVATE_FLAGS_CANONNAME;
+
+ return private_hint;
+}
+
+} // namespace
+
+HostResolverResource::HostResolverResource(Connection connection,
+ PP_Instance instance)
+ : HostResolverResourceBase(connection, instance, false) {
+}
+
+HostResolverResource::~HostResolverResource() {
+}
+
+thunk::PPB_HostResolver_API* HostResolverResource::AsPPB_HostResolver_API() {
+ return this;
+}
+
+int32_t HostResolverResource::Resolve(const char* host,
+ uint16_t port,
+ const PP_HostResolver_Hint* hint,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!hint)
+ return PP_ERROR_BADARGUMENT;
+
+ PP_HostResolver_Private_Hint private_hint =
+ ConvertToHostResolverPrivateHint(*hint);
+ return ResolveImpl(host, port, &private_hint, callback);
+}
+
+PP_Var HostResolverResource::GetCanonicalName() {
+ return GetCanonicalNameImpl();
+}
+
+uint32_t HostResolverResource::GetNetAddressCount() {
+ return GetSizeImpl();
+}
+
+PP_Resource HostResolverResource::GetNetAddress(uint32_t index) {
+ scoped_refptr<NetAddressResource> addr_resource = GetNetAddressImpl(index);
+ if (!addr_resource.get())
+ return 0;
+
+ return addr_resource->GetReference();
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/host_resolver_resource.h b/chromium/ppapi/proxy/host_resolver_resource.h
new file mode 100644
index 00000000000..055dfb81071
--- /dev/null
+++ b/chromium/ppapi/proxy/host_resolver_resource.h
@@ -0,0 +1,43 @@
+// Copyright 2013 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_RESOLVER_RESOURCE_H_
+#define PPAPI_PROXY_HOST_RESOLVER_RESOURCE_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ppapi/proxy/host_resolver_resource_base.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/thunk/ppb_host_resolver_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT HostResolverResource
+ : public HostResolverResourceBase,
+ public thunk::PPB_HostResolver_API {
+ public:
+ HostResolverResource(Connection connection, PP_Instance instance);
+ virtual ~HostResolverResource();
+
+ // PluginResource overrides.
+ virtual thunk::PPB_HostResolver_API* AsPPB_HostResolver_API() OVERRIDE;
+
+ // thunk::PPB_HostResolver_API implementation.
+ virtual int32_t Resolve(const char* host,
+ uint16_t port,
+ const PP_HostResolver_Hint* hint,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual PP_Var GetCanonicalName() OVERRIDE;
+ virtual uint32_t GetNetAddressCount() OVERRIDE;
+ virtual PP_Resource GetNetAddress(uint32_t index) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HostResolverResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_HOST_RESOLVER_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/host_resolver_resource_base.cc b/chromium/ppapi/proxy/host_resolver_resource_base.cc
new file mode 100644
index 00000000000..5cbbbb2aa9a
--- /dev/null
+++ b/chromium/ppapi/proxy/host_resolver_resource_base.cc
@@ -0,0 +1,132 @@
+// Copyright 2013 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_resolver_resource_base.h"
+
+#include "base/bind.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/net_address_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+int32_t ConvertPPError(int32_t pp_error, bool private_api) {
+ // The private API doesn't return network-specific error codes or
+ // PP_ERROR_NOACCESS. In order to preserve the behavior, we convert those to
+ // PP_ERROR_FAILED.
+ // TODO(yzshen): Consider defining ranges for different kinds of PP_Error
+ // codes, so that we can detect network-specific error codes in a better way.
+ if (private_api &&
+ (pp_error <= PP_ERROR_CONNECTION_CLOSED ||
+ pp_error == PP_ERROR_NOACCESS)) {
+ return PP_ERROR_FAILED;
+ }
+
+ return pp_error;
+}
+
+} // namespace
+
+HostResolverResourceBase::HostResolverResourceBase(Connection connection,
+ PP_Instance instance,
+ bool private_api)
+ : PluginResource(connection, instance),
+ private_api_(private_api),
+ allow_get_results_(false) {
+ if (private_api)
+ SendCreate(BROWSER, PpapiHostMsg_HostResolver_CreatePrivate());
+ else
+ SendCreate(BROWSER, PpapiHostMsg_HostResolver_Create());
+}
+
+HostResolverResourceBase::~HostResolverResourceBase() {
+}
+
+int32_t HostResolverResourceBase::ResolveImpl(
+ const char* host,
+ uint16_t port,
+ const PP_HostResolver_Private_Hint* hint,
+ scoped_refptr<TrackedCallback> callback) {
+ allow_get_results_ = false;
+ if (!host || !hint)
+ return PP_ERROR_BADARGUMENT;
+ if (ResolveInProgress())
+ return PP_ERROR_INPROGRESS;
+
+ resolve_callback_ = callback;
+
+ HostPortPair host_port;
+ host_port.host = host;
+ host_port.port = port;
+
+ SendResolve(host_port, hint);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+PP_Var HostResolverResourceBase::GetCanonicalNameImpl() {
+ if (!allow_get_results_)
+ return PP_MakeUndefined();
+
+ return StringVar::StringToPPVar(canonical_name_);
+}
+
+uint32_t HostResolverResourceBase::GetSizeImpl() {
+ if (!allow_get_results_)
+ return 0;
+ return static_cast<uint32_t>(net_address_list_.size());
+}
+
+scoped_refptr<NetAddressResource> HostResolverResourceBase::GetNetAddressImpl(
+ uint32_t index) {
+ if (!allow_get_results_ || index >= GetSizeImpl())
+ return scoped_refptr<NetAddressResource>();
+
+ return net_address_list_[index];
+}
+
+void HostResolverResourceBase::OnPluginMsgResolveReply(
+ const ResourceMessageReplyParams& params,
+ const std::string& canonical_name,
+ const std::vector<PP_NetAddress_Private>& net_address_list) {
+ if (params.result() == PP_OK) {
+ allow_get_results_ = true;
+ canonical_name_ = canonical_name;
+
+ net_address_list_.clear();
+ for (std::vector<PP_NetAddress_Private>::const_iterator iter =
+ net_address_list.begin();
+ iter != net_address_list.end();
+ ++iter) {
+ net_address_list_.push_back(
+ new NetAddressResource(connection(), pp_instance(), *iter));
+ }
+ } else {
+ canonical_name_.clear();
+ net_address_list_.clear();
+ }
+ resolve_callback_->Run(ConvertPPError(params.result(), private_api_));
+}
+
+void HostResolverResourceBase::SendResolve(
+ const HostPortPair& host_port,
+ const PP_HostResolver_Private_Hint* hint) {
+ PpapiHostMsg_HostResolver_Resolve msg(host_port, *hint);
+ Call<PpapiPluginMsg_HostResolver_ResolveReply>(
+ BROWSER,
+ msg,
+ base::Bind(&HostResolverResourceBase::OnPluginMsgResolveReply,
+ base::Unretained(this)));
+}
+
+bool HostResolverResourceBase::ResolveInProgress() const {
+ return TrackedCallback::IsPending(resolve_callback_);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/host_resolver_resource_base.h b/chromium/ppapi/proxy/host_resolver_resource_base.h
new file mode 100644
index 00000000000..d27d9888179
--- /dev/null
+++ b/chromium/ppapi/proxy/host_resolver_resource_base.h
@@ -0,0 +1,74 @@
+// Copyright 2013 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_RESOLVER_RESOURCE_BASE_H_
+#define PPAPI_PROXY_HOST_RESOLVER_RESOURCE_BASE_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "ppapi/c/private/ppb_host_resolver_private.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+
+namespace ppapi {
+
+class TrackedCallback;
+
+struct HostPortPair {
+ std::string host;
+ uint16_t port;
+};
+
+namespace proxy {
+
+class NetAddressResource;
+
+class PPAPI_PROXY_EXPORT HostResolverResourceBase: public PluginResource {
+ public:
+ HostResolverResourceBase(Connection connection,
+ PP_Instance instance,
+ bool private_api);
+ virtual ~HostResolverResourceBase();
+
+ int32_t ResolveImpl(const char* host,
+ uint16_t port,
+ const PP_HostResolver_Private_Hint* hint,
+ scoped_refptr<TrackedCallback> callback);
+ PP_Var GetCanonicalNameImpl();
+ uint32_t GetSizeImpl();
+ scoped_refptr<NetAddressResource> GetNetAddressImpl(uint32_t index);
+
+ private:
+ // IPC message handlers.
+ void OnPluginMsgResolveReply(
+ const ResourceMessageReplyParams& params,
+ const std::string& canonical_name,
+ const std::vector<PP_NetAddress_Private>& net_address_list);
+
+ void SendResolve(const HostPortPair& host_port,
+ const PP_HostResolver_Private_Hint* hint);
+
+ bool ResolveInProgress() const;
+
+ bool private_api_;
+
+ scoped_refptr<TrackedCallback> resolve_callback_;
+
+ // Set to false if there is a pending resolve request or the previous request
+ // failed.
+ bool allow_get_results_;
+ std::string canonical_name_;
+ std::vector<scoped_refptr<NetAddressResource> > net_address_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(HostResolverResourceBase);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_HOST_RESOLVER_RESOURCE_BASE_H_
diff --git a/chromium/ppapi/proxy/host_var_serialization_rules.cc b/chromium/ppapi/proxy/host_var_serialization_rules.cc
new file mode 100644
index 00000000000..dcc965bd691
--- /dev/null
+++ b/chromium/ppapi/proxy/host_var_serialization_rules.cc
@@ -0,0 +1,58 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/host_var_serialization_rules.h"
+
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/var_tracker.h"
+
+using ppapi::PpapiGlobals;
+using ppapi::VarTracker;
+
+namespace ppapi {
+namespace proxy {
+
+HostVarSerializationRules::HostVarSerializationRules() {
+}
+
+HostVarSerializationRules::~HostVarSerializationRules() {
+}
+
+PP_Var HostVarSerializationRules::SendCallerOwned(const PP_Var& var) {
+ return var;
+}
+
+PP_Var HostVarSerializationRules::BeginReceiveCallerOwned(const PP_Var& var) {
+ return var;
+}
+
+void HostVarSerializationRules::EndReceiveCallerOwned(const PP_Var& var) {
+ if (var.type != PP_VARTYPE_OBJECT && var.type >= PP_VARTYPE_STRING) {
+ // Release our reference to the local Var.
+ PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(var);
+ }
+}
+
+PP_Var HostVarSerializationRules::ReceivePassRef(const PP_Var& var) {
+ // See PluginVarSerialization::BeginSendPassRef for an example.
+ if (var.type == PP_VARTYPE_OBJECT)
+ PpapiGlobals::Get()->GetVarTracker()->AddRefVar(var);
+ return var;
+}
+
+PP_Var HostVarSerializationRules::BeginSendPassRef(const PP_Var& var) {
+ return var;
+}
+
+void HostVarSerializationRules::EndSendPassRef(const PP_Var& /* var */) {
+ // See PluginVarSerialization::ReceivePassRef for an example. We don't need
+ // to do anything here.
+}
+
+void HostVarSerializationRules::ReleaseObjectRef(const PP_Var& var) {
+ PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(var);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/host_var_serialization_rules.h b/chromium/ppapi/proxy/host_var_serialization_rules.h
new file mode 100644
index 00000000000..8de6cdecf34
--- /dev/null
+++ b/chromium/ppapi/proxy/host_var_serialization_rules.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_HOST_VAR_SERIALIZATION_RULES_H_
+#define PPAPI_PROXY_HOST_VAR_SERIALIZATION_RULES_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/proxy/var_serialization_rules.h"
+
+namespace ppapi {
+namespace proxy {
+
+// Implementation of the VarSerializationRules interface for the host side.
+class HostVarSerializationRules : public VarSerializationRules {
+ public:
+ HostVarSerializationRules();
+ ~HostVarSerializationRules();
+
+ // VarSerialization implementation.
+ virtual PP_Var SendCallerOwned(const PP_Var& var);
+ virtual PP_Var BeginReceiveCallerOwned(const PP_Var& var);
+ virtual void EndReceiveCallerOwned(const PP_Var& var);
+ virtual PP_Var ReceivePassRef(const PP_Var& var);
+ virtual PP_Var BeginSendPassRef(const PP_Var& var);
+ virtual void EndSendPassRef(const PP_Var& var);
+ virtual void ReleaseObjectRef(const PP_Var& var);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HostVarSerializationRules);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_HOST_VAR_SERIALIZATION_RULES_H_
diff --git a/chromium/ppapi/proxy/interface_list.cc b/chromium/ppapi/proxy/interface_list.cc
new file mode 100644
index 00000000000..d9feb89d08c
--- /dev/null
+++ b/chromium/ppapi/proxy/interface_list.cc
@@ -0,0 +1,392 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/interface_list.h"
+
+#include "base/lazy_instance.h"
+#include "base/memory/singleton.h"
+#include "ppapi/c/dev/ppb_audio_input_dev.h"
+#include "ppapi/c/dev/ppb_buffer_dev.h"
+#include "ppapi/c/dev/ppb_char_set_dev.h"
+#include "ppapi/c/dev/ppb_crypto_dev.h"
+#include "ppapi/c/dev/ppb_cursor_control_dev.h"
+#include "ppapi/c/dev/ppb_device_ref_dev.h"
+#include "ppapi/c/dev/ppb_font_dev.h"
+#include "ppapi/c/dev/ppb_gles_chromium_texture_mapping_dev.h"
+#include "ppapi/c/dev/ppb_graphics_2d_dev.h"
+#include "ppapi/c/dev/ppb_ime_input_event_dev.h"
+#include "ppapi/c/dev/ppb_keyboard_input_event_dev.h"
+#include "ppapi/c/dev/ppb_memory_dev.h"
+#include "ppapi/c/dev/ppb_opengles2ext_dev.h"
+#include "ppapi/c/dev/ppb_printing_dev.h"
+#include "ppapi/c/dev/ppb_resource_array_dev.h"
+#include "ppapi/c/dev/ppb_testing_dev.h"
+#include "ppapi/c/dev/ppb_text_input_dev.h"
+#include "ppapi/c/dev/ppb_trace_event_dev.h"
+#include "ppapi/c/dev/ppb_truetype_font_dev.h"
+#include "ppapi/c/dev/ppb_url_util_dev.h"
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/dev/ppb_video_capture_dev.h"
+#include "ppapi/c/dev/ppb_view_dev.h"
+#include "ppapi/c/extensions/dev/ppb_ext_alarms_dev.h"
+#include "ppapi/c/extensions/dev/ppb_ext_socket_dev.h"
+#include "ppapi/c/ppb_audio_config.h"
+#include "ppapi/c/ppb_audio.h"
+#include "ppapi/c/ppb_console.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/c/ppb_file_io.h"
+#include "ppapi/c/ppb_file_ref.h"
+#include "ppapi/c/ppb_file_system.h"
+#include "ppapi/c/ppb_fullscreen.h"
+#include "ppapi/c/ppb_graphics_2d.h"
+#include "ppapi/c/ppb_host_resolver.h"
+#include "ppapi/c/ppb_image_data.h"
+#include "ppapi/c/ppb_input_event.h"
+#include "ppapi/c/ppb_instance.h"
+#include "ppapi/c/ppb_message_loop.h"
+#include "ppapi/c/ppb_messaging.h"
+#include "ppapi/c/ppb_mouse_lock.h"
+#include "ppapi/c/ppb_net_address.h"
+#include "ppapi/c/ppb_network_proxy.h"
+#include "ppapi/c/ppb_opengles2.h"
+#include "ppapi/c/ppb_tcp_socket.h"
+#include "ppapi/c/ppb_text_input_controller.h"
+#include "ppapi/c/ppb_udp_socket.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/ppb_var_array.h"
+#include "ppapi/c/ppb_var_array_buffer.h"
+#include "ppapi/c/ppb_var_dictionary.h"
+#include "ppapi/c/ppb_view.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppp_instance.h"
+#include "ppapi/c/private/ppb_content_decryptor_private.h"
+#include "ppapi/c/private/ppb_ext_crx_file_system_private.h"
+#include "ppapi/c/private/ppb_file_io_private.h"
+#include "ppapi/c/private/ppb_file_ref_private.h"
+#include "ppapi/c/private/ppb_flash_clipboard.h"
+#include "ppapi/c/private/ppb_flash_file.h"
+#include "ppapi/c/private/ppb_flash_font_file.h"
+#include "ppapi/c/private/ppb_flash_fullscreen.h"
+#include "ppapi/c/private/ppb_flash.h"
+#include "ppapi/c/private/ppb_flash_device_id.h"
+#include "ppapi/c/private/ppb_flash_drm.h"
+#include "ppapi/c/private/ppb_flash_menu.h"
+#include "ppapi/c/private/ppb_flash_message_loop.h"
+#include "ppapi/c/private/ppb_flash_print.h"
+#include "ppapi/c/private/ppb_host_resolver_private.h"
+#include "ppapi/c/private/ppb_net_address_private.h"
+#include "ppapi/c/private/ppb_network_list_private.h"
+#include "ppapi/c/private/ppb_network_monitor_private.h"
+#include "ppapi/c/private/ppb_pdf.h"
+#include "ppapi/c/private/ppb_talk_private.h"
+#include "ppapi/c/private/ppb_tcp_server_socket_private.h"
+#include "ppapi/c/private/ppb_tcp_socket_private.h"
+#include "ppapi/c/private/ppb_udp_socket_private.h"
+#include "ppapi/c/private/ppb_video_destination_private.h"
+#include "ppapi/c/private/ppb_video_source_private.h"
+#include "ppapi/c/private/ppb_x509_certificate_private.h"
+#include "ppapi/c/private/ppp_content_decryptor_private.h"
+#include "ppapi/c/trusted/ppb_broker_trusted.h"
+#include "ppapi/c/trusted/ppb_browser_font_trusted.h"
+#include "ppapi/c/trusted/ppb_char_set_trusted.h"
+#include "ppapi/c/trusted/ppb_file_chooser_trusted.h"
+#include "ppapi/c/trusted/ppb_file_io_trusted.h"
+#include "ppapi/c/trusted/ppb_url_loader_trusted.h"
+#include "ppapi/proxy/interface_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_core_proxy.h"
+#include "ppapi/proxy/ppb_file_ref_proxy.h"
+#include "ppapi/proxy/ppb_flash_message_loop_proxy.h"
+#include "ppapi/proxy/ppb_graphics_3d_proxy.h"
+#include "ppapi/proxy/ppb_image_data_proxy.h"
+#include "ppapi/proxy/ppb_instance_proxy.h"
+#include "ppapi/proxy/ppb_message_loop_proxy.h"
+#include "ppapi/proxy/ppb_network_monitor_private_proxy.h"
+#include "ppapi/proxy/ppb_tcp_socket_private_proxy.h"
+#include "ppapi/proxy/ppb_tcp_socket_proxy.h"
+#include "ppapi/proxy/ppb_testing_proxy.h"
+#include "ppapi/proxy/ppb_var_deprecated_proxy.h"
+#include "ppapi/proxy/ppb_video_decoder_proxy.h"
+#include "ppapi/proxy/ppb_x509_certificate_private_proxy.h"
+#include "ppapi/proxy/ppp_class_proxy.h"
+#include "ppapi/proxy/ppp_content_decryptor_private_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/ppp_messaging_proxy.h"
+#include "ppapi/proxy/ppp_mouse_lock_proxy.h"
+#include "ppapi/proxy/ppp_printing_proxy.h"
+#include "ppapi/proxy/ppp_text_input_proxy.h"
+#include "ppapi/proxy/ppp_video_decoder_proxy.h"
+#include "ppapi/proxy/resource_creation_proxy.h"
+#include "ppapi/shared_impl/ppb_opengles2_shared.h"
+#include "ppapi/shared_impl/ppb_var_shared.h"
+#include "ppapi/thunk/thunk.h"
+
+// Helper to get the proxy name PPB_Foo_Proxy given the API name PPB_Foo.
+#define PROXY_CLASS_NAME(api_name) api_name##_Proxy
+
+// Helper to get the interface ID PPB_Foo_Proxy::kApiID given the API
+// name PPB_Foo.
+#define PROXY_API_ID(api_name) PROXY_CLASS_NAME(api_name)::kApiID
+
+// Helper to get the name of the templatized factory function.
+#define PROXY_FACTORY_NAME(api_name) ProxyFactory<PROXY_CLASS_NAME(api_name)>
+
+// Helper to get the name of the thunk GetPPB_Foo_1_0_Thunk given the interface
+// struct name PPB_Foo_1_0.
+#define INTERFACE_THUNK_NAME(iface_struct) thunk::Get##iface_struct##_Thunk
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+// The interface list has interfaces with no ID listed as "NoAPIName" which
+// means there's no corresponding _Proxy object. Our macros expand this to
+// NoAPIName_Proxy, and then they look for kApiID inside it.
+//
+// This dummy class provides the correct definition for that interface ID,
+// which is "NONE".
+class NoAPIName_Proxy {
+ public:
+ static const ApiID kApiID = API_ID_NONE;
+};
+
+template<typename ProxyClass>
+InterfaceProxy* ProxyFactory(Dispatcher* dispatcher) {
+ return new ProxyClass(dispatcher);
+}
+
+base::LazyInstance<PpapiPermissions> g_process_global_permissions;
+
+} // namespace
+
+InterfaceList::InterfaceList() {
+ memset(id_to_factory_, 0, sizeof(id_to_factory_));
+
+ // Register the API factories for each of the API types. This calls AddProxy
+ // for each InterfaceProxy type we support.
+ #define PROXIED_API(api_name) \
+ AddProxy(PROXY_API_ID(api_name), &PROXY_FACTORY_NAME(api_name));
+
+ // Register each proxied interface by calling AddPPB for each supported
+ // interface. Set current_required_permission to the appropriate value for
+ // the value you want expanded by this macro.
+ #define PROXIED_IFACE(api_name, iface_str, iface_struct) \
+ AddPPB(iface_str, PROXY_API_ID(api_name), \
+ INTERFACE_THUNK_NAME(iface_struct)(), \
+ current_required_permission);
+
+ {
+ Permission current_required_permission = PERMISSION_NONE;
+ #include "ppapi/thunk/interfaces_ppb_private_no_permissions.h"
+ #include "ppapi/thunk/interfaces_ppb_public_stable.h"
+ }
+
+ {
+ Permission current_required_permission = PERMISSION_DEV;
+ #include "ppapi/thunk/interfaces_ppb_public_dev.h"
+ }
+ {
+ Permission current_required_permission = PERMISSION_PRIVATE;
+ #include "ppapi/thunk/interfaces_ppb_private.h"
+ }
+ {
+#if !defined(OS_NACL)
+ Permission current_required_permission = PERMISSION_FLASH;
+ #include "ppapi/thunk/interfaces_ppb_private_flash.h"
+#endif // !defined(OS_NACL)
+ }
+
+ #undef PROXIED_API
+ #undef PROXIED_IFACE
+
+ // Manually add some special proxies. Some of these don't have interfaces
+ // that they support, so aren't covered by the macros above, but have proxies
+ // for message routing. Others have different implementations between the
+ // proxy and the impl and there's no obvious message routing.
+ AddProxy(API_ID_RESOURCE_CREATION, &ResourceCreationProxy::Create);
+ AddProxy(API_ID_PPP_CLASS, &PPP_Class_Proxy::Create);
+ AddPPB(PPB_CORE_INTERFACE_1_0, API_ID_PPB_CORE,
+ PPB_Core_Proxy::GetPPB_Core_Interface(), PERMISSION_NONE);
+ AddPPB(PPB_MESSAGELOOP_INTERFACE_1_0, API_ID_NONE,
+ PPB_MessageLoop_Proxy::GetInterface(), PERMISSION_NONE);
+ AddPPB(PPB_OPENGLES2_INTERFACE_1_0, API_ID_NONE,
+ PPB_OpenGLES2_Shared::GetInterface(), PERMISSION_NONE);
+ AddPPB(PPB_OPENGLES2_INSTANCEDARRAYS_INTERFACE_1_0, API_ID_NONE,
+ PPB_OpenGLES2_Shared::GetInstancedArraysInterface(), PERMISSION_NONE);
+ AddPPB(PPB_OPENGLES2_FRAMEBUFFERBLIT_INTERFACE_1_0, API_ID_NONE,
+ PPB_OpenGLES2_Shared::GetFramebufferBlitInterface(), PERMISSION_NONE);
+ AddPPB(PPB_OPENGLES2_FRAMEBUFFERMULTISAMPLE_INTERFACE_1_0, API_ID_NONE,
+ PPB_OpenGLES2_Shared::GetFramebufferMultisampleInterface(),
+ PERMISSION_NONE);
+ AddPPB(PPB_OPENGLES2_CHROMIUMENABLEFEATURE_INTERFACE_1_0, API_ID_NONE,
+ PPB_OpenGLES2_Shared::GetChromiumEnableFeatureInterface(),
+ PERMISSION_NONE);
+ AddPPB(PPB_OPENGLES2_CHROMIUMMAPSUB_INTERFACE_1_0, API_ID_NONE,
+ PPB_OpenGLES2_Shared::GetChromiumMapSubInterface(), PERMISSION_NONE);
+ AddPPB(PPB_OPENGLES2_CHROMIUMMAPSUB_DEV_INTERFACE_1_0, API_ID_NONE,
+ PPB_OpenGLES2_Shared::GetChromiumMapSubInterface(), PERMISSION_NONE);
+ AddPPB(PPB_OPENGLES2_QUERY_INTERFACE_1_0, API_ID_NONE,
+ PPB_OpenGLES2_Shared::GetQueryInterface(), PERMISSION_NONE);
+ AddPPB(PPB_VAR_ARRAY_BUFFER_INTERFACE_1_0, API_ID_NONE,
+ PPB_Var_Shared::GetVarArrayBufferInterface1_0(),
+ PERMISSION_NONE);
+ AddPPB(PPB_VAR_INTERFACE_1_1, API_ID_NONE,
+ PPB_Var_Shared::GetVarInterface1_1(), PERMISSION_NONE);
+ AddPPB(PPB_VAR_INTERFACE_1_0, API_ID_NONE,
+ PPB_Var_Shared::GetVarInterface1_0(), PERMISSION_NONE);
+
+#if !defined(OS_NACL)
+ // PPB (browser) interfaces.
+ // Do not add more stuff here, they should be added to interface_list*.h
+ // TODO(brettw) remove these.
+ AddPPB(PPB_Instance_Proxy::GetInfoPrivate(), PERMISSION_PRIVATE);
+ AddPPB(PPB_Var_Deprecated_Proxy::GetInfo(), PERMISSION_DEV);
+
+ // TODO(tomfinegan): Figure out where to put these once we refactor things
+ // to load the PPP interface struct from the PPB interface.
+ AddProxy(API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
+ &ProxyFactory<PPP_ContentDecryptor_Private_Proxy>);
+ AddPPP(PPP_CONTENTDECRYPTOR_PRIVATE_INTERFACE,
+ API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
+ PPP_ContentDecryptor_Private_Proxy::GetProxyInterface());
+#endif
+ AddPPB(PPB_Testing_Proxy::GetInfo(), PERMISSION_TESTING);
+
+ // PPP (plugin) interfaces.
+ // TODO(brettw) move these to interface_list*.h
+ AddProxy(API_ID_PPP_INSTANCE, &ProxyFactory<PPP_Instance_Proxy>);
+ #if !defined(OS_NACL)
+ AddPPP(PPP_INSTANCE_INTERFACE_1_1, API_ID_PPP_INSTANCE,
+ PPP_Instance_Proxy::GetInstanceInterface());
+ #endif
+ AddProxy(API_ID_PPP_PRINTING, &ProxyFactory<PPP_Printing_Proxy>);
+ AddPPP(PPP_PRINTING_DEV_INTERFACE, API_ID_PPP_PRINTING,
+ PPP_Printing_Proxy::GetProxyInterface());
+ AddProxy(API_ID_PPP_TEXT_INPUT, &ProxyFactory<PPP_TextInput_Proxy>);
+ AddPPP(PPP_TEXTINPUT_DEV_INTERFACE, API_ID_PPP_TEXT_INPUT,
+ PPP_TextInput_Proxy::GetProxyInterface());
+
+ // Old-style GetInfo PPP interfaces.
+ // Do not add more stuff here, they should be added to interface_list*.h
+ // TODO(brettw) remove these.
+ AddPPP(PPP_InputEvent_Proxy::GetInfo());
+ AddPPP(PPP_Messaging_Proxy::GetInfo());
+ AddPPP(PPP_MouseLock_Proxy::GetInfo());
+ AddPPP(PPP_Graphics3D_Proxy::GetInfo());
+#if !defined(OS_NACL)
+ AddPPP(PPP_Instance_Private_Proxy::GetInfo());
+ AddPPP(PPP_VideoDecoder_Proxy::GetInfo());
+#endif
+}
+
+InterfaceList::~InterfaceList() {
+}
+
+// static
+InterfaceList* InterfaceList::GetInstance() {
+ return Singleton<InterfaceList>::get();
+}
+
+// static
+void InterfaceList::SetProcessGlobalPermissions(
+ const PpapiPermissions& permissions) {
+ g_process_global_permissions.Get() = permissions;
+}
+
+ApiID InterfaceList::GetIDForPPBInterface(const std::string& name) const {
+ NameToInterfaceInfoMap::const_iterator found =
+ name_to_browser_info_.find(name);
+ if (found == name_to_browser_info_.end())
+ return API_ID_NONE;
+ return found->second.id;
+}
+
+ApiID InterfaceList::GetIDForPPPInterface(const std::string& name) const {
+ NameToInterfaceInfoMap::const_iterator found =
+ name_to_plugin_info_.find(name);
+ if (found == name_to_plugin_info_.end())
+ return API_ID_NONE;
+ return found->second.id;
+}
+
+InterfaceProxy::Factory InterfaceList::GetFactoryForID(ApiID id) const {
+ int index = static_cast<int>(id);
+ COMPILE_ASSERT(API_ID_NONE == 0, none_must_be_zero);
+ if (id <= 0 || id >= API_ID_COUNT)
+ return NULL;
+ return id_to_factory_[index];
+}
+
+const void* InterfaceList::GetInterfaceForPPB(const std::string& name) const {
+ NameToInterfaceInfoMap::const_iterator found =
+ name_to_browser_info_.find(name);
+ if (found == name_to_browser_info_.end())
+ return NULL;
+
+ if (g_process_global_permissions.Get().HasPermission(
+ found->second.required_permission))
+ return found->second.iface;
+ return NULL;
+}
+
+const void* InterfaceList::GetInterfaceForPPP(const std::string& name) const {
+ NameToInterfaceInfoMap::const_iterator found =
+ name_to_plugin_info_.find(name);
+ if (found == name_to_plugin_info_.end())
+ return NULL;
+ return found->second.iface;
+}
+
+void InterfaceList::AddProxy(ApiID id,
+ InterfaceProxy::Factory factory) {
+ // For interfaces with no corresponding _Proxy objects, the macros will
+ // generate calls to this function with API_ID_NONE. This means we
+ // should just skip adding a factory for these functions.
+ if (id == API_ID_NONE)
+ return;
+
+ // The factory should be an exact dupe of the one we already have if it
+ // has already been registered before.
+ int index = static_cast<int>(id);
+ DCHECK(!id_to_factory_[index] || id_to_factory_[index] == factory);
+
+ id_to_factory_[index] = factory;
+}
+
+void InterfaceList::AddPPB(const char* name,
+ ApiID id,
+ const void* iface,
+ Permission perm) {
+ DCHECK(name_to_browser_info_.find(name) == name_to_browser_info_.end());
+ name_to_browser_info_[name] = InterfaceInfo(id, iface, perm);
+}
+
+void InterfaceList::AddPPP(const char* name,
+ ApiID id,
+ const void* iface) {
+ DCHECK(name_to_plugin_info_.find(name) == name_to_plugin_info_.end());
+ name_to_plugin_info_[name] = InterfaceInfo(id, iface, PERMISSION_NONE);
+}
+
+void InterfaceList::AddPPB(const InterfaceProxy::Info* info, Permission perm) {
+ AddProxy(info->id, info->create_proxy);
+ AddPPB(info->name, info->id, info->interface_ptr, perm);
+}
+
+void InterfaceList::AddPPP(const InterfaceProxy::Info* info) {
+ AddProxy(info->id, info->create_proxy);
+ AddPPP(info->name, info->id, info->interface_ptr);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/interface_list.h b/chromium/ppapi/proxy/interface_list.h
new file mode 100644
index 00000000000..9ef91dcc1f9
--- /dev/null
+++ b/chromium/ppapi/proxy/interface_list.h
@@ -0,0 +1,105 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_INTERFACE_LIST_H_
+#define PPAPI_PROXY_INTERFACE_LIST_H_
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/ppapi_permissions.h"
+
+namespace ppapi {
+namespace proxy {
+
+class InterfaceList {
+ public:
+ InterfaceList();
+ ~InterfaceList();
+
+ static InterfaceList* GetInstance();
+
+ // Sets the permissions that the interface list will use to compute
+ // whether an interface is available to the current process. By default,
+ // this will be "no permissions", which will give only access to public
+ // stable interfaces via GetInterface.
+ //
+ // IMPORTANT: This is not a security boundary. Malicious plugins can bypass
+ // this check since they run in the same address space as this code in the
+ // plugin process. A real security check is required for all IPC messages.
+ // This check just allows us to return NULL for interfaces you "shouldn't" be
+ // using to keep honest plugins honest.
+ static PPAPI_PROXY_EXPORT void SetProcessGlobalPermissions(
+ const PpapiPermissions& permissions);
+
+ // Looks up the ID for the given interface name. Returns API_ID_NONE if
+ // the interface string is not found.
+ ApiID GetIDForPPBInterface(const std::string& name) const;
+ ApiID GetIDForPPPInterface(const std::string& name) const;
+
+ // Looks up the factory function for the given ID. Returns NULL if not
+ // supported.
+ InterfaceProxy::Factory GetFactoryForID(ApiID id) const;
+
+ // Returns the interface pointer for the given browser or plugin interface,
+ // or NULL if it's not supported.
+ const void* GetInterfaceForPPB(const std::string& name) const;
+ const void* GetInterfaceForPPP(const std::string& name) const;
+
+ private:
+ struct InterfaceInfo {
+ InterfaceInfo()
+ : id(API_ID_NONE),
+ iface(NULL),
+ required_permission(PERMISSION_NONE) {
+ }
+ InterfaceInfo(ApiID in_id, const void* in_interface, Permission in_perm)
+ : id(in_id),
+ iface(in_interface),
+ required_permission(in_perm) {
+ }
+
+ ApiID id;
+ const void* iface;
+
+ // Permission required to return non-null for this interface. This will
+ // be checked with the value set via SetProcessGlobalPermissionBits when
+ // an interface is requested.
+ Permission required_permission;
+ };
+
+ typedef std::map<std::string, InterfaceInfo> NameToInterfaceInfoMap;
+
+ void AddProxy(ApiID id, InterfaceProxy::Factory factory);
+
+ // Permissions is the type of permission required to access the corresponding
+ // interface. Currently this must be just one unique permission (rather than
+ // a bitfield).
+ void AddPPB(const char* name, ApiID id, const void* iface,
+ Permission permission);
+ void AddPPP(const char* name, ApiID id, const void* iface);
+
+ // Old-style add functions. These should be removed when the rest of the
+ // proxies are converted over to using the new system.
+ void AddPPB(const InterfaceProxy::Info* info, Permission perm);
+ void AddPPP(const InterfaceProxy::Info* info);
+
+ PpapiPermissions permissions_;
+
+ NameToInterfaceInfoMap name_to_browser_info_;
+ NameToInterfaceInfoMap name_to_plugin_info_;
+
+ InterfaceProxy::Factory id_to_factory_[API_ID_COUNT];
+
+ DISALLOW_COPY_AND_ASSIGN(InterfaceList);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_INTERFACE_LIST_H_
+
diff --git a/chromium/ppapi/proxy/interface_proxy.cc b/chromium/ppapi/proxy/interface_proxy.cc
new file mode 100644
index 00000000000..2de48033944
--- /dev/null
+++ b/chromium/ppapi/proxy/interface_proxy.cc
@@ -0,0 +1,25 @@
+// 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/interface_proxy.h"
+
+#include "base/logging.h"
+#include "ppapi/proxy/dispatcher.h"
+
+namespace ppapi {
+namespace proxy {
+
+InterfaceProxy::InterfaceProxy(Dispatcher* dispatcher)
+ : dispatcher_(dispatcher) {
+}
+
+InterfaceProxy::~InterfaceProxy() {
+}
+
+bool InterfaceProxy::Send(IPC::Message* msg) {
+ return dispatcher_->Send(msg);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/interface_proxy.h b/chromium/ppapi/proxy/interface_proxy.h
new file mode 100644
index 00000000000..dcab5473c9c
--- /dev/null
+++ b/chromium/ppapi/proxy/interface_proxy.h
@@ -0,0 +1,68 @@
+// 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_listener.h"
+#include "ipc/ipc_sender.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/shared_impl/api_id.h"
+
+namespace ppapi {
+namespace proxy {
+
+class Dispatcher;
+
+class InterfaceProxy : public IPC::Listener, public IPC::Sender {
+ public:
+ // Factory function type for interfaces. Ownership of the returned pointer
+ // is transferred to the caller.
+ typedef InterfaceProxy* (*Factory)(Dispatcher* dispatcher);
+
+ // DEPRECATED: New classes should be registered directly in the interface
+ // list. This is kept around until we convert all the existing code.
+ //
+ // 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;
+ ApiID id;
+
+ bool is_trusted;
+
+ InterfaceProxy::Factory create_proxy;
+ };
+
+ virtual ~InterfaceProxy();
+
+ Dispatcher* dispatcher() const { return dispatcher_; }
+
+ // IPC::Sender implementation.
+ virtual bool Send(IPC::Message* msg);
+
+ // Sub-classes must implement IPC::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.
+ InterfaceProxy(Dispatcher* dispatcher);
+
+ private:
+ Dispatcher* dispatcher_;
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_INTERFACE_PROXY_H_
+
diff --git a/chromium/ppapi/proxy/locking_resource_releaser.h b/chromium/ppapi/proxy/locking_resource_releaser.h
new file mode 100644
index 00000000000..d390ac4426e
--- /dev/null
+++ b/chromium/ppapi/proxy/locking_resource_releaser.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2013 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_LOCKING_RESOURCE_RELEASER_H_
+#define PPAPI_PROXY_LOCKING_RESOURCE_RELEASER_H_
+
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/resource_tracker.h"
+
+namespace ppapi {
+namespace proxy {
+
+// LockingResourceReleaser is a simple RAII class for releasing a resource at
+// the end of scope. This acquires the ProxyLock before releasing the resource.
+// It is for use in unit tests. Most proxy or implementation code should use
+// ScopedPPResource instead. Unit tests sometimes can't use ScopedPPResource
+// because it asserts that the ProxyLock is already held.
+class LockingResourceReleaser {
+ public:
+ explicit LockingResourceReleaser(PP_Resource resource)
+ : resource_(resource) {
+ }
+ ~LockingResourceReleaser() {
+ ProxyAutoLock lock;
+ PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(resource_);
+ }
+
+ PP_Resource get() { return resource_; }
+
+ private:
+ PP_Resource resource_;
+
+ DISALLOW_COPY_AND_ASSIGN(LockingResourceReleaser);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_LOCKING_RESOURCE_RELEASER_H_
diff --git a/chromium/ppapi/proxy/mock_resource.cc b/chromium/ppapi/proxy/mock_resource.cc
new file mode 100644
index 00000000000..9662bad4f41
--- /dev/null
+++ b/chromium/ppapi/proxy/mock_resource.cc
@@ -0,0 +1,18 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/mock_resource.h"
+
+namespace ppapi {
+namespace proxy {
+
+MockResource::MockResource(const HostResource& resource)
+ : Resource(OBJECT_IS_PROXY, resource) {
+}
+
+MockResource::~MockResource() {
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/mock_resource.h b/chromium/ppapi/proxy/mock_resource.h
new file mode 100644
index 00000000000..768929da4f5
--- /dev/null
+++ b/chromium/ppapi/proxy/mock_resource.h
@@ -0,0 +1,26 @@
+// 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/shared_impl/resource.h"
+
+namespace ppapi {
+namespace proxy {
+
+class MockResource : public ppapi::Resource {
+ public:
+ MockResource(const ppapi::HostResource& resource);
+ virtual ~MockResource();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_MOCK_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/net_address_resource.cc b/chromium/ppapi/proxy/net_address_resource.cc
new file mode 100644
index 00000000000..9d906a5e062
--- /dev/null
+++ b/chromium/ppapi/proxy/net_address_resource.cc
@@ -0,0 +1,81 @@
+// Copyright 2013 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/net_address_resource.h"
+
+#include <string>
+
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/shared_impl/private/net_address_private_impl.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+namespace proxy {
+
+NetAddressResource::NetAddressResource(
+ Connection connection,
+ PP_Instance instance,
+ const PP_NetAddress_IPv4& ipv4_addr)
+ : PluginResource(connection, instance) {
+ NetAddressPrivateImpl::CreateNetAddressPrivateFromIPv4Address(ipv4_addr,
+ &address_);
+}
+
+NetAddressResource::NetAddressResource(
+ Connection connection,
+ PP_Instance instance,
+ const PP_NetAddress_IPv6& ipv6_addr)
+ : PluginResource(connection, instance) {
+ NetAddressPrivateImpl::CreateNetAddressPrivateFromIPv6Address(ipv6_addr,
+ &address_);
+}
+
+NetAddressResource::NetAddressResource(
+ Connection connection,
+ PP_Instance instance,
+ const PP_NetAddress_Private& private_addr)
+ : PluginResource(connection, instance) {
+ address_ = private_addr;
+}
+
+NetAddressResource::~NetAddressResource() {
+}
+
+thunk::PPB_NetAddress_API* NetAddressResource::AsPPB_NetAddress_API() {
+ return this;
+}
+
+PP_NetAddress_Family NetAddressResource::GetFamily() {
+ return NetAddressPrivateImpl::GetFamilyFromNetAddressPrivate(address_);
+}
+
+PP_Var NetAddressResource::DescribeAsString(PP_Bool include_port) {
+ std::string description = NetAddressPrivateImpl::DescribeNetAddress(
+ address_, PP_ToBool(include_port));
+
+ if (description.empty())
+ return PP_MakeUndefined();
+ return StringVar::StringToPPVar(description);
+}
+
+PP_Bool NetAddressResource::DescribeAsIPv4Address(
+ PP_NetAddress_IPv4* ipv4_addr) {
+ return PP_FromBool(
+ NetAddressPrivateImpl::DescribeNetAddressPrivateAsIPv4Address(
+ address_, ipv4_addr));
+}
+
+PP_Bool NetAddressResource::DescribeAsIPv6Address(
+ PP_NetAddress_IPv6* ipv6_addr) {
+ return PP_FromBool(
+ NetAddressPrivateImpl::DescribeNetAddressPrivateAsIPv6Address(
+ address_, ipv6_addr));
+}
+
+const PP_NetAddress_Private& NetAddressResource::GetNetAddressPrivate() {
+ return address_;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/net_address_resource.h b/chromium/ppapi/proxy/net_address_resource.h
new file mode 100644
index 00000000000..4d236049f91
--- /dev/null
+++ b/chromium/ppapi/proxy/net_address_resource.h
@@ -0,0 +1,56 @@
+// Copyright 2013 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_NET_ADDRESS_RESOURCE_H_
+#define PPAPI_PROXY_NET_ADDRESS_RESOURCE_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ppapi/c/private/ppb_net_address_private.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/thunk/ppb_net_address_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT NetAddressResource : public PluginResource,
+ public thunk::PPB_NetAddress_API {
+ public:
+ NetAddressResource(Connection connection,
+ PP_Instance instance,
+ const PP_NetAddress_IPv4& ipv4_addr);
+ NetAddressResource(Connection connection,
+ PP_Instance instance,
+ const PP_NetAddress_IPv6& ipv6_addr);
+ NetAddressResource(Connection connection,
+ PP_Instance instance,
+ const PP_NetAddress_Private& private_addr);
+
+ virtual ~NetAddressResource();
+
+ // PluginResource implementation.
+ virtual thunk::PPB_NetAddress_API* AsPPB_NetAddress_API() OVERRIDE;
+
+ // PPB_NetAddress_API implementation.
+ virtual PP_NetAddress_Family GetFamily() OVERRIDE;
+ virtual PP_Var DescribeAsString(PP_Bool include_port) OVERRIDE;
+ virtual PP_Bool DescribeAsIPv4Address(
+ PP_NetAddress_IPv4* ipv4_addr) OVERRIDE;
+ virtual PP_Bool DescribeAsIPv6Address(
+ PP_NetAddress_IPv6* ipv6_addr) OVERRIDE;
+ virtual const PP_NetAddress_Private& GetNetAddressPrivate() OVERRIDE;
+
+ private:
+ // TODO(yzshen): Refactor the code so that PPB_NetAddress resource doesn't
+ // use PP_NetAddress_Private as storage type.
+ PP_NetAddress_Private address_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetAddressResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_NET_ADDRESS_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/network_proxy_resource.cc b/chromium/ppapi/proxy/network_proxy_resource.cc
new file mode 100644
index 00000000000..b004130f018
--- /dev/null
+++ b/chromium/ppapi/proxy/network_proxy_resource.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2013 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/network_proxy_resource.h"
+
+#include "base/bind.h"
+#include "ppapi/proxy/dispatch_reply_message.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+namespace proxy {
+
+NetworkProxyResource::NetworkProxyResource(Connection connection,
+ PP_Instance instance)
+ : PluginResource(connection, instance) {
+ SendCreate(BROWSER, PpapiHostMsg_NetworkProxy_Create());
+}
+
+NetworkProxyResource::~NetworkProxyResource() {
+}
+
+thunk::PPB_NetworkProxy_API* NetworkProxyResource::AsPPB_NetworkProxy_API() {
+ return this;
+}
+
+int32_t NetworkProxyResource::GetProxyForURL(
+ PP_Instance /* instance */,
+ PP_Var url,
+ PP_Var* proxy_string,
+ scoped_refptr<TrackedCallback> callback) {
+ StringVar* string_url = StringVar::FromPPVar(url);
+ if (!string_url)
+ return PP_ERROR_BADARGUMENT;
+ Call<PpapiPluginMsg_NetworkProxy_GetProxyForURLReply>(
+ BROWSER,
+ PpapiHostMsg_NetworkProxy_GetProxyForURL(string_url->value()),
+ base::Bind(&NetworkProxyResource::OnPluginMsgGetProxyForURLReply,
+ base::Unretained(this),
+ base::Unretained(proxy_string),
+ callback));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void NetworkProxyResource::OnPluginMsgGetProxyForURLReply(
+ PP_Var* proxy_string_out_param,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const std::string& proxy_string) {
+ if (!TrackedCallback::IsPending(callback)) {
+ // The callback should not have already been run. If this resource is
+ // deleted, LastPluginRefWasReleased in PluginResource should abort the
+ // callback and should not run this callback.
+ NOTREACHED();
+ return;
+ }
+ if (params.result() == PP_OK) {
+ *proxy_string_out_param = (new StringVar(proxy_string))->GetPPVar();
+ }
+ callback->Run(params.result());
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/network_proxy_resource.h b/chromium/ppapi/proxy/network_proxy_resource.h
new file mode 100644
index 00000000000..f2084ab3fd8
--- /dev/null
+++ b/chromium/ppapi/proxy/network_proxy_resource.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2013 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_NETWORK_PROXY_RESOURCE_H_
+#define PPAPI_PROXY_NETWORK_PROXY_RESOURCE_H_
+
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/thunk/ppb_network_proxy_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+// The proxy-side resource for PPB_NetworkProxy.
+class PPAPI_PROXY_EXPORT NetworkProxyResource
+ : public PluginResource,
+ public thunk::PPB_NetworkProxy_API {
+ public:
+ NetworkProxyResource(Connection connection, PP_Instance instance);
+ virtual ~NetworkProxyResource();
+
+ private:
+ // Resource implementation.
+ virtual thunk::PPB_NetworkProxy_API* AsPPB_NetworkProxy_API() OVERRIDE;
+
+ // PPB_NetworkProxy_API implementation.
+ virtual int32_t GetProxyForURL(
+ PP_Instance instance,
+ PP_Var url,
+ PP_Var* proxy_string,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+
+ void OnPluginMsgGetProxyForURLReply(PP_Var* proxy_string_out_param,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const std::string& proxy_string);
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkProxyResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_NETWORK_PROXY_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/pdf_resource.cc b/chromium/ppapi/proxy/pdf_resource.cc
new file mode 100644
index 00000000000..8e0a2e0bbf1
--- /dev/null
+++ b/chromium/ppapi/proxy/pdf_resource.cc
@@ -0,0 +1,192 @@
+// Copyright (c) 2013 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/pdf_resource.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "base/command_line.h"
+#include "base/metrics/histogram.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/private/ppb_pdf.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_image_data_proxy.h"
+#include "ppapi/shared_impl/var.h"
+#include "third_party/icu/source/i18n/unicode/usearch.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+// TODO(raymes): This is just copied from render_thread_impl.cc. We should have
+// generic code somewhere to get the locale in the plugin.
+std::string GetLocale() {
+ // The browser process should have passed the locale to the plugin via the
+ // --lang command line flag.
+ const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
+ const std::string& lang = parsed_command_line.GetSwitchValueASCII("lang");
+ DCHECK(!lang.empty());
+ return lang;
+}
+
+} // namespace
+
+PDFResource::PDFResource(Connection connection, PP_Instance instance)
+ : PluginResource(connection, instance) {
+ SendCreate(RENDERER, PpapiHostMsg_PDF_Create());
+}
+
+PDFResource::~PDFResource() {
+}
+
+thunk::PPB_PDF_API* PDFResource::AsPPB_PDF_API() {
+ return this;
+}
+
+PP_Var PDFResource::GetLocalizedString(PP_ResourceString string_id) {
+ std::string localized_string;
+ int32_t result = SyncCall<PpapiPluginMsg_PDF_GetLocalizedStringReply>(
+ RENDERER, PpapiHostMsg_PDF_GetLocalizedString(string_id),
+ &localized_string);
+ if (result != PP_OK)
+ return PP_MakeUndefined();
+ return ppapi::StringVar::StringToPPVar(localized_string);
+}
+
+void PDFResource::SearchString(const unsigned short* input_string,
+ const unsigned short* input_term,
+ bool case_sensitive,
+ PP_PrivateFindResult** results, int* count) {
+ if (locale_.empty())
+ locale_ = GetLocale();
+ const char16* string = reinterpret_cast<const char16*>(input_string);
+ const char16* term = reinterpret_cast<const char16*>(input_term);
+
+ UErrorCode status = U_ZERO_ERROR;
+ UStringSearch* searcher = usearch_open(term, -1, string, -1, locale_.c_str(),
+ 0, &status);
+ DCHECK(status == U_ZERO_ERROR || status == U_USING_FALLBACK_WARNING ||
+ status == U_USING_DEFAULT_WARNING);
+ UCollationStrength strength = case_sensitive ? UCOL_TERTIARY : UCOL_PRIMARY;
+
+ UCollator* collator = usearch_getCollator(searcher);
+ if (ucol_getStrength(collator) != strength) {
+ ucol_setStrength(collator, strength);
+ usearch_reset(searcher);
+ }
+
+ status = U_ZERO_ERROR;
+ int match_start = usearch_first(searcher, &status);
+ DCHECK(status == U_ZERO_ERROR);
+
+ std::vector<PP_PrivateFindResult> pp_results;
+ while (match_start != USEARCH_DONE) {
+ size_t matched_length = usearch_getMatchedLength(searcher);
+ PP_PrivateFindResult result;
+ result.start_index = match_start;
+ result.length = matched_length;
+ pp_results.push_back(result);
+ match_start = usearch_next(searcher, &status);
+ DCHECK(status == U_ZERO_ERROR);
+ }
+
+ *count = pp_results.size();
+ if (*count) {
+ *results = reinterpret_cast<PP_PrivateFindResult*>(malloc(
+ *count * sizeof(PP_PrivateFindResult)));
+ memcpy(*results, &pp_results[0], *count * sizeof(PP_PrivateFindResult));
+ } else {
+ *results = NULL;
+ }
+
+ usearch_close(searcher);
+}
+
+void PDFResource::DidStartLoading() {
+ Post(RENDERER, PpapiHostMsg_PDF_DidStartLoading());
+}
+
+void PDFResource::DidStopLoading() {
+ Post(RENDERER, PpapiHostMsg_PDF_DidStopLoading());
+}
+
+void PDFResource::SetContentRestriction(int restrictions) {
+ Post(RENDERER, PpapiHostMsg_PDF_SetContentRestriction(restrictions));
+}
+
+void PDFResource::HistogramPDFPageCount(int count) {
+ UMA_HISTOGRAM_COUNTS_10000("PDF.PageCount", count);
+}
+
+void PDFResource::UserMetricsRecordAction(const PP_Var& action) {
+ scoped_refptr<ppapi::StringVar> action_str(
+ ppapi::StringVar::FromPPVar(action));
+ if (action_str.get()) {
+ Post(RENDERER,
+ PpapiHostMsg_PDF_UserMetricsRecordAction(action_str->value()));
+ }
+}
+
+void PDFResource::HasUnsupportedFeature() {
+ Post(RENDERER, PpapiHostMsg_PDF_HasUnsupportedFeature());
+}
+
+void PDFResource::Print() {
+ Post(RENDERER, PpapiHostMsg_PDF_Print());
+}
+
+void PDFResource::SaveAs() {
+ Post(RENDERER, PpapiHostMsg_PDF_SaveAs());
+}
+
+PP_Bool PDFResource::IsFeatureEnabled(PP_PDFFeature feature) {
+ PP_Bool result = PP_FALSE;
+ switch (feature) {
+ case PP_PDFFEATURE_HIDPI:
+ result = PP_TRUE;
+ break;
+ case PP_PDFFEATURE_PRINTING:
+ // TODO(raymes): Use PrintWebViewHelper::IsPrintingEnabled.
+ result = PP_FALSE;
+ break;
+ }
+ return result;
+}
+
+PP_Resource PDFResource::GetResourceImageForScale(PP_ResourceImage image_id,
+ float scale) {
+ IPC::Message reply;
+ ResourceMessageReplyParams reply_params;
+ int32_t result = GenericSyncCall(
+ RENDERER, PpapiHostMsg_PDF_GetResourceImage(image_id, scale), &reply,
+ &reply_params);
+ if (result != PP_OK)
+ return 0;
+
+ HostResource resource;
+ PP_ImageDataDesc image_desc;
+ if (!UnpackMessage<PpapiPluginMsg_PDF_GetResourceImageReply>(
+ reply, &resource, &image_desc)) {
+ return 0;
+ }
+
+ if (resource.is_null())
+ return 0;
+ if (!PPB_ImageData_Shared::IsImageDataDescValid(image_desc))
+ return 0;
+
+ base::SharedMemoryHandle handle;
+ if (!reply_params.TakeSharedMemoryHandleAtIndex(0, &handle))
+ return 0;
+ return (new SimpleImageData(resource, image_desc, handle))->GetReference();
+}
+
+PP_Resource PDFResource::GetResourceImage(PP_ResourceImage image_id) {
+ return GetResourceImageForScale(image_id, 1.0f);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/pdf_resource.h b/chromium/ppapi/proxy/pdf_resource.h
new file mode 100644
index 00000000000..704e1d4a44e
--- /dev/null
+++ b/chromium/ppapi/proxy/pdf_resource.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2013 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_PDF_RESOURCE_H_
+#define PPAPI_PROXY_PDF_RESOURCE_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/private/ppb_flash.h"
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/thunk/ppb_pdf_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PluginDispatcher;
+
+class PPAPI_PROXY_EXPORT PDFResource
+ : public PluginResource,
+ public thunk::PPB_PDF_API {
+ public:
+ PDFResource(Connection connection, PP_Instance instance);
+ virtual ~PDFResource();
+
+ // For unittesting with a given locale.
+ void SetLocaleForTest(const std::string& locale) {
+ locale_ = locale;
+ }
+
+ // Resource override.
+ virtual thunk::PPB_PDF_API* AsPPB_PDF_API() OVERRIDE;
+
+ // PPB_PDF_API implementation.
+ PP_Var GetLocalizedString(PP_ResourceString string_id) OVERRIDE;
+ virtual void SearchString(const unsigned short* input_string,
+ const unsigned short* input_term,
+ bool case_sensitive,
+ PP_PrivateFindResult** results,
+ int* count) OVERRIDE;
+ virtual void DidStartLoading() OVERRIDE;
+ virtual void DidStopLoading() OVERRIDE;
+ virtual void SetContentRestriction(int restrictions) OVERRIDE;
+ virtual void HistogramPDFPageCount(int count) OVERRIDE;
+ virtual void UserMetricsRecordAction(const PP_Var& action) OVERRIDE;
+ virtual void HasUnsupportedFeature() OVERRIDE;
+ virtual void Print() OVERRIDE;
+ virtual void SaveAs() OVERRIDE;
+ virtual PP_Bool IsFeatureEnabled(PP_PDFFeature feature) OVERRIDE;
+ virtual PP_Resource GetResourceImageForScale(PP_ResourceImage image_id,
+ float scale) OVERRIDE;
+ virtual PP_Resource GetResourceImage(PP_ResourceImage image_id) OVERRIDE;
+
+ private:
+ std::string locale_;
+
+ DISALLOW_COPY_AND_ASSIGN(PDFResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PDF_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/pdf_resource_unittest.cc b/chromium/ppapi/proxy/pdf_resource_unittest.cc
new file mode 100644
index 00000000000..3ac60d6413b
--- /dev/null
+++ b/chromium/ppapi/proxy/pdf_resource_unittest.cc
@@ -0,0 +1,206 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <cstring>
+
+#include "base/strings/utf_string_conversions.h"
+#include "ppapi/c/dev/ppb_memory_dev.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_image_data.h"
+#include "ppapi/proxy/pdf_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+#include "ppapi/proxy/ppb_image_data_proxy.h"
+#include "ppapi/proxy/serialized_handle.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/scoped_pp_var.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/thunk.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+typedef PluginProxyTest PDFResourceTest;
+
+} // namespace
+
+TEST_F(PDFResourceTest, GetLocalizedString) {
+ const PPB_PDF* pdf_iface = thunk::GetPPB_PDF_Thunk();
+
+ std::string expected_string = "hello";
+ PpapiPluginMsg_PDF_GetLocalizedStringReply reply_msg(expected_string);
+ ResourceSyncCallHandler handler(
+ &sink(),
+ PpapiHostMsg_PDF_GetLocalizedString::ID,
+ PP_OK,
+ reply_msg);
+ sink().AddFilter(&handler);
+
+ PP_Var var = pdf_iface->GetLocalizedString(
+ pp_instance(), PP_RESOURCESTRING_PDFGETPASSWORD);
+
+ {
+ ProxyAutoLock lock;
+ ScopedPPVar release_var(ScopedPPVar::PassRef(), var);
+ StringVar* string_var = StringVar::FromPPVar(var);
+ ASSERT_TRUE(string_var != NULL);
+ std::string actual_string = string_var->value();
+
+ ASSERT_EQ(PpapiHostMsg_PDF_GetLocalizedString::ID,
+ handler.last_handled_msg().type());
+ ASSERT_EQ(expected_string, actual_string);
+ }
+
+ // Remove the filter or it will be destroyed before the sink() is destroyed.
+ sink().RemoveFilter(&handler);
+}
+
+TEST_F(PDFResourceTest, SearchString) {
+ ProxyAutoLock lock;
+ // Instantiate a resource explicitly so we can specify the locale.
+ scoped_refptr<PDFResource> pdf_resource(
+ new PDFResource(Connection(&sink(), &sink()), pp_instance()));
+ pdf_resource->SetLocaleForTest("en-US");
+
+ string16 input;
+ string16 term;
+ UTF8ToUTF16("abcdefabcdef", 12, &input);
+ UTF8ToUTF16("bc", 2, &term);
+
+ PP_PrivateFindResult* results;
+ int count = 0;
+ pdf_resource->SearchString(
+ reinterpret_cast<const unsigned short*>(input.c_str()),
+ reinterpret_cast<const unsigned short*>(term.c_str()),
+ true,
+ &results,
+ &count);
+
+ ASSERT_EQ(2, count);
+ ASSERT_EQ(1, results[0].start_index);
+ ASSERT_EQ(2, results[0].length);
+ ASSERT_EQ(7, results[1].start_index);
+ ASSERT_EQ(2, results[1].length);
+
+ const PPB_Memory_Dev* memory_iface = thunk::GetPPB_Memory_Dev_0_1_Thunk();
+ memory_iface->MemFree(results);
+}
+
+TEST_F(PDFResourceTest, DidStartLoading) {
+ const PPB_PDF* pdf_iface = thunk::GetPPB_PDF_Thunk();
+
+ pdf_iface->DidStartLoading(pp_instance());
+
+ ResourceMessageCallParams params;
+ IPC::Message msg;
+ ASSERT_TRUE(sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_PDF_DidStartLoading::ID, &params, &msg));
+}
+
+TEST_F(PDFResourceTest, DidStopLoading) {
+ const PPB_PDF* pdf_iface = thunk::GetPPB_PDF_Thunk();
+
+ pdf_iface->DidStopLoading(pp_instance());
+
+ ResourceMessageCallParams params;
+ IPC::Message msg;
+ ASSERT_TRUE(sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_PDF_DidStopLoading::ID, &params, &msg));
+}
+
+TEST_F(PDFResourceTest, SetContentRestriction) {
+ const PPB_PDF* pdf_iface = thunk::GetPPB_PDF_Thunk();
+
+ int restrictions = 5;
+ pdf_iface->SetContentRestriction(pp_instance(), restrictions);
+
+ ResourceMessageCallParams params;
+ IPC::Message msg;
+ ASSERT_TRUE(sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_PDF_SetContentRestriction::ID, &params, &msg));
+}
+
+TEST_F(PDFResourceTest, HasUnsupportedFeature) {
+ const PPB_PDF* pdf_iface = thunk::GetPPB_PDF_Thunk();
+
+ pdf_iface->HasUnsupportedFeature(pp_instance());
+
+ ResourceMessageCallParams params;
+ IPC::Message msg;
+ ASSERT_TRUE(sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_PDF_HasUnsupportedFeature::ID, &params, &msg));
+}
+
+TEST_F(PDFResourceTest, Print) {
+ const PPB_PDF* pdf_iface = thunk::GetPPB_PDF_Thunk();
+
+ pdf_iface->Print(pp_instance());
+
+ ResourceMessageCallParams params;
+ IPC::Message msg;
+ ASSERT_TRUE(sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_PDF_Print::ID, &params, &msg));
+}
+
+TEST_F(PDFResourceTest, SaveAs) {
+ const PPB_PDF* pdf_iface = thunk::GetPPB_PDF_Thunk();
+
+ pdf_iface->SaveAs(pp_instance());
+
+ ResourceMessageCallParams params;
+ IPC::Message msg;
+ ASSERT_TRUE(sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_PDF_SaveAs::ID, &params, &msg));
+}
+
+TEST_F(PDFResourceTest, GetResourceImageForScale) {
+ const PPB_PDF* pdf_iface = thunk::GetPPB_PDF_Thunk();
+
+ HostResource expected_resource;
+ expected_resource.SetHostResource(pp_instance(), 5);
+ PP_ImageDataDesc expected_desc = {
+ PP_IMAGEDATAFORMAT_BGRA_PREMUL,
+ { 5, 10 },
+ 20,
+ };
+ SerializedHandle serialized_handle(SerializedHandle::SHARED_MEMORY);
+ PpapiPluginMsg_PDF_GetResourceImageReply reply_msg(expected_resource,
+ expected_desc);
+ ResourceSyncCallHandler handler(
+ &sink(),
+ PpapiHostMsg_PDF_GetResourceImage::ID,
+ PP_OK,
+ reply_msg);
+ handler.set_serialized_handle(&serialized_handle);
+ sink().AddFilter(&handler);
+
+ PP_Resource resource = pdf_iface->GetResourceImageForScale(pp_instance(),
+ PP_RESOURCEIMAGE_PDF_BUTTON_FTP, 1.0f);
+ {
+ ProxyAutoLock lock;
+ PluginResourceTracker* resource_tracker =
+ static_cast<PluginResourceTracker*>(
+ PluginGlobals::Get()->GetResourceTracker());
+ Resource* resource_object = resource_tracker->GetResource(resource);
+ ImageData* image_data_object = static_cast<ImageData*>(resource_object);
+ PP_ImageDataDesc actual_desc = image_data_object->desc();
+ ASSERT_EQ(expected_desc.format, actual_desc.format);
+ ASSERT_EQ(expected_desc.size.width, actual_desc.size.width);
+ ASSERT_EQ(expected_desc.size.height, actual_desc.size.height);
+ ASSERT_EQ(expected_desc.stride, actual_desc.stride);
+
+ ASSERT_EQ(resource_tracker->PluginResourceForHostResource(
+ expected_resource), resource);
+
+ resource_tracker->ReleaseResource(resource);
+ }
+
+ // Remove the filter or it will be destroyed before the sink() is destroyed.
+ sink().RemoveFilter(&handler);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/plugin_array_buffer_var.cc b/chromium/ppapi/proxy/plugin_array_buffer_var.cc
new file mode 100644
index 00000000000..7dd64d17b13
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_array_buffer_var.cc
@@ -0,0 +1,110 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/plugin_array_buffer_var.h"
+
+#include <stdlib.h>
+
+#include <limits>
+
+#include "base/memory/shared_memory.h"
+#include "ppapi/c/dev/ppb_buffer_dev.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/serialized_structs.h"
+#include "ppapi/shared_impl/host_resource.h"
+#include "ppapi/shared_impl/resource.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_buffer_api.h"
+
+using base::SharedMemory;
+using base::SharedMemoryHandle;
+using ppapi::proxy::PluginGlobals;
+using ppapi::proxy::PluginResourceTracker;
+
+namespace ppapi {
+
+PluginArrayBufferVar::PluginArrayBufferVar(uint32 size_in_bytes)
+ : buffer_(size_in_bytes),
+ plugin_handle_(base::SharedMemory::NULLHandle()),
+ size_in_bytes_(size_in_bytes) {
+}
+
+PluginArrayBufferVar::PluginArrayBufferVar(uint32 size_in_bytes,
+ SharedMemoryHandle plugin_handle)
+ : plugin_handle_(plugin_handle),
+ size_in_bytes_(size_in_bytes) {
+}
+
+PluginArrayBufferVar::~PluginArrayBufferVar() {
+ Unmap();
+
+ if (shmem_.get() == NULL) {
+ // The SharedMemory destuctor can't close the handle for us.
+ if (SharedMemory::IsHandleValid(plugin_handle_))
+ SharedMemory::CloseHandle(plugin_handle_);
+ } else {
+ // Delete SharedMemory, if we have one.
+ shmem_.reset();
+ }
+}
+
+void* PluginArrayBufferVar::Map() {
+ if (shmem_.get())
+ return shmem_->memory();
+ if (SharedMemory::IsHandleValid(plugin_handle_)) {
+ shmem_.reset(new SharedMemory(plugin_handle_, false));
+ if (!shmem_->Map(size_in_bytes_)) {
+ shmem_.reset();
+ return NULL;
+ }
+ return shmem_->memory();
+ }
+ if (buffer_.empty())
+ return NULL;
+ return &(buffer_[0]);
+}
+
+void PluginArrayBufferVar::Unmap() {
+ if (shmem_.get())
+ shmem_->Unmap();
+}
+
+uint32 PluginArrayBufferVar::ByteLength() {
+ return size_in_bytes_;
+}
+
+bool PluginArrayBufferVar::CopyToNewShmem(
+ PP_Instance instance,
+ int* host_handle_id,
+ SharedMemoryHandle* plugin_out_handle) {
+ ppapi::proxy::PluginDispatcher* dispatcher =
+ ppapi::proxy::PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return false;
+
+ ppapi::proxy::SerializedHandle plugin_handle;
+ dispatcher->Send(new PpapiHostMsg_SharedMemory_CreateSharedMemory(
+ instance, ByteLength(), host_handle_id, &plugin_handle));
+ if (!plugin_handle.IsHandleValid() || !plugin_handle.is_shmem() ||
+ *host_handle_id == -1)
+ return false;
+
+ base::SharedMemoryHandle tmp_handle = plugin_handle.shmem();
+ SharedMemory s(tmp_handle, false);
+ if (!s.Map(ByteLength()))
+ return false;
+ memcpy(s.memory(), Map(), ByteLength());
+ s.Unmap();
+
+ // We don't need to keep the shared memory around on the plugin side;
+ // we've already copied all our data into it. We'll make it invalid
+ // just to be safe.
+ *plugin_out_handle = base::SharedMemory::NULLHandle();
+
+ return true;
+}
+
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/plugin_array_buffer_var.h b/chromium/ppapi/proxy/plugin_array_buffer_var.h
new file mode 100644
index 00000000000..84d9d217708
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_array_buffer_var.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PLUGIN_ARRAY_BUFFER_VAR_H_
+#define PPAPI_PROXY_PLUGIN_ARRAY_BUFFER_VAR_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/shared_memory.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_stdint.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+
+// Represents a plugin-side ArrayBufferVar. In the plugin process, it's
+// owned as a vector.
+class PluginArrayBufferVar : public ArrayBufferVar {
+ public:
+ explicit PluginArrayBufferVar(uint32 size_in_bytes);
+ PluginArrayBufferVar(uint32 size_in_bytes,
+ base::SharedMemoryHandle plugin_handle);
+ virtual ~PluginArrayBufferVar();
+
+ // ArrayBufferVar implementation.
+ virtual void* Map() OVERRIDE;
+ virtual void Unmap() OVERRIDE;
+ virtual uint32 ByteLength() OVERRIDE;
+ virtual bool CopyToNewShmem(
+ PP_Instance instance,
+ int* host_handle,
+ base::SharedMemoryHandle* plugin_handle) OVERRIDE;
+
+ private:
+ // Non-shared memory
+ std::vector<uint8> buffer_;
+
+ // Shared memory
+ base::SharedMemoryHandle plugin_handle_;
+ scoped_ptr<base::SharedMemory> shmem_;
+ uint32 size_in_bytes_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginArrayBufferVar);
+};
+
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PLUGIN_ARRAY_BUFFER_VAR_H_
diff --git a/chromium/ppapi/proxy/plugin_dispatcher.cc b/chromium/ppapi/proxy/plugin_dispatcher.cc
new file mode 100644
index 00000000000..d6d0d909765
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_dispatcher.cc
@@ -0,0 +1,369 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/plugin_dispatcher.h"
+
+#include <map>
+
+#include "base/compiler_specific.h"
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_sync_channel.h"
+#include "ipc/ipc_sync_message_filter.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppp_instance.h"
+#include "ppapi/proxy/flash_clipboard_resource.h"
+#include "ppapi/proxy/flash_file_resource.h"
+#include "ppapi/proxy/flash_resource.h"
+#include "ppapi/proxy/gamepad_resource.h"
+#include "ppapi/proxy/interface_list.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/plugin_globals.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_instance_proxy.h"
+#include "ppapi/proxy/ppp_class_proxy.h"
+#include "ppapi/proxy/resource_creation_proxy.h"
+#include "ppapi/proxy/resource_message_params.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/resource.h"
+
+#if defined(OS_POSIX) && !defined(OS_NACL)
+#include "base/posix/eintr_wrapper.h"
+#include "ipc/ipc_channel_posix.h"
+#endif
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+typedef std::map<PP_Instance, PluginDispatcher*> InstanceToDispatcherMap;
+InstanceToDispatcherMap* g_instance_to_dispatcher = NULL;
+
+typedef std::set<PluginDispatcher*> DispatcherSet;
+DispatcherSet* g_live_dispatchers = NULL;
+
+} // namespace
+
+InstanceData::InstanceData()
+ : is_request_surrounding_text_pending(false),
+ should_do_request_surrounding_text(false) {
+}
+
+InstanceData::~InstanceData() {
+ // Run any pending mouse lock callback to prevent leaks.
+ if (mouse_lock_callback.get())
+ mouse_lock_callback->Abort();
+}
+
+PluginDispatcher::PluginDispatcher(PP_GetInterface_Func get_interface,
+ const PpapiPermissions& permissions,
+ bool incognito)
+ : Dispatcher(get_interface, permissions),
+ plugin_delegate_(NULL),
+ received_preferences_(false),
+ plugin_dispatcher_id_(0),
+ incognito_(incognito) {
+ SetSerializationRules(new PluginVarSerializationRules(AsWeakPtr()));
+
+ if (!g_live_dispatchers)
+ g_live_dispatchers = new DispatcherSet;
+ g_live_dispatchers->insert(this);
+}
+
+PluginDispatcher::~PluginDispatcher() {
+ PluginGlobals::Get()->plugin_var_tracker()->DidDeleteDispatcher(this);
+
+ if (plugin_delegate_)
+ plugin_delegate_->Unregister(plugin_dispatcher_id_);
+
+ g_live_dispatchers->erase(this);
+ if (g_live_dispatchers->empty()) {
+ delete g_live_dispatchers;
+ g_live_dispatchers = NULL;
+ }
+}
+
+// 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
+PluginDispatcher* PluginDispatcher::GetForResource(const Resource* resource) {
+ return GetForInstance(resource->pp_instance());
+}
+
+// static
+const void* PluginDispatcher::GetBrowserInterface(const char* interface_name) {
+ if (!interface_name) {
+ DLOG(WARNING) << "|interface_name| is null. Did you forget to add "
+ "the |interface_name()| template function to the interface's C++ "
+ "wrapper?";
+ return NULL;
+ }
+
+ return InterfaceList::GetInstance()->GetInterfaceForPPB(interface_name);
+}
+
+// static
+void PluginDispatcher::LogWithSource(PP_Instance instance,
+ PP_LogLevel level,
+ const std::string& source,
+ const std::string& value) {
+ if (!g_live_dispatchers || !g_instance_to_dispatcher)
+ return;
+
+ if (instance) {
+ InstanceToDispatcherMap::iterator found =
+ g_instance_to_dispatcher->find(instance);
+ if (found != g_instance_to_dispatcher->end()) {
+ // Send just to this specific dispatcher.
+ found->second->Send(new PpapiHostMsg_LogWithSource(
+ instance, static_cast<int>(level), source, value));
+ return;
+ }
+ }
+
+ // Instance 0 or invalid, send to all dispatchers.
+ for (DispatcherSet::iterator i = g_live_dispatchers->begin();
+ i != g_live_dispatchers->end(); ++i) {
+ (*i)->Send(new PpapiHostMsg_LogWithSource(
+ instance, static_cast<int>(level), source, value));
+ }
+}
+
+const void* PluginDispatcher::GetPluginInterface(
+ const std::string& interface_name) {
+ InterfaceMap::iterator found = plugin_interfaces_.find(interface_name);
+ if (found == plugin_interfaces_.end()) {
+ const void* ret = local_get_interface()(interface_name.c_str());
+ plugin_interfaces_.insert(std::make_pair(interface_name, ret));
+ return ret;
+ }
+ return found->second;
+}
+
+bool PluginDispatcher::InitPluginWithChannel(
+ PluginDelegate* delegate,
+ base::ProcessId peer_pid,
+ const IPC::ChannelHandle& channel_handle,
+ bool is_client) {
+ if (!Dispatcher::InitWithChannel(delegate, peer_pid, channel_handle,
+ is_client))
+ return false;
+ plugin_delegate_ = delegate;
+ plugin_dispatcher_id_ = plugin_delegate_->Register(this);
+
+ sync_filter_ = new IPC::SyncMessageFilter(delegate->GetShutdownEvent());
+ channel()->AddFilter(sync_filter_.get());
+
+ // 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::SendMessage(IPC::Message* msg) {
+ // Currently we need to choose between two different mechanisms for sending.
+ // On the main thread we use the regular dispatch Send() method, on another
+ // thread we use SyncMessageFilter.
+ if (PpapiGlobals::Get()->GetMainThreadMessageLoop()->BelongsToCurrentThread())
+ return Dispatcher::Send(msg);
+ return sync_filter_->Send(msg);
+}
+
+bool PluginDispatcher::Send(IPC::Message* msg) {
+ 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 sent 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.
+ //
+ // We don't want reply messages to unblock however, as they will potentially
+ // end up on the wrong queue - see crbug.com/122443
+ if (!msg->is_reply())
+ msg->set_unblock(true);
+ if (msg->is_sync()) {
+ // Synchronous messages might be re-entrant, so we need to drop the lock.
+ ProxyAutoUnlock unlock;
+ return SendMessage(msg);
+ }
+ return SendMessage(msg);
+}
+
+bool PluginDispatcher::OnMessageReceived(const IPC::Message& msg) {
+ // We need to grab the proxy lock to ensure that we don't collide with the
+ // plugin making pepper calls on a different thread.
+ ProxyAutoLock lock;
+ TRACE_EVENT2("ppapi proxy", "PluginDispatcher::OnMessageReceived",
+ "Class", IPC_MESSAGE_ID_CLASS(msg.type()),
+ "Line", IPC_MESSAGE_ID_LINE(msg.type()));
+
+ 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(PpapiPluginMsg_ResourceReply, OnMsgResourceReply)
+ IPC_MESSAGE_HANDLER(PpapiMsg_SupportsInterface, OnMsgSupportsInterface)
+ IPC_MESSAGE_HANDLER(PpapiMsg_SetPreferences, OnMsgSetPreferences)
+ IPC_MESSAGE_UNHANDLED(handled = false);
+ IPC_END_MESSAGE_MAP()
+ if (handled)
+ return true;
+ }
+ return Dispatcher::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;
+}
+
+thunk::PPB_Instance_API* PluginDispatcher::GetInstanceAPI() {
+ return static_cast<PPB_Instance_Proxy*>(
+ GetInterfaceProxy(API_ID_PPB_INSTANCE));
+}
+
+thunk::ResourceCreationAPI* PluginDispatcher::GetResourceCreationAPI() {
+ return static_cast<ResourceCreationProxy*>(
+ GetInterfaceProxy(API_ID_RESOURCE_CREATION));
+}
+
+// static
+void PluginDispatcher::DispatchResourceReply(
+ const ppapi::proxy::ResourceMessageReplyParams& reply_params,
+ const IPC::Message& nested_msg) {
+ // We need to grab the proxy lock to ensure that we don't collide with the
+ // plugin making pepper calls on a different thread.
+ ProxyAutoLock lock;
+ LockedDispatchResourceReply(reply_params, nested_msg);
+}
+
+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(API_ID_PPP_INSTANCE, i->first);
+ OnMessageReceived(msg);
+ }
+ }
+}
+
+void PluginDispatcher::OnMsgResourceReply(
+ const ppapi::proxy::ResourceMessageReplyParams& reply_params,
+ const IPC::Message& nested_msg) {
+ LockedDispatchResourceReply(reply_params, nested_msg);
+}
+
+void PluginDispatcher::OnMsgSupportsInterface(
+ const std::string& interface_name,
+ bool* result) {
+ *result = !!GetPluginInterface(interface_name);
+
+ // Do fallback for PPP_Instance. This is a hack here and if we have more
+ // cases like this it should be generalized. The PPP_Instance proxy always
+ // proxies the 1.1 interface, and then does fallback to 1.0 inside the
+ // plugin process (see PPP_Instance_Proxy). So here we return true for
+ // supporting the 1.1 interface if either 1.1 or 1.0 is supported.
+ if (!*result && interface_name == PPP_INSTANCE_INTERFACE)
+ *result = !!GetPluginInterface(PPP_INSTANCE_INTERFACE_1_0);
+}
+
+void PluginDispatcher::OnMsgSetPreferences(const 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;
+ }
+}
+
+// static
+void PluginDispatcher::LockedDispatchResourceReply(
+ const ppapi::proxy::ResourceMessageReplyParams& reply_params,
+ const IPC::Message& nested_msg) {
+ Resource* resource = PpapiGlobals::Get()->GetResourceTracker()->GetResource(
+ reply_params.pp_resource());
+ if (!resource) {
+ DLOG_IF(INFO, reply_params.sequence() != 0)
+ << "Pepper resource reply message received but the resource doesn't "
+ "exist (probably has been destroyed).";
+ return;
+ }
+ resource->OnReplyReceived(reply_params, nested_msg);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/plugin_dispatcher.h b/chromium/ppapi/proxy/plugin_dispatcher.h
new file mode 100644
index 00000000000..3a9e7330865
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_dispatcher.h
@@ -0,0 +1,226 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PLUGIN_DISPATCHER_H_
+#define PPAPI_PROXY_PLUGIN_DISPATCHER_H_
+
+#include <set>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/containers/hash_tables.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/process/process.h"
+#include "build/build_config.h"
+#include "ipc/ipc_sync_channel.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_rect.h"
+#include "ppapi/c/ppb_console.h"
+#include "ppapi/proxy/dispatcher.h"
+#include "ppapi/shared_impl/ppapi_preferences.h"
+#include "ppapi/shared_impl/ppb_view_shared.h"
+#include "ppapi/shared_impl/singleton_resource_id.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+
+namespace IPC {
+class SyncMessageFilter;
+}
+
+namespace ppapi {
+
+struct Preferences;
+class Resource;
+
+namespace thunk {
+class PPB_Instance_API;
+class ResourceCreationAPI;
+}
+
+namespace proxy {
+
+class ResourceMessageReplyParams;
+
+// Used to keep track of per-instance data.
+struct InstanceData {
+ InstanceData();
+ ~InstanceData();
+
+ ViewData view;
+
+ // When non-NULL, indicates the callback to execute when mouse lock is lost.
+ scoped_refptr<TrackedCallback> mouse_lock_callback;
+
+ // A map of singleton resources which are lazily created.
+ typedef std::map<SingletonResourceID, scoped_refptr<Resource> >
+ SingletonResourceMap;
+ SingletonResourceMap singleton_resources;
+
+ // Calls to |RequestSurroundingText()| are done by posted tasks. Track whether
+ // a) a task is pending, to avoid redundant calls, and b) whether we should
+ // actually call |RequestSurroundingText()|, to avoid stale calls (i.e.,
+ // calling when we shouldn't).
+ bool is_request_surrounding_text_pending;
+ bool should_do_request_surrounding_text;
+};
+
+class PPAPI_PROXY_EXPORT PluginDispatcher
+ : public Dispatcher,
+ public base::SupportsWeakPtr<PluginDispatcher> {
+ public:
+ class PPAPI_PROXY_EXPORT 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;
+
+ // 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.
+ //
+ // Note about permissions: On the plugin side, the dispatcher and the plugin
+ // run in the same address space (including in nacl). This means that the
+ // permissions here are subject to malicious modification and bypass, and
+ // an exploited or malicious plugin could send any IPC messages and just
+ // bypass the permissions. All permissions must be checked "for realz" in the
+ // host process when receiving messages. We check them on the plugin side
+ // primarily to keep honest plugins honest, especially with respect to
+ // dev interfaces that they "shouldn't" be using.
+ //
+ // You must call InitPluginWithChannel after the constructor.
+ PluginDispatcher(PP_GetInterface_Func get_interface,
+ const PpapiPermissions& permissions,
+ bool incognito);
+ 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);
+
+ // Same as GetForInstance but retrieves the instance from the given resource
+ // object as a convenience. Returns NULL on failure.
+ static PluginDispatcher* GetForResource(const Resource* resource);
+
+ // Implements the GetInterface function for the plugin to call to retrieve
+ // a browser interface.
+ static const void* GetBrowserInterface(const char* interface_name);
+
+ // Logs the given log message to the given instance, or, if the instance is
+ // invalid, to all instances associated with all dispatchers. Used for
+ // global log messages.
+ static void LogWithSource(PP_Instance instance,
+ PP_LogLevel level,
+ const std::string& source,
+ const std::string& value);
+
+ const void* GetPluginInterface(const std::string& interface_name);
+
+ // 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,
+ base::ProcessId peer_pid,
+ const IPC::ChannelHandle& channel_handle,
+ bool is_client);
+
+ // Dispatcher overrides.
+ virtual bool IsPlugin() const;
+ virtual bool Send(IPC::Message* msg);
+
+ // IPC::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);
+
+ // Returns the corresponding API. These are APIs not associated with a
+ // resource. Guaranteed non-NULL.
+ thunk::PPB_Instance_API* GetInstanceAPI();
+ thunk::ResourceCreationAPI* GetResourceCreationAPI();
+
+ // Returns the Preferences.
+ const Preferences& preferences() const { return preferences_; }
+
+ uint32 plugin_dispatcher_id() const { return plugin_dispatcher_id_; }
+ bool incognito() const { return incognito_; }
+
+ // Dispatches the given resource message to the appropriate resource in the
+ // plugin process. This should be wired to the various channels that messages
+ // come in from various other processes.
+ static void DispatchResourceReply(
+ const ppapi::proxy::ResourceMessageReplyParams& reply_params,
+ const IPC::Message& nested_msg);
+
+ 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 OnMsgResourceReply(
+ const ppapi::proxy::ResourceMessageReplyParams& reply_params,
+ const IPC::Message& nested_msg);
+ void OnMsgSupportsInterface(const std::string& interface_name, bool* result);
+ void OnMsgSetPreferences(const Preferences& prefs);
+
+ // Internal backed for DispatchResourceReply.
+ static void LockedDispatchResourceReply(
+ const ppapi::proxy::ResourceMessageReplyParams& reply_params,
+ const IPC::Message& nested_msg);
+
+ virtual bool SendMessage(IPC::Message* msg);
+
+ PluginDelegate* plugin_delegate_;
+
+ // Contains all the plugin interfaces we've queried. The mapped value will
+ // be the pointer to the interface pointer supplied by the plugin if it's
+ // supported, or NULL if it's not supported. This allows us to cache failures
+ // and not req-query if a plugin doesn't support the interface.
+ typedef base::hash_map<std::string, const void*> InterfaceMap;
+ InterfaceMap plugin_interfaces_;
+
+ 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_;
+ Preferences preferences_;
+
+ uint32 plugin_dispatcher_id_;
+
+ // Set to true when the instances associated with this dispatcher are
+ // incognito mode.
+ bool incognito_;
+
+ // A filter for sending messages from threads other than the main thread.
+ scoped_refptr<IPC::SyncMessageFilter> sync_filter_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginDispatcher);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PLUGIN_DISPATCHER_H_
diff --git a/chromium/ppapi/proxy/plugin_dispatcher_unittest.cc b/chromium/ppapi/proxy/plugin_dispatcher_unittest.cc
new file mode 100644
index 00000000000..821ecad3799
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_dispatcher_unittest.cc
@@ -0,0 +1,87 @@
+// 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 ppapi {
+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(ApiID id) {
+ return !!plugin_dispatcher()->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 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(API_ID_PPB_AUDIO));
+ PpapiMsg_PPBAudio_NotifyAudioStreamCreated audio_msg(
+ API_ID_PPB_AUDIO, HostResource(), 0,
+ ppapi::proxy::SerializedHandle(
+ ppapi::proxy::SerializedHandle::SOCKET),
+ ppapi::proxy::SerializedHandle(
+ ppapi::proxy::SerializedHandle::SHARED_MEMORY));
+ plugin_dispatcher()->OnMessageReceived(audio_msg);
+ EXPECT_TRUE(HasTargetProxy(API_ID_PPB_AUDIO));
+}
+
+} // namespace proxy
+} // namespace ppapi
+
diff --git a/chromium/ppapi/proxy/plugin_globals.cc b/chromium/ppapi/proxy/plugin_globals.cc
new file mode 100644
index 00000000000..07ac6885601
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_globals.cc
@@ -0,0 +1,202 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/plugin_globals.h"
+
+#include "base/task_runner.h"
+#include "base/threading/thread.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_sender.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_proxy_delegate.h"
+#include "ppapi/proxy/ppb_message_loop_proxy.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/thunk/enter.h"
+
+namespace ppapi {
+namespace proxy {
+
+// It performs necessary locking/unlocking of the proxy lock, and forwards all
+// messages to the underlying sender.
+class PluginGlobals::BrowserSender : public IPC::Sender {
+ public:
+ // |underlying_sender| must outlive this object.
+ explicit BrowserSender(IPC::Sender* underlying_sender)
+ : underlying_sender_(underlying_sender) {
+ }
+
+ virtual ~BrowserSender() {}
+
+ // IPC::Sender implementation.
+ virtual bool Send(IPC::Message* msg) OVERRIDE {
+ if (msg->is_sync()) {
+ // Synchronous messages might be re-entrant, so we need to drop the lock.
+ ProxyAutoUnlock unlock;
+ return underlying_sender_->Send(msg);
+ }
+
+ return underlying_sender_->Send(msg);
+ }
+
+ private:
+ // Non-owning pointer.
+ IPC::Sender* underlying_sender_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserSender);
+};
+
+PluginGlobals* PluginGlobals::plugin_globals_ = NULL;
+
+PluginGlobals::PluginGlobals()
+ : ppapi::PpapiGlobals(),
+ plugin_proxy_delegate_(NULL),
+ callback_tracker_(new CallbackTracker) {
+ DCHECK(!plugin_globals_);
+ plugin_globals_ = this;
+
+ // ResourceTracker asserts that we have the lock when we add new resources,
+ // so we lock when creating the MessageLoopResource even though there is no
+ // chance of race conditions.
+ ProxyAutoLock lock;
+ loop_for_main_thread_ =
+ new MessageLoopResource(MessageLoopResource::ForMainThread());
+}
+
+PluginGlobals::PluginGlobals(PerThreadForTest per_thread_for_test)
+ : ppapi::PpapiGlobals(per_thread_for_test),
+ plugin_proxy_delegate_(NULL),
+ callback_tracker_(new CallbackTracker) {
+ DCHECK(!plugin_globals_);
+}
+
+PluginGlobals::~PluginGlobals() {
+ DCHECK(plugin_globals_ == this || !plugin_globals_);
+ {
+ ProxyAutoLock lock;
+ // Release the main-thread message loop. We should have the last reference
+ // count, so this will delete the MessageLoop resource. We do this before
+ // we clear plugin_globals_, because the Resource destructor tries to access
+ // this PluginGlobals.
+ DCHECK(!loop_for_main_thread_.get() || loop_for_main_thread_->HasOneRef());
+ loop_for_main_thread_ = NULL;
+ }
+ plugin_globals_ = NULL;
+}
+
+ResourceTracker* PluginGlobals::GetResourceTracker() {
+ return &plugin_resource_tracker_;
+}
+
+VarTracker* PluginGlobals::GetVarTracker() {
+ return &plugin_var_tracker_;
+}
+
+CallbackTracker* PluginGlobals::GetCallbackTrackerForInstance(
+ PP_Instance instance) {
+ // In the plugin process, the callback tracker is always the same, regardless
+ // of the instance.
+ return callback_tracker_.get();
+}
+
+thunk::PPB_Instance_API* PluginGlobals::GetInstanceAPI(PP_Instance instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (dispatcher)
+ return dispatcher->GetInstanceAPI();
+ return NULL;
+}
+
+thunk::ResourceCreationAPI* PluginGlobals::GetResourceCreationAPI(
+ PP_Instance instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (dispatcher)
+ return dispatcher->GetResourceCreationAPI();
+ return NULL;
+}
+
+PP_Module PluginGlobals::GetModuleForInstance(PP_Instance instance) {
+ // Currently proxied plugins don't use the PP_Module for anything useful.
+ return 0;
+}
+
+std::string PluginGlobals::GetCmdLine() {
+ return command_line_;
+}
+
+void PluginGlobals::PreCacheFontForFlash(const void* logfontw) {
+ ProxyAutoUnlock unlock;
+ plugin_proxy_delegate_->PreCacheFont(logfontw);
+}
+
+base::Lock* PluginGlobals::GetProxyLock() {
+ return &proxy_lock_;
+}
+
+void PluginGlobals::LogWithSource(PP_Instance instance,
+ PP_LogLevel level,
+ const std::string& source,
+ const std::string& value) {
+ const std::string& fixed_up_source = source.empty() ? plugin_name_ : source;
+ PluginDispatcher::LogWithSource(instance, level, fixed_up_source, value);
+}
+
+void PluginGlobals::BroadcastLogWithSource(PP_Module /* module */,
+ PP_LogLevel level,
+ const std::string& source,
+ const std::string& value) {
+ // Since we have only one module in a plugin process, broadcast is always
+ // the same as "send to everybody" which is what the dispatcher implements
+ // for the "instance = 0" case.
+ LogWithSource(0, level, source, value);
+}
+
+MessageLoopShared* PluginGlobals::GetCurrentMessageLoop() {
+ return MessageLoopResource::GetCurrent();
+}
+
+base::TaskRunner* PluginGlobals::GetFileTaskRunner(PP_Instance instance) {
+ if (!file_thread_.get()) {
+ file_thread_.reset(new base::Thread("Plugin::File"));
+ base::Thread::Options options;
+ options.message_loop_type = base::MessageLoop::TYPE_IO;
+ file_thread_->StartWithOptions(options);
+ }
+ return file_thread_->message_loop_proxy();
+}
+
+IPC::Sender* PluginGlobals::GetBrowserSender() {
+ if (!browser_sender_.get()) {
+ browser_sender_.reset(
+ new BrowserSender(plugin_proxy_delegate_->GetBrowserSender()));
+ }
+
+ return browser_sender_.get();
+}
+
+std::string PluginGlobals::GetUILanguage() {
+ return plugin_proxy_delegate_->GetUILanguage();
+}
+
+void PluginGlobals::SetActiveURL(const std::string& url) {
+ plugin_proxy_delegate_->SetActiveURL(url);
+}
+
+PP_Resource PluginGlobals::CreateBrowserFont(
+ Connection connection,
+ PP_Instance instance,
+ const PP_BrowserFont_Trusted_Description& desc,
+ const ppapi::Preferences& prefs) {
+ return plugin_proxy_delegate_->CreateBrowserFont(
+ connection, instance, desc, prefs);
+}
+
+MessageLoopResource* PluginGlobals::loop_for_main_thread() {
+ return loop_for_main_thread_.get();
+}
+
+bool PluginGlobals::IsPluginGlobals() const {
+ return true;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/plugin_globals.h b/chromium/ppapi/proxy/plugin_globals.h
new file mode 100644
index 00000000000..044cac7e25c
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_globals.h
@@ -0,0 +1,173 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PLUGIN_GLOBALS_H_
+#define PPAPI_PROXY_PLUGIN_GLOBALS_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/thread_local_storage.h"
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/callback_tracker.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+
+namespace base {
+class Thread;
+}
+namespace IPC {
+class Sender;
+}
+
+struct PP_BrowserFont_Trusted_Description;
+
+namespace ppapi {
+
+struct Preferences;
+
+namespace proxy {
+
+class MessageLoopResource;
+class PluginProxyDelegate;
+
+class PPAPI_PROXY_EXPORT PluginGlobals : public PpapiGlobals {
+ public:
+ PluginGlobals();
+ explicit PluginGlobals(PpapiGlobals::PerThreadForTest);
+ virtual ~PluginGlobals();
+
+ // Getter for the global singleton. Generally, you should use
+ // PpapiGlobals::Get() when possible. Use this only when you need some
+ // plugin-specific functionality.
+ inline static PluginGlobals* Get() {
+ // Explicitly crash if this is the wrong process type, we want to get
+ // crash reports.
+ CHECK(PpapiGlobals::Get()->IsPluginGlobals());
+ return static_cast<PluginGlobals*>(PpapiGlobals::Get());
+ }
+
+ // PpapiGlobals implementation.
+ virtual ResourceTracker* GetResourceTracker() OVERRIDE;
+ virtual VarTracker* GetVarTracker() OVERRIDE;
+ virtual CallbackTracker* GetCallbackTrackerForInstance(
+ PP_Instance instance) OVERRIDE;
+ virtual thunk::PPB_Instance_API* GetInstanceAPI(
+ PP_Instance instance) OVERRIDE;
+ virtual thunk::ResourceCreationAPI* GetResourceCreationAPI(
+ PP_Instance instance) OVERRIDE;
+ virtual PP_Module GetModuleForInstance(PP_Instance instance) OVERRIDE;
+ virtual std::string GetCmdLine() OVERRIDE;
+ virtual void PreCacheFontForFlash(const void* logfontw) OVERRIDE;
+ virtual base::Lock* GetProxyLock() OVERRIDE;
+ virtual void LogWithSource(PP_Instance instance,
+ PP_LogLevel level,
+ const std::string& source,
+ const std::string& value) OVERRIDE;
+ virtual void BroadcastLogWithSource(PP_Module module,
+ PP_LogLevel level,
+ const std::string& source,
+ const std::string& value) OVERRIDE;
+ virtual MessageLoopShared* GetCurrentMessageLoop() OVERRIDE;
+ base::TaskRunner* GetFileTaskRunner(PP_Instance instance) OVERRIDE;
+
+ // Returns the channel for sending to the browser.
+ IPC::Sender* GetBrowserSender();
+
+ // Returns the language code of the current UI language.
+ std::string GetUILanguage();
+
+ // Sets the active url which is reported by breakpad.
+ void SetActiveURL(const std::string& url);
+
+ PP_Resource CreateBrowserFont(
+ Connection connection,
+ PP_Instance instance,
+ const PP_BrowserFont_Trusted_Description& desc,
+ const Preferences& prefs);
+
+ // Getters for the plugin-specific versions.
+ PluginResourceTracker* plugin_resource_tracker() {
+ return &plugin_resource_tracker_;
+ }
+ PluginVarTracker* plugin_var_tracker() {
+ return &plugin_var_tracker_;
+ }
+
+ // The embedder should call set_proxy_delegate during startup.
+ void set_plugin_proxy_delegate(PluginProxyDelegate* d) {
+ plugin_proxy_delegate_ = d;
+ }
+
+ // Returns the TLS slot that holds the message loop TLS.
+ //
+ // If we end up needing more TLS storage for more stuff, we should probably
+ // have a struct in here for the different items.
+ base::ThreadLocalStorage::Slot* msg_loop_slot() {
+ return msg_loop_slot_.get();
+ }
+
+ // Sets the message loop slot, takes ownership of the given heap-alloated
+ // pointer.
+ void set_msg_loop_slot(base::ThreadLocalStorage::Slot* slot) {
+ msg_loop_slot_.reset(slot);
+ }
+
+ // Return the special Resource that represents the MessageLoop for the main
+ // thread. This Resource is not associated with any instance, and lives as
+ // long as the plugin.
+ MessageLoopResource* loop_for_main_thread();
+
+ // The embedder should call this function when the name of the plugin module
+ // is known. This will be used for error logging.
+ void set_plugin_name(const std::string& name) { plugin_name_ = name; }
+
+ // The embedder should call this function when the command line is known.
+ void set_command_line(const std::string& c) { command_line_ = c; }
+
+ private:
+ class BrowserSender;
+
+ // PpapiGlobals overrides.
+ virtual bool IsPluginGlobals() const OVERRIDE;
+
+ static PluginGlobals* plugin_globals_;
+
+ PluginProxyDelegate* plugin_proxy_delegate_;
+ PluginResourceTracker plugin_resource_tracker_;
+ PluginVarTracker plugin_var_tracker_;
+ scoped_refptr<CallbackTracker> callback_tracker_;
+
+ base::Lock proxy_lock_;
+
+ scoped_ptr<base::ThreadLocalStorage::Slot> msg_loop_slot_;
+ // Note that loop_for_main_thread's constructor sets msg_loop_slot_, so it
+ // must be initialized after msg_loop_slot_ (hence the order here).
+ scoped_refptr<MessageLoopResource> loop_for_main_thread_;
+
+ // Name of the plugin used for error logging. This will be empty until
+ // set_plugin_name is called.
+ std::string plugin_name_;
+
+ // Command line for the plugin. This will be empty until set_command_line is
+ // called.
+ std::string command_line_;
+
+ scoped_ptr<BrowserSender> browser_sender_;
+
+ // Thread for performing potentially blocking file operations. It's created
+ // lazily, since it might not be needed.
+ scoped_ptr<base::Thread> file_thread_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginGlobals);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PLUGIN_GLOBALS_H_
diff --git a/chromium/ppapi/proxy/plugin_main_nacl.cc b/chromium/ppapi/proxy/plugin_main_nacl.cc
new file mode 100644
index 00000000000..5978233a537
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_main_nacl.cc
@@ -0,0 +1,296 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <map>
+#include <set>
+
+#include "build/build_config.h"
+// Need to include this before most other files because it defines
+// IPC_MESSAGE_LOG_ENABLED. We need to use it to define
+// IPC_MESSAGE_MACROS_LOG_ENABLED so ppapi_messages.h will generate the
+// ViewMsgLog et al. functions.
+
+#include "base/command_line.h"
+#include "base/message_loop/message_loop.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "components/tracing/child_trace_message_filter.h"
+#include "ipc/ipc_channel_handle.h"
+#include "ipc/ipc_logging.h"
+#include "ipc/ipc_message.h"
+#include "native_client/src/shared/srpc/nacl_srpc.h"
+#include "native_client/src/untrusted/irt/irt_ppapi.h"
+#include "ppapi/c/ppp.h"
+#include "ppapi/c/ppp_instance.h"
+#include "ppapi/native_client/src/shared/ppapi_proxy/ppruntime.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/plugin_proxy_delegate.h"
+#include "ppapi/shared_impl/ppb_audio_shared.h"
+
+#if defined(IPC_MESSAGE_LOG_ENABLED)
+#include "base/containers/hash_tables.h"
+
+LogFunctionMap g_log_function_mapping;
+
+#define IPC_MESSAGE_MACROS_LOG_ENABLED
+#define IPC_LOG_TABLE_ADD_ENTRY(msg_id, logger) \
+ g_log_function_mapping[msg_id] = logger
+
+#endif
+#include "ppapi/proxy/ppapi_messages.h"
+
+// This must match up with NACL_CHROME_INITIAL_IPC_DESC,
+// defined in sel_main_chrome.h
+#define NACL_IPC_FD 6
+
+using ppapi::proxy::PluginDispatcher;
+using ppapi::proxy::PluginGlobals;
+using ppapi::proxy::PluginProxyDelegate;
+using ppapi::proxy::ProxyChannel;
+using ppapi::proxy::SerializedHandle;
+
+namespace {
+
+// This class manages communication between the plugin and the browser, and
+// manages the PluginDispatcher instances for communication between the plugin
+// and the renderer.
+class PpapiDispatcher : public ProxyChannel,
+ public PluginDispatcher::PluginDelegate,
+ public PluginProxyDelegate {
+ public:
+ explicit PpapiDispatcher(scoped_refptr<base::MessageLoopProxy> io_loop);
+
+ // PluginDispatcher::PluginDelegate implementation.
+ virtual base::MessageLoopProxy* GetIPCMessageLoop() OVERRIDE;
+ virtual base::WaitableEvent* GetShutdownEvent() OVERRIDE;
+ virtual IPC::PlatformFileForTransit ShareHandleWithRemote(
+ base::PlatformFile handle,
+ base::ProcessId peer_pid,
+ bool should_close_source) OVERRIDE;
+ virtual std::set<PP_Instance>* GetGloballySeenInstanceIDSet() OVERRIDE;
+ virtual uint32 Register(PluginDispatcher* plugin_dispatcher) OVERRIDE;
+ virtual void Unregister(uint32 plugin_dispatcher_id) OVERRIDE;
+
+ // PluginProxyDelegate implementation.
+ virtual IPC::Sender* GetBrowserSender() OVERRIDE;
+ virtual std::string GetUILanguage() OVERRIDE;
+ virtual void PreCacheFont(const void* logfontw) OVERRIDE;
+ virtual void SetActiveURL(const std::string& url) OVERRIDE;
+ virtual PP_Resource CreateBrowserFont(
+ ppapi::proxy::Connection connection,
+ PP_Instance instance,
+ const PP_BrowserFont_Trusted_Description& desc,
+ const ppapi::Preferences& prefs) OVERRIDE;
+
+ // IPC::Listener implementation.
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ private:
+ void OnMsgCreateNaClChannel(int renderer_id,
+ const ppapi::PpapiNaClChannelArgs& args,
+ SerializedHandle handle);
+ void OnMsgResourceReply(
+ const ppapi::proxy::ResourceMessageReplyParams& reply_params,
+ const IPC::Message& nested_msg);
+ void OnPluginDispatcherMessageReceived(const IPC::Message& msg);
+
+ std::set<PP_Instance> instances_;
+ std::map<uint32, PluginDispatcher*> plugin_dispatchers_;
+ uint32 next_plugin_dispatcher_id_;
+ scoped_refptr<base::MessageLoopProxy> message_loop_;
+ base::WaitableEvent shutdown_event_;
+};
+
+PpapiDispatcher::PpapiDispatcher(scoped_refptr<base::MessageLoopProxy> io_loop)
+ : next_plugin_dispatcher_id_(0),
+ message_loop_(io_loop),
+ shutdown_event_(true, false) {
+ IPC::ChannelHandle channel_handle(
+ "NaCl IPC", base::FileDescriptor(NACL_IPC_FD, false));
+ // We don't have/need a PID since handle sharing happens outside of the
+ // NaCl sandbox.
+ InitWithChannel(this, base::kNullProcessId, channel_handle,
+ false); // Channel is server.
+ channel()->AddFilter(
+ new tracing::ChildTraceMessageFilter(message_loop_.get()));
+}
+
+base::MessageLoopProxy* PpapiDispatcher::GetIPCMessageLoop() {
+ return message_loop_.get();
+}
+
+base::WaitableEvent* PpapiDispatcher::GetShutdownEvent() {
+ return &shutdown_event_;
+}
+
+IPC::PlatformFileForTransit PpapiDispatcher::ShareHandleWithRemote(
+ base::PlatformFile handle,
+ base::ProcessId peer_pid,
+ bool should_close_source) {
+ return IPC::InvalidPlatformFileForTransit();
+}
+
+std::set<PP_Instance>* PpapiDispatcher::GetGloballySeenInstanceIDSet() {
+ return &instances_;
+}
+
+uint32 PpapiDispatcher::Register(PluginDispatcher* plugin_dispatcher) {
+ if (!plugin_dispatcher ||
+ plugin_dispatchers_.size() >= std::numeric_limits<uint32>::max()) {
+ return 0;
+ }
+
+ uint32 id = 0;
+ do {
+ // Although it is unlikely, make sure that we won't cause any trouble
+ // when the counter overflows.
+ id = next_plugin_dispatcher_id_++;
+ } while (id == 0 ||
+ plugin_dispatchers_.find(id) != plugin_dispatchers_.end());
+ plugin_dispatchers_[id] = plugin_dispatcher;
+ return id;
+}
+
+void PpapiDispatcher::Unregister(uint32 plugin_dispatcher_id) {
+ plugin_dispatchers_.erase(plugin_dispatcher_id);
+}
+
+IPC::Sender* PpapiDispatcher::GetBrowserSender() {
+ return this;
+}
+
+std::string PpapiDispatcher::GetUILanguage() {
+ NOTIMPLEMENTED();
+ return std::string();
+}
+
+void PpapiDispatcher::PreCacheFont(const void* logfontw) {
+ NOTIMPLEMENTED();
+}
+
+void PpapiDispatcher::SetActiveURL(const std::string& url) {
+ NOTIMPLEMENTED();
+}
+
+PP_Resource PpapiDispatcher::CreateBrowserFont(
+ ppapi::proxy::Connection connection,
+ PP_Instance instance,
+ const PP_BrowserFont_Trusted_Description& desc,
+ const ppapi::Preferences& prefs) {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+bool PpapiDispatcher::OnMessageReceived(const IPC::Message& msg) {
+ IPC_BEGIN_MESSAGE_MAP(PpapiDispatcher, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_CreateNaClChannel, OnMsgCreateNaClChannel)
+ IPC_MESSAGE_HANDLER(PpapiPluginMsg_ResourceReply, OnMsgResourceReply)
+ // All other messages are simply forwarded to a PluginDispatcher.
+ IPC_MESSAGE_UNHANDLED(OnPluginDispatcherMessageReceived(msg))
+ IPC_END_MESSAGE_MAP()
+ return true;
+}
+
+void PpapiDispatcher::OnMsgCreateNaClChannel(
+ int renderer_id,
+ const ppapi::PpapiNaClChannelArgs& args,
+ SerializedHandle handle) {
+ static bool command_line_and_logging_initialized = false;
+ if (!command_line_and_logging_initialized) {
+ CommandLine::Init(0, NULL);
+ for (size_t i = 0; i < args.switch_names.size(); ++i) {
+ DCHECK(i < args.switch_values.size());
+ CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ args.switch_names[i], args.switch_values[i]);
+ }
+ logging::LoggingSettings settings;
+ settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
+ logging::InitLogging(settings);
+ command_line_and_logging_initialized = true;
+ }
+ // Tell the process-global GetInterface which interfaces it can return to the
+ // plugin.
+ ppapi::proxy::InterfaceList::SetProcessGlobalPermissions(
+ args.permissions);
+
+ PluginDispatcher* dispatcher =
+ new PluginDispatcher(::PPP_GetInterface, args.permissions,
+ args.off_the_record);
+ // The channel handle's true name is not revealed here.
+ IPC::ChannelHandle channel_handle("nacl", handle.descriptor());
+ if (!dispatcher->InitPluginWithChannel(this, base::kNullProcessId,
+ channel_handle, false)) {
+ delete dispatcher;
+ return;
+ }
+ // From here, the dispatcher will manage its own lifetime according to the
+ // lifetime of the attached channel.
+}
+
+void PpapiDispatcher::OnMsgResourceReply(
+ const ppapi::proxy::ResourceMessageReplyParams& reply_params,
+ const IPC::Message& nested_msg) {
+ ppapi::proxy::PluginDispatcher::DispatchResourceReply(reply_params,
+ nested_msg);
+}
+
+void PpapiDispatcher::OnPluginDispatcherMessageReceived(
+ const IPC::Message& msg) {
+ // The first parameter should be a plugin dispatcher ID.
+ PickleIterator iter(msg);
+ uint32 id = 0;
+ if (!msg.ReadUInt32(&iter, &id)) {
+ NOTREACHED();
+ return;
+ }
+ std::map<uint32, ppapi::proxy::PluginDispatcher*>::iterator dispatcher =
+ plugin_dispatchers_.find(id);
+ if (dispatcher != plugin_dispatchers_.end())
+ dispatcher->second->OnMessageReceived(msg);
+}
+
+} // namespace
+
+void PpapiPluginRegisterThreadCreator(
+ const struct PP_ThreadFunctions* thread_functions) {
+ // Initialize all classes that need to create threads that call back into
+ // user code.
+ ppapi::PPB_Audio_Shared::SetThreadFunctions(thread_functions);
+}
+
+int PpapiPluginMain() {
+ // Though it isn't referenced here, we must instantiate an AtExitManager.
+ base::AtExitManager exit_manager;
+ base::MessageLoop loop;
+ IPC::Logging::set_log_function_map(&g_log_function_mapping);
+ ppapi::proxy::PluginGlobals plugin_globals;
+ base::Thread io_thread("Chrome_NaClIOThread");
+ base::Thread::Options options;
+ options.message_loop_type = base::MessageLoop::TYPE_IO;
+ io_thread.StartWithOptions(options);
+
+ // Start up the SRPC server on another thread. Otherwise, when it blocks
+ // on an RPC, the PPAPI proxy will hang. Do this before we initialize the
+ // module and start the PPAPI proxy so that the NaCl plugin can continue
+ // loading the app.
+ static struct NaClSrpcHandlerDesc srpc_methods[] = { { NULL, NULL } };
+ if (!NaClSrpcAcceptClientOnThread(srpc_methods)) {
+ return 1;
+ }
+
+ int32_t error = ::PPP_InitializeModule(
+ 0 /* module */,
+ &ppapi::proxy::PluginDispatcher::GetBrowserInterface);
+ // TODO(dmichael): Handle other error conditions, like failure to connect?
+ if (error)
+ return error;
+
+ PpapiDispatcher ppapi_dispatcher(io_thread.message_loop_proxy());
+ plugin_globals.set_plugin_proxy_delegate(&ppapi_dispatcher);
+
+ loop.Run();
+
+ return 0;
+}
diff --git a/chromium/ppapi/proxy/plugin_message_filter.cc b/chromium/ppapi/proxy/plugin_message_filter.cc
new file mode 100644
index 00000000000..9f178f15acc
--- /dev/null
+++ b/chromium/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 ppapi {
+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 ppapi
diff --git a/chromium/ppapi/proxy/plugin_message_filter.h b/chromium/ppapi/proxy/plugin_message_filter.h
new file mode 100644
index 00000000000..5701a96a09a
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_message_filter.h
@@ -0,0 +1,57 @@
+// 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 "base/compiler_specific.h"
+#include "ipc/ipc_channel_proxy.h"
+#include "ipc/ipc_sender.h"
+#include "ppapi/c/pp_instance.h"
+
+namespace ppapi {
+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::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) OVERRIDE;
+ virtual void OnFilterRemoved() OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ // IPC::Sender implementation.
+ virtual bool Send(IPC::Message* msg) OVERRIDE;
+
+ 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 ppapi
+
+#endif // PPAPI_PROXY_PLUGIN_MESSAGE_FILTER_H_
diff --git a/chromium/ppapi/proxy/plugin_proxy_delegate.h b/chromium/ppapi/proxy/plugin_proxy_delegate.h
new file mode 100644
index 00000000000..438ac6c871e
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_proxy_delegate.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PLUGIN_PROXY_DELEGATE_H_
+#define PPAPI_PROXY_PLUGIN_PROXY_DELEGATE_H_
+
+#include <string>
+
+namespace IPC {
+class Sender;
+}
+
+namespace ppapi {
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT PluginProxyDelegate {
+ public:
+ virtual ~PluginProxyDelegate() {}
+
+ // Returns the channel for sending to the browser.
+ // Note: The returned sender must be thread-safe. It might be used while the
+ // proxy lock is not acquired. Please see the implementation of
+ // PluginGlobals::BrowserSender.
+ virtual IPC::Sender* GetBrowserSender() = 0;
+
+ // Returns the language code of the current UI language.
+ virtual std::string GetUILanguage() = 0;
+
+ // Performs Windows-specific font caching in the browser for the given
+ // LOGFONTW. Does nothing on non-Windows platforms.
+ // Note: This method must be thread-safe.
+ virtual void PreCacheFont(const void* logfontw) = 0;
+
+ // Sets the active url which is reported by breakpad.
+ virtual void SetActiveURL(const std::string& url) = 0;
+
+ // Validates the font description, and uses it to create a
+ // BrowserFontResource_Trusted resource.
+ virtual PP_Resource CreateBrowserFont(
+ Connection connection,
+ PP_Instance instance,
+ const PP_BrowserFont_Trusted_Description& desc,
+ const Preferences& prefs) = 0;
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PLUGIN_PROXY_DELEGATE_H_
diff --git a/chromium/ppapi/proxy/plugin_resource.cc b/chromium/ppapi/proxy/plugin_resource.cc
new file mode 100644
index 00000000000..c450f3c29af
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_resource.cc
@@ -0,0 +1,160 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/plugin_resource.h"
+
+#include <limits>
+
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace ppapi {
+namespace proxy {
+
+PluginResource::PluginResource(Connection connection, PP_Instance instance)
+ : Resource(OBJECT_IS_PROXY, instance),
+ connection_(connection),
+ next_sequence_number_(1),
+ sent_create_to_browser_(false),
+ sent_create_to_renderer_(false) {
+}
+
+PluginResource::~PluginResource() {
+ if (sent_create_to_browser_) {
+ connection_.browser_sender->Send(
+ new PpapiHostMsg_ResourceDestroyed(pp_resource()));
+ }
+ if (sent_create_to_renderer_) {
+ connection_.renderer_sender->Send(
+ new PpapiHostMsg_ResourceDestroyed(pp_resource()));
+ }
+}
+
+void PluginResource::OnReplyReceived(
+ const proxy::ResourceMessageReplyParams& params,
+ const IPC::Message& msg) {
+ TRACE_EVENT2("ppapi proxy", "PluginResource::OnReplyReceived",
+ "Class", IPC_MESSAGE_ID_CLASS(msg.type()),
+ "Line", IPC_MESSAGE_ID_LINE(msg.type()));
+ // Grab the callback for the reply sequence number and run it with |msg|.
+ CallbackMap::iterator it = callbacks_.find(params.sequence());
+ if (it == callbacks_.end()) {
+ DCHECK(false) << "Callback does not exist for an expected sequence number.";
+ } else {
+ scoped_refptr<PluginResourceCallbackBase> callback = it->second;
+ callbacks_.erase(it);
+ callback->Run(params, msg);
+ }
+}
+
+void PluginResource::NotifyLastPluginRefWasDeleted() {
+ Resource::NotifyLastPluginRefWasDeleted();
+
+ // The callbacks may hold referrences to this object. Normally, we will get
+ // reply messages from the host side and remove them. However, it is possible
+ // that some replies from the host never arrive, e.g., the corresponding
+ // renderer crashes. In that case, we have to clean up the callbacks,
+ // otherwise this object will live forever.
+ callbacks_.clear();
+}
+
+void PluginResource::NotifyInstanceWasDeleted() {
+ Resource::NotifyInstanceWasDeleted();
+
+ // Please see comments in NotifyLastPluginRefWasDeleted() about why we must
+ // clean up the callbacks.
+ // It is possible that NotifyLastPluginRefWasDeleted() is never called for a
+ // resource. For example, those singleton-style resources such as
+ // GamepadResource never expose references to the plugin and thus won't
+ // receive a NotifyLastPluginRefWasDeleted() call. For those resources, we
+ // need to clean up callbacks when the instance goes away.
+ callbacks_.clear();
+}
+
+void PluginResource::SendCreate(Destination dest, const IPC::Message& msg) {
+ TRACE_EVENT2("ppapi proxy", "PluginResource::SendCreate",
+ "Class", IPC_MESSAGE_ID_CLASS(msg.type()),
+ "Line", IPC_MESSAGE_ID_LINE(msg.type()));
+ if (dest == RENDERER) {
+ DCHECK(!sent_create_to_renderer_);
+ sent_create_to_renderer_ = true;
+ } else {
+ DCHECK(!sent_create_to_browser_);
+ sent_create_to_browser_ = true;
+ }
+ ResourceMessageCallParams params(pp_resource(), GetNextSequence());
+ GetSender(dest)->Send(
+ new PpapiHostMsg_ResourceCreated(params, pp_instance(), msg));
+}
+
+void PluginResource::AttachToPendingHost(Destination dest,
+ int pending_host_id) {
+ // Connecting to a pending host is a replacement for "create".
+ if (dest == RENDERER) {
+ DCHECK(!sent_create_to_renderer_);
+ sent_create_to_renderer_ = true;
+ } else {
+ DCHECK(!sent_create_to_browser_);
+ sent_create_to_browser_ = true;
+ }
+ GetSender(dest)->Send(
+ new PpapiHostMsg_AttachToPendingHost(pp_resource(), pending_host_id));
+}
+
+void PluginResource::Post(Destination dest, const IPC::Message& msg) {
+ TRACE_EVENT2("ppapi proxy", "PluginResource::Post",
+ "Class", IPC_MESSAGE_ID_CLASS(msg.type()),
+ "Line", IPC_MESSAGE_ID_LINE(msg.type()));
+ ResourceMessageCallParams params(pp_resource(), GetNextSequence());
+ SendResourceCall(dest, params, msg);
+}
+
+bool PluginResource::SendResourceCall(
+ Destination dest,
+ const ResourceMessageCallParams& call_params,
+ const IPC::Message& nested_msg) {
+ // For in-process plugins, we need to send the routing ID with the request.
+ // The browser then uses that routing ID when sending the reply so it will be
+ // routed back to the correct RenderViewImpl.
+ if (dest == BROWSER && connection_.in_process) {
+ return GetSender(dest)->Send(new PpapiHostMsg_InProcessResourceCall(
+ connection_.browser_sender_routing_id,
+ call_params,
+ nested_msg));
+ } else {
+ return GetSender(dest)->Send(
+ new PpapiHostMsg_ResourceCall(call_params, nested_msg));
+ }
+}
+
+int32_t PluginResource::GenericSyncCall(
+ Destination dest,
+ const IPC::Message& msg,
+ IPC::Message* reply,
+ ResourceMessageReplyParams* reply_params) {
+ TRACE_EVENT2("ppapi proxy", "PluginResource::GenericSyncCall",
+ "Class", IPC_MESSAGE_ID_CLASS(msg.type()),
+ "Line", IPC_MESSAGE_ID_LINE(msg.type()));
+ ResourceMessageCallParams params(pp_resource(), GetNextSequence());
+ params.set_has_callback();
+ bool success = GetSender(dest)->Send(new PpapiHostMsg_ResourceSyncCall(
+ params, msg, reply_params, reply));
+ if (success)
+ return reply_params->result();
+ return PP_ERROR_FAILED;
+}
+
+int32_t PluginResource::GetNextSequence() {
+ // Return the value with wraparound, making sure we don't make a sequence
+ // number with a 0 ID. Note that signed wraparound is undefined in C++ so we
+ // manually check.
+ int32_t ret = next_sequence_number_;
+ if (next_sequence_number_ == std::numeric_limits<int32_t>::max())
+ next_sequence_number_ = 1; // Skip 0 which is invalid.
+ else
+ next_sequence_number_++;
+ return ret;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/plugin_resource.h b/chromium/ppapi/proxy/plugin_resource.h
new file mode 100644
index 00000000000..9448326d55c
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_resource.h
@@ -0,0 +1,253 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PLUGIN_RESOURCE_H_
+#define PPAPI_PROXY_PLUGIN_RESOURCE_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_sender.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/plugin_resource_callback.h"
+#include "ppapi/proxy/ppapi_message_utils.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/proxy/resource_message_params.h"
+#include "ppapi/shared_impl/resource.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PluginDispatcher;
+
+class PPAPI_PROXY_EXPORT PluginResource : public Resource {
+ public:
+ enum Destination {
+ RENDERER = 0,
+ BROWSER = 1
+ };
+
+ PluginResource(Connection connection, PP_Instance instance);
+ virtual ~PluginResource();
+
+ // Returns true if we've previously sent a create message to the browser
+ // or renderer. Generally resources will use these to tell if they should
+ // lazily send create messages.
+ bool sent_create_to_browser() const { return sent_create_to_browser_; }
+ bool sent_create_to_renderer() const { return sent_create_to_renderer_; }
+
+ // This handles a reply to a resource call. It works by looking up the
+ // callback that was registered when CallBrowser/CallRenderer was called
+ // and calling it with |params| and |msg|.
+ virtual void OnReplyReceived(const proxy::ResourceMessageReplyParams& params,
+ const IPC::Message& msg) OVERRIDE;
+
+ // Resource overrides.
+ // Note: Subclasses shouldn't override these methods directly. Instead, they
+ // should implement LastPluginRefWasDeleted() or InstanceWasDeleted() to get
+ // notified.
+ virtual void NotifyLastPluginRefWasDeleted() OVERRIDE;
+ virtual void NotifyInstanceWasDeleted() OVERRIDE;
+
+
+ // Sends a create message to the browser or renderer for the current resource.
+ void SendCreate(Destination dest, const IPC::Message& msg);
+
+ // When the host returnes a resource to the plugin, it will create a pending
+ // ResourceHost and send an ID back to the plugin that identifies the pending
+ // object. The plugin uses this function to connect the plugin resource with
+ // the pending host resource. See also PpapiHostMsg_AttachToPendingHost. This
+ // is in lieu of sending a create message.
+ void AttachToPendingHost(Destination dest, int pending_host_id);
+
+ // Sends the given IPC message as a resource request to the host
+ // corresponding to this resource object and does not expect a reply.
+ void Post(Destination dest, const IPC::Message& msg);
+
+ // Like Post() but expects a response. |callback| is a |base::Callback| that
+ // will be run when a reply message with a sequence number matching that of
+ // the call is received. |ReplyMsgClass| is the type of the reply message that
+ // is expected. An example of usage:
+ //
+ // Call<PpapiPluginMsg_MyResourceType_MyReplyMessage>(
+ // BROWSER,
+ // PpapiHostMsg_MyResourceType_MyRequestMessage(),
+ // base::Bind(&MyPluginResource::ReplyHandler, base::Unretained(this)));
+ //
+ // If a reply message to this call is received whose type does not match
+ // |ReplyMsgClass| (for example, in the case of an error), the callback will
+ // still be invoked but with the default values of the message parameters.
+ //
+ // Returns the new request's sequence number which can be used to identify
+ // the callback. This value will never be 0, which you can use to identify
+ // an invalid callback.
+ //
+ // Note: 1) When all plugin references to this resource are gone or the
+ // corresponding plugin instance is deleted, all pending callbacks
+ // are abandoned.
+ // 2) It is *not* recommended to let |callback| hold any reference to
+ // |this|, in which it will be stored. Otherwise, this object will
+ // live forever if we fail to clean up the callback. It is safe to
+ // use base::Unretained(this) or a weak pointer, because this object
+ // will outlive the callback.
+ template<typename ReplyMsgClass, typename CallbackType>
+ int32_t Call(Destination dest,
+ const IPC::Message& msg,
+ const CallbackType& callback);
+
+ // Calls the browser/renderer with sync messages. Returns the pepper error
+ // code from the call.
+ // |ReplyMsgClass| is the type of the reply message that is expected. If it
+ // carries x parameters, then the method with x out parameters should be used.
+ // An example of usage:
+ //
+ // // Assuming the reply message carries a string and an integer.
+ // std::string param_1;
+ // int param_2 = 0;
+ // int32_t result = SyncCall<PpapiPluginMsg_MyResourceType_MyReplyMessage>(
+ // RENDERER, PpapiHostMsg_MyResourceType_MyRequestMessage(),
+ // &param_1, &param_2);
+ template <class ReplyMsgClass>
+ int32_t SyncCall(Destination dest, const IPC::Message& msg);
+ template <class ReplyMsgClass, class A>
+ int32_t SyncCall(Destination dest, const IPC::Message& msg, A* a);
+ template <class ReplyMsgClass, class A, class B>
+ int32_t SyncCall(Destination dest, const IPC::Message& msg, A* a, B* b);
+ template <class ReplyMsgClass, class A, class B, class C>
+ int32_t SyncCall(Destination dest, const IPC::Message& msg, A* a, B* b, C* c);
+ template <class ReplyMsgClass, class A, class B, class C, class D>
+ int32_t SyncCall(
+ Destination dest, const IPC::Message& msg, A* a, B* b, C* c, D* d);
+ template <class ReplyMsgClass, class A, class B, class C, class D, class E>
+ int32_t SyncCall(
+ Destination dest, const IPC::Message& msg, A* a, B* b, C* c, D* d, E* e);
+
+ int32_t GenericSyncCall(Destination dest,
+ const IPC::Message& msg,
+ IPC::Message* reply_msg,
+ ResourceMessageReplyParams* reply_params);
+
+ const Connection& connection() { return connection_; }
+
+ private:
+ IPC::Sender* GetSender(Destination dest) {
+ return dest == RENDERER ? connection_.renderer_sender :
+ connection_.browser_sender;
+ }
+
+ // Helper function to send a |PpapiHostMsg_ResourceCall| to the given
+ // destination with |nested_msg| and |call_params|.
+ bool SendResourceCall(Destination dest,
+ const ResourceMessageCallParams& call_params,
+ const IPC::Message& nested_msg);
+
+ int32_t GetNextSequence();
+
+ Connection connection_;
+
+ // Use GetNextSequence to retrieve the next value.
+ int32_t next_sequence_number_;
+
+ bool sent_create_to_browser_;
+ bool sent_create_to_renderer_;
+
+ typedef std::map<int32_t, scoped_refptr<PluginResourceCallbackBase> >
+ CallbackMap;
+ CallbackMap callbacks_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginResource);
+};
+
+template<typename ReplyMsgClass, typename CallbackType>
+int32_t PluginResource::Call(Destination dest,
+ const IPC::Message& msg,
+ const CallbackType& callback) {
+ TRACE_EVENT2("ppapi proxy", "PluginResource::Call",
+ "Class", IPC_MESSAGE_ID_CLASS(msg.type()),
+ "Line", IPC_MESSAGE_ID_LINE(msg.type()));
+ ResourceMessageCallParams params(pp_resource(), next_sequence_number_++);
+ // Stash the |callback| in |callbacks_| identified by the sequence number of
+ // the call.
+ scoped_refptr<PluginResourceCallbackBase> plugin_callback(
+ new PluginResourceCallback<ReplyMsgClass, CallbackType>(callback));
+ callbacks_.insert(std::make_pair(params.sequence(), plugin_callback));
+ params.set_has_callback();
+ SendResourceCall(dest, params, msg);
+ return params.sequence();
+}
+
+template <class ReplyMsgClass>
+int32_t PluginResource::SyncCall(Destination dest, const IPC::Message& msg) {
+ IPC::Message reply;
+ ResourceMessageReplyParams reply_params;
+ return GenericSyncCall(dest, msg, &reply, &reply_params);
+}
+
+template <class ReplyMsgClass, class A>
+int32_t PluginResource::SyncCall(
+ Destination dest, const IPC::Message& msg, A* a) {
+ IPC::Message reply;
+ ResourceMessageReplyParams reply_params;
+ int32_t result = GenericSyncCall(dest, msg, &reply, &reply_params);
+
+ if (UnpackMessage<ReplyMsgClass>(reply, a))
+ return result;
+ return PP_ERROR_FAILED;
+}
+
+template <class ReplyMsgClass, class A, class B>
+int32_t PluginResource::SyncCall(
+ Destination dest, const IPC::Message& msg, A* a, B* b) {
+ IPC::Message reply;
+ ResourceMessageReplyParams reply_params;
+ int32_t result = GenericSyncCall(dest, msg, &reply, &reply_params);
+
+ if (UnpackMessage<ReplyMsgClass>(reply, a, b))
+ return result;
+ return PP_ERROR_FAILED;
+}
+
+template <class ReplyMsgClass, class A, class B, class C>
+int32_t PluginResource::SyncCall(
+ Destination dest, const IPC::Message& msg, A* a, B* b, C* c) {
+ IPC::Message reply;
+ ResourceMessageReplyParams reply_params;
+ int32_t result = GenericSyncCall(dest, msg, &reply, &reply_params);
+
+ if (UnpackMessage<ReplyMsgClass>(reply, a, b, c))
+ return result;
+ return PP_ERROR_FAILED;
+}
+
+template <class ReplyMsgClass, class A, class B, class C, class D>
+int32_t PluginResource::SyncCall(
+ Destination dest, const IPC::Message& msg, A* a, B* b, C* c, D* d) {
+ IPC::Message reply;
+ ResourceMessageReplyParams reply_params;
+ int32_t result = GenericSyncCall(dest, msg, &reply, &reply_params);
+
+ if (UnpackMessage<ReplyMsgClass>(reply, a, b, c, d))
+ return result;
+ return PP_ERROR_FAILED;
+}
+
+template <class ReplyMsgClass, class A, class B, class C, class D, class E>
+int32_t PluginResource::SyncCall(
+ Destination dest, const IPC::Message& msg, A* a, B* b, C* c, D* d, E* e) {
+ IPC::Message reply;
+ ResourceMessageReplyParams reply_params;
+ int32_t result = GenericSyncCall(dest, msg, &reply, &reply_params);
+
+ if (UnpackMessage<ReplyMsgClass>(reply, a, b, c, d, e))
+ return result;
+ return PP_ERROR_FAILED;
+}
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PLUGIN_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/plugin_resource_callback.h b/chromium/ppapi/proxy/plugin_resource_callback.h
new file mode 100644
index 00000000000..a306c26a1c7
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_resource_callback.h
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PLUGIN_RESOURCE_CALLBACK_H_
+#define PPAPI_PROXY_PLUGIN_RESOURCE_CALLBACK_H_
+
+#include "base/memory/ref_counted.h"
+#include "ipc/ipc_message.h"
+#include "ppapi/proxy/dispatch_reply_message.h"
+#include "ppapi/proxy/resource_message_params.h"
+
+namespace ppapi {
+namespace proxy {
+
+// |PluginResourceCallback| wraps a |base::Callback| on the plugin side which
+// will be triggered in response to a particular message type being received.
+// |MsgClass| is the reply message type that the callback will be called with
+// and |CallbackType| is the type of the |base::Callback| that will be called.
+class PluginResourceCallbackBase
+ : public base::RefCounted<PluginResourceCallbackBase> {
+ public:
+ virtual void Run(const ResourceMessageReplyParams& params,
+ const IPC::Message& msg) = 0;
+ protected:
+ friend class base::RefCounted<PluginResourceCallbackBase>;
+ virtual ~PluginResourceCallbackBase() {}
+};
+
+template<typename MsgClass, typename CallbackType>
+class PluginResourceCallback : public PluginResourceCallbackBase {
+ public:
+ explicit PluginResourceCallback(const CallbackType& callback)
+ : callback_(callback) {}
+
+ virtual void Run(
+ const ResourceMessageReplyParams& reply_params,
+ const IPC::Message& msg) OVERRIDE {
+ DispatchResourceReplyOrDefaultParams<MsgClass>(
+ &callback_, &CallbackType::Run, reply_params, msg);
+ }
+
+ private:
+ virtual ~PluginResourceCallback() {}
+
+ CallbackType callback_;
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PLUGIN_RESOURCE_CALLBACK_H_
diff --git a/chromium/ppapi/proxy/plugin_resource_tracker.cc b/chromium/ppapi/proxy/plugin_resource_tracker.cc
new file mode 100644
index 00000000000..86cbf7cee43
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_resource_tracker.cc
@@ -0,0 +1,72 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/plugin_resource_tracker.h"
+
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/resource.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+namespace proxy {
+
+PluginResourceTracker::PluginResourceTracker() : ResourceTracker(THREAD_SAFE) {
+ UseOddResourceValueInDebugMode();
+}
+
+PluginResourceTracker::~PluginResourceTracker() {
+}
+
+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;
+}
+
+PP_Resource PluginResourceTracker::AddResource(Resource* object) {
+ // If there's a HostResource, it must not be added twice.
+ DCHECK(!object->host_resource().host_resource() ||
+ (host_resource_map_.find(object->host_resource()) ==
+ host_resource_map_.end()));
+
+ PP_Resource ret = ResourceTracker::AddResource(object);
+
+ // Some resources are plugin-only, so they don't have a host resource.
+ if (object->host_resource().host_resource())
+ host_resource_map_.insert(std::make_pair(object->host_resource(), ret));
+ return ret;
+}
+
+void PluginResourceTracker::RemoveResource(Resource* object) {
+ ResourceTracker::RemoveResource(object);
+
+ if (!object->host_resource().is_null()) {
+ // The host_resource will be NULL for proxy-only resources, which we
+ // obviously don't need to tell the host about.
+ DCHECK(host_resource_map_.find(object->host_resource()) !=
+ host_resource_map_.end());
+ host_resource_map_.erase(object->host_resource());
+
+ PluginDispatcher* dispatcher =
+ PluginDispatcher::GetForInstance(object->pp_instance());
+ if (dispatcher) {
+ // The 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.
+ dispatcher->Send(new PpapiHostMsg_PPBCore_ReleaseResource(
+ API_ID_PPB_CORE, object->host_resource()));
+ }
+ }
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/plugin_resource_tracker.h b/chromium/ppapi/proxy/plugin_resource_tracker.h
new file mode 100644
index 00000000000..6bed72f4eff
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_resource_tracker.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PLUGIN_RESOURCE_TRACKER_H_
+#define PPAPI_PROXY_PLUGIN_RESOURCE_TRACKER_H_
+
+#include <map>
+#include <utility>
+
+#include "base/compiler_specific.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/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/host_resource.h"
+#include "ppapi/shared_impl/resource_tracker.h"
+
+template<typename T> struct DefaultSingletonTraits;
+
+namespace ppapi {
+
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT PluginResourceTracker : public ResourceTracker {
+ public:
+ PluginResourceTracker();
+ virtual ~PluginResourceTracker();
+
+ // 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;
+
+ protected:
+ // ResourceTracker overrides.
+ virtual PP_Resource AddResource(Resource* object) OVERRIDE;
+ virtual void RemoveResource(Resource* object) OVERRIDE;
+
+ private:
+ // Map of host instance/resource pairs to a plugin resource ID.
+ typedef std::map<HostResource, PP_Resource> HostResourceMap;
+ HostResourceMap host_resource_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginResourceTracker);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PLUGIN_RESOURCE_TRACKER_H_
diff --git a/chromium/ppapi/proxy/plugin_resource_tracker_unittest.cc b/chromium/ppapi/proxy/plugin_resource_tracker_unittest.cc
new file mode 100644
index 00000000000..8623f649de3
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_resource_tracker_unittest.cc
@@ -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.
+
+#include "base/memory/scoped_ptr.h"
+#include "base/process/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"
+#include "ppapi/shared_impl/proxy_lock.h"
+
+namespace ppapi {
+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() {}
+};
+
+TEST_F(PluginResourceTrackerTest, PluginResourceForHostResource) {
+ ProxyAutoLock lock;
+
+ 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, resource_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 = object->GetReference();
+
+ // Now that the object has been added, the return value should be the plugin
+ // resource ID we already got.
+ EXPECT_EQ(plugin_resource,
+ resource_tracker().PluginResourceForHostResource(serialized));
+
+ // Releasing the resource should have freed it.
+ resource_tracker().ReleaseResource(plugin_resource);
+ EXPECT_EQ(0, TrackedMockResource::tracked_alive_count);
+ EXPECT_EQ(0, resource_tracker().PluginResourceForHostResource(serialized));
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/plugin_var_serialization_rules.cc b/chromium/ppapi/proxy/plugin_var_serialization_rules.cc
new file mode 100644
index 00000000000..f772554b4ac
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_var_serialization_rules.cc
@@ -0,0 +1,120 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/plugin_var_serialization_rules.h"
+
+#include "base/logging.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+namespace proxy {
+
+PluginVarSerializationRules::PluginVarSerializationRules(
+ const base::WeakPtr<PluginDispatcher>& dispatcher)
+ : var_tracker_(PluginGlobals::Get()->plugin_var_tracker()),
+ dispatcher_(dispatcher) {
+}
+
+PluginVarSerializationRules::~PluginVarSerializationRules() {
+}
+
+PP_Var PluginVarSerializationRules::SendCallerOwned(const PP_Var& var) {
+ // Objects need special translations to get the IDs valid in the host.
+ if (var.type == PP_VARTYPE_OBJECT)
+ return var_tracker_->GetHostObject(var);
+ return var;
+}
+
+PP_Var PluginVarSerializationRules::BeginReceiveCallerOwned(const PP_Var& var) {
+ if (var.type == PP_VARTYPE_OBJECT) {
+ return dispatcher_.get() ? var_tracker_->TrackObjectWithNoReference(
+ var, dispatcher_.get())
+ : PP_MakeUndefined();
+ }
+
+ return var;
+}
+
+void PluginVarSerializationRules::EndReceiveCallerOwned(const PP_Var& var) {
+ if (var.type == PP_VARTYPE_OBJECT) {
+ var_tracker_->StopTrackingObjectWithNoReference(var);
+ } else if (var.type >= PP_VARTYPE_STRING) {
+ // Release our reference to the local Var.
+ var_tracker_->ReleaseVar(var);
+ }
+}
+
+PP_Var PluginVarSerializationRules::ReceivePassRef(const PP_Var& var) {
+ // 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
+ // of them in the browser).
+ if (var.type == PP_VARTYPE_OBJECT) {
+ return dispatcher_.get()
+ ? var_tracker_->ReceiveObjectPassRef(var, dispatcher_.get())
+ : PP_MakeUndefined();
+ }
+
+ // Other types are unchanged.
+ return var;
+}
+
+PP_Var PluginVarSerializationRules::BeginSendPassRef(const PP_Var& var) {
+ // 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);
+ return var;
+}
+
+void PluginVarSerializationRules::EndSendPassRef(const PP_Var& var) {
+ // 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) {
+ if (dispatcher_.get())
+ var_tracker_->ReleaseHostObject(dispatcher_.get(), var);
+ } else if (var.type >= PP_VARTYPE_STRING) {
+ var_tracker_->ReleaseVar(var);
+ }
+}
+
+void PluginVarSerializationRules::ReleaseObjectRef(const PP_Var& var) {
+ var_tracker_->ReleaseVar(var);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/plugin_var_serialization_rules.h b/chromium/ppapi/proxy/plugin_var_serialization_rules.h
new file mode 100644
index 00000000000..1616a755220
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_var_serialization_rules.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PLUGIN_VAR_SERIALIZATION_RULES_H_
+#define PPAPI_PROXY_PLUGIN_VAR_SERIALIZATION_RULES_H_
+
+#include "base/basictypes.h"
+#include "base/memory/weak_ptr.h"
+#include "ppapi/proxy/var_serialization_rules.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PluginDispatcher;
+class PluginVarTracker;
+
+// Implementation of the VarSerializationRules 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.
+ explicit PluginVarSerializationRules(
+ const base::WeakPtr<PluginDispatcher>& dispatcher);
+ ~PluginVarSerializationRules();
+
+ // VarSerialization implementation.
+ virtual PP_Var SendCallerOwned(const PP_Var& var);
+ virtual PP_Var BeginReceiveCallerOwned(const PP_Var& var);
+ virtual void EndReceiveCallerOwned(const PP_Var& var);
+ virtual PP_Var ReceivePassRef(const PP_Var& var);
+ virtual PP_Var BeginSendPassRef(const PP_Var& var);
+ virtual void EndSendPassRef(const PP_Var& var);
+ virtual void ReleaseObjectRef(const PP_Var& var);
+
+ private:
+ PluginVarTracker* var_tracker_;
+
+ // In most cases, |dispatcher_| won't be NULL, but you should always check
+ // before using it.
+ // One scenario that it becomes NULL: A SerializedVar holds a ref to this
+ // object, and a sync message is issued. While waiting for the reply to the
+ // sync message, some incoming message causes the dispatcher to be destroyed.
+ // If that happens, we may leak references to object vars. Considering that
+ // scripting has been deprecated, this may not be a big issue.
+ base::WeakPtr<PluginDispatcher> dispatcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginVarSerializationRules);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PLUGIN_VAR_SERIALIZATION_RULES_H_
diff --git a/chromium/ppapi/proxy/plugin_var_tracker.cc b/chromium/ppapi/proxy/plugin_var_tracker.cc
new file mode 100644
index 00000000000..ee299852514
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_var_tracker.cc
@@ -0,0 +1,410 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/plugin_var_tracker.h"
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/singleton.h"
+#include "ppapi/c/dev/ppp_class_deprecated.h"
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/proxy/plugin_array_buffer_var.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/proxy_object_var.h"
+#include "ppapi/shared_impl/api_id.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+namespace proxy {
+
+PluginVarTracker::HostVar::HostVar(PluginDispatcher* d, int32 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::PluginVarTracker() : VarTracker(THREAD_SAFE) {
+}
+
+PluginVarTracker::~PluginVarTracker() {
+}
+
+PP_Var PluginVarTracker::ReceiveObjectPassRef(const PP_Var& host_var,
+ PluginDispatcher* dispatcher) {
+ CheckThreadingPreconditions();
+ DCHECK(host_var.type == PP_VARTYPE_OBJECT);
+
+ // Get the object.
+ scoped_refptr<ProxyObjectVar> object(
+ FindOrMakePluginVarFromHostVar(host_var, dispatcher));
+
+ // Actually create the PP_Var, this will add all the tracking info but not
+ // adjust any refcounts.
+ PP_Var ret = GetOrCreateObjectVarID(object.get());
+
+ VarInfo& info = GetLiveVar(ret)->second;
+ if (info.ref_count > 0) {
+ // We already had a reference to it before. 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(*object.get());
+ }
+ info.ref_count++;
+ return ret;
+}
+
+PP_Var PluginVarTracker::TrackObjectWithNoReference(
+ const PP_Var& host_var,
+ PluginDispatcher* dispatcher) {
+ CheckThreadingPreconditions();
+ DCHECK(host_var.type == PP_VARTYPE_OBJECT);
+
+ // Get the object.
+ scoped_refptr<ProxyObjectVar> object(
+ FindOrMakePluginVarFromHostVar(host_var, dispatcher));
+
+ // Actually create the PP_Var, this will add all the tracking info but not
+ // adjust any refcounts.
+ PP_Var ret = GetOrCreateObjectVarID(object.get());
+
+ VarInfo& info = GetLiveVar(ret)->second;
+ info.track_with_no_reference_count++;
+ return ret;
+}
+
+void PluginVarTracker::StopTrackingObjectWithNoReference(
+ const PP_Var& plugin_var) {
+ CheckThreadingPreconditions();
+ DCHECK(plugin_var.type == PP_VARTYPE_OBJECT);
+
+ VarMap::iterator found = GetLiveVar(plugin_var);
+ if (found == live_vars_.end()) {
+ NOTREACHED();
+ return;
+ }
+
+ DCHECK(found->second.track_with_no_reference_count > 0);
+ found->second.track_with_no_reference_count--;
+ DeleteObjectInfoIfNecessary(found);
+}
+
+PP_Var PluginVarTracker::GetHostObject(const PP_Var& plugin_object) const {
+ CheckThreadingPreconditions();
+ if (plugin_object.type != PP_VARTYPE_OBJECT) {
+ NOTREACHED();
+ return PP_MakeUndefined();
+ }
+
+ Var* var = GetVar(plugin_object);
+ ProxyObjectVar* object = var->AsProxyObjectVar();
+ if (!object) {
+ NOTREACHED();
+ return PP_MakeUndefined();
+ }
+
+ // Make a var with the host ID.
+ PP_Var ret = { PP_VARTYPE_OBJECT };
+ ret.value.as_id = object->host_var_id();
+ return ret;
+}
+
+PluginDispatcher* PluginVarTracker::DispatcherForPluginObject(
+ const PP_Var& plugin_object) const {
+ CheckThreadingPreconditions();
+ if (plugin_object.type != PP_VARTYPE_OBJECT)
+ return NULL;
+
+ VarMap::const_iterator found = GetLiveVar(plugin_object);
+ if (found == live_vars_.end())
+ return NULL;
+
+ ProxyObjectVar* object = found->second.var->AsProxyObjectVar();
+ if (!object)
+ return NULL;
+ return object->dispatcher();
+}
+
+void PluginVarTracker::ReleaseHostObject(PluginDispatcher* dispatcher,
+ const PP_Var& host_object) {
+ CheckThreadingPreconditions();
+ DCHECK(host_object.type == PP_VARTYPE_OBJECT);
+
+ // Convert the host object to a normal var valid in the plugin.
+ HostVarToPluginVarMap::iterator found = host_var_to_plugin_var_.find(
+ HostVar(dispatcher, static_cast<int32>(host_object.value.as_id)));
+ if (found == host_var_to_plugin_var_.end()) {
+ NOTREACHED();
+ return;
+ }
+
+ // Now just release the object given the plugin var ID.
+ ReleaseVar(found->second);
+}
+
+void PluginVarTracker::DidDeleteInstance(PP_Instance instance) {
+ // Calling the destructors on plugin objects may in turn release other
+ // objects which will mutate the map out from under us. So do a two-step
+ // process of identifying the ones to delete, and then delete them.
+ //
+ // See the comment above user_data_to_plugin_ in the header file. We assume
+ // there aren't that many objects so a brute-force search is reasonable.
+ std::vector<void*> user_data_to_delete;
+ for (UserDataToPluginImplementedVarMap::const_iterator i =
+ user_data_to_plugin_.begin();
+ i != user_data_to_plugin_.end();
+ ++i) {
+ if (i->second.instance == instance)
+ user_data_to_delete.push_back(i->first);
+ }
+
+ for (size_t i = 0; i < user_data_to_delete.size(); i++) {
+ UserDataToPluginImplementedVarMap::iterator found =
+ user_data_to_plugin_.find(user_data_to_delete[i]);
+ if (found == user_data_to_plugin_.end())
+ continue; // Object removed from list while we were iterating.
+
+ if (!found->second.plugin_object_id) {
+ // This object is for the freed instance and the plugin is not holding
+ // any references to it. Deallocate immediately.
+ CallWhileUnlocked(found->second.ppp_class->Deallocate, found->first);
+ user_data_to_plugin_.erase(found);
+ } else {
+ // The plugin is holding refs to this object. We don't want to call
+ // Deallocate since the plugin may be depending on those refs to keep
+ // its data alive. To avoid crashes in this case, just clear out the
+ // instance to mark it and continue. When the plugin refs go to 0,
+ // we'll notice there is no instance and call Deallocate.
+ found->second.instance = 0;
+ }
+ }
+}
+
+void PluginVarTracker::DidDeleteDispatcher(PluginDispatcher* dispatcher) {
+ for (VarMap::iterator it = live_vars_.begin();
+ it != live_vars_.end();
+ ++it) {
+ if (it->second.var.get() == NULL)
+ continue;
+ ProxyObjectVar* object = it->second.var->AsProxyObjectVar();
+ if (object && object->dispatcher() == dispatcher)
+ object->clear_dispatcher();
+ }
+}
+
+ArrayBufferVar* PluginVarTracker::CreateArrayBuffer(uint32 size_in_bytes) {
+ return new PluginArrayBufferVar(size_in_bytes);
+}
+
+ArrayBufferVar* PluginVarTracker::CreateShmArrayBuffer(
+ uint32 size_in_bytes,
+ base::SharedMemoryHandle handle) {
+ return new PluginArrayBufferVar(size_in_bytes, handle);
+}
+
+void PluginVarTracker::PluginImplementedObjectCreated(
+ PP_Instance instance,
+ const PP_Var& created_var,
+ const PPP_Class_Deprecated* ppp_class,
+ void* ppp_class_data) {
+ PluginImplementedVar p;
+ p.ppp_class = ppp_class;
+ p.instance = instance;
+ p.plugin_object_id = created_var.value.as_id;
+ user_data_to_plugin_[ppp_class_data] = p;
+
+ // Link the user data to the object.
+ ProxyObjectVar* object = GetVar(created_var)->AsProxyObjectVar();
+ object->set_user_data(ppp_class_data);
+}
+
+void PluginVarTracker::PluginImplementedObjectDestroyed(void* user_data) {
+ UserDataToPluginImplementedVarMap::iterator found =
+ user_data_to_plugin_.find(user_data);
+ if (found == user_data_to_plugin_.end()) {
+ NOTREACHED();
+ return;
+ }
+ user_data_to_plugin_.erase(found);
+}
+
+bool PluginVarTracker::IsPluginImplementedObjectAlive(void* user_data) {
+ return user_data_to_plugin_.find(user_data) != user_data_to_plugin_.end();
+}
+
+bool PluginVarTracker::ValidatePluginObjectCall(
+ const PPP_Class_Deprecated* ppp_class,
+ void* user_data) {
+ UserDataToPluginImplementedVarMap::iterator found =
+ user_data_to_plugin_.find(user_data);
+ if (found == user_data_to_plugin_.end())
+ return false;
+ return found->second.ppp_class == ppp_class;
+}
+
+int32 PluginVarTracker::AddVarInternal(Var* var, AddVarRefMode mode) {
+ // Normal adding.
+ int32 new_id = VarTracker::AddVarInternal(var, mode);
+
+ // Need to add proxy objects to the host var map.
+ ProxyObjectVar* proxy_object = var->AsProxyObjectVar();
+ if (proxy_object) {
+ HostVar host_var(proxy_object->dispatcher(), proxy_object->host_var_id());
+ DCHECK(host_var_to_plugin_var_.find(host_var) ==
+ host_var_to_plugin_var_.end()); // Adding an object twice, use
+ // FindOrMakePluginVarFromHostVar.
+ host_var_to_plugin_var_[host_var] = new_id;
+ }
+ return new_id;
+}
+
+void PluginVarTracker::TrackedObjectGettingOneRef(VarMap::const_iterator iter) {
+ ProxyObjectVar* object = iter->second.var->AsProxyObjectVar();
+ if (!object) {
+ NOTREACHED();
+ return;
+ }
+
+ DCHECK(iter->second.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(*object);
+}
+
+void PluginVarTracker::ObjectGettingZeroRef(VarMap::iterator iter) {
+ ProxyObjectVar* object = iter->second.var->AsProxyObjectVar();
+ if (!object) {
+ NOTREACHED();
+ return;
+ }
+
+ // Notify the host we're no longer holding our ref.
+ DCHECK(iter->second.ref_count == 0);
+ SendReleaseObjectMsg(*object);
+
+ UserDataToPluginImplementedVarMap::iterator found =
+ user_data_to_plugin_.find(object->user_data());
+ if (found != user_data_to_plugin_.end()) {
+ // This object is implemented in the plugin.
+ if (found->second.instance == 0) {
+ // Instance is destroyed. This means that we'll never get a Deallocate
+ // call from the renderer and we should do so now.
+ found->second.ppp_class->Deallocate(found->first);
+ user_data_to_plugin_.erase(found);
+ } else {
+ // The plugin is releasing its last reference to an object it implements.
+ // Clear the tracking data that links our "plugin implemented object" to
+ // the var. If the instance is destroyed and there is no ID, we know that
+ // we should just call Deallocate on the object data.
+ //
+ // See the plugin_object_id declaration for more info.
+ found->second.plugin_object_id = 0;
+ }
+ }
+
+ // This will optionally delete the info from live_vars_.
+ VarTracker::ObjectGettingZeroRef(iter);
+}
+
+bool PluginVarTracker::DeleteObjectInfoIfNecessary(VarMap::iterator iter) {
+ // Get the info before calling the base class's version of this function,
+ // which may delete the object.
+ ProxyObjectVar* object = iter->second.var->AsProxyObjectVar();
+ HostVar host_var(object->dispatcher(), object->host_var_id());
+
+ if (!VarTracker::DeleteObjectInfoIfNecessary(iter))
+ return false;
+
+ // Clean up the host var mapping.
+ DCHECK(host_var_to_plugin_var_.find(host_var) !=
+ host_var_to_plugin_var_.end());
+ host_var_to_plugin_var_.erase(host_var);
+ return true;
+}
+
+PP_Var PluginVarTracker::GetOrCreateObjectVarID(ProxyObjectVar* object) {
+ // We can't use object->GetPPVar() because we don't want to affect the
+ // refcount, so we have to add everything manually here.
+ int32 var_id = object->GetExistingVarID();
+ if (!var_id) {
+ var_id = AddVarInternal(object, ADD_VAR_CREATE_WITH_NO_REFERENCE);
+ object->AssignVarID(var_id);
+ }
+
+ PP_Var ret = { PP_VARTYPE_OBJECT };
+ ret.value.as_id = var_id;
+ return ret;
+}
+
+void PluginVarTracker::SendAddRefObjectMsg(
+ const ProxyObjectVar& proxy_object) {
+ int unused;
+ if (proxy_object.dispatcher()) {
+ proxy_object.dispatcher()->Send(new PpapiHostMsg_PPBVar_AddRefObject(
+ API_ID_PPB_VAR_DEPRECATED, proxy_object.host_var_id(), &unused));
+ }
+}
+
+void PluginVarTracker::SendReleaseObjectMsg(
+ const ProxyObjectVar& proxy_object) {
+ if (proxy_object.dispatcher()) {
+ proxy_object.dispatcher()->Send(new PpapiHostMsg_PPBVar_ReleaseObject(
+ API_ID_PPB_VAR_DEPRECATED, proxy_object.host_var_id()));
+ }
+}
+
+scoped_refptr<ProxyObjectVar> 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()) {
+ // Create a new object.
+ return scoped_refptr<ProxyObjectVar>(
+ new ProxyObjectVar(dispatcher, static_cast<int32>(var.value.as_id)));
+ }
+
+ // Have this host var, look up the object.
+ VarMap::iterator ret = live_vars_.find(found->second);
+ DCHECK(ret != live_vars_.end());
+
+ // All objects should be proxy objects.
+ DCHECK(ret->second.var->AsProxyObjectVar());
+ return scoped_refptr<ProxyObjectVar>(ret->second.var->AsProxyObjectVar());
+}
+
+int PluginVarTracker::TrackSharedMemoryHandle(PP_Instance instance,
+ base::SharedMemoryHandle handle,
+ uint32 size_in_bytes) {
+ NOTREACHED();
+ return -1;
+}
+
+bool PluginVarTracker::StopTrackingSharedMemoryHandle(
+ int id,
+ PP_Instance instance,
+ base::SharedMemoryHandle* handle,
+ uint32* size_in_bytes) {
+ NOTREACHED();
+ return false;
+}
+
+} // namesace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/plugin_var_tracker.h b/chromium/ppapi/proxy/plugin_var_tracker.h
new file mode 100644
index 00000000000..670457f9c05
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_var_tracker.h
@@ -0,0 +1,205 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PLUGIN_VAR_TRACKER_H_
+#define PPAPI_PROXY_PLUGIN_VAR_TRACKER_H_
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/shared_memory.h"
+#include "ppapi/c/pp_stdint.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/var_tracker.h"
+
+template<typename T> struct DefaultSingletonTraits;
+struct PPP_Class_Deprecated;
+
+namespace ppapi {
+
+class ProxyObjectVar;
+
+namespace proxy {
+
+class PluginDispatcher;
+
+// Tracks live strings and objects in the plugin process.
+class PPAPI_PROXY_EXPORT PluginVarTracker : public VarTracker {
+ public:
+ PluginVarTracker();
+ ~PluginVarTracker();
+
+ // 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);
+
+ // See the comment in var_tracker.h for more about what a tracked object is.
+ // This adds and releases the "track_with_no_reference_count" for a given
+ // object.
+ 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. The reference count is not affeceted.
+ 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);
+
+ // VarTracker public overrides.
+ virtual void DidDeleteInstance(PP_Instance instance) OVERRIDE;
+ virtual int TrackSharedMemoryHandle(PP_Instance instance,
+ base::SharedMemoryHandle file,
+ uint32 size_in_bytes) OVERRIDE;
+ virtual bool StopTrackingSharedMemoryHandle(int id,
+ PP_Instance instance,
+ base::SharedMemoryHandle* handle,
+ uint32* size_in_bytes) OVERRIDE;
+
+ // Notification that a plugin-implemented object (PPP_Class) was created by
+ // the plugin or deallocated by WebKit over IPC.
+ void PluginImplementedObjectCreated(PP_Instance instance,
+ const PP_Var& created_var,
+ const PPP_Class_Deprecated* ppp_class,
+ void* ppp_class_data);
+ void PluginImplementedObjectDestroyed(void* ppp_class_data);
+
+ // Returns true if there is an object implemented by the plugin with the
+ // given user_data that has not been deallocated yet. Call this when
+ // receiving a scripting call to the plugin to validate that the object
+ // receiving the call is still alive (see user_data_to_plugin_ below).
+ bool IsPluginImplementedObjectAlive(void* user_data);
+
+ // Validates that the given class/user_data pair corresponds to a currently
+ // living plugin object.
+ bool ValidatePluginObjectCall(const PPP_Class_Deprecated* ppp_class,
+ void* user_data);
+
+ void DidDeleteDispatcher(PluginDispatcher* dispatcher);
+
+ private:
+ // VarTracker protected overrides.
+ virtual int32 AddVarInternal(Var* var, AddVarRefMode mode) OVERRIDE;
+ virtual void TrackedObjectGettingOneRef(VarMap::const_iterator iter) OVERRIDE;
+ virtual void ObjectGettingZeroRef(VarMap::iterator iter) OVERRIDE;
+ virtual bool DeleteObjectInfoIfNecessary(VarMap::iterator iter) OVERRIDE;
+ virtual ArrayBufferVar* CreateArrayBuffer(uint32 size_in_bytes) OVERRIDE;
+ virtual ArrayBufferVar* CreateShmArrayBuffer(
+ uint32 size_in_bytes,
+ base::SharedMemoryHandle handle) OVERRIDE;
+
+ private:
+ friend struct DefaultSingletonTraits<PluginVarTracker>;
+ friend class PluginProxyTestHarness;
+
+ // Represents a var as received from the host.
+ struct HostVar {
+ HostVar(PluginDispatcher* d, int32 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.
+ int32 host_object_id;
+ };
+
+ struct PluginImplementedVar {
+ const PPP_Class_Deprecated* ppp_class;
+
+ // The instance that created this Var. This will be 0 if the instance has
+ // been destroyed but the object is still alive.
+ PP_Instance instance;
+
+ // Represents the plugin var ID for the var corresponding to this object.
+ // If the plugin does not have a ref to the object but it's still alive
+ // (the DOM could be holding a ref keeping it alive) this will be 0.
+ //
+ // There is an obscure corner case. If the plugin returns an object to the
+ // renderer and releases all of its refs, the object will still be alive
+ // but there will be no plugin refs. It's possible for the plugin to get
+ // this same object again through the DOM, and we'll lose the correlation
+ // between plugin implemented object and car. This means we won't know when
+ // the plugin releases its last refs and may call Deallocate when the
+ // plugin is still holding a ref.
+ //
+ // However, for the plugin to be depending on holding a ref to an object
+ // that it implements that it previously released but got again through
+ // indirect means would be extremely rare, and we only allow var scripting
+ // in limited cases anyway.
+ int32 plugin_object_id;
+ };
+
+ // Returns the existing var ID for the given object var, creating and
+ // assigning an ID to it if necessary. This does not affect the reference
+ // count, so in the creation case the refcount will be 0. It's assumed in
+ // this case the caller will either adjust the refcount or the
+ // track_with_no_reference_count.
+ PP_Var GetOrCreateObjectVarID(ProxyObjectVar* object);
+
+ // Sends an addref or release message to the browser for the given object ID.
+ void SendAddRefObjectMsg(const ProxyObjectVar& proxy_object);
+ void SendReleaseObjectMsg(const ProxyObjectVar& proxy_object);
+
+ // Looks up the given host var. If we already know about it, returns a
+ // reference to the already-tracked object. If it doesn't creates a new one
+ // and returns it. If it's created, it's not added to the map.
+ scoped_refptr<ProxyObjectVar> FindOrMakePluginVarFromHostVar(
+ const PP_Var& var,
+ PluginDispatcher* dispatcher);
+
+ // Maps host vars in the host to IDs in the plugin process.
+ typedef std::map<HostVar, int32> HostVarToPluginVarMap;
+ HostVarToPluginVarMap host_var_to_plugin_var_;
+
+ // Maps "user data" for plugin implemented objects (PPP_Class) that are
+ // alive to various tracking info.
+ //
+ // This is tricky because there may not actually be any vars in the plugin
+ // associated with a plugin-implemented object, so they won't all have
+ // entries in our HostVarToPluginVarMap or the base class VarTracker's map.
+ //
+ // All objects that the plugin has created using CreateObject that have not
+ // yet been Deallocate()-ed by WebKit will be in this map. When the instance
+ // that created the object goes away, we know to call Deallocate on all
+ // remaining objects for that instance so that the data backing the object
+ // that the plugin owns is not leaked. We may not receive normal Deallocate
+ // calls from WebKit because the object could be leaked (attached to the DOM
+ // and outliving the plugin instance) or WebKit could send the deallocate
+ // after the out-of-process routing for that instance was torn down.
+ //
+ // There is an additional complexity. In WebKit, objects created by the
+ // plugin aren't actually bound to the plugin instance (for example, you
+ // could attach it to the DOM or send it to another plugin instance). It's
+ // possible that we could force deallocate an object when an instance id
+ // destroyed, but then another instance could get to that object somehow
+ // (like by reading it out of the DOM). We will then have deallocated the
+ // object and can't complete the call. We do not care about this case, and
+ // the calls will just fail.
+ typedef std::map<void*, PluginImplementedVar>
+ UserDataToPluginImplementedVarMap;
+ UserDataToPluginImplementedVarMap user_data_to_plugin_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginVarTracker);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PLUGIN_VAR_TRACKER_H_
diff --git a/chromium/ppapi/proxy/plugin_var_tracker_unittest.cc b/chromium/ppapi/proxy/plugin_var_tracker_unittest.cc
new file mode 100644
index 00000000000..f43d7a8d4da
--- /dev/null
+++ b/chromium/ppapi/proxy/plugin_var_tracker_unittest.cc
@@ -0,0 +1,248 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ipc/ipc_test_sink.h"
+#include "ppapi/c/dev/ppp_class_deprecated.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+#include "ppapi/proxy/proxy_object_var.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+PP_Var MakeObject(int32 object_id) {
+ PP_Var ret;
+ ret.type = PP_VARTYPE_OBJECT;
+ ret.value.as_id = object_id;
+ return ret;
+}
+
+// A Deallocate() function for PPP_Class that just increments the integer
+// referenced by the pointer so we know how often Deallocate was called.
+void MarkOnDeallocate(void* object) {
+ (*static_cast<int*>(object))++;
+}
+
+// A class that just implements MarkOnDeallocate on destruction.
+PPP_Class_Deprecated mark_on_deallocate_class = {
+ NULL, // HasProperty,
+ NULL, // HasMethod,
+ NULL, // GetProperty,
+ NULL, // GetAllPropertyNames,
+ NULL, // SetProperty,
+ NULL, // RemoveProperty,
+ NULL, // Call,
+ NULL, // Construct,
+ &MarkOnDeallocate
+};
+
+} // 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.
+ int32 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, GetHostObject) {
+ ProxyAutoLock lock;
+ 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().ReleaseVar(plugin_object);
+}
+
+TEST_F(PluginVarTrackerTest, ReceiveObjectPassRef) {
+ ProxyAutoLock lock;
+ 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().ReleaseVar(plugin_object);
+ EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
+ var_tracker().ReleaseVar(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) {
+ ProxyAutoLock lock;
+ 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().ReleaseVar(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().ReleaseVar(plugin_var);
+ EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_var));
+ EXPECT_EQ(host_object.value.as_id, GetObjectIDForUniqueReleaseObject());
+}
+
+TEST_F(PluginVarTrackerTest, RecursiveTrackWithNoRef) {
+ ProxyAutoLock lock;
+ 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));
+}
+
+// Tests that objects implemented by the plugin that have no references by
+// the plugin get their Deallocate function called on destruction.
+TEST_F(PluginVarTrackerTest, PluginObjectInstanceDeleted) {
+ ProxyAutoLock lock;
+ PP_Var host_object = MakeObject(12345);
+ PP_Instance pp_instance = 0x12345;
+
+ int deallocate_called = 0;
+ void* user_data = &deallocate_called;
+
+ // Make a var with one reference.
+ scoped_refptr<ProxyObjectVar> object(
+ new ProxyObjectVar(plugin_dispatcher(), host_object.value.as_id));
+ PP_Var plugin_var = MakeObject(var_tracker().AddVar(object.get()));
+ var_tracker().PluginImplementedObjectCreated(
+ pp_instance, plugin_var, &mark_on_deallocate_class, user_data);
+
+ // Release the plugin ref to the var. WebKit hasn't called destroy so
+ // we won't get a destroy call.
+ object = NULL;
+ var_tracker().ReleaseVar(plugin_var);
+ EXPECT_EQ(0, deallocate_called);
+
+ // Synthesize an instance destuction, this should call Deallocate.
+ var_tracker().DidDeleteInstance(pp_instance);
+ EXPECT_EQ(1, deallocate_called);
+}
+
+// Tests what happens when a plugin keeps a ref to a plugin-implemented
+// object var longer than the instance. We should not call the destructor until
+// the plugin releases its last ref.
+TEST_F(PluginVarTrackerTest, PluginObjectLeaked) {
+ ProxyAutoLock lock;
+ PP_Var host_object = MakeObject(12345);
+ PP_Instance pp_instance = 0x12345;
+
+ int deallocate_called = 0;
+ void* user_data = &deallocate_called;
+
+ // Make a var with one reference.
+ scoped_refptr<ProxyObjectVar> object(
+ new ProxyObjectVar(plugin_dispatcher(), host_object.value.as_id));
+ PP_Var plugin_var = MakeObject(var_tracker().AddVar(object.get()));
+ var_tracker().PluginImplementedObjectCreated(
+ pp_instance, plugin_var, &mark_on_deallocate_class, user_data);
+
+ // Destroy the instance. This should not call deallocate since the plugin
+ // still has a ref.
+ var_tracker().DidDeleteInstance(pp_instance);
+ EXPECT_EQ(0, deallocate_called);
+
+ // Release the plugin ref to the var. Since the instance is gone this should
+ // call deallocate.
+ object = NULL;
+ var_tracker().ReleaseVar(plugin_var);
+ EXPECT_EQ(1, deallocate_called);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppapi_command_buffer_proxy.cc b/chromium/ppapi/proxy/ppapi_command_buffer_proxy.cc
new file mode 100644
index 00000000000..8ca17e442d1
--- /dev/null
+++ b/chromium/ppapi/proxy/ppapi_command_buffer_proxy.cc
@@ -0,0 +1,259 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppapi_command_buffer_proxy.h"
+
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/proxy_channel.h"
+#include "ppapi/shared_impl/api_id.h"
+#include "ppapi/shared_impl/host_resource.h"
+
+namespace ppapi {
+namespace proxy {
+
+PpapiCommandBufferProxy::PpapiCommandBufferProxy(
+ const ppapi::HostResource& resource,
+ ProxyChannel* channel)
+ : resource_(resource),
+ channel_(channel) {
+}
+
+PpapiCommandBufferProxy::~PpapiCommandBufferProxy() {
+ // 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;
+ }
+}
+
+void PpapiCommandBufferProxy::ReportChannelError() {
+ if (!channel_error_callback_.is_null()) {
+ channel_error_callback_.Run();
+ channel_error_callback_.Reset();
+ }
+}
+
+int PpapiCommandBufferProxy::GetRouteID() const {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+bool PpapiCommandBufferProxy::Echo(const base::Closure& callback) {
+ return false;
+}
+
+bool PpapiCommandBufferProxy::ProduceFrontBuffer(const gpu::Mailbox& mailbox) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+void PpapiCommandBufferProxy::SetChannelErrorCallback(
+ const base::Closure& callback) {
+ channel_error_callback_ = callback;
+}
+
+bool PpapiCommandBufferProxy::Initialize() {
+ return true;
+}
+
+gpu::CommandBuffer::State PpapiCommandBufferProxy::GetState() {
+ // Send will flag state with lost context if IPC fails.
+ if (last_state_.error == gpu::error::kNoError) {
+ gpu::CommandBuffer::State state;
+ bool success = false;
+ if (Send(new PpapiHostMsg_PPBGraphics3D_GetState(
+ ppapi::API_ID_PPB_GRAPHICS_3D, resource_, &state, &success))) {
+ UpdateState(state, success);
+ }
+ }
+
+ return last_state_;
+}
+
+gpu::CommandBuffer::State PpapiCommandBufferProxy::GetLastState() {
+ // Note: The locking command buffer wrapper does not take a global lock before
+ // calling this function.
+ return last_state_;
+}
+
+int32 PpapiCommandBufferProxy::GetLastToken() {
+ // Note: The locking command buffer wrapper does not take a global lock before
+ // calling this function.
+ return last_state_.token;
+}
+
+void PpapiCommandBufferProxy::Flush(int32 put_offset) {
+ if (last_state_.error != gpu::error::kNoError)
+ return;
+
+ IPC::Message* message = new PpapiHostMsg_PPBGraphics3D_AsyncFlush(
+ ppapi::API_ID_PPB_GRAPHICS_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 PpapiCommandBufferProxy::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;
+ bool success = false;
+ if (Send(new PpapiHostMsg_PPBGraphics3D_Flush(
+ ppapi::API_ID_PPB_GRAPHICS_3D, resource_, put_offset,
+ last_known_get, &state, &success))) {
+ UpdateState(state, success);
+ }
+ }
+ } else {
+ Flush(put_offset);
+ }
+ return last_state_;
+}
+
+void PpapiCommandBufferProxy::SetGetBuffer(int32 transfer_buffer_id) {
+ if (last_state_.error == gpu::error::kNoError) {
+ Send(new PpapiHostMsg_PPBGraphics3D_SetGetBuffer(
+ ppapi::API_ID_PPB_GRAPHICS_3D, resource_, transfer_buffer_id));
+ }
+}
+
+void PpapiCommandBufferProxy::SetGetOffset(int32 get_offset) {
+ // Not implemented in proxy.
+ NOTREACHED();
+}
+
+gpu::Buffer PpapiCommandBufferProxy::CreateTransferBuffer(size_t size,
+ int32* id) {
+ *id = -1;
+
+ if (last_state_.error != gpu::error::kNoError)
+ return gpu::Buffer();
+
+ if (!Send(new PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer(
+ ppapi::API_ID_PPB_GRAPHICS_3D, resource_, size, id))) {
+ return gpu::Buffer();
+ }
+
+ if ((*id) <= 0)
+ return gpu::Buffer();
+
+ return GetTransferBuffer(*id);
+}
+
+void PpapiCommandBufferProxy::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);
+
+ if (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_PPBGraphics3D_DestroyTransferBuffer(
+ ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id));
+}
+
+gpu::Buffer PpapiCommandBufferProxy::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.
+ ppapi::proxy::SerializedHandle handle(
+ ppapi::proxy::SerializedHandle::SHARED_MEMORY);
+ if (!Send(new PpapiHostMsg_PPBGraphics3D_GetTransferBuffer(
+ ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id, &handle))) {
+ return gpu::Buffer();
+ }
+ if (!handle.is_shmem())
+ return gpu::Buffer();
+
+ // Cache the transfer buffer shared memory object client side.
+ scoped_ptr<base::SharedMemory> shared_memory(
+ new base::SharedMemory(handle.shmem(), false));
+
+ // Map the shared memory on demand.
+ if (!shared_memory->memory()) {
+ if (!shared_memory->Map(handle.size())) {
+ return gpu::Buffer();
+ }
+ }
+
+ gpu::Buffer buffer;
+ buffer.ptr = shared_memory->memory();
+ buffer.size = handle.size();
+ buffer.shared_memory = shared_memory.release();
+ transfer_buffers_[id] = buffer;
+
+ return buffer;
+}
+
+void PpapiCommandBufferProxy::SetToken(int32 token) {
+ NOTREACHED();
+}
+
+void PpapiCommandBufferProxy::SetParseError(gpu::error::Error error) {
+ NOTREACHED();
+}
+
+void PpapiCommandBufferProxy::SetContextLostReason(
+ gpu::error::ContextLostReason reason) {
+ NOTREACHED();
+}
+
+uint32 PpapiCommandBufferProxy::InsertSyncPoint() {
+ uint32 sync_point = 0;
+ if (last_state_.error == gpu::error::kNoError) {
+ Send(new PpapiHostMsg_PPBGraphics3D_InsertSyncPoint(
+ ppapi::API_ID_PPB_GRAPHICS_3D, resource_, &sync_point));
+ }
+ return sync_point;
+}
+
+bool PpapiCommandBufferProxy::Send(IPC::Message* msg) {
+ DCHECK(last_state_.error == gpu::error::kNoError);
+
+ if (channel_->Send(msg))
+ return true;
+
+ last_state_.error = gpu::error::kLostContext;
+ return false;
+}
+
+void PpapiCommandBufferProxy::UpdateState(
+ const gpu::CommandBuffer::State& state,
+ bool success) {
+ // Handle wraparound. It works as long as we don't have more than 2B state
+ // updates in flight across which reordering occurs.
+ if (success) {
+ if (state.generation - last_state_.generation < 0x80000000U) {
+ last_state_ = state;
+ }
+ } else {
+ last_state_.error = gpu::error::kLostContext;
+ ++last_state_.generation;
+ }
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppapi_command_buffer_proxy.h b/chromium/ppapi/proxy/ppapi_command_buffer_proxy.h
new file mode 100644
index 00000000000..b5c2c93081c
--- /dev/null
+++ b/chromium/ppapi/proxy/ppapi_command_buffer_proxy.h
@@ -0,0 +1,75 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_COMMAND_BUFFER_PROXY_H_
+#define PPAPI_PROXY_COMMAND_BUFFER_PROXY_H_
+
+#include "base/callback.h"
+#include "base/containers/hash_tables.h"
+#include "gpu/command_buffer/common/command_buffer.h"
+#include "gpu/ipc/command_buffer_proxy.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/host_resource.h"
+
+namespace IPC {
+class Message;
+}
+
+namespace ppapi {
+namespace proxy {
+
+class ProxyChannel;
+
+class PPAPI_PROXY_EXPORT PpapiCommandBufferProxy : public CommandBufferProxy {
+ public:
+ PpapiCommandBufferProxy(const HostResource& resource,
+ ProxyChannel* channel);
+ virtual ~PpapiCommandBufferProxy();
+
+ void ReportChannelError();
+
+ // CommandBufferProxy implementation:
+ virtual int GetRouteID() const OVERRIDE;
+ virtual bool Echo(const base::Closure& callback) OVERRIDE;
+ virtual bool ProduceFrontBuffer(const gpu::Mailbox& mailbox) OVERRIDE;
+ virtual void SetChannelErrorCallback(const base::Closure& callback) OVERRIDE;
+
+ // gpu::CommandBuffer implementation:
+ virtual bool Initialize();
+ virtual State GetState();
+ virtual State GetLastState();
+ virtual int32 GetLastToken();
+ virtual void Flush(int32 put_offset);
+ virtual State FlushSync(int32 put_offset, int32 last_known_get);
+ virtual void SetGetBuffer(int32 transfer_buffer_id);
+ virtual void SetGetOffset(int32 get_offset);
+ virtual gpu::Buffer CreateTransferBuffer(size_t size, int32* id);
+ virtual void DestroyTransferBuffer(int32 id);
+ virtual gpu::Buffer GetTransferBuffer(int32 id);
+ virtual void SetToken(int32 token);
+ virtual void SetParseError(gpu::error::Error error);
+ virtual void SetContextLostReason(gpu::error::ContextLostReason reason);
+ virtual uint32 InsertSyncPoint();
+
+ private:
+ bool Send(IPC::Message* msg);
+ void UpdateState(const gpu::CommandBuffer::State& state, bool success);
+
+ typedef base::hash_map<int32, gpu::Buffer> TransferBufferMap;
+ TransferBufferMap transfer_buffers_;
+
+ State last_state_;
+
+ HostResource resource_;
+ ProxyChannel* channel_;
+
+ base::Closure channel_error_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(PpapiCommandBufferProxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_COMMAND_BUFFER_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppapi_message_utils.h b/chromium/ppapi/proxy/ppapi_message_utils.h
new file mode 100644
index 00000000000..68667ddebd5
--- /dev/null
+++ b/chromium/ppapi/proxy/ppapi_message_utils.h
@@ -0,0 +1,131 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPAPI_MESSAGE_UTILS_H_
+#define PPAPI_PROXY_PPAPI_MESSAGE_UTILS_H_
+
+#include "base/basictypes.h"
+#include "base/pickle.h"
+#include "base/tuple.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_message_utils.h"
+
+namespace ppapi {
+
+namespace internal {
+
+// TupleTypeMatch* check whether a tuple type contains elements of the specified
+// types. They are used to make sure the output parameters of UnpackMessage()
+// match the corresponding message type.
+template <class TupleType, class A>
+struct TupleTypeMatch1 {
+ static const bool kValue = false;
+};
+template <class A>
+struct TupleTypeMatch1<Tuple1<A>, A> {
+ static const bool kValue = true;
+};
+
+template <class TupleType, class A, class B>
+struct TupleTypeMatch2 {
+ static const bool kValue = false;
+};
+template <class A, class B>
+struct TupleTypeMatch2<Tuple2<A, B>, A, B> {
+ static const bool kValue = true;
+};
+
+template <class TupleType, class A, class B, class C>
+struct TupleTypeMatch3 {
+ static const bool kValue = false;
+};
+template <class A, class B, class C>
+struct TupleTypeMatch3<Tuple3<A, B, C>, A, B, C> {
+ static const bool kValue = true;
+};
+
+template <class TupleType, class A, class B, class C, class D>
+struct TupleTypeMatch4 {
+ static const bool kValue = false;
+};
+template <class A, class B, class C, class D>
+struct TupleTypeMatch4<Tuple4<A, B, C, D>, A, B, C, D> {
+ static const bool kValue = true;
+};
+
+template <class TupleType, class A, class B, class C, class D, class E>
+struct TupleTypeMatch5 {
+ static const bool kValue = false;
+};
+template <class A, class B, class C, class D, class E>
+struct TupleTypeMatch5<Tuple5<A, B, C, D, E>, A, B, C, D, E> {
+ static const bool kValue = true;
+};
+
+} // namespace internal
+
+template <class MsgClass, class A>
+bool UnpackMessage(const IPC::Message& msg, A* a) {
+ COMPILE_ASSERT(
+ (internal::TupleTypeMatch1<typename MsgClass::Param, A>::kValue),
+ tuple_types_dont_match);
+
+ PickleIterator iter(msg);
+ return IPC::ReadParam(&msg, &iter, a);
+}
+
+template <class MsgClass, class A, class B>
+bool UnpackMessage(const IPC::Message& msg, A* a, B* b) {
+ COMPILE_ASSERT(
+ (internal::TupleTypeMatch2<typename MsgClass::Param, A, B>::kValue),
+ tuple_types_dont_match);
+
+ PickleIterator iter(msg);
+ return IPC::ReadParam(&msg, &iter, a) && IPC::ReadParam(&msg, &iter, b);
+}
+
+template <class MsgClass, class A, class B, class C>
+bool UnpackMessage(const IPC::Message& msg, A* a, B* b, C* c) {
+ COMPILE_ASSERT(
+ (internal::TupleTypeMatch3<typename MsgClass::Param, A, B, C>::kValue),
+ tuple_types_dont_match);
+
+ PickleIterator iter(msg);
+ return IPC::ReadParam(&msg, &iter, a) &&
+ IPC::ReadParam(&msg, &iter, b) &&
+ IPC::ReadParam(&msg, &iter, c);
+}
+
+template <class MsgClass, class A, class B, class C, class D>
+bool UnpackMessage(const IPC::Message& msg, A* a, B* b, C* c, D* d) {
+ COMPILE_ASSERT(
+ (internal::TupleTypeMatch4<typename MsgClass::Param, A, B, C, D>::kValue),
+ tuple_types_dont_match);
+
+ PickleIterator iter(msg);
+ return IPC::ReadParam(&msg, &iter, a) &&
+ IPC::ReadParam(&msg, &iter, b) &&
+ IPC::ReadParam(&msg, &iter, c) &&
+ IPC::ReadParam(&msg, &iter, d);
+}
+
+template <class MsgClass, class A, class B, class C, class D, class E>
+bool UnpackMessage(const IPC::Message& msg, A* a, B* b, C* c, D* d, E* e) {
+ COMPILE_ASSERT(
+ (internal::TupleTypeMatch5<
+ typename MsgClass::Param, A, B, C, D, E>::kValue),
+ tuple_types_dont_match);
+
+ PickleIterator iter(msg);
+ return IPC::ReadParam(&msg, &iter, a) &&
+ IPC::ReadParam(&msg, &iter, b) &&
+ IPC::ReadParam(&msg, &iter, c) &&
+ IPC::ReadParam(&msg, &iter, d) &&
+ IPC::ReadParam(&msg, &iter, e);
+}
+
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPAPI_MESSAGE_UTILS_H_
+
diff --git a/chromium/ppapi/proxy/ppapi_messages.cc b/chromium/ppapi/proxy/ppapi_messages.cc
new file mode 100644
index 00000000000..5cee1c78254
--- /dev/null
+++ b/chromium/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/chromium/ppapi/proxy/ppapi_messages.h b/chromium/ppapi/proxy/ppapi_messages.h
new file mode 100644
index 00000000000..3767f8f4c1c
--- /dev/null
+++ b/chromium/ppapi/proxy/ppapi_messages.h
@@ -0,0 +1,2060 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Multiply-included message header, no traditional include guard.
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "base/memory/shared_memory.h"
+#include "base/process/process.h"
+#include "base/strings/string16.h"
+#include "base/sync_socket.h"
+#include "base/values.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/dev/pp_video_capture_dev.h"
+#include "ppapi/c/dev/pp_video_dev.h"
+#include "ppapi/c/dev/ppb_truetype_font_dev.h"
+#include "ppapi/c/dev/ppb_url_util_dev.h"
+#include "ppapi/c/dev/ppp_printing_dev.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/pp_time.h"
+#include "ppapi/c/ppb_audio_config.h"
+#include "ppapi/c/ppb_image_data.h"
+#include "ppapi/c/ppb_tcp_socket.h"
+#include "ppapi/c/ppb_text_input_controller.h"
+#include "ppapi/c/ppb_udp_socket.h"
+#include "ppapi/c/private/pp_content_decryptor.h"
+#include "ppapi/c/private/pp_private_font_charset.h"
+#include "ppapi/c/private/ppb_flash.h"
+#include "ppapi/c/private/ppb_host_resolver_private.h"
+#include "ppapi/c/private/ppb_net_address_private.h"
+#include "ppapi/c/private/ppb_pdf.h"
+#include "ppapi/c/private/ppb_talk_private.h"
+#include "ppapi/c/private/ppp_flash_browser_operations.h"
+#include "ppapi/proxy/host_resolver_private_resource.h"
+#include "ppapi/proxy/ppapi_param_traits.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/proxy/resource_message_params.h"
+#include "ppapi/proxy/serialized_flash_menu.h"
+#include "ppapi/proxy/serialized_handle.h"
+#include "ppapi/proxy/serialized_structs.h"
+#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/shared_impl/dir_contents.h"
+#include "ppapi/shared_impl/file_path.h"
+#include "ppapi/shared_impl/file_ref_create_info.h"
+#include "ppapi/shared_impl/ppapi_nacl_channel_args.h"
+#include "ppapi/shared_impl/ppapi_preferences.h"
+#include "ppapi/shared_impl/ppb_device_ref_shared.h"
+#include "ppapi/shared_impl/ppb_input_event_shared.h"
+#include "ppapi/shared_impl/ppb_network_list_private_shared.h"
+#include "ppapi/shared_impl/ppb_view_shared.h"
+#include "ppapi/shared_impl/ppp_flash_browser_operations_shared.h"
+#include "ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h"
+#include "ppapi/shared_impl/socket_option_data.h"
+#include "ppapi/shared_impl/url_request_info_data.h"
+#include "ppapi/shared_impl/url_response_info_data.h"
+
+#undef IPC_MESSAGE_EXPORT
+#define IPC_MESSAGE_EXPORT PPAPI_PROXY_EXPORT
+
+#define IPC_MESSAGE_START PpapiMsgStart
+
+IPC_ENUM_TRAITS(PP_AudioSampleRate)
+IPC_ENUM_TRAITS(PP_DeviceType_Dev)
+IPC_ENUM_TRAITS(PP_DecryptorStreamType)
+IPC_ENUM_TRAITS(PP_FileSystemType)
+IPC_ENUM_TRAITS(PP_FileType)
+IPC_ENUM_TRAITS(PP_Flash_BrowserOperations_Permission)
+IPC_ENUM_TRAITS(PP_Flash_BrowserOperations_SettingType)
+IPC_ENUM_TRAITS(PP_FlashSetting)
+IPC_ENUM_TRAITS(PP_ImageDataFormat)
+IPC_ENUM_TRAITS(PP_InputEvent_MouseButton)
+IPC_ENUM_TRAITS(PP_InputEvent_Type)
+IPC_ENUM_TRAITS_MAX_VALUE(PP_NetAddressFamily_Private,
+ PP_NETADDRESSFAMILY_PRIVATE_IPV6)
+IPC_ENUM_TRAITS(PP_NetworkListState_Private)
+IPC_ENUM_TRAITS(PP_NetworkListType_Private)
+IPC_ENUM_TRAITS(PP_PrintOrientation_Dev)
+IPC_ENUM_TRAITS(PP_PrintOutputFormat_Dev)
+IPC_ENUM_TRAITS(PP_PrintScalingOption_Dev)
+IPC_ENUM_TRAITS(PP_PrivateFontCharset)
+IPC_ENUM_TRAITS(PP_ResourceImage)
+IPC_ENUM_TRAITS(PP_ResourceString)
+IPC_ENUM_TRAITS_MAX_VALUE(PP_TalkEvent, PP_TALKEVENT_NUM_EVENTS - 1)
+IPC_ENUM_TRAITS_MAX_VALUE(PP_TalkPermission,
+ PP_TALKPERMISSION_NUM_PERMISSIONS - 1)
+IPC_ENUM_TRAITS_MAX_VALUE(PP_TCPSocket_Option,
+ PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE)
+IPC_ENUM_TRAITS(PP_TextInput_Type)
+IPC_ENUM_TRAITS(PP_TrueTypeFontFamily_Dev)
+IPC_ENUM_TRAITS(PP_TrueTypeFontStyle_Dev)
+IPC_ENUM_TRAITS(PP_TrueTypeFontWeight_Dev)
+IPC_ENUM_TRAITS(PP_TrueTypeFontWidth_Dev)
+IPC_ENUM_TRAITS(PP_TrueTypeFontCharset_Dev)
+IPC_ENUM_TRAITS_MAX_VALUE(PP_UDPSocket_Option,
+ PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE)
+IPC_ENUM_TRAITS(PP_VideoDecodeError_Dev)
+IPC_ENUM_TRAITS(PP_VideoDecoder_Profile)
+
+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(PP_ImageDataDesc)
+ IPC_STRUCT_TRAITS_MEMBER(format)
+ IPC_STRUCT_TRAITS_MEMBER(size)
+ IPC_STRUCT_TRAITS_MEMBER(stride)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(PP_PictureBuffer_Dev)
+ IPC_STRUCT_TRAITS_MEMBER(id)
+ IPC_STRUCT_TRAITS_MEMBER(size)
+ IPC_STRUCT_TRAITS_MEMBER(texture_id)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(PP_Picture_Dev)
+ IPC_STRUCT_TRAITS_MEMBER(picture_buffer_id)
+ IPC_STRUCT_TRAITS_MEMBER(bitstream_buffer_id)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(PP_PrintPageNumberRange_Dev)
+ IPC_STRUCT_TRAITS_MEMBER(first_page_number)
+ IPC_STRUCT_TRAITS_MEMBER(last_page_number)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(PP_VideoCaptureDeviceInfo_Dev)
+ IPC_STRUCT_TRAITS_MEMBER(width)
+ IPC_STRUCT_TRAITS_MEMBER(height)
+ IPC_STRUCT_TRAITS_MEMBER(frames_per_second)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(PP_HostResolver_Private_Hint)
+ IPC_STRUCT_TRAITS_MEMBER(family)
+ IPC_STRUCT_TRAITS_MEMBER(flags)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(PP_PrintSettings_Dev)
+ IPC_STRUCT_TRAITS_MEMBER(printable_area)
+ IPC_STRUCT_TRAITS_MEMBER(content_area)
+ IPC_STRUCT_TRAITS_MEMBER(paper_size)
+ IPC_STRUCT_TRAITS_MEMBER(dpi)
+ IPC_STRUCT_TRAITS_MEMBER(orientation)
+ IPC_STRUCT_TRAITS_MEMBER(print_scaling_option)
+ IPC_STRUCT_TRAITS_MEMBER(grayscale)
+ IPC_STRUCT_TRAITS_MEMBER(format)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(PP_URLComponent_Dev)
+ IPC_STRUCT_TRAITS_MEMBER(begin)
+ IPC_STRUCT_TRAITS_MEMBER(len)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(PP_URLComponents_Dev)
+ IPC_STRUCT_TRAITS_MEMBER(scheme)
+ IPC_STRUCT_TRAITS_MEMBER(username)
+ IPC_STRUCT_TRAITS_MEMBER(password)
+ IPC_STRUCT_TRAITS_MEMBER(host)
+ IPC_STRUCT_TRAITS_MEMBER(port)
+ IPC_STRUCT_TRAITS_MEMBER(path)
+ IPC_STRUCT_TRAITS_MEMBER(query)
+ IPC_STRUCT_TRAITS_MEMBER(ref)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(ppapi::DeviceRefData)
+ IPC_STRUCT_TRAITS_MEMBER(type)
+ IPC_STRUCT_TRAITS_MEMBER(name)
+ IPC_STRUCT_TRAITS_MEMBER(id)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(ppapi::DirEntry)
+ IPC_STRUCT_TRAITS_MEMBER(name)
+ IPC_STRUCT_TRAITS_MEMBER(is_dir)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(ppapi::FileRef_CreateInfo)
+ IPC_STRUCT_TRAITS_MEMBER(file_system_type)
+ IPC_STRUCT_TRAITS_MEMBER(internal_path)
+ IPC_STRUCT_TRAITS_MEMBER(display_name)
+ IPC_STRUCT_TRAITS_MEMBER(pending_host_resource_id)
+ IPC_STRUCT_TRAITS_MEMBER(file_system_plugin_resource)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(ppapi::FlashSiteSetting)
+ IPC_STRUCT_TRAITS_MEMBER(site)
+ IPC_STRUCT_TRAITS_MEMBER(permission)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(ppapi::ViewData)
+ IPC_STRUCT_TRAITS_MEMBER(rect)
+ IPC_STRUCT_TRAITS_MEMBER(is_fullscreen)
+ IPC_STRUCT_TRAITS_MEMBER(is_page_visible)
+ IPC_STRUCT_TRAITS_MEMBER(clip_rect)
+ IPC_STRUCT_TRAITS_MEMBER(device_scale)
+ IPC_STRUCT_TRAITS_MEMBER(css_scale)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(PP_TouchPoint)
+ IPC_STRUCT_TRAITS_MEMBER(id)
+ IPC_STRUCT_TRAITS_MEMBER(position)
+ IPC_STRUCT_TRAITS_MEMBER(radius)
+ IPC_STRUCT_TRAITS_MEMBER(rotation_angle)
+ IPC_STRUCT_TRAITS_MEMBER(pressure)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(ppapi::Preferences)
+ IPC_STRUCT_TRAITS_MEMBER(standard_font_family_map)
+ IPC_STRUCT_TRAITS_MEMBER(fixed_font_family_map)
+ IPC_STRUCT_TRAITS_MEMBER(serif_font_family_map)
+ IPC_STRUCT_TRAITS_MEMBER(sans_serif_font_family_map)
+ IPC_STRUCT_TRAITS_MEMBER(default_font_size)
+ IPC_STRUCT_TRAITS_MEMBER(default_fixed_font_size)
+ IPC_STRUCT_TRAITS_MEMBER(number_of_cpu_cores)
+ IPC_STRUCT_TRAITS_MEMBER(is_3d_supported)
+ IPC_STRUCT_TRAITS_MEMBER(is_stage3d_supported)
+ IPC_STRUCT_TRAITS_MEMBER(is_stage3d_baseline_supported)
+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(mouse_movement)
+ 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(usb_key_code)
+ IPC_STRUCT_TRAITS_MEMBER(character_text)
+ IPC_STRUCT_TRAITS_MEMBER(composition_segment_offsets)
+ IPC_STRUCT_TRAITS_MEMBER(composition_target_segment)
+ IPC_STRUCT_TRAITS_MEMBER(composition_selection_start)
+ IPC_STRUCT_TRAITS_MEMBER(composition_selection_end)
+ IPC_STRUCT_TRAITS_MEMBER(touches)
+ IPC_STRUCT_TRAITS_MEMBER(changed_touches)
+ IPC_STRUCT_TRAITS_MEMBER(target_touches)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(ppapi::HostPortPair)
+ IPC_STRUCT_TRAITS_MEMBER(host)
+ IPC_STRUCT_TRAITS_MEMBER(port)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(ppapi::URLRequestInfoData)
+ IPC_STRUCT_TRAITS_MEMBER(url)
+ IPC_STRUCT_TRAITS_MEMBER(method)
+ IPC_STRUCT_TRAITS_MEMBER(headers)
+ IPC_STRUCT_TRAITS_MEMBER(stream_to_file)
+ IPC_STRUCT_TRAITS_MEMBER(follow_redirects)
+ IPC_STRUCT_TRAITS_MEMBER(record_download_progress)
+ IPC_STRUCT_TRAITS_MEMBER(record_upload_progress)
+ IPC_STRUCT_TRAITS_MEMBER(has_custom_referrer_url)
+ IPC_STRUCT_TRAITS_MEMBER(custom_referrer_url)
+ IPC_STRUCT_TRAITS_MEMBER(allow_cross_origin_requests)
+ IPC_STRUCT_TRAITS_MEMBER(allow_credentials)
+ IPC_STRUCT_TRAITS_MEMBER(has_custom_content_transfer_encoding)
+ IPC_STRUCT_TRAITS_MEMBER(custom_content_transfer_encoding)
+ IPC_STRUCT_TRAITS_MEMBER(prefetch_buffer_upper_threshold)
+ IPC_STRUCT_TRAITS_MEMBER(prefetch_buffer_lower_threshold)
+ IPC_STRUCT_TRAITS_MEMBER(has_custom_user_agent)
+ IPC_STRUCT_TRAITS_MEMBER(custom_user_agent)
+ IPC_STRUCT_TRAITS_MEMBER(body)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(ppapi::URLRequestInfoData::BodyItem)
+ IPC_STRUCT_TRAITS_MEMBER(is_file)
+ IPC_STRUCT_TRAITS_MEMBER(data)
+ // Note: we don't serialize file_ref.
+ IPC_STRUCT_TRAITS_MEMBER(file_ref_host_resource)
+ IPC_STRUCT_TRAITS_MEMBER(start_offset)
+ IPC_STRUCT_TRAITS_MEMBER(number_of_bytes)
+ IPC_STRUCT_TRAITS_MEMBER(expected_last_modified_time)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(ppapi::URLResponseInfoData)
+ IPC_STRUCT_TRAITS_MEMBER(url)
+ IPC_STRUCT_TRAITS_MEMBER(headers)
+ IPC_STRUCT_TRAITS_MEMBER(status_code)
+ IPC_STRUCT_TRAITS_MEMBER(status_text)
+ IPC_STRUCT_TRAITS_MEMBER(redirect_url)
+ IPC_STRUCT_TRAITS_MEMBER(body_as_file_ref)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(ppapi::NetworkInfo)
+ IPC_STRUCT_TRAITS_MEMBER(name)
+ IPC_STRUCT_TRAITS_MEMBER(type)
+ IPC_STRUCT_TRAITS_MEMBER(state)
+ IPC_STRUCT_TRAITS_MEMBER(addresses)
+ IPC_STRUCT_TRAITS_MEMBER(display_name)
+ IPC_STRUCT_TRAITS_MEMBER(mtu)
+IPC_STRUCT_TRAITS_END()
+
+// Only whitelisted switches passed through NaClChannelArgs.
+// The list of switches can be found in:
+// chrome/browser/nacl_host/nacl_process_host.cc
+IPC_STRUCT_TRAITS_BEGIN(ppapi::PpapiNaClChannelArgs)
+ IPC_STRUCT_TRAITS_MEMBER(off_the_record)
+ IPC_STRUCT_TRAITS_MEMBER(permissions)
+ IPC_STRUCT_TRAITS_MEMBER(switch_names)
+ IPC_STRUCT_TRAITS_MEMBER(switch_values)
+IPC_STRUCT_TRAITS_END()
+
+#if !defined(OS_NACL) && !defined(NACL_WIN64)
+
+IPC_STRUCT_TRAITS_BEGIN(ppapi::proxy::PPPDecryptor_Buffer)
+ IPC_STRUCT_TRAITS_MEMBER(resource)
+ IPC_STRUCT_TRAITS_MEMBER(handle)
+ IPC_STRUCT_TRAITS_MEMBER(size)
+IPC_STRUCT_TRAITS_END()
+
+#endif // !defined(OS_NACL) && !defined(NACL_WIN64)
+
+// These are from the browser to the plugin.
+// Loads the given plugin.
+IPC_MESSAGE_CONTROL2(PpapiMsg_LoadPlugin,
+ base::FilePath /* path */,
+ ppapi::PpapiPermissions /* permissions */)
+
+// Creates a channel to talk to a renderer. The plugin will respond with
+// PpapiHostMsg_ChannelCreated.
+IPC_MESSAGE_CONTROL3(PpapiMsg_CreateChannel,
+ base::ProcessId /* renderer_pid */,
+ int /* renderer_child_id */,
+ bool /* incognito */)
+
+// Creates a channel to talk to a renderer. This message is only used by the
+// NaCl IPC proxy. It is intercepted by NaClIPCAdapter, which creates the
+// actual channel and rewrites the message for the untrusted side.
+IPC_MESSAGE_CONTROL3(PpapiMsg_CreateNaClChannel,
+ int /* renderer_id */,
+ ppapi::PpapiNaClChannelArgs /* args */,
+ ppapi::proxy::SerializedHandle /* channel_handle */)
+
+// Instructs the plugin process to crash.
+IPC_MESSAGE_CONTROL0(PpapiMsg_Crash)
+
+// Instructs the plugin process to hang.
+IPC_MESSAGE_CONTROL0(PpapiMsg_Hang)
+
+// 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)
+
+// 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 */)
+
+#if !defined(OS_NACL) && !defined(NACL_WIN64)
+// Network state notification from the browser for implementing
+// PPP_NetworkState_Dev.
+IPC_MESSAGE_CONTROL1(PpapiMsg_SetNetworkState,
+ bool /* online */)
+
+// Requests a list of sites that have data stored from the plugin. The plugin
+// process will respond with PpapiHostMsg_GetSitesWithDataResult. This is used
+// for Flash.
+IPC_MESSAGE_CONTROL2(PpapiMsg_GetSitesWithData,
+ uint32 /* request_id */,
+ base::FilePath /* plugin_data_path */)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_GetSitesWithDataResult,
+ uint32 /* request_id */,
+ std::vector<std::string> /* sites */)
+
+// Instructs the plugin to clear data for the given site & time. The plugin
+// process will respond with PpapiHostMsg_ClearSiteDataResult. This is used
+// for Flash.
+IPC_MESSAGE_CONTROL5(PpapiMsg_ClearSiteData,
+ uint32 /* request_id */,
+ base::FilePath /* plugin_data_path */,
+ std::string /* site */,
+ uint64 /* flags */,
+ uint64 /* max_age */)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_ClearSiteDataResult,
+ uint32 /* request_id */,
+ bool /* success */)
+
+IPC_MESSAGE_CONTROL2(PpapiMsg_DeauthorizeContentLicenses,
+ uint32 /* request_id */,
+ base::FilePath /* plugin_data_path */)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_DeauthorizeContentLicensesResult,
+ uint32 /* request_id */,
+ bool /* success */)
+
+IPC_MESSAGE_CONTROL3(PpapiMsg_GetPermissionSettings,
+ uint32 /* request_id */,
+ base::FilePath /* plugin_data_path */,
+ PP_Flash_BrowserOperations_SettingType /* setting_type */)
+IPC_MESSAGE_CONTROL4(
+ PpapiHostMsg_GetPermissionSettingsResult,
+ uint32 /* request_id */,
+ bool /* success */,
+ PP_Flash_BrowserOperations_Permission /* default_permission */,
+ ppapi::FlashSiteSettings /* sites */)
+
+IPC_MESSAGE_CONTROL5(PpapiMsg_SetDefaultPermission,
+ uint32 /* request_id */,
+ base::FilePath /* plugin_data_path */,
+ PP_Flash_BrowserOperations_SettingType /* setting_type */,
+ PP_Flash_BrowserOperations_Permission /* permission */,
+ bool /* clear_site_specific */)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_SetDefaultPermissionResult,
+ uint32 /* request_id */,
+ bool /* success */)
+
+IPC_MESSAGE_CONTROL4(PpapiMsg_SetSitePermission,
+ uint32 /* request_id */,
+ base::FilePath /* plugin_data_path */,
+ PP_Flash_BrowserOperations_SettingType /* setting_type */,
+ ppapi::FlashSiteSettings /* sites */)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_SetSitePermissionResult,
+ uint32 /* request_id */,
+ bool /* success */)
+
+// Broker Process.
+IPC_SYNC_MESSAGE_CONTROL2_1(PpapiMsg_ConnectToPlugin,
+ PP_Instance /* instance */,
+ IPC::PlatformFileForTransit /* handle */,
+ int32_t /* result */)
+#endif // !defined(OS_NACL) && !defined(NACL_WIN64)
+
+// 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_ROUTED4(PpapiMsg_PPBAudio_NotifyAudioStreamCreated,
+ ppapi::HostResource /* audio_id */,
+ int32_t /* result_code (will be != PP_OK on failure) */,
+ ppapi::proxy::SerializedHandle /* socket_handle */,
+ ppapi::proxy::SerializedHandle /* handle */)
+
+// PPB_FileRef.
+// TODO(teravest): Remove these messages when we've switched over to the "new"
+// proxy.
+IPC_MESSAGE_ROUTED3(
+ PpapiMsg_PPBFileRef_CallbackComplete,
+ ppapi::HostResource /* resource */,
+ uint32_t /* callback_id */,
+ int32_t /* result */)
+
+IPC_MESSAGE_ROUTED4(
+ PpapiMsg_PPBFileRef_QueryCallbackComplete,
+ ppapi::HostResource /* resource */,
+ PP_FileInfo /* file_info */,
+ uint32_t /* callback_id */,
+ int32_t /* result */)
+
+IPC_MESSAGE_ROUTED5(
+ PpapiMsg_PPBFileRef_ReadDirectoryEntriesCallbackComplete,
+ ppapi::HostResource /* resource */,
+ std::vector<ppapi::PPB_FileRef_CreateInfo> /* files */,
+ std::vector<PP_FileType> /* file_types */,
+ uint32_t /* callback_id */,
+ int32_t /* result */)
+
+// PPB_FileSystem.
+IPC_MESSAGE_ROUTED2(
+ PpapiMsg_PPBFileSystem_OpenComplete,
+ ppapi::HostResource /* filesystem */,
+ int32_t /* result */)
+
+// PPB_Graphics3D.
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPBGraphics3D_SwapBuffersACK,
+ ppapi::HostResource /* graphics_3d */,
+ int32_t /* pp_error */)
+
+// PPB_ImageData.
+IPC_MESSAGE_ROUTED1(PpapiMsg_PPBImageData_NotifyUnusedImageData,
+ ppapi::HostResource /* old_image_data */)
+
+// PPB_Instance.
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPBInstance_MouseLockComplete,
+ PP_Instance /* instance */,
+ int32_t /* result */)
+
+// PPP_Class.
+IPC_SYNC_MESSAGE_ROUTED3_2(PpapiMsg_PPPClass_HasProperty,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ ppapi::proxy::SerializedVar /* property */,
+ ppapi::proxy::SerializedVar /* out_exception */,
+ bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED3_2(PpapiMsg_PPPClass_HasMethod,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ ppapi::proxy::SerializedVar /* method */,
+ ppapi::proxy::SerializedVar /* out_exception */,
+ bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED3_2(PpapiMsg_PPPClass_GetProperty,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ ppapi::proxy::SerializedVar /* property */,
+ ppapi::proxy::SerializedVar /* out_exception */,
+ ppapi::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_2(PpapiMsg_PPPClass_EnumerateProperties,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ std::vector<ppapi::proxy::SerializedVar> /* props */,
+ ppapi::proxy::SerializedVar /* out_exception */)
+IPC_SYNC_MESSAGE_ROUTED4_1(PpapiMsg_PPPClass_SetProperty,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ ppapi::proxy::SerializedVar /* name */,
+ ppapi::proxy::SerializedVar /* value */,
+ ppapi::proxy::SerializedVar /* out_exception */)
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiMsg_PPPClass_RemoveProperty,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ ppapi::proxy::SerializedVar /* property */,
+ ppapi::proxy::SerializedVar /* out_exception */)
+IPC_SYNC_MESSAGE_ROUTED4_2(PpapiMsg_PPPClass_Call,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ ppapi::proxy::SerializedVar /* method_name */,
+ std::vector<ppapi::proxy::SerializedVar> /* args */,
+ ppapi::proxy::SerializedVar /* out_exception */,
+ ppapi::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED3_2(PpapiMsg_PPPClass_Construct,
+ int64 /* ppp_class */,
+ int64 /* object */,
+ std::vector<ppapi::proxy::SerializedVar> /* args */,
+ ppapi::proxy::SerializedVar /* out_exception */,
+ ppapi::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_ROUTED3(PpapiMsg_PPPInstance_DidChangeView,
+ PP_Instance /* instance */,
+ ppapi::ViewData /* new_data */,
+ PP_Bool /* flash_fullscreen */)
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPPInstance_DidChangeFocus,
+ PP_Instance /* instance */,
+ PP_Bool /* has_focus */)
+IPC_MESSAGE_ROUTED3(PpapiMsg_PPPInstance_HandleDocumentLoad,
+ PP_Instance /* instance */,
+ int /* pending_loader_host_id */,
+ ppapi::URLResponseInfoData /* response */)
+
+// PPP_Messaging.
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPPMessaging_HandleMessage,
+ PP_Instance /* instance */,
+ ppapi::proxy::SerializedVar /* message */)
+
+// PPP_MouseLock.
+IPC_MESSAGE_ROUTED1(PpapiMsg_PPPMouseLock_MouseLockLost,
+ PP_Instance /* instance */)
+
+// PPB_NetworkMonitor_Private.
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPBNetworkMonitor_NetworkList,
+ uint32 /* plugin_dispatcher_id */,
+ ppapi::NetworkList /* network_list */)
+
+// PPP_Printing
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiMsg_PPPPrinting_QuerySupportedFormats,
+ PP_Instance /* instance */,
+ uint32_t /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiMsg_PPPPrinting_Begin,
+ PP_Instance /* instance */,
+ std::string /* settings_string */,
+ int32_t /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiMsg_PPPPrinting_PrintPages,
+ PP_Instance /* instance */,
+ std::vector<PP_PrintPageNumberRange_Dev> /* pages */,
+ ppapi::HostResource /* result */)
+IPC_MESSAGE_ROUTED1(PpapiMsg_PPPPrinting_End,
+ PP_Instance /* instance */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiMsg_PPPPrinting_IsScalingDisabled,
+ PP_Instance /* instance */,
+ bool /* result */)
+
+// PPP_TextInput.
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPPTextInput_RequestSurroundingText,
+ PP_Instance /* instance */,
+ uint32_t /* desired_number_of_characters */)
+
+#if !defined(OS_NACL) && !defined(NACL_WIN64)
+// PPB_Broker.
+IPC_MESSAGE_ROUTED3(
+ PpapiMsg_PPBBroker_ConnectComplete,
+ ppapi::HostResource /* broker */,
+ IPC::PlatformFileForTransit /* handle */,
+ int32_t /* result */)
+
+// PPP_ContentDecryptor_Dev
+IPC_MESSAGE_ROUTED4(PpapiMsg_PPPContentDecryptor_GenerateKeyRequest,
+ PP_Instance /* instance */,
+ ppapi::proxy::SerializedVar /* key_system, String */,
+ ppapi::proxy::SerializedVar /* type, String */,
+ ppapi::proxy::SerializedVar /* init_data, ArrayBuffer */)
+IPC_MESSAGE_ROUTED4(PpapiMsg_PPPContentDecryptor_AddKey,
+ PP_Instance /* instance */,
+ ppapi::proxy::SerializedVar /* session_id, String */,
+ ppapi::proxy::SerializedVar /* key, ArrayBuffer */,
+ ppapi::proxy::SerializedVar /* init_data, ArrayBuffer */)
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPPContentDecryptor_CancelKeyRequest,
+ PP_Instance /* instance */,
+ ppapi::proxy::SerializedVar /* session_id, String */)
+IPC_MESSAGE_ROUTED3(PpapiMsg_PPPContentDecryptor_Decrypt,
+ PP_Instance /* instance */,
+ ppapi::proxy::PPPDecryptor_Buffer /* buffer */,
+ std::string /* serialized_block_info */)
+IPC_MESSAGE_ROUTED3(
+ PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder,
+ PP_Instance /* instance */,
+ std::string /* serialized_decoder_config */,
+ ppapi::proxy::PPPDecryptor_Buffer /* extra_data_buffer */)
+IPC_MESSAGE_ROUTED3(
+ PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder,
+ PP_Instance /* instance */,
+ std::string /* serialized_decoder_config */,
+ ppapi::proxy::PPPDecryptor_Buffer /* extra_data_buffer. */)
+IPC_MESSAGE_ROUTED3(PpapiMsg_PPPContentDecryptor_DeinitializeDecoder,
+ PP_Instance /* instance */,
+ PP_DecryptorStreamType /* decoder_type */,
+ uint32_t /* request_id */)
+IPC_MESSAGE_ROUTED3(PpapiMsg_PPPContentDecryptor_ResetDecoder,
+ PP_Instance /* instance */,
+ PP_DecryptorStreamType /* decoder_type */,
+ uint32_t /* request_id */)
+IPC_MESSAGE_ROUTED4(PpapiMsg_PPPContentDecryptor_DecryptAndDecode,
+ PP_Instance /* instance */,
+ PP_DecryptorStreamType /* decoder_type */,
+ ppapi::proxy::PPPDecryptor_Buffer /* buffer */,
+ std::string /* serialized_block_info */)
+#endif // !defined(OS_NACL) && !defined(NACL_WIN64)
+
+// PPB_TCPSocket and PPB_TCPSocket_Private.
+IPC_MESSAGE_ROUTED5(PpapiMsg_PPBTCPSocket_ConnectACK,
+ uint32 /* plugin_dispatcher_id */,
+ uint32 /* socket_id */,
+ int32_t /* result */,
+ PP_NetAddress_Private /* local_addr */,
+ PP_NetAddress_Private /* remote_addr */)
+IPC_MESSAGE_ROUTED4(PpapiMsg_PPBTCPSocket_SSLHandshakeACK,
+ uint32 /* plugin_dispatcher_id */,
+ uint32 /* socket_id */,
+ bool /* succeeded */,
+ ppapi::PPB_X509Certificate_Fields /* certificate_fields */)
+IPC_MESSAGE_ROUTED4(PpapiMsg_PPBTCPSocket_ReadACK,
+ uint32 /* plugin_dispatcher_id */,
+ uint32 /* socket_id */,
+ int32_t /* result */,
+ std::string /* data */)
+IPC_MESSAGE_ROUTED3(PpapiMsg_PPBTCPSocket_WriteACK,
+ uint32 /* plugin_dispatcher_id */,
+ uint32 /* socket_id */,
+ int32_t /* result */)
+IPC_MESSAGE_ROUTED3(PpapiMsg_PPBTCPSocket_SetOptionACK,
+ uint32 /* plugin_dispatcher_id */,
+ uint32 /* socket_id */,
+ int32_t /* result */)
+
+#if !defined(OS_NACL) && !defined(NACL_WIN64)
+// PPP_Instance_Private.
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiMsg_PPPInstancePrivate_GetInstanceObject,
+ PP_Instance /* instance */,
+ ppapi::proxy::SerializedVar /* result */)
+
+// PPB_VideoDecoder_Dev.
+// (Messages from renderer to plugin to notify it to run callbacks.)
+IPC_MESSAGE_ROUTED3(PpapiMsg_PPBVideoDecoder_EndOfBitstreamACK,
+ ppapi::HostResource /* video_decoder */,
+ int32_t /* bitstream buffer id */,
+ int32_t /* PP_CompletionCallback result */)
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPBVideoDecoder_FlushACK,
+ ppapi::HostResource /* video_decoder */,
+ int32_t /* PP_CompletionCallback result */)
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPBVideoDecoder_ResetACK,
+ ppapi::HostResource /* video_decoder */,
+ int32_t /* PP_CompletionCallback result */)
+
+// PPP_VideoDecoder_Dev.
+IPC_MESSAGE_ROUTED4(PpapiMsg_PPPVideoDecoder_ProvidePictureBuffers,
+ ppapi::HostResource /* video_decoder */,
+ uint32_t /* requested number of buffers */,
+ PP_Size /* dimensions of buffers */,
+ uint32_t /* texture_target */)
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_DismissPictureBuffer,
+ ppapi::HostResource /* video_decoder */,
+ int32_t /* picture buffer id */)
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_PictureReady,
+ ppapi::HostResource /* video_decoder */,
+ PP_Picture_Dev /* output picture */)
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_NotifyError,
+ ppapi::HostResource /* video_decoder */,
+ PP_VideoDecodeError_Dev /* error */)
+#endif // !defined(OS_NACL) && !defined(NACL_WIN64)
+
+// -----------------------------------------------------------------------------
+// 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 */)
+
+// Logs the given message to the console of all instances.
+IPC_MESSAGE_CONTROL4(PpapiHostMsg_LogWithSource,
+ PP_Instance /* instance */,
+ int /* log_level */,
+ std::string /* source */,
+ std::string /* value */)
+
+// PPB_Audio.
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBAudio_Create,
+ PP_Instance /* instance_id */,
+ int32_t /* sample_rate */,
+ uint32_t /* sample_frame_count */,
+ ppapi::HostResource /* result */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBAudio_StartOrStop,
+ ppapi::HostResource /* audio_id */,
+ bool /* play */)
+
+// PPB_Core.
+IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBCore_AddRefResource,
+ ppapi::HostResource)
+IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBCore_ReleaseResource,
+ ppapi::HostResource)
+
+// PPB_FileRef.
+// TODO(teravest): Remove these messages when we've switched over to the "new"
+// proxy.
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBFileRef_Create,
+ PP_Instance /* instance */,
+ PP_Resource /* file_system */,
+ std::string /* path */,
+ ppapi::PPB_FileRef_CreateInfo /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFileRef_GetParent,
+ ppapi::HostResource /* file_ref */,
+ ppapi::PPB_FileRef_CreateInfo /* result */)
+IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBFileRef_MakeDirectory,
+ ppapi::HostResource /* file_ref */,
+ PP_Bool /* make_ancestors */,
+ uint32_t /* callback_id */)
+IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBFileRef_Touch,
+ ppapi::HostResource /* file_ref */,
+ PP_Time /* last_access */,
+ PP_Time /* last_modified */,
+ uint32_t /* callback_id */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBFileRef_Delete,
+ ppapi::HostResource /* file_ref */,
+ uint32_t /* callback_id */)
+IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBFileRef_Rename,
+ ppapi::HostResource /* file_ref */,
+ ppapi::HostResource /* new_file_ref */,
+ uint32_t /* callback_id */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBFileRef_Query,
+ ppapi::HostResource /* file_ref */,
+ uint32_t /* callback_id */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFileRef_GetAbsolutePath,
+ ppapi::HostResource /* file_ref */,
+ ppapi::proxy::SerializedVar /* result */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBFileRef_ReadDirectoryEntries,
+ ppapi::HostResource /* file_ref */,
+ uint32_t /* callback_id */)
+
+// PPB_Graphics3D.
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBGraphics3D_Create,
+ PP_Instance /* instance */,
+ ppapi::HostResource /* share_context */,
+ std::vector<int32_t> /* attrib_list */,
+ ppapi::HostResource /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_0(PpapiHostMsg_PPBGraphics3D_SetGetBuffer,
+ ppapi::HostResource /* context */,
+ int32 /* transfer_buffer_id */)
+IPC_SYNC_MESSAGE_ROUTED1_2(PpapiHostMsg_PPBGraphics3D_GetState,
+ ppapi::HostResource /* context */,
+ gpu::CommandBuffer::State /* state */,
+ bool /* success */)
+IPC_SYNC_MESSAGE_ROUTED3_2(PpapiHostMsg_PPBGraphics3D_Flush,
+ ppapi::HostResource /* context */,
+ int32 /* put_offset */,
+ int32 /* last_known_get */,
+ gpu::CommandBuffer::State /* state */,
+ bool /* success */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBGraphics3D_AsyncFlush,
+ ppapi::HostResource /* context */,
+ int32 /* put_offset */)
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer,
+ ppapi::HostResource /* context */,
+ uint32 /* size */,
+ int32 /* id */)
+IPC_SYNC_MESSAGE_ROUTED2_0(PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer,
+ ppapi::HostResource /* context */,
+ int32 /* id */)
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBGraphics3D_GetTransferBuffer,
+ ppapi::HostResource /* context */,
+ int32 /* id */,
+ ppapi::proxy::SerializedHandle /* transfer_buffer */)
+IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBGraphics3D_SwapBuffers,
+ ppapi::HostResource /* graphics_3d */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBGraphics3D_InsertSyncPoint,
+ ppapi::HostResource /* context */,
+ uint32 /* sync_point */)
+
+// PPB_ImageData.
+IPC_SYNC_MESSAGE_ROUTED4_3(PpapiHostMsg_PPBImageData_CreatePlatform,
+ PP_Instance /* instance */,
+ int32 /* format */,
+ PP_Size /* size */,
+ PP_Bool /* init_to_zero */,
+ ppapi::HostResource /* result_resource */,
+ PP_ImageDataDesc /* image_data_desc */,
+ ppapi::proxy::ImageHandle /* result */)
+IPC_SYNC_MESSAGE_ROUTED4_3(PpapiHostMsg_PPBImageData_CreateSimple,
+ PP_Instance /* instance */,
+ int32 /* format */,
+ PP_Size /* size */,
+ PP_Bool /* init_to_zero */,
+ ppapi::HostResource /* result_resource */,
+ PP_ImageDataDesc /* image_data_desc */,
+ ppapi::proxy::SerializedHandle /* result */)
+
+// PPB_Instance.
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBInstance_GetWindowObject,
+ PP_Instance /* instance */,
+ ppapi::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBInstance_GetOwnerElementObject,
+ PP_Instance /* instance */,
+ ppapi::proxy::SerializedVar /* result */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBInstance_BindGraphics,
+ PP_Instance /* instance */,
+ PP_Resource /* device */)
+IPC_SYNC_MESSAGE_ROUTED1_1(
+ PpapiHostMsg_PPBInstance_GetAudioHardwareOutputSampleRate,
+ PP_Instance /* instance */,
+ uint32_t /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_1(
+ PpapiHostMsg_PPBInstance_GetAudioHardwareOutputBufferSize,
+ PP_Instance /* instance */,
+ uint32_t /* 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 */,
+ ppapi::proxy::SerializedVar /* script */,
+ ppapi::proxy::SerializedVar /* out_exception */,
+ ppapi::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBInstance_GetDefaultCharSet,
+ PP_Instance /* instance */,
+ ppapi::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 */,
+ ppapi::proxy::SerializedVar /* message */)
+IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBInstance_LockMouse,
+ PP_Instance /* instance */)
+IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBInstance_UnlockMouse,
+ PP_Instance /* instance */)
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBInstance_ResolveRelativeToDocument,
+ PP_Instance /* instance */,
+ ppapi::proxy::SerializedVar /* relative */,
+ ppapi::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBInstance_DocumentCanRequest,
+ PP_Instance /* instance */,
+ ppapi::proxy::SerializedVar /* relative */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBInstance_DocumentCanAccessDocument,
+ PP_Instance /* active */,
+ PP_Instance /* target */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_2(PpapiHostMsg_PPBInstance_GetDocumentURL,
+ PP_Instance /* active */,
+ PP_URLComponents_Dev /* components */,
+ ppapi::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBInstance_GetPluginInstanceURL,
+ PP_Instance /* active */,
+ ppapi::proxy::SerializedVar /* result */)
+IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBInstance_SetCursor,
+ PP_Instance /* instance */,
+ int32_t /* type */,
+ ppapi::HostResource /* custom_image */,
+ PP_Point /* hot_spot */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBInstance_SetTextInputType,
+ PP_Instance /* instance */,
+ PP_TextInput_Type /* type */)
+IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBInstance_UpdateCaretPosition,
+ PP_Instance /* instance */,
+ PP_Rect /* caret */,
+ PP_Rect /* bounding_box */)
+IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBInstance_CancelCompositionText,
+ PP_Instance /* instance */)
+IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBInstance_UpdateSurroundingText,
+ PP_Instance /* instance */,
+ std::string /* text */,
+ uint32_t /* caret */,
+ uint32_t /* anchor */)
+
+// 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_ROUTED2_2(PpapiHostMsg_PPBVar_HasProperty,
+ ppapi::proxy::SerializedVar /* object */,
+ ppapi::proxy::SerializedVar /* property */,
+ ppapi::proxy::SerializedVar /* out_exception */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_HasMethodDeprecated,
+ ppapi::proxy::SerializedVar /* object */,
+ ppapi::proxy::SerializedVar /* method */,
+ ppapi::proxy::SerializedVar /* out_exception */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_GetProperty,
+ ppapi::proxy::SerializedVar /* object */,
+ ppapi::proxy::SerializedVar /* property */,
+ ppapi::proxy::SerializedVar /* out_exception */,
+ ppapi::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_DeleteProperty,
+ ppapi::proxy::SerializedVar /* object */,
+ ppapi::proxy::SerializedVar /* property */,
+ ppapi::proxy::SerializedVar /* out_exception */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_2(PpapiHostMsg_PPBVar_EnumerateProperties,
+ ppapi::proxy::SerializedVar /* object */,
+ std::vector<ppapi::proxy::SerializedVar> /* props */,
+ ppapi::proxy::SerializedVar /* out_exception */)
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBVar_SetPropertyDeprecated,
+ ppapi::proxy::SerializedVar /* object */,
+ ppapi::proxy::SerializedVar /* name */,
+ ppapi::proxy::SerializedVar /* value */,
+ ppapi::proxy::SerializedVar /* out_exception */)
+IPC_SYNC_MESSAGE_ROUTED3_2(PpapiHostMsg_PPBVar_CallDeprecated,
+ ppapi::proxy::SerializedVar /* object */,
+ ppapi::proxy::SerializedVar /* method_name */,
+ std::vector<ppapi::proxy::SerializedVar> /* args */,
+ ppapi::proxy::SerializedVar /* out_exception */,
+ ppapi::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_Construct,
+ ppapi::proxy::SerializedVar /* object */,
+ std::vector<ppapi::proxy::SerializedVar> /* args */,
+ ppapi::proxy::SerializedVar /* out_exception */,
+ ppapi::proxy::SerializedVar /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBVar_IsInstanceOfDeprecated,
+ ppapi::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 */,
+ ppapi::proxy::SerializedVar /* result */)
+
+#if !defined(OS_NACL) && !defined(NACL_WIN64)
+// PPB_Broker.
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBBroker_Create,
+ PP_Instance /* instance */,
+ ppapi::HostResource /* result_resource */)
+IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBBroker_Connect,
+ ppapi::HostResource /* broker */)
+
+// PPB_Buffer.
+IPC_SYNC_MESSAGE_ROUTED2_2(
+ PpapiHostMsg_PPBBuffer_Create,
+ PP_Instance /* instance */,
+ uint32_t /* size */,
+ ppapi::HostResource /* result_resource */,
+ ppapi::proxy::SerializedHandle /* result_shm_handle */)
+
+// PPB_ContentDecryptor_Dev messages handled in PPB_Instance_Proxy.
+IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBInstance_NeedKey,
+ PP_Instance /* instance */,
+ ppapi::proxy::SerializedVar /* key_system, String */,
+ ppapi::proxy::SerializedVar /* session_id, String */,
+ ppapi::proxy::SerializedVar /* init_data, ArrayBuffer */)
+IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBInstance_KeyAdded,
+ PP_Instance /* instance */,
+ ppapi::proxy::SerializedVar /* key_system, String */,
+ ppapi::proxy::SerializedVar /* session_id, String */)
+IPC_MESSAGE_ROUTED5(PpapiHostMsg_PPBInstance_KeyMessage,
+ PP_Instance /* instance */,
+ ppapi::proxy::SerializedVar /* key_system, String */,
+ ppapi::proxy::SerializedVar /* session_id, String */,
+ ppapi::proxy::SerializedVar /* message, ArrayBuffer */,
+ ppapi::proxy::SerializedVar /* default_url, String */)
+IPC_MESSAGE_ROUTED5(PpapiHostMsg_PPBInstance_KeyError,
+ PP_Instance /* instance */,
+ ppapi::proxy::SerializedVar /* key_system, String */,
+ ppapi::proxy::SerializedVar /* session_id, String */,
+ int32_t /* media_error */,
+ int32_t /* system_code */)
+IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBInstance_DeliverBlock,
+ PP_Instance /* instance */,
+ PP_Resource /* decrypted_block, PPB_Buffer_Dev */,
+ std::string /* serialized_block_info */)
+IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBInstance_DecoderInitializeDone,
+ PP_Instance /* instance */,
+ PP_DecryptorStreamType /* decoder_type */,
+ uint32_t /* request_id */,
+ PP_Bool /* success */)
+IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBInstance_DecoderDeinitializeDone,
+ PP_Instance /* instance */,
+ PP_DecryptorStreamType /* decoder_type */,
+ uint32_t /* request_id */)
+IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBInstance_DecoderResetDone,
+ PP_Instance /* instance */,
+ PP_DecryptorStreamType /* decoder_type */,
+ uint32_t /* request_id */)
+IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBInstance_DeliverFrame,
+ PP_Instance /* instance */,
+ PP_Resource /* decrypted_frame, PPB_Buffer_Dev */,
+ std::string /* serialized_block_info */)
+IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBInstance_DeliverSamples,
+ PP_Instance /* instance */,
+ PP_Resource /* audio_frames, PPB_Buffer_Dev */,
+ std::string /* serialized_block_info */)
+#endif // !defined(OS_NACL) && !defined(NACL_WIN64)
+
+// PPB_NetworkMonitor_Private.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_PPBNetworkMonitor_Start,
+ uint32 /* plugin_dispatcher_id */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_PPBNetworkMonitor_Stop,
+ uint32 /* plugin_dispatcher_id */)
+
+// PPB_Testing.
+IPC_SYNC_MESSAGE_ROUTED3_1(
+ PpapiHostMsg_PPBTesting_ReadImageData,
+ ppapi::HostResource /* device_context_2d */,
+ ppapi::HostResource /* image */,
+ PP_Point /* top_left */,
+ PP_Bool /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBTesting_GetLiveObjectsForInstance,
+ PP_Instance /* instance */,
+ uint32 /* result */)
+IPC_SYNC_MESSAGE_ROUTED2_0(PpapiHostMsg_PPBTesting_SimulateInputEvent,
+ PP_Instance /* instance */,
+ ppapi::InputEventData /* input_event */)
+IPC_SYNC_MESSAGE_ROUTED1_0(
+ PpapiHostMsg_PPBTesting_SetMinimumArrayBufferSizeForShmem,
+ uint32_t /* threshold */)
+
+#if !defined(OS_NACL) && !defined(NACL_WIN64)
+
+// PPB_VideoDecoder.
+IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBVideoDecoder_Create,
+ PP_Instance /* instance */,
+ ppapi::HostResource /* context */,
+ PP_VideoDecoder_Profile /* profile */,
+ ppapi::HostResource /* result */)
+IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBVideoDecoder_Decode,
+ ppapi::HostResource /* video_decoder */,
+ ppapi::HostResource /* bitstream buffer */,
+ int32 /* bitstream buffer id */,
+ uint32 /* size of buffer */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBVideoDecoder_AssignPictureBuffers,
+ ppapi::HostResource /* video_decoder */,
+ std::vector<PP_PictureBuffer_Dev> /* picture buffers */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBVideoDecoder_ReusePictureBuffer,
+ ppapi::HostResource /* video_decoder */,
+ int32_t /* picture buffer id */)
+IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBVideoDecoder_Flush,
+ ppapi::HostResource /* video_decoder */)
+IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBVideoDecoder_Reset,
+ ppapi::HostResource /* video_decoder */)
+IPC_SYNC_MESSAGE_ROUTED1_0(PpapiHostMsg_PPBVideoDecoder_Destroy,
+ ppapi::HostResource /* video_decoder */)
+
+// PPB_Flash_MessageLoop.
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFlashMessageLoop_Create,
+ PP_Instance /* instance */,
+ ppapi::HostResource /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFlashMessageLoop_Run,
+ ppapi::HostResource /* flash_message_loop */,
+ int32_t /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_0(PpapiHostMsg_PPBFlashMessageLoop_Quit,
+ ppapi::HostResource /* flash_message_loop */)
+#endif // !defined(OS_NACL) && !defined(NACL_WIN64)
+
+// PPB_TCPSocket and PPB_TCPSocket_Private.
+// Creates a PPB_TCPSocket resource.
+IPC_SYNC_MESSAGE_CONTROL2_1(PpapiHostMsg_PPBTCPSocket_Create,
+ int32 /* routing_id */,
+ uint32 /* plugin_dispatcher_id */,
+ uint32 /* socket_id */)
+// Creates a PPB_TCPSocket_Private resource.
+IPC_SYNC_MESSAGE_CONTROL2_1(PpapiHostMsg_PPBTCPSocket_CreatePrivate,
+ int32 /* routing_id */,
+ uint32 /* plugin_dispatcher_id */,
+ uint32 /* socket_id */)
+IPC_MESSAGE_CONTROL4(PpapiHostMsg_PPBTCPSocket_Connect,
+ int32 /* routing_id */,
+ uint32 /* socket_id */,
+ std::string /* host */,
+ uint16_t /* port */)
+IPC_MESSAGE_CONTROL3(PpapiHostMsg_PPBTCPSocket_ConnectWithNetAddress,
+ int32 /* routing_id */,
+ uint32 /* socket_id */,
+ PP_NetAddress_Private /* net_addr */)
+IPC_MESSAGE_CONTROL5(PpapiHostMsg_PPBTCPSocket_SSLHandshake,
+ uint32 /* socket_id */,
+ std::string /* server_name */,
+ uint16_t /* server_port */,
+ std::vector<std::vector<char> > /* trusted_certs */,
+ std::vector<std::vector<char> > /* untrusted_certs */)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_PPBTCPSocket_Read,
+ uint32 /* socket_id */,
+ int32_t /* bytes_to_read */)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_PPBTCPSocket_Write,
+ uint32 /* socket_id */,
+ std::string /* data */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_PPBTCPSocket_Disconnect,
+ uint32 /* socket_id */)
+IPC_MESSAGE_CONTROL3(PpapiHostMsg_PPBTCPSocket_SetOption,
+ uint32 /* socket_id */,
+ PP_TCPSocket_Option /* name */,
+ ppapi::SocketOptionData /* value */)
+
+// PPB_X509Certificate_Private
+IPC_SYNC_MESSAGE_CONTROL1_2(PpapiHostMsg_PPBX509Certificate_ParseDER,
+ std::vector<char> /* der */,
+ bool /* succeeded */,
+ ppapi::PPB_X509Certificate_Fields /* result */)
+
+//-----------------------------------------------------------------------------
+// Resource call/reply messages.
+//
+// These are the new-style resource implementations where the resource is only
+// implemented in the proxy and "resource messages" are sent between this and a
+// host object. Resource messages are a wrapper around some general routing
+// information and a separate message of a type defined by the specific resource
+// sending/receiving it. The extra paremeters allow the nested message to be
+// routed automatically to the correct resource.
+
+// Notification that a resource has been created in the plugin. The nested
+// message will be resource-type-specific.
+IPC_MESSAGE_CONTROL3(PpapiHostMsg_ResourceCreated,
+ ppapi::proxy::ResourceMessageCallParams /* call_params */,
+ PP_Instance /* instance */,
+ IPC::Message /* nested_msg */)
+
+// Notification that a resource has been destroyed in the plugin.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_ResourceDestroyed,
+ PP_Resource /* resource */)
+
+// Most resources are created by the plugin, which then sends a ResourceCreated
+// message to create a corresponding ResourceHost in the renderer or browser
+// host process. However, some resources are first created in the host and
+// "pushed" or returned to the plugin.
+//
+// In this case, the host will create a "pending" ResourceHost object which
+// is identified by an ID. The ID is sent to the plugin process and the
+// PluginResource object is created. This message is sent from the plugin to
+// the host process to connect the PluginResource and the pending ResourceHost
+// (at which point, it's no longer pending).
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_AttachToPendingHost,
+ PP_Resource /* resource */,
+ int /* pending_host_id */)
+
+// A resource call is a request from the plugin to the host. It may or may not
+// require a reply, depending on the params. The nested message will be
+// resource-type-specific.
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_ResourceCall,
+ ppapi::proxy::ResourceMessageCallParams /* call_params */,
+ IPC::Message /* nested_msg */)
+IPC_MESSAGE_CONTROL3(PpapiHostMsg_InProcessResourceCall,
+ int /* routing_id */,
+ ppapi::proxy::ResourceMessageCallParams /* call_params */,
+ IPC::Message /* nested_msg */)
+
+// A resource reply is a response to a ResourceCall from a host to the
+// plugin. The resource ID + sequence number in the params will correspond to
+// that of the previous ResourceCall.
+IPC_MESSAGE_CONTROL2(
+ PpapiPluginMsg_ResourceReply,
+ ppapi::proxy::ResourceMessageReplyParams /* reply_params */,
+ IPC::Message /* nested_msg */)
+IPC_MESSAGE_ROUTED2(
+ PpapiHostMsg_InProcessResourceReply,
+ ppapi::proxy::ResourceMessageReplyParams /* reply_params */,
+ IPC::Message /* nested_msg */)
+
+
+IPC_SYNC_MESSAGE_CONTROL2_2(PpapiHostMsg_ResourceSyncCall,
+ ppapi::proxy::ResourceMessageCallParams /* call_params */,
+ IPC::Message /* nested_msg */,
+ ppapi::proxy::ResourceMessageReplyParams /* reply_params */,
+ IPC::Message /* reply_msg */)
+
+// This message is sent from the renderer to the browser when it wants to create
+// a ResourceHost in the browser. It contains the process ID of the plugin and
+// the instance of the plugin for which to create the resource for. params
+// contains the sequence number for the message to track the response.
+// The nested message is a ResourceHost creation message.
+IPC_MESSAGE_CONTROL5(
+ PpapiHostMsg_CreateResourceHostFromHost,
+ int /* routing_id */,
+ int /* child_process_id */,
+ ppapi::proxy::ResourceMessageCallParams /* params */,
+ PP_Instance /* instance */,
+ IPC::Message /* nested_msg */)
+
+// This message is sent from the browser to the renderer when it has created a
+// ResourceHost for the renderer. It contains the sequence number that was sent
+// in the request and the ID of the pending ResourceHost which was created in
+// the browser. This ID is only useful for the plugin which can attach to the
+// ResourceHost in the browser.
+IPC_MESSAGE_ROUTED2(
+ PpapiHostMsg_CreateResourceHostFromHostReply,
+ int32_t /* sequence */,
+ int /* pending_host_id */)
+
+//-----------------------------------------------------------------------------
+// Messages for resources using call/reply above.
+
+// Broker ----------------------------------------------------------------------
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_Broker_Create)
+
+// Queries whether the plugin has permission to connect to the Pepper broker.
+// The response is contained in the error value of the
+// ResourceMessageReplyParams in the reply message.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_Broker_IsAllowed)
+
+// Extensions common -----------------------------------------------------------
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_ExtensionsCommon_Create)
+
+// Starts an extension API request which doesn't expect a response.
+// |request_name| is an API function name. |args| is a list of input arguments.
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_ExtensionsCommon_Post,
+ std::string /* request_name */,
+ base::ListValue /* args */)
+
+// Starts an extension API request which expects a response sent back using a
+// PpapiPluginMsg_ExtensionsCommon_CallReply message.
+// |request_name| is an API function name. |args| is a list of input arguments.
+// |output| is a list of output results.
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_ExtensionsCommon_Call,
+ std::string /* request_name */,
+ base::ListValue /* args */)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_ExtensionsCommon_CallReply,
+ base::ListValue /* output */)
+
+// Ext_CrxFileSystem
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_Ext_CrxFileSystem_Create)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_Ext_CrxFileSystem_BrowserOpen)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_Ext_CrxFileSystem_BrowserOpenReply,
+ std::string /* fsid */)
+
+// File chooser.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileChooser_Create)
+IPC_MESSAGE_CONTROL4(PpapiHostMsg_FileChooser_Show,
+ bool /* save_as */,
+ bool /* open_multiple */,
+ std::string /* suggested_file_name */,
+ std::vector<std::string> /* accept_mime_types */)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FileChooser_ShowReply,
+ std::vector<ppapi::PPB_FileRef_CreateInfo> /* files */)
+
+// FileIO
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileIO_Create)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileIO_Open,
+ PP_Resource /* file_ref_resource */,
+ int32_t /* open_flags */)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_FileIO_OpenReply)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileIO_Close)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileIO_Touch,
+ PP_Time /* last_access_time */,
+ PP_Time /* last_modified_time */)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileIO_Write,
+ int64_t /* offset */,
+ std::string /* data */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_FileIO_SetLength,
+ int64_t /* length */)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileIO_Flush)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileIO_WillWrite,
+ int64_t /* offset */,
+ int32_t /* bytes_to_write */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_FileIO_WillSetLength,
+ int64_t /* length */)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileIO_GetOSFileDescriptor)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FileIO_GetOSFileDescriptorReply,
+ int32_t /* file descriptor */)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileIO_RequestOSFileHandle)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_FileIO_RequestOSFileHandleReply)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_FileIO_GeneralReply)
+
+// FileRef
+// Creates a FileRef to a path on an external file system. This message may
+// only be sent from the renderer.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_FileRef_CreateExternal,
+ base::FilePath /* external_path */)
+
+// Creates a FileRef to a path on an internal file system. This message may
+// be sent from the renderer or the plugin.
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileRef_CreateInternal,
+ PP_Resource /* file_system */,
+ std::string /* internal_path */)
+
+// Requests that the browser create a directory at the location indicated by
+// the FileRef.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_FileRef_MakeDirectory,
+ bool /* make_ancestors */)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_FileRef_MakeDirectoryReply)
+
+// Requests that the browser update the last accessed and last modified times
+// at the location indicated by the FileRef.
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileRef_Touch,
+ PP_Time /* last_accessed */,
+ PP_Time /* last_modified */)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_FileRef_TouchReply)
+
+// Requests that the browser delete a file or directory at the location
+// indicated by the FileRef.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileRef_Delete)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_FileRef_DeleteReply)
+
+// Requests that the browser rename a file or directory at the location
+// indicated by the FileRef.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_FileRef_Rename,
+ PP_Resource /* new_file_ref */)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_FileRef_RenameReply)
+
+// Requests that the browser retrieve metadata information for a file or
+// directory at the location indicated by the FileRef.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileRef_Query)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FileRef_QueryReply,
+ PP_FileInfo /* file_info */)
+
+// Requests that the browser retrieve then entries in a directory at the
+// location indicated by the FileRef.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileRef_ReadDirectoryEntries)
+
+// FileRef_CreateInfo does not provide file type information, so two
+// corresponding vectors are returned.
+IPC_MESSAGE_CONTROL2(PpapiPluginMsg_FileRef_ReadDirectoryEntriesReply,
+ std::vector<ppapi::FileRef_CreateInfo> /* files */,
+ std::vector<PP_FileType> /* file_types */)
+
+// Requests that the browser reply with the absolute path to the indicated
+// file.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileRef_GetAbsolutePath)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FileRef_GetAbsolutePathReply,
+ std::string /* absolute_path */)
+
+// FileSystem
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_FileSystem_Create,
+ PP_FileSystemType /* type */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_FileSystem_Open,
+ int64_t /* expected_size */)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_FileSystem_OpenReply)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_FileSystem_InitIsolatedFileSystem,
+ std::string /* fsid */)
+
+// Flash DRM ------------------------------------------------------------------
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_Create)
+
+// Requests the device ID.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_GetDeviceID)
+// Reply for GetDeviceID which includes the device ID as a string.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_GetDeviceIDReply,
+ std::string /* id */)
+
+// Requests the HMONITOR corresponding to the monitor on which the instance is
+// displayed.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_GetHmonitor)
+// Reply message for GetHmonitor which contains the HMONITOR as an int64_t.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_GetHmonitorReply,
+ int64_t /* hmonitor */)
+
+// Requests the voucher file which is used to verify the integrity of the Flash
+// module. A PPB_FileRef resource will be created.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_GetVoucherFile)
+// Reply message for GetVoucherFile which contains the CreateInfo for a
+// PPB_FileRef which points to the voucher file.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_GetVoucherFileReply,
+ ppapi::PPB_FileRef_CreateInfo /* file_info */)
+
+// Gamepad.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_Gamepad_Create)
+
+// Requests that the gamepad host send the shared memory handle to the plugin
+// process.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_Gamepad_RequestMemory)
+
+// Reply to a RequestMemory call. This supplies the shared memory handle. The
+// actual handle is passed in the ReplyParams struct.
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_Gamepad_SendMemory)
+
+
+// Graphics2D, plugin -> host
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_Graphics2D_Create,
+ PP_Size /* size */,
+ PP_Bool /* is_always_opaque */)
+IPC_MESSAGE_CONTROL4(PpapiHostMsg_Graphics2D_PaintImageData,
+ ppapi::HostResource /* image_data */,
+ PP_Point /* top_left */,
+ bool /* src_rect_specified */,
+ PP_Rect /* src_rect */)
+IPC_MESSAGE_CONTROL3(PpapiHostMsg_Graphics2D_Scroll,
+ bool /* clip_specified */,
+ PP_Rect /* clip */,
+ PP_Point /* amount */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_Graphics2D_ReplaceContents,
+ ppapi::HostResource /* image_data */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_Graphics2D_Dev_SetScale,
+ float /* scale */)
+
+// Graphics2D, plugin -> host -> plugin
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_Graphics2D_Flush)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_Graphics2D_FlushAck)
+
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_Graphics2D_ReadImageData,
+ PP_Resource /* image */,
+ PP_Point /* top_left */)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_Graphics2D_ReadImageDataAck)
+
+// NetworkProxy ----------------------------------------------------------------
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_NetworkProxy_Create)
+
+// Query the browser for the proxy server to use for the given URL.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_NetworkProxy_GetProxyForURL,
+ std::string /* url */)
+
+// Reply message for GetProxyForURL containing the proxy server.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_NetworkProxy_GetProxyForURLReply,
+ std::string /* proxy */)
+
+// TrueTypeFont.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_TrueTypeFontSingleton_Create)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_TrueTypeFontSingleton_GetFontFamilies)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_TrueTypeFontSingleton_GetFontFamiliesReply,
+ std::vector<std::string> /* font_families */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_TrueTypeFontSingleton_GetFontsInFamily,
+ std::string /* family */)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_TrueTypeFontSingleton_GetFontsInFamilyReply,
+ std::vector<ppapi::proxy::SerializedTrueTypeFontDesc>
+ /* fonts */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_TrueTypeFont_Create,
+ ppapi::proxy::SerializedTrueTypeFontDesc /* desc */)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_TrueTypeFont_Describe)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_TrueTypeFont_DescribeReply,
+ ppapi::proxy::SerializedTrueTypeFontDesc /* desc */)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_TrueTypeFont_GetTableTags)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_TrueTypeFont_GetTableTagsReply,
+ std::vector<uint32_t> /* tags */)
+IPC_MESSAGE_CONTROL3(PpapiHostMsg_TrueTypeFont_GetTable,
+ uint32_t /* table */,
+ int32_t /* offset */,
+ int32_t /* max_data_length */)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_TrueTypeFont_GetTableReply,
+ std::string /* data */)
+
+// Host Resolver ---------------------------------------------------------------
+// Creates a PPB_HostResolver resource.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_HostResolver_Create)
+
+// Creates a PPB_HostResolver_Private resource.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_HostResolver_CreatePrivate)
+
+// Resolves the given hostname.
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_HostResolver_Resolve,
+ ppapi::HostPortPair /* host_port */,
+ PP_HostResolver_Private_Hint /* hint */)
+
+// This message is a reply to HostResolver_Resolve. On success,
+// |canonical_name| contains the canonical name of the host; |net_address_list|
+// is a list of network addresses. On failure, both fields are set to empty.
+IPC_MESSAGE_CONTROL2(PpapiPluginMsg_HostResolver_ResolveReply,
+ std::string /* canonical_name */,
+ std::vector<PP_NetAddress_Private> /* net_address_list */)
+
+// Printing.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_Printing_Create)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_Printing_GetDefaultPrintSettings)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_Printing_GetDefaultPrintSettingsReply,
+ PP_PrintSettings_Dev /* print_settings */)
+
+// TCP Server Socket -----------------------------------------------------------
+// Creates a PPB_TCPServerSocket_Private resource.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_TCPServerSocket_CreatePrivate)
+
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_TCPServerSocket_Listen,
+ PP_NetAddress_Private /* addr */,
+ int32_t /* backlog */)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_TCPServerSocket_ListenReply,
+ PP_NetAddress_Private /* local_addr */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_TCPServerSocket_Accept,
+ uint32 /* plugin_dispatcher_id */)
+IPC_MESSAGE_CONTROL3(PpapiPluginMsg_TCPServerSocket_AcceptReply,
+ uint32 /* accepted_socket_id */,
+ PP_NetAddress_Private /* local_addr */,
+ PP_NetAddress_Private /* remote_addr */)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_TCPServerSocket_StopListening)
+
+// UDP Socket ------------------------------------------------------------------
+// Creates a PPB_UDPSocket resource.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_UDPSocket_Create)
+
+// Creates a PPB_UDPSocket_Private resource.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_UDPSocket_CreatePrivate)
+
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_UDPSocket_SetOption,
+ PP_UDPSocket_Option /* name */,
+ ppapi::SocketOptionData /* value */)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_UDPSocket_SetOptionReply)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_UDPSocket_Bind,
+ PP_NetAddress_Private /* net_addr */)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_UDPSocket_BindReply,
+ PP_NetAddress_Private /* bound_addr */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_UDPSocket_RecvFrom,
+ int32_t /* num_bytes */)
+IPC_MESSAGE_CONTROL2(PpapiPluginMsg_UDPSocket_RecvFromReply,
+ std::string /* data */,
+ PP_NetAddress_Private /* remote_addr */)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_UDPSocket_SendTo,
+ std::string /* data */,
+ PP_NetAddress_Private /* net_addr */)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_UDPSocket_SendToReply,
+ int32_t /* bytes_written */)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_UDPSocket_Close)
+
+// URLLoader ------------------------------------------------------------------
+
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_URLLoader_Create)
+
+// These messages correspond to PPAPI calls and all should get a
+// CallbackComplete message.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_URLLoader_Open,
+ ppapi::URLRequestInfoData /* request_data */)
+
+// The plugin can tell the host to defer a load to hold off on sending more
+// data because the buffer in the plugin is full. When defers_loading is set to
+// false, data streaming will resume.
+//
+// When auditing redirects (no auto follow) the load will be automatically
+// deferred each time we get a redirect. The plugin will reset this to false
+// by sending this message when it wants to continue following the redirect.
+//
+// When streaming data, the host may still send more data after this call (for
+// example, it could already be in-flight at the time of this request).
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_URLLoader_SetDeferLoading,
+ bool /* defers_loading */)
+
+// Closes the URLLoader. There is no reply.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_URLLoader_Close)
+
+// Requests that cross-site restrictions be ignored. The plugin must have
+// the private permission set. Otherwise this message will be ignored by the
+// renderer. There is no reply.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_URLLoader_GrantUniversalAccess)
+
+// Push notification that a response is available.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_URLLoader_ReceivedResponse,
+ ppapi::URLResponseInfoData /* response */)
+
+// Push notification with load data from the renderer. It is a custom generated
+// message with the response data (array of bytes stored via WriteData)
+// appended.
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_URLLoader_SendData)
+
+// Push notification indicating that all data has been sent, either via
+// SendData or by streaming it to a file. Note that since this is a push
+// notification, we don't use the result field of the ResourceMessageReply.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_URLLoader_FinishedLoading,
+ int32_t /* result */)
+
+// Push notification from the renderer to the plugin to tell it about download
+// and upload progress. This will only be sent if the plugin has requested
+// progress updates, and only the fields requested by the plugin will be
+// valid.
+IPC_MESSAGE_CONTROL4(PpapiPluginMsg_URLLoader_UpdateProgress,
+ int64_t /* bytes_sent */,
+ int64_t /* total_bytes_to_be_sent */,
+ int64_t /* bytes_received */,
+ int64_t /* total_bytes_to_be_received */)
+
+// Shared memory ---------------------------------------------------------------
+
+// Creates shared memory on the host side, returning a handle to the shared
+// memory on the plugin and keeping the memory mapped in on the host.
+// We return a "host handle_id" that can be mapped back to the
+// handle on the host side by PpapiGlobals::UntrackSharedMemoryHandle().
+IPC_SYNC_MESSAGE_CONTROL2_2(PpapiHostMsg_SharedMemory_CreateSharedMemory,
+ PP_Instance /* instance */,
+ uint32_t /* size */,
+ int /* host_handle_id */,
+ ppapi::proxy::SerializedHandle /* plugin_handle */)
+
+// MediaStream -----------------------------------------------------------------
+
+// VideoDestination Private.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_VideoDestination_Create)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_VideoDestination_Open,
+ std::string /* stream_url */)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_VideoDestination_OpenReply)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_VideoDestination_PutFrame,
+ ppapi::HostResource /* image_data */,
+ PP_TimeTicks /* timestamp */)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_VideoDestination_Close)
+
+// VideoSource Private.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_VideoSource_Create)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_VideoSource_Open,
+ std::string /* stream_url */)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_VideoSource_OpenReply)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_VideoSource_GetFrame)
+IPC_MESSAGE_CONTROL3(PpapiPluginMsg_VideoSource_GetFrameReply,
+ ppapi::HostResource /* resource_id */,
+ PP_ImageDataDesc /* image_data_desc */,
+ PP_TimeTicks /* timestamp */)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_VideoSource_Close)
+
+// WebSocket -------------------------------------------------------------------
+
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_WebSocket_Create)
+
+// Establishes the connection to a server. This message requires
+// WebSocket_ConnectReply as a reply message.
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_WebSocket_Connect,
+ std::string /* url */,
+ std::vector<std::string> /* protocols */)
+
+// Closes established connection with graceful closing handshake. This message
+// requires WebSocket_CloseReply as a reply message.
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_WebSocket_Close,
+ int32_t /* code */,
+ std::string /* reason */)
+
+// Sends a text frame to the server. No reply is defined.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_WebSocket_SendText,
+ std::string /* message */)
+
+// Sends a binary frame to the server. No reply is defined.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_WebSocket_SendBinary,
+ std::vector<uint8_t> /* message */)
+
+// Fails the connection. This message invokes RFC6455 defined
+// _Fail the WebSocket Connection_ operation. No reply is defined.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_WebSocket_Fail,
+ std::string /* message */)
+
+// This message is a reply to WebSocket_Connect. If the |url| and |protocols|
+// are invalid, WebSocket_ConnectReply is issued immediately and it contains
+// proper error code in its result. Otherwise, WebSocket_ConnectReply is sent
+// with valid |url|, |protocol|, and result PP_OK. |protocol| is not a passed
+// |protocols|, but a result of opening handshake negotiation. If the
+// connection can not be established successfully, WebSocket_ConnectReply is
+// not issued, but WebSocket_ClosedReply is sent instead.
+IPC_MESSAGE_CONTROL2(PpapiPluginMsg_WebSocket_ConnectReply,
+ std::string /* url */,
+ std::string /* protocol */)
+
+// This message is a reply to WebSocket_Close. If the operation fails,
+// WebSocket_CloseReply is issued immediately and it contains PP_ERROR_FAILED.
+// Otherwise, CloseReply will be issued after the closing handshake is
+// finished. All arguments will be valid iff the result is PP_OK and it means
+// that the client initiated closing handshake is finished gracefully.
+IPC_MESSAGE_CONTROL4(PpapiPluginMsg_WebSocket_CloseReply,
+ uint64_t /* buffered_amount */,
+ bool /* was_clean */,
+ uint16_t /* code */,
+ std::string /* reason */)
+
+// Unsolicited reply message to transmit a receiving text frame.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_WebSocket_ReceiveTextReply,
+ std::string /* message */)
+
+// Unsolicited reply message to transmit a receiving binary frame.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_WebSocket_ReceiveBinaryReply,
+ std::vector<uint8_t> /* message */)
+
+// Unsolicited reply message to notify a error on underlying network connetion.
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_WebSocket_ErrorReply)
+
+// Unsolicited reply message to update the buffered amount value.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_WebSocket_BufferedAmountReply,
+ uint64_t /* buffered_amount */)
+
+// Unsolicited reply message to update |state| because of incoming external
+// events, e.g., protocol error, or unexpected network closure.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_WebSocket_StateReply,
+ int32_t /* state */)
+
+// Unsolicited reply message to notify that the connection is closed without
+// any WebSocket_Close request. Server initiated closing handshake or
+// unexpected network errors will invoke this message.
+IPC_MESSAGE_CONTROL4(PpapiPluginMsg_WebSocket_ClosedReply,
+ uint64_t /* buffered_amount */,
+ bool /* was_clean */,
+ uint16_t /* code */,
+ std::string /* reason */)
+
+#if !defined(OS_NACL) && !defined(NACL_WIN64)
+
+// Audio input.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_AudioInput_Create)
+IPC_MESSAGE_CONTROL3(PpapiHostMsg_AudioInput_Open,
+ std::string /* device_id */,
+ PP_AudioSampleRate /* sample_rate */,
+ uint32_t /* sample_frame_count */)
+// Reply to an Open call. This supplies a socket handle and a shared memory
+// handle. Both handles are passed in the ReplyParams struct.
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_AudioInput_OpenReply)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_AudioInput_StartOrStop, bool /* capture */)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_AudioInput_Close)
+
+// BrowserFont -----------------------------------------------------------------
+
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_BrowserFontSingleton_Create)
+
+// Requests that the browser reply with the list of font families via
+// PpapiPluginMsg_BrowserFontSingleton_GetFontFamiliesReply.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_BrowserFontSingleton_GetFontFamilies)
+
+// Reply to PpapiHostMsg_BrowserFontSingleton_GetFontFamilies with the font
+// family list. The |families| result is encoded by separating each family name
+// by a null character.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_BrowserFontSingleton_GetFontFamiliesReply,
+ std::string /* families */)
+
+// FileRef.
+// Requests that the browser reply with file system and path information about
+// the resource indicated in |params| which exists in the given
+// |child_process_id|. |routing_id| is sent so that the reply can be routed
+// properly in the renderer.
+// Only sent from the renderer to the browser.
+IPC_MESSAGE_CONTROL4(PpapiHostMsg_FileRef_GetInfoForRenderer,
+ int /* routing_id */,
+ int /* child_process_id */,
+ int32_t /* sequence */,
+ std::vector<PP_Resource> /* resources */)
+
+// Reply to PpapiHostMsg_FileRef_GetInfoForRenderer with a sequence number for
+// invoking the right callback, |fs_type| which indicates the file system, and
+// path information in either |file_system_url_spec| (for internal file systems)
+// or |external_path| (for external file systems).
+// Only sent from the browser to the renderer.
+IPC_MESSAGE_ROUTED5(PpapiHostMsg_FileRef_GetInfoForRendererReply,
+ int32_t /* sequence */,
+ std::vector<PP_Resource> /* resources */,
+ std::vector<PP_FileSystemType> /* fs_type */,
+ std::vector<std::string> /* file_system_url_spec */,
+ std::vector<base::FilePath> /* external_path */)
+
+// Flash -----------------------------------------------------------------------
+
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_Flash_Create)
+
+// Message to notify the browser to register an update in system activity.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_Flash_UpdateActivity)
+
+// Query the browser for the proxy server to use for the given URL.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_Flash_GetProxyForURL, std::string /* url */)
+// Reply message for GetProxyForURL containing the proxy server.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_Flash_GetProxyForURLReply,
+ std::string /* proxy */)
+
+// Queries the browser for the local time zone offset for a given time.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_Flash_GetLocalTimeZoneOffset,
+ base::Time /* time */)
+// Reply to GetLocalTimeZoneOffset containing the time zone offset as a double.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_Flash_GetLocalTimeZoneOffsetReply,
+ double /* offset */)
+
+// Query the browser for the restrictions on storing Flash LSOs.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_Flash_GetLocalDataRestrictions)
+// Reply message for GetLocalDataRestrictions containing the restrictions to
+// use. These are PP_FlashLSORestrictions cast to an int32_t.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_Flash_GetLocalDataRestrictionsReply,
+ int32_t /* restrictions */)
+
+// Notifies the renderer whether the Flash instance is in windowed mode. No
+// reply is sent.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_Flash_SetInstanceAlwaysOnTop,
+ bool /* on_top */)
+
+// Notifies the renderer to draw text to the given PP_ImageData resource. All
+// parmeters for drawing (including the resource to draw to) are contianed in
+// the PPBFlash_DrawGlyphs_Params structure. An error code is sent in a reply
+// message indicating success.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_Flash_DrawGlyphs,
+ ppapi::proxy::PPBFlash_DrawGlyphs_Params /* params */)
+
+// Notifies the renderer to navigate to the given URL contained in the
+// URLRequestInfoData. An error code is sent in a reply message indicating
+// success.
+IPC_MESSAGE_CONTROL3(PpapiHostMsg_Flash_Navigate,
+ ppapi::URLRequestInfoData /* data */,
+ std::string /* target */,
+ bool /* from_user_action */)
+
+// Queries the renderer on whether the plugin instance is the topmost element
+// in the area of the instance specified by the given PP_Rect. PP_OK is sent as
+// the error code in a reply message if the rect is topmost otherwise
+// PP_ERROR_FAILED is sent.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_Flash_IsRectTopmost,
+ PP_Rect /* rect */)
+
+// Notifies the renderer to invoke printing for the given plugin instance. No
+// reply is sent.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_Flash_InvokePrinting)
+
+// DeviceEnumeration -----------------------------------------------------------
+// Device enumeration messages used by audio input and video capture.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_DeviceEnumeration_EnumerateDevices)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply,
+ std::vector<ppapi::DeviceRefData> /* devices */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_DeviceEnumeration_MonitorDeviceChange,
+ uint32_t /* callback_id */)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_DeviceEnumeration_StopMonitoringDeviceChange)
+IPC_MESSAGE_CONTROL2(PpapiPluginMsg_DeviceEnumeration_NotifyDeviceChange,
+ uint32_t /* callback_id */,
+ std::vector<ppapi::DeviceRefData> /* devices */)
+
+// Flash clipboard.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashClipboard_Create)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashClipboard_RegisterCustomFormat,
+ std::string /* format_name */)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashClipboard_RegisterCustomFormatReply,
+ uint32_t /* format */)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_FlashClipboard_IsFormatAvailable,
+ uint32_t /* clipboard_type */,
+ uint32_t /* format */)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_FlashClipboard_ReadData,
+ uint32_t /* clipboard_type */,
+ uint32_t /* format */)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashClipboard_ReadDataReply,
+ std::string /* result */)
+IPC_MESSAGE_CONTROL3(PpapiHostMsg_FlashClipboard_WriteData,
+ uint32_t /* clipboard_type */,
+ std::vector<uint32_t> /* formats */,
+ std::vector<std::string> /* data */)
+
+// Flash file.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashFile_Create)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_FlashFile_OpenFile,
+ ppapi::PepperFilePath /* path */,
+ int /* pp_open_flags */)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_FlashFile_RenameFile,
+ ppapi::PepperFilePath /* from_path */,
+ ppapi::PepperFilePath /* to_path */)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_FlashFile_DeleteFileOrDir,
+ ppapi::PepperFilePath /* path */,
+ bool /* recursive */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashFile_CreateDir,
+ ppapi::PepperFilePath /* path */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashFile_QueryFile,
+ ppapi::PepperFilePath /* path */)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashFile_QueryFileReply,
+ base::PlatformFileInfo /* file_info */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashFile_GetDirContents,
+ ppapi::PepperFilePath /* path */)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashFile_GetDirContentsReply,
+ ppapi::DirContents /* entries */)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashFile_CreateTemporaryFile)
+
+// Flash font file.
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_FlashFontFile_Create,
+ ppapi::proxy::SerializedFontDescription /* description */,
+ PP_PrivateFontCharset /* charset */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashFontFile_GetFontTable,
+ uint32_t /* table */)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashFontFile_GetFontTableReply,
+ std::string /* output */)
+
+// Flash fullscreen.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashFullscreen_Create)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashFullscreen_SetFullscreen,
+ bool /* fullscreen */)
+
+// FlashMenu ------------------------------------------------------------------
+
+// Creates the flash menu with the given data.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashMenu_Create,
+ ppapi::proxy::SerializedFlashMenu /* menu_data */)
+
+// Shows the menu at the given location relative to the plugin instance.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashMenu_Show,
+ PP_Point /* location */)
+
+// Reply to a show command. If the resource reply is PP_OK, the selected_id
+// will be the menu item ID chosen by the user.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashMenu_ShowReply,
+ int32_t /* selected_id */)
+
+// PDF ------------------------------------------------------------------------
+
+// Creates the PDF resource.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_PDF_Create)
+
+// Requests the localized string for the given ID.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_PDF_GetLocalizedString,
+ PP_ResourceString /* string_id */)
+// Reply for PpapiHostMsg_PDF_GetLocalizedString containing the localized
+// string.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_PDF_GetLocalizedStringReply,
+ std::string /* localized_string*/)
+
+// Notifies the renderer that the PDF started loading.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_PDF_DidStartLoading)
+
+// Notifies the renderer that the PDF stopped loading.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_PDF_DidStopLoading)
+
+// Sets any restrictions on the PDF content.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_PDF_SetContentRestriction,
+ int /* restrictions */)
+
+// Requests that the specified action be recorded with UMA.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_PDF_UserMetricsRecordAction,
+ std::string /* action */)
+
+// Notifies the renderer that the current PDF uses an unsupported feature.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_PDF_HasUnsupportedFeature)
+
+// Notifies the renderer to print the current PDF.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_PDF_Print)
+
+// Notifies the renderer to save the current PDF.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_PDF_SaveAs)
+
+// Requests a resource image for the plugin at a particular scale.
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_PDF_GetResourceImage,
+ PP_ResourceImage /* image_id */,
+ float /* scale */)
+
+// Reply for PpapiHostMsg_PDF_GetResourceImage containing the host resource id
+// of the image and a PP_ImageDataDesc which describes the image. Also carries
+// a shared memory handle pointing to the memory containg the image.
+IPC_MESSAGE_CONTROL2(PpapiPluginMsg_PDF_GetResourceImageReply,
+ ppapi::HostResource /* resource_id */,
+ PP_ImageDataDesc /* image_data_desc */)
+
+// VideoCapture_Dev, plugin -> host
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_VideoCapture_Create)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_VideoCapture_StartCapture)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_VideoCapture_ReuseBuffer,
+ uint32_t /* buffer */)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_VideoCapture_StopCapture)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_VideoCapture_Close)
+
+// VideoCapture_Dev, plugin -> host -> plugin
+IPC_MESSAGE_CONTROL3(PpapiHostMsg_VideoCapture_Open,
+ std::string /* device_id */,
+ PP_VideoCaptureDeviceInfo_Dev /* requested_info */,
+ uint32_t /* buffer_count */)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_VideoCapture_OpenReply)
+
+// VideoCapture_Dev, host -> plugin
+IPC_MESSAGE_CONTROL3(PpapiPluginMsg_VideoCapture_OnDeviceInfo,
+ PP_VideoCaptureDeviceInfo_Dev /* info */,
+ std::vector<ppapi::HostResource> /* buffers */,
+ uint32_t /* buffer_size */)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_VideoCapture_OnStatus,
+ uint32_t /* status */)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_VideoCapture_OnError,
+ uint32_t /* error */)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_VideoCapture_OnBufferReady,
+ uint32_t /* buffer */)
+
+// Talk ------------------------------------------------------------------------
+
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_Talk_Create)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_Talk_RequestPermission,
+ PP_TalkPermission /* permission */)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_Talk_RequestPermissionReply)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_Talk_StartRemoting)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_Talk_StartRemotingReply)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_Talk_StopRemoting)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_Talk_StopRemotingReply)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_Talk_NotifyEvent, PP_TalkEvent /* event */)
+
+#endif // !defined(OS_NACL) && !defined(NACL_WIN64)
diff --git a/chromium/ppapi/proxy/ppapi_param_traits.cc b/chromium/ppapi/proxy/ppapi_param_traits.cc
new file mode 100644
index 00000000000..ca25f82f257
--- /dev/null
+++ b/chromium/ppapi/proxy/ppapi_param_traits.cc
@@ -0,0 +1,740 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppapi_param_traits.h"
+
+#include <string.h> // For memcpy
+
+#include "ppapi/c/pp_file_info.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/proxy/serialized_flash_menu.h"
+#include "ppapi/shared_impl/host_resource.h"
+#include "ppapi/shared_impl/private/ppb_x509_certificate_private_shared.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,
+ PickleIterator* 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,
+ PickleIterator* 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, PickleIterator* 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_INVALID &&
+ system_type != PP_FILESYSTEMTYPE_EXTERNAL &&
+ system_type != PP_FILESYSTEMTYPE_LOCALPERSISTENT &&
+ system_type != PP_FILESYSTEMTYPE_LOCALTEMPORARY &&
+ system_type != PP_FILESYSTEMTYPE_ISOLATED)
+ 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_NetAddress_Private -------------------------------------------------------
+
+// static
+void ParamTraits<PP_NetAddress_Private>::Write(Message* m,
+ const param_type& p) {
+ WriteParam(m, p.size);
+ m->WriteBytes(p.data, static_cast<int>(p.size));
+}
+
+// static
+bool ParamTraits<PP_NetAddress_Private>::Read(const Message* m,
+ PickleIterator* 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_NetAddress_Private>::Log(const param_type& p,
+ std::string* l) {
+ l->append("<PP_NetAddress_Private (");
+ LogParam(p.size, l);
+ l->append(" bytes)>");
+}
+
+// TODO(teravest): Remove this when FileRef is moved to the "new" proxy.
+// PPB_FileRef_CreateInfo ------------------------------------------------------
+
+// static
+void ParamTraits<ppapi::PPB_FileRef_CreateInfo>::Write(Message* m,
+ const param_type& p) {
+ ParamTraits<ppapi::HostResource>::Write(m, p.resource);
+ ParamTraits<int>::Write(m, p.file_system_type);
+ ParamTraits<std::string>::Write(m, p.path);
+ ParamTraits<std::string>::Write(m, p.name);
+ ParamTraits<PP_Resource>::Write(m, p.file_system_plugin_resource);
+}
+
+// static
+bool ParamTraits<ppapi::PPB_FileRef_CreateInfo>::Read(const Message* m,
+ PickleIterator* iter,
+ param_type* r) {
+ return
+ ParamTraits<ppapi::HostResource>::Read(m, iter, &r->resource) &&
+ ParamTraits<int>::Read(m, iter, &r->file_system_type) &&
+ ParamTraits<std::string>::Read(m, iter, &r->path) &&
+ ParamTraits<std::string>::Read(m, iter, &r->name) &&
+ ParamTraits<PP_Resource>::Read(m, iter, &r->file_system_plugin_resource);
+}
+
+// static
+void ParamTraits<ppapi::PPB_FileRef_CreateInfo>::Log(const param_type& p,
+ std::string* l) {
+}
+
+// HostResource ----------------------------------------------------------------
+
+// static
+void ParamTraits<ppapi::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<ppapi::HostResource>::Read(const Message* m,
+ PickleIterator* 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<ppapi::HostResource>::Log(const param_type& p,
+ std::string* l) {
+}
+
+// SerializedVar ---------------------------------------------------------------
+
+// static
+void ParamTraits<ppapi::proxy::SerializedVar>::Write(Message* m,
+ const param_type& p) {
+ p.WriteToMessage(m);
+}
+
+// static
+bool ParamTraits<ppapi::proxy::SerializedVar>::Read(const Message* m,
+ PickleIterator* iter,
+ param_type* r) {
+ return r->ReadFromMessage(m, iter);
+}
+
+// static
+void ParamTraits<ppapi::proxy::SerializedVar>::Log(const param_type& p,
+ std::string* l) {
+}
+
+// std::vector<SerializedVar> --------------------------------------------------
+
+void ParamTraits< std::vector<ppapi::proxy::SerializedVar> >::Write(
+ Message* m,
+ const param_type& p) {
+ WriteVectorWithoutCopy(m, p);
+}
+
+// static
+bool ParamTraits< std::vector<ppapi::proxy::SerializedVar> >::Read(
+ const Message* m,
+ PickleIterator* iter,
+ param_type* r) {
+ return ReadVectorWithoutCopy(m, iter, r);
+}
+
+// static
+void ParamTraits< std::vector<ppapi::proxy::SerializedVar> >::Log(
+ const param_type& p,
+ std::string* l) {
+}
+
+// std::vector<PPB_FileRef_CreateInfo> -----------------------------------------
+
+void ParamTraits< std::vector<ppapi::PPB_FileRef_CreateInfo> >::Write(
+ Message* m,
+ const param_type& p) {
+ WriteVectorWithoutCopy(m, p);
+}
+
+// static
+bool ParamTraits< std::vector<ppapi::PPB_FileRef_CreateInfo> >::Read(
+ const Message* m,
+ PickleIterator* iter,
+ param_type* r) {
+ return ReadVectorWithoutCopy(m, iter, r);
+}
+
+// static
+void ParamTraits< std::vector<ppapi::PPB_FileRef_CreateInfo> >::Log(
+ const param_type& p,
+ std::string* l) {
+}
+
+// ppapi::PpapiPermissions -----------------------------------------------------
+
+void ParamTraits<ppapi::PpapiPermissions>::Write(Message* m,
+ const param_type& p) {
+ ParamTraits<uint32_t>::Write(m, p.GetBits());
+}
+
+// static
+bool ParamTraits<ppapi::PpapiPermissions>::Read(const Message* m,
+ PickleIterator* iter,
+ param_type* r) {
+ uint32_t bits;
+ if (!ParamTraits<uint32_t>::Read(m, iter, &bits))
+ return false;
+ *r = ppapi::PpapiPermissions(bits);
+ return true;
+}
+
+// static
+void ParamTraits<ppapi::PpapiPermissions>::Log(const param_type& p,
+ std::string* l) {
+}
+
+// SerializedHandle ------------------------------------------------------------
+
+// static
+void ParamTraits<ppapi::proxy::SerializedHandle>::Write(Message* m,
+ const param_type& p) {
+ ppapi::proxy::SerializedHandle::WriteHeader(p.header(), m);
+ switch (p.type()) {
+ case ppapi::proxy::SerializedHandle::SHARED_MEMORY:
+ ParamTraits<base::SharedMemoryHandle>::Write(m, p.shmem());
+ break;
+ case ppapi::proxy::SerializedHandle::SOCKET:
+ case ppapi::proxy::SerializedHandle::CHANNEL_HANDLE:
+ case ppapi::proxy::SerializedHandle::FILE:
+ ParamTraits<IPC::PlatformFileForTransit>::Write(m, p.descriptor());
+ break;
+ case ppapi::proxy::SerializedHandle::INVALID:
+ break;
+ // No default so the compiler will warn on new types.
+ }
+}
+
+// static
+bool ParamTraits<ppapi::proxy::SerializedHandle>::Read(const Message* m,
+ PickleIterator* iter,
+ param_type* r) {
+ ppapi::proxy::SerializedHandle::Header header;
+ if (!ppapi::proxy::SerializedHandle::ReadHeader(iter, &header))
+ return false;
+ switch (header.type) {
+ case ppapi::proxy::SerializedHandle::SHARED_MEMORY: {
+ base::SharedMemoryHandle handle;
+ if (ParamTraits<base::SharedMemoryHandle>::Read(m, iter, &handle)) {
+ r->set_shmem(handle, header.size);
+ return true;
+ }
+ break;
+ }
+ case ppapi::proxy::SerializedHandle::SOCKET: {
+ IPC::PlatformFileForTransit socket;
+ if (ParamTraits<IPC::PlatformFileForTransit>::Read(m, iter, &socket)) {
+ r->set_socket(socket);
+ return true;
+ }
+ break;
+ }
+ case ppapi::proxy::SerializedHandle::CHANNEL_HANDLE: {
+ IPC::PlatformFileForTransit desc;
+ if (ParamTraits<IPC::PlatformFileForTransit>::Read(m, iter, &desc)) {
+ r->set_channel_handle(desc);
+ return true;
+ }
+ break;
+ }
+ case ppapi::proxy::SerializedHandle::FILE: {
+ IPC::PlatformFileForTransit desc;
+ if (ParamTraits<IPC::PlatformFileForTransit>::Read(m, iter, &desc)) {
+ r->set_file_handle(desc, header.open_flag);
+ return true;
+ }
+ break;
+ }
+ case ppapi::proxy::SerializedHandle::INVALID:
+ return true;
+ // No default so the compiler will warn us if a new type is added.
+ }
+ return false;
+}
+
+// static
+void ParamTraits<ppapi::proxy::SerializedHandle>::Log(const param_type& p,
+ std::string* l) {
+}
+
+// PPBURLLoader_UpdateProgress_Params ------------------------------------------
+
+// static
+void ParamTraits<ppapi::proxy::PPBURLLoader_UpdateProgress_Params>::Write(
+ Message* m,
+ const param_type& p) {
+ ParamTraits<PP_Instance>::Write(m, p.instance);
+ ParamTraits<ppapi::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<ppapi::proxy::PPBURLLoader_UpdateProgress_Params>::Read(
+ const Message* m,
+ PickleIterator* iter,
+ param_type* r) {
+ return
+ ParamTraits<PP_Instance>::Read(m, iter, &r->instance) &&
+ ParamTraits<ppapi::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<ppapi::proxy::PPBURLLoader_UpdateProgress_Params>::Log(
+ const param_type& p,
+ std::string* l) {
+}
+
+#if !defined(OS_NACL) && !defined(NACL_WIN64)
+// PPBFlash_DrawGlyphs_Params --------------------------------------------------
+// static
+void ParamTraits<ppapi::proxy::PPBFlash_DrawGlyphs_Params>::Write(
+ Message* m,
+ const param_type& p) {
+ ParamTraits<PP_Instance>::Write(m, p.instance);
+ ParamTraits<ppapi::HostResource>::Write(m, p.image_data);
+ ParamTraits<ppapi::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<PP_Bool>::Write(m, p.allow_subpixel_aa);
+ ParamTraits<std::vector<uint16_t> >::Write(m, p.glyph_indices);
+ ParamTraits<std::vector<PP_Point> >::Write(m, p.glyph_advances);
+}
+
+// static
+bool ParamTraits<ppapi::proxy::PPBFlash_DrawGlyphs_Params>::Read(
+ const Message* m,
+ PickleIterator* iter,
+ param_type* r) {
+ return
+ ParamTraits<PP_Instance>::Read(m, iter, &r->instance) &&
+ ParamTraits<ppapi::HostResource>::Read(m, iter, &r->image_data) &&
+ ParamTraits<ppapi::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<PP_Bool>::Read(m, iter, &r->allow_subpixel_aa) &&
+ 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<ppapi::proxy::PPBFlash_DrawGlyphs_Params>::Log(
+ const param_type& p,
+ std::string* l) {
+}
+
+// SerializedDirEntry ----------------------------------------------------------
+
+// static
+void ParamTraits<ppapi::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<ppapi::proxy::SerializedDirEntry>::Read(const Message* m,
+ PickleIterator* iter,
+ param_type* r) {
+ return ParamTraits<std::string>::Read(m, iter, &r->name) &&
+ ParamTraits<bool>::Read(m, iter, &r->is_dir);
+}
+
+// static
+void ParamTraits<ppapi::proxy::SerializedDirEntry>::Log(const param_type& p,
+ std::string* l) {
+}
+
+// ppapi::proxy::SerializedFontDescription -------------------------------------
+
+// static
+void ParamTraits<ppapi::proxy::SerializedFontDescription>::Write(
+ Message* m,
+ const param_type& p) {
+ ParamTraits<std::string>::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<ppapi::proxy::SerializedFontDescription>::Read(
+ const Message* m,
+ PickleIterator* iter,
+ param_type* r) {
+ return
+ ParamTraits<std::string>::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<ppapi::proxy::SerializedFontDescription>::Log(
+ const param_type& p,
+ std::string* l) {
+}
+#endif // !defined(OS_NACL) && !defined(NACL_WIN64)
+
+// ppapi::proxy::SerializedTrueTypeFontDesc ------------------------------------
+
+// static
+void ParamTraits<ppapi::proxy::SerializedTrueTypeFontDesc>::Write(
+ Message* m,
+ const param_type& p) {
+ ParamTraits<std::string>::Write(m, p.family);
+ ParamTraits<PP_TrueTypeFontFamily_Dev>::Write(m, p.generic_family);
+ ParamTraits<PP_TrueTypeFontStyle_Dev>::Write(m, p.style);
+ ParamTraits<PP_TrueTypeFontWeight_Dev>::Write(m, p.weight);
+ ParamTraits<PP_TrueTypeFontWidth_Dev>::Write(m, p.width);
+ ParamTraits<PP_TrueTypeFontCharset_Dev>::Write(m, p.charset);
+}
+
+// static
+bool ParamTraits<ppapi::proxy::SerializedTrueTypeFontDesc>::Read(
+ const Message* m,
+ PickleIterator* iter,
+ param_type* r) {
+ return
+ ParamTraits<std::string>::Read(m, iter, &r->family) &&
+ ParamTraits<PP_TrueTypeFontFamily_Dev>::Read(m, iter,
+ &r->generic_family) &&
+ ParamTraits<PP_TrueTypeFontStyle_Dev>::Read(m, iter, &r->style) &&
+ ParamTraits<PP_TrueTypeFontWeight_Dev>::Read(m, iter, &r->weight) &&
+ ParamTraits<PP_TrueTypeFontWidth_Dev>::Read(m, iter, &r->width) &&
+ ParamTraits<PP_TrueTypeFontCharset_Dev>::Read(m, iter, &r->charset);
+}
+
+// static
+void ParamTraits<ppapi::proxy::SerializedTrueTypeFontDesc>::Log(
+ const param_type& p,
+ std::string* l) {
+}
+
+#if !defined(OS_NACL) && !defined(NACL_WIN64)
+// ppapi::PepperFilePath -------------------------------------------------------
+
+// static
+void ParamTraits<ppapi::PepperFilePath>::Write(Message* m,
+ const param_type& p) {
+ WriteParam(m, static_cast<unsigned>(p.domain()));
+ WriteParam(m, p.path());
+}
+
+// static
+bool ParamTraits<ppapi::PepperFilePath>::Read(const Message* m,
+ PickleIterator* iter,
+ param_type* p) {
+ unsigned domain;
+ base::FilePath path;
+ if (!ReadParam(m, iter, &domain) || !ReadParam(m, iter, &path))
+ return false;
+ if (domain > ppapi::PepperFilePath::DOMAIN_MAX_VALID)
+ return false;
+
+ *p = ppapi::PepperFilePath(
+ static_cast<ppapi::PepperFilePath::Domain>(domain), path);
+ return true;
+}
+
+// static
+void ParamTraits<ppapi::PepperFilePath>::Log(const param_type& p,
+ std::string* l) {
+ l->append("(");
+ LogParam(static_cast<unsigned>(p.domain()), l);
+ l->append(", ");
+ LogParam(p.path(), l);
+ l->append(")");
+}
+
+// SerializedFlashMenu ---------------------------------------------------------
+
+// static
+void ParamTraits<ppapi::proxy::SerializedFlashMenu>::Write(
+ Message* m,
+ const param_type& p) {
+ p.WriteToMessage(m);
+}
+
+// static
+bool ParamTraits<ppapi::proxy::SerializedFlashMenu>::Read(const Message* m,
+ PickleIterator* iter,
+ param_type* r) {
+ return r->ReadFromMessage(m, iter);
+}
+
+// static
+void ParamTraits<ppapi::proxy::SerializedFlashMenu>::Log(const param_type& p,
+ std::string* l) {
+}
+#endif // !defined(OS_NACL) && !defined(NACL_WIN64)
+
+// PPB_X509Certificate_Fields --------------------------------------------------
+
+// static
+void ParamTraits<ppapi::PPB_X509Certificate_Fields>::Write(
+ Message* m,
+ const param_type& p) {
+ ParamTraits<base::ListValue>::Write(m, p.values_);
+}
+
+// static
+bool ParamTraits<ppapi::PPB_X509Certificate_Fields>::Read(const Message* m,
+ PickleIterator* iter,
+ param_type* r) {
+ return ParamTraits<base::ListValue>::Read(m, iter, &(r->values_));
+}
+
+// static
+void ParamTraits<ppapi::PPB_X509Certificate_Fields>::Log(const param_type& p,
+ std::string* l) {
+}
+
+// ppapi::SocketOptionData -----------------------------------------------------
+
+// static
+void ParamTraits<ppapi::SocketOptionData>::Write(Message* m,
+ const param_type& p) {
+ ppapi::SocketOptionData::Type type = p.GetType();
+ ParamTraits<int32_t>::Write(m, static_cast<int32_t>(type));
+ switch (type) {
+ case ppapi::SocketOptionData::TYPE_INVALID: {
+ break;
+ }
+ case ppapi::SocketOptionData::TYPE_BOOL: {
+ bool out_value = false;
+ bool result = p.GetBool(&out_value);
+ // Suppress unused variable warnings.
+ static_cast<void>(result);
+ DCHECK(result);
+
+ ParamTraits<bool>::Write(m, out_value);
+ break;
+ }
+ case ppapi::SocketOptionData::TYPE_INT32: {
+ int32_t out_value = 0;
+ bool result = p.GetInt32(&out_value);
+ // Suppress unused variable warnings.
+ static_cast<void>(result);
+ DCHECK(result);
+
+ ParamTraits<int32_t>::Write(m, out_value);
+ break;
+ }
+ // No default so the compiler will warn on new types.
+ }
+}
+
+// static
+bool ParamTraits<ppapi::SocketOptionData>::Read(const Message* m,
+ PickleIterator* iter,
+ param_type* r) {
+ *r = ppapi::SocketOptionData();
+ int32_t type = 0;
+ if (!ParamTraits<int32_t>::Read(m, iter, &type))
+ return false;
+ if (type != ppapi::SocketOptionData::TYPE_INVALID &&
+ type != ppapi::SocketOptionData::TYPE_BOOL &&
+ type != ppapi::SocketOptionData::TYPE_INT32) {
+ return false;
+ }
+ switch (static_cast<ppapi::SocketOptionData::Type>(type)) {
+ case ppapi::SocketOptionData::TYPE_INVALID: {
+ return true;
+ }
+ case ppapi::SocketOptionData::TYPE_BOOL: {
+ bool value = false;
+ if (!ParamTraits<bool>::Read(m, iter, &value))
+ return false;
+ r->SetBool(value);
+ return true;
+ }
+ case ppapi::SocketOptionData::TYPE_INT32: {
+ int32_t value = 0;
+ if (!ParamTraits<int32_t>::Read(m, iter, &value))
+ return false;
+ r->SetInt32(value);
+ return true;
+ }
+ // No default so the compiler will warn on new types.
+ }
+ return false;
+}
+
+// static
+void ParamTraits<ppapi::SocketOptionData>::Log(const param_type& p,
+ std::string* l) {
+}
+
+} // namespace IPC
diff --git a/chromium/ppapi/proxy/ppapi_param_traits.h b/chromium/ppapi/proxy/ppapi_param_traits.h
new file mode 100644
index 00000000000..f56415a869f
--- /dev/null
+++ b/chromium/ppapi/proxy/ppapi_param_traits.h
@@ -0,0 +1,209 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_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_rect.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/file_path.h"
+#include "ppapi/shared_impl/file_ref_create_info.h"
+#include "ppapi/shared_impl/ppapi_permissions.h"
+#include "ppapi/shared_impl/ppb_file_ref_shared.h"
+#include "ppapi/shared_impl/socket_option_data.h"
+
+struct PP_FileInfo;
+struct PP_NetAddress_Private;
+
+namespace ppapi {
+
+class HostResource;
+class PPB_X509Certificate_Fields;
+
+namespace proxy {
+
+struct PPBFlash_DrawGlyphs_Params;
+struct PPBURLLoader_UpdateProgress_Params;
+struct SerializedDirEntry;
+struct SerializedFontDescription;
+struct SerializedTrueTypeFontDesc;
+class SerializedFlashMenu;
+class SerializedHandle;
+class SerializedVar;
+
+} // namespace proxy
+} // namespace ppapi
+
+namespace IPC {
+
+template<>
+struct PPAPI_PROXY_EXPORT ParamTraits<PP_Bool> {
+ typedef PP_Bool param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct PPAPI_PROXY_EXPORT ParamTraits<PP_FileInfo> {
+ typedef PP_FileInfo param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct PPAPI_PROXY_EXPORT ParamTraits<PP_NetAddress_Private> {
+ typedef PP_NetAddress_Private param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* p);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct PPAPI_PROXY_EXPORT ParamTraits<
+ ppapi::proxy::PPBFlash_DrawGlyphs_Params> {
+ typedef ppapi::proxy::PPBFlash_DrawGlyphs_Params param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+// TODO(teravest): Remove this when we've switched over to the new proxy.
+template<>
+struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::PPB_FileRef_CreateInfo> {
+ typedef ppapi::PPB_FileRef_CreateInfo param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct PPAPI_PROXY_EXPORT ParamTraits<
+ ppapi::proxy::PPBURLLoader_UpdateProgress_Params> {
+ typedef ppapi::proxy::PPBURLLoader_UpdateProgress_Params param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::proxy::SerializedDirEntry> {
+ typedef ppapi::proxy::SerializedDirEntry param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::proxy::SerializedFontDescription> {
+ typedef ppapi::proxy::SerializedFontDescription param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct PPAPI_PROXY_EXPORT
+ ParamTraits<ppapi::proxy::SerializedTrueTypeFontDesc> {
+ typedef ppapi::proxy::SerializedTrueTypeFontDesc param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::proxy::SerializedHandle> {
+ typedef ppapi::proxy::SerializedHandle param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::HostResource> {
+ typedef ppapi::HostResource param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::proxy::SerializedVar> {
+ typedef ppapi::proxy::SerializedVar param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct PPAPI_PROXY_EXPORT ParamTraits<
+ std::vector<ppapi::proxy::SerializedVar> > {
+ typedef std::vector<ppapi::proxy::SerializedVar> param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct PPAPI_PROXY_EXPORT ParamTraits< std::vector<
+ ppapi::PPB_FileRef_CreateInfo> > {
+ typedef std::vector<ppapi::PPB_FileRef_CreateInfo> param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::PpapiPermissions> {
+ typedef ppapi::PpapiPermissions param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+#if !defined(OS_NACL) && !defined(NACL_WIN64)
+template <>
+struct ParamTraits<ppapi::PepperFilePath> {
+ typedef ppapi::PepperFilePath param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* p);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::proxy::SerializedFlashMenu> {
+ typedef ppapi::proxy::SerializedFlashMenu param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+#endif // !defined(OS_NACL) && !defined(NACL_WIN64)
+
+template<>
+struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::PPB_X509Certificate_Fields> {
+ typedef ppapi::PPB_X509Certificate_Fields param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template<>
+struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::SocketOptionData> {
+ typedef ppapi::SocketOptionData param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* 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/chromium/ppapi/proxy/ppapi_perftests.cc b/chromium/ppapi/proxy/ppapi_perftests.cc
new file mode 100644
index 00000000000..a9138e6a2a2
--- /dev/null
+++ b/chromium/ppapi/proxy/ppapi_perftests.cc
@@ -0,0 +1,10 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/test/perf_test_suite.h"
+
+int main(int argc, char** argv) {
+ return base::PerfTestSuite(argc, argv).Run();
+}
+
diff --git a/chromium/ppapi/proxy/ppapi_proxy_export.h b/chromium/ppapi/proxy/ppapi_proxy_export.h
new file mode 100644
index 00000000000..be86da43d6e
--- /dev/null
+++ b/chromium/ppapi/proxy/ppapi_proxy_export.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_PPAPI_PROXY_EXPORT_H_
+#define PPAPI_PROXY_PPAPI_PROXY_EXPORT_H_
+
+#if defined(COMPONENT_BUILD) && !defined(NACL_WIN64)
+#if defined(WIN32)
+
+#if defined(PPAPI_PROXY_IMPLEMENTATION)
+#define PPAPI_PROXY_EXPORT __declspec(dllexport)
+#else
+#define PPAPI_PROXY_EXPORT __declspec(dllimport)
+#endif // defined(PPAPI_PROXY_IMPLEMENTATION)
+
+#else // defined(WIN32)
+#if defined(PPAPI_PROXY_IMPLEMENTATION)
+#define PPAPI_PROXY_EXPORT __attribute__((visibility("default")))
+#else
+#define PPAPI_PROXY_EXPORT
+#endif
+#endif
+
+#else // defined(COMPONENT_BUILD) && !defined(NACL_WIN64)
+#define PPAPI_PROXY_EXPORT
+#endif
+
+#endif // PPAPI_PROXY_PPAPI_PROXY_EXPORT_H_
diff --git a/chromium/ppapi/proxy/ppapi_proxy_test.cc b/chromium/ppapi/proxy/ppapi_proxy_test.cc
new file mode 100644
index 00000000000..5e4b67bc4f3
--- /dev/null
+++ b/chromium/ppapi/proxy/ppapi_proxy_test.cc
@@ -0,0 +1,592 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppapi_proxy_test.h"
+
+#include <sstream>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/observer_list.h"
+#include "base/run_loop.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/proxy/ppb_message_loop_proxy.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+
+namespace ppapi {
+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.
+}
+
+void AddRefModule(PP_Module module) {}
+void ReleaseModule(PP_Module module) {}
+PP_Bool IsInModuleDestructor(PP_Module module) { return PP_FALSE; }
+
+PPB_Proxy_Private ppb_proxy_private = {
+ &PluginCrashed,
+ &GetInstanceForResource,
+ &SetReserveInstanceIDCallback,
+ &AddRefModule,
+ &ReleaseModule,
+ &IsInModuleDestructor
+};
+
+// 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();
+}
+
+void RunTaskOnRemoteHarness(const base::Closure& task,
+ base::WaitableEvent* task_complete) {
+ task.Run();
+ task_complete->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* test_interface) {
+ registered_interfaces_[name] = test_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(
+ GlobalsConfiguration globals_config)
+ : globals_config_(globals_config) {
+}
+
+PluginProxyTestHarness::~PluginProxyTestHarness() {
+}
+
+PpapiGlobals* PluginProxyTestHarness::GetGlobals() {
+ return plugin_globals_.get();
+}
+
+Dispatcher* PluginProxyTestHarness::GetDispatcher() {
+ return plugin_dispatcher_.get();
+}
+
+void PluginProxyTestHarness::SetUpHarness() {
+ // These must be first since the dispatcher set-up uses them.
+ CreatePluginGlobals();
+ // Some of the methods called during set-up check that the lock is held.
+ ProxyAutoLock lock;
+
+ resource_tracker().DidCreateInstance(pp_instance());
+
+ plugin_dispatcher_.reset(new PluginDispatcher(
+ &MockGetInterface,
+ PpapiPermissions(),
+ false));
+ plugin_dispatcher_->InitWithTestSink(&sink());
+ // The plugin proxy delegate is needed for
+ // |PluginProxyDelegate::GetBrowserSender| which is used
+ // in |ResourceCreationProxy::GetConnection| to get the channel to the
+ // browser. In this case we just use the |plugin_dispatcher_| as the channel
+ // for test purposes.
+ plugin_delegate_mock_.set_browser_sender(plugin_dispatcher_.get());
+ PluginGlobals::Get()->set_plugin_proxy_delegate(&plugin_delegate_mock_);
+ 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.
+ CreatePluginGlobals();
+ // Some of the methods called during set-up check that the lock is held.
+ ProxyAutoLock lock;
+
+ resource_tracker().DidCreateInstance(pp_instance());
+ plugin_delegate_mock_.Init(ipc_message_loop, shutdown_event);
+
+ plugin_dispatcher_.reset(new PluginDispatcher(
+ &MockGetInterface,
+ PpapiPermissions(),
+ false));
+ plugin_dispatcher_->InitPluginWithChannel(&plugin_delegate_mock_,
+ base::kNullProcessId,
+ channel_handle,
+ is_client);
+ plugin_delegate_mock_.set_browser_sender(plugin_dispatcher_.get());
+ PluginGlobals::Get()->set_plugin_proxy_delegate(&plugin_delegate_mock_);
+ plugin_dispatcher_->DidCreateInstance(pp_instance());
+}
+
+void PluginProxyTestHarness::TearDownHarness() {
+ {
+ // Some of the methods called during tear-down check that the lock is held.
+ ProxyAutoLock lock;
+
+ plugin_dispatcher_->DidDestroyInstance(pp_instance());
+ plugin_dispatcher_.reset();
+
+ resource_tracker().DidDeleteInstance(pp_instance());
+ }
+ plugin_globals_.reset();
+}
+
+void PluginProxyTestHarness::CreatePluginGlobals() {
+ if (globals_config_ == PER_THREAD_GLOBALS) {
+ plugin_globals_.reset(new PluginGlobals(PpapiGlobals::PerThreadForTest()));
+ PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals());
+ } else {
+ plugin_globals_.reset(new PluginGlobals());
+ }
+}
+
+base::MessageLoopProxy*
+PluginProxyTestHarness::PluginDelegateMock::GetIPCMessageLoop() {
+ return ipc_message_loop_;
+}
+
+base::WaitableEvent*
+PluginProxyTestHarness::PluginDelegateMock::GetShutdownEvent() {
+ return shutdown_event_;
+}
+
+IPC::PlatformFileForTransit
+PluginProxyTestHarness::PluginDelegateMock::ShareHandleWithRemote(
+ base::PlatformFile handle,
+ base::ProcessId /* remote_pid */,
+ bool should_close_source) {
+ return IPC::GetFileHandleForProcess(handle,
+ base::Process::Current().handle(),
+ should_close_source);
+}
+
+std::set<PP_Instance>*
+PluginProxyTestHarness::PluginDelegateMock::GetGloballySeenInstanceIDSet() {
+ return &instance_id_set_;
+}
+
+uint32 PluginProxyTestHarness::PluginDelegateMock::Register(
+ PluginDispatcher* plugin_dispatcher) {
+ return 0;
+}
+
+void PluginProxyTestHarness::PluginDelegateMock::Unregister(
+ uint32 plugin_dispatcher_id) {
+}
+
+IPC::Sender* PluginProxyTestHarness::PluginDelegateMock::GetBrowserSender() {
+ return browser_sender_;
+}
+
+std::string PluginProxyTestHarness::PluginDelegateMock::GetUILanguage() {
+ return std::string("en-US");
+}
+
+void PluginProxyTestHarness::PluginDelegateMock::PreCacheFont(
+ const void* logfontw) {
+}
+
+void PluginProxyTestHarness::PluginDelegateMock::SetActiveURL(
+ const std::string& url) {
+}
+
+PP_Resource PluginProxyTestHarness::PluginDelegateMock::CreateBrowserFont(
+ Connection connection,
+ PP_Instance instance,
+ const PP_BrowserFont_Trusted_Description& desc,
+ const Preferences& prefs) {
+ return 0;
+}
+
+// PluginProxyTest -------------------------------------------------------------
+
+PluginProxyTest::PluginProxyTest() : PluginProxyTestHarness(SINGLETON_GLOBALS) {
+}
+
+PluginProxyTest::~PluginProxyTest() {
+}
+
+void PluginProxyTest::SetUp() {
+ SetUpHarness();
+}
+
+void PluginProxyTest::TearDown() {
+ TearDownHarness();
+}
+
+// PluginProxyMultiThreadTest --------------------------------------------------
+
+PluginProxyMultiThreadTest::PluginProxyMultiThreadTest() {
+}
+
+PluginProxyMultiThreadTest::~PluginProxyMultiThreadTest() {
+}
+
+void PluginProxyMultiThreadTest::RunTest() {
+ main_thread_message_loop_proxy_ =
+ PpapiGlobals::Get()->GetMainThreadMessageLoop();
+ ASSERT_EQ(main_thread_message_loop_proxy_.get(),
+ base::MessageLoopProxy::current());
+ nested_main_thread_message_loop_.reset(new base::RunLoop());
+
+ secondary_thread_.reset(new base::DelegateSimpleThread(
+ this, "PluginProxyMultiThreadTest"));
+
+ {
+ ProxyAutoLock auto_lock;
+
+ // MessageLoopResource assumes that the proxy lock has been acquired.
+ secondary_thread_message_loop_ = new MessageLoopResource(pp_instance());
+
+ ASSERT_EQ(PP_OK,
+ secondary_thread_message_loop_->PostWork(
+ PP_MakeCompletionCallback(
+ &PluginProxyMultiThreadTest::InternalSetUpTestOnSecondaryThread,
+ this),
+ 0));
+ }
+
+ SetUpTestOnMainThread();
+
+ secondary_thread_->Start();
+ nested_main_thread_message_loop_->Run();
+ secondary_thread_->Join();
+
+ {
+ ProxyAutoLock auto_lock;
+
+ // The destruction requires a valid PpapiGlobals instance, so we should
+ // explicitly release it.
+ secondary_thread_message_loop_ = NULL;
+ }
+
+ secondary_thread_.reset(NULL);
+ nested_main_thread_message_loop_.reset(NULL);
+ main_thread_message_loop_proxy_ = NULL;
+}
+
+void PluginProxyMultiThreadTest::CheckOnThread(ThreadType thread_type) {
+ ProxyAutoLock auto_lock;
+ if (thread_type == MAIN_THREAD) {
+ ASSERT_TRUE(MessageLoopResource::GetCurrent()->is_main_thread_loop());
+ } else {
+ ASSERT_EQ(secondary_thread_message_loop_.get(),
+ MessageLoopResource::GetCurrent());
+ }
+}
+
+void PluginProxyMultiThreadTest::PostQuitForMainThread() {
+ main_thread_message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&PluginProxyMultiThreadTest::QuitNestedLoop,
+ base::Unretained(this)));
+}
+
+void PluginProxyMultiThreadTest::PostQuitForSecondaryThread() {
+ ProxyAutoLock auto_lock;
+ secondary_thread_message_loop_->PostQuit(PP_TRUE);
+}
+
+void PluginProxyMultiThreadTest::Run() {
+ ProxyAutoLock auto_lock;
+ ASSERT_EQ(PP_OK, secondary_thread_message_loop_->AttachToCurrentThread());
+ ASSERT_EQ(PP_OK, secondary_thread_message_loop_->Run());
+ secondary_thread_message_loop_->DetachFromThread();
+}
+
+void PluginProxyMultiThreadTest::QuitNestedLoop() {
+ nested_main_thread_message_loop_->Quit();
+}
+
+// static
+void PluginProxyMultiThreadTest::InternalSetUpTestOnSecondaryThread(
+ void* user_data,
+ int32_t result) {
+ EXPECT_EQ(PP_OK, result);
+ PluginProxyMultiThreadTest* thiz =
+ static_cast<PluginProxyMultiThreadTest*>(user_data);
+ thiz->CheckOnThread(SECONDARY_THREAD);
+ thiz->SetUpTestOnSecondaryThread();
+}
+
+// HostProxyTestHarness --------------------------------------------------------
+
+class HostProxyTestHarness::MockSyncMessageStatusReceiver
+ : public HostDispatcher::SyncMessageStatusReceiver {
+ public:
+ virtual void BeginBlockOnSyncMessage() OVERRIDE {}
+ virtual void EndBlockOnSyncMessage() OVERRIDE {}
+};
+
+HostProxyTestHarness::HostProxyTestHarness(GlobalsConfiguration globals_config)
+ : globals_config_(globals_config),
+ status_receiver_(new MockSyncMessageStatusReceiver) {
+}
+
+HostProxyTestHarness::~HostProxyTestHarness() {
+}
+
+PpapiGlobals* HostProxyTestHarness::GetGlobals() {
+ return host_globals_.get();
+}
+
+Dispatcher* HostProxyTestHarness::GetDispatcher() {
+ return host_dispatcher_.get();
+}
+
+void HostProxyTestHarness::SetUpHarness() {
+ // These must be first since the dispatcher set-up uses them.
+ CreateHostGlobals();
+
+ host_dispatcher_.reset(new HostDispatcher(
+ pp_module(),
+ &MockGetInterface,
+ status_receiver_.release(),
+ PpapiPermissions::AllPermissions()));
+ 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) {
+ // These must be first since the dispatcher set-up uses them.
+ CreateHostGlobals();
+
+ delegate_mock_.Init(ipc_message_loop, shutdown_event);
+
+ host_dispatcher_.reset(new HostDispatcher(
+ pp_module(),
+ &MockGetInterface,
+ status_receiver_.release(),
+ PpapiPermissions::AllPermissions()));
+ ppapi::Preferences preferences;
+ host_dispatcher_->InitHostWithChannel(&delegate_mock_,
+ base::kNullProcessId, channel_handle,
+ is_client, preferences);
+ HostDispatcher::SetForInstance(pp_instance(), host_dispatcher_.get());
+}
+
+void HostProxyTestHarness::TearDownHarness() {
+ HostDispatcher::RemoveForInstance(pp_instance());
+ host_dispatcher_.reset();
+ host_globals_.reset();
+}
+
+void HostProxyTestHarness::CreateHostGlobals() {
+ if (globals_config_ == PER_THREAD_GLOBALS) {
+ host_globals_.reset(new TestGlobals(PpapiGlobals::PerThreadForTest()));
+ PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals());
+ } else {
+ host_globals_.reset(new TestGlobals());
+ }
+}
+
+base::MessageLoopProxy*
+HostProxyTestHarness::DelegateMock::GetIPCMessageLoop() {
+ return ipc_message_loop_;
+}
+
+base::WaitableEvent* HostProxyTestHarness::DelegateMock::GetShutdownEvent() {
+ return shutdown_event_;
+}
+
+IPC::PlatformFileForTransit
+HostProxyTestHarness::DelegateMock::ShareHandleWithRemote(
+ base::PlatformFile handle,
+ base::ProcessId /* remote_pid */,
+ bool should_close_source) {
+ return IPC::GetFileHandleForProcess(handle,
+ base::Process::Current().handle(),
+ should_close_source);
+}
+
+
+// HostProxyTest ---------------------------------------------------------------
+
+HostProxyTest::HostProxyTest() : HostProxyTestHarness(SINGLETON_GLOBALS) {
+}
+
+HostProxyTest::~HostProxyTest() {
+}
+
+void HostProxyTest::SetUp() {
+ SetUpHarness();
+}
+
+void HostProxyTest::TearDown() {
+ TearDownHarness();
+}
+
+// TwoWayTest ---------------------------------------------------------------
+
+TwoWayTest::TwoWayTest(TwoWayTest::TwoWayTestMode test_mode)
+ : test_mode_(test_mode),
+ host_(ProxyTestHarnessBase::PER_THREAD_GLOBALS),
+ plugin_(ProxyTestHarnessBase::PER_THREAD_GLOBALS),
+ 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 = base::MessageLoop::TYPE_IO;
+ io_thread_.StartWithOptions(options);
+ plugin_thread_.Start();
+
+ // Construct the IPC handle name using the process ID so we can safely run
+ // multiple |TwoWayTest|s concurrently.
+ std::ostringstream handle_name;
+ handle_name << "TwoWayTestChannel" << base::GetCurrentProcId();
+ IPC::ChannelHandle handle(handle_name.str());
+ base::WaitableEvent remote_harness_set_up(true, false);
+ plugin_thread_.message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(&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().get(),
+ &shutdown_event_,
+ true); // is_client
+}
+
+void TwoWayTest::TearDown() {
+ base::WaitableEvent remote_harness_torn_down(true, false);
+ plugin_thread_.message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(&TearDownRemoteHarness,
+ remote_harness_,
+ &remote_harness_torn_down));
+ remote_harness_torn_down.Wait();
+
+ local_harness_->TearDownHarness();
+
+ io_thread_.Stop();
+}
+
+void TwoWayTest::PostTaskOnRemoteHarness(const base::Closure& task) {
+ base::WaitableEvent task_complete(true, false);
+ plugin_thread_.message_loop_proxy()->PostTask(FROM_HERE,
+ base::Bind(&RunTaskOnRemoteHarness,
+ task,
+ &task_complete));
+ task_complete.Wait();
+}
+
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppapi_proxy_test.h b/chromium/ppapi/proxy/ppapi_proxy_test.h
new file mode 100644
index 00000000000..9a2df1c5d2c
--- /dev/null
+++ b/chromium/ppapi/proxy/ppapi_proxy_test.h
@@ -0,0 +1,372 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <map>
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/simple_thread.h"
+#include "base/threading/thread.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/plugin_proxy_delegate.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+#include "ppapi/proxy/resource_message_test_sink.h"
+#include "ppapi/shared_impl/test_globals.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+class MessageLoopProxy;
+class RunLoop;
+}
+
+namespace ppapi {
+namespace proxy {
+
+class MessageLoopResource;
+
+// Base class for plugin and host test harnesses. Tests will not use this
+// directly. Instead, use the PluginProxyTest, HostProxyTest, or TwoWayTest.
+class ProxyTestHarnessBase {
+ public:
+ enum GlobalsConfiguration {
+ PER_THREAD_GLOBALS,
+ SINGLETON_GLOBALS
+ };
+
+ ProxyTestHarnessBase();
+ virtual ~ProxyTestHarnessBase();
+
+ PP_Module pp_module() const { return pp_module_; }
+ PP_Instance pp_instance() const { return pp_instance_; }
+ ResourceMessageTestSink& sink() { return sink_; }
+
+ virtual PpapiGlobals* GetGlobals() = 0;
+ // 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* test_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.
+ ResourceMessageTestSink 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:
+ explicit PluginProxyTestHarness(GlobalsConfiguration globals_config);
+ virtual ~PluginProxyTestHarness();
+
+ PluginDispatcher* plugin_dispatcher() { return plugin_dispatcher_.get(); }
+ PluginResourceTracker& resource_tracker() {
+ return *plugin_globals_->plugin_resource_tracker();
+ }
+ PluginVarTracker& var_tracker() {
+ return *plugin_globals_->plugin_var_tracker();
+ }
+
+ // ProxyTestHarnessBase implementation.
+ virtual PpapiGlobals* GetGlobals();
+ 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 PluginProxyDelegate {
+ 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;
+ }
+
+ void set_browser_sender(IPC::Sender* browser_sender) {
+ browser_sender_ = browser_sender;
+ }
+
+ // ProxyChannel::Delegate implementation.
+ virtual base::MessageLoopProxy* GetIPCMessageLoop() OVERRIDE;
+ virtual base::WaitableEvent* GetShutdownEvent() OVERRIDE;
+ virtual IPC::PlatformFileForTransit ShareHandleWithRemote(
+ base::PlatformFile handle,
+ base::ProcessId remote_pid,
+ bool should_close_source) OVERRIDE;
+
+ // PluginDispatcher::PluginDelegate implementation.
+ virtual std::set<PP_Instance>* GetGloballySeenInstanceIDSet() OVERRIDE;
+ virtual uint32 Register(PluginDispatcher* plugin_dispatcher) OVERRIDE;
+ virtual void Unregister(uint32 plugin_dispatcher_id) OVERRIDE;
+
+ // PluginProxyDelegate implementation.
+ virtual IPC::Sender* GetBrowserSender() OVERRIDE;
+ virtual std::string GetUILanguage() OVERRIDE;
+ virtual void PreCacheFont(const void* logfontw) OVERRIDE;
+ virtual void SetActiveURL(const std::string& url) OVERRIDE;
+ virtual PP_Resource CreateBrowserFont(
+ Connection connection,
+ PP_Instance instance,
+ const PP_BrowserFont_Trusted_Description& desc,
+ const Preferences& prefs) OVERRIDE;
+
+ private:
+ base::MessageLoopProxy* ipc_message_loop_; // Weak
+ base::WaitableEvent* shutdown_event_; // Weak
+ std::set<PP_Instance> instance_id_set_;
+ IPC::Sender* browser_sender_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginDelegateMock);
+ };
+
+ private:
+ void CreatePluginGlobals();
+
+ GlobalsConfiguration globals_config_;
+ scoped_ptr<PluginGlobals> plugin_globals_;
+
+ 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:
+ base::MessageLoop message_loop_;
+};
+
+// This class provides support for multi-thread testing. A secondary thread is
+// created with a Pepper message loop.
+// Subclasses need to implement the two SetUpTestOn*Thread() methods to do the
+// actual testing work; and call both PostQuitFor*Thread() when testing is
+// done.
+class PluginProxyMultiThreadTest
+ : public PluginProxyTest,
+ public base::DelegateSimpleThread::Delegate {
+ public:
+ PluginProxyMultiThreadTest();
+ virtual ~PluginProxyMultiThreadTest();
+
+ // Called before the secondary thread is started, but after all the member
+ // variables, including |secondary_thread_| and
+ // |secondary_thread_message_loop_|, are initialized.
+ virtual void SetUpTestOnMainThread() = 0;
+
+ virtual void SetUpTestOnSecondaryThread() = 0;
+
+ // TEST_F() should call this method.
+ void RunTest();
+
+ enum ThreadType {
+ MAIN_THREAD,
+ SECONDARY_THREAD
+ };
+ void CheckOnThread(ThreadType thread_type);
+
+ // These can be called on any thread.
+ void PostQuitForMainThread();
+ void PostQuitForSecondaryThread();
+
+ protected:
+ scoped_refptr<MessageLoopResource> secondary_thread_message_loop_;
+ scoped_refptr<base::MessageLoopProxy> main_thread_message_loop_proxy_;
+
+ private:
+ // base::DelegateSimpleThread::Delegate implementation.
+ virtual void Run() OVERRIDE;
+
+ void QuitNestedLoop();
+
+ static void InternalSetUpTestOnSecondaryThread(void* user_data,
+ int32_t result);
+
+ scoped_ptr<base::DelegateSimpleThread> secondary_thread_;
+ scoped_ptr<base::RunLoop> nested_main_thread_message_loop_;
+};
+
+class HostProxyTestHarness : public ProxyTestHarnessBase {
+ public:
+ explicit HostProxyTestHarness(GlobalsConfiguration globals_config);
+ virtual ~HostProxyTestHarness();
+
+ HostDispatcher* host_dispatcher() { return host_dispatcher_.get(); }
+ ResourceTracker& resource_tracker() {
+ return *host_globals_->GetResourceTracker();
+ }
+ VarTracker& var_tracker() {
+ return *host_globals_->GetVarTracker();
+ }
+
+ // ProxyTestBase implementation.
+ virtual PpapiGlobals* GetGlobals();
+ 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();
+ virtual IPC::PlatformFileForTransit ShareHandleWithRemote(
+ base::PlatformFile handle,
+ base::ProcessId remote_pid,
+ bool should_close_source) OVERRIDE;
+
+ private:
+ base::MessageLoopProxy* ipc_message_loop_; // Weak
+ base::WaitableEvent* shutdown_event_; // Weak
+
+ DISALLOW_COPY_AND_ASSIGN(DelegateMock);
+ };
+
+ private:
+ class MockSyncMessageStatusReceiver;
+
+ void CreateHostGlobals();
+
+ GlobalsConfiguration globals_config_;
+ scoped_ptr<ppapi::TestGlobals> host_globals_;
+ scoped_ptr<HostDispatcher> host_dispatcher_;
+ DelegateMock delegate_mock_;
+
+ scoped_ptr<MockSyncMessageStatusReceiver> status_receiver_;
+};
+
+class HostProxyTest : public HostProxyTestHarness, public testing::Test {
+ public:
+ HostProxyTest();
+ virtual ~HostProxyTest();
+
+ // testing::Test implementation.
+ virtual void SetUp();
+ virtual void TearDown();
+ private:
+ base::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();
+
+ protected:
+ // Post a task to the thread where the remote harness lives. This
+ // is typically used to test the state of the var tracker on the plugin
+ // thread. This runs the task synchronously for convenience.
+ void PostTaskOnRemoteHarness(const base::Closure& task);
+
+ 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.
+ base::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_;
+};
+
+// Used during Gtests when you have a PP_Var that you want to EXPECT is equal
+// to a certain constant string value:
+//
+// EXPECT_VAR_IS_STRING("foo", my_var);
+#define EXPECT_VAR_IS_STRING(str, var) { \
+ StringVar* sv = StringVar::FromPPVar(var); \
+ EXPECT_TRUE(sv); \
+ if (sv) \
+ EXPECT_EQ(str, sv->value()); \
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppb_audio_proxy.cc b/chromium/ppapi/proxy/ppb_audio_proxy.cc
new file mode 100644
index 00000000000..aae9a5de198
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_audio_proxy.cc
@@ -0,0 +1,349 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppb_audio_proxy.h"
+
+#include "base/compiler_specific.h"
+#include "base/threading/simple_thread.h"
+#include "media/audio/shared_memory_util.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/proxy/enter_proxy.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/api_id.h"
+#include "ppapi/shared_impl/platform_file.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/ppb_audio_shared.h"
+#include "ppapi/shared_impl/resource.h"
+#include "ppapi/thunk/ppb_audio_config_api.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/resource_creation_api.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::IntToPlatformFile;
+using ppapi::proxy::SerializedHandle;
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_Audio_API;
+using ppapi::thunk::PPB_AudioConfig_API;
+
+namespace ppapi {
+namespace proxy {
+
+class Audio : public Resource, public PPB_Audio_Shared {
+ public:
+ Audio(const HostResource& audio_id,
+ PP_Resource config_id,
+ PPB_Audio_Callback callback,
+ void* user_data);
+ virtual ~Audio();
+
+ // Resource 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;
+ virtual int32_t Open(
+ PP_Resource config_id,
+ scoped_refptr<TrackedCallback> create_callback) OVERRIDE;
+ virtual int32_t GetSyncSocket(int* sync_socket) OVERRIDE;
+ virtual int32_t GetSharedMemory(int* shm_handle, uint32_t* shm_size) 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)
+ : Resource(OBJECT_IS_PROXY, audio_id),
+ config_(config_id) {
+ SetCallback(callback, user_data);
+ PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(config_);
+}
+
+Audio::~Audio() {
+#if defined(OS_NACL)
+ // Invoke StopPlayback() to ensure audio back-end has a chance to send the
+ // escape value over the sync socket, which will terminate the client side
+ // audio callback loop. This is required for NaCl Plugins that can't escape
+ // by shutting down the sync_socket.
+ StopPlayback();
+#endif
+ PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(config_);
+}
+
+PPB_Audio_API* Audio::AsPPB_Audio_API() {
+ return this;
+}
+
+PP_Resource Audio::GetCurrentConfig() {
+ // AddRef for the caller.
+ PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(config_);
+ return config_;
+}
+
+PP_Bool Audio::StartPlayback() {
+ if (playing())
+ return PP_TRUE;
+ SetStartPlaybackState();
+ PluginDispatcher::GetForResource(this)->Send(
+ new PpapiHostMsg_PPBAudio_StartOrStop(
+ API_ID_PPB_AUDIO, host_resource(), true));
+ return PP_TRUE;
+}
+
+PP_Bool Audio::StopPlayback() {
+ if (!playing())
+ return PP_TRUE;
+ PluginDispatcher::GetForResource(this)->Send(
+ new PpapiHostMsg_PPBAudio_StartOrStop(
+ API_ID_PPB_AUDIO, host_resource(), false));
+ SetStopPlaybackState();
+ return PP_TRUE;
+}
+
+int32_t Audio::Open(PP_Resource config_id,
+ scoped_refptr<TrackedCallback> create_callback) {
+ return PP_ERROR_NOTSUPPORTED; // Don't proxy the trusted interface.
+}
+
+int32_t Audio::GetSyncSocket(int* sync_socket) {
+ return PP_ERROR_NOTSUPPORTED; // Don't proxy the trusted interface.
+}
+
+int32_t Audio::GetSharedMemory(int* shm_handle, uint32_t* shm_size) {
+ return PP_ERROR_NOTSUPPORTED; // Don't proxy the trusted interface.
+}
+
+PPB_Audio_Proxy::PPB_Audio_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher),
+ callback_factory_(this) {
+}
+
+PPB_Audio_Proxy::~PPB_Audio_Proxy() {
+}
+
+// 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;
+
+ EnterResourceNoLock<PPB_AudioConfig_API> config(config_id, true);
+ if (config.failed())
+ return 0;
+
+ if (!audio_callback)
+ return 0;
+
+ HostResource result;
+ dispatcher->Send(new PpapiHostMsg_PPBAudio_Create(
+ API_ID_PPB_AUDIO, instance_id,
+ config.object()->GetSampleRate(), config.object()->GetSampleFrameCount(),
+ &result));
+ if (result.is_null())
+ return 0;
+
+ return (new Audio(result, config_id,
+ audio_callback, user_data))->GetReference();
+}
+
+bool PPB_Audio_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Audio_Proxy, msg)
+// Don't build host side into NaCl IRT.
+#if !defined(OS_NACL)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBAudio_Create, OnMsgCreate)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBAudio_StartOrStop,
+ OnMsgStartOrStop)
+#endif
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBAudio_NotifyAudioStreamCreated,
+ OnMsgNotifyAudioStreamCreated)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+#if !defined(OS_NACL)
+void PPB_Audio_Proxy::OnMsgCreate(PP_Instance instance_id,
+ int32_t sample_rate,
+ uint32_t sample_frame_count,
+ HostResource* result) {
+ thunk::EnterResourceCreation resource_creation(instance_id);
+ 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;
+
+ // At this point, we've set the result resource, and this is a sync request.
+ // Anything below this point must issue the AudioChannelConnected callback
+ // to the browser. Since that's an async message, it will be issued back to
+ // the plugin after the Create function returns (which is good because it
+ // would be weird to get a connected message with a failure code for a
+ // resource you haven't finished creating yet).
+ //
+ // The ...ForceCallback class will help ensure the callback is always called.
+ // All error cases must call SetResult on this class.
+ EnterHostFromHostResourceForceCallback<PPB_Audio_API> enter(
+ *result, callback_factory_,
+ &PPB_Audio_Proxy::AudioChannelConnected, *result);
+ if (enter.failed())
+ return; // When enter fails, it will internally schedule the callback.
+
+ // 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) {
+ enter.SetResult(PP_ERROR_FAILED);
+ return;
+ }
+
+ // Initiate opening the audio object.
+ enter.SetResult(enter.object()->Open(audio_config_res,
+ enter.callback()));
+
+ // Clean up the temporary audio config resource we made.
+ const PPB_Core* core = static_cast<const PPB_Core*>(
+ dispatcher()->local_get_interface()(PPB_CORE_INTERFACE));
+ core->ReleaseResource(audio_config_res);
+}
+
+void PPB_Audio_Proxy::OnMsgStartOrStop(const HostResource& audio_id,
+ bool play) {
+ EnterHostFromHostResource<PPB_Audio_API> enter(audio_id);
+ if (enter.failed())
+ return;
+ if (play)
+ enter.object()->StartPlayback();
+ else
+ enter.object()->StopPlayback();
+}
+
+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 audio_buffer_length = 0;
+
+ int32_t result_code = result;
+ if (result_code == PP_OK) {
+ result_code = GetAudioConnectedHandles(resource, &socket_handle,
+ &shared_memory,
+ &audio_buffer_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.
+ SerializedHandle fd_wrapper(SerializedHandle::SOCKET, socket_handle);
+
+ // Note that we must call TotalSharedMemorySizeInBytes because
+ // Audio allocates extra space in shared memory for book-keeping, so the
+ // actual size of the shared memory buffer is larger than audio_buffer_length.
+ // When sending to NaCl, NaClIPCAdapter expects this size to match the size
+ // of the full shared memory buffer.
+ SerializedHandle handle_wrapper(
+ shared_memory,
+ media::TotalSharedMemorySizeInBytes(audio_buffer_length));
+ dispatcher()->Send(new PpapiMsg_PPBAudio_NotifyAudioStreamCreated(
+ API_ID_PPB_AUDIO, resource, result_code, fd_wrapper, handle_wrapper));
+}
+
+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 audio interface which will give us the handles.
+ EnterHostFromHostResource<PPB_Audio_API> enter(resource);
+ if (enter.failed())
+ return PP_ERROR_NOINTERFACE;
+
+ // Get the socket handle for signaling.
+ int32_t socket_handle;
+ int32_t result = enter.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 = enter.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;
+}
+#endif // !defined(OS_NACL)
+
+// Processed in the plugin (message from host).
+void PPB_Audio_Proxy::OnMsgNotifyAudioStreamCreated(
+ const HostResource& audio_id,
+ int32_t result_code,
+ SerializedHandle socket_handle,
+ SerializedHandle handle) {
+ CHECK(socket_handle.is_socket());
+ CHECK(handle.is_shmem());
+ 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.descriptor()));
+ base::SharedMemory temp_mem(handle.shmem(), false);
+ } else {
+ EnterResourceNoLock<PPB_AudioConfig_API> config(
+ static_cast<Audio*>(enter.object())->GetCurrentConfig(), true);
+ // See the comment above about how we must call
+ // TotalSharedMemorySizeInBytes to get the actual size of the buffer. Here,
+ // we must call PacketSizeInBytes to get back the size of the audio buffer,
+ // excluding the bytes that audio uses for book-keeping.
+ static_cast<Audio*>(enter.object())->SetStreamInfo(
+ enter.resource()->pp_instance(), handle.shmem(),
+ media::PacketSizeInBytes(handle.size()),
+ IPC::PlatformFileForTransitToPlatformFile(socket_handle.descriptor()),
+ config.object()->GetSampleFrameCount());
+ }
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppb_audio_proxy.h b/chromium/ppapi/proxy/ppb_audio_proxy.h
new file mode 100644
index 00000000000..fa887de7f1a
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_audio_proxy.h
@@ -0,0 +1,87 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPB_AUDIO_PROXY_H_
+#define PPAPI_PROXY_PPB_AUDIO_PROXY_H_
+
+#include <utility>
+
+#include "base/basictypes.h"
+#include "base/memory/shared_memory.h"
+#include "base/sync_socket.h"
+#include "ipc/ipc_platform_file.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/ppb_audio.h"
+#include "ppapi/c/ppb_audio_config.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/proxy_completion_callback_factory.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+namespace ppapi {
+
+class HostResource;
+
+namespace proxy {
+
+class SerializedHandle;
+
+class PPB_Audio_Proxy : public InterfaceProxy {
+ public:
+ PPB_Audio_Proxy(Dispatcher* dispatcher);
+ virtual ~PPB_Audio_Proxy();
+
+ // 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);
+
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ static const ApiID kApiID = API_ID_PPB_AUDIO;
+
+ private:
+ // Plugin->renderer message handlers.
+ void OnMsgCreate(PP_Instance instance_id,
+ int32_t sample_rate,
+ uint32_t sample_frame_count,
+ ppapi::HostResource* result);
+ void OnMsgStartOrStop(const ppapi::HostResource& audio_id, bool play);
+
+ // Renderer->plugin message handlers.
+ void OnMsgNotifyAudioStreamCreated(
+ const ppapi::HostResource& audio_id,
+ int32_t result_code,
+ ppapi::proxy::SerializedHandle socket_handle,
+ ppapi::proxy::SerializedHandle handle);
+
+ void AudioChannelConnected(int32_t result,
+ const ppapi::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 ppapi::HostResource& resource,
+ IPC::PlatformFileForTransit* foreign_socket_handle,
+ base::SharedMemoryHandle* foreign_shared_memory_handle,
+ uint32_t* shared_memory_length);
+
+ ProxyCompletionCallbackFactory<PPB_Audio_Proxy> callback_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_Audio_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPB_AUDIO_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppb_broker_proxy.cc b/chromium/ppapi/proxy/ppb_broker_proxy.cc
new file mode 100644
index 00000000000..19cd978608f
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_broker_proxy.cc
@@ -0,0 +1,235 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppb_broker_proxy.h"
+
+#include "base/bind.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/ppapi_messages.h"
+#include "ppapi/shared_impl/platform_file.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/ppb_broker_api.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/resource_creation_api.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::IntToPlatformFile;
+using ppapi::PlatformFileToInt;
+using ppapi::thunk::PPB_Broker_API;
+
+namespace ppapi {
+namespace proxy {
+
+class Broker : public PPB_Broker_API, public Resource {
+ public:
+ explicit Broker(const HostResource& resource);
+ virtual ~Broker();
+
+ // Resource overrides.
+ virtual PPB_Broker_API* AsPPB_Broker_API() OVERRIDE;
+
+ // PPB_Broker_API implementation.
+ virtual int32_t Connect(
+ scoped_refptr<TrackedCallback> 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_;
+ scoped_refptr<TrackedCallback> 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)
+ : Resource(OBJECT_IS_PROXY, resource),
+ called_connect_(false),
+ socket_handle_(base::kInvalidPlatformFileValue) {
+}
+
+Broker::~Broker() {
+ socket_handle_ = base::kInvalidPlatformFileValue;
+}
+
+PPB_Broker_API* Broker::AsPPB_Broker_API() {
+ return this;
+}
+
+int32_t Broker::Connect(scoped_refptr<TrackedCallback> connect_callback) {
+ if (TrackedCallback::IsPending(current_connect_callback_))
+ return PP_ERROR_INPROGRESS;
+ else if (called_connect_)
+ return PP_ERROR_FAILED;
+
+ current_connect_callback_ = connect_callback;
+ called_connect_ = true;
+
+ bool success = PluginDispatcher::GetForResource(this)->Send(
+ new PpapiHostMsg_PPBBroker_Connect(
+ API_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 (!TrackedCallback::IsPending(current_connect_callback_)) {
+ // The handle might leak if the plugin never calls GetHandle().
+ return;
+ }
+
+ current_connect_callback_->Run(result);
+}
+
+PPB_Broker_Proxy::PPB_Broker_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher),
+ callback_factory_(this){
+}
+
+PPB_Broker_Proxy::~PPB_Broker_Proxy() {
+}
+
+// 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(
+ API_ID_PPB_BROKER, instance, &result));
+ if (result.is_null())
+ return 0;
+ return (new Broker(result))->GetReference();
+}
+
+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) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
+ return;
+ thunk::EnterResourceCreation enter(instance);
+ if (enter.succeeded()) {
+ result_resource->SetHostResource(
+ instance,
+ enter.functions()->CreateBroker(instance));
+ }
+}
+
+void PPB_Broker_Proxy::OnMsgConnect(const HostResource& broker) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
+ return;
+ EnterHostFromHostResourceForceCallback<PPB_Broker_API> enter(
+ broker, callback_factory_,
+ &PPB_Broker_Proxy::ConnectCompleteInHost, broker);
+ if (enter.succeeded())
+ enter.SetResult(enter.object()->Connect(enter.callback()));
+}
+
+// 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<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);
+ EnterHostFromHostResource<PPB_Broker_API> enter(broker);
+ if (enter.succeeded())
+ result = enter.object()->GetHandle(&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(
+ API_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 ppapi
diff --git a/chromium/ppapi/proxy/ppb_broker_proxy.h b/chromium/ppapi/proxy/ppb_broker_proxy.h
new file mode 100644
index 00000000000..5bc195afa50
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_broker_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_BROKER_PROXY_H_
+#define PPAPI_PROXY_PPB_BROKER_PROXY_H_
+
+#include "base/sync_socket.h"
+#include "ipc/ipc_platform_file.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/proxy_completion_callback_factory.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+namespace ppapi {
+
+class HostResource;
+
+namespace proxy {
+
+class PPB_Broker_Proxy : public InterfaceProxy {
+ public:
+ explicit PPB_Broker_Proxy(Dispatcher* dispatcher);
+ virtual ~PPB_Broker_Proxy();
+
+ static PP_Resource CreateProxyResource(PP_Instance instance);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ static const ApiID kApiID = API_ID_PPB_BROKER;
+
+ private:
+ // Message handlers.
+ void OnMsgCreate(PP_Instance instance, ppapi::HostResource* result_resource);
+ void OnMsgConnect(const ppapi::HostResource& broker);
+ void OnMsgConnectComplete(const ppapi::HostResource& broker,
+ IPC::PlatformFileForTransit foreign_socket_handle,
+ int32_t result);
+
+ void ConnectCompleteInHost(int32_t result,
+ const ppapi::HostResource& host_resource);
+
+ ProxyCompletionCallbackFactory<PPB_Broker_Proxy> callback_factory_;
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPB_BROKER_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppb_buffer_proxy.cc b/chromium/ppapi/proxy/ppb_buffer_proxy.cc
new file mode 100644
index 00000000000..c6d8cdd626b
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_buffer_proxy.cc
@@ -0,0 +1,156 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/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/ppapi_messages.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/resource_creation_api.h"
+#include "ppapi/thunk/thunk.h"
+
+namespace ppapi {
+namespace proxy {
+
+Buffer::Buffer(const HostResource& resource,
+ const base::SharedMemoryHandle& shm_handle,
+ uint32_t size)
+ : Resource(OBJECT_IS_PROXY, resource),
+ shm_(shm_handle, false),
+ size_(size),
+ map_count_(0) {
+}
+
+Buffer::~Buffer() {
+ Unmap();
+}
+
+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(map_count_ > 0);
+}
+
+void* Buffer::Map() {
+ if (map_count_++ == 0)
+ shm_.Map(size_);
+ return shm_.memory();
+}
+
+void Buffer::Unmap() {
+ if (--map_count_ == 0)
+ shm_.Unmap();
+}
+
+int32_t Buffer::GetSharedMemory(int* out_handle) {
+ NOTREACHED();
+ return PP_ERROR_NOTSUPPORTED;
+}
+
+PPB_Buffer_Proxy::PPB_Buffer_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher) {
+}
+
+PPB_Buffer_Proxy::~PPB_Buffer_Proxy() {
+}
+
+// static
+PP_Resource PPB_Buffer_Proxy::CreateProxyResource(PP_Instance instance,
+ uint32_t size) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+
+ HostResource result;
+ ppapi::proxy::SerializedHandle shm_handle;
+ dispatcher->Send(new PpapiHostMsg_PPBBuffer_Create(
+ API_ID_PPB_BUFFER, instance, size, &result, &shm_handle));
+ if (result.is_null() || !shm_handle.IsHandleValid() ||
+ !shm_handle.is_shmem())
+ return 0;
+
+ return AddProxyResource(result, shm_handle.shmem(), size);
+}
+
+// static
+PP_Resource PPB_Buffer_Proxy::AddProxyResource(
+ const HostResource& resource,
+ base::SharedMemoryHandle shm_handle,
+ uint32_t size) {
+ return (new Buffer(resource, shm_handle, size))->GetReference();
+}
+
+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,
+ ppapi::proxy::SerializedHandle* result_shm_handle) {
+ // Overwritten below on success.
+ result_shm_handle->set_null_shmem();
+ HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return;
+ if (!dispatcher->permissions().HasPermission(ppapi::PERMISSION_DEV))
+ return;
+
+ thunk::EnterResourceCreation enter(instance);
+ if (enter.failed())
+ return;
+ PP_Resource local_buffer_resource = enter.functions()->CreateBuffer(instance,
+ size);
+ if (local_buffer_resource == 0)
+ return;
+
+ thunk::EnterResourceNoLock<thunk::PPB_Buffer_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->set_shmem(
+ dispatcher->ShareHandleWithRemote(platform_file, false), size);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppb_buffer_proxy.h b/chromium/ppapi/proxy/ppb_buffer_proxy.h
new file mode 100644
index 00000000000..6c8fcc2fe4e
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_buffer_proxy.h
@@ -0,0 +1,76 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPB_BUFFER_PROXY_H_
+#define PPAPI_PROXY_PPB_BUFFER_PROXY_H_
+
+#include "base/memory/shared_memory.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/shared_impl/resource.h"
+#include "ppapi/thunk/ppb_buffer_api.h"
+
+namespace ppapi {
+
+class HostResource;
+
+namespace proxy {
+
+class SerializedHandle;
+
+class Buffer : public thunk::PPB_Buffer_API, public Resource {
+ public:
+ Buffer(const HostResource& resource,
+ const base::SharedMemoryHandle& shm_handle,
+ uint32_t size);
+ virtual ~Buffer();
+
+ // Resource overrides.
+ virtual 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;
+
+ // Trusted
+ virtual int32_t GetSharedMemory(int* handle) OVERRIDE;
+
+ private:
+ base::SharedMemory shm_;
+ uint32_t size_;
+ int map_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(Buffer);
+};
+
+class PPB_Buffer_Proxy : public InterfaceProxy {
+ public:
+ explicit PPB_Buffer_Proxy(Dispatcher* dispatcher);
+ virtual ~PPB_Buffer_Proxy();
+
+ static PP_Resource CreateProxyResource(PP_Instance instance,
+ uint32_t size);
+ static PP_Resource AddProxyResource(const HostResource& resource,
+ base::SharedMemoryHandle shm_handle,
+ uint32_t size);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ static const ApiID kApiID = API_ID_PPB_BUFFER;
+
+ private:
+ // Message handlers.
+ void OnMsgCreate(PP_Instance instance,
+ uint32_t size,
+ HostResource* result_resource,
+ ppapi::proxy::SerializedHandle* result_shm_handle);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPB_BUFFER_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppb_core_proxy.cc b/chromium/ppapi/proxy/ppb_core_proxy.cc
new file mode 100644
index 00000000000..65845aed7be
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_core_proxy.cc
@@ -0,0 +1,131 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppb_core_proxy.h"
+
+#include <stdlib.h> // For malloc
+
+#include "base/bind.h"
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "base/time/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/ppapi_globals.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/time_conversion.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+void AddRefResource(PP_Resource resource) {
+ ppapi::ProxyAutoLock lock;
+ PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(resource);
+}
+
+void ReleaseResource(PP_Resource resource) {
+ ppapi::ProxyAutoLock lock;
+ PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(resource);
+}
+
+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);
+ CallWhileUnlocked(PP_RunCompletionCallback, &callback, result);
+}
+
+void CallOnMainThread(int delay_in_ms,
+ PP_CompletionCallback callback,
+ int32_t result) {
+ DCHECK(callback.func);
+#if defined(OS_NACL)
+ // Some NaCl apps pass a negative delay, so we just sanitize to 0, to run as
+ // soon as possible. MessageLoop checks that the delay is non-negative.
+ if (delay_in_ms < 0)
+ delay_in_ms = 0;
+#endif
+ if (!callback.func)
+ return;
+ ProxyAutoLock lock;
+ PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostDelayedTask(
+ FROM_HERE,
+ RunWhileLocked(base::Bind(&CallbackWrapper, callback, result)),
+ base::TimeDelta::FromMilliseconds(delay_in_ms));
+}
+
+PP_Bool IsMainThread() {
+ return PP_FromBool(PpapiGlobals::Get()->
+ GetMainThreadMessageLoop()->BelongsToCurrentThread());
+}
+
+const PPB_Core core_interface = {
+ &AddRefResource,
+ &ReleaseResource,
+ &GetTime,
+ &GetTimeTicks,
+ &CallOnMainThread,
+ &IsMainThread
+};
+
+} // namespace
+
+PPB_Core_Proxy::PPB_Core_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher),
+ ppb_core_impl_(NULL) {
+ if (!dispatcher->IsPlugin()) {
+ ppb_core_impl_ = static_cast<const PPB_Core*>(
+ dispatcher->local_get_interface()(PPB_CORE_INTERFACE));
+ }
+}
+
+PPB_Core_Proxy::~PPB_Core_Proxy() {
+}
+
+// static
+const PPB_Core* PPB_Core_Proxy::GetPPB_Core_Interface() {
+ return &core_interface;
+}
+
+bool PPB_Core_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Core_Proxy, msg)
+#if !defined(OS_NACL)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCore_AddRefResource,
+ OnMsgAddRefResource)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCore_ReleaseResource,
+ OnMsgReleaseResource)
+#endif
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ // TODO(brettw) handle bad messages!
+ return handled;
+}
+
+#if !defined(OS_NACL)
+void PPB_Core_Proxy::OnMsgAddRefResource(const HostResource& resource) {
+ ppb_core_impl_->AddRefResource(resource.host_resource());
+}
+
+void PPB_Core_Proxy::OnMsgReleaseResource(const HostResource& resource) {
+ ppb_core_impl_->ReleaseResource(resource.host_resource());
+}
+#endif // !defined(OS_NACL)
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppb_core_proxy.h b/chromium/ppapi/proxy/ppb_core_proxy.h
new file mode 100644
index 00000000000..a5645195fdb
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_core_proxy.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_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/c/ppb_core.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/shared_impl/host_resource.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPB_Core_Proxy : public InterfaceProxy {
+ public:
+ PPB_Core_Proxy(Dispatcher* dispatcher);
+ virtual ~PPB_Core_Proxy();
+
+ static const PPB_Core* GetPPB_Core_Interface();
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ static const ApiID kApiID = API_ID_PPB_CORE;
+
+ private:
+ // Message handlers.
+ void OnMsgAddRefResource(const ppapi::HostResource& resource);
+ void OnMsgReleaseResource(const ppapi::HostResource& resource);
+
+ // When this proxy is in the host side, this value caches the interface
+ // pointer so we don't have to retrieve it from the dispatcher each time.
+ // In the plugin, this value is always NULL.
+ const PPB_Core* ppb_core_impl_;
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PPB_CORE_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppb_file_ref_proxy.cc b/chromium/ppapi/proxy/ppb_file_ref_proxy.cc
new file mode 100644
index 00000000000..62c55da9d8b
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_file_ref_proxy.cc
@@ -0,0 +1,549 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppb_file_ref_proxy.h"
+
+#include <map>
+
+#include "base/bind.h"
+#include "ppapi/c/pp_directory_entry.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_file_ref.h"
+#include "ppapi/c/private/ppb_file_ref_private.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/ppapi_messages.h"
+#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/shared_impl/array_writer.h"
+#include "ppapi/shared_impl/ppb_file_ref_shared.h"
+#include "ppapi/shared_impl/scoped_pp_resource.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/resource_creation_api.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_FileRef_API;
+using ppapi::thunk::ResourceCreationAPI;
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+void ReleaseEntries(const std::vector<PP_DirectoryEntry>& entries) {
+ ResourceTracker* tracker = PpapiGlobals::Get()->GetResourceTracker();
+ for (std::vector<PP_DirectoryEntry>::const_iterator it = entries.begin();
+ it != entries.end(); ++it)
+ tracker->ReleaseResource(it->file_ref);
+}
+
+} // namespace
+
+class FileRef : public PPB_FileRef_Shared {
+ public:
+ explicit FileRef(const PPB_FileRef_CreateInfo& info);
+ virtual ~FileRef();
+
+ // Resource overrides.
+ virtual void LastPluginRefWasDeleted() OVERRIDE;
+
+ // PPB_FileRef_API implementation (not provided by PPB_FileRef_Shared).
+ virtual PP_Resource GetParent() OVERRIDE;
+ virtual int32_t MakeDirectory(
+ PP_Bool make_ancestors,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Touch(PP_Time last_access_time,
+ PP_Time last_modified_time,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Delete(scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Rename(PP_Resource new_file_ref,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Query(PP_FileInfo* info,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t ReadDirectoryEntries(
+ const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t QueryInHost(
+ linked_ptr<PP_FileInfo> info,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t ReadDirectoryEntriesInHost(
+ linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
+ linked_ptr<std::vector<PP_FileType> > file_types,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual PP_Var GetAbsolutePath() OVERRIDE;
+
+ // Executes the pending callback with the given ID. See pending_callbacks_.
+ void ExecuteCallback(uint32_t callback_id, int32_t result);
+ int32_t SetFileInfo(uint32_t callback_id, const PP_FileInfo& info);
+ int32_t SetReadDirectoryEntriesOutput(
+ uint32_t callback_id,
+ const std::vector<ppapi::PPB_FileRef_CreateInfo>& infos,
+ const std::vector<PP_FileType>& file_types);
+
+ private:
+ PluginDispatcher* GetDispatcher() const {
+ return PluginDispatcher::GetForResource(this);
+ }
+
+ // Adds a callback to the list and returns its ID.
+ uint32_t SendCallback(scoped_refptr<TrackedCallback> callback);
+
+ // This class can have any number of out-standing requests with completion
+ // callbacks, in contrast to most resources which have one possible pending
+ // callback pending (like a Flush callback).
+ //
+ // To keep track of them, assign integer IDs to the callbacks, which is how
+ // the callback will be identified when it's passed to the host and then
+ // back here. Use unsigned so that overflow is well-defined.
+ uint32_t next_callback_id_;
+ typedef std::map<uint32_t,
+ scoped_refptr<TrackedCallback> > PendingCallbackMap;
+ PendingCallbackMap pending_callbacks_;
+
+ // Used to keep pointers to PP_FileInfo instances that are written before
+ // callbacks are invoked. The id of a pending file info will match that of
+ // the corresponding callback.
+ typedef std::map<uint32_t, PP_FileInfo*> PendingFileInfoMap;
+ PendingFileInfoMap pending_file_infos_;
+
+ // Used to keep PP_ArrayOutput instances that are written before callbacks
+ // are invoked. The id of a pending array output will match that of the
+ // corresponding callback.
+ typedef std::map<uint32_t, PP_ArrayOutput>
+ PendingReadDirectoryEntriesOutputMap;
+ PendingReadDirectoryEntriesOutputMap pending_read_entries_outputs_;
+
+ // Holds a reference on plugin side when running out of process, so that
+ // FileSystem won't die before FileRef. See PPB_FileRef_Impl for
+ // corresponding code for in-process mode. Note that this workaround will
+ // be no longer needed after FileRef refactoring.
+ ScopedPPResource file_system_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(FileRef);
+};
+
+FileRef::FileRef(const PPB_FileRef_CreateInfo& info)
+ : PPB_FileRef_Shared(OBJECT_IS_PROXY, info),
+ next_callback_id_(0u),
+ file_system_(info.file_system_plugin_resource) {
+}
+
+FileRef::~FileRef() {
+ // The callbacks map should have been cleared by LastPluginRefWasDeleted.
+ DCHECK(pending_callbacks_.empty());
+ DCHECK(pending_file_infos_.empty());
+ DCHECK(pending_read_entries_outputs_.empty());
+}
+
+void FileRef::LastPluginRefWasDeleted() {
+ // The callback tracker will abort our callbacks for us.
+ pending_callbacks_.clear();
+ pending_file_infos_.clear();
+ pending_read_entries_outputs_.clear();
+}
+
+PP_Resource FileRef::GetParent() {
+ PPB_FileRef_CreateInfo create_info;
+ GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_GetParent(
+ API_ID_PPB_FILE_REF, host_resource(), &create_info));
+ return PPB_FileRef_Proxy::DeserializeFileRef(create_info);
+}
+
+int32_t FileRef::MakeDirectory(PP_Bool make_ancestors,
+ scoped_refptr<TrackedCallback> callback) {
+ GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_MakeDirectory(
+ API_ID_PPB_FILE_REF, host_resource(), make_ancestors,
+ SendCallback(callback)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileRef::Touch(PP_Time last_access_time,
+ PP_Time last_modified_time,
+ scoped_refptr<TrackedCallback> callback) {
+ GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Touch(
+ API_ID_PPB_FILE_REF, host_resource(), last_access_time,
+ last_modified_time, SendCallback(callback)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileRef::Delete(scoped_refptr<TrackedCallback> callback) {
+ GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Delete(
+ API_ID_PPB_FILE_REF, host_resource(), SendCallback(callback)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileRef::Rename(PP_Resource new_file_ref,
+ scoped_refptr<TrackedCallback> callback) {
+ Resource* new_file_ref_object =
+ PpapiGlobals::Get()->GetResourceTracker()->GetResource(new_file_ref);
+ if (!new_file_ref_object ||
+ new_file_ref_object->host_resource().instance() != pp_instance())
+ return PP_ERROR_BADRESOURCE;
+
+ GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Rename(
+ API_ID_PPB_FILE_REF, host_resource(),
+ new_file_ref_object->host_resource(), SendCallback(callback)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileRef::Query(PP_FileInfo* info,
+ scoped_refptr<TrackedCallback> callback) {
+ // Store the pending file info id.
+ uint32_t id = SendCallback(callback);
+ pending_file_infos_[id] = info;
+ GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Query(
+ API_ID_PPB_FILE_REF, host_resource(), id));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileRef::ReadDirectoryEntries(
+ const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback) {
+ // Store the pending read entries output id.
+ uint32_t id = SendCallback(callback);
+ pending_read_entries_outputs_[id] = output;
+ GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_ReadDirectoryEntries(
+ API_ID_PPB_FILE_REF, host_resource(), id));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileRef::QueryInHost(
+ linked_ptr<PP_FileInfo> info,
+ scoped_refptr<TrackedCallback> callback) {
+ NOTREACHED();
+ return PP_ERROR_FAILED;
+}
+
+int32_t FileRef::ReadDirectoryEntriesInHost(
+ linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
+ linked_ptr<std::vector<PP_FileType> > file_types,
+ scoped_refptr<TrackedCallback> callback) {
+ NOTREACHED();
+ return PP_ERROR_FAILED;
+}
+
+PP_Var FileRef::GetAbsolutePath() {
+ ReceiveSerializedVarReturnValue result;
+ GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_GetAbsolutePath(
+ API_ID_PPB_FILE_REF, host_resource(), &result));
+ return result.Return(GetDispatcher());
+}
+
+void FileRef::ExecuteCallback(uint32_t callback_id, int32_t result) {
+ PendingCallbackMap::iterator found = pending_callbacks_.find(callback_id);
+ if (found == pending_callbacks_.end()) {
+ // This will happen when the plugin deletes its resource with a pending
+ // callback. The callback will be locally issued with an ABORTED call while
+ // the operation may still be pending in the renderer.
+ return;
+ }
+
+ // Executing the callback may mutate the callback list.
+ scoped_refptr<TrackedCallback> callback = found->second;
+ pending_callbacks_.erase(found);
+ callback->Run(result);
+}
+
+int32_t FileRef::SetFileInfo(uint32_t callback_id, const PP_FileInfo& info) {
+ PendingFileInfoMap::iterator found = pending_file_infos_.find(callback_id);
+ if (found == pending_file_infos_.end())
+ return PP_ERROR_FAILED;
+ PP_FileInfo* target_info = found->second;
+ *target_info = info;
+ pending_file_infos_.erase(found);
+ return PP_OK;
+}
+
+int32_t FileRef::SetReadDirectoryEntriesOutput(
+ uint32_t callback_id,
+ const std::vector<ppapi::PPB_FileRef_CreateInfo>& infos,
+ const std::vector<PP_FileType>& file_types) {
+ PendingReadDirectoryEntriesOutputMap::iterator found =
+ pending_read_entries_outputs_.find(callback_id);
+ if (found == pending_read_entries_outputs_.end())
+ return PP_ERROR_FAILED;
+
+ PP_ArrayOutput output = found->second;
+ pending_read_entries_outputs_.erase(found);
+
+ std::vector<PP_DirectoryEntry> entries;
+ for (size_t i = 0; i < infos.size(); ++i) {
+ PP_DirectoryEntry entry;
+ entry.file_ref = PPB_FileRef_Proxy::DeserializeFileRef(infos[i]);
+ entry.file_type = file_types[i];
+ entries.push_back(entry);
+ }
+
+ ArrayWriter writer(output);
+ if (!writer.is_valid()) {
+ ReleaseEntries(entries);
+ return PP_ERROR_BADARGUMENT;
+ }
+
+ writer.StoreVector(entries);
+ return PP_OK;
+}
+
+uint32_t FileRef::SendCallback(scoped_refptr<TrackedCallback> callback) {
+ // In extreme cases the IDs may wrap around, so avoid duplicates.
+ while (pending_callbacks_.count(next_callback_id_))
+ ++next_callback_id_;
+
+ pending_callbacks_[next_callback_id_] = callback;
+ return next_callback_id_++;
+}
+
+PPB_FileRef_Proxy::PPB_FileRef_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher),
+ callback_factory_(this) {
+}
+
+PPB_FileRef_Proxy::~PPB_FileRef_Proxy() {
+}
+
+// static
+PP_Resource PPB_FileRef_Proxy::CreateProxyResource(PP_Instance instance,
+ PP_Resource file_system,
+ const char* path) {
+ PPB_FileRef_CreateInfo create_info;
+ PluginDispatcher::GetForInstance(instance)->Send(
+ new PpapiHostMsg_PPBFileRef_Create(
+ API_ID_PPB_FILE_REF, instance, file_system, 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)
+#if !defined(OS_NACL)
+ 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_HANDLER(PpapiHostMsg_PPBFileRef_Query, OnMsgQuery)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_ReadDirectoryEntries,
+ OnMsgReadDirectoryEntries)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_GetAbsolutePath,
+ OnMsgGetAbsolutePath)
+#endif // !defined(OS_NACL)
+
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileRef_CallbackComplete,
+ OnMsgCallbackComplete)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileRef_QueryCallbackComplete,
+ OnMsgQueryCallbackComplete)
+ IPC_MESSAGE_HANDLER(
+ PpapiMsg_PPBFileRef_ReadDirectoryEntriesCallbackComplete,
+ OnMsgReadDirectoryEntriesCallbackComplete)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+// static
+void PPB_FileRef_Proxy::SerializeFileRef(PP_Resource file_ref,
+ PPB_FileRef_CreateInfo* result) {
+ EnterResourceNoLock<PPB_FileRef_API> enter(file_ref, false);
+ if (enter.succeeded())
+ *result = enter.object()->GetCreateInfo();
+}
+
+// static
+PP_Resource PPB_FileRef_Proxy::DeserializeFileRef(
+ const PPB_FileRef_CreateInfo& serialized) {
+ if (serialized.resource.is_null())
+ return 0; // Resource invalid.
+ return (new FileRef(serialized))->GetReference();
+}
+
+#if !defined(OS_NACL)
+void PPB_FileRef_Proxy::OnMsgCreate(PP_Instance pp_instance,
+ PP_Resource file_system,
+ const std::string& path,
+ PPB_FileRef_CreateInfo* result) {
+ thunk::EnterResourceCreation enter(pp_instance);
+ if (enter.failed())
+ return;
+
+ PP_Resource resource = enter.functions()->CreateFileRef(
+ pp_instance, file_system, path.c_str());
+ if (!resource)
+ return; // CreateInfo default constructor initializes to 0.
+ SerializeFileRef(resource, result);
+}
+
+void PPB_FileRef_Proxy::OnMsgGetParent(const HostResource& host_resource,
+ PPB_FileRef_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 callback_id) {
+ EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter(
+ host_resource, callback_factory_,
+ &PPB_FileRef_Proxy::OnCallbackCompleteInHost, host_resource, callback_id);
+ if (enter.succeeded()) {
+ enter.SetResult(enter.object()->MakeDirectory(make_ancestors,
+ enter.callback()));
+ }
+}
+
+void PPB_FileRef_Proxy::OnMsgTouch(const HostResource& host_resource,
+ PP_Time last_access,
+ PP_Time last_modified,
+ uint32_t callback_id) {
+ EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter(
+ host_resource, callback_factory_,
+ &PPB_FileRef_Proxy::OnCallbackCompleteInHost, host_resource, callback_id);
+ if (enter.succeeded()) {
+ enter.SetResult(enter.object()->Touch(last_access, last_modified,
+ enter.callback()));
+ }
+}
+
+void PPB_FileRef_Proxy::OnMsgDelete(const HostResource& host_resource,
+ uint32_t callback_id) {
+ EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter(
+ host_resource, callback_factory_,
+ &PPB_FileRef_Proxy::OnCallbackCompleteInHost, host_resource, callback_id);
+ if (enter.succeeded())
+ enter.SetResult(enter.object()->Delete(enter.callback()));
+}
+
+void PPB_FileRef_Proxy::OnMsgRename(const HostResource& file_ref,
+ const HostResource& new_file_ref,
+ uint32_t callback_id) {
+ EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter(
+ file_ref, callback_factory_,
+ &PPB_FileRef_Proxy::OnCallbackCompleteInHost, file_ref, callback_id);
+ if (enter.succeeded()) {
+ enter.SetResult(enter.object()->Rename(new_file_ref.host_resource(),
+ enter.callback()));
+ }
+}
+
+void PPB_FileRef_Proxy::OnMsgQuery(const HostResource& file_ref,
+ uint32_t callback_id) {
+ linked_ptr<PP_FileInfo> info(new PP_FileInfo());
+ EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter(
+ file_ref, callback_factory_,
+ &PPB_FileRef_Proxy::OnQueryCallbackCompleteInHost, file_ref,
+ info, callback_id);
+ if (enter.succeeded())
+ enter.SetResult(enter.object()->QueryInHost(info, enter.callback()));
+}
+
+void PPB_FileRef_Proxy::OnMsgGetAbsolutePath(const HostResource& host_resource,
+ SerializedVarReturnValue result) {
+ EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource);
+ if (enter.succeeded())
+ result.Return(dispatcher(), enter.object()->GetAbsolutePath());
+}
+
+void PPB_FileRef_Proxy::OnMsgReadDirectoryEntries(const HostResource& file_ref,
+ uint32_t callback_id) {
+ linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files(
+ new std::vector<ppapi::PPB_FileRef_CreateInfo>());
+ linked_ptr<std::vector<PP_FileType> > file_types(
+ new std::vector<PP_FileType>());
+ HostCallbackParams params(file_ref, callback_id);
+ EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter(
+ file_ref, callback_factory_,
+ &PPB_FileRef_Proxy::OnReadDirectoryEntriesCallbackCompleteInHost,
+ params, files, file_types);
+ if (enter.succeeded()) {
+ enter.SetResult(enter.object()->ReadDirectoryEntriesInHost(
+ files, file_types, enter.callback()));
+ }
+}
+
+#endif // !defined(OS_NACL)
+
+void PPB_FileRef_Proxy::OnMsgCallbackComplete(
+ const HostResource& host_resource,
+ uint32_t callback_id,
+ int32_t result) {
+ // Forward the callback info to the plugin resource.
+ EnterPluginFromHostResource<PPB_FileRef_API> enter(host_resource);
+ if (enter.succeeded())
+ static_cast<FileRef*>(enter.object())->ExecuteCallback(callback_id, result);
+}
+
+void PPB_FileRef_Proxy::OnMsgQueryCallbackComplete(
+ const HostResource& host_resource,
+ const PP_FileInfo& info,
+ uint32_t callback_id,
+ int32_t result) {
+ EnterPluginFromHostResource<PPB_FileRef_API> enter(host_resource);
+ if (!enter.succeeded())
+ return;
+
+ if (result == PP_OK) {
+ result = static_cast<FileRef*>(enter.object())->SetFileInfo(
+ callback_id, info);
+ }
+ static_cast<FileRef*>(enter.object())->ExecuteCallback(callback_id, result);
+}
+
+void PPB_FileRef_Proxy::OnMsgReadDirectoryEntriesCallbackComplete(
+ const HostResource& host_resource,
+ const std::vector<ppapi::PPB_FileRef_CreateInfo>& infos,
+ const std::vector<PP_FileType>& file_types,
+ uint32_t callback_id,
+ int32_t result) {
+ CHECK_EQ(infos.size(), file_types.size());
+
+ EnterPluginFromHostResource<PPB_FileRef_API> enter(host_resource);
+ if (!enter.succeeded())
+ return;
+
+ if (result == PP_OK) {
+ result =
+ static_cast<FileRef*>(enter.object())->SetReadDirectoryEntriesOutput(
+ callback_id, infos, file_types);
+ }
+ static_cast<FileRef*>(enter.object())->ExecuteCallback(
+ callback_id, result);
+}
+
+#if !defined(OS_NACL)
+void PPB_FileRef_Proxy::OnCallbackCompleteInHost(
+ int32_t result,
+ const HostResource& host_resource,
+ uint32_t callback_id) {
+ // Execute OnMsgCallbackComplete in the plugin process.
+ Send(new PpapiMsg_PPBFileRef_CallbackComplete(
+ API_ID_PPB_FILE_REF, host_resource, callback_id, result));
+}
+
+void PPB_FileRef_Proxy::OnQueryCallbackCompleteInHost(
+ int32_t result,
+ const HostResource& host_resource,
+ linked_ptr<PP_FileInfo> info,
+ uint32_t callback_id) {
+ Send(new PpapiMsg_PPBFileRef_QueryCallbackComplete(
+ API_ID_PPB_FILE_REF, host_resource, *info, callback_id, result));
+}
+
+void PPB_FileRef_Proxy::OnReadDirectoryEntriesCallbackCompleteInHost(
+ int32_t result,
+ HostCallbackParams params,
+ linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
+ linked_ptr<std::vector<PP_FileType> > file_types) {
+ Send(new PpapiMsg_PPBFileRef_ReadDirectoryEntriesCallbackComplete(
+ API_ID_PPB_FILE_REF, params.host_resource,
+ *files, *file_types, params.callback_id, result));
+}
+
+#endif // !defined(OS_NACL)
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppb_file_ref_proxy.h b/chromium/ppapi/proxy/ppb_file_ref_proxy.h
new file mode 100644
index 00000000000..cbfadb5b5f4
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_file_ref_proxy.h
@@ -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.
+
+#ifndef PPAPI_PROXY_PPB_FILE_REF_PROXY_H_
+#define PPAPI_PROXY_PPB_FILE_REF_PROXY_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/linked_ptr.h"
+#include "ppapi/c/pp_file_info.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_time.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/proxy/proxy_completion_callback_factory.h"
+#include "ppapi/shared_impl/host_resource.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+namespace ppapi {
+
+struct PPB_FileRef_CreateInfo;
+
+namespace proxy {
+
+class SerializedVarReturnValue;
+
+class PPAPI_PROXY_EXPORT PPB_FileRef_Proxy
+ : public NON_EXPORTED_BASE(InterfaceProxy) {
+ public:
+ explicit PPB_FileRef_Proxy(Dispatcher* dispatcher);
+ virtual ~PPB_FileRef_Proxy();
+
+ static PP_Resource CreateProxyResource(PP_Instance instance,
+ PP_Resource file_system,
+ const char* path);
+ static PP_Resource CreateProxyResource(
+ const PPB_FileRef_CreateInfo& serialized);
+
+ // 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.
+ //
+ // Various PPAPI functions return file refs from various interfaces, so this
+ // function is public so anybody can send a file ref.
+ static void SerializeFileRef(PP_Resource file_ref,
+ PPB_FileRef_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 PPB_FileRef_CreateInfo& serialized);
+
+ static const ApiID kApiID = API_ID_PPB_FILE_REF;
+
+ private:
+ // Plugin -> host message handlers.
+ void OnMsgCreate(PP_Instance instance,
+ PP_Resource file_system,
+ const std::string& path,
+ PPB_FileRef_CreateInfo* result);
+ void OnMsgGetParent(const HostResource& host_resource,
+ PPB_FileRef_CreateInfo* result);
+ void OnMsgMakeDirectory(const HostResource& host_resource,
+ PP_Bool make_ancestors,
+ uint32_t callback_id);
+ void OnMsgTouch(const HostResource& host_resource,
+ PP_Time last_access,
+ PP_Time last_modified,
+ uint32_t callback_id);
+ void OnMsgDelete(const HostResource& host_resource,
+ uint32_t callback_id);
+ void OnMsgRename(const HostResource& file_ref,
+ const HostResource& new_file_ref,
+ uint32_t callback_id);
+ void OnMsgQuery(const HostResource& file_ref,
+ uint32_t callback_id);
+ void OnMsgGetAbsolutePath(const HostResource& host_resource,
+ SerializedVarReturnValue result);
+ void OnMsgReadDirectoryEntries(const HostResource& file_ref,
+ uint32_t callback_id);
+
+ // Host -> Plugin message handlers.
+ void OnMsgCallbackComplete(const HostResource& host_resource,
+ uint32_t callback_id,
+ int32_t result);
+ void OnMsgQueryCallbackComplete(const HostResource& host_resource,
+ const PP_FileInfo& info,
+ uint32_t callback_id,
+ int32_t result);
+ void OnMsgReadDirectoryEntriesCallbackComplete(
+ const HostResource& host_resource,
+ const std::vector<ppapi::PPB_FileRef_CreateInfo>& infos,
+ const std::vector<PP_FileType>& file_types,
+ uint32_t callback_id,
+ int32_t result);
+
+ struct HostCallbackParams {
+ HostCallbackParams(const HostResource& host_res, uint32_t cb_id)
+ : host_resource(host_res), callback_id(cb_id) {
+ }
+ HostResource host_resource;
+ uint32_t callback_id;
+ };
+
+ void OnCallbackCompleteInHost(int32_t result,
+ const HostResource& host_resource,
+ uint32_t callback_id);
+ void OnQueryCallbackCompleteInHost(
+ int32_t result,
+ const HostResource& host_resource,
+ linked_ptr<PP_FileInfo> info,
+ uint32_t callback_id);
+ void OnReadDirectoryEntriesCallbackCompleteInHost(
+ int32_t result,
+ HostCallbackParams params,
+ linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
+ linked_ptr<std::vector<PP_FileType> > file_types);
+
+ ProxyCompletionCallbackFactory<PPB_FileRef_Proxy> callback_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_FileRef_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPB_FILE_REF_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppb_flash_message_loop_proxy.cc b/chromium/ppapi/proxy/ppb_flash_message_loop_proxy.cc
new file mode 100644
index 00000000000..8b7ff823ee0
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_flash_message_loop_proxy.cc
@@ -0,0 +1,165 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppb_flash_message_loop_proxy.h"
+
+#include "base/bind.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/private/ppb_flash_message_loop.h"
+#include "ppapi/proxy/enter_proxy.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/resource.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_flash_message_loop_api.h"
+#include "ppapi/thunk/resource_creation_api.h"
+
+using ppapi::thunk::PPB_Flash_MessageLoop_API;
+
+namespace ppapi {
+namespace proxy {
+namespace {
+
+class FlashMessageLoop : public PPB_Flash_MessageLoop_API, public Resource {
+ public:
+ explicit FlashMessageLoop(const HostResource& resource);
+ virtual ~FlashMessageLoop();
+
+ // Resource overrides.
+ virtual PPB_Flash_MessageLoop_API* AsPPB_Flash_MessageLoop_API() OVERRIDE;
+
+ // PPB_Flash_MesssageLoop_API implementation.
+ virtual int32_t Run() OVERRIDE;
+ virtual void Quit() OVERRIDE;
+ virtual void RunFromHostProxy(
+ const RunFromHostProxyCallback& callback) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FlashMessageLoop);
+};
+
+FlashMessageLoop::FlashMessageLoop(const HostResource& resource)
+ : Resource(OBJECT_IS_PROXY, resource) {
+}
+
+FlashMessageLoop::~FlashMessageLoop() {
+}
+
+PPB_Flash_MessageLoop_API* FlashMessageLoop::AsPPB_Flash_MessageLoop_API() {
+ return this;
+}
+
+int32_t FlashMessageLoop::Run() {
+ int32_t result = PP_ERROR_FAILED;
+ IPC::SyncMessage* msg = new PpapiHostMsg_PPBFlashMessageLoop_Run(
+ API_ID_PPB_FLASH_MESSAGELOOP, host_resource(), &result);
+ msg->EnableMessagePumping();
+ PluginDispatcher::GetForResource(this)->Send(msg);
+ return result;
+}
+
+void FlashMessageLoop::Quit() {
+ PluginDispatcher::GetForResource(this)->Send(
+ new PpapiHostMsg_PPBFlashMessageLoop_Quit(
+ API_ID_PPB_FLASH_MESSAGELOOP, host_resource()));
+}
+
+void FlashMessageLoop::RunFromHostProxy(
+ const RunFromHostProxyCallback& callback) {
+ // This should never be called on the plugin side.
+ NOTREACHED();
+}
+
+} // namespace
+
+PPB_Flash_MessageLoop_Proxy::PPB_Flash_MessageLoop_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher) {
+}
+
+PPB_Flash_MessageLoop_Proxy::~PPB_Flash_MessageLoop_Proxy() {
+}
+
+// static
+PP_Resource PPB_Flash_MessageLoop_Proxy::CreateProxyResource(
+ PP_Instance instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+
+ HostResource result;
+ dispatcher->Send(new PpapiHostMsg_PPBFlashMessageLoop_Create(
+ API_ID_PPB_FLASH_MESSAGELOOP, instance, &result));
+ if (result.is_null())
+ return 0;
+ return (new FlashMessageLoop(result))->GetReference();
+}
+
+bool PPB_Flash_MessageLoop_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_FLASH))
+ return false;
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Flash_MessageLoop_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashMessageLoop_Create,
+ OnMsgCreate)
+ // We cannot use IPC_MESSAGE_HANDLER here. Because it tries to send the sync
+ // message reply after the handler returns. However, in this case, the
+ // PPB_Flash_MessageLoop_Proxy object may be destroyed before the handler
+ // returns.
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(PpapiHostMsg_PPBFlashMessageLoop_Run,
+ OnMsgRun)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashMessageLoop_Quit,
+ OnMsgQuit)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPB_Flash_MessageLoop_Proxy::OnMsgCreate(PP_Instance instance,
+ HostResource* result) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_FLASH))
+ return;
+ thunk::EnterResourceCreation enter(instance);
+ if (enter.succeeded()) {
+ result->SetHostResource(
+ instance, enter.functions()->CreateFlashMessageLoop(instance));
+ }
+}
+
+void PPB_Flash_MessageLoop_Proxy::OnMsgRun(
+ const HostResource& flash_message_loop,
+ IPC::Message* reply) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_FLASH))
+ return;
+
+ PPB_Flash_MessageLoop_API::RunFromHostProxyCallback callback =
+ base::Bind(&PPB_Flash_MessageLoop_Proxy::WillQuitSoon, AsWeakPtr(),
+ base::Passed(scoped_ptr<IPC::Message>(reply)));
+
+ EnterHostFromHostResource<PPB_Flash_MessageLoop_API>
+ enter(flash_message_loop);
+ if (enter.succeeded())
+ enter.object()->RunFromHostProxy(callback);
+ else
+ callback.Run(PP_ERROR_BADRESOURCE);
+}
+
+void PPB_Flash_MessageLoop_Proxy::OnMsgQuit(
+ const ppapi::HostResource& flash_message_loop) {
+ EnterHostFromHostResource<PPB_Flash_MessageLoop_API>
+ enter(flash_message_loop);
+ if (enter.succeeded())
+ enter.object()->Quit();
+}
+
+void PPB_Flash_MessageLoop_Proxy::WillQuitSoon(
+ scoped_ptr<IPC::Message> reply_message,
+ int32_t result) {
+ PpapiHostMsg_PPBFlashMessageLoop_Run::WriteReplyParams(reply_message.get(),
+ result);
+ Send(reply_message.release());
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppb_flash_message_loop_proxy.h b/chromium/ppapi/proxy/ppb_flash_message_loop_proxy.h
new file mode 100644
index 00000000000..238f106ddc5
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_flash_message_loop_proxy.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PPB_FLASH_MESSAGE_LOOP_PROXY_H_
+#define PPAPI_PPB_FLASH_MESSAGE_LOOP_PROXY_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+namespace IPC {
+class Message;
+}
+
+namespace ppapi {
+
+class HostResource;
+
+namespace proxy {
+
+class PPB_Flash_MessageLoop_Proxy
+ : public InterfaceProxy,
+ public base::SupportsWeakPtr<PPB_Flash_MessageLoop_Proxy> {
+ public:
+ explicit PPB_Flash_MessageLoop_Proxy(Dispatcher* dispatcher);
+ virtual ~PPB_Flash_MessageLoop_Proxy();
+
+ static PP_Resource CreateProxyResource(PP_Instance instance);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+
+ static const ApiID kApiID = API_ID_PPB_FLASH_MESSAGELOOP;
+
+ private:
+ void OnMsgCreate(PP_Instance instance, ppapi::HostResource* resource);
+ void OnMsgRun(const ppapi::HostResource& flash_message_loop,
+ IPC::Message* reply);
+ void OnMsgQuit(const ppapi::HostResource& flash_message_loop);
+
+ void WillQuitSoon(scoped_ptr<IPC::Message> reply_message, int32_t result);
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_Flash_MessageLoop_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PPB_FLASH_MESSAGE_LOOP_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppb_graphics_3d_proxy.cc b/chromium/ppapi/proxy/ppb_graphics_3d_proxy.cc
new file mode 100644
index 00000000000..7d18850ea3c
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_graphics_3d_proxy.cc
@@ -0,0 +1,497 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppb_graphics_3d_proxy.h"
+
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/common/command_buffer.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/enter_proxy.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_command_buffer_proxy.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/resource_creation_api.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_Graphics3D_API;
+using ppapi::thunk::ResourceCreationAPI;
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+const int32 kCommandBufferSize = 1024 * 1024;
+const int32 kTransferBufferSize = 1024 * 1024;
+
+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);
+}
+
+gpu::CommandBuffer::State GetErrorState() {
+ gpu::CommandBuffer::State error_state;
+ error_state.error = gpu::error::kGenericError;
+ return error_state;
+}
+
+} // namespace
+
+// This class just wraps a CommandBuffer and optionally locks around every
+// method. This is used to ensure that we have the Proxy lock any time we enter
+// PpapiCommandBufferProxy.
+//
+// Note, for performance reasons, most of this code is not truly thread
+// safe in the sense of multiple threads concurrently rendering to the same
+// Graphics3D context; this isn't allowed, and will likely either crash or
+// result in undefined behavior. It is assumed that the thread which creates
+// the Graphics3D context will be the thread on which subsequent gl rendering
+// will be done.
+//
+// TODO(nfullagar): At some point, allow multiple threads to concurrently render
+// each to its own context. First step is to allow a single thread (either main
+// thread or background thread) to render to a single Graphics3D context.
+class Graphics3D::LockingCommandBuffer : public gpu::CommandBuffer {
+ public:
+ explicit LockingCommandBuffer(gpu::CommandBuffer* gpu_command_buffer)
+ : gpu_command_buffer_(gpu_command_buffer), need_to_lock_(true) {
+ }
+ virtual ~LockingCommandBuffer() {
+ }
+ void set_need_to_lock(bool need_to_lock) { need_to_lock_ = need_to_lock; }
+ bool need_to_lock() const { return need_to_lock_; }
+
+ private:
+ // MaybeLock acquires the proxy lock on construction if and only if
+ // need_to_lock is true. If it acquired the lock, it releases it on
+ // destruction. If need_to_lock is false, then the lock must already be held.
+ struct MaybeLock {
+ explicit MaybeLock(bool need_to_lock) : locked_(need_to_lock) {
+ if (need_to_lock)
+ ppapi::ProxyLock::Acquire();
+ else
+ ppapi::ProxyLock::AssertAcquired();
+ }
+ ~MaybeLock() {
+ if (locked_)
+ ppapi::ProxyLock::Release();
+ }
+ private:
+ bool locked_;
+ };
+
+ // gpu::CommandBuffer implementation:
+ virtual bool Initialize() OVERRIDE {
+ MaybeLock lock(need_to_lock_);
+ return gpu_command_buffer_->Initialize();
+ }
+ virtual State GetState() OVERRIDE {
+ MaybeLock lock(need_to_lock_);
+ return gpu_command_buffer_->GetState();
+ }
+ virtual State GetLastState() OVERRIDE {
+ // During a normal scene, the vast majority of calls are to GetLastState().
+ // We don't allow multi-threaded rendering on the same contex, so for
+ // performance reasons, avoid the global lock for this entry point. We can
+ // get away with this here because the underlying implementation of
+ // GetLastState() is trivial and does not involve global or shared state
+ // between other contexts.
+ // TODO(nfullagar): We can probably skip MaybeLock for other methods, but
+ // the performance gain may not be worth it.
+ //
+ // MaybeLock lock(need_to_lock_);
+ return gpu_command_buffer_->GetLastState();
+ }
+ virtual int32 GetLastToken() OVERRIDE {
+ return GetLastState().token;
+ }
+ virtual void Flush(int32 put_offset) OVERRIDE {
+ MaybeLock lock(need_to_lock_);
+ gpu_command_buffer_->Flush(put_offset);
+ }
+ virtual State FlushSync(int32 put_offset, int32 last_known_get) OVERRIDE {
+ MaybeLock lock(need_to_lock_);
+ return gpu_command_buffer_->FlushSync(put_offset, last_known_get);
+ }
+ virtual void SetGetBuffer(int32 transfer_buffer_id) OVERRIDE {
+ MaybeLock lock(need_to_lock_);
+ gpu_command_buffer_->SetGetBuffer(transfer_buffer_id);
+ }
+ virtual void SetGetOffset(int32 get_offset) OVERRIDE {
+ MaybeLock lock(need_to_lock_);
+ gpu_command_buffer_->SetGetOffset(get_offset);
+ }
+ virtual gpu::Buffer CreateTransferBuffer(size_t size,
+ int32* id) OVERRIDE {
+ MaybeLock lock(need_to_lock_);
+ return gpu_command_buffer_->CreateTransferBuffer(size, id);
+ }
+ virtual void DestroyTransferBuffer(int32 id) OVERRIDE {
+ MaybeLock lock(need_to_lock_);
+ gpu_command_buffer_->DestroyTransferBuffer(id);
+ }
+ virtual gpu::Buffer GetTransferBuffer(int32 id) OVERRIDE {
+ MaybeLock lock(need_to_lock_);
+ return gpu_command_buffer_->GetTransferBuffer(id);
+ }
+ virtual void SetToken(int32 token) OVERRIDE {
+ MaybeLock lock(need_to_lock_);
+ gpu_command_buffer_->SetToken(token);
+ }
+ virtual void SetParseError(gpu::error::Error error) OVERRIDE {
+ MaybeLock lock(need_to_lock_);
+ gpu_command_buffer_->SetParseError(error);
+ }
+ virtual void SetContextLostReason(
+ gpu::error::ContextLostReason reason) OVERRIDE {
+ MaybeLock lock(need_to_lock_);
+ gpu_command_buffer_->SetContextLostReason(reason);
+ }
+ virtual uint32 InsertSyncPoint() OVERRIDE {
+ MaybeLock lock(need_to_lock_);
+ return gpu_command_buffer_->InsertSyncPoint();
+ }
+
+ // Weak pointer - see class Graphics3D for the scopted_ptr.
+ gpu::CommandBuffer* gpu_command_buffer_;
+
+ bool need_to_lock_;
+};
+
+Graphics3D::Graphics3D(const HostResource& resource)
+ : PPB_Graphics3D_Shared(resource),
+ num_already_locked_calls_(0) {
+}
+
+Graphics3D::~Graphics3D() {
+ DestroyGLES2Impl();
+}
+
+bool Graphics3D::Init(gpu::gles2::GLES2Implementation* share_gles2) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForResource(this);
+ if (!dispatcher)
+ return false;
+
+ command_buffer_.reset(
+ new PpapiCommandBufferProxy(host_resource(), dispatcher));
+ locking_command_buffer_.reset(
+ new LockingCommandBuffer(command_buffer_.get()));
+
+ ScopedNoLocking already_locked(this);
+ return CreateGLES2Impl(kCommandBufferSize, kTransferBufferSize,
+ share_gles2);
+}
+
+PP_Bool Graphics3D::SetGetBuffer(int32_t /* transfer_buffer_id */) {
+ return PP_FALSE;
+}
+
+gpu::CommandBuffer::State Graphics3D::GetState() {
+ return GetErrorState();
+}
+
+PP_Bool Graphics3D::Flush(int32_t put_offset) {
+ return PP_FALSE;
+}
+
+gpu::CommandBuffer::State Graphics3D::FlushSync(int32_t put_offset) {
+ return GetErrorState();
+}
+
+int32_t Graphics3D::CreateTransferBuffer(uint32_t size) {
+ return PP_FALSE;
+}
+
+PP_Bool Graphics3D::DestroyTransferBuffer(int32_t id) {
+ return PP_FALSE;
+}
+
+PP_Bool Graphics3D::GetTransferBuffer(int32_t id,
+ int* shm_handle,
+ uint32_t* shm_size) {
+ return PP_FALSE;
+}
+
+gpu::CommandBuffer::State Graphics3D::FlushSyncFast(int32_t put_offset,
+ int32_t last_known_get) {
+ return GetErrorState();
+}
+
+uint32_t Graphics3D::InsertSyncPoint() {
+ NOTREACHED();
+ return 0;
+}
+
+gpu::CommandBuffer* Graphics3D::GetCommandBuffer() {
+ return locking_command_buffer_.get();
+}
+
+int32 Graphics3D::DoSwapBuffers() {
+ // gles2_impl()->SwapBuffers() results in CommandBuffer calls, and we already
+ // have the proxy lock.
+ ScopedNoLocking already_locked(this);
+
+ gles2_impl()->SwapBuffers();
+ IPC::Message* msg = new PpapiHostMsg_PPBGraphics3D_SwapBuffers(
+ API_ID_PPB_GRAPHICS_3D, host_resource());
+ msg->set_unblock(true);
+ PluginDispatcher::GetForResource(this)->Send(msg);
+
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void Graphics3D::PushAlreadyLocked() {
+ ppapi::ProxyLock::AssertAcquired();
+ if (num_already_locked_calls_ == 0)
+ locking_command_buffer_->set_need_to_lock(false);
+ ++num_already_locked_calls_;
+}
+
+void Graphics3D::PopAlreadyLocked() {
+ // We must have Pushed before we can Pop.
+ DCHECK(!locking_command_buffer_->need_to_lock());
+ DCHECK_GT(num_already_locked_calls_, 0);
+ ppapi::ProxyLock::AssertAcquired();
+ --num_already_locked_calls_;
+ if (num_already_locked_calls_ == 0)
+ locking_command_buffer_->set_need_to_lock(true);
+}
+
+PPB_Graphics3D_Proxy::PPB_Graphics3D_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher),
+ callback_factory_(this) {
+}
+
+PPB_Graphics3D_Proxy::~PPB_Graphics3D_Proxy() {
+}
+
+// static
+PP_Resource PPB_Graphics3D_Proxy::CreateProxyResource(
+ PP_Instance instance,
+ PP_Resource share_context,
+ const int32_t* attrib_list) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return PP_ERROR_BADARGUMENT;
+
+ HostResource share_host;
+ gpu::gles2::GLES2Implementation* share_gles2 = NULL;
+ if (share_context != 0) {
+ EnterResourceNoLock<PPB_Graphics3D_API> enter(share_context, true);
+ if (enter.failed())
+ return PP_ERROR_BADARGUMENT;
+
+ PPB_Graphics3D_Shared* share_graphics =
+ static_cast<PPB_Graphics3D_Shared*>(enter.object());
+ share_host = share_graphics->host_resource();
+ share_gles2 = share_graphics->gles2_impl();
+ }
+
+ std::vector<int32_t> attribs;
+ if (attrib_list) {
+ for (const int32_t* attr = attrib_list;
+ attr[0] != PP_GRAPHICS3DATTRIB_NONE;
+ attr += 2) {
+ attribs.push_back(attr[0]);
+ attribs.push_back(attr[1]);
+ }
+ }
+ attribs.push_back(PP_GRAPHICS3DATTRIB_NONE);
+
+ HostResource result;
+ dispatcher->Send(new PpapiHostMsg_PPBGraphics3D_Create(
+ API_ID_PPB_GRAPHICS_3D, instance, share_host, attribs, &result));
+ if (result.is_null())
+ return 0;
+
+ scoped_refptr<Graphics3D> graphics_3d(new Graphics3D(result));
+ if (!graphics_3d->Init(share_gles2))
+ return 0;
+ return graphics_3d->GetReference();
+}
+
+bool PPB_Graphics3D_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Graphics3D_Proxy, msg)
+#if !defined(OS_NACL)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_Create,
+ OnMsgCreate)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SetGetBuffer,
+ OnMsgSetGetBuffer)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_GetState,
+ OnMsgGetState)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_Flush,
+ OnMsgFlush)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_AsyncFlush,
+ OnMsgAsyncFlush)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer,
+ OnMsgCreateTransferBuffer)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer,
+ OnMsgDestroyTransferBuffer)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_GetTransferBuffer,
+ OnMsgGetTransferBuffer)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SwapBuffers,
+ OnMsgSwapBuffers)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_InsertSyncPoint,
+ OnMsgInsertSyncPoint)
+#endif // !defined(OS_NACL)
+
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBGraphics3D_SwapBuffersACK,
+ OnMsgSwapBuffersACK)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+
+ IPC_END_MESSAGE_MAP()
+ // FIXME(brettw) handle bad messages!
+ return handled;
+}
+
+#if !defined(OS_NACL)
+void PPB_Graphics3D_Proxy::OnMsgCreate(PP_Instance instance,
+ HostResource share_context,
+ const std::vector<int32_t>& attribs,
+ HostResource* result) {
+ if (attribs.empty() ||
+ attribs.back() != PP_GRAPHICS3DATTRIB_NONE ||
+ !(attribs.size() & 1))
+ return; // Bad message.
+
+ thunk::EnterResourceCreation enter(instance);
+
+ if (enter.succeeded()) {
+ result->SetHostResource(
+ instance,
+ enter.functions()->CreateGraphics3DRaw(instance,
+ share_context.host_resource(),
+ &attribs.front()));
+ }
+}
+
+void PPB_Graphics3D_Proxy::OnMsgSetGetBuffer(
+ const HostResource& context,
+ int32 transfer_buffer_id) {
+ EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
+ if (enter.succeeded())
+ enter.object()->SetGetBuffer(transfer_buffer_id);
+}
+
+void PPB_Graphics3D_Proxy::OnMsgGetState(const HostResource& context,
+ gpu::CommandBuffer::State* state,
+ bool* success) {
+ EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
+ if (enter.failed()) {
+ *success = false;
+ return;
+ }
+ *state = enter.object()->GetState();
+ *success = true;
+}
+
+void PPB_Graphics3D_Proxy::OnMsgFlush(const HostResource& context,
+ int32 put_offset,
+ int32 last_known_get,
+ gpu::CommandBuffer::State* state,
+ bool* success) {
+ EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
+ if (enter.failed()) {
+ *success = false;
+ return;
+ }
+ *state = enter.object()->FlushSyncFast(put_offset, last_known_get);
+ *success = true;
+}
+
+void PPB_Graphics3D_Proxy::OnMsgAsyncFlush(const HostResource& context,
+ int32 put_offset) {
+ EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
+ if (enter.succeeded())
+ enter.object()->Flush(put_offset);
+}
+
+void PPB_Graphics3D_Proxy::OnMsgCreateTransferBuffer(
+ const HostResource& context,
+ uint32 size,
+ int32* id) {
+ EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
+ if (enter.succeeded())
+ *id = enter.object()->CreateTransferBuffer(size);
+ else
+ *id = -1;
+}
+
+void PPB_Graphics3D_Proxy::OnMsgDestroyTransferBuffer(
+ const HostResource& context,
+ int32 id) {
+ EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
+ if (enter.succeeded())
+ enter.object()->DestroyTransferBuffer(id);
+}
+
+void PPB_Graphics3D_Proxy::OnMsgGetTransferBuffer(
+ const HostResource& context,
+ int32 id,
+ ppapi::proxy::SerializedHandle* transfer_buffer) {
+ transfer_buffer->set_null_shmem();
+
+ EnterHostFromHostResource<PPB_Graphics3D_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->set_shmem(
+ TransportSHMHandleFromInt(dispatcher(), shm_handle),
+ shm_size);
+ }
+}
+
+void PPB_Graphics3D_Proxy::OnMsgSwapBuffers(const HostResource& context) {
+ EnterHostFromHostResourceForceCallback<PPB_Graphics3D_API> enter(
+ context, callback_factory_,
+ &PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin, context);
+ if (enter.succeeded())
+ enter.SetResult(enter.object()->SwapBuffers(enter.callback()));
+}
+
+void PPB_Graphics3D_Proxy::OnMsgInsertSyncPoint(const HostResource& context,
+ uint32* sync_point) {
+ *sync_point = 0;
+ EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
+ if (enter.succeeded())
+ *sync_point = enter.object()->InsertSyncPoint();
+}
+#endif // !defined(OS_NACL)
+
+void PPB_Graphics3D_Proxy::OnMsgSwapBuffersACK(const HostResource& resource,
+ int32_t pp_error) {
+ EnterPluginFromHostResource<PPB_Graphics3D_API> enter(resource);
+ if (enter.succeeded())
+ static_cast<Graphics3D*>(enter.object())->SwapBuffersACK(pp_error);
+}
+
+#if !defined(OS_NACL)
+void PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin(
+ int32_t result,
+ const HostResource& context) {
+ dispatcher()->Send(new PpapiMsg_PPBGraphics3D_SwapBuffersACK(
+ API_ID_PPB_GRAPHICS_3D, context, result));
+}
+#endif // !defined(OS_NACL)
+
+} // namespace proxy
+} // namespace ppapi
+
diff --git a/chromium/ppapi/proxy/ppb_graphics_3d_proxy.h b/chromium/ppapi/proxy/ppb_graphics_3d_proxy.h
new file mode 100644
index 00000000000..ffda80c754a
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_graphics_3d_proxy.h
@@ -0,0 +1,124 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPB_GRAPHICS_3D_PROXY_H_
+#define PPAPI_PROXY_PPB_GRAPHICS_3D_PROXY_H_
+
+#include <vector>
+
+#include "base/memory/shared_memory.h"
+#include "gpu/command_buffer/common/command_buffer.h"
+#include "ppapi/c/pp_graphics_3d.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/proxy_completion_callback_factory.h"
+#include "ppapi/shared_impl/ppb_graphics_3d_shared.h"
+#include "ppapi/shared_impl/resource.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+namespace ppapi {
+
+class HostResource;
+
+namespace proxy {
+
+class SerializedHandle;
+
+class Graphics3D : public PPB_Graphics3D_Shared {
+ public:
+ explicit Graphics3D(const HostResource& resource);
+ virtual ~Graphics3D();
+
+ bool Init(gpu::gles2::GLES2Implementation* share_gles2);
+
+ // Graphics3DTrusted API. These are not implemented in the proxy.
+ virtual PP_Bool SetGetBuffer(int32_t shm_id) OVERRIDE;
+ virtual gpu::CommandBuffer::State GetState() OVERRIDE;
+ virtual PP_Bool Flush(int32_t put_offset) OVERRIDE;
+ virtual gpu::CommandBuffer::State 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 gpu::CommandBuffer::State FlushSyncFast(
+ int32_t put_offset,
+ int32_t last_known_get) OVERRIDE;
+ virtual uint32_t InsertSyncPoint() OVERRIDE;
+
+ private:
+ class LockingCommandBuffer;
+
+ // PPB_Graphics3D_Shared overrides.
+ virtual gpu::CommandBuffer* GetCommandBuffer() OVERRIDE;
+ virtual int32 DoSwapBuffers() OVERRIDE;
+ virtual void PushAlreadyLocked() OVERRIDE;
+ virtual void PopAlreadyLocked() OVERRIDE;
+
+ int num_already_locked_calls_;
+ scoped_ptr<gpu::CommandBuffer> command_buffer_;
+ scoped_ptr<LockingCommandBuffer> locking_command_buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(Graphics3D);
+};
+
+class PPB_Graphics3D_Proxy : public InterfaceProxy {
+ public:
+ PPB_Graphics3D_Proxy(Dispatcher* dispatcher);
+ virtual ~PPB_Graphics3D_Proxy();
+
+ static PP_Resource CreateProxyResource(
+ PP_Instance instance,
+ PP_Resource share_context,
+ const int32_t* attrib_list);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ static const ApiID kApiID = API_ID_PPB_GRAPHICS_3D;
+
+ private:
+ void OnMsgCreate(PP_Instance instance,
+ HostResource share_context,
+ const std::vector<int32_t>& attribs,
+ HostResource* result);
+ void OnMsgSetGetBuffer(const HostResource& context,
+ int32 id);
+ void OnMsgGetState(const HostResource& context,
+ gpu::CommandBuffer::State* state,
+ bool* success);
+ void OnMsgFlush(const HostResource& context,
+ int32 put_offset,
+ int32 last_known_get,
+ gpu::CommandBuffer::State* state,
+ bool* success);
+ void OnMsgAsyncFlush(const HostResource& context,
+ int32 put_offset);
+ void OnMsgCreateTransferBuffer(const HostResource& context,
+ uint32 size,
+ int32* id);
+ void OnMsgDestroyTransferBuffer(const HostResource& context,
+ int32 id);
+ void OnMsgGetTransferBuffer(const HostResource& context,
+ int32 id,
+ ppapi::proxy::SerializedHandle* transfer_buffer);
+ void OnMsgSwapBuffers(const HostResource& context);
+ void OnMsgInsertSyncPoint(const HostResource& context, uint32* sync_point);
+ // Renderer->plugin message handlers.
+ void OnMsgSwapBuffersACK(const HostResource& context,
+ int32_t pp_error);
+
+ void SendSwapBuffersACKToPlugin(int32_t result,
+ const HostResource& context);
+
+ ProxyCompletionCallbackFactory<PPB_Graphics3D_Proxy> callback_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_Graphics3D_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPB_GRAPHICS_3D_PROXY_H_
+
diff --git a/chromium/ppapi/proxy/ppb_image_data_proxy.cc b/chromium/ppapi/proxy/ppb_image_data_proxy.cc
new file mode 100644
index 00000000000..0ed3c24a37a
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_image_data_proxy.cc
@@ -0,0 +1,707 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppb_image_data_proxy.h"
+
+#include <string.h> // For memcpy
+
+#include <map>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "base/memory/weak_ptr.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/enter_proxy.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/host_resource.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/resource.h"
+#include "ppapi/shared_impl/scoped_pp_resource.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/thunk.h"
+
+#if !defined(OS_NACL)
+#include "skia/ext/platform_canvas.h"
+#include "ui/surface/transport_dib.h"
+#endif
+
+using ppapi::thunk::PPB_ImageData_API;
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+// How ImageData re-use works
+// --------------------------
+//
+// When animating plugins (like video), re-creating image datas for each frame
+// and mapping the memory has a high overhead. So we try to re-use these when
+// possible.
+//
+// 1. Plugin makes an asynchronous call that transfers an ImageData to the
+// implementation of some API.
+// 2. Plugin frees its ImageData reference. If it doesn't do this we can't
+// re-use it.
+// 3. When the last plugin ref of an ImageData is released, we don't actually
+// delete it. Instead we put it on a queue where we hold onto it in the
+// plugin process for a short period of time.
+// 4. The API implementation that received the ImageData finishes using it.
+// Without our caching system it would get deleted at this point.
+// 5. The proxy in the renderer will send NotifyUnusedImageData back to the
+// plugin process. We check if the given resource is in the queue and mark
+// it as usable.
+// 6. When the plugin requests a new image data, we check our queue and if there
+// is a usable ImageData of the right size and format, we'll return it
+// instead of making a new one. It's important that caching is only requested
+// when the size is unlikely to change, so cache hits are high.
+//
+// Some notes:
+//
+// - We only re-use image data when the plugin and host are rapidly exchanging
+// them and the size is likely to remain constant. It should be clear that
+// the plugin is promising that it's done with the image.
+//
+// - Theoretically we could re-use them in other cases but the lifetime
+// becomes more difficult to manage. The plugin could have used an ImageData
+// in an arbitrary number of queued up PaintImageData calls which we would
+// have to check.
+//
+// - If a flush takes a long time or there are many released image datas
+// accumulating in our queue such that some are deleted, we will have
+// released our reference by the time the renderer notifies us of an unused
+// image data. In this case we just give up.
+//
+// - We maintain a per-instance cache. Some pages have many instances of
+// Flash, for example, each of a different size. If they're all animating we
+// want each to get its own image data re-use.
+//
+// - We generate new resource IDs when re-use happens to try to avoid weird
+// problems if the plugin messes up its refcounting.
+
+// Keep a cache entry for this many seconds before expiring it. We get an entry
+// back from the renderer after an ImageData is swapped out, so it means the
+// plugin has to be painting at least two frames for this time interval to
+// get caching.
+static const int kMaxAgeSeconds = 2;
+
+// ImageDataCacheEntry ---------------------------------------------------------
+
+struct ImageDataCacheEntry {
+ ImageDataCacheEntry() : added_time(), usable(false), image() {}
+ ImageDataCacheEntry(ImageData* i)
+ : added_time(base::TimeTicks::Now()),
+ usable(false),
+ image(i) {
+ }
+
+ base::TimeTicks added_time;
+
+ // Set to true when the renderer tells us that it's OK to re-use this iamge.
+ bool usable;
+
+ scoped_refptr<ImageData> image;
+};
+
+// ImageDataInstanceCache ------------------------------------------------------
+
+// Per-instance cache of image datas.
+class ImageDataInstanceCache {
+ public:
+ ImageDataInstanceCache() : next_insertion_point_(0) {}
+
+ // These functions have the same spec as the ones in ImageDataCache.
+ scoped_refptr<ImageData> Get(PPB_ImageData_Shared::ImageDataType type,
+ int width, int height,
+ PP_ImageDataFormat format);
+ void Add(ImageData* image_data);
+ void ImageDataUsable(ImageData* image_data);
+
+ // Expires old entries. Returns true if there are still entries in the list,
+ // false if this instance cache is now empty.
+ bool ExpireEntries();
+
+ private:
+ void IncrementInsertionPoint();
+
+ // We'll store this many ImageDatas per instance.
+ const static int kCacheSize = 2;
+
+ ImageDataCacheEntry images_[kCacheSize];
+
+ // Index into cache where the next item will go.
+ int next_insertion_point_;
+};
+
+scoped_refptr<ImageData> ImageDataInstanceCache::Get(
+ PPB_ImageData_Shared::ImageDataType type,
+ int width, int height,
+ PP_ImageDataFormat format) {
+ // Just do a brute-force search since the cache is so small.
+ for (int i = 0; i < kCacheSize; i++) {
+ if (!images_[i].usable)
+ continue;
+ if (images_[i].image->type() != type)
+ continue;
+ const PP_ImageDataDesc& desc = images_[i].image->desc();
+ if (desc.format == format &&
+ desc.size.width == width && desc.size.height == height) {
+ scoped_refptr<ImageData> ret(images_[i].image);
+ images_[i] = ImageDataCacheEntry();
+
+ // Since we just removed an item, this entry is the best place to insert
+ // a subsequent one.
+ next_insertion_point_ = i;
+ return ret;
+ }
+ }
+ return scoped_refptr<ImageData>();
+}
+
+void ImageDataInstanceCache::Add(ImageData* image_data) {
+ images_[next_insertion_point_] = ImageDataCacheEntry(image_data);
+ IncrementInsertionPoint();
+}
+
+void ImageDataInstanceCache::ImageDataUsable(ImageData* image_data) {
+ for (int i = 0; i < kCacheSize; i++) {
+ if (images_[i].image.get() == image_data) {
+ images_[i].usable = true;
+
+ // This test is important. The renderer doesn't guarantee how many image
+ // datas it has or when it notifies us when one is usable. Its possible
+ // to get into situations where it's always telling us the old one is
+ // usable, and then the older one immediately gets expired. Therefore,
+ // if the next insertion would overwrite this now-usable entry, make the
+ // next insertion overwrite some other entry to avoid the replacement.
+ if (next_insertion_point_ == i)
+ IncrementInsertionPoint();
+ return;
+ }
+ }
+}
+
+bool ImageDataInstanceCache::ExpireEntries() {
+ base::TimeTicks threshold_time =
+ base::TimeTicks::Now() - base::TimeDelta::FromSeconds(kMaxAgeSeconds);
+
+ bool has_entry = false;
+ for (int i = 0; i < kCacheSize; i++) {
+ if (images_[i].image.get()) {
+ // Entry present.
+ if (images_[i].added_time <= threshold_time) {
+ // Found an entry to expire.
+ images_[i] = ImageDataCacheEntry();
+ next_insertion_point_ = i;
+ } else {
+ // Found an entry that we're keeping.
+ has_entry = true;
+ }
+ }
+ }
+ return has_entry;
+}
+
+void ImageDataInstanceCache::IncrementInsertionPoint() {
+ // Go to the next location, wrapping around to get LRU.
+ next_insertion_point_++;
+ if (next_insertion_point_ >= kCacheSize)
+ next_insertion_point_ = 0;
+}
+
+// ImageDataCache --------------------------------------------------------------
+
+class ImageDataCache {
+ public:
+ ImageDataCache() : weak_factory_(this) {}
+ ~ImageDataCache() {}
+
+ static ImageDataCache* GetInstance();
+
+ // Retrieves an image data from the cache of the specified type, size and
+ // format if one exists. If one doesn't exist, this will return a null refptr.
+ scoped_refptr<ImageData> Get(PP_Instance instance,
+ PPB_ImageData_Shared::ImageDataType type,
+ int width, int height,
+ PP_ImageDataFormat format);
+
+ // Adds the given image data to the cache. There should be no plugin
+ // references to it. This may delete an older item from the cache.
+ void Add(ImageData* image_data);
+
+ // Notification from the renderer that the given image data is usable.
+ void ImageDataUsable(ImageData* image_data);
+
+ void DidDeleteInstance(PP_Instance instance);
+
+ private:
+ friend struct LeakySingletonTraits<ImageDataCache>;
+
+ // Timer callback to expire entries for the given instance.
+ void OnTimer(PP_Instance instance);
+
+ // This class does timer calls and we don't want to run these outside of the
+ // scope of the object. Technically, since this class is a leaked static,
+ // this will never happen and this factory is unnecessary. However, it's
+ // probably better not to make assumptions about the lifetime of this class.
+ base::WeakPtrFactory<ImageDataCache> weak_factory_;
+
+ typedef std::map<PP_Instance, ImageDataInstanceCache> CacheMap;
+ CacheMap cache_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImageDataCache);
+};
+
+// static
+ImageDataCache* ImageDataCache::GetInstance() {
+ return Singleton<ImageDataCache,
+ LeakySingletonTraits<ImageDataCache> >::get();
+}
+
+scoped_refptr<ImageData> ImageDataCache::Get(
+ PP_Instance instance,
+ PPB_ImageData_Shared::ImageDataType type,
+ int width, int height,
+ PP_ImageDataFormat format) {
+ CacheMap::iterator found = cache_.find(instance);
+ if (found == cache_.end())
+ return scoped_refptr<ImageData>();
+ return found->second.Get(type, width, height, format);
+}
+
+void ImageDataCache::Add(ImageData* image_data) {
+ cache_[image_data->pp_instance()].Add(image_data);
+
+ // Schedule a timer to invalidate this entry.
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ RunWhileLocked(base::Bind(&ImageDataCache::OnTimer,
+ weak_factory_.GetWeakPtr(),
+ image_data->pp_instance())),
+ base::TimeDelta::FromSeconds(kMaxAgeSeconds));
+}
+
+void ImageDataCache::ImageDataUsable(ImageData* image_data) {
+ CacheMap::iterator found = cache_.find(image_data->pp_instance());
+ if (found != cache_.end())
+ found->second.ImageDataUsable(image_data);
+}
+
+void ImageDataCache::DidDeleteInstance(PP_Instance instance) {
+ cache_.erase(instance);
+}
+
+void ImageDataCache::OnTimer(PP_Instance instance) {
+ CacheMap::iterator found = cache_.find(instance);
+ if (found == cache_.end())
+ return;
+ if (!found->second.ExpireEntries()) {
+ // There are no more entries for this instance, remove it from the cache.
+ cache_.erase(found);
+ }
+}
+
+} // namespace
+
+// ImageData -------------------------------------------------------------------
+
+ImageData::ImageData(const HostResource& resource,
+ PPB_ImageData_Shared::ImageDataType type,
+ const PP_ImageDataDesc& desc)
+ : Resource(OBJECT_IS_PROXY, resource),
+ type_(type),
+ desc_(desc),
+ is_candidate_for_reuse_(false) {
+}
+
+ImageData::~ImageData() {
+}
+
+PPB_ImageData_API* ImageData::AsPPB_ImageData_API() {
+ return this;
+}
+
+void ImageData::LastPluginRefWasDeleted() {
+ // The plugin no longer needs this ImageData, add it to our cache if it's
+ // been used in a ReplaceContents. These are the ImageDatas that the renderer
+ // will send back ImageDataUsable messages for.
+ if (is_candidate_for_reuse_)
+ ImageDataCache::GetInstance()->Add(this);
+}
+
+void ImageData::InstanceWasDeleted() {
+ ImageDataCache::GetInstance()->DidDeleteInstance(pp_instance());
+}
+
+PP_Bool ImageData::Describe(PP_ImageDataDesc* desc) {
+ memcpy(desc, &desc_, sizeof(PP_ImageDataDesc));
+ return PP_TRUE;
+}
+
+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;
+}
+
+void ImageData::SetIsCandidateForReuse() {
+ is_candidate_for_reuse_ = true;
+}
+
+void ImageData::RecycleToPlugin(bool zero_contents) {
+ is_candidate_for_reuse_ = false;
+ if (zero_contents) {
+ void* data = Map();
+ memset(data, 0, desc_.stride * desc_.size.height);
+ Unmap();
+ }
+}
+
+// PlatformImageData -----------------------------------------------------------
+
+#if !defined(OS_NACL)
+PlatformImageData::PlatformImageData(const HostResource& resource,
+ const PP_ImageDataDesc& desc,
+ ImageHandle handle)
+ : ImageData(resource, PPB_ImageData_Shared::PLATFORM, desc) {
+#if defined(OS_WIN)
+ transport_dib_.reset(TransportDIB::CreateWithHandle(handle));
+#else
+ transport_dib_.reset(TransportDIB::Map(handle));
+#endif // defined(OS_WIN)
+}
+
+PlatformImageData::~PlatformImageData() {
+}
+
+void* PlatformImageData::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 PlatformImageData::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.
+}
+
+SkCanvas* PlatformImageData::GetPlatformCanvas() {
+ return mapped_canvas_.get();
+}
+
+SkCanvas* PlatformImageData::GetCanvas() {
+ return mapped_canvas_.get();
+}
+
+// static
+ImageHandle PlatformImageData::NullHandle() {
+#if defined(OS_WIN)
+ return NULL;
+#elif defined(TOOLKIT_GTK)
+ return 0;
+#else
+ return ImageHandle();
+#endif
+}
+
+ImageHandle PlatformImageData::HandleFromInt(int32_t i) {
+#if defined(OS_WIN)
+ return reinterpret_cast<ImageHandle>(i);
+#elif defined(TOOLKIT_GTK)
+ return static_cast<ImageHandle>(i);
+#else
+ return ImageHandle(i, false);
+#endif
+}
+#endif // !defined(OS_NACL)
+
+// SimpleImageData -------------------------------------------------------------
+
+SimpleImageData::SimpleImageData(const HostResource& resource,
+ const PP_ImageDataDesc& desc,
+ const base::SharedMemoryHandle& handle)
+ : ImageData(resource, PPB_ImageData_Shared::SIMPLE, desc),
+ shm_(handle, false /* read_only */),
+ size_(desc.size.width * desc.size.height * 4),
+ map_count_(0) {
+}
+
+SimpleImageData::~SimpleImageData() {
+}
+
+void* SimpleImageData::Map() {
+ if (map_count_++ == 0)
+ shm_.Map(size_);
+ return shm_.memory();
+}
+
+void SimpleImageData::Unmap() {
+ if (--map_count_ == 0)
+ shm_.Unmap();
+}
+
+SkCanvas* SimpleImageData::GetPlatformCanvas() {
+ return NULL; // No canvas available.
+}
+
+SkCanvas* SimpleImageData::GetCanvas() {
+ return NULL; // No canvas available.
+}
+
+// PPB_ImageData_Proxy ---------------------------------------------------------
+
+PPB_ImageData_Proxy::PPB_ImageData_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher) {
+}
+
+PPB_ImageData_Proxy::~PPB_ImageData_Proxy() {
+}
+
+// static
+PP_Resource PPB_ImageData_Proxy::CreateProxyResource(
+ PP_Instance instance,
+ PPB_ImageData_Shared::ImageDataType type,
+ PP_ImageDataFormat format,
+ const PP_Size& size,
+ PP_Bool init_to_zero) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+
+ // Check the cache.
+ scoped_refptr<ImageData> cached_image_data =
+ ImageDataCache::GetInstance()->Get(instance, type,
+ size.width, size.height, format);
+ if (cached_image_data.get()) {
+ // We have one we can re-use rather than allocating a new one.
+ cached_image_data->RecycleToPlugin(PP_ToBool(init_to_zero));
+ return cached_image_data->GetReference();
+ }
+
+ HostResource result;
+ PP_ImageDataDesc desc;
+ switch (type) {
+ case PPB_ImageData_Shared::SIMPLE: {
+ ppapi::proxy::SerializedHandle image_handle_wrapper;
+ dispatcher->Send(new PpapiHostMsg_PPBImageData_CreateSimple(
+ kApiID, instance, format, size, init_to_zero,
+ &result, &desc, &image_handle_wrapper));
+ if (image_handle_wrapper.is_shmem()) {
+ base::SharedMemoryHandle image_handle = image_handle_wrapper.shmem();
+ if (!result.is_null())
+ return
+ (new SimpleImageData(result, desc, image_handle))->GetReference();
+ }
+ break;
+ }
+ case PPB_ImageData_Shared::PLATFORM: {
+#if !defined(OS_NACL)
+ ImageHandle image_handle = PlatformImageData::NullHandle();
+ dispatcher->Send(new PpapiHostMsg_PPBImageData_CreatePlatform(
+ kApiID, instance, format, size, init_to_zero,
+ &result, &desc, &image_handle));
+ if (!result.is_null())
+ return
+ (new PlatformImageData(result, desc, image_handle))->GetReference();
+#else
+ // PlatformImageData shouldn't be created in untrusted code.
+ NOTREACHED();
+#endif
+ break;
+ }
+ }
+
+ return 0;
+}
+
+bool PPB_ImageData_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_ImageData_Proxy, msg)
+#if !defined(OS_NACL)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_CreatePlatform,
+ OnHostMsgCreatePlatform)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_CreateSimple,
+ OnHostMsgCreateSimple)
+#endif
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBImageData_NotifyUnusedImageData,
+ OnPluginMsgNotifyUnusedImageData)
+
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+#if !defined(OS_NACL)
+// static
+PP_Resource PPB_ImageData_Proxy::CreateImageData(
+ PP_Instance instance,
+ PPB_ImageData_Shared::ImageDataType type,
+ PP_ImageDataFormat format,
+ const PP_Size& size,
+ bool init_to_zero,
+ PP_ImageDataDesc* desc,
+ IPC::PlatformFileForTransit* image_handle,
+ uint32_t* byte_count) {
+ HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+
+ thunk::EnterResourceCreation enter(instance);
+ if (enter.failed())
+ return 0;
+
+ PP_Bool pp_init_to_zero = init_to_zero ? PP_TRUE : PP_FALSE;
+ PP_Resource pp_resource = 0;
+ switch (type) {
+ case PPB_ImageData_Shared::SIMPLE: {
+ pp_resource = enter.functions()->CreateImageDataSimple(
+ instance, format, &size, pp_init_to_zero);
+ break;
+ }
+ case PPB_ImageData_Shared::PLATFORM: {
+ pp_resource = enter.functions()->CreateImageData(
+ instance, format, &size, pp_init_to_zero);
+ break;
+ }
+ }
+
+ if (!pp_resource)
+ return 0;
+
+ ppapi::ScopedPPResource resource(ppapi::ScopedPPResource::PassRef(),
+ pp_resource);
+
+ thunk::EnterResourceNoLock<PPB_ImageData_API> enter_resource(resource.get(),
+ false);
+ if (enter_resource.object()->Describe(desc) != PP_TRUE) {
+ DVLOG(1) << "CreateImageData failed: could not Describe";
+ return 0;
+ }
+
+ int local_fd = 0;
+ if (enter_resource.object()->GetSharedMemory(&local_fd,
+ byte_count) != PP_OK) {
+ DVLOG(1) << "CreateImageData failed: could not GetSharedMemory";
+ return 0;
+ }
+
+#if defined(OS_WIN)
+ *image_handle = dispatcher->ShareHandleWithRemote(
+ reinterpret_cast<HANDLE>(static_cast<intptr_t>(local_fd)), false);
+#elif defined(TOOLKIT_GTK)
+ // On X Windows, a PlatformImageData is backed by a SysV shared memory key,
+ // so embed that in a fake PlatformFileForTransit and don't share it across
+ // processes.
+ if (type == PPB_ImageData_Shared::PLATFORM)
+ *image_handle = IPC::PlatformFileForTransit(local_fd, false);
+ else
+ *image_handle = dispatcher->ShareHandleWithRemote(local_fd, false);
+#elif defined(OS_POSIX)
+ *image_handle = dispatcher->ShareHandleWithRemote(local_fd, false);
+#else
+ #error Not implemented.
+#endif
+
+ return resource.Release();
+}
+
+void PPB_ImageData_Proxy::OnHostMsgCreatePlatform(
+ PP_Instance instance,
+ int32_t format,
+ const PP_Size& size,
+ PP_Bool init_to_zero,
+ HostResource* result,
+ PP_ImageDataDesc* desc,
+ ImageHandle* result_image_handle) {
+ IPC::PlatformFileForTransit image_handle;
+ uint32_t byte_count;
+ PP_Resource resource =
+ CreateImageData(instance,
+ PPB_ImageData_Shared::PLATFORM,
+ static_cast<PP_ImageDataFormat>(format),
+ size,
+ true /* init_to_zero */,
+ desc, &image_handle, &byte_count);
+ result->SetHostResource(instance, resource);
+ if (resource) {
+#if defined(TOOLKIT_GTK)
+ // On X Windows ImageHandle is a SysV shared memory key.
+ *result_image_handle = image_handle.fd;
+#else
+ *result_image_handle = image_handle;
+#endif
+ } else {
+ *result_image_handle = PlatformImageData::NullHandle();
+ }
+}
+
+void PPB_ImageData_Proxy::OnHostMsgCreateSimple(
+ PP_Instance instance,
+ int32_t format,
+ const PP_Size& size,
+ PP_Bool init_to_zero,
+ HostResource* result,
+ PP_ImageDataDesc* desc,
+ ppapi::proxy::SerializedHandle* result_image_handle) {
+ IPC::PlatformFileForTransit image_handle;
+ uint32_t byte_count;
+ PP_Resource resource =
+ CreateImageData(instance,
+ PPB_ImageData_Shared::SIMPLE,
+ static_cast<PP_ImageDataFormat>(format),
+ size,
+ true /* init_to_zero */,
+ desc, &image_handle, &byte_count);
+
+ result->SetHostResource(instance, resource);
+ if (resource) {
+ result_image_handle->set_shmem(image_handle, byte_count);
+ } else {
+ result_image_handle->set_null_shmem();
+ }
+}
+#endif // !defined(OS_NACL)
+
+void PPB_ImageData_Proxy::OnPluginMsgNotifyUnusedImageData(
+ const HostResource& old_image_data) {
+ PluginGlobals* plugin_globals = PluginGlobals::Get();
+ if (!plugin_globals)
+ return; // This may happen if the plugin is maliciously sending this
+ // message to the renderer.
+
+ EnterPluginFromHostResource<PPB_ImageData_API> enter(old_image_data);
+ if (enter.succeeded()) {
+ ImageData* image_data = static_cast<ImageData*>(enter.object());
+ ImageDataCache::GetInstance()->ImageDataUsable(image_data);
+ }
+
+ // The renderer sent us a reference with the message. If the image data was
+ // still cached in our process, the proxy still holds a reference so we can
+ // remove the one the renderer just sent is. If the proxy no longer holds a
+ // reference, we released everything and we should also release the one the
+ // renderer just sent us.
+ dispatcher()->Send(new PpapiHostMsg_PPBCore_ReleaseResource(
+ API_ID_PPB_CORE, old_image_data));
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppb_image_data_proxy.h b/chromium/ppapi/proxy/ppb_image_data_proxy.h
new file mode 100644
index 00000000000..ab7191b0c92
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_image_data_proxy.h
@@ -0,0 +1,192 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PPB_IMAGE_DATA_PROXY_H_
+#define PPAPI_PPB_IMAGE_DATA_PROXY_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/shared_memory.h"
+#include "build/build_config.h"
+#include "ipc/ipc_platform_file.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/c/ppb_image_data.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/proxy/serialized_structs.h"
+#include "ppapi/shared_impl/ppb_image_data_shared.h"
+#include "ppapi/shared_impl/resource.h"
+#include "ppapi/thunk/ppb_image_data_api.h"
+
+class TransportDIB;
+
+namespace ppapi {
+namespace proxy {
+
+class SerializedHandle;
+
+// ImageData is an abstract base class for image data resources. Unlike most
+// resources, ImageData must be public in the header since a number of other
+// resources need to access it.
+class PPAPI_PROXY_EXPORT ImageData
+ : public ppapi::Resource,
+ public NON_EXPORTED_BASE(ppapi::thunk::PPB_ImageData_API),
+ public ppapi::PPB_ImageData_Shared {
+ public:
+ virtual ~ImageData();
+
+ // Resource overrides.
+ virtual ppapi::thunk::PPB_ImageData_API* AsPPB_ImageData_API() OVERRIDE;
+ virtual void LastPluginRefWasDeleted() OVERRIDE;
+ virtual void InstanceWasDeleted() OVERRIDE;
+
+ // PPB_ImageData API.
+ virtual PP_Bool Describe(PP_ImageDataDesc* desc) OVERRIDE;
+ virtual int32_t GetSharedMemory(int* handle, uint32_t* byte_count) OVERRIDE;
+ virtual void SetIsCandidateForReuse() OVERRIDE;
+
+ PPB_ImageData_Shared::ImageDataType type() const { return type_; }
+ const PP_ImageDataDesc& desc() const { return desc_; }
+
+ // Prepares this image data to be recycled to the plugin. Clears the contents
+ // if zero_contents is true.
+ void RecycleToPlugin(bool zero_contents);
+
+ protected:
+ ImageData(const ppapi::HostResource& resource,
+ PPB_ImageData_Shared::ImageDataType type,
+ const PP_ImageDataDesc& desc);
+
+ PPB_ImageData_Shared::ImageDataType type_;
+ PP_ImageDataDesc desc_;
+
+ // Set to true when this ImageData is a good candidate for reuse.
+ bool is_candidate_for_reuse_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImageData);
+};
+
+// PlatformImageData is a full featured image data resource which can access
+// the underlying platform-specific canvas and ImageHandle. This can't be used
+// by NaCl apps.
+#if !defined(OS_NACL)
+class PPAPI_PROXY_EXPORT PlatformImageData : public ImageData {
+ public:
+ PlatformImageData(const ppapi::HostResource& resource,
+ const PP_ImageDataDesc& desc,
+ ImageHandle handle);
+ virtual ~PlatformImageData();
+
+ // PPB_ImageData API.
+ virtual void* Map() OVERRIDE;
+ virtual void Unmap() OVERRIDE;
+ virtual SkCanvas* GetPlatformCanvas() OVERRIDE;
+ virtual SkCanvas* GetCanvas() OVERRIDE;
+
+ static ImageHandle NullHandle();
+ static ImageHandle HandleFromInt(int32_t i);
+
+ private:
+ scoped_ptr<TransportDIB> transport_dib_;
+
+ // Null when the image isn't mapped.
+ scoped_ptr<SkCanvas> mapped_canvas_;
+
+ DISALLOW_COPY_AND_ASSIGN(PlatformImageData);
+};
+#endif // !defined(OS_NACL)
+
+// SimpleImageData is a simple, platform-independent image data resource which
+// can be used by NaCl. It can also be used by trusted apps when access to the
+// platform canvas isn't needed.
+class PPAPI_PROXY_EXPORT SimpleImageData : public ImageData {
+ public:
+ SimpleImageData(const ppapi::HostResource& resource,
+ const PP_ImageDataDesc& desc,
+ const base::SharedMemoryHandle& handle);
+ virtual ~SimpleImageData();
+
+ // PPB_ImageData API.
+ virtual void* Map() OVERRIDE;
+ virtual void Unmap() OVERRIDE;
+ virtual SkCanvas* GetPlatformCanvas() OVERRIDE;
+ virtual SkCanvas* GetCanvas() OVERRIDE;
+
+ private:
+ base::SharedMemory shm_;
+ uint32 size_;
+ int map_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(SimpleImageData);
+};
+
+class PPB_ImageData_Proxy : public InterfaceProxy {
+ public:
+ PPB_ImageData_Proxy(Dispatcher* dispatcher);
+ virtual ~PPB_ImageData_Proxy();
+
+ static PP_Resource CreateProxyResource(
+ PP_Instance instance,
+ PPB_ImageData_Shared::ImageDataType type,
+ PP_ImageDataFormat format,
+ const PP_Size& size,
+ PP_Bool init_to_zero);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ // Utility for creating ImageData resources.
+ // This can only be called on the host side of the proxy.
+ // On failure, will return invalid resource (0). On success it will return a
+ // valid resource and the out params will be written.
+ // |desc| contains the result of Describe.
+ // |image_handle| and |byte_count| contain the result of GetSharedMemory.
+ // NOTE: if |init_to_zero| is false, you should write over the entire image
+ // to avoid leaking sensitive data to a less privileged process.
+ PPAPI_PROXY_EXPORT static PP_Resource CreateImageData(
+ PP_Instance instance,
+ PPB_ImageData_Shared::ImageDataType type,
+ PP_ImageDataFormat format,
+ const PP_Size& size,
+ bool init_to_zero,
+ PP_ImageDataDesc* desc,
+ IPC::PlatformFileForTransit* image_handle,
+ uint32_t* byte_count);
+
+ static const ApiID kApiID = API_ID_PPB_IMAGE_DATA;
+
+ private:
+ // Plugin->Host message handlers.
+ void OnHostMsgCreatePlatform(
+ PP_Instance instance,
+ int32_t format,
+ const PP_Size& size,
+ PP_Bool init_to_zero,
+ HostResource* result,
+ PP_ImageDataDesc* desc,
+ ImageHandle* result_image_handle);
+ void OnHostMsgCreateSimple(
+ PP_Instance instance,
+ int32_t format,
+ const PP_Size& size,
+ PP_Bool init_to_zero,
+ HostResource* result,
+ PP_ImageDataDesc* desc,
+ ppapi::proxy::SerializedHandle* result_image_handle);
+
+ // Host->Plugin message handlers.
+ void OnPluginMsgNotifyUnusedImageData(const HostResource& old_image_data);
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_ImageData_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PPB_IMAGE_DATA_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppb_instance_proxy.cc b/chromium/ppapi/proxy/ppb_instance_proxy.cc
new file mode 100644
index 00000000000..20b93649ece
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_instance_proxy.cc
@@ -0,0 +1,1277 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppb_instance_proxy.h"
+
+#include "base/memory/ref_counted.h"
+#include "build/build_config.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_time.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_audio_config.h"
+#include "ppapi/c/ppb_instance.h"
+#include "ppapi/c/ppb_messaging.h"
+#include "ppapi/c/ppb_mouse_lock.h"
+#include "ppapi/c/private/pp_content_decryptor.h"
+#include "ppapi/proxy/broker_resource.h"
+#include "ppapi/proxy/browser_font_singleton_resource.h"
+#include "ppapi/proxy/content_decryptor_private_serializer.h"
+#include "ppapi/proxy/enter_proxy.h"
+#include "ppapi/proxy/ext_crx_file_system_private_resource.h"
+#include "ppapi/proxy/extensions_common_resource.h"
+#include "ppapi/proxy/flash_clipboard_resource.h"
+#include "ppapi/proxy/flash_file_resource.h"
+#include "ppapi/proxy/flash_fullscreen_resource.h"
+#include "ppapi/proxy/flash_resource.h"
+#include "ppapi/proxy/gamepad_resource.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/network_proxy_resource.h"
+#include "ppapi/proxy/pdf_resource.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/proxy/truetype_font_singleton_resource.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/ppb_url_util_shared.h"
+#include "ppapi/shared_impl/ppb_view_shared.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_graphics_2d_api.h"
+#include "ppapi/thunk/ppb_graphics_3d_api.h"
+#include "ppapi/thunk/thunk.h"
+
+// Windows headers interfere with this file.
+#ifdef PostMessage
+#undef PostMessage
+#endif
+
+using ppapi::thunk::EnterInstanceNoLock;
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_Graphics2D_API;
+using ppapi::thunk::PPB_Graphics3D_API;
+using ppapi::thunk::PPB_Instance_API;
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+const char kSerializationError[] = "Failed to convert a PostMessage "
+ "argument from a PP_Var to a Javascript value. It may have cycles or be of "
+ "an unsupported type.";
+
+InterfaceProxy* CreateInstanceProxy(Dispatcher* dispatcher) {
+ return new PPB_Instance_Proxy(dispatcher);
+}
+
+void RequestSurroundingText(PP_Instance instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return; // Instance has gone away while message was pending.
+
+ InstanceData* data = dispatcher->GetInstanceData(instance);
+ DCHECK(data); // Should have it, since we still have a dispatcher.
+ data->is_request_surrounding_text_pending = false;
+ if (!data->should_do_request_surrounding_text)
+ return;
+
+ // Just fake out a RequestSurroundingText message to the proxy for the PPP
+ // interface.
+ InterfaceProxy* proxy = dispatcher->GetInterfaceProxy(API_ID_PPP_TEXT_INPUT);
+ if (!proxy)
+ return;
+ proxy->OnMessageReceived(PpapiMsg_PPPTextInput_RequestSurroundingText(
+ API_ID_PPP_TEXT_INPUT, instance,
+ PPB_Instance_Shared::kExtraCharsForTextInput));
+}
+
+} // namespace
+
+PPB_Instance_Proxy::PPB_Instance_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher),
+ callback_factory_(this) {
+}
+
+PPB_Instance_Proxy::~PPB_Instance_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Instance_Proxy::GetInfoPrivate() {
+ static const Info info = {
+ ppapi::thunk::GetPPB_Instance_Private_0_1_Thunk(),
+ PPB_INSTANCE_PRIVATE_INTERFACE_0_1,
+ API_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).
+#if !defined(OS_NACL)
+ ScopedModuleReference death_grip(dispatcher());
+#endif
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Instance_Proxy, msg)
+#if !defined(OS_NACL)
+ // Plugin -> Host messages.
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetWindowObject,
+ OnHostMsgGetWindowObject)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetOwnerElementObject,
+ OnHostMsgGetOwnerElementObject)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_BindGraphics,
+ OnHostMsgBindGraphics)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_IsFullFrame,
+ OnHostMsgIsFullFrame)
+ IPC_MESSAGE_HANDLER(
+ PpapiHostMsg_PPBInstance_GetAudioHardwareOutputSampleRate,
+ OnHostMsgGetAudioHardwareOutputSampleRate)
+ IPC_MESSAGE_HANDLER(
+ PpapiHostMsg_PPBInstance_GetAudioHardwareOutputBufferSize,
+ OnHostMsgGetAudioHardwareOutputBufferSize)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_ExecuteScript,
+ OnHostMsgExecuteScript)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetDefaultCharSet,
+ OnHostMsgGetDefaultCharSet)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_PostMessage,
+ OnHostMsgPostMessage)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SetFullscreen,
+ OnHostMsgSetFullscreen)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetScreenSize,
+ OnHostMsgGetScreenSize)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_RequestInputEvents,
+ OnHostMsgRequestInputEvents)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_ClearInputEvents,
+ OnHostMsgClearInputEvents)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_LockMouse,
+ OnHostMsgLockMouse)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_UnlockMouse,
+ OnHostMsgUnlockMouse)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SetCursor,
+ OnHostMsgSetCursor)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SetTextInputType,
+ OnHostMsgSetTextInputType)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_UpdateCaretPosition,
+ OnHostMsgUpdateCaretPosition)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_CancelCompositionText,
+ OnHostMsgCancelCompositionText)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_UpdateSurroundingText,
+ OnHostMsgUpdateSurroundingText)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetDocumentURL,
+ OnHostMsgGetDocumentURL)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_ResolveRelativeToDocument,
+ OnHostMsgResolveRelativeToDocument)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DocumentCanRequest,
+ OnHostMsgDocumentCanRequest)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DocumentCanAccessDocument,
+ OnHostMsgDocumentCanAccessDocument)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetPluginInstanceURL,
+ OnHostMsgGetPluginInstanceURL)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_NeedKey,
+ OnHostMsgNeedKey)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_KeyAdded,
+ OnHostMsgKeyAdded)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_KeyMessage,
+ OnHostMsgKeyMessage)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_KeyError,
+ OnHostMsgKeyError)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DeliverBlock,
+ OnHostMsgDeliverBlock)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DecoderInitializeDone,
+ OnHostMsgDecoderInitializeDone)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DecoderDeinitializeDone,
+ OnHostMsgDecoderDeinitializeDone)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DecoderResetDone,
+ OnHostMsgDecoderResetDone)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DeliverFrame,
+ OnHostMsgDeliverFrame)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DeliverSamples,
+ OnHostMsgDeliverSamples)
+#endif // !defined(OS_NACL)
+
+ // Host -> Plugin messages.
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBInstance_MouseLockComplete,
+ OnPluginMsgMouseLockComplete)
+
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+PP_Bool PPB_Instance_Proxy::BindGraphics(PP_Instance instance,
+ PP_Resource device) {
+ // If device is 0, pass a null HostResource. This signals the host to unbind
+ // all devices.
+ HostResource host_resource;
+ PP_Resource pp_resource = 0;
+ if (device) {
+ Resource* resource =
+ PpapiGlobals::Get()->GetResourceTracker()->GetResource(device);
+ if (!resource || resource->pp_instance() != instance)
+ return PP_FALSE;
+ host_resource = resource->host_resource();
+ pp_resource = resource->pp_resource();
+ } else {
+ // Passing 0 means unbinding all devices.
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_BindGraphics(
+ API_ID_PPB_INSTANCE, instance, 0));
+ return PP_TRUE;
+ }
+
+ // We need to pass different resource to Graphics 2D and 3D right now. Once
+ // 3D is migrated to the new design, we should be able to unify this.
+ EnterResourceNoLock<PPB_Graphics2D_API> enter_2d(device, false);
+ EnterResourceNoLock<PPB_Graphics3D_API> enter_3d(device, false);
+ if (enter_2d.succeeded()) {
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_BindGraphics(
+ API_ID_PPB_INSTANCE, instance, pp_resource));
+ return PP_TRUE;
+ } else if (enter_3d.succeeded()) {
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_BindGraphics(
+ API_ID_PPB_INSTANCE, instance, host_resource.host_resource()));
+ return PP_TRUE;
+ }
+ return PP_FALSE;
+}
+
+PP_Bool PPB_Instance_Proxy::IsFullFrame(PP_Instance instance) {
+ PP_Bool result = PP_FALSE;
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_IsFullFrame(
+ API_ID_PPB_INSTANCE, instance, &result));
+ return result;
+}
+
+const ViewData* PPB_Instance_Proxy::GetViewData(PP_Instance instance) {
+ InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
+ GetInstanceData(instance);
+ if (!data)
+ return NULL;
+ return &data->view;
+}
+
+PP_Bool PPB_Instance_Proxy::FlashIsFullscreen(PP_Instance instance) {
+ // This function is only used for proxying in the renderer process. It is not
+ // implemented in the plugin process.
+ NOTREACHED();
+ return PP_FALSE;
+}
+
+PP_Var PPB_Instance_Proxy::GetWindowObject(PP_Instance instance) {
+ ReceiveSerializedVarReturnValue result;
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetWindowObject(
+ API_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(
+ API_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(
+ API_ID_PPB_INSTANCE, instance,
+ SerializedVarSendInput(dispatcher(), script), &se, &result));
+ return result.Return(dispatcher());
+}
+
+uint32_t PPB_Instance_Proxy::GetAudioHardwareOutputSampleRate(
+ PP_Instance instance) {
+ uint32_t result = PP_AUDIOSAMPLERATE_NONE;
+ dispatcher()->Send(
+ new PpapiHostMsg_PPBInstance_GetAudioHardwareOutputSampleRate(
+ API_ID_PPB_INSTANCE, instance, &result));
+ return result;
+}
+
+uint32_t PPB_Instance_Proxy::GetAudioHardwareOutputBufferSize(
+ PP_Instance instance) {
+ uint32_t result = 0;
+ dispatcher()->Send(
+ new PpapiHostMsg_PPBInstance_GetAudioHardwareOutputBufferSize(
+ API_ID_PPB_INSTANCE, instance, &result));
+ return result;
+}
+
+PP_Var PPB_Instance_Proxy::GetDefaultCharSet(PP_Instance instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return PP_MakeUndefined();
+
+ ReceiveSerializedVarReturnValue result;
+ dispatcher->Send(new PpapiHostMsg_PPBInstance_GetDefaultCharSet(
+ API_ID_PPB_INSTANCE, instance, &result));
+ return result.Return(dispatcher);
+}
+
+void PPB_Instance_Proxy::NumberOfFindResultsChanged(PP_Instance instance,
+ int32_t total,
+ PP_Bool final_result) {
+ NOTIMPLEMENTED(); // Not proxied yet.
+}
+
+void PPB_Instance_Proxy::SelectedFindResultChanged(PP_Instance instance,
+ int32_t index) {
+ NOTIMPLEMENTED(); // Not proxied yet.
+}
+
+PP_Bool PPB_Instance_Proxy::IsFullscreen(PP_Instance instance) {
+ InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
+ GetInstanceData(instance);
+ if (!data)
+ return PP_FALSE;
+ return PP_FromBool(data->view.is_fullscreen);
+}
+
+PP_Bool PPB_Instance_Proxy::SetFullscreen(PP_Instance instance,
+ PP_Bool fullscreen) {
+ PP_Bool result = PP_FALSE;
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_SetFullscreen(
+ API_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(
+ API_ID_PPB_INSTANCE, instance, &result, size));
+ return result;
+}
+
+Resource* PPB_Instance_Proxy::GetSingletonResource(PP_Instance instance,
+ SingletonResourceID id) {
+ InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
+ GetInstanceData(instance);
+
+ InstanceData::SingletonResourceMap::iterator it =
+ data->singleton_resources.find(id);
+ if (it != data->singleton_resources.end())
+ return it->second.get();
+
+ scoped_refptr<Resource> new_singleton;
+ Connection connection(PluginGlobals::Get()->GetBrowserSender(), dispatcher());
+
+ switch (id) {
+ case BROKER_SINGLETON_ID:
+ new_singleton = new BrokerResource(connection, instance);
+ break;
+ case CRX_FILESYSTEM_SINGLETON_ID:
+ new_singleton = new ExtCrxFileSystemPrivateResource(connection, instance);
+ break;
+ case EXTENSIONS_COMMON_SINGLETON_ID:
+ new_singleton = new ExtensionsCommonResource(connection, instance);
+ break;
+ case GAMEPAD_SINGLETON_ID:
+ new_singleton = new GamepadResource(connection, instance);
+ break;
+ case NETWORK_PROXY_SINGLETON_ID:
+ new_singleton = new NetworkProxyResource(connection, instance);
+ break;
+ case TRUETYPE_FONT_SINGLETON_ID:
+ new_singleton = new TrueTypeFontSingletonResource(connection, instance);
+ break;
+// Flash/trusted resources aren't needed for NaCl.
+#if !defined(OS_NACL) && !defined(NACL_WIN64)
+ case BROWSER_FONT_SINGLETON_ID:
+ new_singleton = new BrowserFontSingletonResource(connection, instance);
+ break;
+ case FLASH_CLIPBOARD_SINGLETON_ID:
+ new_singleton = new FlashClipboardResource(connection, instance);
+ break;
+ case FLASH_FILE_SINGLETON_ID:
+ new_singleton = new FlashFileResource(connection, instance);
+ break;
+ case FLASH_FULLSCREEN_SINGLETON_ID:
+ new_singleton = new FlashFullscreenResource(connection, instance);
+ break;
+ case FLASH_SINGLETON_ID:
+ new_singleton = new FlashResource(connection, instance,
+ static_cast<PluginDispatcher*>(dispatcher()));
+ break;
+ case PDF_SINGLETON_ID:
+ new_singleton = new PDFResource(connection, instance);
+ break;
+#else
+ case BROWSER_FONT_SINGLETON_ID:
+ case FLASH_CLIPBOARD_SINGLETON_ID:
+ case FLASH_FILE_SINGLETON_ID:
+ case FLASH_FULLSCREEN_SINGLETON_ID:
+ case FLASH_SINGLETON_ID:
+ case PDF_SINGLETON_ID:
+ NOTREACHED();
+ break;
+#endif // !defined(OS_NACL) && !defined(NACL_WIN64)
+ }
+
+ if (!new_singleton.get()) {
+ // Getting here implies that a constructor is missing in the above switch.
+ NOTREACHED();
+ return NULL;
+ }
+
+ data->singleton_resources[id] = new_singleton;
+ return new_singleton.get();
+}
+
+int32_t PPB_Instance_Proxy::RequestInputEvents(PP_Instance instance,
+ uint32_t event_classes) {
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_RequestInputEvents(
+ API_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(
+ API_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(
+ API_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();
+}
+
+PP_Var PPB_Instance_Proxy::GetDocumentURL(PP_Instance instance,
+ PP_URLComponents_Dev* components) {
+ ReceiveSerializedVarReturnValue result;
+ PP_URLComponents_Dev url_components;
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetDocumentURL(
+ API_ID_PPB_INSTANCE, instance, &url_components, &result));
+ if (components)
+ *components = url_components;
+ return result.Return(dispatcher());
+}
+
+#if !defined(OS_NACL)
+PP_Var PPB_Instance_Proxy::ResolveRelativeToDocument(
+ PP_Instance instance,
+ PP_Var relative,
+ PP_URLComponents_Dev* components) {
+ ReceiveSerializedVarReturnValue result;
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_ResolveRelativeToDocument(
+ API_ID_PPB_INSTANCE, instance,
+ SerializedVarSendInput(dispatcher(), relative),
+ &result));
+ return PPB_URLUtil_Shared::ConvertComponentsAndReturnURL(
+ result.Return(dispatcher()),
+ components);
+}
+
+PP_Bool PPB_Instance_Proxy::DocumentCanRequest(PP_Instance instance,
+ PP_Var url) {
+ PP_Bool result = PP_FALSE;
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_DocumentCanRequest(
+ API_ID_PPB_INSTANCE, instance,
+ SerializedVarSendInput(dispatcher(), url),
+ &result));
+ return result;
+}
+
+PP_Bool PPB_Instance_Proxy::DocumentCanAccessDocument(PP_Instance instance,
+ PP_Instance target) {
+ PP_Bool result = PP_FALSE;
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_DocumentCanAccessDocument(
+ API_ID_PPB_INSTANCE, instance, target, &result));
+ return result;
+}
+
+PP_Var PPB_Instance_Proxy::GetPluginInstanceURL(
+ PP_Instance instance,
+ PP_URLComponents_Dev* components) {
+ ReceiveSerializedVarReturnValue result;
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetPluginInstanceURL(
+ API_ID_PPB_INSTANCE, instance, &result));
+ return PPB_URLUtil_Shared::ConvertComponentsAndReturnURL(
+ result.Return(dispatcher()),
+ components);
+}
+
+void PPB_Instance_Proxy::NeedKey(PP_Instance instance,
+ PP_Var key_system,
+ PP_Var session_id,
+ PP_Var init_data) {
+ dispatcher()->Send(
+ new PpapiHostMsg_PPBInstance_NeedKey(
+ API_ID_PPB_INSTANCE,
+ instance,
+ SerializedVarSendInput(dispatcher(), key_system),
+ SerializedVarSendInput(dispatcher(), session_id),
+ SerializedVarSendInput(dispatcher(), init_data)));
+}
+
+void PPB_Instance_Proxy::KeyAdded(PP_Instance instance,
+ PP_Var key_system,
+ PP_Var session_id) {
+ dispatcher()->Send(
+ new PpapiHostMsg_PPBInstance_KeyAdded(
+ API_ID_PPB_INSTANCE,
+ instance,
+ SerializedVarSendInput(dispatcher(), key_system),
+ SerializedVarSendInput(dispatcher(), session_id)));
+}
+
+void PPB_Instance_Proxy::KeyMessage(PP_Instance instance,
+ PP_Var key_system,
+ PP_Var session_id,
+ PP_Var message,
+ PP_Var default_url) {
+ dispatcher()->Send(
+ new PpapiHostMsg_PPBInstance_KeyMessage(
+ API_ID_PPB_INSTANCE,
+ instance,
+ SerializedVarSendInput(dispatcher(), key_system),
+ SerializedVarSendInput(dispatcher(), session_id),
+ SerializedVarSendInput(dispatcher(), message),
+ SerializedVarSendInput(dispatcher(), default_url)));
+}
+
+void PPB_Instance_Proxy::KeyError(PP_Instance instance,
+ PP_Var key_system,
+ PP_Var session_id,
+ int32_t media_error,
+ int32_t system_code) {
+ dispatcher()->Send(
+ new PpapiHostMsg_PPBInstance_KeyError(
+ API_ID_PPB_INSTANCE,
+ instance,
+ SerializedVarSendInput(dispatcher(), key_system),
+ SerializedVarSendInput(dispatcher(), session_id),
+ media_error,
+ system_code));
+}
+
+void PPB_Instance_Proxy::DeliverBlock(PP_Instance instance,
+ PP_Resource decrypted_block,
+ const PP_DecryptedBlockInfo* block_info) {
+ PP_Resource decrypted_block_host_resource = 0;
+
+ if (decrypted_block) {
+ Resource* object =
+ PpapiGlobals::Get()->GetResourceTracker()->GetResource(decrypted_block);
+ if (!object || object->pp_instance() != instance) {
+ NOTREACHED();
+ return;
+ }
+ decrypted_block_host_resource = object->host_resource().host_resource();
+ }
+
+ std::string serialized_block_info;
+ if (!SerializeBlockInfo(*block_info, &serialized_block_info)) {
+ NOTREACHED();
+ return;
+ }
+
+ dispatcher()->Send(
+ new PpapiHostMsg_PPBInstance_DeliverBlock(API_ID_PPB_INSTANCE,
+ instance,
+ decrypted_block_host_resource,
+ serialized_block_info));
+}
+
+void PPB_Instance_Proxy::DecoderInitializeDone(
+ PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id,
+ PP_Bool success) {
+ dispatcher()->Send(
+ new PpapiHostMsg_PPBInstance_DecoderInitializeDone(
+ API_ID_PPB_INSTANCE,
+ instance,
+ decoder_type,
+ request_id,
+ success));
+}
+
+void PPB_Instance_Proxy::DecoderDeinitializeDone(
+ PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id) {
+ dispatcher()->Send(
+ new PpapiHostMsg_PPBInstance_DecoderDeinitializeDone(
+ API_ID_PPB_INSTANCE,
+ instance,
+ decoder_type,
+ request_id));
+}
+
+void PPB_Instance_Proxy::DecoderResetDone(PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id) {
+ dispatcher()->Send(
+ new PpapiHostMsg_PPBInstance_DecoderResetDone(
+ API_ID_PPB_INSTANCE,
+ instance,
+ decoder_type,
+ request_id));
+}
+
+void PPB_Instance_Proxy::DeliverFrame(PP_Instance instance,
+ PP_Resource decrypted_frame,
+ const PP_DecryptedFrameInfo* frame_info) {
+ PP_Resource host_resource = 0;
+ if (decrypted_frame != 0) {
+ ResourceTracker* tracker = PpapiGlobals::Get()->GetResourceTracker();
+ Resource* object = tracker->GetResource(decrypted_frame);
+
+ if (!object || object->pp_instance() != instance) {
+ NOTREACHED();
+ return;
+ }
+
+ host_resource = object->host_resource().host_resource();
+ }
+
+ std::string serialized_frame_info;
+ if (!SerializeBlockInfo(*frame_info, &serialized_frame_info)) {
+ NOTREACHED();
+ return;
+ }
+
+ dispatcher()->Send(
+ new PpapiHostMsg_PPBInstance_DeliverFrame(API_ID_PPB_INSTANCE,
+ instance,
+ host_resource,
+ serialized_frame_info));
+}
+
+void PPB_Instance_Proxy::DeliverSamples(
+ PP_Instance instance,
+ PP_Resource decrypted_samples,
+ const PP_DecryptedBlockInfo* block_info) {
+ PP_Resource host_resource = 0;
+ if (decrypted_samples != 0) {
+ ResourceTracker* tracker = PpapiGlobals::Get()->GetResourceTracker();
+ Resource* object = tracker->GetResource(decrypted_samples);
+
+ if (!object || object->pp_instance() != instance) {
+ NOTREACHED();
+ return;
+ }
+
+ host_resource = object->host_resource().host_resource();
+ }
+
+ std::string serialized_block_info;
+ if (!SerializeBlockInfo(*block_info, &serialized_block_info)) {
+ NOTREACHED();
+ return;
+ }
+
+ dispatcher()->Send(
+ new PpapiHostMsg_PPBInstance_DeliverSamples(API_ID_PPB_INSTANCE,
+ instance,
+ host_resource,
+ serialized_block_info));
+}
+#endif // !defined(OS_NACL)
+
+void PPB_Instance_Proxy::PostMessage(PP_Instance instance,
+ PP_Var message) {
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_PostMessage(
+ API_ID_PPB_INSTANCE,
+ instance, SerializedVarSendInputShmem(dispatcher(), message,
+ instance)));
+}
+
+PP_Bool PPB_Instance_Proxy::SetCursor(PP_Instance instance,
+ PP_MouseCursor_Type type,
+ PP_Resource image,
+ const PP_Point* hot_spot) {
+ // Some of these parameters are important for security. This check is in the
+ // plugin process just for the convenience of the caller (since we don't
+ // bother returning errors from the other process with a sync message). The
+ // parameters will be validated again in the renderer.
+ if (!ValidateSetCursorParams(type, image, hot_spot))
+ return PP_FALSE;
+
+ HostResource image_host_resource;
+ if (image) {
+ Resource* cursor_image =
+ PpapiGlobals::Get()->GetResourceTracker()->GetResource(image);
+ if (!cursor_image || cursor_image->pp_instance() != instance)
+ return PP_FALSE;
+ image_host_resource = cursor_image->host_resource();
+ }
+
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_SetCursor(
+ API_ID_PPB_INSTANCE, instance, static_cast<int32_t>(type),
+ image_host_resource, hot_spot ? *hot_spot : PP_MakePoint(0, 0)));
+ return PP_TRUE;
+}
+
+int32_t PPB_Instance_Proxy::LockMouse(PP_Instance instance,
+ scoped_refptr<TrackedCallback> callback) {
+ // Save the mouse callback on the instance data.
+ InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
+ GetInstanceData(instance);
+ if (!data)
+ return PP_ERROR_BADARGUMENT;
+ if (TrackedCallback::IsPending(data->mouse_lock_callback))
+ return PP_ERROR_INPROGRESS; // Already have a pending callback.
+ data->mouse_lock_callback = callback;
+
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_LockMouse(
+ API_ID_PPB_INSTANCE, instance));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void PPB_Instance_Proxy::UnlockMouse(PP_Instance instance) {
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_UnlockMouse(
+ API_ID_PPB_INSTANCE, instance));
+}
+
+void PPB_Instance_Proxy::SetTextInputType(PP_Instance instance,
+ PP_TextInput_Type type) {
+ CancelAnyPendingRequestSurroundingText(instance);
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_SetTextInputType(
+ API_ID_PPB_INSTANCE, instance, type));
+}
+
+void PPB_Instance_Proxy::UpdateCaretPosition(PP_Instance instance,
+ const PP_Rect& caret,
+ const PP_Rect& bounding_box) {
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_UpdateCaretPosition(
+ API_ID_PPB_INSTANCE, instance, caret, bounding_box));
+}
+
+void PPB_Instance_Proxy::CancelCompositionText(PP_Instance instance) {
+ CancelAnyPendingRequestSurroundingText(instance);
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_CancelCompositionText(
+ API_ID_PPB_INSTANCE, instance));
+}
+
+void PPB_Instance_Proxy::SelectionChanged(PP_Instance instance) {
+ // The "right" way to do this is to send the message to the host. However,
+ // all it will do is call RequestSurroundingText with a hardcoded number of
+ // characters in response, which is an entire IPC round-trip.
+ //
+ // We can avoid this round-trip by just implementing the
+ // RequestSurroundingText logic in the plugin process. If the logic in the
+ // host becomes more complex (like a more adaptive number of characters),
+ // we'll need to reevanuate whether we want to do the round trip instead.
+ //
+ // Be careful to post a task to avoid reentering the plugin.
+
+ InstanceData* data =
+ static_cast<PluginDispatcher*>(dispatcher())->GetInstanceData(instance);
+ if (!data)
+ return;
+ data->should_do_request_surrounding_text = true;
+
+ if (!data->is_request_surrounding_text_pending) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ RunWhileLocked(base::Bind(&RequestSurroundingText, instance)));
+ data->is_request_surrounding_text_pending = true;
+ }
+}
+
+void PPB_Instance_Proxy::UpdateSurroundingText(PP_Instance instance,
+ const char* text,
+ uint32_t caret,
+ uint32_t anchor) {
+ dispatcher()->Send(new PpapiHostMsg_PPBInstance_UpdateSurroundingText(
+ API_ID_PPB_INSTANCE, instance, text, caret, anchor));
+}
+
+#if !defined(OS_NACL)
+void PPB_Instance_Proxy::OnHostMsgGetWindowObject(
+ PP_Instance instance,
+ SerializedVarReturnValue result) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
+ return;
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded())
+ result.Return(dispatcher(), enter.functions()->GetWindowObject(instance));
+}
+
+void PPB_Instance_Proxy::OnHostMsgGetOwnerElementObject(
+ PP_Instance instance,
+ SerializedVarReturnValue result) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
+ return;
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded()) {
+ result.Return(dispatcher(),
+ enter.functions()->GetOwnerElementObject(instance));
+ }
+}
+
+void PPB_Instance_Proxy::OnHostMsgBindGraphics(PP_Instance instance,
+ PP_Resource device) {
+ // Note that we ignroe the return value here. Otherwise, this would need to
+ // be a slow sync call, and the plugin side of the proxy will have already
+ // validated the resources, so we shouldn't see errors here that weren't
+ // already caught.
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded())
+ enter.functions()->BindGraphics(instance, device);
+}
+
+void PPB_Instance_Proxy::OnHostMsgGetAudioHardwareOutputSampleRate(
+ PP_Instance instance, uint32_t* result) {
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded())
+ *result = enter.functions()->GetAudioHardwareOutputSampleRate(instance);
+}
+
+void PPB_Instance_Proxy::OnHostMsgGetAudioHardwareOutputBufferSize(
+ PP_Instance instance, uint32_t* result) {
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded())
+ *result = enter.functions()->GetAudioHardwareOutputBufferSize(instance);
+}
+
+void PPB_Instance_Proxy::OnHostMsgIsFullFrame(PP_Instance instance,
+ PP_Bool* result) {
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded())
+ *result = enter.functions()->IsFullFrame(instance);
+}
+
+void PPB_Instance_Proxy::OnHostMsgExecuteScript(
+ PP_Instance instance,
+ SerializedVarReceiveInput script,
+ SerializedVarOutParam out_exception,
+ SerializedVarReturnValue result) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
+ return;
+ EnterInstanceNoLock enter(instance);
+ 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::OnHostMsgGetDefaultCharSet(
+ PP_Instance instance,
+ SerializedVarReturnValue result) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
+ return;
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded())
+ result.Return(dispatcher(), enter.functions()->GetDefaultCharSet(instance));
+}
+
+void PPB_Instance_Proxy::OnHostMsgSetFullscreen(PP_Instance instance,
+ PP_Bool fullscreen,
+ PP_Bool* result) {
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded())
+ *result = enter.functions()->SetFullscreen(instance, fullscreen);
+}
+
+
+void PPB_Instance_Proxy::OnHostMsgGetScreenSize(PP_Instance instance,
+ PP_Bool* result,
+ PP_Size* size) {
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded())
+ *result = enter.functions()->GetScreenSize(instance, size);
+}
+
+void PPB_Instance_Proxy::OnHostMsgRequestInputEvents(PP_Instance instance,
+ bool is_filtering,
+ uint32_t event_classes) {
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded()) {
+ if (is_filtering)
+ enter.functions()->RequestFilteringInputEvents(instance, event_classes);
+ else
+ enter.functions()->RequestInputEvents(instance, event_classes);
+ }
+}
+
+void PPB_Instance_Proxy::OnHostMsgClearInputEvents(PP_Instance instance,
+ uint32_t event_classes) {
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded())
+ enter.functions()->ClearInputEventRequest(instance, event_classes);
+}
+
+void PPB_Instance_Proxy::OnHostMsgPostMessage(
+ PP_Instance instance,
+ SerializedVarReceiveInput message) {
+ EnterInstanceNoLock enter(instance);
+ if (!message.is_valid_var()) {
+ PpapiGlobals::Get()->LogWithSource(
+ instance, PP_LOGLEVEL_ERROR, std::string(), kSerializationError);
+ return;
+ }
+
+ if (enter.succeeded())
+ enter.functions()->PostMessage(instance,
+ message.GetForInstance(dispatcher(),
+ instance));
+}
+
+void PPB_Instance_Proxy::OnHostMsgLockMouse(PP_Instance instance) {
+ // Need to be careful to always issue the callback.
+ pp::CompletionCallback cb = callback_factory_.NewCallback(
+ &PPB_Instance_Proxy::MouseLockCompleteInHost, instance);
+
+ EnterInstanceNoLock enter(instance, cb.pp_completion_callback());
+ if (enter.succeeded())
+ enter.SetResult(enter.functions()->LockMouse(instance, enter.callback()));
+}
+
+void PPB_Instance_Proxy::OnHostMsgUnlockMouse(PP_Instance instance) {
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded())
+ enter.functions()->UnlockMouse(instance);
+}
+
+void PPB_Instance_Proxy::OnHostMsgGetDocumentURL(
+ PP_Instance instance,
+ PP_URLComponents_Dev* components,
+ SerializedVarReturnValue result) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
+ return;
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded()) {
+ PP_Var document_url = enter.functions()->GetDocumentURL(instance,
+ components);
+ result.Return(dispatcher(), document_url);
+ }
+}
+
+void PPB_Instance_Proxy::OnHostMsgResolveRelativeToDocument(
+ PP_Instance instance,
+ SerializedVarReceiveInput relative,
+ SerializedVarReturnValue result) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
+ return;
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded()) {
+ result.Return(dispatcher(),
+ enter.functions()->ResolveRelativeToDocument(
+ instance, relative.Get(dispatcher()), NULL));
+ }
+}
+
+void PPB_Instance_Proxy::OnHostMsgDocumentCanRequest(
+ PP_Instance instance,
+ SerializedVarReceiveInput url,
+ PP_Bool* result) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
+ return;
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded()) {
+ *result = enter.functions()->DocumentCanRequest(instance,
+ url.Get(dispatcher()));
+ }
+}
+
+void PPB_Instance_Proxy::OnHostMsgDocumentCanAccessDocument(PP_Instance active,
+ PP_Instance target,
+ PP_Bool* result) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
+ return;
+ EnterInstanceNoLock enter(active);
+ if (enter.succeeded())
+ *result = enter.functions()->DocumentCanAccessDocument(active, target);
+}
+
+void PPB_Instance_Proxy::OnHostMsgGetPluginInstanceURL(
+ PP_Instance instance,
+ SerializedVarReturnValue result) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
+ return;
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded()) {
+ result.Return(dispatcher(),
+ enter.functions()->GetPluginInstanceURL(instance, NULL));
+ }
+}
+
+void PPB_Instance_Proxy::OnHostMsgNeedKey(PP_Instance instance,
+ SerializedVarReceiveInput key_system,
+ SerializedVarReceiveInput session_id,
+ SerializedVarReceiveInput init_data) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
+ return;
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded()) {
+ enter.functions()->NeedKey(instance,
+ key_system.Get(dispatcher()),
+ session_id.Get(dispatcher()),
+ init_data.Get(dispatcher()));
+ }
+}
+
+void PPB_Instance_Proxy::OnHostMsgKeyAdded(
+ PP_Instance instance,
+ SerializedVarReceiveInput key_system,
+ SerializedVarReceiveInput session_id) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
+ return;
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded()) {
+ enter.functions()->KeyAdded(instance,
+ key_system.Get(dispatcher()),
+ session_id.Get(dispatcher()));
+ }
+}
+
+void PPB_Instance_Proxy::OnHostMsgKeyMessage(
+ PP_Instance instance,
+ SerializedVarReceiveInput key_system,
+ SerializedVarReceiveInput session_id,
+ SerializedVarReceiveInput message,
+ SerializedVarReceiveInput default_url) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
+ return;
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded()) {
+ enter.functions()->KeyMessage(instance,
+ key_system.Get(dispatcher()),
+ session_id.Get(dispatcher()),
+ message.Get(dispatcher()),
+ default_url.Get(dispatcher()));
+ }
+}
+
+void PPB_Instance_Proxy::OnHostMsgKeyError(
+ PP_Instance instance,
+ SerializedVarReceiveInput key_system,
+ SerializedVarReceiveInput session_id,
+ int32_t media_error,
+ int32_t system_error) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
+ return;
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded()) {
+ enter.functions()->KeyError(instance,
+ key_system.Get(dispatcher()),
+ session_id.Get(dispatcher()),
+ media_error,
+ system_error);
+ }
+}
+
+void PPB_Instance_Proxy::OnHostMsgDeliverBlock(
+ PP_Instance instance,
+ PP_Resource decrypted_block,
+ const std::string& serialized_block_info) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
+ return;
+ PP_DecryptedBlockInfo block_info;
+ if (!DeserializeBlockInfo(serialized_block_info, &block_info))
+ return;
+
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded())
+ enter.functions()->DeliverBlock(instance, decrypted_block, &block_info);
+}
+
+void PPB_Instance_Proxy::OnHostMsgDecoderInitializeDone(
+ PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id,
+ PP_Bool success) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
+ return;
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded()) {
+ enter.functions()->DecoderInitializeDone(instance,
+ decoder_type,
+ request_id,
+ success);
+ }
+}
+
+void PPB_Instance_Proxy::OnHostMsgDecoderDeinitializeDone(
+ PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
+ return;
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded())
+ enter.functions()->DecoderDeinitializeDone(instance,
+ decoder_type,
+ request_id);
+}
+
+void PPB_Instance_Proxy::OnHostMsgDecoderResetDone(
+ PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
+ return;
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded())
+ enter.functions()->DecoderResetDone(instance, decoder_type, request_id);
+}
+
+void PPB_Instance_Proxy::OnHostMsgDeliverFrame(
+ PP_Instance instance,
+ PP_Resource decrypted_frame,
+ const std::string& serialized_frame_info) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
+ return;
+ PP_DecryptedFrameInfo frame_info;
+ if (!DeserializeBlockInfo(serialized_frame_info, &frame_info))
+ return;
+
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded())
+ enter.functions()->DeliverFrame(instance, decrypted_frame, &frame_info);
+}
+
+void PPB_Instance_Proxy::OnHostMsgDeliverSamples(
+ PP_Instance instance,
+ PP_Resource audio_frames,
+ const std::string& serialized_block_info) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
+ return;
+ PP_DecryptedBlockInfo block_info;
+ if (!DeserializeBlockInfo(serialized_block_info, &block_info))
+ return;
+
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded())
+ enter.functions()->DeliverSamples(instance, audio_frames, &block_info);
+}
+
+void PPB_Instance_Proxy::OnHostMsgSetCursor(
+ PP_Instance instance,
+ int32_t type,
+ const ppapi::HostResource& custom_image,
+ const PP_Point& hot_spot) {
+ // This API serves PPB_CursorControl_Dev and PPB_MouseCursor, so is public.
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded()) {
+ enter.functions()->SetCursor(
+ instance, static_cast<PP_MouseCursor_Type>(type),
+ custom_image.host_resource(), &hot_spot);
+ }
+}
+
+void PPB_Instance_Proxy::OnHostMsgSetTextInputType(PP_Instance instance,
+ PP_TextInput_Type type) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
+ return;
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded())
+ enter.functions()->SetTextInputType(instance, type);
+}
+
+void PPB_Instance_Proxy::OnHostMsgUpdateCaretPosition(
+ PP_Instance instance,
+ const PP_Rect& caret,
+ const PP_Rect& bounding_box) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
+ return;
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded())
+ enter.functions()->UpdateCaretPosition(instance, caret, bounding_box);
+}
+
+void PPB_Instance_Proxy::OnHostMsgCancelCompositionText(PP_Instance instance) {
+ EnterInstanceNoLock enter(instance);
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
+ return;
+ if (enter.succeeded())
+ enter.functions()->CancelCompositionText(instance);
+}
+
+void PPB_Instance_Proxy::OnHostMsgUpdateSurroundingText(
+ PP_Instance instance,
+ const std::string& text,
+ uint32_t caret,
+ uint32_t anchor) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
+ return;
+ EnterInstanceNoLock enter(instance);
+ if (enter.succeeded()) {
+ enter.functions()->UpdateSurroundingText(instance, text.c_str(), caret,
+ anchor);
+ }
+}
+#endif // !defined(OS_NACL)
+
+void PPB_Instance_Proxy::OnPluginMsgMouseLockComplete(PP_Instance instance,
+ int32_t result) {
+ if (!dispatcher()->IsPlugin())
+ return;
+
+ // Save the mouse callback on the instance data.
+ InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
+ GetInstanceData(instance);
+ if (!data)
+ return; // Instance was probably deleted.
+ if (!TrackedCallback::IsPending(data->mouse_lock_callback)) {
+ NOTREACHED();
+ return;
+ }
+ data->mouse_lock_callback->Run(result);
+}
+
+#if !defined(OS_NACL)
+void PPB_Instance_Proxy::MouseLockCompleteInHost(int32_t result,
+ PP_Instance instance) {
+ dispatcher()->Send(new PpapiMsg_PPBInstance_MouseLockComplete(
+ API_ID_PPB_INSTANCE, instance, result));
+}
+#endif // !defined(OS_NACL)
+
+void PPB_Instance_Proxy::CancelAnyPendingRequestSurroundingText(
+ PP_Instance instance) {
+ InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
+ GetInstanceData(instance);
+ if (!data)
+ return; // Instance was probably deleted.
+ data->should_do_request_surrounding_text = false;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppb_instance_proxy.h b/chromium/ppapi/proxy/ppb_instance_proxy.h
new file mode 100644
index 00000000000..6df4f8d9eab
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_instance_proxy.h
@@ -0,0 +1,276 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPB_INSTANCE_PROXY_H_
+#define PPAPI_PROXY_PPB_INSTANCE_PROXY_H_
+
+#include <string>
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/proxy_completion_callback_factory.h"
+#include "ppapi/shared_impl/host_resource.h"
+#include "ppapi/shared_impl/ppb_instance_shared.h"
+#include "ppapi/shared_impl/singleton_resource_id.h"
+#include "ppapi/thunk/ppb_instance_api.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+// Windows headers interfere with this file.
+#ifdef PostMessage
+#undef PostMessage
+#endif
+
+struct PP_DecryptedBlockInfo;
+struct PP_DecryptedFrameInfo;
+
+namespace ppapi {
+namespace proxy {
+
+class SerializedVarReceiveInput;
+class SerializedVarOutParam;
+class SerializedVarReturnValue;
+
+class PPB_Instance_Proxy : public InterfaceProxy,
+ public PPB_Instance_Shared {
+ public:
+ PPB_Instance_Proxy(Dispatcher* dispatcher);
+ virtual ~PPB_Instance_Proxy();
+
+ static const Info* GetInfoPrivate();
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ // PPB_Instance_API implementation.
+ virtual PP_Bool BindGraphics(PP_Instance instance,
+ PP_Resource device) OVERRIDE;
+ virtual PP_Bool IsFullFrame(PP_Instance instance) OVERRIDE;
+ virtual const ViewData* GetViewData(PP_Instance instance) OVERRIDE;
+ virtual PP_Bool FlashIsFullscreen(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 uint32_t GetAudioHardwareOutputSampleRate(PP_Instance instance)
+ OVERRIDE;
+ virtual uint32_t GetAudioHardwareOutputBufferSize(PP_Instance instance)
+ OVERRIDE;
+ virtual PP_Var GetDefaultCharSet(PP_Instance instance) OVERRIDE;
+ virtual void NumberOfFindResultsChanged(PP_Instance instance,
+ int32_t total,
+ PP_Bool final_result) OVERRIDE;
+ virtual void SelectedFindResultChanged(PP_Instance instance,
+ int32_t index) 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 Resource* GetSingletonResource(PP_Instance instance,
+ SingletonResourceID id) 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;
+ virtual PP_Bool SetCursor(PP_Instance instance,
+ PP_MouseCursor_Type type,
+ PP_Resource image,
+ const PP_Point* hot_spot) OVERRIDE;
+ virtual int32_t LockMouse(PP_Instance instance,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual void UnlockMouse(PP_Instance instance) OVERRIDE;
+ virtual void SetTextInputType(PP_Instance instance,
+ PP_TextInput_Type type) OVERRIDE;
+ virtual void UpdateCaretPosition(PP_Instance instance,
+ const PP_Rect& caret,
+ const PP_Rect& bounding_box) OVERRIDE;
+ virtual void CancelCompositionText(PP_Instance instance) OVERRIDE;
+ virtual void SelectionChanged(PP_Instance instance) OVERRIDE;
+ virtual void UpdateSurroundingText(PP_Instance instance,
+ const char* text,
+ uint32_t caret,
+ uint32_t anchor) OVERRIDE;
+ virtual PP_Var GetDocumentURL(PP_Instance instance,
+ PP_URLComponents_Dev* components) OVERRIDE;
+#if !defined(OS_NACL)
+ virtual PP_Var ResolveRelativeToDocument(
+ PP_Instance instance,
+ PP_Var relative,
+ PP_URLComponents_Dev* components) OVERRIDE;
+ virtual PP_Bool DocumentCanRequest(PP_Instance instance, PP_Var url) OVERRIDE;
+ virtual PP_Bool DocumentCanAccessDocument(PP_Instance instance,
+ PP_Instance target) OVERRIDE;
+ virtual PP_Var GetPluginInstanceURL(
+ PP_Instance instance,
+ PP_URLComponents_Dev* components) OVERRIDE;
+ virtual void NeedKey(PP_Instance instance,
+ PP_Var key_system,
+ PP_Var session_id,
+ PP_Var init_data) OVERRIDE;
+ virtual void KeyAdded(PP_Instance instance,
+ PP_Var key_system,
+ PP_Var session_id) OVERRIDE;
+ virtual void KeyMessage(PP_Instance instance,
+ PP_Var key_system,
+ PP_Var session_id,
+ PP_Var message,
+ PP_Var default_url) OVERRIDE;
+ virtual void KeyError(PP_Instance instance,
+ PP_Var key_system,
+ PP_Var session_id,
+ int32_t media_error,
+ int32_t system_code) OVERRIDE;
+ virtual void DeliverBlock(PP_Instance instance,
+ PP_Resource decrypted_block,
+ const PP_DecryptedBlockInfo* block_info) OVERRIDE;
+ virtual void DecoderInitializeDone(PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id,
+ PP_Bool success) OVERRIDE;
+ virtual void DecoderDeinitializeDone(PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id) OVERRIDE;
+ virtual void DecoderResetDone(PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id) OVERRIDE;
+ virtual void DeliverFrame(PP_Instance instance,
+ PP_Resource decrypted_frame,
+ const PP_DecryptedFrameInfo* frame_info) OVERRIDE;
+ virtual void DeliverSamples(PP_Instance instance,
+ PP_Resource audio_frames,
+ const PP_DecryptedBlockInfo* block_info) OVERRIDE;
+#endif // !defined(OS_NACL)
+
+ static const ApiID kApiID = API_ID_PPB_INSTANCE;
+
+ private:
+ // Plugin -> Host message handlers.
+ void OnHostMsgGetWindowObject(PP_Instance instance,
+ SerializedVarReturnValue result);
+ void OnHostMsgGetOwnerElementObject(PP_Instance instance,
+ SerializedVarReturnValue result);
+ void OnHostMsgBindGraphics(PP_Instance instance,
+ PP_Resource device);
+ void OnHostMsgIsFullFrame(PP_Instance instance, PP_Bool* result);
+ void OnHostMsgExecuteScript(PP_Instance instance,
+ SerializedVarReceiveInput script,
+ SerializedVarOutParam out_exception,
+ SerializedVarReturnValue result);
+ void OnHostMsgGetAudioHardwareOutputSampleRate(PP_Instance instance,
+ uint32_t *result);
+ void OnHostMsgGetAudioHardwareOutputBufferSize(PP_Instance instance,
+ uint32_t *result);
+ void OnHostMsgGetDefaultCharSet(PP_Instance instance,
+ SerializedVarReturnValue result);
+ void OnHostMsgSetFullscreen(PP_Instance instance,
+ PP_Bool fullscreen,
+ PP_Bool* result);
+ void OnHostMsgGetScreenSize(PP_Instance instance,
+ PP_Bool* result,
+ PP_Size* size);
+ void OnHostMsgRequestInputEvents(PP_Instance instance,
+ bool is_filtering,
+ uint32_t event_classes);
+ void OnHostMsgClearInputEvents(PP_Instance instance,
+ uint32_t event_classes);
+ void OnHostMsgPostMessage(PP_Instance instance,
+ SerializedVarReceiveInput message);
+ void OnHostMsgLockMouse(PP_Instance instance);
+ void OnHostMsgUnlockMouse(PP_Instance instance);
+ void OnHostMsgSetCursor(PP_Instance instance,
+ int32_t type,
+ const ppapi::HostResource& custom_image,
+ const PP_Point& hot_spot);
+ void OnHostMsgSetTextInputType(PP_Instance instance, PP_TextInput_Type type);
+ void OnHostMsgUpdateCaretPosition(PP_Instance instance,
+ const PP_Rect& caret,
+ const PP_Rect& bounding_box);
+ void OnHostMsgCancelCompositionText(PP_Instance instance);
+ void OnHostMsgUpdateSurroundingText(
+ PP_Instance instance,
+ const std::string& text,
+ uint32_t caret,
+ uint32_t anchor);
+ void OnHostMsgGetDocumentURL(PP_Instance instance,
+ PP_URLComponents_Dev* components,
+ SerializedVarReturnValue result);
+
+#if !defined(OS_NACL)
+ void OnHostMsgResolveRelativeToDocument(PP_Instance instance,
+ SerializedVarReceiveInput relative,
+ SerializedVarReturnValue result);
+ void OnHostMsgDocumentCanRequest(PP_Instance instance,
+ SerializedVarReceiveInput url,
+ PP_Bool* result);
+ void OnHostMsgDocumentCanAccessDocument(PP_Instance active,
+ PP_Instance target,
+ PP_Bool* result);
+ void OnHostMsgGetPluginInstanceURL(PP_Instance instance,
+ SerializedVarReturnValue result);
+ virtual void OnHostMsgNeedKey(PP_Instance instance,
+ SerializedVarReceiveInput key_system,
+ SerializedVarReceiveInput session_id,
+ SerializedVarReceiveInput init_data);
+ virtual void OnHostMsgKeyAdded(PP_Instance instance,
+ SerializedVarReceiveInput key_system,
+ SerializedVarReceiveInput session_id);
+ virtual void OnHostMsgKeyMessage(PP_Instance instance,
+ SerializedVarReceiveInput key_system,
+ SerializedVarReceiveInput session_id,
+ SerializedVarReceiveInput message,
+ SerializedVarReceiveInput default_url);
+ virtual void OnHostMsgKeyError(PP_Instance instance,
+ SerializedVarReceiveInput key_system,
+ SerializedVarReceiveInput session_id,
+ int32_t media_error,
+ int32_t system_code);
+ virtual void OnHostMsgDecoderInitializeDone(
+ PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id,
+ PP_Bool success);
+ virtual void OnHostMsgDecoderDeinitializeDone(
+ PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id);
+ virtual void OnHostMsgDecoderResetDone(PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id);
+ virtual void OnHostMsgDeliverBlock(PP_Instance instance,
+ PP_Resource decrypted_block,
+ const std::string& serialized_block_info);
+ virtual void OnHostMsgDeliverFrame(PP_Instance instance,
+ PP_Resource decrypted_frame,
+ const std::string& serialized_block_info);
+ virtual void OnHostMsgDeliverSamples(
+ PP_Instance instance,
+ PP_Resource audio_frames,
+ const std::string& serialized_block_info);
+#endif // !defined(OS_NACL)
+
+ // Host -> Plugin message handlers.
+ void OnPluginMsgMouseLockComplete(PP_Instance instance, int32_t result);
+
+ void MouseLockCompleteInHost(int32_t result, PP_Instance instance);
+
+ // Other helpers.
+ void CancelAnyPendingRequestSurroundingText(PP_Instance instance);
+
+ ProxyCompletionCallbackFactory<PPB_Instance_Proxy> callback_factory_;
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPB_INSTANCE_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppb_message_loop_proxy.cc b/chromium/ppapi/proxy/ppb_message_loop_proxy.cc
new file mode 100644
index 00000000000..7e2cdfa6559
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_message_loop_proxy.cc
@@ -0,0 +1,274 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppb_message_loop_proxy.h"
+
+#include <vector>
+
+#include "base/bind.h"
+#include "base/compiler_specific.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_message_loop.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/thunk/enter.h"
+
+using ppapi::thunk::PPB_MessageLoop_API;
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+typedef thunk::EnterResource<PPB_MessageLoop_API> EnterMessageLoop;
+}
+
+MessageLoopResource::MessageLoopResource(PP_Instance instance)
+ : MessageLoopShared(instance),
+ nested_invocations_(0),
+ destroyed_(false),
+ should_destroy_(false),
+ is_main_thread_loop_(false) {
+}
+
+MessageLoopResource::MessageLoopResource(ForMainThread for_main_thread)
+ : MessageLoopShared(for_main_thread),
+ nested_invocations_(0),
+ destroyed_(false),
+ should_destroy_(false),
+ is_main_thread_loop_(true) {
+ // We attach the main thread immediately. We can't use AttachToCurrentThread,
+ // because the MessageLoop already exists.
+
+ // This must be called only once, so the slot must be empty.
+ CHECK(!PluginGlobals::Get()->msg_loop_slot());
+ // We don't add a reference for TLS here, so we don't release it. Instead,
+ // this loop is owned by PluginGlobals. Contrast with AttachToCurrentThread
+ // where we register ReleaseMessageLoop with TLS and call AddRef.
+ base::ThreadLocalStorage::Slot* slot = new base::ThreadLocalStorage::Slot();
+ PluginGlobals::Get()->set_msg_loop_slot(slot);
+
+ slot->Set(this);
+
+ loop_proxy_ = base::MessageLoopProxy::current();
+}
+
+
+MessageLoopResource::~MessageLoopResource() {
+}
+
+PPB_MessageLoop_API* MessageLoopResource::AsPPB_MessageLoop_API() {
+ return this;
+}
+
+int32_t MessageLoopResource::AttachToCurrentThread() {
+ if (is_main_thread_loop_)
+ return PP_ERROR_INPROGRESS;
+
+ PluginGlobals* globals = PluginGlobals::Get();
+
+ base::ThreadLocalStorage::Slot* slot = globals->msg_loop_slot();
+ if (!slot) {
+ slot = new base::ThreadLocalStorage::Slot(&ReleaseMessageLoop);
+ globals->set_msg_loop_slot(slot);
+ } else {
+ if (slot->Get())
+ return PP_ERROR_INPROGRESS;
+ }
+ // TODO(dmichael) check that the current thread can support a message loop.
+
+ // Take a ref to the MessageLoop on behalf of the TLS. Note that this is an
+ // internal ref and not a plugin ref so the plugin can't accidentally
+ // release it. This is released by ReleaseMessageLoop().
+ AddRef();
+ slot->Set(this);
+
+ loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_DEFAULT));
+ loop_proxy_ = base::MessageLoopProxy::current();
+
+ // Post all pending work to the message loop.
+ for (size_t i = 0; i < pending_tasks_.size(); i++) {
+ const TaskInfo& info = pending_tasks_[i];
+ PostClosure(info.from_here, info.closure, info.delay_ms);
+ }
+ pending_tasks_.clear();
+
+ return PP_OK;
+}
+
+int32_t MessageLoopResource::Run() {
+ if (!IsCurrent())
+ return PP_ERROR_WRONG_THREAD;
+ if (is_main_thread_loop_)
+ return PP_ERROR_INPROGRESS;
+
+ nested_invocations_++;
+ CallWhileUnlocked(
+ base::Bind(&base::MessageLoop::Run, base::Unretained(loop_.get())));
+ nested_invocations_--;
+
+ if (should_destroy_ && nested_invocations_ == 0) {
+ loop_proxy_ = NULL;
+ loop_.reset();
+ destroyed_ = true;
+ }
+ return PP_OK;
+}
+
+int32_t MessageLoopResource::PostWork(PP_CompletionCallback callback,
+ int64_t delay_ms) {
+ if (!callback.func)
+ return PP_ERROR_BADARGUMENT;
+ if (destroyed_)
+ return PP_ERROR_FAILED;
+ PostClosure(FROM_HERE,
+ base::Bind(callback.func, callback.user_data,
+ static_cast<int32_t>(PP_OK)),
+ delay_ms);
+ return PP_OK;
+}
+
+int32_t MessageLoopResource::PostQuit(PP_Bool should_destroy) {
+ if (is_main_thread_loop_)
+ return PP_ERROR_WRONG_THREAD;
+
+ if (PP_ToBool(should_destroy))
+ should_destroy_ = true;
+
+ if (IsCurrent() && nested_invocations_ > 0)
+ loop_->Quit();
+ else
+ PostClosure(FROM_HERE, base::MessageLoop::QuitClosure(), 0);
+ return PP_OK;
+}
+
+// static
+MessageLoopResource* MessageLoopResource::GetCurrent() {
+ PluginGlobals* globals = PluginGlobals::Get();
+ if (!globals->msg_loop_slot())
+ return NULL;
+ return reinterpret_cast<MessageLoopResource*>(
+ globals->msg_loop_slot()->Get());
+}
+
+void MessageLoopResource::DetachFromThread() {
+ // Note that the message loop must be destroyed on the thread it was created
+ // on.
+ loop_proxy_ = NULL;
+ loop_.reset();
+
+ // Cancel out the AddRef in AttachToCurrentThread().
+ Release();
+ // DANGER: may delete this.
+}
+
+bool MessageLoopResource::IsCurrent() const {
+ PluginGlobals* globals = PluginGlobals::Get();
+ if (!globals->msg_loop_slot())
+ return false; // Can't be current if there's nothing in the slot.
+ return static_cast<const void*>(globals->msg_loop_slot()->Get()) ==
+ static_cast<const void*>(this);
+}
+
+void MessageLoopResource::PostClosure(
+ const tracked_objects::Location& from_here,
+ const base::Closure& closure,
+ int64 delay_ms) {
+ if (loop_proxy_.get()) {
+ loop_proxy_->PostDelayedTask(
+ from_here, closure, base::TimeDelta::FromMilliseconds(delay_ms));
+ } else {
+ TaskInfo info;
+ info.from_here = FROM_HERE;
+ info.closure = closure;
+ info.delay_ms = delay_ms;
+ pending_tasks_.push_back(info);
+ }
+}
+
+// static
+void MessageLoopResource::ReleaseMessageLoop(void* value) {
+ static_cast<MessageLoopResource*>(value)->DetachFromThread();
+}
+
+// -----------------------------------------------------------------------------
+
+PP_Resource Create(PP_Instance instance) {
+ ProxyAutoLock lock;
+ // Validate the instance.
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+ return (new MessageLoopResource(instance))->GetReference();
+}
+
+PP_Resource GetForMainThread() {
+ ProxyAutoLock lock;
+ return PluginGlobals::Get()->loop_for_main_thread()->GetReference();
+}
+
+PP_Resource GetCurrent() {
+ ProxyAutoLock lock;
+ Resource* resource = MessageLoopResource::GetCurrent();
+ if (resource)
+ return resource->GetReference();
+ return 0;
+}
+
+int32_t AttachToCurrentThread(PP_Resource message_loop) {
+ EnterMessageLoop enter(message_loop, true);
+ if (enter.succeeded())
+ return enter.object()->AttachToCurrentThread();
+ return PP_ERROR_BADRESOURCE;
+}
+
+int32_t Run(PP_Resource message_loop) {
+ EnterMessageLoop enter(message_loop, true);
+ if (enter.succeeded())
+ return enter.object()->Run();
+ return PP_ERROR_BADRESOURCE;
+}
+
+int32_t PostWork(PP_Resource message_loop,
+ PP_CompletionCallback callback,
+ int64_t delay_ms) {
+ EnterMessageLoop enter(message_loop, true);
+ if (enter.succeeded())
+ return enter.object()->PostWork(callback, delay_ms);
+ return PP_ERROR_BADRESOURCE;
+}
+
+int32_t PostQuit(PP_Resource message_loop, PP_Bool should_destroy) {
+ EnterMessageLoop enter(message_loop, true);
+ if (enter.succeeded())
+ return enter.object()->PostQuit(should_destroy);
+ return PP_ERROR_BADRESOURCE;
+}
+
+const PPB_MessageLoop_1_0 ppb_message_loop_interface = {
+ &Create,
+ &GetForMainThread,
+ &GetCurrent,
+ &AttachToCurrentThread,
+ &Run,
+ &PostWork,
+ &PostQuit
+};
+
+PPB_MessageLoop_Proxy::PPB_MessageLoop_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher) {
+}
+
+PPB_MessageLoop_Proxy::~PPB_MessageLoop_Proxy() {
+}
+
+// static
+const PPB_MessageLoop_1_0* PPB_MessageLoop_Proxy::GetInterface() {
+ return &ppb_message_loop_interface;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppb_message_loop_proxy.h b/chromium/ppapi/proxy/ppb_message_loop_proxy.h
new file mode 100644
index 00000000000..4e3a9332286
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_message_loop_proxy.h
@@ -0,0 +1,111 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPB_MESSAGE_LOOP_PROXY_H_
+#define PPAPI_PROXY_PPB_MESSAGE_LOOP_PROXY_H_
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/ppb_message_loop_shared.h"
+#include "ppapi/thunk/ppb_message_loop_api.h"
+
+struct PPB_MessageLoop_1_0;
+
+namespace ppapi {
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT MessageLoopResource : public MessageLoopShared {
+ public:
+ explicit MessageLoopResource(PP_Instance instance);
+ // Construct the one MessageLoopResource for the main thread. This must be
+ // invoked on the main thread.
+ explicit MessageLoopResource(ForMainThread);
+ virtual ~MessageLoopResource();
+
+ // Resource overrides.
+ virtual thunk::PPB_MessageLoop_API* AsPPB_MessageLoop_API() OVERRIDE;
+
+ // PPB_MessageLoop_API implementation.
+ virtual int32_t AttachToCurrentThread() OVERRIDE;
+ virtual int32_t Run() OVERRIDE;
+ virtual int32_t PostWork(PP_CompletionCallback callback,
+ int64_t delay_ms) OVERRIDE;
+ virtual int32_t PostQuit(PP_Bool should_destroy) OVERRIDE;
+
+ static MessageLoopResource* GetCurrent();
+ void DetachFromThread();
+ bool is_main_thread_loop() const {
+ return is_main_thread_loop_;
+ }
+
+ private:
+ struct TaskInfo {
+ tracked_objects::Location from_here;
+ base::Closure closure;
+ int64 delay_ms;
+ };
+
+ // Returns true if the object is associated with the current thread.
+ bool IsCurrent() const;
+
+ // Handles posting to the message loop if there is one, or the pending queue
+ // if there isn't.
+ // NOTE: The given closure will be run *WITHOUT* acquiring the Proxy lock.
+ // This only makes sense for user code and completely thread-safe
+ // proxy operations (e.g., MessageLoop::QuitClosure).
+ virtual void PostClosure(const tracked_objects::Location& from_here,
+ const base::Closure& closure,
+ int64 delay_ms) OVERRIDE;
+
+ // TLS destructor function.
+ static void ReleaseMessageLoop(void* value);
+
+ // Created when we attach to the current thread, since MessageLoop assumes
+ // that it's created on the thread it will run on. NULL for the main thread
+ // loop, since that's owned by somebody else. This is needed for Run and Quit.
+ // Any time we post tasks, we should post them using loop_proxy_.
+ scoped_ptr<base::MessageLoop> loop_;
+ scoped_refptr<base::MessageLoopProxy> loop_proxy_;
+
+ // Number of invocations of Run currently on the stack.
+ int nested_invocations_;
+
+ // Set to true when the message loop is destroyed to prevent forther
+ // posting of work.
+ bool destroyed_;
+
+ // Set to true if all message loop invocations should exit and that the
+ // loop should be destroyed once it reaches the outermost Run invocation.
+ bool should_destroy_;
+
+ bool is_main_thread_loop_;
+
+ // Since we allow tasks to be posted before the message loop is actually
+ // created (when it's associated with a thread), we keep tasks posted here
+ // until that happens. Once the loop_ is created, this is unused.
+ std::vector<TaskInfo> pending_tasks_;
+
+ DISALLOW_COPY_AND_ASSIGN(MessageLoopResource);
+};
+
+class PPB_MessageLoop_Proxy : public InterfaceProxy {
+ public:
+ explicit PPB_MessageLoop_Proxy(Dispatcher* dispatcher);
+ virtual ~PPB_MessageLoop_Proxy();
+
+ static const PPB_MessageLoop_1_0* GetInterface();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PPB_MessageLoop_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPB_MESSAGE_LOOP_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppb_network_monitor_private_proxy.cc b/chromium/ppapi/proxy/ppb_network_monitor_private_proxy.cc
new file mode 100644
index 00000000000..055ed2e3a7b
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_network_monitor_private_proxy.cc
@@ -0,0 +1,156 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppb_network_monitor_private_proxy.h"
+
+#include "ppapi/proxy/enter_proxy.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/thunk/ppb_network_monitor_private_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPB_NetworkMonitor_Private_Proxy::NetworkMonitor
+ : public Resource,
+ public thunk::PPB_NetworkMonitor_Private_API,
+ public base::SupportsWeakPtr<
+ PPB_NetworkMonitor_Private_Proxy::NetworkMonitor> {
+ public:
+ NetworkMonitor(PP_Instance instance,
+ PPB_NetworkMonitor_Private_Proxy* proxy,
+ PPB_NetworkMonitor_Callback callback,
+ void* user_data)
+ : Resource(OBJECT_IS_PROXY, instance),
+ proxy_(proxy),
+ callback_(callback),
+ user_data_(user_data) {
+ }
+
+ virtual ~NetworkMonitor() {
+ proxy_->OnNetworkMonitorDeleted(this, pp_instance());
+ }
+
+
+ // Resource overrides.
+ virtual ppapi::thunk::PPB_NetworkMonitor_Private_API*
+ AsPPB_NetworkMonitor_Private_API() OVERRIDE {
+ return this;
+ }
+
+ // This is invoked when a network list is received for this monitor (either
+ // initially or on a change). It acquires the ProxyLock inside because
+ // ObserverListThreadSafe does not support Bind/Closure, otherwise we would
+ // wrap the call with a lock using RunWhileLocked.
+ void OnNetworkListReceivedLocks(
+ const scoped_refptr<NetworkListStorage>& list) {
+ ProxyAutoLock lock;
+ PP_Resource list_resource =
+ PPB_NetworkList_Private_Shared::Create(
+ OBJECT_IS_PROXY, pp_instance(), list);
+ CallWhileUnlocked(callback_, user_data_, list_resource);
+ }
+
+ private:
+ PPB_NetworkMonitor_Private_Proxy* proxy_;
+ PPB_NetworkMonitor_Callback callback_;
+ void* user_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkMonitor);
+};
+
+PPB_NetworkMonitor_Private_Proxy::PPB_NetworkMonitor_Private_Proxy(
+ Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher),
+ monitors_(new ObserverListThreadSafe<NetworkMonitor>()),
+ monitors_count_(0) {
+}
+
+PPB_NetworkMonitor_Private_Proxy::~PPB_NetworkMonitor_Private_Proxy() {
+ monitors_->AssertEmpty();
+}
+
+// static
+PP_Resource PPB_NetworkMonitor_Private_Proxy::CreateProxyResource(
+ PP_Instance instance,
+ PPB_NetworkMonitor_Callback callback,
+ void* user_data) {
+ // TODO(dmichael): Check that this thread has a valid message loop associated
+ // with it.
+ if (!callback)
+ return 0;
+
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+ PPB_NetworkMonitor_Private_Proxy* proxy =
+ static_cast<PPB_NetworkMonitor_Private_Proxy*>(
+ dispatcher->GetInterfaceProxy(kApiID));
+ if (!proxy)
+ return 0;
+
+ scoped_refptr<NetworkMonitor> result(
+ new NetworkMonitor(instance, proxy, callback, user_data));
+ proxy->monitors_->AddObserver(result.get());
+
+ proxy->monitors_count_++;
+ if (proxy->monitors_count_ == 1) {
+ // If that is the first network monitor then send Start message.
+ PluginGlobals::Get()->GetBrowserSender()->Send(
+ new PpapiHostMsg_PPBNetworkMonitor_Start(
+ dispatcher->plugin_dispatcher_id()));
+
+ // We could have received network list message after sending the
+ // previous Stop message. This list is stale now, so reset it
+ // here.
+ proxy->current_list_ = NULL;
+ } else if (proxy->current_list_.get()) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&NetworkMonitor::OnNetworkListReceivedLocks,
+ result->AsWeakPtr(),
+ proxy->current_list_));
+ }
+
+ return result->GetReference();
+}
+
+bool PPB_NetworkMonitor_Private_Proxy::OnMessageReceived(
+ const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_NetworkMonitor_Private_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBNetworkMonitor_NetworkList,
+ OnPluginMsgNetworkList)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPB_NetworkMonitor_Private_Proxy::OnPluginMsgNetworkList(
+ uint32 plugin_dispatcher_id,
+ const ppapi::NetworkList& list) {
+ scoped_refptr<NetworkListStorage> list_storage(new NetworkListStorage(list));
+ current_list_ = list_storage;
+ monitors_->Notify(&NetworkMonitor::OnNetworkListReceivedLocks, list_storage);
+}
+
+void PPB_NetworkMonitor_Private_Proxy::OnNetworkMonitorDeleted(
+ NetworkMonitor* monitor,
+ PP_Instance instance) {
+ monitors_->RemoveObserver(monitor);
+ monitors_count_--;
+ if (monitors_count_ == 0) {
+ // Send Stop message if that was the last NetworkMonitor.
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (dispatcher) {
+ PluginGlobals::Get()->GetBrowserSender()->Send(
+ new PpapiHostMsg_PPBNetworkMonitor_Stop(
+ dispatcher->plugin_dispatcher_id()));
+ }
+ current_list_ = NULL;
+ }
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppb_network_monitor_private_proxy.h b/chromium/ppapi/proxy/ppb_network_monitor_private_proxy.h
new file mode 100644
index 00000000000..e764b0cb34f
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_network_monitor_private_proxy.h
@@ -0,0 +1,63 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPB_NETWORK_MONITOR_PRIVATE_PROXY_H_
+#define PPAPI_PROXY_PPB_NETWORK_MONITOR_PRIVATE_PROXY_H_
+
+#include <list>
+
+#include "base/observer_list_threadsafe.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/shared_impl/ppb_network_list_private_shared.h"
+#include "ppapi/shared_impl/scoped_pp_resource.h"
+#include "ppapi/thunk/ppb_network_monitor_private_api.h"
+
+namespace base {
+class MessageLoopProxy;
+} // namespace base
+
+namespace ppapi {
+namespace proxy {
+
+class PPB_NetworkMonitor_Private_Proxy : public InterfaceProxy {
+ public:
+ explicit PPB_NetworkMonitor_Private_Proxy(Dispatcher* dispatcher);
+ virtual ~PPB_NetworkMonitor_Private_Proxy();
+
+ // Creates n NetworkManager object in the plugin process.
+ static PP_Resource CreateProxyResource(PP_Instance instance,
+ PPB_NetworkMonitor_Callback callback,
+ void* user_data);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ static const ApiID kApiID = API_ID_PPB_NETWORKMANAGER_PRIVATE;
+
+ private:
+ class NetworkMonitor;
+ friend class NetworkMonitor;
+
+ // IPC message handler for the messages received from the browser.
+ void OnPluginMsgNetworkList(uint32 plugin_dispatcher_id,
+ const ppapi::NetworkList& list);
+
+ // Called by NetworkMonitor destructor.
+ void OnNetworkMonitorDeleted(NetworkMonitor* monitor,
+ PP_Instance instance);
+
+ // We use ObserverListThreadSafe because we want to send notifications to the
+ // same thread that created the NetworkMonitor.
+ scoped_refptr<ObserverListThreadSafe<NetworkMonitor> > monitors_;
+
+ int monitors_count_;
+ scoped_refptr<NetworkListStorage> current_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_NetworkMonitor_Private_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPB_NETWORK_MONITOR_PRIVATE_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppb_tcp_socket_private_proxy.cc b/chromium/ppapi/proxy/ppb_tcp_socket_private_proxy.cc
new file mode 100644
index 00000000000..58199fd140e
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_tcp_socket_private_proxy.cc
@@ -0,0 +1,263 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppb_tcp_socket_private_proxy.h"
+
+#include <map>
+
+#include "base/logging.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h"
+#include "ppapi/shared_impl/private/tcp_socket_private_impl.h"
+#include "ppapi/shared_impl/resource.h"
+#include "ppapi/shared_impl/socket_option_data.h"
+#include "ppapi/thunk/thunk.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+typedef std::map<uint32, TCPSocketPrivateImpl*> IDToSocketMap;
+IDToSocketMap* g_id_to_socket = NULL;
+
+class TCPSocket : public TCPSocketPrivateImpl {
+ public:
+ // C-tor for new sockets.
+ TCPSocket(const HostResource& resource, uint32 socket_id);
+ // C-tor for already connected sockets.
+ TCPSocket(const HostResource& resource,
+ uint32 socket_id,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr);
+ virtual ~TCPSocket();
+
+ virtual void SendConnect(const std::string& host, uint16_t port) OVERRIDE;
+ virtual void SendConnectWithNetAddress(
+ const PP_NetAddress_Private& addr) OVERRIDE;
+ virtual void SendSSLHandshake(
+ const std::string& server_name,
+ uint16_t server_port,
+ const std::vector<std::vector<char> >& trusted_certs,
+ const std::vector<std::vector<char> >& untrusted_certs) OVERRIDE;
+ virtual void SendRead(int32_t bytes_to_read) OVERRIDE;
+ virtual void SendWrite(const std::string& buffer) OVERRIDE;
+ virtual void SendDisconnect() OVERRIDE;
+ virtual void SendSetOption(PP_TCPSocket_Option name,
+ const SocketOptionData& value) OVERRIDE;
+
+ private:
+ void SendToBrowser(IPC::Message* msg);
+
+ DISALLOW_COPY_AND_ASSIGN(TCPSocket);
+};
+
+TCPSocket::TCPSocket(const HostResource& resource, uint32 socket_id)
+ : TCPSocketPrivateImpl(resource, socket_id) {
+ 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;
+}
+
+TCPSocket::TCPSocket(const HostResource& resource,
+ uint32 socket_id,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr)
+ : TCPSocketPrivateImpl(resource, socket_id) {
+ if (!g_id_to_socket)
+ g_id_to_socket = new IDToSocketMap();
+ DCHECK(g_id_to_socket->find(socket_id) == g_id_to_socket->end());
+
+ connection_state_ = CONNECTED;
+ local_addr_ = local_addr;
+ remote_addr_ = remote_addr;
+
+ (*g_id_to_socket)[socket_id] = this;
+}
+
+TCPSocket::~TCPSocket() {
+ Disconnect();
+}
+
+void TCPSocket::SendConnect(const std::string& host, uint16_t port) {
+ SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Connect(
+ API_ID_PPB_TCPSOCKET_PRIVATE, socket_id_, host, port));
+}
+
+void TCPSocket::SendConnectWithNetAddress(const PP_NetAddress_Private& addr) {
+ SendToBrowser(new PpapiHostMsg_PPBTCPSocket_ConnectWithNetAddress(
+ API_ID_PPB_TCPSOCKET_PRIVATE, socket_id_, addr));
+}
+
+void TCPSocket::SendSSLHandshake(
+ const std::string& server_name,
+ uint16_t server_port,
+ const std::vector<std::vector<char> >& trusted_certs,
+ const std::vector<std::vector<char> >& untrusted_certs) {
+ SendToBrowser(new PpapiHostMsg_PPBTCPSocket_SSLHandshake(
+ socket_id_, server_name, server_port, trusted_certs, untrusted_certs));
+}
+
+void TCPSocket::SendRead(int32_t bytes_to_read) {
+ SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Read(socket_id_, bytes_to_read));
+}
+
+void TCPSocket::SendWrite(const std::string& buffer) {
+ SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Write(socket_id_, buffer));
+}
+
+void TCPSocket::SendDisconnect() {
+ // After removed from the mapping, this object won't receive any notifications
+ // from the proxy.
+ DCHECK(g_id_to_socket->find(socket_id_) != g_id_to_socket->end());
+ g_id_to_socket->erase(socket_id_);
+ SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Disconnect(socket_id_));
+}
+
+void TCPSocket::SendSetOption(PP_TCPSocket_Option name,
+ const SocketOptionData& value) {
+ SendToBrowser(
+ new PpapiHostMsg_PPBTCPSocket_SetOption(socket_id_, name, value));
+}
+
+void TCPSocket::SendToBrowser(IPC::Message* msg) {
+ PluginGlobals::Get()->GetBrowserSender()->Send(msg);
+}
+
+} // namespace
+
+//------------------------------------------------------------------------------
+
+PPB_TCPSocket_Private_Proxy::PPB_TCPSocket_Private_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher) {
+}
+
+PPB_TCPSocket_Private_Proxy::~PPB_TCPSocket_Private_Proxy() {
+}
+
+// static
+PP_Resource PPB_TCPSocket_Private_Proxy::CreateProxyResource(
+ PP_Instance instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+
+ uint32 socket_id = 0;
+ PluginGlobals::Get()->GetBrowserSender()->Send(
+ new PpapiHostMsg_PPBTCPSocket_CreatePrivate(
+ API_ID_PPB_TCPSOCKET_PRIVATE, dispatcher->plugin_dispatcher_id(),
+ &socket_id));
+ if (socket_id == 0)
+ return 0;
+ return (new TCPSocket(HostResource::MakeInstanceOnly(instance),
+ socket_id))->GetReference();
+}
+
+// static
+PP_Resource PPB_TCPSocket_Private_Proxy::CreateProxyResourceForConnectedSocket(
+ PP_Instance instance,
+ uint32 socket_id,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr) {
+ return (new TCPSocket(HostResource::MakeInstanceOnly(instance),
+ socket_id,
+ local_addr,
+ remote_addr))->GetReference();
+}
+
+bool PPB_TCPSocket_Private_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_TCPSocket_Private_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_ConnectACK,
+ OnMsgConnectACK)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_SSLHandshakeACK,
+ OnMsgSSLHandshakeACK)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_ReadACK, OnMsgReadACK)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_WriteACK, OnMsgWriteACK)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_SetOptionACK, OnMsgSetOptionACK)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPB_TCPSocket_Private_Proxy::OnMsgConnectACK(
+ uint32 /* plugin_dispatcher_id */,
+ uint32 socket_id,
+ int32_t result,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& 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(result, local_addr, remote_addr);
+}
+
+void PPB_TCPSocket_Private_Proxy::OnMsgSSLHandshakeACK(
+ uint32 /* plugin_dispatcher_id */,
+ uint32 socket_id,
+ bool succeeded,
+ const PPB_X509Certificate_Fields& certificate_fields) {
+ 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->OnSSLHandshakeCompleted(succeeded, certificate_fields);
+}
+
+void PPB_TCPSocket_Private_Proxy::OnMsgReadACK(
+ uint32 /* plugin_dispatcher_id */,
+ uint32 socket_id,
+ int32_t result,
+ 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(result, data);
+}
+
+void PPB_TCPSocket_Private_Proxy::OnMsgWriteACK(
+ uint32 /* plugin_dispatcher_id */,
+ uint32 socket_id,
+ int32_t result) {
+ 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(result);
+}
+
+void PPB_TCPSocket_Private_Proxy::OnMsgSetOptionACK(
+ uint32 /* plugin_dispatcher_id */,
+ uint32 socket_id,
+ int32_t result) {
+ 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->OnSetOptionCompleted(result);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppb_tcp_socket_private_proxy.h b/chromium/ppapi/proxy/ppb_tcp_socket_private_proxy.h
new file mode 100644
index 00000000000..0813531a00e
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_tcp_socket_private_proxy.h
@@ -0,0 +1,69 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPB_TCP_SOCKET_PRIVATE_PROXY_H_
+#define PPAPI_PROXY_PPB_TCP_SOCKET_PRIVATE_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_tcp_socket_private.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+
+namespace ppapi {
+
+class PPB_X509Certificate_Fields;
+
+namespace proxy {
+
+class PPB_TCPSocket_Private_Proxy : public InterfaceProxy {
+ public:
+ explicit PPB_TCPSocket_Private_Proxy(Dispatcher* dispatcher);
+ virtual ~PPB_TCPSocket_Private_Proxy();
+
+ static PP_Resource CreateProxyResource(PP_Instance instance);
+ static PP_Resource CreateProxyResourceForConnectedSocket(
+ PP_Instance instance,
+ uint32 socket_id,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ static const ApiID kApiID = API_ID_PPB_TCPSOCKET_PRIVATE;
+
+ private:
+ // Browser->plugin message handlers.
+ void OnMsgConnectACK(uint32 plugin_dispatcher_id,
+ uint32 socket_id,
+ int32_t result,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr);
+ void OnMsgSSLHandshakeACK(
+ uint32 plugin_dispatcher_id,
+ uint32 socket_id,
+ bool succeeded,
+ const PPB_X509Certificate_Fields& certificate_fields);
+ void OnMsgReadACK(uint32 plugin_dispatcher_id,
+ uint32 socket_id,
+ int32_t result,
+ const std::string& data);
+ void OnMsgWriteACK(uint32 plugin_dispatcher_id,
+ uint32 socket_id,
+ int32_t result);
+ void OnMsgSetOptionACK(uint32 plugin_dispatcher_id,
+ uint32 socket_id,
+ int32_t result);
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_TCPSocket_Private_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPB_TCP_SOCKET_PRIVATE_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppb_tcp_socket_proxy.cc b/chromium/ppapi/proxy/ppb_tcp_socket_proxy.cc
new file mode 100644
index 00000000000..2ec16603300
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_tcp_socket_proxy.cc
@@ -0,0 +1,299 @@
+// Copyright 2013 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_tcp_socket_proxy.h"
+
+#include <map>
+
+#include "base/logging.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/resource.h"
+#include "ppapi/shared_impl/socket_option_data.h"
+#include "ppapi/shared_impl/tcp_socket_shared.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_net_address_api.h"
+#include "ppapi/thunk/ppb_tcp_socket_api.h"
+#include "ppapi/thunk/thunk.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+typedef thunk::EnterResourceNoLock<thunk::PPB_NetAddress_API>
+ EnterNetAddressNoLock;
+
+typedef std::map<uint32, TCPSocketShared*> IDToSocketMap;
+IDToSocketMap* g_id_to_socket = NULL;
+
+class TCPSocket : public thunk::PPB_TCPSocket_API,
+ public Resource,
+ public TCPSocketShared {
+ public:
+ TCPSocket(const HostResource& resource, uint32 socket_id);
+ virtual ~TCPSocket();
+
+ // Resource overrides.
+ virtual thunk::PPB_TCPSocket_API* AsPPB_TCPSocket_API() OVERRIDE;
+
+ // thunk::PPB_TCPSocket_API implementation.
+ virtual int32_t Connect(PP_Resource addr,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual PP_Resource GetLocalAddress() OVERRIDE;
+ virtual PP_Resource GetRemoteAddress() OVERRIDE;
+ virtual int32_t Read(char* buffer,
+ int32_t bytes_to_read,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Write(const char* buffer,
+ int32_t bytes_to_write,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual void Close() OVERRIDE;
+ virtual int32_t SetOption(PP_TCPSocket_Option name,
+ const PP_Var& value,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+
+ // TCPSocketShared implementation.
+ virtual void SendConnect(const std::string& host, uint16_t port) OVERRIDE;
+ virtual void SendConnectWithNetAddress(
+ const PP_NetAddress_Private& addr) OVERRIDE;
+ virtual void SendSSLHandshake(
+ const std::string& server_name,
+ uint16_t server_port,
+ const std::vector<std::vector<char> >& trusted_certs,
+ const std::vector<std::vector<char> >& untrusted_certs) OVERRIDE;
+ virtual void SendRead(int32_t bytes_to_read) OVERRIDE;
+ virtual void SendWrite(const std::string& buffer) OVERRIDE;
+ virtual void SendDisconnect() OVERRIDE;
+ virtual void SendSetOption(PP_TCPSocket_Option name,
+ const SocketOptionData& value) OVERRIDE;
+ virtual Resource* GetOwnerResource() OVERRIDE;
+
+ private:
+ void SendToBrowser(IPC::Message* msg);
+
+ DISALLOW_COPY_AND_ASSIGN(TCPSocket);
+};
+
+TCPSocket::TCPSocket(const HostResource& resource, uint32 socket_id)
+ : Resource(OBJECT_IS_PROXY, resource),
+ TCPSocketShared(OBJECT_IS_PROXY, socket_id) {
+ 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;
+}
+
+TCPSocket::~TCPSocket() {
+ DisconnectImpl();
+}
+
+thunk::PPB_TCPSocket_API* TCPSocket::AsPPB_TCPSocket_API() {
+ return this;
+}
+
+int32_t TCPSocket::Connect(PP_Resource addr,
+ scoped_refptr<TrackedCallback> callback) {
+ EnterNetAddressNoLock enter(addr, true);
+ if (enter.failed())
+ return PP_ERROR_BADARGUMENT;
+
+ return ConnectWithNetAddressImpl(&enter.object()->GetNetAddressPrivate(),
+ callback);
+}
+
+PP_Resource TCPSocket::GetLocalAddress() {
+ PP_NetAddress_Private addr_private;
+ if (!GetLocalAddressImpl(&addr_private))
+ return 0;
+
+ thunk::EnterResourceCreationNoLock enter(pp_instance());
+ if (enter.failed())
+ return 0;
+ return enter.functions()->CreateNetAddressFromNetAddressPrivate(
+ pp_instance(), addr_private);
+}
+
+PP_Resource TCPSocket::GetRemoteAddress() {
+ PP_NetAddress_Private addr_private;
+ if (!GetRemoteAddressImpl(&addr_private))
+ return 0;
+
+ thunk::EnterResourceCreationNoLock enter(pp_instance());
+ if (enter.failed())
+ return 0;
+ return enter.functions()->CreateNetAddressFromNetAddressPrivate(
+ pp_instance(), addr_private);
+}
+
+int32_t TCPSocket::Read(char* buffer,
+ int32_t bytes_to_read,
+ scoped_refptr<TrackedCallback> callback) {
+ return ReadImpl(buffer, bytes_to_read, callback);
+}
+
+int32_t TCPSocket::Write(const char* buffer,
+ int32_t bytes_to_write,
+ scoped_refptr<TrackedCallback> callback) {
+ return WriteImpl(buffer, bytes_to_write, callback);
+}
+
+void TCPSocket::Close() {
+ DisconnectImpl();
+}
+
+int32_t TCPSocket::SetOption(PP_TCPSocket_Option name,
+ const PP_Var& value,
+ scoped_refptr<TrackedCallback> callback) {
+ return SetOptionImpl(name, value, callback);
+}
+
+void TCPSocket::SendConnect(const std::string& host, uint16_t port) {
+ NOTREACHED();
+}
+
+void TCPSocket::SendConnectWithNetAddress(const PP_NetAddress_Private& addr) {
+ SendToBrowser(new PpapiHostMsg_PPBTCPSocket_ConnectWithNetAddress(
+ API_ID_PPB_TCPSOCKET, socket_id_, addr));
+}
+
+void TCPSocket::SendSSLHandshake(
+ const std::string& server_name,
+ uint16_t server_port,
+ const std::vector<std::vector<char> >& trusted_certs,
+ const std::vector<std::vector<char> >& untrusted_certs) {
+ NOTREACHED();
+}
+
+void TCPSocket::SendRead(int32_t bytes_to_read) {
+ SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Read(socket_id_, bytes_to_read));
+}
+
+void TCPSocket::SendWrite(const std::string& buffer) {
+ SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Write(socket_id_, buffer));
+}
+
+void TCPSocket::SendDisconnect() {
+ // After removed from the mapping, this object won't receive any notifications
+ // from the proxy.
+ DCHECK(g_id_to_socket->find(socket_id_) != g_id_to_socket->end());
+ g_id_to_socket->erase(socket_id_);
+ SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Disconnect(socket_id_));
+}
+
+void TCPSocket::SendSetOption(PP_TCPSocket_Option name,
+ const SocketOptionData& value) {
+ SendToBrowser(
+ new PpapiHostMsg_PPBTCPSocket_SetOption(socket_id_, name, value));
+}
+
+Resource* TCPSocket::GetOwnerResource() {
+ return this;
+}
+
+void TCPSocket::SendToBrowser(IPC::Message* msg) {
+ PluginGlobals::Get()->GetBrowserSender()->Send(msg);
+}
+
+} // namespace
+
+//------------------------------------------------------------------------------
+
+PPB_TCPSocket_Proxy::PPB_TCPSocket_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher) {
+}
+
+PPB_TCPSocket_Proxy::~PPB_TCPSocket_Proxy() {
+}
+
+// static
+PP_Resource PPB_TCPSocket_Proxy::CreateProxyResource(PP_Instance instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+
+ uint32 socket_id = 0;
+ PluginGlobals::Get()->GetBrowserSender()->Send(
+ new PpapiHostMsg_PPBTCPSocket_Create(
+ API_ID_PPB_TCPSOCKET, dispatcher->plugin_dispatcher_id(),
+ &socket_id));
+ if (socket_id == 0)
+ return 0;
+ return (new TCPSocket(HostResource::MakeInstanceOnly(instance),
+ socket_id))->GetReference();
+}
+
+bool PPB_TCPSocket_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_TCPSocket_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_ConnectACK,
+ OnMsgConnectACK)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_ReadACK, OnMsgReadACK)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_WriteACK, OnMsgWriteACK)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_SetOptionACK,
+ OnMsgSetOptionACK)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPB_TCPSocket_Proxy::OnMsgConnectACK(
+ uint32 /* plugin_dispatcher_id */,
+ uint32 socket_id,
+ int32_t result,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& 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(result, local_addr, remote_addr);
+}
+
+void PPB_TCPSocket_Proxy::OnMsgReadACK(uint32 /* plugin_dispatcher_id */,
+ uint32 socket_id,
+ int32_t result,
+ 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(result, data);
+}
+
+void PPB_TCPSocket_Proxy::OnMsgWriteACK(uint32 /* plugin_dispatcher_id */,
+ uint32 socket_id,
+ int32_t result) {
+ 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(result);
+}
+
+void PPB_TCPSocket_Proxy::OnMsgSetOptionACK(uint32 /* plugin_dispatcher_id */,
+ uint32 socket_id,
+ int32_t result) {
+ 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->OnSetOptionCompleted(result);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppb_tcp_socket_proxy.h b/chromium/ppapi/proxy/ppb_tcp_socket_proxy.h
new file mode 100644
index 00000000000..c5a3de8c721
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_tcp_socket_proxy.h
@@ -0,0 +1,57 @@
+// Copyright 2013 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_TCP_SOCKET_PROXY_H_
+#define PPAPI_PROXY_PPB_TCP_SOCKET_PROXY_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+
+struct PP_NetAddress_Private;
+
+namespace ppapi {
+namespace proxy {
+
+class PPB_TCPSocket_Proxy : public InterfaceProxy {
+ public:
+ explicit PPB_TCPSocket_Proxy(Dispatcher* dispatcher);
+ virtual ~PPB_TCPSocket_Proxy();
+
+ static PP_Resource CreateProxyResource(PP_Instance instance);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ static const ApiID kApiID = API_ID_PPB_TCPSOCKET;
+
+ private:
+ // Browser->plugin message handlers.
+ void OnMsgConnectACK(uint32 plugin_dispatcher_id,
+ uint32 socket_id,
+ int32_t result,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr);
+ void OnMsgReadACK(uint32 plugin_dispatcher_id,
+ uint32 socket_id,
+ int32_t result,
+ const std::string& data);
+ void OnMsgWriteACK(uint32 plugin_dispatcher_id,
+ uint32 socket_id,
+ int32_t result);
+ void OnMsgSetOptionACK(uint32 plugin_dispatcher_id,
+ uint32 socket_id,
+ int32_t result);
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_TCPSocket_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPB_TCP_SOCKET_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppb_testing_proxy.cc b/chromium/ppapi/proxy/ppb_testing_proxy.cc
new file mode 100644
index 00000000000..f80e60cbf5a
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_testing_proxy.cc
@@ -0,0 +1,229 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppb_testing_proxy.h"
+
+#include "base/message_loop/message_loop.h"
+#include "ppapi/c/dev/ppb_testing_dev.h"
+#include "ppapi/proxy/enter_proxy.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/resource.h"
+#include "ppapi/shared_impl/resource_tracker.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_graphics_2d_api.h"
+#include "ppapi/thunk/ppb_input_event_api.h"
+
+using ppapi::thunk::EnterInstance;
+using ppapi::thunk::EnterResource;
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_Graphics2D_API;
+using ppapi::thunk::PPB_InputEvent_API;
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+PP_Bool ReadImageData(PP_Resource graphics_2d,
+ PP_Resource image,
+ const PP_Point* top_left) {
+ ProxyAutoLock lock;
+ Resource* image_object =
+ PpapiGlobals::Get()->GetResourceTracker()->GetResource(image);
+ if (!image_object)
+ return PP_FALSE;
+ Resource* graphics_2d_object =
+ PpapiGlobals::Get()->GetResourceTracker()->GetResource(graphics_2d);
+ if (!graphics_2d_object ||
+ image_object->pp_instance() != graphics_2d_object->pp_instance())
+ return PP_FALSE;
+
+ EnterResourceNoLock<PPB_Graphics2D_API> enter(graphics_2d, true);
+ if (enter.failed())
+ return PP_FALSE;
+ const HostResource& host_image = image_object->host_resource();
+ return enter.object()->ReadImageData(host_image.host_resource(), top_left) ?
+ PP_TRUE : PP_FALSE;
+}
+
+void RunMessageLoop(PP_Instance instance) {
+ base::MessageLoop::ScopedNestableTaskAllower allow(
+ base::MessageLoop::current());
+ CHECK(PpapiGlobals::Get()->GetMainThreadMessageLoop()->
+ BelongsToCurrentThread());
+ base::MessageLoop::current()->Run();
+}
+
+void QuitMessageLoop(PP_Instance instance) {
+ CHECK(PpapiGlobals::Get()->GetMainThreadMessageLoop()->
+ BelongsToCurrentThread());
+ base::MessageLoop::current()->QuitNow();
+}
+
+uint32_t GetLiveObjectsForInstance(PP_Instance instance_id) {
+ ProxyAutoLock lock;
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id);
+ if (!dispatcher)
+ return static_cast<uint32_t>(-1);
+
+ uint32_t result = 0;
+ dispatcher->Send(new PpapiHostMsg_PPBTesting_GetLiveObjectsForInstance(
+ API_ID_PPB_TESTING, instance_id, &result));
+ return result;
+}
+
+PP_Bool IsOutOfProcess() {
+ return PP_TRUE;
+}
+
+void SimulateInputEvent(PP_Instance instance_id, PP_Resource input_event) {
+ ProxyAutoLock lock;
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id);
+ if (!dispatcher)
+ return;
+ EnterResourceNoLock<PPB_InputEvent_API> enter(input_event, false);
+ if (enter.failed())
+ return;
+
+ const InputEventData& input_event_data = enter.object()->GetInputEventData();
+ dispatcher->Send(new PpapiHostMsg_PPBTesting_SimulateInputEvent(
+ API_ID_PPB_TESTING, instance_id, input_event_data));
+}
+
+PP_Var GetDocumentURL(PP_Instance instance, PP_URLComponents_Dev* components) {
+ EnterInstance enter(instance);
+ if (enter.failed())
+ return PP_MakeUndefined();
+ return enter.functions()->GetDocumentURL(instance, components);
+}
+
+// TODO(dmichael): Ideally we could get a way to check the number of vars in the
+// host-side tracker when running out-of-process, to make sure the proxy does
+// not leak host-side vars.
+uint32_t GetLiveVars(PP_Var live_vars[], uint32_t array_size) {
+ ProxyAutoLock lock;
+ std::vector<PP_Var> vars =
+ PpapiGlobals::Get()->GetVarTracker()->GetLiveVars();
+ for (size_t i = 0u;
+ i < std::min(static_cast<size_t>(array_size), vars.size());
+ ++i)
+ live_vars[i] = vars[i];
+ return vars.size();
+}
+
+void SetMinimumArrayBufferSizeForShmem(PP_Instance instance,
+ uint32_t threshold) {
+ ProxyAutoLock lock;
+ RawVarDataGraph::SetMinimumArrayBufferSizeForShmemForTest(threshold);
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return;
+ dispatcher->Send(
+ new PpapiHostMsg_PPBTesting_SetMinimumArrayBufferSizeForShmem(
+ API_ID_PPB_TESTING, threshold));
+}
+
+const PPB_Testing_Dev testing_interface = {
+ &ReadImageData,
+ &RunMessageLoop,
+ &QuitMessageLoop,
+ &GetLiveObjectsForInstance,
+ &IsOutOfProcess,
+ &SimulateInputEvent,
+ &GetDocumentURL,
+ &GetLiveVars,
+ &SetMinimumArrayBufferSizeForShmem
+};
+
+InterfaceProxy* CreateTestingProxy(Dispatcher* dispatcher) {
+ return new PPB_Testing_Proxy(dispatcher);
+}
+
+} // namespace
+
+PPB_Testing_Proxy::PPB_Testing_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher),
+ ppb_testing_impl_(NULL) {
+ if (!dispatcher->IsPlugin()) {
+ ppb_testing_impl_ = static_cast<const PPB_Testing_Dev*>(
+ dispatcher->local_get_interface()(PPB_TESTING_DEV_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,
+ API_ID_PPB_TESTING,
+ false,
+ &CreateTestingProxy,
+ };
+ return &info;
+}
+
+bool PPB_Testing_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_TESTING))
+ return false;
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_Testing_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTesting_ReadImageData,
+ OnMsgReadImageData)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTesting_GetLiveObjectsForInstance,
+ OnMsgGetLiveObjectsForInstance)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTesting_SimulateInputEvent,
+ OnMsgSimulateInputEvent)
+ IPC_MESSAGE_HANDLER(
+ PpapiHostMsg_PPBTesting_SetMinimumArrayBufferSizeForShmem,
+ OnMsgSetMinimumArrayBufferSizeForShmem)
+ 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_impl_->ReadImageData(
+ device_context_2d.host_resource(), image.host_resource(), &top_left);
+}
+
+void PPB_Testing_Proxy::OnMsgRunMessageLoop(PP_Instance instance) {
+ ppb_testing_impl_->RunMessageLoop(instance);
+}
+
+void PPB_Testing_Proxy::OnMsgQuitMessageLoop(PP_Instance instance) {
+ ppb_testing_impl_->QuitMessageLoop(instance);
+}
+
+void PPB_Testing_Proxy::OnMsgGetLiveObjectsForInstance(PP_Instance instance,
+ uint32_t* result) {
+ *result = ppb_testing_impl_->GetLiveObjectsForInstance(instance);
+}
+
+void PPB_Testing_Proxy::OnMsgSimulateInputEvent(
+ PP_Instance instance,
+ const InputEventData& input_event) {
+ scoped_refptr<PPB_InputEvent_Shared> input_event_impl(
+ new PPB_InputEvent_Shared(OBJECT_IS_PROXY, instance, input_event));
+ ppb_testing_impl_->SimulateInputEvent(instance,
+ input_event_impl->pp_resource());
+}
+
+void PPB_Testing_Proxy::OnMsgSetMinimumArrayBufferSizeForShmem(
+ uint32_t threshold) {
+ RawVarDataGraph::SetMinimumArrayBufferSizeForShmemForTest(threshold);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppb_testing_proxy.h b/chromium/ppapi/proxy/ppb_testing_proxy.h
new file mode 100644
index 00000000000..61af47fcb00
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_testing_proxy.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_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/c/dev/ppb_testing_dev.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/shared_impl/host_resource.h"
+
+struct PP_Point;
+
+namespace ppapi {
+
+struct InputEventData;
+
+namespace proxy {
+
+class PPB_Testing_Proxy : public InterfaceProxy {
+ public:
+ PPB_Testing_Proxy(Dispatcher* dispatcher);
+ virtual ~PPB_Testing_Proxy();
+
+ static const Info* GetInfo();
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgReadImageData(const ppapi::HostResource& device_context_2d,
+ const ppapi::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);
+ void OnMsgSimulateInputEvent(PP_Instance instance,
+ const ppapi::InputEventData& input_event);
+ void OnMsgSetMinimumArrayBufferSizeForShmem(uint32_t threshold);
+
+ // When this proxy is in the host side, this value caches the interface
+ // pointer so we don't have to retrieve it from the dispatcher each time.
+ // In the plugin, this value is always NULL.
+ const PPB_Testing_Dev* ppb_testing_impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_Testing_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPB_TESTING_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppb_var_deprecated_proxy.cc b/chromium/ppapi/proxy/ppb_var_deprecated_proxy.cc
new file mode 100644
index 00000000000..43452ef019a
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_var_deprecated_proxy.cc
@@ -0,0 +1,538 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppb_var_deprecated_proxy.h"
+
+#include <stdlib.h> // For malloc
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppp_class_proxy.h"
+#include "ppapi/proxy/proxy_object_var.h"
+#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/shared_impl/ppb_var_shared.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+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;
+
+
+ if (object.type == PP_VARTYPE_OBJECT) {
+ // Get the dispatcher for the object.
+ PluginDispatcher* dispatcher =
+ PluginGlobals::Get()->plugin_var_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 = StringVar::StringToPPVar(
+ std::string("Attempting to use an invalid object"));
+ }
+ return NULL;
+}
+
+// PPB_Var_Deprecated plugin ---------------------------------------------------
+
+bool HasProperty(PP_Var var,
+ PP_Var name,
+ PP_Var* exception) {
+ ProxyAutoLock lock;
+ 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(
+ API_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) {
+ ProxyAutoLock lock;
+ 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(
+ API_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) {
+ ProxyAutoLock lock;
+ 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(
+ API_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) {
+ ProxyAutoLock lock;
+ 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(
+ API_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) {
+ ProxyAutoLock lock;
+ Dispatcher* dispatcher = CheckExceptionAndGetDispatcher(var, exception);
+ if (!dispatcher)
+ return;
+
+ ReceiveSerializedException se(dispatcher, exception);
+ if (!se.IsThrown()) {
+ dispatcher->Send(new PpapiHostMsg_PPBVar_SetPropertyDeprecated(
+ API_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) {
+ ProxyAutoLock lock;
+ 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(
+ API_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) {
+ ProxyAutoLock lock;
+ 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(
+ API_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) {
+ ProxyAutoLock lock;
+ 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(
+ API_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) {
+ ProxyAutoLock lock;
+ 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(
+ API_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) {
+ ProxyAutoLock lock;
+ Dispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return PP_MakeUndefined();
+
+ PluginVarTracker* tracker = PluginGlobals::Get()->plugin_var_tracker();
+ if (tracker->IsPluginImplementedObjectAlive(ppp_class_data))
+ return PP_MakeUndefined(); // Object already exists with this user data.
+
+ 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(
+ API_ID_PPB_VAR_DEPRECATED, instance, class_int, data_int,
+ &result));
+ PP_Var ret_var = result.Return(dispatcher);
+
+ // Register this object as being implemented by the plugin.
+ if (ret_var.type == PP_VARTYPE_OBJECT) {
+ tracker->PluginImplementedObjectCreated(instance, ret_var,
+ ppp_class, ppp_class_data);
+ }
+ return ret_var;
+}
+
+InterfaceProxy* CreateVarDeprecatedProxy(Dispatcher* dispatcher) {
+ return new PPB_Var_Deprecated_Proxy(dispatcher );
+}
+
+} // namespace
+
+PPB_Var_Deprecated_Proxy::PPB_Var_Deprecated_Proxy(
+ Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher),
+ task_factory_(this),
+ ppb_var_impl_(NULL) {
+ if (!dispatcher->IsPlugin()) {
+ ppb_var_impl_ = static_cast<const PPB_Var_Deprecated*>(
+ dispatcher->local_get_interface()(PPB_VAR_DEPRECATED_INTERFACE));
+ }
+}
+
+PPB_Var_Deprecated_Proxy::~PPB_Var_Deprecated_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPB_Var_Deprecated_Proxy::GetInfo() {
+ static const PPB_Var_Deprecated var_deprecated_interface = {
+ ppapi::PPB_Var_Shared::GetVarInterface1_0()->AddRef,
+ ppapi::PPB_Var_Shared::GetVarInterface1_0()->Release,
+ ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarFromUtf8,
+ ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarToUtf8,
+ &HasProperty,
+ &HasMethod,
+ &GetProperty,
+ &EnumerateProperties,
+ &SetProperty,
+ &RemoveProperty,
+ &Call,
+ &Construct,
+ &IsInstanceOf,
+ &CreateObject
+ };
+
+ static const Info info = {
+ &var_deprecated_interface,
+ PPB_VAR_DEPRECATED_INTERFACE,
+ API_ID_PPB_VAR_DEPRECATED,
+ false,
+ &CreateVarDeprecatedProxy,
+ };
+ return &info;
+}
+
+bool PPB_Var_Deprecated_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
+ return false;
+
+ // 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 = { PP_VARTYPE_OBJECT };
+ var.value.as_id = object_id;
+ ppb_var_impl_->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.
+ base::MessageLoop::current()->PostNonNestableTask(
+ FROM_HERE,
+ RunWhileLocked(base::Bind(&PPB_Var_Deprecated_Proxy::DoReleaseObject,
+ task_factory_.GetWeakPtr(),
+ object_id)));
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgHasProperty(
+ SerializedVarReceiveInput var,
+ SerializedVarReceiveInput name,
+ SerializedVarOutParam exception,
+ PP_Bool* result) {
+ SetAllowPluginReentrancy();
+ *result = PP_FromBool(ppb_var_impl_->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_impl_->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_impl_->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_impl_->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_impl_->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_impl_->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_impl_->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_impl_->Construct(
+ var.Get(dispatcher()), arg_count, args,
+ exception.OutParam(dispatcher())));
+}
+
+void PPB_Var_Deprecated_Proxy::OnMsgIsInstanceOfDeprecated(
+ SerializedVarReceiveInput var,
+ int64 ppp_class,
+ int64* ppp_class_data,
+ PP_Bool* result) {
+ SetAllowPluginReentrancy();
+ *result = PPP_Class_Proxy::IsInstanceOf(ppb_var_impl_,
+ var.Get(dispatcher()),
+ ppp_class,
+ ppp_class_data);
+}
+
+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_impl_, 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 = { PP_VARTYPE_OBJECT };
+ var.value.as_id = object_id;
+ ppb_var_impl_->Release(var);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppb_var_deprecated_proxy.h b/chromium/ppapi/proxy/ppb_var_deprecated_proxy.h
new file mode 100644
index 00000000000..59400aede6e
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_var_deprecated_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_PROXY_PPB_VAR_DEPRECATED_PROXY_H_
+#define PPAPI_PROXY_PPB_VAR_DEPRECATED_PROXY_H_
+
+#include <vector>
+
+#include "base/memory/weak_ptr.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_Var_Deprecated;
+
+namespace ppapi {
+namespace proxy {
+
+class SerializedVar;
+class SerializedVarReceiveInput;
+class SerializedVarVectorOutParam;
+class SerializedVarVectorReceiveInput;
+class SerializedVarOutParam;
+class SerializedVarReturnValue;
+
+class PPB_Var_Deprecated_Proxy : public InterfaceProxy {
+ public:
+ explicit PPB_Var_Deprecated_Proxy(Dispatcher* dispatcher);
+ virtual ~PPB_Var_Deprecated_Proxy();
+
+ static const Info* GetInfo();
+
+ // 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(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);
+ base::WeakPtrFactory<PPB_Var_Deprecated_Proxy> task_factory_;
+
+ const PPB_Var_Deprecated* ppb_var_impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_Var_Deprecated_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPB_VAR_DEPRECATED_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppb_var_unittest.cc b/chromium/ppapi/proxy/ppb_var_unittest.cc
new file mode 100644
index 00000000000..7315d00b72a
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_var_unittest.cc
@@ -0,0 +1,241 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+#include <vector>
+
+#include "base/strings/string_number_conversions.h"
+#include "base/threading/platform_thread.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+#include "ppapi/shared_impl/ppb_var_shared.h"
+
+namespace {
+std::string VarToString(const PP_Var& var, const PPB_Var* ppb_var) {
+ uint32_t len = 0;
+ const char* utf8 = ppb_var->VarToUtf8(var, &len);
+ return std::string(utf8, len);
+}
+const size_t kNumStrings = 100;
+const size_t kNumThreads = 20;
+const int kRefsToAdd = 20;
+} // namespace
+
+namespace ppapi {
+namespace proxy {
+
+class PPB_VarTest : public PluginProxyTest {
+ public:
+ PPB_VarTest()
+ : test_strings_(kNumStrings), vars_(kNumStrings),
+ ppb_var_(ppapi::PPB_Var_Shared::GetVarInterface1_1()) {
+ // Set the value of test_strings_[i] to "i".
+ for (size_t i = 0; i < kNumStrings; ++i)
+ test_strings_[i] = base::IntToString(i);
+ }
+ protected:
+ std::vector<std::string> test_strings_;
+ std::vector<PP_Var> vars_;
+ const PPB_Var* ppb_var_;
+};
+
+// Test basic String operations.
+TEST_F(PPB_VarTest, Strings) {
+ for (size_t i = 0; i < kNumStrings; ++i) {
+ vars_[i] = ppb_var_->VarFromUtf8(test_strings_[i].c_str(),
+ test_strings_[i].length());
+ EXPECT_EQ(test_strings_[i], VarToString(vars_[i], ppb_var_));
+ }
+ // At this point, they should each have a ref count of 1. Add some more.
+ for (int ref = 0; ref < kRefsToAdd; ++ref) {
+ for (size_t i = 0; i < kNumStrings; ++i) {
+ ppb_var_->AddRef(vars_[i]);
+ // Make sure the string is still there with the right value.
+ EXPECT_EQ(test_strings_[i], VarToString(vars_[i], ppb_var_));
+ }
+ }
+ for (int ref = 0; ref < kRefsToAdd; ++ref) {
+ for (size_t i = 0; i < kNumStrings; ++i) {
+ ppb_var_->Release(vars_[i]);
+ // Make sure the string is still there with the right value.
+ EXPECT_EQ(test_strings_[i], VarToString(vars_[i], ppb_var_));
+ }
+ }
+ // Now remove the ref counts for each string and make sure they are gone.
+ for (size_t i = 0; i < kNumStrings; ++i) {
+ ppb_var_->Release(vars_[i]);
+ uint32_t len = 10;
+ const char* utf8 = ppb_var_->VarToUtf8(vars_[i], &len);
+ EXPECT_EQ(NULL, utf8);
+ EXPECT_EQ(0u, len);
+ }
+}
+
+// PPB_VarTest.Threads tests string operations accessed by multiple threads.
+namespace {
+// These three delegate classes which precede the test are for use with
+// PlatformThread. The test goes roughly like this:
+// 1) Spawn kNumThreads 'CreateVar' threads, giving each a roughly equal subset
+// of test_strings_ to 'create'. Each 'CreateVar' thread also converts its
+// set of vars back in to strings so that the main test thread can verify
+// their values were correctly converted.
+// 2) Spawn kNumThreads 'ChangeRefVar' threads. Each of these threads will
+// incremement & decrement the reference count of ALL vars kRefsToAdd times.
+// Finally, each thread adds 1 ref count. This leaves each var with a ref-
+// count of |kNumThreads + 1|. The main test thread removes a ref, leaving
+// each var with a ref-count of |kNumThreads|.
+// 3) Spawn kNumThreads 'RemoveVar' threads. Each of these threads releases each
+// var once. Once all the threads have finished, there should be no vars
+// left.
+class CreateVarThreadDelegate : public base::PlatformThread::Delegate {
+ public:
+ // |strings_in|, |vars|, and |strings_out| are arrays, and size is their size.
+ // For each |strings_in[i]|, we will set |vars[i]| using that value. Then we
+ // read the var back out to |strings_out[i]|.
+ CreateVarThreadDelegate(PP_Module pp_module, const std::string* strings_in,
+ PP_Var* vars_out, std::string* strings_out,
+ size_t size)
+ : pp_module_(pp_module), strings_in_(strings_in), vars_out_(vars_out),
+ strings_out_(strings_out), size_(size) {
+ }
+ virtual ~CreateVarThreadDelegate() {}
+ virtual void ThreadMain() {
+ const PPB_Var* ppb_var = ppapi::PPB_Var_Shared::GetVarInterface1_1();
+ for (size_t i = 0; i < size_; ++i) {
+ vars_out_[i] = ppb_var->VarFromUtf8(strings_in_[i].c_str(),
+ strings_in_[i].length());
+ strings_out_[i] = VarToString(vars_out_[i], ppb_var);
+ }
+ }
+ private:
+ PP_Module pp_module_;
+ const std::string* strings_in_;
+ PP_Var* vars_out_;
+ std::string* strings_out_;
+ size_t size_;
+};
+
+// A thread that will increment and decrement the reference count of every var
+// multiple times.
+class ChangeRefVarThreadDelegate : public base::PlatformThread::Delegate {
+ public:
+ ChangeRefVarThreadDelegate(const std::vector<PP_Var>& vars) : vars_(vars) {
+ }
+ virtual ~ChangeRefVarThreadDelegate() {}
+ virtual void ThreadMain() {
+ const PPB_Var* ppb_var = ppapi::PPB_Var_Shared::GetVarInterface1_1();
+ // Increment and decrement the reference count for each var kRefsToAdd
+ // times. Note that we always AddRef once before doing the matching Release,
+ // to ensure that we never accidentally release the last reference.
+ for (int ref = 0; ref < kRefsToAdd; ++ref) {
+ for (size_t i = 0; i < kNumStrings; ++i) {
+ ppb_var->AddRef(vars_[i]);
+ ppb_var->Release(vars_[i]);
+ }
+ }
+ // Now add 1 ref to each Var. The net result is that all Vars will have a
+ // ref-count of (kNumThreads + 1) after this. That will allow us to have all
+ // threads release all vars later.
+ for (size_t i = 0; i < kNumStrings; ++i) {
+ ppb_var->AddRef(vars_[i]);
+ }
+ }
+ private:
+ std::vector<PP_Var> vars_;
+};
+
+// A thread that will decrement the reference count of every var once.
+class RemoveRefVarThreadDelegate : public base::PlatformThread::Delegate {
+ public:
+ RemoveRefVarThreadDelegate(const std::vector<PP_Var>& vars) : vars_(vars) {
+ }
+ virtual ~RemoveRefVarThreadDelegate() {}
+ virtual void ThreadMain() {
+ const PPB_Var* ppb_var = ppapi::PPB_Var_Shared::GetVarInterface1_1();
+ for (size_t i = 0; i < kNumStrings; ++i) {
+ ppb_var->Release(vars_[i]);
+ }
+ }
+ private:
+ std::vector<PP_Var> vars_;
+};
+
+} // namespace
+
+TEST_F(PPB_VarTest, Threads) {
+ std::vector<base::PlatformThreadHandle> create_var_threads(kNumThreads);
+ std::vector<CreateVarThreadDelegate> create_var_delegates;
+ // The strings that the threads will re-extract from Vars (so we can check
+ // that they match the original strings).
+ std::vector<std::string> strings_out(kNumStrings);
+ size_t strings_per_thread = kNumStrings/kNumThreads;
+ // Give each thread an equal slice of strings to turn in to vars. (Except the
+ // last thread may get fewer if kNumStrings is not evenly divisible by
+ // kNumThreads).
+ for (size_t slice_start= 0; slice_start < kNumStrings;
+ slice_start += strings_per_thread) {
+ create_var_delegates.push_back(
+ CreateVarThreadDelegate(pp_module(),
+ &test_strings_[slice_start],
+ &vars_[slice_start],
+ &strings_out[slice_start],
+ std::min(strings_per_thread,
+ kNumStrings - slice_start)));
+ }
+ // Now run then join all the threads.
+ for (size_t i = 0; i < kNumThreads; ++i)
+ base::PlatformThread::Create(0, &create_var_delegates[i],
+ &create_var_threads[i]);
+ for (size_t i = 0; i < kNumThreads; ++i)
+ base::PlatformThread::Join(create_var_threads[i]);
+ // Now check that the strings have the expected values.
+ EXPECT_EQ(test_strings_, strings_out);
+
+ // Tinker with the reference counts in a multithreaded way.
+ std::vector<base::PlatformThreadHandle> change_ref_var_threads(kNumThreads);
+ std::vector<ChangeRefVarThreadDelegate> change_ref_var_delegates;
+ for (size_t i = 0; i < kNumThreads; ++i)
+ change_ref_var_delegates.push_back(ChangeRefVarThreadDelegate(vars_));
+ for (size_t i = 0; i < kNumThreads; ++i) {
+ base::PlatformThread::Create(0, &change_ref_var_delegates[i],
+ &change_ref_var_threads[i]);
+ }
+ for (size_t i = 0; i < kNumThreads; ++i)
+ base::PlatformThread::Join(change_ref_var_threads[i]);
+
+ // Now each var has a refcount of (kNumThreads + 1). Let's decrement each var
+ // once so that every 'RemoveRef' thread (spawned below) owns 1 reference, and
+ // when the last one removes a ref, the Var will be deleted.
+ for (size_t i = 0; i < kNumStrings; ++i) {
+ ppb_var_->Release(vars_[i]);
+ }
+
+ // Check that all vars are still valid and have the values we expect.
+ for (size_t i = 0; i < kNumStrings; ++i)
+ EXPECT_EQ(test_strings_[i], VarToString(vars_[i], ppb_var_));
+
+ // Remove the last reference counts for all vars.
+ std::vector<base::PlatformThreadHandle> remove_ref_var_threads(kNumThreads);
+ std::vector<RemoveRefVarThreadDelegate> remove_ref_var_delegates;
+ for (size_t i = 0; i < kNumThreads; ++i)
+ remove_ref_var_delegates.push_back(RemoveRefVarThreadDelegate(vars_));
+ for (size_t i = 0; i < kNumThreads; ++i) {
+ base::PlatformThread::Create(0, &remove_ref_var_delegates[i],
+ &remove_ref_var_threads[i]);
+ }
+ for (size_t i = 0; i < kNumThreads; ++i)
+ base::PlatformThread::Join(remove_ref_var_threads[i]);
+
+ // All the vars should no longer represent valid strings.
+ for (size_t i = 0; i < kNumStrings; ++i) {
+ uint32_t len = 10;
+ const char* utf8 = ppb_var_->VarToUtf8(vars_[i], &len);
+ EXPECT_EQ(NULL, utf8);
+ EXPECT_EQ(0u, len);
+ }
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppb_video_decoder_proxy.cc b/chromium/ppapi/proxy/ppb_video_decoder_proxy.cc
new file mode 100644
index 00000000000..2a00674f416
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_video_decoder_proxy.cc
@@ -0,0 +1,320 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppb_video_decoder_proxy.h"
+
+#include "base/logging.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "ppapi/proxy/enter_proxy.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_buffer_proxy.h"
+#include "ppapi/proxy/ppb_graphics_3d_proxy.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/resource_creation_api.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_Buffer_API;
+using ppapi::thunk::PPB_Graphics3D_API;
+using ppapi::thunk::PPB_VideoDecoder_API;
+
+namespace ppapi {
+namespace proxy {
+
+class VideoDecoder : public PPB_VideoDecoder_Shared {
+ public:
+ // You must call Init() before using this class.
+ explicit VideoDecoder(const HostResource& resource);
+ virtual ~VideoDecoder();
+
+ static VideoDecoder* Create(const HostResource& resource,
+ PP_Resource graphics_context,
+ PP_VideoDecoder_Profile profile);
+
+ // PPB_VideoDecoder_API implementation.
+ virtual int32_t Decode(const PP_VideoBitstreamBuffer_Dev* bitstream_buffer,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual void AssignPictureBuffers(
+ uint32_t no_of_buffers, const PP_PictureBuffer_Dev* buffers) OVERRIDE;
+ virtual void ReusePictureBuffer(int32_t picture_buffer_id) OVERRIDE;
+ virtual int32_t Flush(scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Reset(scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+
+ private:
+ friend class PPB_VideoDecoder_Proxy;
+
+ PluginDispatcher* GetDispatcher() const;
+
+ // Run the callbacks that were passed into the plugin interface.
+ void FlushACK(int32_t result);
+ void ResetACK(int32_t result);
+ void EndOfBitstreamACK(int32_t buffer_id, int32_t result);
+
+ DISALLOW_COPY_AND_ASSIGN(VideoDecoder);
+};
+
+VideoDecoder::VideoDecoder(const HostResource& decoder)
+ : PPB_VideoDecoder_Shared(decoder) {
+}
+
+VideoDecoder::~VideoDecoder() {
+ FlushCommandBuffer();
+ PPB_VideoDecoder_Shared::Destroy();
+}
+
+int32_t VideoDecoder::Decode(
+ const PP_VideoBitstreamBuffer_Dev* bitstream_buffer,
+ scoped_refptr<TrackedCallback> callback) {
+ EnterResourceNoLock<PPB_Buffer_API>
+ enter_buffer(bitstream_buffer->data, true);
+ if (enter_buffer.failed())
+ return PP_ERROR_BADRESOURCE;
+
+ if (!SetBitstreamBufferCallback(bitstream_buffer->id, callback))
+ return PP_ERROR_BADARGUMENT;
+
+ Buffer* ppb_buffer =
+ static_cast<Buffer*>(enter_buffer.object());
+ HostResource host_buffer = ppb_buffer->host_resource();
+
+ FlushCommandBuffer();
+ GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_Decode(
+ API_ID_PPB_VIDEO_DECODER_DEV, host_resource(),
+ host_buffer, bitstream_buffer->id,
+ bitstream_buffer->size));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void VideoDecoder::AssignPictureBuffers(uint32_t no_of_buffers,
+ const PP_PictureBuffer_Dev* buffers) {
+ std::vector<PP_PictureBuffer_Dev> buffer_list(
+ buffers, buffers + no_of_buffers);
+ FlushCommandBuffer();
+ GetDispatcher()->Send(
+ new PpapiHostMsg_PPBVideoDecoder_AssignPictureBuffers(
+ API_ID_PPB_VIDEO_DECODER_DEV, host_resource(), buffer_list));
+}
+
+void VideoDecoder::ReusePictureBuffer(int32_t picture_buffer_id) {
+ FlushCommandBuffer();
+ GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_ReusePictureBuffer(
+ API_ID_PPB_VIDEO_DECODER_DEV, host_resource(), picture_buffer_id));
+}
+
+int32_t VideoDecoder::Flush(scoped_refptr<TrackedCallback> callback) {
+ if (!SetFlushCallback(callback))
+ return PP_ERROR_INPROGRESS;
+
+ FlushCommandBuffer();
+ GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_Flush(
+ API_ID_PPB_VIDEO_DECODER_DEV, host_resource()));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t VideoDecoder::Reset(scoped_refptr<TrackedCallback> callback) {
+ if (!SetResetCallback(callback))
+ return PP_ERROR_INPROGRESS;
+
+ FlushCommandBuffer();
+ GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_Reset(
+ API_ID_PPB_VIDEO_DECODER_DEV, host_resource()));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void VideoDecoder::Destroy() {
+ FlushCommandBuffer();
+ GetDispatcher()->Send(new PpapiHostMsg_PPBVideoDecoder_Destroy(
+ API_ID_PPB_VIDEO_DECODER_DEV, host_resource()));
+ PPB_VideoDecoder_Shared::Destroy();
+}
+
+PluginDispatcher* VideoDecoder::GetDispatcher() const {
+ return PluginDispatcher::GetForResource(this);
+}
+
+void VideoDecoder::ResetACK(int32_t result) {
+ RunResetCallback(result);
+}
+
+void VideoDecoder::FlushACK(int32_t result) {
+ RunFlushCallback(result);
+}
+
+void VideoDecoder::EndOfBitstreamACK(
+ int32_t bitstream_buffer_id, int32_t result) {
+ RunBitstreamBufferCallback(bitstream_buffer_id, result);
+}
+
+PPB_VideoDecoder_Proxy::PPB_VideoDecoder_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher),
+ callback_factory_(this) {
+}
+
+PPB_VideoDecoder_Proxy::~PPB_VideoDecoder_Proxy() {
+}
+
+bool PPB_VideoDecoder_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
+ return false;
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_VideoDecoder_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Create,
+ OnMsgCreate)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Decode, OnMsgDecode)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_AssignPictureBuffers,
+ OnMsgAssignPictureBuffers)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_ReusePictureBuffer,
+ OnMsgReusePictureBuffer)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Flush, OnMsgFlush)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Reset, OnMsgReset)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVideoDecoder_Destroy, OnMsgDestroy)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBVideoDecoder_ResetACK, OnMsgResetACK)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBVideoDecoder_EndOfBitstreamACK,
+ OnMsgEndOfBitstreamACK)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBVideoDecoder_FlushACK, OnMsgFlushACK)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ DCHECK(handled);
+ return handled;
+}
+
+PP_Resource PPB_VideoDecoder_Proxy::CreateProxyResource(
+ PP_Instance instance,
+ PP_Resource graphics_context,
+ PP_VideoDecoder_Profile profile) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ // Dispatcher is null if it cannot find the instance passed to it (i.e. if the
+ // client passes in an invalid instance).
+ if (!dispatcher)
+ return 0;
+
+ EnterResourceNoLock<PPB_Graphics3D_API> enter_context(graphics_context,
+ true);
+ if (enter_context.failed())
+ return 0;
+
+ Graphics3D* context = static_cast<Graphics3D*>(enter_context.object());
+
+ HostResource result;
+ dispatcher->Send(new PpapiHostMsg_PPBVideoDecoder_Create(
+ API_ID_PPB_VIDEO_DECODER_DEV, instance,
+ context->host_resource(), profile, &result));
+ if (result.is_null())
+ return 0;
+
+ // Need a scoped_refptr to keep the object alive during the Init call.
+ scoped_refptr<VideoDecoder> decoder(new VideoDecoder(result));
+ decoder->InitCommon(graphics_context, context->gles2_impl());
+ return decoder->GetReference();
+}
+
+void PPB_VideoDecoder_Proxy::OnMsgCreate(
+ PP_Instance instance, const HostResource& graphics_context,
+ PP_VideoDecoder_Profile profile,
+ HostResource* result) {
+ thunk::EnterResourceCreation resource_creation(instance);
+ if (resource_creation.failed())
+ return;
+
+ // Make the resource and get the API pointer to its interface.
+ result->SetHostResource(
+ instance, resource_creation.functions()->CreateVideoDecoder(
+ instance, graphics_context.host_resource(), profile));
+}
+
+void PPB_VideoDecoder_Proxy::OnMsgDecode(
+ const HostResource& decoder,
+ const HostResource& buffer, int32 id, uint32 size) {
+ EnterHostFromHostResourceForceCallback<PPB_VideoDecoder_API> enter(
+ decoder, callback_factory_,
+ &PPB_VideoDecoder_Proxy::SendMsgEndOfBitstreamACKToPlugin, decoder, id);
+ if (enter.failed())
+ return;
+ PP_VideoBitstreamBuffer_Dev bitstream = { id, buffer.host_resource(), size };
+ enter.SetResult(enter.object()->Decode(&bitstream, enter.callback()));
+}
+
+void PPB_VideoDecoder_Proxy::OnMsgAssignPictureBuffers(
+ const HostResource& decoder,
+ const std::vector<PP_PictureBuffer_Dev>& buffers) {
+ EnterHostFromHostResource<PPB_VideoDecoder_API> enter(decoder);
+ if (enter.succeeded() && !buffers.empty()) {
+ const PP_PictureBuffer_Dev* buffer_array = &buffers.front();
+ enter.object()->AssignPictureBuffers(buffers.size(), buffer_array);
+ }
+}
+
+void PPB_VideoDecoder_Proxy::OnMsgReusePictureBuffer(
+ const HostResource& decoder, int32 picture_buffer_id) {
+ EnterHostFromHostResource<PPB_VideoDecoder_API> enter(decoder);
+ if (enter.succeeded())
+ enter.object()->ReusePictureBuffer(picture_buffer_id);
+}
+
+void PPB_VideoDecoder_Proxy::OnMsgFlush(const HostResource& decoder) {
+ EnterHostFromHostResourceForceCallback<PPB_VideoDecoder_API> enter(
+ decoder, callback_factory_,
+ &PPB_VideoDecoder_Proxy::SendMsgFlushACKToPlugin, decoder);
+ if (enter.succeeded())
+ enter.SetResult(enter.object()->Flush(enter.callback()));
+}
+
+void PPB_VideoDecoder_Proxy::OnMsgReset(const HostResource& decoder) {
+ EnterHostFromHostResourceForceCallback<PPB_VideoDecoder_API> enter(
+ decoder, callback_factory_,
+ &PPB_VideoDecoder_Proxy::SendMsgResetACKToPlugin, decoder);
+ if (enter.succeeded())
+ enter.SetResult(enter.object()->Reset(enter.callback()));
+}
+
+void PPB_VideoDecoder_Proxy::OnMsgDestroy(const HostResource& decoder) {
+ EnterHostFromHostResource<PPB_VideoDecoder_API> enter(decoder);
+ if (enter.succeeded())
+ enter.object()->Destroy();
+}
+
+void PPB_VideoDecoder_Proxy::SendMsgEndOfBitstreamACKToPlugin(
+ int32_t result, const HostResource& decoder, int32 id) {
+ dispatcher()->Send(new PpapiMsg_PPBVideoDecoder_EndOfBitstreamACK(
+ API_ID_PPB_VIDEO_DECODER_DEV, decoder, id, result));
+}
+
+void PPB_VideoDecoder_Proxy::SendMsgFlushACKToPlugin(
+ int32_t result, const HostResource& decoder) {
+ dispatcher()->Send(new PpapiMsg_PPBVideoDecoder_FlushACK(
+ API_ID_PPB_VIDEO_DECODER_DEV, decoder, result));
+}
+
+void PPB_VideoDecoder_Proxy::SendMsgResetACKToPlugin(
+ int32_t result, const HostResource& decoder) {
+ dispatcher()->Send(new PpapiMsg_PPBVideoDecoder_ResetACK(
+ API_ID_PPB_VIDEO_DECODER_DEV, decoder, result));
+}
+
+void PPB_VideoDecoder_Proxy::OnMsgEndOfBitstreamACK(
+ const HostResource& decoder, int32_t id, int32_t result) {
+ EnterPluginFromHostResource<PPB_VideoDecoder_API> enter(decoder);
+ if (enter.succeeded())
+ static_cast<VideoDecoder*>(enter.object())->EndOfBitstreamACK(id, result);
+}
+
+void PPB_VideoDecoder_Proxy::OnMsgFlushACK(
+ const HostResource& decoder, int32_t result) {
+ EnterPluginFromHostResource<PPB_VideoDecoder_API> enter(decoder);
+ if (enter.succeeded())
+ static_cast<VideoDecoder*>(enter.object())->FlushACK(result);
+}
+
+void PPB_VideoDecoder_Proxy::OnMsgResetACK(
+ const HostResource& decoder, int32_t result) {
+ EnterPluginFromHostResource<PPB_VideoDecoder_API> enter(decoder);
+ if (enter.succeeded())
+ static_cast<VideoDecoder*>(enter.object())->ResetACK(result);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppb_video_decoder_proxy.h b/chromium/ppapi/proxy/ppb_video_decoder_proxy.h
new file mode 100644
index 00000000000..e9127a7e63a
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_video_decoder_proxy.h
@@ -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.
+
+#ifndef PPAPI_PROXY_PPB_VIDEO_DECODER_PROXY_H_
+#define PPAPI_PROXY_PPB_VIDEO_DECODER_PROXY_H_
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/proxy_completion_callback_factory.h"
+#include "ppapi/shared_impl/ppb_video_decoder_shared.h"
+#include "ppapi/thunk/ppb_video_decoder_api.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPB_VideoDecoder_Proxy : public InterfaceProxy {
+ public:
+ PPB_VideoDecoder_Proxy(Dispatcher* dispatcher);
+ virtual ~PPB_VideoDecoder_Proxy();
+
+ // Creates a VideoDecoder object in the plugin process.
+ static PP_Resource CreateProxyResource(
+ PP_Instance instance,
+ PP_Resource graphics_context,
+ PP_VideoDecoder_Profile profile);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ static const ApiID kApiID = API_ID_PPB_VIDEO_DECODER_DEV;
+
+ private:
+ // Message handlers in the renderer process to receive messages from the
+ // plugin process.
+ void OnMsgCreate(PP_Instance instance,
+ const ppapi::HostResource& graphics_context,
+ PP_VideoDecoder_Profile profile,
+ ppapi::HostResource* result);
+ void OnMsgDecode(
+ const ppapi::HostResource& decoder,
+ const ppapi::HostResource& buffer, int32 id, uint32 size);
+ void OnMsgAssignPictureBuffers(
+ const ppapi::HostResource& decoder,
+ const std::vector<PP_PictureBuffer_Dev>& buffers);
+ void OnMsgReusePictureBuffer(
+ const ppapi::HostResource& decoder,
+ int32 picture_buffer_id);
+ void OnMsgFlush(const ppapi::HostResource& decoder);
+ void OnMsgReset(const ppapi::HostResource& decoder);
+ void OnMsgDestroy(const ppapi::HostResource& decoder);
+
+ // Send a message from the renderer process to the plugin process to tell it
+ // to run its callback.
+ void SendMsgEndOfBitstreamACKToPlugin(
+ int32_t result, const ppapi::HostResource& decoder, int32 id);
+ void SendMsgFlushACKToPlugin(
+ int32_t result, const ppapi::HostResource& decoder);
+ void SendMsgResetACKToPlugin(
+ int32_t result, const ppapi::HostResource& decoder);
+
+ // Message handlers in the plugin process to receive messages from the
+ // renderer process.
+ void OnMsgEndOfBitstreamACK(const ppapi::HostResource& decoder,
+ int32_t id, int32_t result);
+ void OnMsgFlushACK(const ppapi::HostResource& decoder, int32_t result);
+ void OnMsgResetACK(const ppapi::HostResource& decoder, int32_t result);
+
+ ProxyCompletionCallbackFactory<PPB_VideoDecoder_Proxy> callback_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_VideoDecoder_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPB_VIDEO_DECODER_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppb_x509_certificate_private_proxy.cc b/chromium/ppapi/proxy/ppb_x509_certificate_private_proxy.cc
new file mode 100644
index 00000000000..7a9b01343f5
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_x509_certificate_private_proxy.cc
@@ -0,0 +1,74 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppb_x509_certificate_private_proxy.h"
+
+#include "ppapi/c/private/ppb_x509_certificate_private.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+class X509CertificatePrivate : public PPB_X509Certificate_Private_Shared {
+ public:
+ X509CertificatePrivate(PP_Instance instance);
+ virtual ~X509CertificatePrivate();
+
+ virtual bool ParseDER(const std::vector<char>& der,
+ PPB_X509Certificate_Fields* result) OVERRIDE;
+
+ private:
+ void SendToBrowser(IPC::Message* msg);
+
+ DISALLOW_COPY_AND_ASSIGN(X509CertificatePrivate);
+};
+
+X509CertificatePrivate::X509CertificatePrivate(PP_Instance instance)
+ : PPB_X509Certificate_Private_Shared(OBJECT_IS_PROXY, instance) {
+}
+
+X509CertificatePrivate::~X509CertificatePrivate() {
+}
+
+bool X509CertificatePrivate::ParseDER(const std::vector<char>& der,
+ PPB_X509Certificate_Fields* result) {
+ bool succeeded = false;
+ SendToBrowser(
+ new PpapiHostMsg_PPBX509Certificate_ParseDER(der, &succeeded, result));
+ return succeeded;
+}
+
+void X509CertificatePrivate::SendToBrowser(IPC::Message* msg) {
+ PluginGlobals::Get()->GetBrowserSender()->Send(msg);
+}
+
+} // namespace
+
+//------------------------------------------------------------------------------
+
+PPB_X509Certificate_Private_Proxy::PPB_X509Certificate_Private_Proxy(
+ Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher) {
+}
+
+PPB_X509Certificate_Private_Proxy::~PPB_X509Certificate_Private_Proxy() {
+}
+
+// static
+PP_Resource PPB_X509Certificate_Private_Proxy::CreateProxyResource(
+ PP_Instance instance) {
+ return (new X509CertificatePrivate(instance))->GetReference();
+}
+
+bool PPB_X509Certificate_Private_Proxy::OnMessageReceived(
+ const IPC::Message& msg) {
+ return false;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppb_x509_certificate_private_proxy.h b/chromium/ppapi/proxy/ppb_x509_certificate_private_proxy.h
new file mode 100644
index 00000000000..4c51bab5617
--- /dev/null
+++ b/chromium/ppapi/proxy/ppb_x509_certificate_private_proxy.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPB_X509_CERTIFICATE_PRIVATE_PROXY_H_
+#define PPAPI_PROXY_PPB_X509_CERTIFICATE_PRIVATE_PROXY_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPB_X509Certificate_Private_Proxy
+ : public InterfaceProxy {
+ public:
+ explicit PPB_X509Certificate_Private_Proxy(Dispatcher* dispatcher);
+ virtual ~PPB_X509Certificate_Private_Proxy();
+ static PP_Resource CreateProxyResource(PP_Instance instance);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+
+ static const ApiID kApiID = API_ID_PPB_X509_CERTIFICATE_PRIVATE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PPB_X509Certificate_Private_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPB_X509_CERTIFICATE_PRIVATE_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppp_class_proxy.cc b/chromium/ppapi/proxy/ppp_class_proxy.cc
new file mode 100644
index 00000000000..3c28d0d54c0
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_class_proxy.cc
@@ -0,0 +1,396 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppp_class_proxy.h"
+
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/dev/ppp_class_deprecated.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/api_id.h"
+
+namespace ppapi {
+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) {
+ ObjectProxy* obj = reinterpret_cast<ObjectProxy*>(data);
+ if (!obj || !obj->dispatcher)
+ return NULL;
+ if (!obj->dispatcher->permissions().HasPermission(PERMISSION_DEV))
+ return NULL;
+ return obj;
+}
+
+bool HasProperty(void* object, PP_Var name, PP_Var* exception) {
+ ObjectProxy* obj = ToObjectProxy(object);
+ if (!obj)
+ return false;
+
+ bool result = false;
+ ReceiveSerializedException se(obj->dispatcher, exception);
+ obj->dispatcher->Send(new PpapiMsg_PPPClass_HasProperty(
+ API_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);
+ if (!obj)
+ return false;
+
+ bool result = false;
+ ReceiveSerializedException se(obj->dispatcher, exception);
+ obj->dispatcher->Send(new PpapiMsg_PPPClass_HasMethod(
+ API_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);
+ if (!obj)
+ return PP_MakeUndefined();
+
+ ReceiveSerializedException se(obj->dispatcher, exception);
+ ReceiveSerializedVarReturnValue result;
+ obj->dispatcher->Send(new PpapiMsg_PPPClass_GetProperty(
+ API_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);
+ if (!obj)
+ return;
+
+ ReceiveSerializedException se(obj->dispatcher, exception);
+ obj->dispatcher->Send(new PpapiMsg_PPPClass_SetProperty(
+ API_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);
+ if (!obj)
+ return;
+
+ ReceiveSerializedException se(obj->dispatcher, exception);
+ obj->dispatcher->Send(new PpapiMsg_PPPClass_RemoveProperty(
+ API_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);
+ if (!obj)
+ return PP_MakeUndefined();
+
+ 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(
+ API_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);
+ if (!obj)
+ return PP_MakeUndefined();
+
+ 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(
+ API_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);
+ if (!obj)
+ return;
+
+ obj->dispatcher->Send(new PpapiMsg_PPPClass_Deallocate(
+ API_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) {
+}
+
+PPP_Class_Proxy::~PPP_Class_Proxy() {
+}
+
+// static
+InterfaceProxy* PPP_Class_Proxy::Create(Dispatcher* dispatcher) {
+ return new PPP_Class_Proxy(dispatcher);
+}
+
+// static
+PP_Var PPP_Class_Proxy::CreateProxiedObject(const PPB_Var_Deprecated* var,
+ Dispatcher* dispatcher,
+ PP_Instance instance_id,
+ int64 ppp_class,
+ int64 class_data) {
+ ObjectProxy* object_proxy = new ObjectProxy(dispatcher,
+ ppp_class, class_data);
+ return var->CreateObject(instance_id, &class_interface, object_proxy);
+}
+
+// static
+PP_Bool PPP_Class_Proxy::IsInstanceOf(const PPB_Var_Deprecated* ppb_var_impl,
+ const PP_Var& var,
+ int64 ppp_class,
+ int64* ppp_class_data) {
+ void* proxied_object = NULL;
+ if (ppb_var_impl->IsInstanceOf(var,
+ &class_interface,
+ &proxied_object)) {
+ if (static_cast<ObjectProxy*>(proxied_object)->ppp_class == ppp_class) {
+ DCHECK(ppp_class_data);
+ *ppp_class_data = static_cast<ObjectProxy*>(proxied_object)->user_data;
+ return PP_TRUE;
+ }
+ }
+ return PP_FALSE;
+}
+
+bool PPP_Class_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ if (!dispatcher()->IsPlugin())
+ return false; // These messages are only valid from host->plugin.
+
+ 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) {
+ if (!ValidateUserData(ppp_class, object, &exception))
+ return;
+ *result = CallWhileUnlocked(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) {
+ if (!ValidateUserData(ppp_class, object, &exception))
+ return;
+ *result = CallWhileUnlocked(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) {
+ if (!ValidateUserData(ppp_class, object, &exception))
+ return;
+ result.Return(dispatcher(), CallWhileUnlocked(
+ ToPPPClass(ppp_class)->GetProperty,
+ ToUserData(object), property.Get(dispatcher()),
+ exception.OutParam(dispatcher())));
+}
+
+void PPP_Class_Proxy::OnMsgEnumerateProperties(
+ int64 ppp_class, int64 object,
+ std::vector<SerializedVar>* props,
+ SerializedVarOutParam exception) {
+ if (!ValidateUserData(ppp_class, object, &exception))
+ return;
+ NOTIMPLEMENTED();
+ // TODO(brettw) implement this.
+}
+
+void PPP_Class_Proxy::OnMsgSetProperty(int64 ppp_class, int64 object,
+ SerializedVarReceiveInput property,
+ SerializedVarReceiveInput value,
+ SerializedVarOutParam exception) {
+ if (!ValidateUserData(ppp_class, object, &exception))
+ return;
+ CallWhileUnlocked(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) {
+ if (!ValidateUserData(ppp_class, object, &exception))
+ return;
+ CallWhileUnlocked(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) {
+ if (!ValidateUserData(ppp_class, object, &exception))
+ return;
+ uint32_t arg_count = 0;
+ PP_Var* args = arg_vector.Get(dispatcher(), &arg_count);
+ result.Return(dispatcher(), CallWhileUnlocked(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) {
+ if (!ValidateUserData(ppp_class, object, &exception))
+ return;
+ uint32_t arg_count = 0;
+ PP_Var* args = arg_vector.Get(dispatcher(), &arg_count);
+ result.Return(dispatcher(), CallWhileUnlocked(
+ ToPPPClass(ppp_class)->Construct,
+ ToUserData(object), arg_count, args, exception.OutParam(dispatcher())));
+}
+
+void PPP_Class_Proxy::OnMsgDeallocate(int64 ppp_class, int64 object) {
+ if (!ValidateUserData(ppp_class, object, NULL))
+ return;
+ PluginGlobals::Get()->plugin_var_tracker()->PluginImplementedObjectDestroyed(
+ ToUserData(object));
+ CallWhileUnlocked(ToPPPClass(ppp_class)->Deallocate, ToUserData(object));
+}
+
+bool PPP_Class_Proxy::ValidateUserData(int64 ppp_class, int64 class_data,
+ SerializedVarOutParam* exception) {
+ if (!PluginGlobals::Get()->plugin_var_tracker()->ValidatePluginObjectCall(
+ ToPPPClass(ppp_class), ToUserData(class_data))) {
+ // Set the exception. This is so the caller will know about the error and
+ // also that we won't assert that somebody forgot to call OutParam on the
+ // output parameter. Although this exception of "1" won't be very useful
+ // this shouldn't happen in normal usage, only when the renderer is being
+ // malicious.
+ if (exception)
+ *exception->OutParam(dispatcher()) = PP_MakeInt32(1);
+ return false;
+ }
+ return true;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppp_class_proxy.h b/chromium/ppapi/proxy/ppp_class_proxy.h
new file mode 100644
index 00000000000..f890b3ddf44
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_class_proxy.h
@@ -0,0 +1,100 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPP_CLASS_PROXY_H_
+#define PPAPI_PROXY_PPP_CLASS_PROXY_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_Var_Deprecated;
+
+namespace ppapi {
+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.
+ explicit PPP_Class_Proxy(Dispatcher* dispatcher);
+ virtual ~PPP_Class_Proxy();
+
+ // Factory function used for registration (normal code can just use the
+ // constructor).
+ static InterfaceProxy* Create(Dispatcher* dispatcher);
+
+ // 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_Instance instance_id,
+ int64 ppp_class,
+ int64 class_data);
+
+ static PP_Bool IsInstanceOf(const PPB_Var_Deprecated* ppb_var_impl,
+ const PP_Var& var,
+ int64 ppp_class,
+ int64* ppp_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<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);
+
+ // Returns true if the given class/data points to a plugin-implemented
+ // object. On failure, the exception, if non-NULL, will also be set.
+ bool ValidateUserData(int64 ppp_class, int64 class_data,
+ SerializedVarOutParam* exception);
+
+ DISALLOW_COPY_AND_ASSIGN(PPP_Class_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPP_CLASS_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppp_content_decryptor_private_proxy.cc b/chromium/ppapi/proxy/ppp_content_decryptor_private_proxy.cc
new file mode 100644
index 00000000000..f986e7f8d72
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_content_decryptor_private_proxy.cc
@@ -0,0 +1,581 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppp_content_decryptor_private_proxy.h"
+
+#include "base/platform_file.h"
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/proxy/content_decryptor_private_serializer.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_buffer_proxy.h"
+#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/shared_impl/scoped_pp_resource.h"
+#include "ppapi/shared_impl/var_tracker.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_buffer_api.h"
+#include "ppapi/thunk/ppb_instance_api.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_Buffer_API;
+using ppapi::thunk::PPB_Instance_API;
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+PP_Bool DescribeHostBufferResource(PP_Resource resource, uint32_t* size) {
+ EnterResourceNoLock<PPB_Buffer_API> enter(resource, true);
+ if (enter.failed())
+ return PP_FALSE;
+ return enter.object()->Describe(size);
+}
+
+// TODO(dmichael): Refactor so this handle sharing code is in one place.
+PP_Bool ShareHostBufferResourceToPlugin(
+ HostDispatcher* dispatcher,
+ PP_Resource resource,
+ base::SharedMemoryHandle* shared_mem_handle) {
+ if (!dispatcher || resource == 0 || !shared_mem_handle)
+ return PP_FALSE;
+ EnterResourceNoLock<PPB_Buffer_API> enter(resource, true);
+ if (enter.failed())
+ return PP_FALSE;
+ int handle;
+ int32_t result = enter.object()->GetSharedMemory(&handle);
+ if (result != PP_OK)
+ return PP_FALSE;
+ base::PlatformFile platform_file =
+ #if defined(OS_WIN)
+ reinterpret_cast<HANDLE>(static_cast<intptr_t>(handle));
+ #elif defined(OS_POSIX)
+ handle;
+ #else
+ #error Not implemented.
+ #endif
+
+ *shared_mem_handle = dispatcher->ShareHandleWithRemote(platform_file, false);
+ return PP_TRUE;
+}
+
+// SerializedVarReceiveInput will decrement the reference count, but we want
+// to give the recipient a reference. This utility function takes care of that
+// work for the message handlers defined below.
+PP_Var ExtractReceivedVarAndAddRef(Dispatcher* dispatcher,
+ SerializedVarReceiveInput* serialized_var) {
+ PP_Var var = serialized_var->Get(dispatcher);
+ PpapiGlobals::Get()->GetVarTracker()->AddRefVar(var);
+ return var;
+}
+
+bool InitializePppDecryptorBuffer(PP_Instance instance,
+ HostDispatcher* dispatcher,
+ PP_Resource resource,
+ PPPDecryptor_Buffer* buffer) {
+ if (!buffer) {
+ NOTREACHED();
+ return false;
+ }
+
+ if (resource == 0) {
+ buffer->resource = HostResource();
+ buffer->handle = base::SharedMemoryHandle();
+ buffer->size = 0;
+ return true;
+ }
+
+ HostResource host_resource;
+ host_resource.SetHostResource(instance, resource);
+
+ uint32_t size = 0;
+ if (DescribeHostBufferResource(resource, &size) == PP_FALSE)
+ return false;
+
+ base::SharedMemoryHandle handle;
+ if (ShareHostBufferResourceToPlugin(dispatcher,
+ resource,
+ &handle) == PP_FALSE)
+ return false;
+
+ buffer->resource = host_resource;
+ buffer->handle = handle;
+ buffer->size = size;
+ return true;
+}
+
+void GenerateKeyRequest(PP_Instance instance,
+ PP_Var key_system,
+ PP_Var type,
+ PP_Var init_data) {
+ HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ if (!dispatcher) {
+ NOTREACHED();
+ return;
+ }
+
+ dispatcher->Send(
+ new PpapiMsg_PPPContentDecryptor_GenerateKeyRequest(
+ API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
+ instance,
+ SerializedVarSendInput(dispatcher, key_system),
+ SerializedVarSendInput(dispatcher, type),
+ SerializedVarSendInput(dispatcher, init_data)));
+}
+
+void AddKey(PP_Instance instance,
+ PP_Var session_id,
+ PP_Var key,
+ PP_Var init_data) {
+ HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ if (!dispatcher) {
+ NOTREACHED();
+ return;
+ }
+
+ dispatcher->Send(
+ new PpapiMsg_PPPContentDecryptor_AddKey(
+ API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
+ instance,
+ SerializedVarSendInput(dispatcher, session_id),
+ SerializedVarSendInput(dispatcher, key),
+ SerializedVarSendInput(dispatcher, init_data)));
+}
+
+void CancelKeyRequest(PP_Instance instance, PP_Var session_id) {
+ HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ if (!dispatcher) {
+ NOTREACHED();
+ return;
+ }
+
+ dispatcher->Send(
+ new PpapiMsg_PPPContentDecryptor_CancelKeyRequest(
+ API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
+ instance,
+ SerializedVarSendInput(dispatcher, session_id)));
+}
+
+void Decrypt(PP_Instance instance,
+ PP_Resource encrypted_block,
+ const PP_EncryptedBlockInfo* encrypted_block_info) {
+ HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ if (!dispatcher) {
+ NOTREACHED();
+ return;
+ }
+
+ PPPDecryptor_Buffer buffer;
+ if (!InitializePppDecryptorBuffer(instance,
+ dispatcher,
+ encrypted_block,
+ &buffer)) {
+ NOTREACHED();
+ return;
+ }
+
+ std::string serialized_block_info;
+ if (!SerializeBlockInfo(*encrypted_block_info, &serialized_block_info)) {
+ NOTREACHED();
+ return;
+ }
+
+ // 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 |encryped_block| here.
+ PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_block);
+
+ dispatcher->Send(
+ new PpapiMsg_PPPContentDecryptor_Decrypt(
+ API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
+ instance,
+ buffer,
+ serialized_block_info));
+}
+
+void InitializeAudioDecoder(
+ PP_Instance instance,
+ const PP_AudioDecoderConfig* decoder_config,
+ PP_Resource extra_data_buffer) {
+ HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ if (!dispatcher) {
+ NOTREACHED();
+ return;
+ }
+
+ std::string serialized_decoder_config;
+ if (!SerializeBlockInfo(*decoder_config, &serialized_decoder_config)) {
+ NOTREACHED();
+ return;
+ }
+
+ PPPDecryptor_Buffer buffer;
+ if (!InitializePppDecryptorBuffer(instance,
+ dispatcher,
+ extra_data_buffer,
+ &buffer)) {
+ NOTREACHED();
+ return;
+ }
+
+ // 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 |extra_data_buffer| here.
+ PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer);
+
+ dispatcher->Send(
+ new PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder(
+ API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
+ instance,
+ serialized_decoder_config,
+ buffer));
+}
+
+void InitializeVideoDecoder(
+ PP_Instance instance,
+ const PP_VideoDecoderConfig* decoder_config,
+ PP_Resource extra_data_buffer) {
+ HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ if (!dispatcher) {
+ NOTREACHED();
+ return;
+ }
+
+ std::string serialized_decoder_config;
+ if (!SerializeBlockInfo(*decoder_config, &serialized_decoder_config)) {
+ NOTREACHED();
+ return;
+ }
+
+ PPPDecryptor_Buffer buffer;
+ if (!InitializePppDecryptorBuffer(instance,
+ dispatcher,
+ extra_data_buffer,
+ &buffer)) {
+ NOTREACHED();
+ return;
+ }
+
+ // 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 |extra_data_buffer| here.
+ PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(extra_data_buffer);
+
+ dispatcher->Send(
+ new PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder(
+ API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
+ instance,
+ serialized_decoder_config,
+ buffer));
+}
+
+
+void DeinitializeDecoder(PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id) {
+ HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ if (!dispatcher) {
+ NOTREACHED();
+ return;
+ }
+
+ dispatcher->Send(
+ new PpapiMsg_PPPContentDecryptor_DeinitializeDecoder(
+ API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
+ instance,
+ decoder_type,
+ request_id));
+}
+
+void ResetDecoder(PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id) {
+ HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ if (!dispatcher) {
+ NOTREACHED();
+ return;
+ }
+
+ dispatcher->Send(
+ new PpapiMsg_PPPContentDecryptor_ResetDecoder(
+ API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
+ instance,
+ decoder_type,
+ request_id));
+}
+
+void DecryptAndDecode(PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ PP_Resource encrypted_buffer,
+ const PP_EncryptedBlockInfo* encrypted_block_info) {
+ HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ if (!dispatcher) {
+ NOTREACHED();
+ return;
+ }
+
+ PPPDecryptor_Buffer buffer;
+ if (!InitializePppDecryptorBuffer(instance,
+ dispatcher,
+ encrypted_buffer,
+ &buffer)) {
+ NOTREACHED();
+ return;
+ }
+
+ std::string serialized_block_info;
+ if (!SerializeBlockInfo(*encrypted_block_info, &serialized_block_info)) {
+ NOTREACHED();
+ return;
+ }
+
+ // 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 |encrypted_buffer| here.
+ PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(encrypted_buffer);
+
+ dispatcher->Send(
+ new PpapiMsg_PPPContentDecryptor_DecryptAndDecode(
+ API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
+ instance,
+ decoder_type,
+ buffer,
+ serialized_block_info));
+}
+
+static const PPP_ContentDecryptor_Private content_decryptor_interface = {
+ &GenerateKeyRequest,
+ &AddKey,
+ &CancelKeyRequest,
+ &Decrypt,
+ &InitializeAudioDecoder,
+ &InitializeVideoDecoder,
+ &DeinitializeDecoder,
+ &ResetDecoder,
+ &DecryptAndDecode
+};
+
+} // namespace
+
+PPP_ContentDecryptor_Private_Proxy::PPP_ContentDecryptor_Private_Proxy(
+ Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher),
+ ppp_decryptor_impl_(NULL) {
+ if (dispatcher->IsPlugin()) {
+ ppp_decryptor_impl_ = static_cast<const PPP_ContentDecryptor_Private*>(
+ dispatcher->local_get_interface()(
+ PPP_CONTENTDECRYPTOR_PRIVATE_INTERFACE));
+ }
+}
+
+PPP_ContentDecryptor_Private_Proxy::~PPP_ContentDecryptor_Private_Proxy() {
+}
+
+// static
+const PPP_ContentDecryptor_Private*
+ PPP_ContentDecryptor_Private_Proxy::GetProxyInterface() {
+ return &content_decryptor_interface;
+}
+
+bool PPP_ContentDecryptor_Private_Proxy::OnMessageReceived(
+ const IPC::Message& msg) {
+ if (!dispatcher()->IsPlugin())
+ return false; // These are only valid from host->plugin.
+ // Don't allow the plugin to send these to the host.
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPP_ContentDecryptor_Private_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_GenerateKeyRequest,
+ OnMsgGenerateKeyRequest)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_AddKey,
+ OnMsgAddKey)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_CancelKeyRequest,
+ OnMsgCancelKeyRequest)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_Decrypt,
+ OnMsgDecrypt)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeAudioDecoder,
+ OnMsgInitializeAudioDecoder)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_InitializeVideoDecoder,
+ OnMsgInitializeVideoDecoder)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DeinitializeDecoder,
+ OnMsgDeinitializeDecoder)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_ResetDecoder,
+ OnMsgResetDecoder)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPContentDecryptor_DecryptAndDecode,
+ OnMsgDecryptAndDecode)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ DCHECK(handled);
+ return handled;
+}
+
+void PPP_ContentDecryptor_Private_Proxy::OnMsgGenerateKeyRequest(
+ PP_Instance instance,
+ SerializedVarReceiveInput key_system,
+ SerializedVarReceiveInput type,
+ SerializedVarReceiveInput init_data) {
+ if (ppp_decryptor_impl_) {
+ CallWhileUnlocked(ppp_decryptor_impl_->GenerateKeyRequest,
+ instance,
+ ExtractReceivedVarAndAddRef(dispatcher(), &key_system),
+ ExtractReceivedVarAndAddRef(dispatcher(), &type),
+ ExtractReceivedVarAndAddRef(dispatcher(), &init_data));
+ }
+}
+
+void PPP_ContentDecryptor_Private_Proxy::OnMsgAddKey(
+ PP_Instance instance,
+ SerializedVarReceiveInput session_id,
+ SerializedVarReceiveInput key,
+ SerializedVarReceiveInput init_data) {
+ if (ppp_decryptor_impl_) {
+ CallWhileUnlocked(ppp_decryptor_impl_->AddKey,
+ instance,
+ ExtractReceivedVarAndAddRef(dispatcher(), &session_id),
+ ExtractReceivedVarAndAddRef(dispatcher(), &key),
+ ExtractReceivedVarAndAddRef(dispatcher(), &init_data));
+ }
+}
+
+void PPP_ContentDecryptor_Private_Proxy::OnMsgCancelKeyRequest(
+ PP_Instance instance,
+ SerializedVarReceiveInput session_id) {
+ if (ppp_decryptor_impl_) {
+ CallWhileUnlocked(ppp_decryptor_impl_->CancelKeyRequest,
+ instance,
+ ExtractReceivedVarAndAddRef(dispatcher(), &session_id));
+ }
+}
+
+void PPP_ContentDecryptor_Private_Proxy::OnMsgDecrypt(
+ PP_Instance instance,
+ const PPPDecryptor_Buffer& encrypted_buffer,
+ const std::string& serialized_block_info) {
+ ScopedPPResource plugin_resource(
+ ScopedPPResource::PassRef(),
+ PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer.resource,
+ encrypted_buffer.handle,
+ encrypted_buffer.size));
+ if (ppp_decryptor_impl_) {
+ PP_EncryptedBlockInfo block_info;
+ if (!DeserializeBlockInfo(serialized_block_info, &block_info))
+ return;
+ CallWhileUnlocked(ppp_decryptor_impl_->Decrypt,
+ instance,
+ plugin_resource.get(),
+ const_cast<const PP_EncryptedBlockInfo*>(&block_info));
+ }
+}
+
+void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeAudioDecoder(
+ PP_Instance instance,
+ const std::string& serialized_decoder_config,
+ const PPPDecryptor_Buffer& extra_data_buffer) {
+ ScopedPPResource plugin_resource;
+ if (extra_data_buffer.size > 0) {
+ plugin_resource = ScopedPPResource(
+ ScopedPPResource::PassRef(),
+ PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer.resource,
+ extra_data_buffer.handle,
+ extra_data_buffer.size));
+ }
+
+ PP_AudioDecoderConfig decoder_config;
+ if (!DeserializeBlockInfo(serialized_decoder_config, &decoder_config))
+ return;
+
+ if (ppp_decryptor_impl_) {
+ CallWhileUnlocked(
+ ppp_decryptor_impl_->InitializeAudioDecoder,
+ instance,
+ const_cast<const PP_AudioDecoderConfig*>(&decoder_config),
+ plugin_resource.get());
+ }
+}
+
+void PPP_ContentDecryptor_Private_Proxy::OnMsgInitializeVideoDecoder(
+ PP_Instance instance,
+ const std::string& serialized_decoder_config,
+ const PPPDecryptor_Buffer& extra_data_buffer) {
+ ScopedPPResource plugin_resource;
+ if (extra_data_buffer.resource.host_resource() != 0) {
+ plugin_resource = ScopedPPResource(
+ ScopedPPResource::PassRef(),
+ PPB_Buffer_Proxy::AddProxyResource(extra_data_buffer.resource,
+ extra_data_buffer.handle,
+ extra_data_buffer.size));
+ }
+
+ PP_VideoDecoderConfig decoder_config;
+ if (!DeserializeBlockInfo(serialized_decoder_config, &decoder_config))
+ return;
+
+ if (ppp_decryptor_impl_) {
+ CallWhileUnlocked(
+ ppp_decryptor_impl_->InitializeVideoDecoder,
+ instance,
+ const_cast<const PP_VideoDecoderConfig*>(&decoder_config),
+ plugin_resource.get());
+ }
+}
+
+void PPP_ContentDecryptor_Private_Proxy::OnMsgDeinitializeDecoder(
+ PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id) {
+ if (ppp_decryptor_impl_) {
+ CallWhileUnlocked(
+ ppp_decryptor_impl_->DeinitializeDecoder,
+ instance,
+ decoder_type,
+ request_id);
+ }
+}
+
+void PPP_ContentDecryptor_Private_Proxy::OnMsgResetDecoder(
+ PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id) {
+ if (ppp_decryptor_impl_) {
+ CallWhileUnlocked(
+ ppp_decryptor_impl_->ResetDecoder,
+ instance,
+ decoder_type,
+ request_id);
+ }
+}
+
+void PPP_ContentDecryptor_Private_Proxy::OnMsgDecryptAndDecode(
+ PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ const PPPDecryptor_Buffer& encrypted_buffer,
+ const std::string& serialized_block_info) {
+ ScopedPPResource plugin_resource;
+ if (encrypted_buffer.resource.host_resource() != 0) {
+ plugin_resource = ScopedPPResource(
+ ScopedPPResource::PassRef(),
+ PPB_Buffer_Proxy::AddProxyResource(encrypted_buffer.resource,
+ encrypted_buffer.handle,
+ encrypted_buffer.size));
+ }
+
+ if (ppp_decryptor_impl_) {
+ PP_EncryptedBlockInfo block_info;
+ if (!DeserializeBlockInfo(serialized_block_info, &block_info))
+ return;
+ CallWhileUnlocked(
+ ppp_decryptor_impl_->DecryptAndDecode,
+ instance,
+ decoder_type,
+ plugin_resource.get(),
+ const_cast<const PP_EncryptedBlockInfo*>(&block_info));
+ }
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppp_content_decryptor_private_proxy.h b/chromium/ppapi/proxy/ppp_content_decryptor_private_proxy.h
new file mode 100644
index 00000000000..5e7ecc85dba
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_content_decryptor_private_proxy.h
@@ -0,0 +1,74 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPP_CONTENT_DECRYPTOR_PRIVATE_PROXY_H_
+#define PPAPI_PROXY_PPP_CONTENT_DECRYPTOR_PRIVATE_PROXY_H_
+
+#include <string>
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/private/ppp_content_decryptor_private.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/serialized_structs.h"
+#include "ppapi/shared_impl/host_resource.h"
+
+namespace ppapi {
+namespace proxy {
+
+class SerializedVarReceiveInput;
+
+class PPP_ContentDecryptor_Private_Proxy : public InterfaceProxy {
+ public:
+ explicit PPP_ContentDecryptor_Private_Proxy(Dispatcher* dispatcher);
+ virtual ~PPP_ContentDecryptor_Private_Proxy();
+
+ static const PPP_ContentDecryptor_Private* GetProxyInterface();
+
+ private:
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ // Message handlers.
+ void OnMsgGenerateKeyRequest(PP_Instance instance,
+ SerializedVarReceiveInput key_system,
+ SerializedVarReceiveInput type,
+ SerializedVarReceiveInput init_data);
+ void OnMsgAddKey(PP_Instance instance,
+ SerializedVarReceiveInput session_id,
+ SerializedVarReceiveInput key,
+ SerializedVarReceiveInput init_data);
+ void OnMsgCancelKeyRequest(PP_Instance instance,
+ SerializedVarReceiveInput session_id);
+ void OnMsgDecrypt(PP_Instance instance,
+ const PPPDecryptor_Buffer& encrypted_buffer,
+ const std::string& serialized_encrypted_block_info);
+ void OnMsgInitializeAudioDecoder(
+ PP_Instance instance,
+ const std::string& decoder_config,
+ const PPPDecryptor_Buffer& extra_data_buffer);
+ void OnMsgInitializeVideoDecoder(
+ PP_Instance instance,
+ const std::string& decoder_config,
+ const PPPDecryptor_Buffer& extra_data_buffer);
+ void OnMsgDeinitializeDecoder(PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id);
+ void OnMsgResetDecoder(PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id);
+ void OnMsgDecryptAndDecode(
+ PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ const PPPDecryptor_Buffer& encrypted_buffer,
+ const std::string& serialized_encrypted_block_info);
+
+ const PPP_ContentDecryptor_Private* ppp_decryptor_impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPP_ContentDecryptor_Private_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPP_CONTENT_DECRYPTOR_PRIVATE_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppp_graphics_3d_proxy.cc b/chromium/ppapi/proxy/ppp_graphics_3d_proxy.cc
new file mode 100644
index 00000000000..ee00a925ed0
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_graphics_3d_proxy.cc
@@ -0,0 +1,81 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppp_graphics_3d_proxy.h"
+
+#include "ppapi/c/ppp_graphics_3d.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+#if !defined(OS_NACL)
+void ContextLost(PP_Instance instance) {
+ HostDispatcher::GetForInstance(instance)->Send(
+ new PpapiMsg_PPPGraphics3D_ContextLost(API_ID_PPP_GRAPHICS_3D, instance));
+}
+
+static const PPP_Graphics3D graphics_3d_interface = {
+ &ContextLost
+};
+#else
+// The NaCl plugin doesn't need the host side interface - stub it out.
+static const PPP_Graphics3D graphics_3d_interface = {};
+#endif // !defined(OS_NACL)
+
+InterfaceProxy* CreateGraphics3DProxy(Dispatcher* dispatcher) {
+ return new PPP_Graphics3D_Proxy(dispatcher);
+}
+
+} // namespace
+
+PPP_Graphics3D_Proxy::PPP_Graphics3D_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher),
+ ppp_graphics_3d_impl_(NULL) {
+ if (dispatcher->IsPlugin()) {
+ ppp_graphics_3d_impl_ = static_cast<const PPP_Graphics3D*>(
+ dispatcher->local_get_interface()(PPP_GRAPHICS_3D_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_INTERFACE,
+ API_ID_PPP_GRAPHICS_3D,
+ false,
+ &CreateGraphics3DProxy,
+ };
+ return &info;
+}
+
+bool PPP_Graphics3D_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ if (!dispatcher()->IsPlugin())
+ return false;
+
+ 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_impl_)
+ CallWhileUnlocked(ppp_graphics_3d_impl_->Graphics3DContextLost, instance);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppp_graphics_3d_proxy.h b/chromium/ppapi/proxy/ppp_graphics_3d_proxy.h
new file mode 100644
index 00000000000..9b4d7a0fe67
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_graphics_3d_proxy.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPP_GRAPHICS_3D_PROXY_H_
+#define PPAPI_PROXY_PPP_GRAPHICS_3D_PROXY_H_
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/ppp_graphics_3d.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/shared_impl/host_resource.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPP_Graphics3D_Proxy : public InterfaceProxy {
+ public:
+ PPP_Graphics3D_Proxy(Dispatcher* dispatcher);
+ virtual ~PPP_Graphics3D_Proxy();
+
+ static const Info* GetInfo();
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgContextLost(PP_Instance instance);
+
+ // When this proxy is in the plugin side, this value caches the interface
+ // pointer so we don't have to retrieve it from the dispatcher each time.
+ // In the host, this value is always NULL.
+ const PPP_Graphics3D* ppp_graphics_3d_impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPP_Graphics3D_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPP_GRAPHICS_3D_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppp_input_event_proxy.cc b/chromium/ppapi/proxy/ppp_input_event_proxy.cc
new file mode 100644
index 00000000000..8302dfd12db
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_input_event_proxy.cc
@@ -0,0 +1,123 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppp_input_event_proxy.h"
+
+#include "ppapi/c/ppp_input_event.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/ppb_input_event_shared.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_input_event_api.h"
+
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_InputEvent_API;
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+#if !defined(OS_NACL)
+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(
+ API_ID_PPP_INPUT_EVENT, instance, data, &result));
+ } else {
+ dispatcher->Send(new PpapiMsg_PPPInputEvent_HandleInputEvent(
+ API_ID_PPP_INPUT_EVENT, instance, data));
+ }
+ return result;
+}
+
+static const PPP_InputEvent input_event_interface = {
+ &HandleInputEvent
+};
+#else
+// The NaCl plugin doesn't need the host side interface - stub it out.
+static const PPP_InputEvent input_event_interface = {};
+#endif // !defined(OS_NACL)
+
+InterfaceProxy* CreateInputEventProxy(Dispatcher* dispatcher) {
+ return new PPP_InputEvent_Proxy(dispatcher);
+}
+
+} // namespace
+
+PPP_InputEvent_Proxy::PPP_InputEvent_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher),
+ ppp_input_event_impl_(NULL) {
+ if (dispatcher->IsPlugin()) {
+ ppp_input_event_impl_ = static_cast<const PPP_InputEvent*>(
+ dispatcher->local_get_interface()(PPP_INPUT_EVENT_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,
+ API_ID_PPP_INPUT_EVENT,
+ false,
+ &CreateInputEventProxy,
+ };
+ return &info;
+}
+
+bool PPP_InputEvent_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ if (!dispatcher()->IsPlugin())
+ return false;
+
+ 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) {
+ scoped_refptr<PPB_InputEvent_Shared> resource(new PPB_InputEvent_Shared(
+ OBJECT_IS_PROXY, instance, data));
+ CallWhileUnlocked(ppp_input_event_impl_->HandleInputEvent,
+ instance,
+ resource->pp_resource());
+}
+
+void PPP_InputEvent_Proxy::OnMsgHandleFilteredInputEvent(
+ PP_Instance instance,
+ const InputEventData& data,
+ PP_Bool* result) {
+ scoped_refptr<PPB_InputEvent_Shared> resource(new PPB_InputEvent_Shared(
+ OBJECT_IS_PROXY, instance, data));
+ *result = CallWhileUnlocked(ppp_input_event_impl_->HandleInputEvent,
+ instance,
+ resource->pp_resource());
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppp_input_event_proxy.h b/chromium/ppapi/proxy/ppp_input_event_proxy.h
new file mode 100644
index 00000000000..a7cc05455c9
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_input_event_proxy.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPP_INPUT_EVENT_PROXY_H_
+#define PPAPI_PROXY_PPP_INPUT_EVENT_PROXY_H_
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/ppp_input_event.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+namespace ppapi {
+
+struct InputEventData;
+
+namespace proxy {
+
+class PPP_InputEvent_Proxy : public InterfaceProxy {
+ public:
+ PPP_InputEvent_Proxy(Dispatcher* dispatcher);
+ virtual ~PPP_InputEvent_Proxy();
+
+ static const Info* GetInfo();
+
+ // 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);
+
+ // When this proxy is in the plugin side, this value caches the interface
+ // pointer so we don't have to retrieve it from the dispatcher each time.
+ // In the host, this value is always NULL.
+ const PPP_InputEvent* ppp_input_event_impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPP_InputEvent_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPP_INPUT_EVENT_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppp_instance_private_proxy.cc b/chromium/ppapi/proxy/ppp_instance_private_proxy.cc
new file mode 100644
index 00000000000..1d8b8d753ca
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_instance_private_proxy.cc
@@ -0,0 +1,89 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/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"
+#include "ppapi/shared_impl/proxy_lock.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+PP_Var GetInstanceObject(PP_Instance instance) {
+ Dispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ if (!dispatcher->permissions().HasPermission(PERMISSION_PRIVATE))
+ return PP_MakeUndefined();
+
+ ReceiveSerializedVarReturnValue result;
+ dispatcher->Send(new PpapiMsg_PPPInstancePrivate_GetInstanceObject(
+ API_ID_PPP_INSTANCE_PRIVATE, instance, &result));
+ return result.Return(dispatcher);
+}
+
+static const PPP_Instance_Private instance_private_interface = {
+ &GetInstanceObject
+};
+
+InterfaceProxy* CreateInstancePrivateProxy(Dispatcher* dispatcher) {
+ return new PPP_Instance_Private_Proxy(dispatcher);
+}
+
+} // namespace
+
+PPP_Instance_Private_Proxy::PPP_Instance_Private_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher),
+ ppp_instance_private_impl_(NULL) {
+ if (dispatcher->IsPlugin()) {
+ ppp_instance_private_impl_ = static_cast<const PPP_Instance_Private*>(
+ dispatcher->local_get_interface()(PPP_INSTANCE_PRIVATE_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,
+ API_ID_PPP_INSTANCE_PRIVATE,
+ false,
+ &CreateInstancePrivateProxy,
+ };
+ return &info;
+}
+
+bool PPP_Instance_Private_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ if (!dispatcher()->IsPlugin())
+ return false;
+
+ 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(),
+ CallWhileUnlocked(ppp_instance_private_impl_->GetInstanceObject,
+ instance));
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppp_instance_private_proxy.h b/chromium/ppapi/proxy/ppp_instance_private_proxy.h
new file mode 100644
index 00000000000..60d5ea9f1f3
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_instance_private_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_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/c/private/ppp_instance_private.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/shared_impl/host_resource.h"
+
+namespace ppapi {
+namespace proxy {
+
+class SerializedVarReturnValue;
+
+class PPP_Instance_Private_Proxy : public InterfaceProxy {
+ public:
+ PPP_Instance_Private_Proxy(Dispatcher* dispatcher);
+ virtual ~PPP_Instance_Private_Proxy();
+
+ static const Info* GetInfo();
+
+ private:
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ // Message handlers.
+ void OnMsgGetInstanceObject(PP_Instance instance,
+ SerializedVarReturnValue result);
+
+ // When this proxy is in the plugin side, this value caches the interface
+ // pointer so we don't have to retrieve it from the dispatcher each time.
+ // In the host, this value is always NULL.
+ const PPP_Instance_Private* ppp_instance_private_impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPP_Instance_Private_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPP_INSTANCE_PRIVATE_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppp_instance_private_proxy_unittest.cc b/chromium/ppapi/proxy/ppp_instance_private_proxy_unittest.cc
new file mode 100644
index 00000000000..abafa87d0e8
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_instance_private_proxy_unittest.cc
@@ -0,0 +1,210 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "base/test/test_timeouts.h"
+#include "base/time/time.h"
+#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/dev/ppp_class_deprecated.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/c/ppp_instance.h"
+#include "ppapi/c/private/ppp_instance_private.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/interface_list.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+#include "ppapi/shared_impl/ppapi_permissions.h"
+#include "ppapi/shared_impl/ppb_var_shared.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+
+// A fake version of NPObjectVar for testing.
+class NPObjectVar : public ppapi::Var {
+ public:
+ NPObjectVar() {}
+ virtual ~NPObjectVar() {}
+
+ // Var overrides.
+ virtual NPObjectVar* AsNPObjectVar() OVERRIDE { return this; }
+ virtual PP_VarType GetType() const OVERRIDE { return PP_VARTYPE_OBJECT; }
+};
+
+namespace proxy {
+
+namespace {
+const PP_Instance kInstance = 0xdeadbeef;
+
+PP_Var GetPPVarNoAddRef(Var* var) {
+ PP_Var var_to_return = var->GetPPVar();
+ PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(var_to_return);
+ return var_to_return;
+}
+
+PluginDispatcher* plugin_dispatcher = NULL;
+// Return the plugin-side proxy for PPB_Var_Deprecated.
+const PPB_Var_Deprecated* plugin_var_deprecated_if() {
+ // The test code must set the plugin dispatcher.
+ CHECK(plugin_dispatcher);
+ // Grab the plugin-side proxy for PPB_Var_Deprecated (for CreateObject).
+ return static_cast<const PPB_Var_Deprecated*>(
+ plugin_dispatcher->GetBrowserInterface(
+ PPB_VAR_DEPRECATED_INTERFACE));
+}
+
+// Mock PPP_Instance_Private.
+PP_Var instance_obj;
+PP_Var GetInstanceObject(PP_Instance /*instance*/) {
+ // The 1 ref we got from CreateObject will be passed to the host. We want to
+ // have a ref of our own.
+ printf("GetInstanceObject called\n");
+ plugin_var_deprecated_if()->AddRef(instance_obj);
+ return instance_obj;
+}
+
+PPP_Instance_Private ppp_instance_private_mock = {
+ &GetInstanceObject
+};
+
+// We need to pass in a |PPP_Class_Deprecated| to
+// |PPB_Var_Deprecated->CreateObject| for a mock |Deallocate| method.
+void Deallocate(void* object) {
+}
+
+const PPP_Class_Deprecated ppp_class_deprecated_mock = {
+ NULL, // HasProperty
+ NULL, // HasMethod
+ NULL, // GetProperty
+ NULL, // GetAllPropertyNames
+ NULL, // SetProperty
+ NULL, // RemoveProperty
+ NULL, // Call
+ NULL, // Construct
+ &Deallocate
+};
+
+
+// We need to mock PPP_Instance, so that we can create and destroy the pretend
+// instance that PPP_Instance_Private uses.
+PP_Bool DidCreate(PP_Instance /*instance*/, uint32_t /*argc*/,
+ const char* /*argn*/[], const char* /*argv*/[]) {
+ // Create an object var. This should exercise the typical path for creating
+ // instance objects.
+ instance_obj =
+ plugin_var_deprecated_if()->CreateObject(kInstance,
+ &ppp_class_deprecated_mock,
+ NULL);
+ return PP_TRUE;
+}
+
+void DidDestroy(PP_Instance /*instance*/) {
+ // Decrement the reference count for our instance object. It should be
+ // deleted.
+ plugin_var_deprecated_if()->Release(instance_obj);
+}
+
+PPP_Instance_1_0 ppp_instance_mock = { &DidCreate, &DidDestroy };
+
+// Mock PPB_Var_Deprecated, so that we can emulate creating an Object Var.
+PP_Var CreateObject(PP_Instance /*instance*/,
+ const PPP_Class_Deprecated* /*ppp_class*/,
+ void* /*ppp_class_data*/) {
+ NPObjectVar* obj_var = new NPObjectVar;
+ return obj_var->GetPPVar();
+}
+
+const PPB_Var_Deprecated ppb_var_deprecated_mock = {
+ PPB_Var_Shared::GetVarInterface1_0()->AddRef,
+ PPB_Var_Shared::GetVarInterface1_0()->Release,
+ PPB_Var_Shared::GetVarInterface1_0()->VarFromUtf8,
+ PPB_Var_Shared::GetVarInterface1_0()->VarToUtf8,
+ NULL, // HasProperty
+ NULL, // HasMethod
+ NULL, // GetProperty
+ NULL, // EnumerateProperties
+ NULL, // SetProperty
+ NULL, // RemoveProperty
+ NULL, // Call
+ NULL, // Construct
+ NULL, // IsInstanceOf
+ &CreateObject
+};
+
+class PPP_Instance_Private_ProxyTest : public TwoWayTest {
+ public:
+ PPP_Instance_Private_ProxyTest()
+ : TwoWayTest(TwoWayTest::TEST_PPP_INTERFACE) {
+ plugin().RegisterTestInterface(PPP_INSTANCE_PRIVATE_INTERFACE,
+ &ppp_instance_private_mock);
+ plugin().RegisterTestInterface(PPP_INSTANCE_INTERFACE_1_0,
+ &ppp_instance_mock);
+ host().RegisterTestInterface(PPB_VAR_DEPRECATED_INTERFACE,
+ &ppb_var_deprecated_mock);
+ }
+};
+
+} // namespace
+
+TEST_F(PPP_Instance_Private_ProxyTest, PPPInstancePrivate) {
+ // This test controls its own instance; we can't use the one that
+ // PluginProxyTestHarness provides.
+ ASSERT_NE(kInstance, pp_instance());
+ HostDispatcher::SetForInstance(kInstance, host().host_dispatcher());
+
+ // Requires dev interfaces.
+ InterfaceList::SetProcessGlobalPermissions(
+ PpapiPermissions::AllPermissions());
+
+ // This file-local global is used by the PPP_Instance mock above in order to
+ // access PPB_Var_Deprecated.
+ plugin_dispatcher = plugin().plugin_dispatcher();
+
+ // Grab the host-side proxy for PPP_Instance and PPP_Instance_Private.
+ const PPP_Instance_Private* ppp_instance_private =
+ static_cast<const PPP_Instance_Private*>(
+ host().host_dispatcher()->GetProxiedInterface(
+ PPP_INSTANCE_PRIVATE_INTERFACE));
+ const PPP_Instance_1_1* ppp_instance = static_cast<const PPP_Instance_1_1*>(
+ host().host_dispatcher()->GetProxiedInterface(
+ PPP_INSTANCE_INTERFACE_1_1));
+
+ // Initialize an Instance, so that the plugin-side machinery will work
+ // properly.
+ EXPECT_EQ(PP_TRUE, ppp_instance->DidCreate(kInstance, 0, NULL, NULL));
+
+ // Check the plugin-side reference count.
+ EXPECT_EQ(1, plugin().var_tracker().GetRefCountForObject(instance_obj));
+ // Check the host-side var exists with the expected id and has 1 refcount (the
+ // refcount on behalf of the plugin).
+ int32 expected_host_id =
+ plugin().var_tracker().GetHostObject(instance_obj).value.as_id;
+ Var* host_var = host().var_tracker().GetVar(expected_host_id);
+ ASSERT_TRUE(host_var);
+ EXPECT_EQ(
+ 1,
+ host().var_tracker().GetRefCountForObject(GetPPVarNoAddRef(host_var)));
+
+ // Call from the browser side to get the instance object.
+ PP_Var host_pp_var = ppp_instance_private->GetInstanceObject(kInstance);
+ EXPECT_EQ(instance_obj.type, host_pp_var.type);
+ EXPECT_EQ(host_pp_var.value.as_id, expected_host_id);
+ EXPECT_EQ(1, plugin().var_tracker().GetRefCountForObject(instance_obj));
+ // A reference is passed to the browser, which we consume here.
+ host().var_tracker().ReleaseVar(host_pp_var);
+ EXPECT_EQ(1, host().var_tracker().GetRefCountForObject(host_pp_var));
+
+ // The plugin is going away; generally, so will all references to its instance
+ // object.
+ host().var_tracker().ReleaseVar(host_pp_var);
+ // Destroy the instance. DidDestroy above decrements the reference count for
+ // instance_obj, so it should also be destroyed.
+ ppp_instance->DidDestroy(kInstance);
+ EXPECT_EQ(-1, plugin().var_tracker().GetRefCountForObject(instance_obj));
+ EXPECT_EQ(-1, host().var_tracker().GetRefCountForObject(host_pp_var));
+}
+
+} // namespace proxy
+} // namespace ppapi
+
diff --git a/chromium/ppapi/proxy/ppp_instance_proxy.cc b/chromium/ppapi/proxy/ppp_instance_proxy.cc
new file mode 100644
index 00000000000..a7a0699508b
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_instance_proxy.cc
@@ -0,0 +1,256 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppp_instance_proxy.h"
+
+#include <algorithm>
+
+#include "base/bind.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/c/ppb_fullscreen.h"
+#include "ppapi/c/ppp_instance.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/plugin_proxy_delegate.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/url_loader_resource.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/ppb_view_shared.h"
+#include "ppapi/shared_impl/resource_tracker.h"
+#include "ppapi/shared_impl/scoped_pp_resource.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_flash_fullscreen_api.h"
+#include "ppapi/thunk/ppb_view_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+using thunk::EnterInstanceAPINoLock;
+using thunk::EnterInstanceNoLock;
+using thunk::EnterResourceNoLock;
+using thunk::PPB_Flash_Fullscreen_API;
+using thunk::PPB_Instance_API;
+using thunk::PPB_View_API;
+
+namespace {
+
+#if !defined(OS_NACL)
+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(API_ID_PPP_INSTANCE, instance,
+ argn_vect, argv_vect, &result));
+ return result;
+}
+
+void DidDestroy(PP_Instance instance) {
+ HostDispatcher::GetForInstance(instance)->Send(
+ new PpapiMsg_PPPInstance_DidDestroy(API_ID_PPP_INSTANCE, instance));
+}
+
+void DidChangeView(PP_Instance instance, PP_Resource view_resource) {
+ HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+
+ EnterResourceNoLock<PPB_View_API> enter_view(view_resource, false);
+ if (enter_view.failed()) {
+ NOTREACHED();
+ return;
+ }
+
+ PP_Bool flash_fullscreen = PP_FALSE;
+ EnterInstanceNoLock enter_instance(instance);
+ if (!enter_instance.failed())
+ flash_fullscreen = enter_instance.functions()->FlashIsFullscreen(instance);
+ dispatcher->Send(new PpapiMsg_PPPInstance_DidChangeView(
+ API_ID_PPP_INSTANCE, instance, enter_view.object()->GetData(),
+ flash_fullscreen));
+}
+
+void DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {
+ HostDispatcher::GetForInstance(instance)->Send(
+ new PpapiMsg_PPPInstance_DidChangeFocus(API_ID_PPP_INSTANCE,
+ instance, has_focus));
+}
+
+PP_Bool HandleDocumentLoad(PP_Instance instance, PP_Resource url_loader) {
+ // This should never get called. Out-of-process document loads are handled
+ // specially.
+ NOTREACHED();
+ return PP_FALSE;
+}
+
+static const PPP_Instance_1_1 instance_interface = {
+ &DidCreate,
+ &DidDestroy,
+ &DidChangeView,
+ &DidChangeFocus,
+ &HandleDocumentLoad
+};
+#endif // !defined(OS_NACL)
+
+} // namespace
+
+PPP_Instance_Proxy::PPP_Instance_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher) {
+ if (dispatcher->IsPlugin()) {
+ // The PPP_Instance proxy works by always proxying the 1.1 version of the
+ // interface, and then detecting in the plugin process which one to use.
+ // PPP_Instance_Combined handles dispatching to whatever interface is
+ // supported.
+ //
+ // This means that if the plugin supports either 1.0 or 1.1 version of
+ // the interface, we want to say it supports the 1.1 version since we'll
+ // convert it here. This magic conversion code is hardcoded into
+ // PluginDispatcher::OnMsgSupportsInterface.
+ combined_interface_.reset(PPP_Instance_Combined::Create(
+ base::Bind(dispatcher->local_get_interface())));
+ }
+}
+
+PPP_Instance_Proxy::~PPP_Instance_Proxy() {
+}
+
+#if !defined(OS_NACL)
+// static
+const PPP_Instance* PPP_Instance_Proxy::GetInstanceInterface() {
+ return &instance_interface;
+}
+#endif // !defined(OS_NACL)
+
+bool PPP_Instance_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ if (!dispatcher()->IsPlugin())
+ return false;
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPP_Instance_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidCreate,
+ OnPluginMsgDidCreate)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidDestroy,
+ OnPluginMsgDidDestroy)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeView,
+ OnPluginMsgDidChangeView)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeFocus,
+ OnPluginMsgDidChangeFocus)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_HandleDocumentLoad,
+ OnPluginMsgHandleDocumentLoad)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPP_Instance_Proxy::OnPluginMsgDidCreate(
+ 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);
+ PpapiGlobals::Get()->GetResourceTracker()->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::OnPluginMsgDidDestroy(PP_Instance instance) {
+ combined_interface_->DidDestroy(instance);
+
+ PpapiGlobals* globals = PpapiGlobals::Get();
+ globals->GetResourceTracker()->DidDeleteInstance(instance);
+ globals->GetVarTracker()->DidDeleteInstance(instance);
+
+ static_cast<PluginDispatcher*>(dispatcher())->DidDestroyInstance(instance);
+}
+
+void PPP_Instance_Proxy::OnPluginMsgDidChangeView(
+ PP_Instance instance,
+ const ViewData& new_data,
+ PP_Bool flash_fullscreen) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return;
+ InstanceData* data = dispatcher->GetInstanceData(instance);
+ if (!data)
+ return;
+ data->view = new_data;
+
+#if !defined(OS_NACL)
+ EnterInstanceAPINoLock<PPB_Flash_Fullscreen_API> enter(instance);
+ if (!enter.failed())
+ enter.functions()->SetLocalIsFullscreen(instance, flash_fullscreen);
+#endif // !defined(OS_NACL)
+
+ ScopedPPResource resource(
+ ScopedPPResource::PassRef(),
+ (new PPB_View_Shared(OBJECT_IS_PROXY,
+ instance, new_data))->GetReference());
+
+ combined_interface_->DidChangeView(instance, resource,
+ &new_data.rect,
+ &new_data.clip_rect);
+}
+
+void PPP_Instance_Proxy::OnPluginMsgDidChangeFocus(PP_Instance instance,
+ PP_Bool has_focus) {
+ combined_interface_->DidChangeFocus(instance, has_focus);
+}
+
+void PPP_Instance_Proxy::OnPluginMsgHandleDocumentLoad(
+ PP_Instance instance,
+ int pending_loader_host_id,
+ const URLResponseInfoData& data) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return;
+ Connection connection(PluginGlobals::Get()->GetBrowserSender(),
+ dispatcher);
+
+ scoped_refptr<URLLoaderResource> loader_resource(
+ new URLLoaderResource(connection, instance,
+ pending_loader_host_id, data));
+
+ PP_Resource loader_pp_resource = loader_resource->GetReference();
+ if (!combined_interface_->HandleDocumentLoad(instance, loader_pp_resource))
+ loader_resource->Close();
+ // We don't pass a ref into the plugin, if it wants one, it will have taken
+ // an additional one.
+ PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(
+ loader_pp_resource);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppp_instance_proxy.h b/chromium/ppapi/proxy/ppp_instance_proxy.h
new file mode 100644
index 00000000000..85ae55cbddb
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_instance_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_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/interface_proxy.h"
+#include "ppapi/shared_impl/host_resource.h"
+#include "ppapi/shared_impl/ppp_instance_combined.h"
+
+struct PP_Rect;
+
+namespace ppapi {
+
+struct URLResponseInfoData;
+struct ViewData;
+
+namespace proxy {
+
+class PPP_Instance_Proxy : public InterfaceProxy {
+ public:
+ explicit PPP_Instance_Proxy(Dispatcher* dispatcher);
+ virtual ~PPP_Instance_Proxy();
+
+ static const PPP_Instance* GetInstanceInterface();
+
+ PPP_Instance_Combined* ppp_instance_target() const {
+ return combined_interface_.get();
+ }
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnPluginMsgDidCreate(PP_Instance instance,
+ const std::vector<std::string>& argn,
+ const std::vector<std::string>& argv,
+ PP_Bool* result);
+ void OnPluginMsgDidDestroy(PP_Instance instance);
+ void OnPluginMsgDidChangeView(PP_Instance instance,
+ const ViewData& new_data,
+ PP_Bool flash_fullscreen);
+ void OnPluginMsgDidChangeFocus(PP_Instance instance, PP_Bool has_focus);
+ void OnPluginMsgHandleDocumentLoad(PP_Instance instance,
+ int pending_loader_host_id,
+ const URLResponseInfoData& data);
+
+ scoped_ptr<PPP_Instance_Combined> combined_interface_;
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPP_INSTANCE_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppp_instance_proxy_unittest.cc b/chromium/ppapi/proxy/ppp_instance_proxy_unittest.cc
new file mode 100644
index 00000000000..e2df26e250f
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_instance_proxy_unittest.cc
@@ -0,0 +1,197 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/synchronization/waitable_event.h"
+#include "ipc/ipc_message_utils.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/c/ppb_fullscreen.h"
+#include "ppapi/c/ppb_url_loader.h"
+#include "ppapi/c/ppp_instance.h"
+#include "ppapi/c/private/ppb_flash_fullscreen.h"
+#include "ppapi/proxy/locking_resource_releaser.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+#include "ppapi/shared_impl/ppb_view_shared.h"
+
+namespace ppapi {
+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_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;
+}
+
+// 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;
+}
+
+PPP_Instance_1_0 ppp_instance_1_0 = {
+ &DidCreate,
+ &DidDestroy,
+ &DidChangeView,
+ &DidChangeFocus,
+ &HandleDocumentLoad
+};
+
+// PPP_Instance_Proxy::DidChangeView relies on PPB_(Flash)Fullscreen being
+// available with a valid implementation of IsFullScreen, so we mock it.
+PP_Bool IsFullscreen(PP_Instance instance) {
+ return PP_FALSE;
+}
+PPB_Fullscreen ppb_fullscreen = { &IsFullscreen };
+PPB_FlashFullscreen ppb_flash_fullscreen = { &IsFullscreen };
+
+} // namespace
+
+class PPP_Instance_ProxyTest : public TwoWayTest {
+ public:
+ PPP_Instance_ProxyTest()
+ : TwoWayTest(TwoWayTest::TEST_PPP_INTERFACE) {
+ }
+};
+
+TEST_F(PPP_Instance_ProxyTest, PPPInstance1_0) {
+ plugin().RegisterTestInterface(PPP_INSTANCE_INTERFACE_1_0, &ppp_instance_1_0);
+ host().RegisterTestInterface(PPB_FLASHFULLSCREEN_INTERFACE,
+ &ppb_flash_fullscreen);
+ host().RegisterTestInterface(PPB_FULLSCREEN_INTERFACE,
+ &ppb_fullscreen);
+
+ // Grab the host-side proxy for the interface. The browser only speaks 1.1,
+ // while the proxy ensures support for the 1.0 version on the plugin side.
+ const PPP_Instance_1_1* ppp_instance = static_cast<const PPP_Instance_1_1*>(
+ host().host_dispatcher()->GetProxiedInterface(
+ PPP_INSTANCE_INTERFACE_1_1));
+
+ // 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();
+ // Tell the host resource tracker about the instance.
+ host().resource_tracker().DidCreateInstance(expected_instance);
+ 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} };
+ ViewData data;
+ data.rect = expected_position;
+ data.is_fullscreen = false;
+ data.is_page_visible = true;
+ data.clip_rect = expected_clip;
+ data.device_scale = 1.0f;
+ ResetReceived();
+ LockingResourceReleaser view_resource(
+ (new PPB_View_Shared(OBJECT_IS_IMPL,
+ expected_instance, data))->GetReference());
+ ppp_instance->DidChangeView(expected_instance, view_resource.get());
+ 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);
+
+ // 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.
+
+ host().resource_tracker().DidDeleteInstance(expected_instance);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppp_messaging_proxy.cc b/chromium/ppapi/proxy/ppp_messaging_proxy.cc
new file mode 100644
index 00000000000..5a12419f78a
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_messaging_proxy.cc
@@ -0,0 +1,103 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppp_messaging_proxy.h"
+
+#include <algorithm>
+
+#include "ppapi/c/ppp_messaging.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/plugin_var_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/var_tracker.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+#if !defined(OS_NACL)
+void HandleMessage(PP_Instance instance, PP_Var message_data) {
+ HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ if (!dispatcher || (message_data.type == PP_VARTYPE_OBJECT)) {
+ // The dispatcher should always be valid, and the browser should never send
+ // an 'object' var over PPP_Messaging.
+ NOTREACHED();
+ return;
+ }
+
+ dispatcher->Send(new PpapiMsg_PPPMessaging_HandleMessage(
+ API_ID_PPP_MESSAGING,
+ instance,
+ SerializedVarSendInputShmem(dispatcher, message_data, instance)));
+}
+
+static const PPP_Messaging messaging_interface = {
+ &HandleMessage
+};
+#else
+// The NaCl plugin doesn't need the host side interface - stub it out.
+static const PPP_Messaging messaging_interface = {};
+#endif // !defined(OS_NACL)
+
+InterfaceProxy* CreateMessagingProxy(Dispatcher* dispatcher) {
+ return new PPP_Messaging_Proxy(dispatcher);
+}
+
+} // namespace
+
+PPP_Messaging_Proxy::PPP_Messaging_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher),
+ ppp_messaging_impl_(NULL) {
+ if (dispatcher->IsPlugin()) {
+ ppp_messaging_impl_ = static_cast<const PPP_Messaging*>(
+ dispatcher->local_get_interface()(PPP_MESSAGING_INTERFACE));
+ }
+}
+
+PPP_Messaging_Proxy::~PPP_Messaging_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPP_Messaging_Proxy::GetInfo() {
+ static const Info info = {
+ &messaging_interface,
+ PPP_MESSAGING_INTERFACE,
+ API_ID_PPP_MESSAGING,
+ false,
+ &CreateMessagingProxy,
+ };
+ return &info;
+}
+
+bool PPP_Messaging_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ if (!dispatcher()->IsPlugin())
+ return false;
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPP_Messaging_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPMessaging_HandleMessage,
+ OnMsgHandleMessage)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPP_Messaging_Proxy::OnMsgHandleMessage(
+ PP_Instance instance, SerializedVarReceiveInput message_data) {
+ PP_Var received_var(message_data.GetForInstance(dispatcher(), instance));
+ // SerializedVarReceiveInput will decrement the reference count, but we want
+ // to give the recipient a reference.
+ PpapiGlobals::Get()->GetVarTracker()->AddRefVar(received_var);
+ CallWhileUnlocked(ppp_messaging_impl_->HandleMessage,
+ instance,
+ received_var);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppp_messaging_proxy.h b/chromium/ppapi/proxy/ppp_messaging_proxy.h
new file mode 100644
index 00000000000..4b66f92c4f7
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_messaging_proxy.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPP_MESSAGING_PROXY_H_
+#define PPAPI_PROXY_PPP_MESSAGING_PROXY_H_
+
+#include "base/compiler_specific.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/ppp_messaging.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+namespace ppapi {
+namespace proxy {
+
+class SerializedVarReceiveInput;
+
+class PPP_Messaging_Proxy : public InterfaceProxy {
+ public:
+ PPP_Messaging_Proxy(Dispatcher* dispatcher);
+ virtual ~PPP_Messaging_Proxy();
+
+ static const Info* GetInfo();
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+
+ private:
+ // Message handlers.
+ void OnMsgHandleMessage(PP_Instance instance,
+ SerializedVarReceiveInput data);
+
+ // When this proxy is in the plugin side, this value caches the interface
+ // pointer so we don't have to retrieve it from the dispatcher each time.
+ // In the host, this value is always NULL.
+ const PPP_Messaging* ppp_messaging_impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPP_Messaging_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPP_MESSAGING_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppp_messaging_proxy_perftest.cc b/chromium/ppapi/proxy/ppp_messaging_proxy_perftest.cc
new file mode 100644
index 00000000000..c52ea116687
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_messaging_proxy_perftest.cc
@@ -0,0 +1,88 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "base/perftimer.h"
+#include "base/strings/string_number_conversions.h"
+#include "ppapi/c/ppp_messaging.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/shared_impl/var_tracker.h"
+
+namespace ppapi {
+namespace proxy {
+namespace {
+
+base::WaitableEvent handle_message_called(false, false);
+
+void HandleMessage(PP_Instance /* instance */, PP_Var message_data) {
+ StringVar* string_var = StringVar::FromPPVar(message_data);
+ DCHECK(string_var);
+ // Retrieve the string to make sure the proxy can't "optimize away" sending
+ // the actual contents of the string (e.g., by doing a lazy retrieve or
+ // something). Note that this test is for performance only, and assumes
+ // other tests check for correctness.
+ std::string s = string_var->value();
+ // Do something simple with the string so the compiler won't complain.
+ if (s.length() > 0)
+ s[0] = 'a';
+ PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(message_data);
+ handle_message_called.Signal();
+}
+
+PPP_Messaging ppp_messaging_mock = {
+ &HandleMessage
+};
+
+class PppMessagingPerfTest : public TwoWayTest {
+ public:
+ PppMessagingPerfTest() : TwoWayTest(TwoWayTest::TEST_PPP_INTERFACE) {
+ plugin().RegisterTestInterface(PPP_MESSAGING_INTERFACE,
+ &ppp_messaging_mock);
+ }
+};
+
+} // namespace
+
+// Tests the performance of sending strings through the proxy.
+TEST_F(PppMessagingPerfTest, StringPerformance) {
+ // Grab the host-side proxy of ppp_messaging.
+ const PPP_Messaging* ppp_messaging = static_cast<const PPP_Messaging*>(
+ host().host_dispatcher()->GetProxiedInterface(
+ PPP_MESSAGING_INTERFACE));
+ const PP_Instance kTestInstance = pp_instance();
+ int seed = 123;
+ int string_count = 1000;
+ int max_string_size = 1000000;
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ if (command_line) {
+ if (command_line->HasSwitch("seed")) {
+ base::StringToInt(command_line->GetSwitchValueASCII("seed"),
+ &seed);
+ }
+ if (command_line->HasSwitch("string_count")) {
+ base::StringToInt(command_line->GetSwitchValueASCII("string_count"),
+ &string_count);
+ }
+ if (command_line->HasSwitch("max_string_size")) {
+ base::StringToInt(command_line->GetSwitchValueASCII("max_string_size"),
+ &max_string_size);
+ }
+ }
+ srand(seed);
+ PerfTimeLogger logger("PppMessagingPerfTest.StringPerformance");
+ for (int i = 0; i < string_count; ++i) {
+ const std::string test_string(rand() % max_string_size, 'a');
+ PP_Var host_string = StringVar::StringToPPVar(test_string);
+ ppp_messaging->HandleMessage(kTestInstance, host_string);
+ handle_message_called.Wait();
+ PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(host_string);
+ }
+}
+
+} // namespace proxy
+} // namespace ppapi
+
diff --git a/chromium/ppapi/proxy/ppp_messaging_proxy_unittest.cc b/chromium/ppapi/proxy/ppp_messaging_proxy_unittest.cc
new file mode 100644
index 00000000000..1fe0ef71806
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_messaging_proxy_unittest.cc
@@ -0,0 +1,136 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <cstring>
+
+#include "base/synchronization/waitable_event.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/c/ppp_messaging.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+// This is a poor man's mock of PPP_Messaging using global variables. Eventually
+// we should generalize making PPAPI interface mocks by using IDL or macro/
+// template magic.
+PP_Instance received_instance;
+PP_Var received_var;
+base::WaitableEvent handle_message_called(false, false);
+
+void HandleMessage(PP_Instance instance, PP_Var message_data) {
+ received_instance = instance;
+ received_var = message_data;
+ handle_message_called.Signal();
+}
+
+// Clear all the 'received' values for our mock. Call this before you expect
+// one of the functions to be invoked.
+void ResetReceived() {
+ received_instance = 0;
+ received_var.type = PP_VARTYPE_UNDEFINED;
+ received_var.value.as_id = 0;
+}
+
+PPP_Messaging ppp_messaging_mock = {
+ &HandleMessage
+};
+
+class PPP_Messaging_ProxyTest : public TwoWayTest {
+ public:
+ PPP_Messaging_ProxyTest()
+ : TwoWayTest(TwoWayTest::TEST_PPP_INTERFACE) {
+ plugin().RegisterTestInterface(PPP_MESSAGING_INTERFACE,
+ &ppp_messaging_mock);
+ }
+};
+
+void CompareAndReleaseStringVar(PluginProxyTestHarness* plugin_harness,
+ PP_Var received_var,
+ const std::string& test_string) {
+ ProxyAutoLock lock;
+ Var* received_string = plugin_harness->var_tracker().GetVar(received_var);
+ ASSERT_TRUE(received_string);
+ ASSERT_TRUE(received_string->AsStringVar());
+ EXPECT_EQ(test_string, received_string->AsStringVar()->value());
+ // Now release the var, and the string should go away (because the ref
+ // count should be one).
+ plugin_harness->var_tracker().ReleaseVar(received_var);
+ EXPECT_FALSE(StringVar::FromPPVar(received_var));
+}
+
+} // namespace
+
+TEST_F(PPP_Messaging_ProxyTest, SendMessages) {
+ // Grab the host-side proxy of ppp_messaging.
+ const PPP_Messaging* ppp_messaging = static_cast<const PPP_Messaging*>(
+ host().host_dispatcher()->GetProxiedInterface(
+ PPP_MESSAGING_INTERFACE));
+
+ PP_Instance expected_instance = pp_instance();
+ PP_Var expected_var = PP_MakeUndefined();
+ ResetReceived();
+ ppp_messaging->HandleMessage(expected_instance, expected_var);
+ handle_message_called.Wait();
+ EXPECT_EQ(expected_instance, received_instance);
+ EXPECT_EQ(expected_var.type, received_var.type);
+
+ expected_var = PP_MakeNull();
+ ResetReceived();
+ ppp_messaging->HandleMessage(expected_instance, expected_var);
+ handle_message_called.Wait();
+ EXPECT_EQ(expected_instance, received_instance);
+ EXPECT_EQ(expected_var.type, received_var.type);
+
+ expected_var = PP_MakeBool(PP_TRUE);
+ ResetReceived();
+ ppp_messaging->HandleMessage(expected_instance, expected_var);
+ handle_message_called.Wait();
+ EXPECT_EQ(expected_instance, received_instance);
+ EXPECT_EQ(expected_var.type, received_var.type);
+ EXPECT_EQ(expected_var.value.as_bool, received_var.value.as_bool);
+
+ expected_var = PP_MakeInt32(12345);
+ ResetReceived();
+ ppp_messaging->HandleMessage(expected_instance, expected_var);
+ handle_message_called.Wait();
+ EXPECT_EQ(expected_instance, received_instance);
+ EXPECT_EQ(expected_var.type, received_var.type);
+ EXPECT_EQ(expected_var.value.as_int, received_var.value.as_int);
+
+ expected_var = PP_MakeDouble(3.1415);
+ ResetReceived();
+ ppp_messaging->HandleMessage(expected_instance, expected_var);
+ handle_message_called.Wait();
+ EXPECT_EQ(expected_instance, received_instance);
+ EXPECT_EQ(expected_var.type, received_var.type);
+ EXPECT_EQ(expected_var.value.as_double, received_var.value.as_double);
+
+ const std::string kTestString("Hello world!");
+ expected_var = StringVar::StringToPPVar(kTestString);
+ ResetReceived();
+ ppp_messaging->HandleMessage(expected_instance, expected_var);
+ // Now release the var, and the string should go away (because the ref
+ // count should be one).
+ host().var_tracker().ReleaseVar(expected_var);
+ EXPECT_FALSE(StringVar::FromPPVar(expected_var));
+
+ handle_message_called.Wait();
+ EXPECT_EQ(expected_instance, received_instance);
+ EXPECT_EQ(expected_var.type, received_var.type);
+ PostTaskOnRemoteHarness(
+ base::Bind(CompareAndReleaseStringVar,
+ &plugin(),
+ received_var,
+ kTestString));
+}
+
+} // namespace proxy
+} // namespace ppapi
+
diff --git a/chromium/ppapi/proxy/ppp_mouse_lock_proxy.cc b/chromium/ppapi/proxy/ppp_mouse_lock_proxy.cc
new file mode 100644
index 00000000000..6fd746dc01f
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_mouse_lock_proxy.cc
@@ -0,0 +1,87 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppp_mouse_lock_proxy.h"
+
+#include "ppapi/c/ppp_mouse_lock.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+#if !defined(OS_NACL)
+void MouseLockLost(PP_Instance instance) {
+ HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ if (!dispatcher) {
+ // The dispatcher should always be valid.
+ NOTREACHED();
+ return;
+ }
+
+ dispatcher->Send(new PpapiMsg_PPPMouseLock_MouseLockLost(
+ API_ID_PPP_MOUSE_LOCK, instance));
+}
+
+static const PPP_MouseLock mouse_lock_interface = {
+ &MouseLockLost
+};
+#else
+// The NaCl plugin doesn't need the host side interface - stub it out.
+static const PPP_MouseLock mouse_lock_interface = {};
+#endif // !defined(OS_NACL)
+
+InterfaceProxy* CreateMouseLockProxy(Dispatcher* dispatcher) {
+ return new PPP_MouseLock_Proxy(dispatcher);
+}
+
+} // namespace
+
+PPP_MouseLock_Proxy::PPP_MouseLock_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher),
+ ppp_mouse_lock_impl_(NULL) {
+ if (dispatcher->IsPlugin()) {
+ ppp_mouse_lock_impl_ = static_cast<const PPP_MouseLock*>(
+ dispatcher->local_get_interface()(PPP_MOUSELOCK_INTERFACE));
+ }
+}
+
+PPP_MouseLock_Proxy::~PPP_MouseLock_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPP_MouseLock_Proxy::GetInfo() {
+ static const Info info = {
+ &mouse_lock_interface,
+ PPP_MOUSELOCK_INTERFACE,
+ API_ID_PPP_MOUSE_LOCK,
+ false,
+ &CreateMouseLockProxy,
+ };
+ return &info;
+}
+
+bool PPP_MouseLock_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ if (!dispatcher()->IsPlugin())
+ return false;
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPP_MouseLock_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPMouseLock_MouseLockLost,
+ OnMsgMouseLockLost)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPP_MouseLock_Proxy::OnMsgMouseLockLost(PP_Instance instance) {
+ if (ppp_mouse_lock_impl_)
+ CallWhileUnlocked(ppp_mouse_lock_impl_->MouseLockLost, instance);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppp_mouse_lock_proxy.h b/chromium/ppapi/proxy/ppp_mouse_lock_proxy.h
new file mode 100644
index 00000000000..64f1b7a05d7
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_mouse_lock_proxy.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPP_MOUSE_LOCK_PROXY_H_
+#define PPAPI_PROXY_PPP_MOUSE_LOCK_PROXY_H_
+
+#include "base/compiler_specific.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/ppp_mouse_lock.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPP_MouseLock_Proxy : public InterfaceProxy {
+ public:
+ PPP_MouseLock_Proxy(Dispatcher* dispatcher);
+ virtual ~PPP_MouseLock_Proxy();
+
+ static const Info* GetInfo();
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+
+ private:
+ // Message handlers.
+ void OnMsgMouseLockLost(PP_Instance instance);
+
+ // When this proxy is in the plugin side, this value caches the interface
+ // pointer so we don't have to retrieve it from the dispatcher each time.
+ // In the host, this value is always NULL.
+ const PPP_MouseLock* ppp_mouse_lock_impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPP_MouseLock_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPP_MOUSE_LOCK_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppp_printing_proxy.cc b/chromium/ppapi/proxy/ppp_printing_proxy.cc
new file mode 100644
index 00000000000..9d58c780111
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_printing_proxy.cc
@@ -0,0 +1,214 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppp_printing_proxy.h"
+
+#include <string.h>
+
+#include "ppapi/c/dev/ppp_printing_dev.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/resource_tracker.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+#if !defined(OS_NACL)
+bool HasPrintingPermission(PP_Instance instance) {
+ Dispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return false;
+ return dispatcher->permissions().HasPermission(PERMISSION_DEV);
+}
+
+uint32_t QuerySupportedFormats(PP_Instance instance) {
+ if (!HasPrintingPermission(instance))
+ return 0;
+ uint32_t result = 0;
+ HostDispatcher::GetForInstance(instance)->Send(
+ new PpapiMsg_PPPPrinting_QuerySupportedFormats(API_ID_PPP_PRINTING,
+ instance, &result));
+ return result;
+}
+
+int32_t Begin(PP_Instance instance,
+ const struct PP_PrintSettings_Dev* print_settings) {
+ if (!HasPrintingPermission(instance))
+ return 0;
+ // Settings is just serialized as a string.
+ std::string settings_string;
+ settings_string.resize(sizeof(*print_settings));
+ memcpy(&settings_string[0], print_settings, sizeof(*print_settings));
+
+ int32_t result = 0;
+ HostDispatcher::GetForInstance(instance)->Send(
+ new PpapiMsg_PPPPrinting_Begin(API_ID_PPP_PRINTING, instance,
+ settings_string, &result));
+ return result;
+}
+
+PP_Resource PrintPages(PP_Instance instance,
+ const PP_PrintPageNumberRange_Dev* page_ranges,
+ uint32_t page_range_count) {
+ if (!HasPrintingPermission(instance))
+ return 0;
+ std::vector<PP_PrintPageNumberRange_Dev> pages(
+ page_ranges, page_ranges + page_range_count);
+
+ HostResource result;
+ HostDispatcher::GetForInstance(instance)->Send(
+ new PpapiMsg_PPPPrinting_PrintPages(API_ID_PPP_PRINTING,
+ instance, pages, &result));
+
+ // How refcounting works when returning a resource:
+ //
+ // The plugin in the plugin process makes a resource that it returns to the
+ // browser. The plugin proxy code returns that ref to us and asynchronously
+ // releases it. Before any release message associated with that operation
+ // comes, we'll get this reply. We need to add one ref since our caller
+ // expects us to add one ref for it to consume.
+ PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(
+ result.host_resource());
+ return result.host_resource();
+}
+
+void End(PP_Instance instance) {
+ if (!HasPrintingPermission(instance))
+ return;
+ HostDispatcher::GetForInstance(instance)->Send(
+ new PpapiMsg_PPPPrinting_End(API_ID_PPP_PRINTING, instance));
+}
+
+PP_Bool IsScalingDisabled(PP_Instance instance) {
+ if (!HasPrintingPermission(instance))
+ return PP_FALSE;
+ bool result = false;
+ HostDispatcher::GetForInstance(instance)->Send(
+ new PpapiMsg_PPPPrinting_IsScalingDisabled(API_ID_PPP_PRINTING,
+ instance, &result));
+ return PP_FromBool(result);
+}
+
+const PPP_Printing_Dev ppp_printing_interface = {
+ &QuerySupportedFormats,
+ &Begin,
+ &PrintPages,
+ &End,
+ &IsScalingDisabled
+};
+#else
+// The NaCl plugin doesn't need the host side interface - stub it out.
+static const PPP_Printing_Dev ppp_printing_interface = {};
+#endif // !defined(OS_NACL)
+
+} // namespace
+
+PPP_Printing_Proxy::PPP_Printing_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher),
+ ppp_printing_impl_(NULL) {
+ if (dispatcher->IsPlugin()) {
+ ppp_printing_impl_ = static_cast<const PPP_Printing_Dev*>(
+ dispatcher->local_get_interface()(PPP_PRINTING_DEV_INTERFACE));
+ }
+}
+
+PPP_Printing_Proxy::~PPP_Printing_Proxy() {
+}
+
+// static
+const PPP_Printing_Dev* PPP_Printing_Proxy::GetProxyInterface() {
+ return &ppp_printing_interface;
+}
+
+bool PPP_Printing_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ if (!dispatcher()->IsPlugin())
+ return false;
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPP_Printing_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_QuerySupportedFormats,
+ OnPluginMsgQuerySupportedFormats)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_Begin,
+ OnPluginMsgBegin)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_PrintPages,
+ OnPluginMsgPrintPages)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_End,
+ OnPluginMsgEnd)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_IsScalingDisabled,
+ OnPluginMsgIsScalingDisabled)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPP_Printing_Proxy::OnPluginMsgQuerySupportedFormats(PP_Instance instance,
+ uint32_t* result) {
+ if (ppp_printing_impl_) {
+ *result = CallWhileUnlocked(ppp_printing_impl_->QuerySupportedFormats,
+ instance);
+ } else {
+ *result = 0;
+ }
+}
+
+void PPP_Printing_Proxy::OnPluginMsgBegin(PP_Instance instance,
+ const std::string& settings_string,
+ int32_t* result) {
+ *result = 0;
+
+ PP_PrintSettings_Dev settings;
+ if (settings_string.size() != sizeof(settings))
+ return;
+ memcpy(&settings, &settings_string[0], sizeof(settings));
+
+ if (ppp_printing_impl_) {
+ *result = CallWhileUnlocked(ppp_printing_impl_->Begin,
+ instance,
+ const_cast<const PP_PrintSettings_Dev*>(&settings));
+ }
+}
+
+void PPP_Printing_Proxy::OnPluginMsgPrintPages(
+ PP_Instance instance,
+ const std::vector<PP_PrintPageNumberRange_Dev>& pages,
+ HostResource* result) {
+ if (!ppp_printing_impl_ || pages.empty())
+ return;
+
+ PP_Resource plugin_resource = CallWhileUnlocked(
+ ppp_printing_impl_->PrintPages,
+ instance, &pages[0], static_cast<uint32_t>(pages.size()));
+ ResourceTracker* resource_tracker = PpapiGlobals::Get()->GetResourceTracker();
+ Resource* resource_object = resource_tracker->GetResource(plugin_resource);
+ if (!resource_object)
+ return;
+
+ *result = resource_object->host_resource();
+
+ // See PrintPages above for how refcounting works.
+ resource_tracker->ReleaseResourceSoon(plugin_resource);
+}
+
+void PPP_Printing_Proxy::OnPluginMsgEnd(PP_Instance instance) {
+ if (ppp_printing_impl_)
+ CallWhileUnlocked(ppp_printing_impl_->End, instance);
+}
+
+void PPP_Printing_Proxy::OnPluginMsgIsScalingDisabled(PP_Instance instance,
+ bool* result) {
+ if (ppp_printing_impl_) {
+ *result = PP_ToBool(CallWhileUnlocked(ppp_printing_impl_->IsScalingDisabled,
+ instance));
+ } else {
+ *result = false;
+ }
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppp_printing_proxy.h b/chromium/ppapi/proxy/ppp_printing_proxy.h
new file mode 100644
index 00000000000..03bebf7b6aa
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_printing_proxy.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPP_PRINTING_PROXY_H_
+#define PPAPI_PROXY_PPP_PRINTING_PROXY_H_
+
+#include <string>
+#include <vector>
+
+#include "ppapi/c/dev/ppp_printing_dev.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PP_PrintPageNumberRange_Dev;
+
+namespace ppapi {
+
+class HostResource;
+
+namespace proxy {
+
+class PPP_Printing_Proxy : public InterfaceProxy {
+ public:
+ PPP_Printing_Proxy(Dispatcher* dispatcher);
+ virtual ~PPP_Printing_Proxy();
+
+ static const PPP_Printing_Dev* GetProxyInterface();
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnPluginMsgQuerySupportedFormats(PP_Instance instance, uint32_t* result);
+ void OnPluginMsgBegin(PP_Instance instance,
+ const std::string& settings_string,
+ int32_t* result);
+ void OnPluginMsgPrintPages(
+ PP_Instance instance,
+ const std::vector<PP_PrintPageNumberRange_Dev>& pages,
+ HostResource* result);
+ void OnPluginMsgEnd(PP_Instance instance);
+ void OnPluginMsgIsScalingDisabled(PP_Instance instance, bool* result);
+
+ // When this proxy is in the plugin side, this value caches the interface
+ // pointer so we don't have to retrieve it from the dispatcher each time.
+ // In the host, this value is always NULL.
+ const PPP_Printing_Dev* ppp_printing_impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPP_Printing_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPP_PRINTING_PROXY_H_
+
diff --git a/chromium/ppapi/proxy/ppp_text_input_proxy.cc b/chromium/ppapi/proxy/ppp_text_input_proxy.cc
new file mode 100644
index 00000000000..061b73cd4fd
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_text_input_proxy.cc
@@ -0,0 +1,81 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppp_text_input_proxy.h"
+
+#include "ppapi/c/dev/ppp_text_input_dev.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+#if !defined(OS_NACL)
+void RequestSurroundingText(PP_Instance instance,
+ uint32_t desired_number_of_characters) {
+ proxy::HostDispatcher* dispatcher =
+ proxy::HostDispatcher::GetForInstance(instance);
+ if (!dispatcher) {
+ // The dispatcher should always be valid.
+ NOTREACHED();
+ return;
+ }
+
+ dispatcher->Send(new PpapiMsg_PPPTextInput_RequestSurroundingText(
+ API_ID_PPP_TEXT_INPUT, instance, desired_number_of_characters));
+}
+
+const PPP_TextInput_Dev g_ppp_text_input_thunk = {
+ &RequestSurroundingText
+};
+#else
+// The NaCl plugin doesn't need the host side interface - stub it out.
+static const PPP_TextInput_Dev g_ppp_text_input_thunk = {};
+#endif // !defined(OS_NACL)
+
+} // namespace
+
+// static
+const PPP_TextInput_Dev* PPP_TextInput_Proxy::GetProxyInterface() {
+ return &g_ppp_text_input_thunk;
+}
+
+PPP_TextInput_Proxy::PPP_TextInput_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher),
+ ppp_text_input_impl_(NULL) {
+ if (dispatcher->IsPlugin()) {
+ ppp_text_input_impl_ = static_cast<const PPP_TextInput_Dev*>(
+ dispatcher->local_get_interface()(PPP_TEXTINPUT_DEV_INTERFACE));
+ }
+}
+
+PPP_TextInput_Proxy::~PPP_TextInput_Proxy() {
+}
+
+bool PPP_TextInput_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ if (!dispatcher()->IsPlugin())
+ return false;
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPP_TextInput_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPTextInput_RequestSurroundingText,
+ OnMsgRequestSurroundingText)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPP_TextInput_Proxy::OnMsgRequestSurroundingText(
+ PP_Instance instance, uint32_t desired_number_of_characters) {
+ if (ppp_text_input_impl_) {
+ CallWhileUnlocked(ppp_text_input_impl_->RequestSurroundingText,
+ instance, desired_number_of_characters);
+ }
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppp_text_input_proxy.h b/chromium/ppapi/proxy/ppp_text_input_proxy.h
new file mode 100644
index 00000000000..7ac0cacffab
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_text_input_proxy.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPP_TEXT_INPUT_PROXY_H_
+#define PPAPI_PROXY_PPP_TEXT_INPUT_PROXY_H_
+
+#include "base/compiler_specific.h"
+#include "ppapi/c/dev/ppp_text_input_dev.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPP_TextInput_Proxy : public InterfaceProxy {
+ public:
+ PPP_TextInput_Proxy(Dispatcher* dispatcher);
+ virtual ~PPP_TextInput_Proxy();
+
+ static const PPP_TextInput_Dev* GetProxyInterface();
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+
+ private:
+ // Message handlers.
+ void OnMsgRequestSurroundingText(PP_Instance instance,
+ uint32_t desired_number_of_characters);
+
+ // When this proxy is in the plugin side, this value caches the interface
+ // pointer so we don't have to retrieve it from the dispatcher each time.
+ // In the host, this value is always NULL.
+ const PPP_TextInput_Dev* ppp_text_input_impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPP_TextInput_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPP_TEXT_INPUT_PROXY_H_
diff --git a/chromium/ppapi/proxy/ppp_video_decoder_proxy.cc b/chromium/ppapi/proxy/ppp_video_decoder_proxy.cc
new file mode 100644
index 00000000000..f1a67212791
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_video_decoder_proxy.cc
@@ -0,0 +1,184 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppp_video_decoder_proxy.h"
+
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_video_decoder_proxy.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_video_decoder_api.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::thunk::PPB_VideoDecoder_API;
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+void ProvidePictureBuffers(PP_Instance instance, PP_Resource decoder,
+ uint32_t req_num_of_bufs,
+ const PP_Size* dimensions,
+ uint32_t texture_target) {
+ HostResource decoder_resource;
+ decoder_resource.SetHostResource(instance, decoder);
+
+ HostDispatcher::GetForInstance(instance)->Send(
+ new PpapiMsg_PPPVideoDecoder_ProvidePictureBuffers(
+ API_ID_PPP_VIDEO_DECODER_DEV,
+ decoder_resource, req_num_of_bufs, *dimensions, texture_target));
+}
+
+void DismissPictureBuffer(PP_Instance instance, PP_Resource decoder,
+ int32_t picture_buffer_id) {
+ HostResource decoder_resource;
+ decoder_resource.SetHostResource(instance, decoder);
+
+ HostDispatcher::GetForInstance(instance)->Send(
+ new PpapiMsg_PPPVideoDecoder_DismissPictureBuffer(
+ API_ID_PPP_VIDEO_DECODER_DEV,
+ decoder_resource, picture_buffer_id));
+}
+
+void PictureReady(PP_Instance instance, PP_Resource decoder,
+ const PP_Picture_Dev* picture) {
+ HostResource decoder_resource;
+ decoder_resource.SetHostResource(instance, decoder);
+
+ HostDispatcher::GetForInstance(instance)->Send(
+ new PpapiMsg_PPPVideoDecoder_PictureReady(
+ API_ID_PPP_VIDEO_DECODER_DEV, decoder_resource, *picture));
+}
+
+void NotifyError(PP_Instance instance, PP_Resource decoder,
+ PP_VideoDecodeError_Dev error) {
+ HostResource decoder_resource;
+ decoder_resource.SetHostResource(instance, decoder);
+
+ // It's possible that the error we're being notified about is happening
+ // because the instance is shutting down. In this case, our instance may
+ // already have been removed from the HostDispatcher map.
+ HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
+ if (dispatcher) {
+ dispatcher->Send(
+ new PpapiMsg_PPPVideoDecoder_NotifyError(
+ API_ID_PPP_VIDEO_DECODER_DEV, decoder_resource, error));
+ }
+}
+
+static const PPP_VideoDecoder_Dev video_decoder_interface = {
+ &ProvidePictureBuffers,
+ &DismissPictureBuffer,
+ &PictureReady,
+ &NotifyError
+};
+
+InterfaceProxy* CreateVideoDecoderPPPProxy(Dispatcher* dispatcher) {
+ return new PPP_VideoDecoder_Proxy(dispatcher);
+}
+
+} // namespace
+
+PPP_VideoDecoder_Proxy::PPP_VideoDecoder_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher),
+ ppp_video_decoder_impl_(NULL) {
+ if (dispatcher->IsPlugin()) {
+ ppp_video_decoder_impl_ = static_cast<const PPP_VideoDecoder_Dev*>(
+ dispatcher->local_get_interface()(PPP_VIDEODECODER_DEV_INTERFACE));
+ }
+}
+
+PPP_VideoDecoder_Proxy::~PPP_VideoDecoder_Proxy() {
+}
+
+// static
+const InterfaceProxy::Info* PPP_VideoDecoder_Proxy::GetInfo() {
+ static const Info info = {
+ &video_decoder_interface,
+ PPP_VIDEODECODER_DEV_INTERFACE,
+ API_ID_PPP_VIDEO_DECODER_DEV,
+ false,
+ &CreateVideoDecoderPPPProxy,
+ };
+ return &info;
+}
+
+bool PPP_VideoDecoder_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ if (!dispatcher()->IsPlugin())
+ return false;
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPP_VideoDecoder_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPVideoDecoder_ProvidePictureBuffers,
+ OnMsgProvidePictureBuffers)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPVideoDecoder_DismissPictureBuffer,
+ OnMsgDismissPictureBuffer)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPVideoDecoder_PictureReady,
+ OnMsgPictureReady)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPPVideoDecoder_NotifyError,
+ OnMsgNotifyError)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ DCHECK(handled);
+ return handled;
+}
+
+void PPP_VideoDecoder_Proxy::OnMsgProvidePictureBuffers(
+ const HostResource& decoder,
+ uint32_t req_num_of_bufs,
+ const PP_Size& dimensions,
+ uint32_t texture_target) {
+ PP_Resource plugin_decoder = PluginGlobals::Get()->plugin_resource_tracker()->
+ PluginResourceForHostResource(decoder);
+ if (!plugin_decoder)
+ return;
+ CallWhileUnlocked(ppp_video_decoder_impl_->ProvidePictureBuffers,
+ decoder.instance(),
+ plugin_decoder,
+ req_num_of_bufs,
+ &dimensions,
+ texture_target);
+}
+
+void PPP_VideoDecoder_Proxy::OnMsgDismissPictureBuffer(
+ const HostResource& decoder, int32_t picture_id) {
+ PP_Resource plugin_decoder = PluginGlobals::Get()->plugin_resource_tracker()->
+ PluginResourceForHostResource(decoder);
+ if (!plugin_decoder)
+ return;
+ CallWhileUnlocked(ppp_video_decoder_impl_->DismissPictureBuffer,
+ decoder.instance(),
+ plugin_decoder,
+ picture_id);
+}
+
+void PPP_VideoDecoder_Proxy::OnMsgPictureReady(
+ const HostResource& decoder, const PP_Picture_Dev& picture) {
+ PP_Resource plugin_decoder = PluginGlobals::Get()->plugin_resource_tracker()->
+ PluginResourceForHostResource(decoder);
+ if (!plugin_decoder)
+ return;
+ CallWhileUnlocked(ppp_video_decoder_impl_->PictureReady,
+ decoder.instance(),
+ plugin_decoder,
+ &picture);
+}
+
+void PPP_VideoDecoder_Proxy::OnMsgNotifyError(
+ const HostResource& decoder, PP_VideoDecodeError_Dev error) {
+ PP_Resource plugin_decoder = PluginGlobals::Get()->plugin_resource_tracker()->
+ PluginResourceForHostResource(decoder);
+ if (!plugin_decoder)
+ return;
+ CallWhileUnlocked(ppp_video_decoder_impl_->NotifyError,
+ decoder.instance(),
+ plugin_decoder,
+ error);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/ppp_video_decoder_proxy.h b/chromium/ppapi/proxy/ppp_video_decoder_proxy.h
new file mode 100644
index 00000000000..84d83a56b1a
--- /dev/null
+++ b/chromium/ppapi/proxy/ppp_video_decoder_proxy.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPP_VIDEO_DECODER_PROXY_H_
+#define PPAPI_PROXY_PPP_VIDEO_DECODER_PROXY_H_
+
+#include "ppapi/c/dev/ppp_video_decoder_dev.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/shared_impl/host_resource.h"
+
+struct PP_Picture_Dev;
+struct PP_Size;
+
+namespace ppapi {
+namespace proxy {
+
+class PPP_VideoDecoder_Proxy : public InterfaceProxy {
+ public:
+ PPP_VideoDecoder_Proxy(Dispatcher* dispatcher);
+ virtual ~PPP_VideoDecoder_Proxy();
+
+ static const Info* GetInfo();
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgProvidePictureBuffers(const ppapi::HostResource& decoder,
+ uint32_t req_num_of_buffers,
+ const PP_Size& dimensions,
+ uint32_t texture_target);
+ void OnMsgDismissPictureBuffer(const ppapi::HostResource& decoder,
+ int32_t picture_id);
+ void OnMsgPictureReady(const ppapi::HostResource& decoder,
+ const PP_Picture_Dev& picture_buffer);
+ void OnMsgNotifyError(const ppapi::HostResource& decoder,
+ PP_VideoDecodeError_Dev error);
+
+ // When this proxy is in the plugin side, this value caches the interface
+ // pointer so we don't have to retrieve it from the dispatcher each time.
+ // In the host, this value is always NULL.
+ const PPP_VideoDecoder_Dev* ppp_video_decoder_impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPP_VideoDecoder_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPP_VIDEO_DECODER_PROXY_H_
diff --git a/chromium/ppapi/proxy/printing_resource.cc b/chromium/ppapi/proxy/printing_resource.cc
new file mode 100644
index 00000000000..d9be3b74301
--- /dev/null
+++ b/chromium/ppapi/proxy/printing_resource.cc
@@ -0,0 +1,58 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/printing_resource.h"
+
+#include "base/bind.h"
+#include "ipc/ipc_message.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/dispatch_reply_message.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace ppapi {
+namespace proxy {
+
+PrintingResource::PrintingResource(Connection connection, PP_Instance instance)
+ : PluginResource(connection, instance) {
+}
+
+PrintingResource::~PrintingResource() {
+}
+
+thunk::PPB_Printing_API* PrintingResource::AsPPB_Printing_API() {
+ return this;
+}
+
+int32_t PrintingResource::GetDefaultPrintSettings(
+ PP_PrintSettings_Dev* print_settings,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!print_settings)
+ return PP_ERROR_BADARGUMENT;
+
+ if (!sent_create_to_browser())
+ SendCreate(BROWSER, PpapiHostMsg_Printing_Create());
+
+ Call<PpapiPluginMsg_Printing_GetDefaultPrintSettingsReply>(
+ BROWSER,
+ PpapiHostMsg_Printing_GetDefaultPrintSettings(),
+ base::Bind(&PrintingResource::OnPluginMsgGetDefaultPrintSettingsReply,
+ this, print_settings, callback));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void PrintingResource::OnPluginMsgGetDefaultPrintSettingsReply(
+ PP_PrintSettings_Dev* settings_out,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const PP_PrintSettings_Dev& settings) {
+ if (params.result() == PP_OK)
+ *settings_out = settings;
+
+ // Notify the plugin of the new data.
+ callback->Run(params.result());
+ // DANGER: May delete |this|!
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/printing_resource.h b/chromium/ppapi/proxy/printing_resource.h
new file mode 100644
index 00000000000..1f9216ba9ab
--- /dev/null
+++ b/chromium/ppapi/proxy/printing_resource.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PRINTING_RESOURCE_H_
+#define PPAPI_PROXY_PRINTING_RESOURCE_H_
+
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/ppb_printing_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT PrintingResource
+ : public PluginResource,
+ public NON_EXPORTED_BASE(thunk::PPB_Printing_API) {
+ public:
+ PrintingResource(Connection connection,
+ PP_Instance instance);
+ virtual ~PrintingResource();
+
+ // Resource overrides.
+ virtual thunk::PPB_Printing_API* AsPPB_Printing_API() OVERRIDE;
+
+ // PPB_Printing_API.
+ virtual int32_t GetDefaultPrintSettings(
+ PP_PrintSettings_Dev* print_settings,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+
+ private:
+ void OnPluginMsgGetDefaultPrintSettingsReply(
+ PP_PrintSettings_Dev* settings_out,
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params,
+ const PP_PrintSettings_Dev& settings);
+
+ DISALLOW_COPY_AND_ASSIGN(PrintingResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PRINTING_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/printing_resource_unittest.cc b/chromium/ppapi/proxy/printing_resource_unittest.cc
new file mode 100644
index 00000000000..af6c7420f27
--- /dev/null
+++ b/chromium/ppapi/proxy/printing_resource_unittest.cc
@@ -0,0 +1,102 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <cstring>
+
+#include "base/message_loop/message_loop.h"
+#include "ppapi/c/dev/ppb_printing_dev.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/locking_resource_releaser.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+#include "ppapi/proxy/printing_resource.h"
+#include "ppapi/thunk/thunk.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+typedef PluginProxyTest PrintingResourceTest;
+
+bool g_callback_called;
+int32_t g_callback_result;
+
+void Callback(void* user_data, int32_t result) {
+ g_callback_called = true;
+ g_callback_result = result;
+}
+
+bool PP_SizeEqual(const PP_Size& lhs, const PP_Size& rhs) {
+ return lhs.width == rhs.width && lhs.height == rhs.height;
+}
+
+bool PP_RectEqual(const PP_Rect& lhs, const PP_Rect& rhs) {
+ return lhs.point.x == rhs.point.x &&
+ lhs.point.y == rhs.point.y &&
+ PP_SizeEqual(lhs.size, rhs.size);
+}
+
+} // namespace
+
+// Does a full test of GetDefaultPrintSettings() and reply functionality in the
+// plugin side using the public C interfaces.
+TEST_F(PrintingResourceTest, GetDefaultPrintSettings) {
+ g_callback_called = false;
+
+ const PPB_Printing_Dev_0_7* printing_iface =
+ thunk::GetPPB_Printing_Dev_0_7_Thunk();
+ LockingResourceReleaser res(printing_iface->Create(pp_instance()));
+
+ PP_PrintSettings_Dev output_settings;
+
+ int32_t result = printing_iface->GetDefaultPrintSettings(
+ res.get(), &output_settings, PP_MakeCompletionCallback(&Callback, NULL));
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
+
+ // Should have sent a "GetDefaultPrintSettings" message.
+ ResourceMessageCallParams params;
+ IPC::Message msg;
+ ASSERT_TRUE(sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_Printing_GetDefaultPrintSettings::ID, &params, &msg));
+
+ // Synthesize a response with some random print settings.
+ ResourceMessageReplyParams reply_params(params.pp_resource(),
+ params.sequence());
+ reply_params.set_result(PP_OK);
+
+ PP_PrintSettings_Dev reply_settings = {
+ { { 0, 0 }, { 500, 515 } },
+ { { 25, 35 }, { 300, 720 } },
+ { 600, 700 },
+ 200,
+ PP_PRINTORIENTATION_NORMAL,
+ PP_PRINTSCALINGOPTION_NONE,
+ PP_FALSE,
+ PP_PRINTOUTPUTFORMAT_PDF
+ };
+ ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(
+ PpapiPluginMsg_ResourceReply(reply_params,
+ PpapiPluginMsg_Printing_GetDefaultPrintSettingsReply(
+ reply_settings))));
+
+ EXPECT_TRUE(PP_RectEqual(reply_settings.printable_area,
+ output_settings.printable_area));
+ EXPECT_TRUE(PP_RectEqual(reply_settings.content_area,
+ output_settings.content_area));
+ EXPECT_TRUE(PP_SizeEqual(reply_settings.paper_size,
+ output_settings.paper_size));
+ EXPECT_EQ(reply_settings.dpi, output_settings.dpi);
+ EXPECT_EQ(reply_settings.orientation, output_settings.orientation);
+ EXPECT_EQ(reply_settings.print_scaling_option,
+ output_settings.print_scaling_option);
+ EXPECT_EQ(reply_settings.grayscale, output_settings.grayscale);
+ EXPECT_EQ(reply_settings.format, output_settings.format);
+
+ EXPECT_EQ(g_callback_result, PP_OK);
+ EXPECT_EQ(g_callback_called, true);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/proxy_array_output.cc b/chromium/ppapi/proxy/proxy_array_output.cc
new file mode 100644
index 00000000000..e550b1ceacf
--- /dev/null
+++ b/chromium/ppapi/proxy/proxy_array_output.cc
@@ -0,0 +1,21 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/proxy_array_output.h"
+
+#include "base/logging.h"
+
+namespace ppapi {
+namespace proxy {
+
+// static
+void* ArrayOutputAdapterBase::GetDataBufferThunk(void* user_data,
+ uint32_t element_count,
+ uint32_t element_size) {
+ return static_cast<ArrayOutputAdapterBase*>(user_data)->
+ GetDataBuffer(element_count, element_size);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/proxy_array_output.h b/chromium/ppapi/proxy/proxy_array_output.h
new file mode 100644
index 00000000000..6d15e0b8358
--- /dev/null
+++ b/chromium/ppapi/proxy/proxy_array_output.h
@@ -0,0 +1,138 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PROXY_ARRAY_OUTPUT_H_
+#define PPAPI_PROXY_PROXY_ARRAY_OUTPUT_H_
+
+#include <vector>
+
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "ppapi/c/pp_array_output.h"
+
+// Like ppapi/cpp/array_output.h file in the C++ wrappers but for use in the
+// proxy where we can't link to the C++ wrappers. This also adds a refcounted
+// version.
+//
+// Use ArrayOutputAdapter when calling a function that synchronously returns
+// an array of data. Use RefCountedArrayOutputAdapterWithStorage for
+// asynchronous returns:
+//
+// void OnCallbackComplete(
+// int32_t result,
+// scoped_refptr<RefCountedArrayOutputAdapter<PP_Resource> > output) {
+// // Vector is in output->output().
+// }
+//
+// void ScheduleCallback() {
+// base::scoped_refptr<RefCountedArrayOutputAdapter<PP_Resource> > output;
+//
+// callback = factory.NewOptionalCallback(&OnCallbackComplete, output);
+// DoSomethingAsynchronously(output->pp_array_output(),
+// callback.pp_completion_callback());
+// ...
+namespace ppapi {
+namespace proxy {
+
+// Non-templatized base class for the array output conversion. It provides the
+// C implementation of a PP_ArrayOutput whose callback function is implemented
+// as a virtual call on a derived class. Do not use directly, use one of the
+// derived classes below.
+class ArrayOutputAdapterBase {
+ public:
+ ArrayOutputAdapterBase() {
+ pp_array_output_.GetDataBuffer =
+ &ArrayOutputAdapterBase::GetDataBufferThunk;
+ pp_array_output_.user_data = this;
+ }
+ virtual ~ArrayOutputAdapterBase() {}
+
+ const PP_ArrayOutput& pp_array_output() { return pp_array_output_; }
+
+ protected:
+ virtual void* GetDataBuffer(uint32_t element_count,
+ uint32_t element_size) = 0;
+
+ private:
+ static void* GetDataBufferThunk(void* user_data,
+ uint32_t element_count,
+ uint32_t element_size);
+
+ PP_ArrayOutput pp_array_output_;
+
+ // Disallow copying and assignment. This will do the wrong thing for most
+ // subclasses.
+ ArrayOutputAdapterBase(const ArrayOutputAdapterBase&);
+ ArrayOutputAdapterBase& operator=(const ArrayOutputAdapterBase&);
+};
+
+// This adapter provides functionality for implementing a PP_ArrayOutput
+// structure as writing to a given vector object.
+//
+// This is generally used internally in the C++ wrapper objects to
+// write into an output parameter supplied by the plugin. If the element size
+// that the browser is writing does not match the size of the type we're using
+// this will assert and return NULL (which will cause the browser to fail the
+// call).
+//
+// Example that allows the browser to write into a given vector:
+// void DoFoo(std::vector<int>* results) {
+// ArrayOutputAdapter<int> adapter(results);
+// ppb_foo->DoFoo(adapter.pp_array_output());
+// }
+template<typename T>
+class ArrayOutputAdapter : public ArrayOutputAdapterBase {
+ public:
+ ArrayOutputAdapter(std::vector<T>* output) : output_(output) {}
+
+ protected:
+ // Two-step init for the "with storage" version below.
+ ArrayOutputAdapter() : output_(NULL) {}
+ void set_output(std::vector<T>* output) { output_ = output; }
+
+ // ArrayOutputAdapterBase implementation.
+ virtual void* GetDataBuffer(uint32_t element_count, uint32_t element_size) {
+ DCHECK(element_size == sizeof(T));
+ if (element_count == 0 || element_size != sizeof(T))
+ return NULL;
+ output_->resize(element_count);
+ return &(*output_)[0];
+ }
+
+ private:
+ std::vector<T>* output_;
+};
+
+template<typename T>
+class ArrayOutputAdapterWithStorage : public ArrayOutputAdapter<T> {
+ public:
+ ArrayOutputAdapterWithStorage() {
+ // Note: "this->" is required due to two-phase name lookup where it isn't
+ // allowed to look in the base class during parsing.
+ this->set_output(&output_storage_);
+ }
+
+ std::vector<T>& output() { return output_storage_; }
+
+ private:
+ std::vector<T> output_storage_;
+};
+
+// A reference counted version of ArrayOutputAdapterWithStorage. Since it
+// doesn't make much sense to heap-allocate one without storage, we don't
+// call it "with storage" to keep the name length under control.
+template<typename T>
+class RefCountedArrayOutputAdapter
+ : public ArrayOutputAdapterWithStorage<T>,
+ public base::RefCounted<RefCountedArrayOutputAdapter<T> > {
+ public:
+ RefCountedArrayOutputAdapter()
+ : ArrayOutputAdapterWithStorage<T>() {
+ }
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PROXY_ARRAY_OUTPUT_H_
diff --git a/chromium/ppapi/proxy/proxy_channel.cc b/chromium/ppapi/proxy/proxy_channel.cc
new file mode 100644
index 00000000000..b7f8a826ce3
--- /dev/null
+++ b/chromium/ppapi/proxy/proxy_channel.cc
@@ -0,0 +1,92 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/proxy_channel.h"
+
+#include "base/logging.h"
+#include "ipc/ipc_platform_file.h"
+#include "ipc/ipc_test_sink.h"
+
+#if defined(OS_NACL)
+#include <unistd.h>
+#endif
+
+namespace ppapi {
+namespace proxy {
+
+ProxyChannel::ProxyChannel()
+ : delegate_(NULL),
+ peer_pid_(base::kNullProcessId),
+ test_sink_(NULL) {
+}
+
+ProxyChannel::~ProxyChannel() {
+ DVLOG(1) << "ProxyChannel::~ProxyChannel()";
+}
+
+bool ProxyChannel::InitWithChannel(Delegate* delegate,
+ base::ProcessId peer_pid,
+ const IPC::ChannelHandle& channel_handle,
+ bool is_client) {
+ delegate_ = delegate;
+ peer_pid_ = peer_pid;
+ 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(), true,
+ delegate->GetShutdownEvent()));
+ return true;
+}
+
+void ProxyChannel::InitWithTestSink(IPC::TestSink* test_sink) {
+ DCHECK(!test_sink_);
+ test_sink_ = test_sink;
+#if !defined(OS_NACL)
+ peer_pid_ = base::GetCurrentProcId();
+#endif
+}
+
+void ProxyChannel::OnChannelError() {
+ channel_.reset();
+}
+
+#if defined(OS_POSIX) && !defined(OS_NACL)
+int ProxyChannel::TakeRendererFD() {
+ DCHECK(channel());
+ return channel()->TakeClientFileDescriptor();
+}
+#endif
+
+IPC::PlatformFileForTransit ProxyChannel::ShareHandleWithRemote(
+ base::PlatformFile handle,
+ bool should_close_source) {
+ // Channel could be closed if the plugin crashes.
+ if (!channel_.get()) {
+ if (should_close_source) {
+#if !defined(OS_NACL)
+ base::ClosePlatformFile(handle);
+#else
+ close(handle);
+#endif
+ }
+ return IPC::InvalidPlatformFileForTransit();
+ }
+ DCHECK(peer_pid_ != base::kNullProcessId);
+ return delegate_->ShareHandleWithRemote(handle, peer_pid_,
+ 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 ppapi
diff --git a/chromium/ppapi/proxy/proxy_channel.h b/chromium/ppapi/proxy/proxy_channel.h
new file mode 100644
index 00000000000..6c9f1f67f74
--- /dev/null
+++ b/chromium/ppapi/proxy/proxy_channel.h
@@ -0,0 +1,126 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PROXY_CHANNEL_H_
+#define PPAPI_PROXY_PROXY_CHANNEL_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/process/process.h"
+#include "ipc/ipc_listener.h"
+#include "ipc/ipc_platform_file.h"
+#include "ipc/ipc_sender.h"
+#include "ipc/ipc_sync_channel.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+
+namespace base {
+class MessageLoopProxy;
+class WaitableEvent;
+}
+
+namespace IPC {
+class TestSink;
+}
+
+namespace ppapi {
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT ProxyChannel
+ : public IPC::Listener,
+ public IPC::Sender {
+ public:
+ class PPAPI_PROXY_EXPORT Delegate {
+ public:
+ virtual ~Delegate() {}
+
+ // 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;
+
+ // Duplicates a handle to the provided object, returning one that is valid
+ // on the other side of the channel. This is part of the delegate interface
+ // because both sides of the channel may not have sufficient permission to
+ // duplicate handles directly. The implementation must provide the same
+ // guarantees as ProxyChannel::ShareHandleWithRemote below.
+ virtual IPC::PlatformFileForTransit ShareHandleWithRemote(
+ base::PlatformFile handle,
+ base::ProcessId remote_pid,
+ bool should_close_source) = 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. In this case, the peer PID will be the current
+ // process ID.
+ 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::Sender implementation.
+ virtual bool Send(IPC::Message* msg) OVERRIDE;
+
+ // IPC::Listener implementation.
+ virtual void OnChannelError() OVERRIDE;
+
+ // 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) && !defined(OS_NACL)
+ int TakeRendererFD();
+#endif
+
+ protected:
+ explicit ProxyChannel();
+
+ // 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,
+ base::ProcessId peer_pid,
+ 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_;
+
+ // PID of the remote process. Use this instead of the Channel::peer_pid since
+ // this is set synchronously on construction rather than waiting on the
+ // "hello" message from the peer (which introduces a race condition).
+ base::ProcessId peer_pid_;
+
+ // 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 ppapi
+
+#endif // PPAPI_PROXY_PROXY_CHANNEL_H_
diff --git a/chromium/ppapi/proxy/proxy_completion_callback_factory.h b/chromium/ppapi/proxy/proxy_completion_callback_factory.h
new file mode 100644
index 00000000000..c8dabf183b4
--- /dev/null
+++ b/chromium/ppapi/proxy/proxy_completion_callback_factory.h
@@ -0,0 +1,87 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PROXY_COMPLETION_CALLBACK_FACTORY_H_
+#define PPAPI_PROXY_PROXY_COMPLETION_CALLBACK_FACTORY_H_
+
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "ppapi/cpp/completion_callback.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+namespace ppapi {
+namespace proxy {
+
+// This class is just like pp::NonThreadSafeThreadTraits but rather than using
+// pp::Module::core (which doesn't exist), it uses Chrome threads which do.
+class ProxyNonThreadSafeThreadTraits {
+ public:
+ class RefCount {
+ public:
+ RefCount() : ref_(0) {
+#ifndef NDEBUG
+ message_loop_ = base::MessageLoop::current();
+#endif
+ }
+
+ ~RefCount() {
+#ifndef NDEBUG
+ DCHECK(message_loop_ == base::MessageLoop::current());
+#endif
+ }
+
+ int32_t AddRef() {
+#ifndef NDEBUG
+ DCHECK(message_loop_ == base::MessageLoop::current());
+#endif
+ return ++ref_;
+ }
+
+ int32_t Release() {
+#ifndef NDEBUG
+ DCHECK(message_loop_ == base::MessageLoop::current());
+#endif
+ DCHECK(ref_ > 0);
+ return --ref_;
+ }
+
+ private:
+ int32_t ref_;
+#ifndef NDEBUG
+ base::MessageLoop* message_loop_;
+#endif
+ };
+
+ // No-op lock class.
+ class Lock {
+ public:
+ Lock() {}
+ ~Lock() {}
+
+ void Acquire() {}
+ void Release() {}
+ };
+
+ // No-op AutoLock class.
+ class AutoLock {
+ public:
+ explicit AutoLock(Lock&) {}
+ ~AutoLock() {}
+ };
+};
+
+template<typename T>
+class ProxyCompletionCallbackFactory
+ : public pp::CompletionCallbackFactory<T, ProxyNonThreadSafeThreadTraits> {
+ public:
+ ProxyCompletionCallbackFactory()
+ : pp::CompletionCallbackFactory<T, ProxyNonThreadSafeThreadTraits>() {}
+ ProxyCompletionCallbackFactory(T* t)
+ : pp::CompletionCallbackFactory<T, ProxyNonThreadSafeThreadTraits>(t) {}
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PROXY_COMPLETION_CALLBACK_FACTORY_H_
diff --git a/chromium/ppapi/proxy/proxy_module.cc b/chromium/ppapi/proxy/proxy_module.cc
new file mode 100644
index 00000000000..885552d72e0
--- /dev/null
+++ b/chromium/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 ppapi {
+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 ppapi
diff --git a/chromium/ppapi/proxy/proxy_module.h b/chromium/ppapi/proxy/proxy_module.h
new file mode 100644
index 00000000000..1ee0b758261
--- /dev/null
+++ b/chromium/ppapi/proxy/proxy_module.h
@@ -0,0 +1,43 @@
+// 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"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+
+template<typename T> struct DefaultSingletonTraits;
+
+namespace ppapi {
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT 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 ppapi
+
+#endif // PPAPI_PROXY_PROXY_MODULE_H_
diff --git a/chromium/ppapi/proxy/proxy_object_var.cc b/chromium/ppapi/proxy/proxy_object_var.cc
new file mode 100644
index 00000000000..cc0054faa13
--- /dev/null
+++ b/chromium/ppapi/proxy/proxy_object_var.cc
@@ -0,0 +1,38 @@
+// 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_object_var.h"
+
+#include "base/logging.h"
+#include "ppapi/c/pp_var.h"
+
+using ppapi::proxy::PluginDispatcher;
+
+namespace ppapi {
+
+ProxyObjectVar::ProxyObjectVar(PluginDispatcher* dispatcher,
+ int32 host_var_id)
+ : dispatcher_(dispatcher),
+ host_var_id_(host_var_id),
+ user_data_(NULL) {
+ // Should be given valid objects or we'll crash later.
+ DCHECK(host_var_id_);
+}
+
+ProxyObjectVar::~ProxyObjectVar() {
+}
+
+ProxyObjectVar* ProxyObjectVar::AsProxyObjectVar() {
+ return this;
+}
+
+PP_VarType ProxyObjectVar::GetType() const {
+ return PP_VARTYPE_OBJECT;
+}
+
+void ProxyObjectVar::AssignVarID(int32 id) {
+ return Var::AssignVarID(id);
+}
+
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/proxy_object_var.h b/chromium/ppapi/proxy/proxy_object_var.h
new file mode 100644
index 00000000000..599105352ec
--- /dev/null
+++ b/chromium/ppapi/proxy/proxy_object_var.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_PROXY_OBJECT_VAR_H_
+#define PPAPI_PROXY_PROXY_OBJECT_VAR_H_
+
+#include "base/compiler_specific.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+
+namespace proxy {
+class PluginDispatcher;
+} // namespace proxy
+
+// Tracks a reference to an object var in the plugin side of the proxy. This
+// just stores the dispatcher and host var ID, and provides the interface for
+// integrating this with PP_Var creation.
+class PPAPI_PROXY_EXPORT ProxyObjectVar : public Var {
+ public:
+ ProxyObjectVar(proxy::PluginDispatcher* dispatcher,
+ int32 host_var_id);
+
+ virtual ~ProxyObjectVar();
+
+ // Var overrides.
+ virtual ProxyObjectVar* AsProxyObjectVar() OVERRIDE;
+ virtual PP_VarType GetType() const OVERRIDE;
+
+ proxy::PluginDispatcher* dispatcher() const { return dispatcher_; }
+ int32 host_var_id() const { return host_var_id_; }
+
+ void* user_data() const { return user_data_; }
+ void set_user_data(void* ud) { user_data_ = ud; }
+
+ // Expose AssignVarID on Var so the PluginResourceTracker can call us when
+ // it's creating IDs.
+ void AssignVarID(int32 id);
+
+ void clear_dispatcher() { dispatcher_ = NULL; }
+
+ private:
+ proxy::PluginDispatcher* dispatcher_;
+ int32 host_var_id_;
+
+ // When this object is created as representing a var implemented by the
+ // plugin, this stores the user data so that we can look it up later. See
+ // PluginVarTracker.
+ void* user_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProxyObjectVar);
+};
+
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PROXY_OBJECT_VAR_H_
diff --git a/chromium/ppapi/proxy/raw_var_data.cc b/chromium/ppapi/proxy/raw_var_data.cc
new file mode 100644
index 00000000000..a550c3fca05
--- /dev/null
+++ b/chromium/ppapi/proxy/raw_var_data.cc
@@ -0,0 +1,665 @@
+// Copyright (c) 2013 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/raw_var_data.h"
+
+#include <stack>
+
+#include "base/containers/hash_tables.h"
+#include "base/stl_util.h"
+#include "ipc/ipc_message.h"
+#include "ppapi/proxy/ppapi_param_traits.h"
+#include "ppapi/shared_impl/array_var.h"
+#include "ppapi/shared_impl/dictionary_var.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/scoped_pp_var.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/shared_impl/var_tracker.h"
+
+using std::make_pair;
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+// When sending array buffers, if the size is over 256K, we use shared
+// memory instead of sending the data over IPC. Light testing suggests
+// shared memory is much faster for 256K and larger messages.
+static const uint32 kMinimumArrayBufferSizeForShmem = 256 * 1024;
+static uint32 g_minimum_array_buffer_size_for_shmem =
+ kMinimumArrayBufferSizeForShmem;
+
+struct StackEntry {
+ StackEntry(PP_Var v, size_t i) : var(v), data_index(i) {}
+ PP_Var var;
+ size_t data_index;
+};
+
+// For a given PP_Var, returns the RawVarData associated with it, or creates a
+// new one if there is no existing one. The data is appended to |data| if it
+// is newly created. The index into |data| pointing to the result is returned.
+// |visited_map| keeps track of RawVarDatas that have already been created.
+size_t GetOrCreateRawVarData(const PP_Var& var,
+ base::hash_map<int64_t, size_t>* visited_map,
+ ScopedVector<RawVarData>* data) {
+ if (VarTracker::IsVarTypeRefcounted(var.type)) {
+ base::hash_map<int64_t, size_t>::iterator it = visited_map->find(
+ var.value.as_id);
+ if (it != visited_map->end()) {
+ return it->second;
+ } else {
+ data->push_back(RawVarData::Create(var.type));
+ (*visited_map)[var.value.as_id] = data->size() - 1;
+ }
+ } else {
+ data->push_back(RawVarData::Create(var.type));
+ }
+ return data->size() - 1;
+}
+
+bool CanHaveChildren(PP_Var var) {
+ return var.type == PP_VARTYPE_ARRAY || var.type == PP_VARTYPE_DICTIONARY;
+}
+
+} // namespace
+
+// RawVarDataGraph ------------------------------------------------------------
+RawVarDataGraph::RawVarDataGraph() {
+}
+
+RawVarDataGraph::~RawVarDataGraph() {
+}
+
+// This function uses a stack-based DFS search to traverse the var graph. Each
+// iteration, the top node on the stack examined. If the node has not been
+// visited yet (i.e. !initialized()) then it is added to the list of
+// |parent_ids| which contains all of the nodes on the path from the start node
+// to the current node. Each of that nodes children are examined. If they appear
+// in the list of |parent_ids| it means we have a cycle and we return NULL.
+// Otherwise, if they haven't been visited yet we add them to the stack, If the
+// node at the top of the stack has already been visited, then we pop it off the
+// stack and erase it from |parent_ids|.
+// static
+scoped_ptr<RawVarDataGraph> RawVarDataGraph::Create(const PP_Var& var,
+ PP_Instance instance) {
+ scoped_ptr<RawVarDataGraph> graph(new RawVarDataGraph);
+ // Map of |var.value.as_id| to a RawVarData index in RawVarDataGraph.
+ base::hash_map<int64_t, size_t> visited_map;
+ base::hash_set<int64_t> parent_ids;
+
+ std::stack<StackEntry> stack;
+ stack.push(StackEntry(var, GetOrCreateRawVarData(var, &visited_map,
+ &graph->data_)));
+
+ while (!stack.empty()) {
+ PP_Var current_var = stack.top().var;
+ RawVarData* current_var_data = graph->data_[stack.top().data_index];
+
+ if (current_var_data->initialized()) {
+ stack.pop();
+ if (CanHaveChildren(current_var))
+ parent_ids.erase(current_var.value.as_id);
+ continue;
+ }
+
+ if (CanHaveChildren(current_var))
+ parent_ids.insert(current_var.value.as_id);
+ if (!current_var_data->Init(current_var, instance)) {
+ NOTREACHED();
+ return scoped_ptr<RawVarDataGraph>();
+ }
+
+ // Add child nodes to the stack.
+ if (current_var.type == PP_VARTYPE_ARRAY) {
+ ArrayVar* array_var = ArrayVar::FromPPVar(current_var);
+ if (!array_var) {
+ NOTREACHED();
+ return scoped_ptr<RawVarDataGraph>();
+ }
+ for (ArrayVar::ElementVector::const_iterator iter =
+ array_var->elements().begin();
+ iter != array_var->elements().end();
+ ++iter) {
+ const PP_Var& child = iter->get();
+ // If a child of this node is already in parent_ids, we have a cycle so
+ // we just return null.
+ if (CanHaveChildren(child) && parent_ids.count(child.value.as_id) != 0)
+ return scoped_ptr<RawVarDataGraph>();
+ size_t child_id = GetOrCreateRawVarData(child, &visited_map,
+ &graph->data_);
+ static_cast<ArrayRawVarData*>(current_var_data)->AddChild(child_id);
+ if (!graph->data_[child_id]->initialized())
+ stack.push(StackEntry(child, child_id));
+ }
+ } else if (current_var.type == PP_VARTYPE_DICTIONARY) {
+ DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var);
+ if (!dict_var) {
+ NOTREACHED();
+ return scoped_ptr<RawVarDataGraph>();
+ }
+ for (DictionaryVar::KeyValueMap::const_iterator iter =
+ dict_var->key_value_map().begin();
+ iter != dict_var->key_value_map().end();
+ ++iter) {
+ const PP_Var& child = iter->second.get();
+ if (CanHaveChildren(child) && parent_ids.count(child.value.as_id) != 0)
+ return scoped_ptr<RawVarDataGraph>();
+ size_t child_id = GetOrCreateRawVarData(child, &visited_map,
+ &graph->data_);
+ static_cast<DictionaryRawVarData*>(
+ current_var_data)->AddChild(iter->first, child_id);
+ if (!graph->data_[child_id]->initialized())
+ stack.push(StackEntry(child, child_id));
+ }
+ }
+ }
+ return graph.Pass();
+}
+
+PP_Var RawVarDataGraph::CreatePPVar(PP_Instance instance) {
+ // Create and initialize each node in the graph.
+ std::vector<PP_Var> graph;
+ for (size_t i = 0; i < data_.size(); ++i)
+ graph.push_back(data_[i]->CreatePPVar(instance));
+ for (size_t i = 0; i < data_.size(); ++i)
+ data_[i]->PopulatePPVar(graph[i], graph);
+ // Everything except the root will have one extra ref. Remove that ref.
+ for (size_t i = 1; i < data_.size(); ++i)
+ ScopedPPVar(ScopedPPVar::PassRef(), graph[i]);
+ // The first element is the root.
+ return graph[0];
+}
+
+void RawVarDataGraph::Write(IPC::Message* m,
+ const HandleWriter& handle_writer) {
+ // Write the size, followed by each node in the graph.
+ m->WriteUInt32(static_cast<uint32_t>(data_.size()));
+ for (size_t i = 0; i < data_.size(); ++i) {
+ m->WriteInt(data_[i]->Type());
+ data_[i]->Write(m, handle_writer);
+ }
+}
+
+// static
+scoped_ptr<RawVarDataGraph> RawVarDataGraph::Read(const IPC::Message* m,
+ PickleIterator* iter) {
+ scoped_ptr<RawVarDataGraph> result(new RawVarDataGraph);
+ uint32_t size = 0;
+ if (!m->ReadUInt32(iter, &size))
+ return scoped_ptr<RawVarDataGraph>();
+ for (uint32_t i = 0; i < size; ++i) {
+ int32_t type;
+ if (!m->ReadInt(iter, &type))
+ return scoped_ptr<RawVarDataGraph>();
+ PP_VarType var_type = static_cast<PP_VarType>(type);
+ result->data_.push_back(RawVarData::Create(var_type));
+ if (!result->data_.back()->Read(var_type, m, iter))
+ return scoped_ptr<RawVarDataGraph>();
+ }
+ return result.Pass();
+}
+
+std::vector<SerializedHandle*> RawVarDataGraph::GetHandles() {
+ std::vector<SerializedHandle*> result;
+ for (size_t i = 0; i < data_.size(); ++i) {
+ SerializedHandle* handle = data_[i]->GetHandle();
+ if (handle)
+ result.push_back(handle);
+ }
+ return result;
+}
+
+// static
+void RawVarDataGraph::SetMinimumArrayBufferSizeForShmemForTest(
+ uint32 threshold) {
+ if (threshold == 0)
+ g_minimum_array_buffer_size_for_shmem = kMinimumArrayBufferSizeForShmem;
+ else
+ g_minimum_array_buffer_size_for_shmem = threshold;
+}
+
+// RawVarData ------------------------------------------------------------------
+
+// static
+RawVarData* RawVarData::Create(PP_VarType type) {
+ switch (type) {
+ case PP_VARTYPE_UNDEFINED:
+ case PP_VARTYPE_NULL:
+ case PP_VARTYPE_BOOL:
+ case PP_VARTYPE_INT32:
+ case PP_VARTYPE_DOUBLE:
+ case PP_VARTYPE_OBJECT:
+ return new BasicRawVarData();
+ case PP_VARTYPE_STRING:
+ return new StringRawVarData();
+ case PP_VARTYPE_ARRAY_BUFFER:
+ return new ArrayBufferRawVarData();
+ case PP_VARTYPE_ARRAY:
+ return new ArrayRawVarData();
+ case PP_VARTYPE_DICTIONARY:
+ return new DictionaryRawVarData();
+ }
+ NOTREACHED();
+ return NULL;
+}
+
+RawVarData::RawVarData() : initialized_(false) {
+}
+
+RawVarData::~RawVarData() {
+}
+
+SerializedHandle* RawVarData::GetHandle() {
+ return NULL;
+}
+
+// BasicRawVarData -------------------------------------------------------------
+BasicRawVarData::BasicRawVarData() {
+}
+
+BasicRawVarData::~BasicRawVarData() {
+}
+
+PP_VarType BasicRawVarData::Type() {
+ return var_.type;
+}
+
+bool BasicRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
+ var_ = var;
+ initialized_ = true;
+ return true;
+}
+
+PP_Var BasicRawVarData::CreatePPVar(PP_Instance instance) {
+ return var_;
+}
+
+void BasicRawVarData::PopulatePPVar(const PP_Var& var,
+ const std::vector<PP_Var>& graph) {
+}
+
+void BasicRawVarData::Write(
+ IPC::Message* m,
+ const HandleWriter& handle_writer) {
+ 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_OBJECT:
+ m->WriteInt64(var_.value.as_id);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+bool BasicRawVarData::Read(PP_VarType type,
+ const IPC::Message* m,
+ PickleIterator* iter) {
+ PP_Var result;
+ result.type = type;
+ 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.
+ break;
+ case PP_VARTYPE_BOOL: {
+ bool bool_value;
+ if (!m->ReadBool(iter, &bool_value))
+ return false;
+ result.value.as_bool = PP_FromBool(bool_value);
+ break;
+ }
+ case PP_VARTYPE_INT32:
+ if (!m->ReadInt(iter, &result.value.as_int))
+ return false;
+ break;
+ case PP_VARTYPE_DOUBLE:
+ if (!IPC::ParamTraits<double>::Read(m, iter, &result.value.as_double))
+ return false;
+ break;
+ case PP_VARTYPE_OBJECT:
+ if (!m->ReadInt64(iter, &result.value.as_id))
+ return false;
+ break;
+ default:
+ NOTREACHED();
+ return false;
+ }
+ var_ = result;
+ return true;
+}
+
+// StringRawVarData ------------------------------------------------------------
+StringRawVarData::StringRawVarData() {
+}
+
+StringRawVarData::~StringRawVarData() {
+}
+
+PP_VarType StringRawVarData::Type() {
+ return PP_VARTYPE_STRING;
+}
+
+bool StringRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
+ DCHECK(var.type == PP_VARTYPE_STRING);
+ StringVar* string_var = StringVar::FromPPVar(var);
+ if (!string_var)
+ return false;
+ data_ = string_var->value();
+ initialized_ = true;
+ return true;
+}
+
+PP_Var StringRawVarData::CreatePPVar(PP_Instance instance) {
+ return StringVar::SwapValidatedUTF8StringIntoPPVar(&data_);
+}
+
+void StringRawVarData::PopulatePPVar(const PP_Var& var,
+ const std::vector<PP_Var>& graph) {
+}
+
+void StringRawVarData::Write(IPC::Message* m,
+ const HandleWriter& handle_writer) {
+ m->WriteString(data_);
+}
+
+bool StringRawVarData::Read(PP_VarType type,
+ const IPC::Message* m,
+ PickleIterator* iter) {
+ if (!m->ReadString(iter, &data_))
+ return false;
+ return true;
+}
+
+// ArrayBufferRawVarData -------------------------------------------------------
+ArrayBufferRawVarData::ArrayBufferRawVarData() {
+}
+
+ArrayBufferRawVarData::~ArrayBufferRawVarData() {
+}
+
+PP_VarType ArrayBufferRawVarData::Type() {
+ return PP_VARTYPE_ARRAY_BUFFER;
+}
+
+bool ArrayBufferRawVarData::Init(const PP_Var& var,
+ PP_Instance instance) {
+ DCHECK(var.type == PP_VARTYPE_ARRAY_BUFFER);
+ ArrayBufferVar* buffer_var = ArrayBufferVar::FromPPVar(var);
+ if (!buffer_var)
+ return false;
+ bool using_shmem = false;
+ if (buffer_var->ByteLength() >= g_minimum_array_buffer_size_for_shmem &&
+ instance != 0) {
+ int host_handle_id;
+ base::SharedMemoryHandle plugin_handle;
+ using_shmem = buffer_var->CopyToNewShmem(instance,
+ &host_handle_id,
+ &plugin_handle);
+ if (using_shmem) {
+ if (host_handle_id != -1) {
+ DCHECK(!base::SharedMemory::IsHandleValid(plugin_handle));
+ DCHECK(PpapiGlobals::Get()->IsPluginGlobals());
+ type_ = ARRAY_BUFFER_SHMEM_HOST;
+ host_shm_handle_id_ = host_handle_id;
+ } else {
+ DCHECK(base::SharedMemory::IsHandleValid(plugin_handle));
+ DCHECK(PpapiGlobals::Get()->IsHostGlobals());
+ type_ = ARRAY_BUFFER_SHMEM_PLUGIN;
+ plugin_shm_handle_ = SerializedHandle(plugin_handle,
+ buffer_var->ByteLength());
+ }
+ }
+ }
+ if (!using_shmem) {
+ type_ = ARRAY_BUFFER_NO_SHMEM;
+ data_ = std::string(static_cast<const char*>(buffer_var->Map()),
+ buffer_var->ByteLength());
+ }
+ initialized_ = true;
+ return true;
+}
+
+PP_Var ArrayBufferRawVarData::CreatePPVar(PP_Instance instance) {
+ PP_Var result = PP_MakeUndefined();
+ switch (type_) {
+ case ARRAY_BUFFER_SHMEM_HOST: {
+ base::SharedMemoryHandle host_handle;
+ uint32 size_in_bytes;
+ bool ok = PpapiGlobals::Get()->GetVarTracker()->
+ StopTrackingSharedMemoryHandle(host_shm_handle_id_,
+ instance,
+ &host_handle,
+ &size_in_bytes);
+ if (ok) {
+ result = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
+ size_in_bytes, host_handle);
+ } else {
+ LOG(ERROR) << "Couldn't find array buffer id: " << host_shm_handle_id_;
+ return PP_MakeUndefined();
+ }
+ break;
+ }
+ case ARRAY_BUFFER_SHMEM_PLUGIN: {
+ result = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
+ plugin_shm_handle_.size(),
+ plugin_shm_handle_.shmem());
+ break;
+ }
+ case ARRAY_BUFFER_NO_SHMEM: {
+ result = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
+ static_cast<uint32>(data_.size()), data_.data());
+ break;
+ }
+ default:
+ NOTREACHED();
+ return PP_MakeUndefined();
+ }
+ DCHECK(result.type == PP_VARTYPE_ARRAY_BUFFER);
+ return result;
+}
+
+void ArrayBufferRawVarData::PopulatePPVar(const PP_Var& var,
+ const std::vector<PP_Var>& graph) {
+}
+
+void ArrayBufferRawVarData::Write(
+ IPC::Message* m,
+ const HandleWriter& handle_writer) {
+ m->WriteInt(type_);
+ switch (type_) {
+ case ARRAY_BUFFER_SHMEM_HOST:
+ m->WriteInt(host_shm_handle_id_);
+ break;
+ case ARRAY_BUFFER_SHMEM_PLUGIN:
+ handle_writer.Run(m, plugin_shm_handle_);
+ break;
+ case ARRAY_BUFFER_NO_SHMEM:
+ m->WriteString(data_);
+ break;
+ }
+}
+
+bool ArrayBufferRawVarData::Read(PP_VarType type,
+ const IPC::Message* m,
+ PickleIterator* iter) {
+ int shmem_type;
+ if (!m->ReadInt(iter, &shmem_type))
+ return false;
+ type_ = static_cast<ShmemType>(shmem_type);
+ switch (type_) {
+ case ARRAY_BUFFER_SHMEM_HOST:
+ if (!m->ReadInt(iter, &host_shm_handle_id_))
+ return false;
+ break;
+ case ARRAY_BUFFER_SHMEM_PLUGIN:
+ if (!IPC::ParamTraits<SerializedHandle>::Read(
+ m, iter, &plugin_shm_handle_)) {
+ return false;
+ }
+ break;
+ case ARRAY_BUFFER_NO_SHMEM:
+ if (!m->ReadString(iter, &data_))
+ return false;
+ break;
+ default:
+ // We read an invalid ID.
+ NOTREACHED();
+ return false;
+ }
+ return true;
+}
+
+SerializedHandle* ArrayBufferRawVarData::GetHandle() {
+ if (type_ == ARRAY_BUFFER_SHMEM_PLUGIN && plugin_shm_handle_.size() != 0)
+ return &plugin_shm_handle_;
+ return NULL;
+}
+
+// ArrayRawVarData -------------------------------------------------------------
+ArrayRawVarData::ArrayRawVarData() {
+}
+
+ArrayRawVarData::~ArrayRawVarData() {
+}
+
+void ArrayRawVarData::AddChild(size_t element) {
+ children_.push_back(element);
+}
+
+PP_VarType ArrayRawVarData::Type() {
+ return PP_VARTYPE_ARRAY;
+}
+
+bool ArrayRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
+ initialized_ = true;
+ DCHECK(var.type == PP_VARTYPE_ARRAY);
+ initialized_ = true;
+ return true;
+}
+
+PP_Var ArrayRawVarData::CreatePPVar(PP_Instance instance) {
+ return (new ArrayVar())->GetPPVar();
+}
+
+void ArrayRawVarData::PopulatePPVar(const PP_Var& var,
+ const std::vector<PP_Var>& graph) {
+ if (var.type != PP_VARTYPE_ARRAY) {
+ NOTREACHED();
+ return;
+ }
+ ArrayVar* array_var = ArrayVar::FromPPVar(var);
+ DCHECK(array_var->elements().empty());
+ for (size_t i = 0; i < children_.size(); ++i)
+ array_var->elements().push_back(ScopedPPVar(graph[children_[i]]));
+}
+
+void ArrayRawVarData::Write(IPC::Message* m,
+ const HandleWriter& handle_writer) {
+ m->WriteUInt32(static_cast<uint32_t>(children_.size()));
+ for (size_t i = 0; i < children_.size(); ++i)
+ m->WriteUInt32(static_cast<uint32_t>(children_[i]));
+}
+
+bool ArrayRawVarData::Read(PP_VarType type,
+ const IPC::Message* m,
+ PickleIterator* iter) {
+ uint32_t size;
+ if (!m->ReadUInt32(iter, &size))
+ return false;
+ for (uint32_t i = 0; i < size; ++i) {
+ uint32_t index;
+ if (!m->ReadUInt32(iter, &index))
+ return false;
+ children_.push_back(index);
+ }
+ return true;
+}
+
+// DictionaryRawVarData --------------------------------------------------------
+DictionaryRawVarData::DictionaryRawVarData() {
+}
+
+DictionaryRawVarData::~DictionaryRawVarData() {
+}
+
+void DictionaryRawVarData::AddChild(const std::string& key,
+ size_t value) {
+ children_.push_back(make_pair(key, value));
+}
+
+PP_VarType DictionaryRawVarData::Type() {
+ return PP_VARTYPE_DICTIONARY;
+}
+
+bool DictionaryRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
+ DCHECK(var.type == PP_VARTYPE_DICTIONARY);
+ initialized_ = true;
+ return true;
+}
+
+PP_Var DictionaryRawVarData::CreatePPVar(PP_Instance instance) {
+ return (new DictionaryVar())->GetPPVar();
+}
+
+void DictionaryRawVarData::PopulatePPVar(const PP_Var& var,
+ const std::vector<PP_Var>& graph) {
+ if (var.type != PP_VARTYPE_DICTIONARY) {
+ NOTREACHED();
+ return;
+ }
+ DictionaryVar* dictionary_var = DictionaryVar::FromPPVar(var);
+ DCHECK(dictionary_var->key_value_map().empty());
+ for (size_t i = 0; i < children_.size(); ++i) {
+ bool success = dictionary_var->SetWithStringKey(children_[i].first,
+ graph[children_[i].second]);
+ DCHECK(success);
+ }
+}
+
+void DictionaryRawVarData::Write(
+ IPC::Message* m,
+ const HandleWriter& handle_writer) {
+ m->WriteUInt32(static_cast<uint32_t>(children_.size()));
+ for (size_t i = 0; i < children_.size(); ++i) {
+ m->WriteString(children_[i].first);
+ m->WriteUInt32(static_cast<uint32_t>(children_[i].second));
+ }
+}
+
+bool DictionaryRawVarData::Read(PP_VarType type,
+ const IPC::Message* m,
+ PickleIterator* iter) {
+ uint32_t size;
+ if (!m->ReadUInt32(iter, &size))
+ return false;
+ for (uint32_t i = 0; i < size; ++i) {
+ std::string key;
+ uint32_t value;
+ if (!m->ReadString(iter, &key))
+ return false;
+ if (!m->ReadUInt32(iter, &value))
+ return false;
+ children_.push_back(make_pair(key, value));
+ }
+ return true;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/raw_var_data.h b/chromium/ppapi/proxy/raw_var_data.h
new file mode 100644
index 00000000000..c7981d38ff7
--- /dev/null
+++ b/chromium/ppapi/proxy/raw_var_data.h
@@ -0,0 +1,261 @@
+// Copyright (c) 2013 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_RAW_VAR_DATA_H_
+#define PPAPI_PROXY_RAW_VAR_DATA_H_
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/ppapi_param_traits.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/proxy/serialized_handle.h"
+
+class PickleIterator;
+
+namespace IPC {
+class Message;
+}
+
+namespace ppapi {
+namespace proxy {
+
+class RawVarData;
+
+typedef base::Callback<void(IPC::Message*, const SerializedHandle&)>
+ HandleWriter;
+
+// Contains the data associated with a graph of connected PP_Vars. Useful for
+// serializing/deserializing a graph of PP_Vars. First we compute the transitive
+// closure of the given PP_Var to find all PP_Vars which are referenced by that
+// var. A RawVarData object is created for each of these vars. We then write
+// data contained in each RawVarData to the message. The format looks like this:
+// idx | size | (number of vars in the graph)
+// 0 | var type |
+// | var data |
+// 1 | var type |
+// | var data |
+// 2 | var type |
+// | var data |
+// | .... |
+//
+// Vars that reference other vars (such as Arrays or Dictionaries) use indices
+// into the message to denote which PP_Var is pointed to.
+class PPAPI_PROXY_EXPORT RawVarDataGraph {
+ public:
+ // Construct a RawVarDataGraph from a given root PP_Var. A null pointer
+ // is returned upon failure.
+ static scoped_ptr<RawVarDataGraph> Create(const PP_Var& var,
+ PP_Instance instance);
+
+ // Constructs an empty RawVarDataGraph.
+ RawVarDataGraph();
+ ~RawVarDataGraph();
+
+ // Construct a new PP_Var from the graph. All of the PP_Vars referenced by
+ // the returned PP_Var are also constructed. Each PP_Var created has a
+ // ref-count equal to the number of references it has in the graph of vars.
+ // The returned var (the "root") has one additional reference.
+ PP_Var CreatePPVar(PP_Instance instance);
+
+ // Write the graph to a message using the given HandleWriter.
+ void Write(IPC::Message* m, const HandleWriter& handle_writer);
+
+ // Create a RawVarDataGraph from the given message.
+ static scoped_ptr<RawVarDataGraph> Read(const IPC::Message* m,
+ PickleIterator* iter);
+
+ // Returns a vector of SerializedHandles associated with this RawVarDataGraph.
+ // Ownership of the pointers remains with the elements of the RawVarDataGraph.
+ std::vector<SerializedHandle*> GetHandles();
+
+ // Sets the threshold size at which point we switch from transmitting
+ // array buffers in IPC messages to using shared memory. This is only used
+ // for testing purposes where we need to transmit small buffers using shmem
+ // (in order to have fast tests).
+ static void SetMinimumArrayBufferSizeForShmemForTest(uint32 threshold);
+
+ // A list of the nodes in the graph.
+ ScopedVector<RawVarData> data_;
+};
+
+// Abstract base class for the data contained in a PP_Var.
+class RawVarData {
+ public:
+ // Create a new, empty RawVarData for the given type.
+ static RawVarData* Create(PP_VarType type);
+ RawVarData();
+ virtual ~RawVarData();
+
+ // Returns the type of the PP_Var represented by the RawVarData.
+ virtual PP_VarType Type() = 0;
+
+ // Initializes a RawVarData from a PP_Var. Returns true on success.
+ virtual bool Init(const PP_Var& var, PP_Instance instance) = 0;
+
+ // Create a PP_Var from the raw data contained in this object.
+ virtual PP_Var CreatePPVar(PP_Instance instance) = 0;
+ // Some PP_Vars may require 2-step initialization. For example, they may
+ // reference other PP_Vars which had not yet been created when |CreatePPVar|
+ // was called. The original var created with |CreatePPVar| is passed back in,
+ // along with the graph it is a part of to be initialized.
+ virtual void PopulatePPVar(const PP_Var& var,
+ const std::vector<PP_Var>& graph) = 0;
+
+ // Writes the RawVarData to a message.
+ virtual void Write(IPC::Message* m,
+ const HandleWriter& handle_writer) = 0;
+ // Reads the RawVarData from a message. Returns true on success.
+ virtual bool Read(PP_VarType type,
+ const IPC::Message* m,
+ PickleIterator* iter) = 0;
+
+ // Returns a SerializedHandle associated with this RawVarData or NULL if none
+ // exists. Ownership of the pointer remains with the RawVarData.
+ virtual SerializedHandle* GetHandle();
+
+ bool initialized() { return initialized_; }
+
+ protected:
+ bool initialized_;
+};
+
+// A RawVarData class for PP_Vars which are value types.
+class BasicRawVarData : public RawVarData {
+ public:
+ BasicRawVarData();
+ virtual ~BasicRawVarData();
+
+ // RawVarData implementation.
+ virtual PP_VarType Type() OVERRIDE;
+ virtual bool Init(const PP_Var& var, PP_Instance instance) OVERRIDE;
+ virtual PP_Var CreatePPVar(PP_Instance instance) OVERRIDE;
+ virtual void PopulatePPVar(const PP_Var& var,
+ const std::vector<PP_Var>& graph) OVERRIDE;
+ virtual void Write(IPC::Message* m,
+ const HandleWriter& handle_writer) OVERRIDE;
+ virtual bool Read(PP_VarType type,
+ const IPC::Message* m,
+ PickleIterator* iter) OVERRIDE;
+
+ private:
+ PP_Var var_;
+};
+
+// A RawVarData class for string PP_Vars.
+class StringRawVarData : public RawVarData {
+ public:
+ StringRawVarData();
+ virtual ~StringRawVarData();
+
+ // RawVarData implementation.
+ virtual PP_VarType Type() OVERRIDE;
+ virtual bool Init(const PP_Var& var, PP_Instance instance) OVERRIDE;
+ virtual PP_Var CreatePPVar(PP_Instance instance) OVERRIDE;
+ virtual void PopulatePPVar(const PP_Var& var,
+ const std::vector<PP_Var>& graph) OVERRIDE;
+ virtual void Write(IPC::Message* m,
+ const HandleWriter& handle_writer) OVERRIDE;
+ virtual bool Read(PP_VarType type,
+ const IPC::Message* m,
+ PickleIterator* iter) OVERRIDE;
+
+ private:
+ // The data in the string.
+ std::string data_;
+};
+
+// A RawVarData class for array buffer PP_Vars.
+class ArrayBufferRawVarData : public RawVarData {
+ public:
+ // Enum for array buffer message types.
+ enum ShmemType {
+ ARRAY_BUFFER_NO_SHMEM,
+ ARRAY_BUFFER_SHMEM_HOST,
+ ARRAY_BUFFER_SHMEM_PLUGIN,
+ };
+
+ ArrayBufferRawVarData();
+ virtual ~ArrayBufferRawVarData();
+
+ // RawVarData implementation.
+ virtual PP_VarType Type() OVERRIDE;
+ virtual bool Init(const PP_Var& var, PP_Instance instance) OVERRIDE;
+ virtual PP_Var CreatePPVar(PP_Instance instance) OVERRIDE;
+ virtual void PopulatePPVar(const PP_Var& var,
+ const std::vector<PP_Var>& graph) OVERRIDE;
+ virtual void Write(IPC::Message* m,
+ const HandleWriter& handle_writer) OVERRIDE;
+ virtual bool Read(PP_VarType type,
+ const IPC::Message* m,
+ PickleIterator* iter) OVERRIDE;
+ virtual SerializedHandle* GetHandle() OVERRIDE;
+
+ private:
+ // The type of the storage underlying the array buffer.
+ ShmemType type_;
+ // The data in the buffer. Valid for |type_| == ARRAY_BUFFER_NO_SHMEM.
+ std::string data_;
+ // Host shmem handle. Valid for |type_| == ARRAY_BUFFER_SHMEM_HOST.
+ int host_shm_handle_id_;
+ // Plugin shmem handle. Valid for |type_| == ARRAY_BUFFER_SHMEM_PLUGIN.
+ SerializedHandle plugin_shm_handle_;
+};
+
+// A RawVarData class for array PP_Vars.
+class ArrayRawVarData : public RawVarData {
+ public:
+ ArrayRawVarData();
+ virtual ~ArrayRawVarData();
+
+ void AddChild(size_t element);
+
+ // RawVarData implementation.
+ virtual PP_VarType Type() OVERRIDE;
+ virtual bool Init(const PP_Var& var, PP_Instance instance) OVERRIDE;
+ virtual PP_Var CreatePPVar(PP_Instance instance) OVERRIDE;
+ virtual void PopulatePPVar(const PP_Var& var,
+ const std::vector<PP_Var>& graph) OVERRIDE;
+ virtual void Write(IPC::Message* m,
+ const HandleWriter& handle_writer) OVERRIDE;
+ virtual bool Read(PP_VarType type,
+ const IPC::Message* m,
+ PickleIterator* iter) OVERRIDE;
+
+ private:
+ std::vector<size_t> children_;
+};
+
+// A RawVarData class for dictionary PP_Vars.
+class DictionaryRawVarData : public RawVarData {
+ public:
+ DictionaryRawVarData();
+ virtual ~DictionaryRawVarData();
+
+ void AddChild(const std::string& key, size_t value);
+
+ // RawVarData implementation.
+ virtual PP_VarType Type() OVERRIDE;
+ virtual bool Init(const PP_Var& var, PP_Instance instance) OVERRIDE;
+ virtual PP_Var CreatePPVar(PP_Instance instance) OVERRIDE;
+ virtual void PopulatePPVar(const PP_Var& var,
+ const std::vector<PP_Var>& graph) OVERRIDE;
+ virtual void Write(IPC::Message* m,
+ const HandleWriter& handle_writer) OVERRIDE;
+ virtual bool Read(PP_VarType type,
+ const IPC::Message* m,
+ PickleIterator* iter) OVERRIDE;
+
+ private:
+ std::vector<std::pair<std::string, size_t> > children_;
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_RAW_VAR_DATA_H_
diff --git a/chromium/ppapi/proxy/raw_var_data_unittest.cc b/chromium/ppapi/proxy/raw_var_data_unittest.cc
new file mode 100644
index 00000000000..2ee69144f61
--- /dev/null
+++ b/chromium/ppapi/proxy/raw_var_data_unittest.cc
@@ -0,0 +1,189 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/raw_var_data.h"
+
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/shared_impl/array_var.h"
+#include "ppapi/shared_impl/dictionary_var.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/scoped_pp_var.h"
+#include "ppapi/shared_impl/test_globals.h"
+#include "ppapi/shared_impl/unittest_utils.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/shared_impl/var_tracker.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+void DefaultHandleWriter(IPC::Message* m, const SerializedHandle& handle) {
+ IPC::ParamTraits<SerializedHandle>::Write(m, handle);
+}
+
+class RawVarDataTest : public testing::Test {
+ public:
+ RawVarDataTest() {}
+ ~RawVarDataTest() {}
+
+ // testing::Test implementation.
+ virtual void SetUp() {
+ ProxyLock::Acquire();
+ }
+ virtual void TearDown() {
+ ASSERT_TRUE(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().empty());
+ ProxyLock::Release();
+ }
+
+ private:
+ TestGlobals globals_;
+};
+
+bool WriteAndRead(const PP_Var& var, PP_Var* result) {
+ PP_Instance dummy_instance = 1234;
+ scoped_ptr<RawVarDataGraph> expected_data(RawVarDataGraph::Create(
+ var, dummy_instance));
+ if (!expected_data)
+ return false;
+ IPC::Message m;
+ expected_data->Write(&m, base::Bind(&DefaultHandleWriter));
+ PickleIterator iter(m);
+ scoped_ptr<RawVarDataGraph> actual_data(RawVarDataGraph::Read(&m, &iter));
+ *result = actual_data->CreatePPVar(dummy_instance);
+ return true;
+}
+
+// Assumes a ref for var.
+bool WriteReadAndCompare(const PP_Var& var) {
+ ScopedPPVar expected(ScopedPPVar::PassRef(), var);
+ PP_Var result;
+ bool success = WriteAndRead(expected.get(), &result);
+ if (!success)
+ return false;
+ ScopedPPVar actual(ScopedPPVar::PassRef(), result);
+ return TestEqual(expected.get(), actual.get());
+}
+
+} // namespace
+
+TEST_F(RawVarDataTest, SimpleTest) {
+ EXPECT_TRUE(WriteReadAndCompare(PP_MakeUndefined()));
+ EXPECT_TRUE(WriteReadAndCompare(PP_MakeNull()));
+ EXPECT_TRUE(WriteReadAndCompare(PP_MakeInt32(100)));
+ EXPECT_TRUE(WriteReadAndCompare(PP_MakeBool(PP_TRUE)));
+ EXPECT_TRUE(WriteReadAndCompare(PP_MakeDouble(53.75)));
+ PP_Var object;
+ object.type = PP_VARTYPE_OBJECT;
+ object.value.as_id = 10;
+ EXPECT_TRUE(WriteReadAndCompare(object));
+}
+
+TEST_F(RawVarDataTest, StringTest) {
+ EXPECT_TRUE(WriteReadAndCompare(StringVar::StringToPPVar("")));
+ EXPECT_TRUE(WriteReadAndCompare(StringVar::StringToPPVar("hello world!")));
+}
+
+TEST_F(RawVarDataTest, ArrayBufferTest) {
+ std::string data = "hello world!";
+ PP_Var var = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
+ data.size(), data.data());
+ EXPECT_TRUE(WriteReadAndCompare(var));
+ var = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
+ 0, static_cast<void*>(NULL));
+ EXPECT_TRUE(WriteReadAndCompare(var));
+ // TODO(raymes): add tests for shmem type array buffers.
+}
+
+TEST_F(RawVarDataTest, DictionaryArrayTest) {
+ // Empty array.
+ scoped_refptr<ArrayVar> array(new ArrayVar);
+ ScopedPPVar release_array(ScopedPPVar::PassRef(), array->GetPPVar());
+ EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));
+
+ size_t index = 0;
+
+ // Array with primitives.
+ array->Set(index++, PP_MakeUndefined());
+ array->Set(index++, PP_MakeNull());
+ array->Set(index++, PP_MakeInt32(100));
+ array->Set(index++, PP_MakeBool(PP_FALSE));
+ array->Set(index++, PP_MakeDouble(0.123));
+ EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));
+
+ // Array with 2 references to the same string.
+ ScopedPPVar release_string(
+ ScopedPPVar::PassRef(), StringVar::StringToPPVar("abc"));
+ array->Set(index++, release_string.get());
+ array->Set(index++, release_string.get());
+ EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));
+
+ // Array with nested array that references the same string.
+ scoped_refptr<ArrayVar> array2(new ArrayVar);
+ ScopedPPVar release_array2(ScopedPPVar::PassRef(), array2->GetPPVar());
+ array2->Set(0, release_string.get());
+ array->Set(index++, release_array2.get());
+ EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));
+
+ // Empty dictionary.
+ scoped_refptr<DictionaryVar> dictionary(new DictionaryVar);
+ ScopedPPVar release_dictionary(ScopedPPVar::PassRef(),
+ dictionary->GetPPVar());
+ EXPECT_TRUE(WriteReadAndCompare(dictionary->GetPPVar()));
+
+ // Dictionary with primitives.
+ dictionary->SetWithStringKey("1", PP_MakeUndefined());
+ dictionary->SetWithStringKey("2", PP_MakeNull());
+ dictionary->SetWithStringKey("3", PP_MakeInt32(-100));
+ dictionary->SetWithStringKey("4", PP_MakeBool(PP_TRUE));
+ dictionary->SetWithStringKey("5", PP_MakeDouble(-103.52));
+ EXPECT_TRUE(WriteReadAndCompare(dictionary->GetPPVar()));
+
+ // Dictionary with 2 references to the same string.
+ dictionary->SetWithStringKey("6", release_string.get());
+ dictionary->SetWithStringKey("7", release_string.get());
+ EXPECT_TRUE(WriteReadAndCompare(dictionary->GetPPVar()));
+
+ // Dictionary with nested dictionary that references the same string.
+ scoped_refptr<DictionaryVar> dictionary2(new DictionaryVar);
+ ScopedPPVar release_dictionary2(ScopedPPVar::PassRef(),
+ dictionary2->GetPPVar());
+ dictionary2->SetWithStringKey("abc", release_string.get());
+ dictionary->SetWithStringKey("8", release_dictionary2.get());
+ EXPECT_TRUE(WriteReadAndCompare(dictionary->GetPPVar()));
+
+ // Array with dictionary.
+ array->Set(index++, release_dictionary.get());
+ EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));
+
+ // Array with dictionary with array.
+ array2->Set(0, PP_MakeInt32(100));
+ dictionary->SetWithStringKey("9", release_array2.get());
+ EXPECT_TRUE(WriteReadAndCompare(array->GetPPVar()));
+
+ // Array <-> dictionary cycle.
+ dictionary->SetWithStringKey("10", release_array.get());
+ PP_Var result;
+ ASSERT_FALSE(WriteAndRead(release_dictionary.get(), &result));
+ // Break the cycle.
+ // TODO(raymes): We need some better machinery for releasing vars with
+ // cycles. Remove the code below once we have that.
+ dictionary->DeleteWithStringKey("10");
+
+ // Array with self references.
+ array->Set(index, release_array.get());
+ ASSERT_FALSE(WriteAndRead(release_array.get(), &result));
+ // Break the self reference.
+ array->Set(index, PP_MakeUndefined());
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/resource_creation_proxy.cc b/chromium/ppapi/proxy/resource_creation_proxy.cc
new file mode 100644
index 00000000000..53cade1e91a
--- /dev/null
+++ b/chromium/ppapi/proxy/resource_creation_proxy.cc
@@ -0,0 +1,464 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/resource_creation_proxy.h"
+
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_size.h"
+#include "ppapi/proxy/audio_input_resource.h"
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/ext_crx_file_system_private_resource.h"
+#include "ppapi/proxy/file_chooser_resource.h"
+#include "ppapi/proxy/file_io_resource.h"
+#include "ppapi/proxy/file_system_resource.h"
+#include "ppapi/proxy/flash_drm_resource.h"
+#include "ppapi/proxy/flash_font_file_resource.h"
+#include "ppapi/proxy/flash_menu_resource.h"
+#include "ppapi/proxy/graphics_2d_resource.h"
+#include "ppapi/proxy/host_resolver_private_resource.h"
+#include "ppapi/proxy/host_resolver_resource.h"
+#include "ppapi/proxy/net_address_resource.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.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_file_ref_proxy.h"
+#include "ppapi/proxy/ppb_flash_message_loop_proxy.h"
+#include "ppapi/proxy/ppb_graphics_3d_proxy.h"
+#include "ppapi/proxy/ppb_image_data_proxy.h"
+#include "ppapi/proxy/ppb_network_monitor_private_proxy.h"
+#include "ppapi/proxy/ppb_tcp_socket_private_proxy.h"
+#include "ppapi/proxy/ppb_tcp_socket_proxy.h"
+#include "ppapi/proxy/ppb_video_decoder_proxy.h"
+#include "ppapi/proxy/ppb_x509_certificate_private_proxy.h"
+#include "ppapi/proxy/printing_resource.h"
+#include "ppapi/proxy/talk_resource.h"
+#include "ppapi/proxy/tcp_server_socket_private_resource.h"
+#include "ppapi/proxy/truetype_font_resource.h"
+#include "ppapi/proxy/udp_socket_private_resource.h"
+#include "ppapi/proxy/udp_socket_resource.h"
+#include "ppapi/proxy/url_loader_resource.h"
+#include "ppapi/proxy/url_request_info_resource.h"
+#include "ppapi/proxy/url_response_info_resource.h"
+#include "ppapi/proxy/video_capture_resource.h"
+#include "ppapi/proxy/video_destination_resource.h"
+#include "ppapi/proxy/video_source_resource.h"
+#include "ppapi/proxy/websocket_resource.h"
+#include "ppapi/shared_impl/api_id.h"
+#include "ppapi/shared_impl/host_resource.h"
+#include "ppapi/shared_impl/ppb_audio_config_shared.h"
+#include "ppapi/shared_impl/ppb_input_event_shared.h"
+#include "ppapi/shared_impl/ppb_resource_array_shared.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_image_data_api.h"
+
+using ppapi::thunk::ResourceCreationAPI;
+
+namespace ppapi {
+namespace proxy {
+
+ResourceCreationProxy::ResourceCreationProxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher) {
+}
+
+ResourceCreationProxy::~ResourceCreationProxy() {
+}
+
+// static
+InterfaceProxy* ResourceCreationProxy::Create(Dispatcher* dispatcher) {
+ return new ResourceCreationProxy(dispatcher);
+}
+
+PP_Resource ResourceCreationProxy::CreateFileIO(PP_Instance instance) {
+ return (new FileIOResource(GetConnection(), instance))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateFileRef(PP_Instance instance,
+ PP_Resource file_system,
+ const char* path) {
+ return PPB_FileRef_Proxy::CreateProxyResource(instance, file_system, path);
+}
+
+PP_Resource ResourceCreationProxy::CreateFileRef(
+ const PPB_FileRef_CreateInfo& create_info) {
+ return PPB_FileRef_Proxy::DeserializeFileRef(create_info);
+}
+
+PP_Resource ResourceCreationProxy::CreateFileSystem(
+ PP_Instance instance,
+ PP_FileSystemType type) {
+ return (new FileSystemResource(GetConnection(), instance,
+ type))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateIsolatedFileSystem(
+ PP_Instance instance,
+ const char* fsid) {
+ FileSystemResource* fs = new FileSystemResource(
+ GetConnection(), instance, PP_FILESYSTEMTYPE_ISOLATED);
+ fs->InitIsolatedFileSystem(fsid);
+ return fs->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateIMEInputEvent(
+ PP_Instance instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ struct PP_Var text,
+ uint32_t segment_number,
+ const uint32_t* segment_offsets,
+ int32_t target_segment,
+ uint32_t selection_start,
+ uint32_t selection_end) {
+ return PPB_InputEvent_Shared::CreateIMEInputEvent(
+ OBJECT_IS_PROXY, instance, type, time_stamp, text, segment_number,
+ segment_offsets, target_segment, selection_start, selection_end);
+}
+
+PP_Resource ResourceCreationProxy::CreateKeyboardInputEvent(
+ PP_Instance instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ uint32_t modifiers,
+ uint32_t key_code,
+ struct PP_Var character_text) {
+ return PPB_InputEvent_Shared::CreateKeyboardInputEvent(
+ OBJECT_IS_PROXY, instance, type, time_stamp, modifiers, key_code,
+ character_text);
+}
+
+PP_Resource ResourceCreationProxy::CreateMouseInputEvent(
+ PP_Instance instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ uint32_t modifiers,
+ PP_InputEvent_MouseButton mouse_button,
+ const PP_Point* mouse_position,
+ int32_t click_count,
+ const PP_Point* mouse_movement) {
+ return PPB_InputEvent_Shared::CreateMouseInputEvent(
+ OBJECT_IS_PROXY, instance, type, time_stamp, modifiers,
+ mouse_button, mouse_position, click_count, mouse_movement);
+}
+
+PP_Resource ResourceCreationProxy::CreateTouchInputEvent(
+ PP_Instance instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ uint32_t modifiers) {
+ return PPB_InputEvent_Shared::CreateTouchInputEvent(
+ OBJECT_IS_PROXY, instance, type, time_stamp, modifiers);
+}
+
+PP_Resource ResourceCreationProxy::CreateResourceArray(
+ PP_Instance instance,
+ const PP_Resource elements[],
+ uint32_t size) {
+ PPB_ResourceArray_Shared* object = new PPB_ResourceArray_Shared(
+ OBJECT_IS_PROXY, instance, elements, size);
+ return object->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateTrueTypeFont(
+ PP_Instance instance,
+ const PP_TrueTypeFontDesc_Dev* desc) {
+ return (new TrueTypeFontResource(GetConnection(),
+ instance, *desc))->GetReference();
+
+}
+
+PP_Resource ResourceCreationProxy::CreateURLLoader(PP_Instance instance) {
+ return (new URLLoaderResource(GetConnection(), instance))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateURLRequestInfo(
+ PP_Instance instance) {
+ return (new URLRequestInfoResource(
+ GetConnection(), instance, URLRequestInfoData()))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateWheelInputEvent(
+ PP_Instance instance,
+ PP_TimeTicks time_stamp,
+ uint32_t modifiers,
+ const PP_FloatPoint* wheel_delta,
+ const PP_FloatPoint* wheel_ticks,
+ PP_Bool scroll_by_page) {
+ return PPB_InputEvent_Shared::CreateWheelInputEvent(
+ OBJECT_IS_PROXY, instance, time_stamp, modifiers,
+ wheel_delta, wheel_ticks, scroll_by_page);
+}
+
+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::CreateAudioTrusted(PP_Instance instance) {
+ // Proxied plugins can't create trusted audio devices.
+ return 0;
+}
+
+PP_Resource ResourceCreationProxy::CreateAudioConfig(
+ PP_Instance instance,
+ PP_AudioSampleRate sample_rate,
+ uint32_t sample_frame_count) {
+ return PPB_AudioConfig_Shared::Create(
+ OBJECT_IS_PROXY, instance, sample_rate, sample_frame_count);
+}
+
+PP_Resource ResourceCreationProxy::CreateFileChooser(
+ PP_Instance instance,
+ PP_FileChooserMode_Dev mode,
+ const PP_Var& accept_types) {
+ scoped_refptr<StringVar> string_var = StringVar::FromPPVar(accept_types);
+ std::string str = string_var.get() ? string_var->value() : std::string();
+ return (new FileChooserResource(GetConnection(), instance, mode, str.c_str()))
+ ->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateGraphics2D(PP_Instance instance,
+ const PP_Size* size,
+ PP_Bool is_always_opaque) {
+ return (new Graphics2DResource(GetConnection(), instance, *size,
+ is_always_opaque))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateGraphics3D(
+ PP_Instance instance,
+ PP_Resource share_context,
+ const int32_t* attrib_list) {
+ return PPB_Graphics3D_Proxy::CreateProxyResource(
+ instance, share_context, attrib_list);
+}
+
+PP_Resource ResourceCreationProxy::CreateGraphics3DRaw(
+ PP_Instance instance,
+ 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::CreateHostResolver(PP_Instance instance) {
+ return (new HostResolverResource(GetConnection(), instance))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateHostResolverPrivate(
+ PP_Instance instance) {
+ return (new HostResolverPrivateResource(
+ GetConnection(), instance))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateImageData(
+ PP_Instance instance,
+ PP_ImageDataFormat format,
+ const PP_Size* size,
+ PP_Bool init_to_zero) {
+ // On the plugin side, we create PlatformImageData resources for trusted
+ // plugins and SimpleImageData resources for untrusted ones.
+ PPB_ImageData_Shared::ImageDataType type =
+#if !defined(OS_NACL)
+ PPB_ImageData_Shared::PLATFORM;
+#else
+ PPB_ImageData_Shared::SIMPLE;
+#endif
+ return PPB_ImageData_Proxy::CreateProxyResource(
+ instance, type,
+ format, *size, init_to_zero);
+}
+
+PP_Resource ResourceCreationProxy::CreateImageDataSimple(
+ PP_Instance instance,
+ PP_ImageDataFormat format,
+ const PP_Size* size,
+ PP_Bool init_to_zero) {
+ return PPB_ImageData_Proxy::CreateProxyResource(
+ instance,
+ PPB_ImageData_Shared::SIMPLE,
+ format, *size, init_to_zero);
+}
+
+PP_Resource ResourceCreationProxy::CreateNetAddressFromIPv4Address(
+ PP_Instance instance,
+ const PP_NetAddress_IPv4* ipv4_addr) {
+ return (new NetAddressResource(GetConnection(), instance,
+ *ipv4_addr))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateNetAddressFromIPv6Address(
+ PP_Instance instance,
+ const PP_NetAddress_IPv6* ipv6_addr) {
+ return (new NetAddressResource(GetConnection(), instance,
+ *ipv6_addr))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateNetAddressFromNetAddressPrivate(
+ PP_Instance instance,
+ const PP_NetAddress_Private& private_addr) {
+ return (new NetAddressResource(GetConnection(), instance,
+ private_addr))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateNetworkMonitor(
+ PP_Instance instance,
+ PPB_NetworkMonitor_Callback callback,
+ void* user_data) {
+ return PPB_NetworkMonitor_Private_Proxy::CreateProxyResource(
+ instance, callback, user_data);
+}
+
+PP_Resource ResourceCreationProxy::CreatePrinting(PP_Instance instance) {
+ return (new PrintingResource(GetConnection(), instance))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateTCPServerSocketPrivate(
+ PP_Instance instance) {
+ return (new TCPServerSocketPrivateResource(GetConnection(), instance))->
+ GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateTCPSocket(
+ PP_Instance instance) {
+ return PPB_TCPSocket_Proxy::CreateProxyResource(instance);
+}
+
+PP_Resource ResourceCreationProxy::CreateTCPSocketPrivate(
+ PP_Instance instance) {
+ return PPB_TCPSocket_Private_Proxy::CreateProxyResource(instance);
+}
+
+PP_Resource ResourceCreationProxy::CreateUDPSocket(PP_Instance instance) {
+ return (new UDPSocketResource(GetConnection(), instance))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateUDPSocketPrivate(
+ PP_Instance instance) {
+ return (new UDPSocketPrivateResource(
+ GetConnection(), instance))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateVideoDestination(
+ PP_Instance instance) {
+ return (new VideoDestinationResource(GetConnection(),
+ instance))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateVideoSource(
+ PP_Instance instance) {
+ return (new VideoSourceResource(GetConnection(), instance))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateWebSocket(PP_Instance instance) {
+ return (new WebSocketResource(GetConnection(), instance))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateX509CertificatePrivate(
+ PP_Instance instance) {
+ return PPB_X509Certificate_Private_Proxy::CreateProxyResource(instance);
+}
+
+#if !defined(OS_NACL)
+PP_Resource ResourceCreationProxy::CreateAudioInput(
+ PP_Instance instance) {
+ return (new AudioInputResource(GetConnection(), instance))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateBroker(PP_Instance instance) {
+ return PPB_Broker_Proxy::CreateProxyResource(instance);
+}
+
+PP_Resource ResourceCreationProxy::CreateBrowserFont(
+ PP_Instance instance,
+ const PP_BrowserFont_Trusted_Description* description) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+ return PluginGlobals::Get()->CreateBrowserFont(
+ GetConnection(), instance, *description, dispatcher->preferences());
+}
+
+PP_Resource ResourceCreationProxy::CreateBuffer(PP_Instance instance,
+ uint32_t size) {
+ return PPB_Buffer_Proxy::CreateProxyResource(instance, size);
+}
+
+PP_Resource ResourceCreationProxy::CreateFlashDRM(PP_Instance instance) {
+ return (new FlashDRMResource(GetConnection(), instance))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateFlashFontFile(
+ PP_Instance instance,
+ const PP_BrowserFont_Trusted_Description* description,
+ PP_PrivateFontCharset charset) {
+ return (new FlashFontFileResource(
+ GetConnection(), instance, description, charset))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateFlashMenu(
+ PP_Instance instance,
+ const PP_Flash_Menu* menu_data) {
+ scoped_refptr<FlashMenuResource> flash_menu(
+ new FlashMenuResource(GetConnection(), instance));
+ if (!flash_menu->Initialize(menu_data))
+ return 0;
+ return flash_menu->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateFlashMessageLoop(
+ PP_Instance instance) {
+ return PPB_Flash_MessageLoop_Proxy::CreateProxyResource(instance);
+}
+
+PP_Resource ResourceCreationProxy::CreateScrollbar(PP_Instance instance,
+ PP_Bool vertical) {
+ NOTIMPLEMENTED(); // Not proxied yet.
+ return 0;
+}
+
+PP_Resource ResourceCreationProxy::CreateTalk(PP_Instance instance) {
+ return (new TalkResource(GetConnection(), instance))->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateVideoCapture(PP_Instance instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+ return (new VideoCaptureResource(GetConnection(), instance, dispatcher))
+ ->GetReference();
+}
+
+PP_Resource ResourceCreationProxy::CreateVideoDecoder(
+ PP_Instance instance,
+ PP_Resource context3d_id,
+ PP_VideoDecoder_Profile profile) {
+ return PPB_VideoDecoder_Proxy::CreateProxyResource(
+ instance, context3d_id, profile);
+}
+
+#endif // !defined(OS_NACL)
+
+bool ResourceCreationProxy::Send(IPC::Message* msg) {
+ return dispatcher()->Send(msg);
+}
+
+bool ResourceCreationProxy::OnMessageReceived(const IPC::Message& msg) {
+ return false;
+}
+
+Connection ResourceCreationProxy::GetConnection() {
+ return Connection(PluginGlobals::Get()->GetBrowserSender(), dispatcher());
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/resource_creation_proxy.h b/chromium/ppapi/proxy/resource_creation_proxy.h
new file mode 100644
index 00000000000..47b40a83927
--- /dev/null
+++ b/chromium/ppapi/proxy/resource_creation_proxy.h
@@ -0,0 +1,191 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_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/interface_proxy.h"
+#include "ppapi/proxy/serialized_structs.h"
+#include "ppapi/thunk/resource_creation_api.h"
+
+struct PP_Size;
+
+namespace ppapi {
+
+class HostResource;
+
+namespace proxy {
+
+struct Connection;
+class Dispatcher;
+
+class ResourceCreationProxy : public InterfaceProxy,
+ public thunk::ResourceCreationAPI {
+ public:
+ explicit ResourceCreationProxy(Dispatcher* dispatcher);
+ virtual ~ResourceCreationProxy();
+
+ // Factory function used for registration (normal code can just use the
+ // constructor).
+ static InterfaceProxy* Create(Dispatcher* dispatcher);
+
+ // ResourceCreationAPI (called in plugin).
+ virtual PP_Resource CreateFileIO(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateFileRef(PP_Instance instance,
+ PP_Resource file_system,
+ const char* path) OVERRIDE;
+ virtual PP_Resource CreateFileRef(
+ const PPB_FileRef_CreateInfo& create_info) OVERRIDE;
+ virtual PP_Resource CreateFileSystem(PP_Instance instance,
+ PP_FileSystemType type) OVERRIDE;
+ virtual PP_Resource CreateIsolatedFileSystem(
+ PP_Instance instance,
+ const char* fsid) OVERRIDE;
+ virtual PP_Resource CreateIMEInputEvent(PP_Instance instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ struct PP_Var text,
+ uint32_t segment_number,
+ const uint32_t* segment_offsets,
+ int32_t target_segment,
+ uint32_t selection_start,
+ uint32_t selection_end) OVERRIDE;
+ virtual PP_Resource CreateKeyboardInputEvent(
+ PP_Instance instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ uint32_t modifiers,
+ uint32_t key_code,
+ PP_Var character_text) OVERRIDE;
+ virtual PP_Resource CreateMouseInputEvent(
+ PP_Instance instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ uint32_t modifiers,
+ PP_InputEvent_MouseButton mouse_button,
+ const PP_Point* mouse_position,
+ int32_t click_count,
+ const PP_Point* mouse_movement) OVERRIDE;
+ virtual PP_Resource CreateTouchInputEvent(
+ PP_Instance instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ uint32_t modifiers) OVERRIDE;
+ virtual PP_Resource CreateResourceArray(PP_Instance instance,
+ const PP_Resource elements[],
+ uint32_t size) OVERRIDE;
+ virtual PP_Resource CreateTrueTypeFont(
+ PP_Instance instance,
+ const PP_TrueTypeFontDesc_Dev* desc) OVERRIDE;
+ virtual PP_Resource CreateURLLoader(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateURLRequestInfo(
+ PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateWheelInputEvent(
+ PP_Instance instance,
+ PP_TimeTicks time_stamp,
+ uint32_t modifiers,
+ const PP_FloatPoint* wheel_delta,
+ const PP_FloatPoint* wheel_ticks,
+ PP_Bool scroll_by_page) OVERRIDE;
+
+ virtual PP_Resource CreateAudio(PP_Instance instance,
+ PP_Resource config_id,
+ PPB_Audio_Callback audio_callback,
+ void* user_data) OVERRIDE;
+ virtual PP_Resource CreateAudioTrusted(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateAudioConfig(PP_Instance instance,
+ PP_AudioSampleRate sample_rate,
+ uint32_t sample_frame_count) OVERRIDE;
+ virtual PP_Resource CreateFileChooser(PP_Instance instance,
+ PP_FileChooserMode_Dev mode,
+ const PP_Var& accept_types) 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_Resource share_context,
+ const int32_t* attrib_list) OVERRIDE;
+ virtual PP_Resource CreateGraphics3DRaw(
+ PP_Instance instance,
+ PP_Resource share_context,
+ const int32_t* attrib_list) OVERRIDE;
+ virtual PP_Resource CreateHostResolver(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateHostResolverPrivate(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateImageData(PP_Instance instance,
+ PP_ImageDataFormat format,
+ const PP_Size* size,
+ PP_Bool init_to_zero) OVERRIDE;
+ virtual PP_Resource CreateImageDataSimple(PP_Instance instance,
+ PP_ImageDataFormat format,
+ const PP_Size* size,
+ PP_Bool init_to_zero) OVERRIDE;
+ virtual PP_Resource CreateNetAddressFromIPv4Address(
+ PP_Instance instance,
+ const PP_NetAddress_IPv4* ipv4_addr) OVERRIDE;
+ virtual PP_Resource CreateNetAddressFromIPv6Address(
+ PP_Instance instance,
+ const PP_NetAddress_IPv6* ipv6_addr) OVERRIDE;
+ virtual PP_Resource CreateNetAddressFromNetAddressPrivate(
+ PP_Instance instance,
+ const PP_NetAddress_Private& private_addr) OVERRIDE;
+ virtual PP_Resource CreateNetworkMonitor(
+ PP_Instance instance,
+ PPB_NetworkMonitor_Callback callback,
+ void* user_data) OVERRIDE;
+ virtual PP_Resource CreatePrinting(PP_Instance) OVERRIDE;
+ virtual PP_Resource CreateTCPServerSocketPrivate(
+ PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateTCPSocket(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateTCPSocketPrivate(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateUDPSocket(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateUDPSocketPrivate(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateVideoDestination(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateVideoSource(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateWebSocket(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateX509CertificatePrivate(
+ PP_Instance instance) OVERRIDE;
+#if !defined(OS_NACL)
+ virtual PP_Resource CreateAudioInput(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateBroker(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateBrowserFont(
+ PP_Instance instance,
+ const PP_BrowserFont_Trusted_Description* description) OVERRIDE;
+ virtual PP_Resource CreateBuffer(PP_Instance instance,
+ uint32_t size) OVERRIDE;
+ virtual PP_Resource CreateFlashDRM(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateFlashFontFile(
+ PP_Instance instance,
+ const PP_BrowserFont_Trusted_Description* description,
+ PP_PrivateFontCharset charset) OVERRIDE;
+ virtual PP_Resource CreateFlashMenu(PP_Instance instance,
+ const PP_Flash_Menu* menu_data) OVERRIDE;
+ virtual PP_Resource CreateFlashMessageLoop(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateScrollbar(PP_Instance instance,
+ PP_Bool vertical) OVERRIDE;
+ virtual PP_Resource CreateTalk(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateVideoCapture(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateVideoDecoder(
+ PP_Instance instance,
+ PP_Resource context3d_id,
+ PP_VideoDecoder_Profile profile) OVERRIDE;
+#endif // !defined(OS_NACL)
+
+ virtual bool Send(IPC::Message* msg) OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+
+ private:
+ Connection GetConnection();
+ DISALLOW_COPY_AND_ASSIGN(ResourceCreationProxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_RESOURCE_CREATION_PROXY_H_
diff --git a/chromium/ppapi/proxy/resource_message_params.cc b/chromium/ppapi/proxy/resource_message_params.cc
new file mode 100644
index 00000000000..e4858da55f3
--- /dev/null
+++ b/chromium/ppapi/proxy/resource_message_params.cc
@@ -0,0 +1,204 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/resource_message_params.h"
+
+#include "base/logging.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace ppapi {
+namespace proxy {
+
+ResourceMessageParams::SerializedHandles::SerializedHandles()
+ : should_close_(false) {
+}
+
+ResourceMessageParams::SerializedHandles::~SerializedHandles() {
+ if (should_close_) {
+ for (std::vector<SerializedHandle>::iterator iter = data_.begin();
+ iter != data_.end(); ++iter) {
+ iter->Close();
+ }
+ }
+}
+
+ResourceMessageParams::ResourceMessageParams()
+ : pp_resource_(0),
+ sequence_(0),
+ handles_(new SerializedHandles()) {
+}
+
+ResourceMessageParams::ResourceMessageParams(PP_Resource resource,
+ int32_t sequence)
+ : pp_resource_(resource),
+ sequence_(sequence),
+ handles_(new SerializedHandles()) {
+}
+
+ResourceMessageParams::~ResourceMessageParams() {
+}
+
+void ResourceMessageParams::Serialize(IPC::Message* msg) const {
+ WriteHeader(msg);
+ WriteHandles(msg);
+}
+
+bool ResourceMessageParams::Deserialize(const IPC::Message* msg,
+ PickleIterator* iter) {
+ return ReadHeader(msg, iter) && ReadHandles(msg, iter);
+}
+
+void ResourceMessageParams::WriteHeader(IPC::Message* msg) const {
+ IPC::ParamTraits<PP_Resource>::Write(msg, pp_resource_);
+ IPC::ParamTraits<int32_t>::Write(msg, sequence_);
+}
+
+void ResourceMessageParams::WriteHandles(IPC::Message* msg) const {
+ IPC::ParamTraits<std::vector<SerializedHandle> >::Write(msg,
+ handles_->data());
+}
+
+bool ResourceMessageParams::ReadHeader(const IPC::Message* msg,
+ PickleIterator* iter) {
+ DCHECK(handles_->data().empty());
+ handles_->set_should_close(true);
+ return IPC::ParamTraits<PP_Resource>::Read(msg, iter, &pp_resource_) &&
+ IPC::ParamTraits<int32_t>::Read(msg, iter, &sequence_);
+}
+
+bool ResourceMessageParams::ReadHandles(const IPC::Message* msg,
+ PickleIterator* iter) {
+ return IPC::ParamTraits<std::vector<SerializedHandle> >::Read(
+ msg, iter, &handles_->data());
+}
+
+void ResourceMessageParams::ConsumeHandles() const {
+ // Note: we must not invalidate the handles. This is used for converting
+ // handles from the host OS to NaCl, and that conversion will not work if we
+ // invalidate the handles (see HandleConverter).
+ handles_->set_should_close(false);
+}
+
+SerializedHandle ResourceMessageParams::TakeHandleOfTypeAtIndex(
+ size_t index,
+ SerializedHandle::Type type) const {
+ SerializedHandle handle;
+ std::vector<SerializedHandle>& data = handles_->data();
+ if (index < data.size() && data[index].type() == type) {
+ handle = data[index];
+ data[index] = SerializedHandle();
+ }
+ return handle;
+}
+
+bool ResourceMessageParams::TakeSharedMemoryHandleAtIndex(
+ size_t index,
+ base::SharedMemoryHandle* handle) const {
+ SerializedHandle serialized = TakeHandleOfTypeAtIndex(
+ index, SerializedHandle::SHARED_MEMORY);
+ if (!serialized.is_shmem())
+ return false;
+ *handle = serialized.shmem();
+ return true;
+}
+
+bool ResourceMessageParams::TakeSocketHandleAtIndex(
+ size_t index,
+ IPC::PlatformFileForTransit* handle) const {
+ SerializedHandle serialized = TakeHandleOfTypeAtIndex(
+ index, SerializedHandle::SOCKET);
+ if (!serialized.is_socket())
+ return false;
+ *handle = serialized.descriptor();
+ return true;
+}
+
+bool ResourceMessageParams::TakeFileHandleAtIndex(
+ size_t index,
+ IPC::PlatformFileForTransit* handle) const {
+ SerializedHandle serialized = TakeHandleOfTypeAtIndex(
+ index, SerializedHandle::FILE);
+ if (!serialized.is_file())
+ return false;
+ *handle = serialized.descriptor();
+ return true;
+}
+
+void ResourceMessageParams::TakeAllSharedMemoryHandles(
+ std::vector<base::SharedMemoryHandle>* handles) const {
+ for (size_t i = 0; i < handles_->data().size(); ++i) {
+ base::SharedMemoryHandle handle;
+ if (TakeSharedMemoryHandleAtIndex(i, &handle))
+ handles->push_back(handle);
+ }
+}
+
+void ResourceMessageParams::AppendHandle(const SerializedHandle& handle) const {
+ handles_->data().push_back(handle);
+}
+
+ResourceMessageCallParams::ResourceMessageCallParams()
+ : ResourceMessageParams(),
+ has_callback_(0) {
+}
+
+ResourceMessageCallParams::ResourceMessageCallParams(PP_Resource resource,
+ int32_t sequence)
+ : ResourceMessageParams(resource, sequence),
+ has_callback_(0) {
+}
+
+ResourceMessageCallParams::~ResourceMessageCallParams() {
+}
+
+void ResourceMessageCallParams::Serialize(IPC::Message* msg) const {
+ ResourceMessageParams::Serialize(msg);
+ IPC::ParamTraits<bool>::Write(msg, has_callback_);
+}
+
+bool ResourceMessageCallParams::Deserialize(const IPC::Message* msg,
+ PickleIterator* iter) {
+ if (!ResourceMessageParams::Deserialize(msg, iter))
+ return false;
+ return IPC::ParamTraits<bool>::Read(msg, iter, &has_callback_);
+}
+
+ResourceMessageReplyParams::ResourceMessageReplyParams()
+ : ResourceMessageParams(),
+ result_(PP_OK) {
+}
+
+ResourceMessageReplyParams::ResourceMessageReplyParams(PP_Resource resource,
+ int32_t sequence)
+ : ResourceMessageParams(resource, sequence),
+ result_(PP_OK) {
+}
+
+ResourceMessageReplyParams::~ResourceMessageReplyParams() {
+}
+
+void ResourceMessageReplyParams::Serialize(IPC::Message* msg) const {
+ // Rather than serialize all of ResourceMessageParams first, we serialize all
+ // non-handle data first, then the handles. When transferring to NaCl on
+ // Windows, we need to be able to translate Windows-style handles to POSIX-
+ // style handles, and it's easier to put all the regular stuff at the front.
+ WriteReplyHeader(msg);
+ WriteHandles(msg);
+}
+
+bool ResourceMessageReplyParams::Deserialize(const IPC::Message* msg,
+ PickleIterator* iter) {
+ return (ReadHeader(msg, iter) &&
+ IPC::ParamTraits<int32_t>::Read(msg, iter, &result_) &&
+ ReadHandles(msg, iter));
+}
+
+void ResourceMessageReplyParams::WriteReplyHeader(IPC::Message* msg) const {
+ WriteHeader(msg);
+ IPC::ParamTraits<int32_t>::Write(msg, result_);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/resource_message_params.h b/chromium/ppapi/proxy/resource_message_params.h
new file mode 100644
index 00000000000..21b0f73800b
--- /dev/null
+++ b/chromium/ppapi/proxy/resource_message_params.h
@@ -0,0 +1,211 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_RESOURCE_MESSAGE_PARAMS_H_
+#define PPAPI_PROXY_RESOURCE_MESSAGE_PARAMS_H_
+
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "ipc/ipc_message_utils.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/proxy/serialized_handle.h"
+
+namespace ppapi {
+namespace proxy {
+
+// Common parameters for resource call and reply params structures below.
+class PPAPI_PROXY_EXPORT ResourceMessageParams {
+ public:
+ virtual ~ResourceMessageParams();
+
+ PP_Resource pp_resource() const { return pp_resource_; }
+ int32_t sequence() const { return sequence_; }
+
+ // Note that the caller doesn't take ownership of the returned handles.
+ const std::vector<SerializedHandle>& handles() const {
+ return handles_->data();
+ }
+
+ // Makes ResourceMessageParams leave its handles open, even if they weren't
+ // taken using a Take.* function. After this call, no Take.* calls are
+ // allowed.
+ void ConsumeHandles() const;
+
+ // Returns the handle at the given index if it exists and is of the given
+ // type. The corresponding slot in the list is set to an invalid handle.
+ // If the index doesn't exist or the handle isn't of the given type, returns
+ // an invalid handle.
+ // Note that the caller is responsible for closing the returned handle, if it
+ // is valid.
+ SerializedHandle TakeHandleOfTypeAtIndex(size_t index,
+ SerializedHandle::Type type) const;
+
+ // Helper functions to return shared memory, socket or file handles passed in
+ // the params struct.
+ // If the index has a valid handle of the given type, it will be placed in the
+ // output parameter, the corresponding slot in the list will be set to an
+ // invalid handle, and the function will return true. If the handle doesn't
+ // exist or is a different type, the functions will return false and the
+ // output parameter will be untouched.
+ //
+ // Note: 1) the handle could still be a "null" or invalid handle of the right
+ // type and the functions will succeed.
+ // 2) the caller is responsible for closing the returned handle, if it
+ // is valid.
+ bool TakeSharedMemoryHandleAtIndex(size_t index,
+ base::SharedMemoryHandle* handle) const;
+ bool TakeSocketHandleAtIndex(size_t index,
+ IPC::PlatformFileForTransit* handle) const;
+ bool TakeFileHandleAtIndex(size_t index,
+ IPC::PlatformFileForTransit* handle) const;
+ void TakeAllSharedMemoryHandles(
+ std::vector<base::SharedMemoryHandle>* handles) const;
+
+ // Appends the given handle to the list of handles sent with the call or
+ // reply.
+ void AppendHandle(const SerializedHandle& handle) const;
+
+ protected:
+ ResourceMessageParams();
+ ResourceMessageParams(PP_Resource resource, int32_t sequence);
+
+ virtual void Serialize(IPC::Message* msg) const;
+ virtual bool Deserialize(const IPC::Message* msg, PickleIterator* iter);
+
+ // Writes everything except the handles to |msg|.
+ void WriteHeader(IPC::Message* msg) const;
+ // Writes the handles to |msg|.
+ void WriteHandles(IPC::Message* msg) const;
+ // Matching deserialize helpers.
+ bool ReadHeader(const IPC::Message* msg, PickleIterator* iter);
+ bool ReadHandles(const IPC::Message* msg, PickleIterator* iter);
+
+ private:
+ class SerializedHandles
+ : public base::RefCountedThreadSafe<SerializedHandles> {
+ public:
+ SerializedHandles();
+ ~SerializedHandles();
+
+ void set_should_close(bool value) { should_close_ = value; }
+ std::vector<SerializedHandle>& data() { return data_; }
+
+ private:
+ friend class base::RefCountedThreadSafe<SerializedHandles>;
+
+ // Whether the handles stored in |data_| should be closed when this object
+ // goes away.
+ //
+ // It is set to true by ResourceMessageParams::Deserialize(), so that the
+ // receiving side of the params (the host side for
+ // ResourceMessageCallParams; the plugin side for
+ // ResourceMessageReplyParams) will close those handles which haven't been
+ // taken using any of the Take*() methods.
+ bool should_close_;
+ std::vector<SerializedHandle> data_;
+ };
+
+ PP_Resource pp_resource_;
+
+ // Identifier for this message. Sequence numbers are quasi-unique within a
+ // resource, but will overlap between different resource objects.
+ //
+ // If you send a lot of messages, the ID may wrap around. This is OK. All IDs
+ // are valid and 0 and -1 aren't special, so those cases won't confuse us.
+ // In practice, if you send more than 4 billion messages for a resource, the
+ // old ones will be long gone and there will be no collisions.
+ //
+ // If there is a malicious plugin (or exceptionally bad luck) that causes a
+ // wraparound and collision the worst that will happen is that we can get
+ // confused between different callbacks. But since these can only cause
+ // confusion within the plugin and within callbacks on the same resource,
+ // there shouldn't be a security problem.
+ int32_t sequence_;
+
+ // A list of all handles transferred in the message. Handles go here so that
+ // the NaCl adapter can extract them generally when it rewrites them to
+ // go between Windows and NaCl (Posix) apps.
+ // TODO(yzshen): Mark it as mutable so that we can take/append handles using a
+ // const reference. We need to change all the callers and make it not mutable.
+ mutable scoped_refptr<SerializedHandles> handles_;
+};
+
+// Parameters common to all ResourceMessage "Call" requests.
+class PPAPI_PROXY_EXPORT ResourceMessageCallParams
+ : public ResourceMessageParams {
+ public:
+ ResourceMessageCallParams();
+ ResourceMessageCallParams(PP_Resource resource, int32_t sequence);
+ virtual ~ResourceMessageCallParams();
+
+ void set_has_callback() { has_callback_ = true; }
+ bool has_callback() const { return has_callback_; }
+
+ virtual void Serialize(IPC::Message* msg) const OVERRIDE;
+ virtual bool Deserialize(const IPC::Message* msg,
+ PickleIterator* iter) OVERRIDE;
+
+ private:
+ bool has_callback_;
+};
+
+// Parameters common to all ResourceMessage "Reply" requests.
+class PPAPI_PROXY_EXPORT ResourceMessageReplyParams
+ : public ResourceMessageParams {
+ public:
+ ResourceMessageReplyParams();
+ ResourceMessageReplyParams(PP_Resource resource, int32_t sequence);
+ virtual ~ResourceMessageReplyParams();
+
+ void set_result(int32_t r) { result_ = r; }
+ int32_t result() const { return result_; }
+
+ virtual void Serialize(IPC::Message* msg) const OVERRIDE;
+ virtual bool Deserialize(const IPC::Message* msg,
+ PickleIterator* iter) OVERRIDE;
+
+ // Writes everything except the handles to |msg|.
+ void WriteReplyHeader(IPC::Message* msg) const;
+
+ private:
+ // Pepper "result code" for the callback.
+ int32_t result_;
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+namespace IPC {
+
+template <> struct PPAPI_PROXY_EXPORT
+ParamTraits<ppapi::proxy::ResourceMessageCallParams> {
+ typedef ppapi::proxy::ResourceMessageCallParams param_type;
+ static void Write(Message* m, const param_type& p) {
+ p.Serialize(m);
+ }
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
+ return r->Deserialize(m, iter);
+ }
+ static void Log(const param_type& p, std::string* l) {
+ }
+};
+
+template <> struct PPAPI_PROXY_EXPORT
+ParamTraits<ppapi::proxy::ResourceMessageReplyParams> {
+ typedef ppapi::proxy::ResourceMessageReplyParams param_type;
+ static void Write(Message* m, const param_type& p) {
+ p.Serialize(m);
+ }
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
+ return r->Deserialize(m, iter);
+ }
+ static void Log(const param_type& p, std::string* l) {
+ }
+};
+
+} // namespace IPC
+
+#endif // PPAPI_PROXY_RESOURCE_MESSAGE_PARAMS_H_
diff --git a/chromium/ppapi/proxy/resource_message_test_sink.cc b/chromium/ppapi/proxy/resource_message_test_sink.cc
new file mode 100644
index 00000000000..e76e32ac88e
--- /dev/null
+++ b/chromium/ppapi/proxy/resource_message_test_sink.cc
@@ -0,0 +1,130 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/resource_message_test_sink.h"
+
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/resource_message_params.h"
+#include "ppapi/proxy/serialized_handle.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+// Backend for GetFirstResource[Call|Reply]Matching.
+template<class WrapperMessage, class Params>
+bool GetFirstResourceMessageMatching(const ResourceMessageTestSink& sink,
+ uint32 id,
+ Params* params,
+ IPC::Message* nested_msg) {
+ for (size_t i = 0; i < sink.message_count(); i++) {
+ const IPC::Message* msg = sink.GetMessageAt(i);
+ if (msg->type() == WrapperMessage::ID) {
+ Params cur_params;
+ IPC::Message cur_msg;
+ WrapperMessage::Read(msg, &cur_params, &cur_msg);
+ if (cur_msg.type() == id) {
+ *params = cur_params;
+ *nested_msg = cur_msg;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+} // namespace
+
+ResourceMessageTestSink::ResourceMessageTestSink() {
+}
+
+ResourceMessageTestSink::~ResourceMessageTestSink() {
+}
+
+bool ResourceMessageTestSink::Send(IPC::Message* msg) {
+ int message_id = 0;
+ scoped_ptr<IPC::MessageReplyDeserializer> reply_deserializer;
+ if (msg->is_sync()) {
+ reply_deserializer.reset(
+ static_cast<IPC::SyncMessage*>(msg)->GetReplyDeserializer());
+ message_id = IPC::SyncMessage::GetMessageId(*msg);
+ }
+ bool result = IPC::TestSink::Send(msg); // Deletes |msg|.
+ if (sync_reply_msg_.get()) {
+ // |sync_reply_msg_| should always be a reply to the pending sync message.
+ DCHECK(IPC::SyncMessage::IsMessageReplyTo(*sync_reply_msg_.get(),
+ message_id));
+ reply_deserializer->SerializeOutputParameters(*sync_reply_msg_.get());
+ sync_reply_msg_.reset(NULL);
+ }
+ return result;
+}
+
+void ResourceMessageTestSink::SetSyncReplyMessage(IPC::Message* reply_msg) {
+ DCHECK(!sync_reply_msg_.get());
+ sync_reply_msg_.reset(reply_msg);
+}
+
+bool ResourceMessageTestSink::GetFirstResourceCallMatching(
+ uint32 id,
+ ResourceMessageCallParams* params,
+ IPC::Message* nested_msg) const {
+ return GetFirstResourceMessageMatching<PpapiHostMsg_ResourceCall,
+ ResourceMessageCallParams>(
+ *this, id, params, nested_msg);
+}
+
+bool ResourceMessageTestSink::GetFirstResourceReplyMatching(
+ uint32 id,
+ ResourceMessageReplyParams* params,
+ IPC::Message* nested_msg) {
+ return GetFirstResourceMessageMatching<PpapiPluginMsg_ResourceReply,
+ ResourceMessageReplyParams>(
+ *this, id, params, nested_msg);
+}
+
+ResourceSyncCallHandler::ResourceSyncCallHandler(
+ ResourceMessageTestSink* test_sink,
+ uint32 incoming_type,
+ int32_t result,
+ const IPC::Message& reply_msg)
+ : test_sink_(test_sink),
+ incoming_type_(incoming_type),
+ result_(result),
+ serialized_handle_(NULL),
+ reply_msg_(reply_msg) {
+}
+
+ResourceSyncCallHandler::~ResourceSyncCallHandler() {
+}
+
+bool ResourceSyncCallHandler::OnMessageReceived(const IPC::Message& msg) {
+ if (msg.type() != PpapiHostMsg_ResourceSyncCall::ID)
+ return false;
+ PpapiHostMsg_ResourceSyncCall::Schema::SendParam send_params;
+ bool success = PpapiHostMsg_ResourceSyncCall::ReadSendParam(
+ &msg, &send_params);
+ DCHECK(success);
+ ResourceMessageCallParams call_params = send_params.a;
+ IPC::Message call_msg = send_params.b;
+ if (call_msg.type() != incoming_type_)
+ return false;
+ IPC::Message* wrapper_reply_msg = IPC::SyncMessage::GenerateReply(&msg);
+ ResourceMessageReplyParams reply_params(call_params.pp_resource(),
+ call_params.sequence());
+ reply_params.set_result(result_);
+ if (serialized_handle_)
+ reply_params.AppendHandle(*serialized_handle_);
+ PpapiHostMsg_ResourceSyncCall::WriteReplyParams(
+ wrapper_reply_msg, reply_params, reply_msg_);
+ test_sink_->SetSyncReplyMessage(wrapper_reply_msg);
+
+ // Stash a copy of the message for inspection later.
+ last_handled_msg_ = call_msg;
+ return true;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/resource_message_test_sink.h b/chromium/ppapi/proxy/resource_message_test_sink.h
new file mode 100644
index 00000000000..cbbece3134d
--- /dev/null
+++ b/chromium/ppapi/proxy/resource_message_test_sink.h
@@ -0,0 +1,99 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_RESOURCE_MESSAGE_TEST_SINK_H_
+#define PPAPI_PROXY_RESOURCE_MESSAGE_TEST_SINK_H_
+
+#include "ipc/ipc_listener.h"
+#include "ipc/ipc_test_sink.h"
+#include "ppapi/c/pp_stdint.h"
+
+namespace ppapi {
+namespace proxy {
+
+class ResourceMessageCallParams;
+class ResourceMessageReplyParams;
+class SerializedHandle;
+
+// Extends IPC::TestSink to add extra capabilities for searching for and
+// decoding resource messages.
+class ResourceMessageTestSink : public IPC::TestSink {
+ public:
+ ResourceMessageTestSink();
+ virtual ~ResourceMessageTestSink();
+
+ // IPC::TestSink.
+ // Overridden to handle sync messages.
+ virtual bool Send(IPC::Message* msg) OVERRIDE;
+
+ // Sets the reply message that will be returned to the next sync message sent.
+ // This test sink owns any reply messages passed into this method.
+ void SetSyncReplyMessage(IPC::Message* reply_msg);
+
+ // Searches the queue for the first resource call message with a nested
+ // message matching the given ID. On success, returns true and populates the
+ // givem params and nested message.
+ bool GetFirstResourceCallMatching(
+ uint32 id,
+ ResourceMessageCallParams* params,
+ IPC::Message* nested_msg) const;
+
+ // Like GetFirstResourceCallMatching except for replies.
+ bool GetFirstResourceReplyMatching(
+ uint32 id,
+ ResourceMessageReplyParams* params,
+ IPC::Message* nested_msg);
+
+ private:
+ scoped_ptr<IPC::Message> sync_reply_msg_;
+};
+
+// This is a message handler which generates reply messages for synchronous
+// resource calls. This allows unit testing of the plugin side of resources
+// which send sync messages. If you want to reply to a sync message type named
+// |PpapiHostMsg_X_Y| with |PpapiPluginMsg_X_YReply| then usage would be as
+// follows (from within |PluginProxyTest|s):
+//
+// PpapiHostMsg_X_YReply my_reply;
+// ResourceSyncCallHandler handler(&sink(),
+// PpapiHostMsg_X_Y::ID,
+// PP_OK,
+// my_reply);
+// sink().AddFilter(&handler);
+// // Do stuff to send a sync message ...
+// // You can check handler.last_handled_msg() to ensure the correct message was
+// // handled.
+// sink().RemoveFilter(&handler);
+class ResourceSyncCallHandler : public IPC::Listener {
+ public:
+ ResourceSyncCallHandler(ResourceMessageTestSink* test_sink,
+ uint32 incoming_type,
+ int32_t result,
+ const IPC::Message& reply_msg);
+ virtual ~ResourceSyncCallHandler();
+
+ // IPC::Listener.
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ IPC::Message last_handled_msg() { return last_handled_msg_; }
+
+ // Sets a handle to be appended to the ReplyParams. The pointer is owned by
+ // the caller.
+ void set_serialized_handle(const SerializedHandle* serialized_handle) {
+ serialized_handle_ = serialized_handle;
+ }
+
+ private:
+ ResourceMessageTestSink* test_sink_;
+ uint32 incoming_type_;
+ int32_t result_;
+ const SerializedHandle* serialized_handle_; // Non-owning pointer.
+ IPC::Message reply_msg_;
+ IPC::Message last_handled_msg_;
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_RESOURCE_MESSAGE_TEST_SINK_H_
diff --git a/chromium/ppapi/proxy/run_all_unittests.cc b/chromium/ppapi/proxy/run_all_unittests.cc
new file mode 100644
index 00000000000..7fd6ef2e80e
--- /dev/null
+++ b/chromium/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/chromium/ppapi/proxy/serialized_flash_menu.cc b/chromium/ppapi/proxy/serialized_flash_menu.cc
new file mode 100644
index 00000000000..bbd698cc7b4
--- /dev/null
+++ b/chromium/ppapi/proxy/serialized_flash_menu.cc
@@ -0,0 +1,181 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/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 ppapi {
+namespace proxy {
+
+namespace {
+// Maximum depth of submenus allowed (e.g., 1 indicates that submenus are
+// allowed, but not sub-submenus).
+const int kMaxMenuDepth = 2;
+const uint32_t kMaxMenuEntries = 1000;
+
+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, PickleIterator* 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,
+ PickleIterator* 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,
+ PickleIterator* 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;
+
+ if (menu->count > kMaxMenuEntries) {
+ FreeMenu(menu);
+ return NULL;
+ }
+
+ 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,
+ PickleIterator* iter) {
+ DCHECK(!pp_menu_);
+ pp_menu_ = ReadMenu(0, m, iter);
+ if (!pp_menu_)
+ return false;
+
+ own_menu_ = true;
+ return true;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/serialized_flash_menu.h b/chromium/ppapi/proxy/serialized_flash_menu.h
new file mode 100644
index 00000000000..271caba368b
--- /dev/null
+++ b/chromium/ppapi/proxy/serialized_flash_menu.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_SERIALIZED_FLASH_MENU_H_
+#define PPAPI_PROXY_SERIALIZED_FLASH_MENU_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+
+class PickleIterator;
+
+struct PP_Flash_Menu;
+
+namespace IPC {
+class Message;
+}
+
+namespace ppapi {
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT 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, PickleIterator* iter);
+
+ private:
+ const PP_Flash_Menu* pp_menu_;
+ bool own_menu_;
+ DISALLOW_COPY_AND_ASSIGN(SerializedFlashMenu);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_SERIALIZED_FLASH_MENU_H_
diff --git a/chromium/ppapi/proxy/serialized_handle.cc b/chromium/ppapi/proxy/serialized_handle.cc
new file mode 100644
index 00000000000..c9ce13b41a9
--- /dev/null
+++ b/chromium/ppapi/proxy/serialized_handle.cc
@@ -0,0 +1,143 @@
+// Copyright (c) 2013 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_handle.h"
+
+#include "base/memory/shared_memory.h"
+#include "base/pickle.h"
+#include "base/platform_file.h"
+#include "build/build_config.h"
+#include "ipc/ipc_platform_file.h"
+
+#if defined(OS_NACL)
+#include <unistd.h>
+#endif
+
+namespace ppapi {
+namespace proxy {
+
+SerializedHandle::SerializedHandle()
+ : type_(INVALID),
+ shm_handle_(base::SharedMemory::NULLHandle()),
+ size_(0),
+ descriptor_(IPC::InvalidPlatformFileForTransit()) {
+}
+
+SerializedHandle::SerializedHandle(Type type_param)
+ : type_(type_param),
+ shm_handle_(base::SharedMemory::NULLHandle()),
+ size_(0),
+ descriptor_(IPC::InvalidPlatformFileForTransit()) {
+}
+
+SerializedHandle::SerializedHandle(const base::SharedMemoryHandle& handle,
+ uint32 size)
+ : type_(SHARED_MEMORY),
+ shm_handle_(handle),
+ size_(size),
+ descriptor_(IPC::InvalidPlatformFileForTransit()) {
+}
+
+SerializedHandle::SerializedHandle(
+ Type type,
+ const IPC::PlatformFileForTransit& socket_descriptor)
+ : type_(type),
+ shm_handle_(base::SharedMemory::NULLHandle()),
+ size_(0),
+ descriptor_(socket_descriptor) {
+}
+
+bool SerializedHandle::IsHandleValid() const {
+ switch (type_) {
+ case SHARED_MEMORY:
+ return base::SharedMemory::IsHandleValid(shm_handle_);
+ case SOCKET:
+ case CHANNEL_HANDLE:
+ case FILE:
+ return !(IPC::InvalidPlatformFileForTransit() == descriptor_);
+ case INVALID:
+ return false;
+ // No default so the compiler will warn us if a new type is added.
+ }
+ return false;
+}
+
+void SerializedHandle::Close() {
+ if (IsHandleValid()) {
+ switch (type_) {
+ case INVALID:
+ NOTREACHED();
+ break;
+ case SHARED_MEMORY:
+ base::SharedMemory::CloseHandle(shm_handle_);
+ break;
+ case SOCKET:
+ case CHANNEL_HANDLE:
+ case FILE:
+ base::PlatformFile file =
+ IPC::PlatformFileForTransitToPlatformFile(descriptor_);
+#if !defined(OS_NACL)
+ base::ClosePlatformFile(file);
+#else
+ close(file);
+#endif
+ break;
+ // No default so the compiler will warn us if a new type is added.
+ }
+ }
+ *this = SerializedHandle();
+}
+
+// static
+bool SerializedHandle::WriteHeader(const Header& hdr, Pickle* pickle) {
+ if (!pickle->WriteInt(hdr.type))
+ return false;
+ if (hdr.type == SHARED_MEMORY) {
+ if (!pickle->WriteUInt32(hdr.size))
+ return false;
+ }
+ if (hdr.type == FILE) {
+ if (!pickle->WriteInt(hdr.open_flag))
+ return false;
+ }
+ return true;
+}
+
+// static
+bool SerializedHandle::ReadHeader(PickleIterator* iter, Header* hdr) {
+ *hdr = Header(INVALID, 0, 0);
+ int type = 0;
+ if (!iter->ReadInt(&type))
+ return false;
+ bool valid_type = false;
+ switch (type) {
+ case SHARED_MEMORY: {
+ uint32 size = 0;
+ if (!iter->ReadUInt32(&size))
+ return false;
+ hdr->size = size;
+ valid_type = true;
+ break;
+ }
+ case FILE: {
+ int open_flag = 0;
+ if (!iter->ReadInt(&open_flag))
+ return false;
+ hdr->open_flag = open_flag;
+ valid_type = true;
+ }
+ case SOCKET:
+ case CHANNEL_HANDLE:
+ case INVALID:
+ valid_type = true;
+ break;
+ // No default so the compiler will warn us if a new type is added.
+ }
+ if (valid_type)
+ hdr->type = Type(type);
+ return valid_type;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/serialized_handle.h b/chromium/ppapi/proxy/serialized_handle.h
new file mode 100644
index 00000000000..91efa075b5d
--- /dev/null
+++ b/chromium/ppapi/proxy/serialized_handle.h
@@ -0,0 +1,150 @@
+// Copyright (c) 2013 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_HANDLES_H_
+#define PPAPI_PROXY_SERIALIZED_HANDLES_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/memory/shared_memory.h"
+#include "build/build_config.h"
+#include "ipc/ipc_platform_file.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+
+class Pickle;
+
+namespace ppapi {
+namespace proxy {
+
+// SerializedHandle is a unified structure for holding a handle (e.g., a shared
+// memory handle, socket descriptor, etc). This is useful for passing handles in
+// resource messages and also makes it easier to translate handles in
+// NaClIPCAdapter for use in NaCl.
+class PPAPI_PROXY_EXPORT SerializedHandle {
+ public:
+ enum Type { INVALID, SHARED_MEMORY, SOCKET, CHANNEL_HANDLE, FILE };
+ struct Header {
+ Header() : type(INVALID), size(0), open_flag(0) {}
+ Header(Type type_arg, uint32 size_arg, int32 open_flag_arg)
+ : type(type_arg), size(size_arg), open_flag(open_flag_arg) {
+ }
+ Type type;
+ uint32 size;
+ int32 open_flag;
+ };
+
+ SerializedHandle();
+ // Create an invalid handle of the given type.
+ explicit SerializedHandle(Type type);
+
+ // Create a shared memory handle.
+ SerializedHandle(const base::SharedMemoryHandle& handle, uint32 size);
+
+ // Create a socket, channel or file handle.
+ SerializedHandle(const Type type,
+ const IPC::PlatformFileForTransit& descriptor);
+
+ Type type() const { return type_; }
+ bool is_shmem() const { return type_ == SHARED_MEMORY; }
+ bool is_socket() const { return type_ == SOCKET; }
+ bool is_channel_handle() const { return type_ == CHANNEL_HANDLE; }
+ bool is_file() const { return type_ == FILE; }
+ const base::SharedMemoryHandle& shmem() const {
+ DCHECK(is_shmem());
+ return shm_handle_;
+ }
+ uint32 size() const {
+ DCHECK(is_shmem());
+ return size_;
+ }
+ const IPC::PlatformFileForTransit& descriptor() const {
+ DCHECK(is_socket() || is_channel_handle() || is_file());
+ return descriptor_;
+ }
+ int32 open_flag() const {
+ return open_flag_;
+ }
+ void set_shmem(const base::SharedMemoryHandle& handle, uint32 size) {
+ type_ = SHARED_MEMORY;
+ shm_handle_ = handle;
+ size_ = size;
+
+ descriptor_ = IPC::InvalidPlatformFileForTransit();
+ }
+ void set_socket(const IPC::PlatformFileForTransit& socket) {
+ type_ = SOCKET;
+ descriptor_ = socket;
+
+ shm_handle_ = base::SharedMemory::NULLHandle();
+ size_ = 0;
+ }
+ void set_channel_handle(const IPC::PlatformFileForTransit& descriptor) {
+ type_ = CHANNEL_HANDLE;
+
+ descriptor_ = descriptor;
+ shm_handle_ = base::SharedMemory::NULLHandle();
+ size_ = 0;
+ }
+ void set_file_handle(const IPC::PlatformFileForTransit& descriptor,
+ int32 open_flag) {
+ type_ = FILE;
+
+ descriptor_ = descriptor;
+ shm_handle_ = base::SharedMemory::NULLHandle();
+ size_ = 0;
+ open_flag_ = open_flag;
+ }
+ void set_null_shmem() {
+ set_shmem(base::SharedMemory::NULLHandle(), 0);
+ }
+ void set_null_socket() {
+ set_socket(IPC::InvalidPlatformFileForTransit());
+ }
+ void set_null_channel_handle() {
+ set_channel_handle(IPC::InvalidPlatformFileForTransit());
+ }
+ void set_null_file_handle() {
+ set_file_handle(IPC::InvalidPlatformFileForTransit(), 0);
+ }
+ bool IsHandleValid() const;
+
+ Header header() const {
+ return Header(type_, size_, open_flag_);
+ }
+
+ // Closes the handle and sets it to invalid.
+ void Close();
+
+ // Write/Read a Header, which contains all the data except the handle. This
+ // allows us to write the handle in a platform-specific way, as is necessary
+ // in NaClIPCAdapter to share handles with NaCl from Windows.
+ static bool WriteHeader(const Header& hdr, Pickle* pickle);
+ static bool ReadHeader(PickleIterator* iter, Header* hdr);
+
+ private:
+ // The kind of handle we're holding.
+ Type type_;
+
+ // We hold more members than we really need; we can't easily use a union,
+ // because we hold non-POD types. But these types are pretty light-weight. If
+ // we add more complex things later, we should come up with a more memory-
+ // efficient strategy.
+ // These are valid if type == SHARED_MEMORY.
+ base::SharedMemoryHandle shm_handle_;
+ uint32 size_;
+
+ // This is valid if type == SOCKET || type == CHANNEL_HANDLE || type == FILE.
+ IPC::PlatformFileForTransit descriptor_;
+
+ // This is valid if type == FILE.
+ int32 open_flag_;
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_SERIALIZED_HANDLES_H_
diff --git a/chromium/ppapi/proxy/serialized_structs.cc b/chromium/ppapi/proxy/serialized_structs.cc
new file mode 100644
index 00000000000..8c984d55dba
--- /dev/null
+++ b/chromium/ppapi/proxy/serialized_structs.cc
@@ -0,0 +1,133 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/serialized_structs.h"
+
+#include "base/pickle.h"
+#include "build/build_config.h"
+#include "ppapi/c/dev/ppb_font_dev.h"
+#include "ppapi/c/pp_file_info.h"
+#include "ppapi/c/pp_rect.h"
+#include "ppapi/c/trusted/ppb_browser_font_trusted.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+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(
+ const PP_FontDescription_Dev& desc) {
+ StringVar* string_var = StringVar::FromPPVar(desc.face);
+ face = string_var ? string_var->value() : std::string();
+
+ 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::SetFromPPBrowserFontDescription(
+ const PP_BrowserFont_Trusted_Description& desc) {
+ StringVar* string_var = StringVar::FromPPVar(desc.face);
+ face = string_var ? string_var->value() : std::string();
+
+ 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(
+ PP_FontDescription_Dev* desc) const {
+ desc->face = StringVar::StringToPPVar(face);
+ 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;
+}
+
+void SerializedFontDescription::SetToPPBrowserFontDescription(
+ PP_BrowserFont_Trusted_Description* desc) const {
+ desc->face = StringVar::StringToPPVar(face);
+ desc->family = static_cast<PP_BrowserFont_Trusted_Family>(family);
+ desc->size = size;
+ desc->weight = static_cast<PP_BrowserFont_Trusted_Weight>(weight);
+ desc->italic = italic;
+ desc->small_caps = small_caps;
+ desc->letter_spacing = letter_spacing;
+ desc->word_spacing = word_spacing;
+}
+
+SerializedTrueTypeFontDesc::SerializedTrueTypeFontDesc()
+ : family(),
+ generic_family(),
+ style(),
+ weight(),
+ width(),
+ charset() {
+}
+
+SerializedTrueTypeFontDesc::~SerializedTrueTypeFontDesc() {}
+
+void SerializedTrueTypeFontDesc::SetFromPPTrueTypeFontDesc(
+ const PP_TrueTypeFontDesc_Dev& desc) {
+ StringVar* string_var = StringVar::FromPPVar(desc.family);
+ family = string_var ? string_var->value() : std::string();
+
+ generic_family = desc.generic_family;
+ style = desc.style;
+ weight = desc.weight;
+ width = desc.width;
+ charset = desc.charset;
+}
+
+void SerializedTrueTypeFontDesc::CopyToPPTrueTypeFontDesc(
+ PP_TrueTypeFontDesc_Dev* desc) const {
+ desc->family = StringVar::StringToPPVar(family);
+
+ desc->generic_family = generic_family;
+ desc->style = style;
+ desc->weight = weight;
+ desc->width = width;
+ desc->charset = charset;
+}
+
+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;
+ allow_subpixel_aa = PP_FALSE;
+}
+
+PPBFlash_DrawGlyphs_Params::~PPBFlash_DrawGlyphs_Params() {}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/serialized_structs.h b/chromium/ppapi/proxy/serialized_structs.h
new file mode 100644
index 00000000000..1f89ae2047c
--- /dev/null
+++ b/chromium/ppapi/proxy/serialized_structs.h
@@ -0,0 +1,133 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_SERIALIZED_STRUCTS_H_
+#define PPAPI_PROXY_SERIALIZED_STRUCTS_H_
+
+#include <string>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/memory/shared_memory.h"
+#include "build/build_config.h"
+#include "ppapi/c/dev/ppb_truetype_font_dev.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/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/host_resource.h"
+
+class Pickle;
+struct PP_FontDescription_Dev;
+struct PP_BrowserFont_Trusted_Description;
+
+namespace ppapi {
+namespace proxy {
+
+// PP_FontDescription_Dev/PP_BrowserFontDescription (same definition, different
+// names) has to be redefined with a string in place of the PP_Var used for the
+// face name.
+struct PPAPI_PROXY_EXPORT SerializedFontDescription {
+ SerializedFontDescription();
+ ~SerializedFontDescription();
+
+ // Converts a PP_FontDescription_Dev to a SerializedFontDescription.
+ //
+ // The reference of |face| owned by the PP_FontDescription_Dev will be
+ // unchanged and the caller is responsible for freeing it.
+ void SetFromPPFontDescription(const PP_FontDescription_Dev& desc);
+ void SetFromPPBrowserFontDescription(
+ const PP_BrowserFont_Trusted_Description& desc);
+
+ // Converts to a PP_FontDescription_Dev. The face name will have one ref
+ // assigned to it. The caller is responsible for freeing it.
+ void SetToPPFontDescription(PP_FontDescription_Dev* desc) const;
+ void SetToPPBrowserFontDescription(
+ PP_BrowserFont_Trusted_Description* desc) const;
+
+ std::string 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 PPAPI_PROXY_EXPORT SerializedTrueTypeFontDesc {
+ SerializedTrueTypeFontDesc();
+ ~SerializedTrueTypeFontDesc();
+
+ // Sets this to correspond to the contents of a PP_TrueTypeFontDesc_Dev.
+ //
+ // The reference count of the desc.family PP_Var will be unchanged and the
+ // caller is responsible for releasing it.
+ void SetFromPPTrueTypeFontDesc(const PP_TrueTypeFontDesc_Dev& desc);
+
+ // Converts this to a PP_FontDescription_Dev.
+ //
+ // The desc.family PP_Var will have one reference assigned to it. The caller
+ // is responsible for releasing it.
+ void CopyToPPTrueTypeFontDesc(PP_TrueTypeFontDesc_Dev* desc) const;
+
+ std::string family;
+ PP_TrueTypeFontFamily_Dev generic_family;
+ PP_TrueTypeFontStyle_Dev style;
+ PP_TrueTypeFontWeight_Dev weight;
+ PP_TrueTypeFontWidth_Dev width;
+ PP_TrueTypeFontCharset_Dev charset;
+};
+
+struct SerializedDirEntry {
+ std::string name;
+ bool is_dir;
+};
+
+struct PPAPI_PROXY_EXPORT PPBFlash_DrawGlyphs_Params {
+ PPBFlash_DrawGlyphs_Params();
+ ~PPBFlash_DrawGlyphs_Params();
+
+ PP_Instance instance;
+ ppapi::HostResource image_data;
+ SerializedFontDescription font_desc;
+ uint32_t color;
+ PP_Point position;
+ PP_Rect clip;
+ float transformation[3][3];
+ PP_Bool allow_subpixel_aa;
+ std::vector<uint16_t> glyph_indices;
+ std::vector<PP_Point> glyph_advances;
+};
+
+struct PPBURLLoader_UpdateProgress_Params {
+ PP_Instance instance;
+ ppapi::HostResource resource;
+ int64_t bytes_sent;
+ int64_t total_bytes_to_be_sent;
+ int64_t bytes_received;
+ int64_t total_bytes_to_be_received;
+};
+
+struct PPPDecryptor_Buffer {
+ ppapi::HostResource resource;
+ uint32_t size;
+ base::SharedMemoryHandle handle;
+};
+
+// TODO(raymes): Make ImageHandle compatible with SerializedHandle.
+#if defined(OS_WIN)
+typedef HANDLE ImageHandle;
+#elif defined(TOOLKIT_GTK)
+// On legacy X Windows this is a SysV shared memory key.
+typedef int ImageHandle;
+#else
+typedef base::SharedMemoryHandle ImageHandle;
+#endif
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_SERIALIZED_STRUCTS_H_
diff --git a/chromium/ppapi/proxy/serialized_var.cc b/chromium/ppapi/proxy/serialized_var.cc
new file mode 100644
index 00000000000..72e7cc8ecbb
--- /dev/null
+++ b/chromium/ppapi/proxy/serialized_var.cc
@@ -0,0 +1,467 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/serialized_var.h"
+
+#include "base/logging.h"
+#include "ipc/ipc_message_utils.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/proxy/dispatcher.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/ppapi_param_traits.h"
+#include "ppapi/proxy/ppb_buffer_proxy.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/enter.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+void DefaultHandleWriter(IPC::Message* m, const SerializedHandle& handle) {
+ IPC::ParamTraits<SerializedHandle>::Write(m, handle);
+}
+} // namespace
+
+// SerializedVar::Inner --------------------------------------------------------
+
+SerializedVar::Inner::Inner()
+ : serialization_rules_(NULL),
+ var_(PP_MakeUndefined()),
+ instance_(0),
+ cleanup_mode_(CLEANUP_NONE),
+ is_valid_var_(true) {
+#ifndef NDEBUG
+ has_been_serialized_ = false;
+ has_been_deserialized_ = false;
+#endif
+}
+
+SerializedVar::Inner::Inner(VarSerializationRules* serialization_rules)
+ : serialization_rules_(serialization_rules),
+ var_(PP_MakeUndefined()),
+ instance_(0),
+ cleanup_mode_(CLEANUP_NONE) {
+#ifndef NDEBUG
+ has_been_serialized_ = false;
+ has_been_deserialized_ = false;
+#endif
+}
+
+SerializedVar::Inner::~Inner() {
+ switch (cleanup_mode_) {
+ case END_SEND_PASS_REF:
+ serialization_rules_->EndSendPassRef(var_);
+ break;
+ case END_RECEIVE_CALLER_OWNED:
+ serialization_rules_->EndReceiveCallerOwned(var_);
+ break;
+ default:
+ break;
+ }
+}
+
+PP_Var SerializedVar::Inner::GetVar() {
+ DCHECK(serialization_rules_.get());
+
+#if defined(NACL_WIN64)
+ NOTREACHED();
+ return PP_MakeUndefined();
+#endif
+
+ if (raw_var_data_.get()) {
+ var_ = raw_var_data_->CreatePPVar(instance_);
+ raw_var_data_.reset(NULL);
+ }
+
+ 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_.get());
+ var_ = var;
+ raw_var_data_.reset(NULL);
+}
+
+void SerializedVar::Inner::SetInstance(PP_Instance instance) {
+ instance_ = instance;
+}
+
+void SerializedVar::Inner::ForceSetVarValueForTest(PP_Var value) {
+ var_ = value;
+ raw_var_data_.reset(NULL);
+}
+
+void SerializedVar::Inner::WriteToMessage(IPC::Message* m) const {
+ // When writing to the IPC messages, a serialization 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_.get());
+
+#ifndef NDEBUG
+ // We should only be serializing something once.
+ DCHECK(!has_been_serialized_);
+ has_been_serialized_ = true;
+#endif
+ scoped_ptr<RawVarDataGraph> data = RawVarDataGraph::Create(var_, instance_);
+ if (data) {
+ m->WriteBool(true); // Success.
+ data->Write(m, base::Bind(&DefaultHandleWriter));
+ } else {
+ m->WriteBool(false); // Failure.
+ }
+}
+
+void SerializedVar::Inner::WriteDataToMessage(
+ IPC::Message* m,
+ const HandleWriter& handle_writer) const {
+ if (raw_var_data_) {
+ m->WriteBool(true); // Success.
+ raw_var_data_->Write(m, handle_writer);
+ } else {
+ m->WriteBool(false); // Failure.
+ }
+}
+
+bool SerializedVar::Inner::ReadFromMessage(const IPC::Message* m,
+ PickleIterator* 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).
+ if (!m->ReadBool(iter, &is_valid_var_))
+ return false;
+ if (is_valid_var_) {
+ raw_var_data_ = RawVarDataGraph::Read(m, iter);
+ if (!raw_var_data_)
+ return false;
+ }
+
+ return true;
+}
+
+void SerializedVar::Inner::SetCleanupModeToEndSendPassRef() {
+ 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() {
+}
+
+// SerializedVarSendInput ------------------------------------------------------
+
+SerializedVarSendInput::SerializedVarSendInput(Dispatcher* dispatcher,
+ const PP_Var& var)
+ : SerializedVar(dispatcher->serialization_rules()) {
+ inner_->SetVar(dispatcher->serialization_rules()->SendCallerOwned(var));
+}
+
+// static
+void SerializedVarSendInput::ConvertVector(Dispatcher* dispatcher,
+ const PP_Var* input,
+ size_t input_count,
+ std::vector<SerializedVar>* output) {
+ output->reserve(input_count);
+ for (size_t i = 0; i < input_count; i++)
+ output->push_back(SerializedVarSendInput(dispatcher, input[i]));
+}
+
+// SerializedVarSendInputShmem -------------------------------------------------
+
+SerializedVarSendInputShmem::SerializedVarSendInputShmem(
+ Dispatcher* dispatcher,
+ const PP_Var& var,
+ const PP_Instance& instance)
+ : SerializedVar(dispatcher->serialization_rules()) {
+ inner_->SetVar(dispatcher->serialization_rules()->SendCallerOwned(var));
+ inner_->SetInstance(instance);
+}
+
+// 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_->GetVar()));
+ return inner_->GetVar();
+}
+
+// ReceiveSerializedException --------------------------------------------------
+
+ReceiveSerializedException::ReceiveSerializedException(Dispatcher* dispatcher,
+ PP_Var* exception)
+ : SerializedVar(dispatcher->serialization_rules()),
+ 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_->GetVar()));
+ *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) {
+}
+
+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_->GetVar()));
+ return serialized_.inner_->GetVar();
+}
+
+
+PP_Var SerializedVarReceiveInput::GetForInstance(Dispatcher* dispatcher,
+ PP_Instance instance) {
+ serialized_.inner_->SetInstance(instance);
+ return Get(dispatcher);
+}
+
+// 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 vectors 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_->GetVar()));
+ 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();
+
+ serialized_->inner_->SetVar(
+ dispatcher->serialization_rules()->BeginSendPassRef(var));
+}
+
+// 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_));
+
+ // 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();
+ }
+}
+
+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_->ForceSetVarValueForTest(pod_var);
+}
+
+SerializedVarTestConstructor::SerializedVarTestConstructor(
+ const std::string& str) {
+ inner_->ForceSetVarValueForTest(StringVar::StringToPPVar(str));
+}
+
+SerializedVarTestReader::SerializedVarTestReader(const SerializedVar& var)
+ : SerializedVar(var) {
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/serialized_var.h b/chromium/ppapi/proxy/serialized_var.h
new file mode 100644
index 00000000000..13052c91d38
--- /dev/null
+++ b/chromium/ppapi/proxy/serialized_var.h
@@ -0,0 +1,502 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_SERIALIZED_VAR_H_
+#define PPAPI_PROXY_SERIALIZED_VAR_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/shared_memory.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/proxy/raw_var_data.h"
+#include "ppapi/proxy/serialized_handle.h"
+#include "ppapi/proxy/serialized_structs.h"
+#include "ppapi/proxy/var_serialization_rules.h"
+
+class PickleIterator;
+
+namespace IPC {
+class Message;
+}
+
+namespace ppapi {
+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 use-specific
+// classes that each 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 do 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 PPAPI_PROXY_EXPORT SerializedVar {
+ public:
+ SerializedVar();
+ ~SerializedVar();
+
+ // Backend implementation for IPC::ParamTraits<SerializedVar>.
+ void WriteToMessage(IPC::Message* m) const {
+ inner_->WriteToMessage(m);
+ }
+ // If ReadFromMessage has been called, WriteDataToMessage will write the var
+ // that has been read from ReadFromMessage back to a message. This is used
+ // when converting handles for use in NaCl.
+ void WriteDataToMessage(IPC::Message* m,
+ const HandleWriter& handle_writer) const {
+ inner_->WriteDataToMessage(m, handle_writer);
+ }
+ bool ReadFromMessage(const IPC::Message* m, PickleIterator* iter) {
+ return inner_->ReadFromMessage(m, iter);
+ }
+
+ bool is_valid_var() const {
+ return inner_->is_valid_var();
+ }
+
+ // Returns the shared memory handles associated with this SerializedVar.
+ std::vector<SerializedHandle*> GetHandles() const {
+ return inner_->GetHandles();
+ }
+
+ protected:
+ friend class SerializedVarReceiveInput;
+ friend class SerializedVarReturnValue;
+ friend class SerializedVarOutParam;
+ friend class SerializedVarSendInput;
+ friend class SerializedVarSendInputShmem;
+ friend class SerializedVarTestConstructor;
+ friend class SerializedVarVectorReceiveInput;
+
+ class PPAPI_PROXY_EXPORT Inner : public base::RefCounted<Inner> {
+ public:
+ Inner();
+ Inner(VarSerializationRules* serialization_rules);
+ ~Inner();
+
+ VarSerializationRules* serialization_rules() {
+ return serialization_rules_.get();
+ }
+ void set_serialization_rules(VarSerializationRules* serialization_rules) {
+ serialization_rules_ = serialization_rules;
+ }
+
+ bool is_valid_var() const {
+ return is_valid_var_;
+ }
+
+ std::vector<SerializedHandle*> GetHandles() {
+ return (raw_var_data_ ? raw_var_data_->GetHandles() :
+ std::vector<SerializedHandle*>());
+ }
+
+ // See outer class's declarations above.
+ PP_Var GetVar();
+ void SetVar(PP_Var var);
+ void SetInstance(PP_Instance instance);
+
+ // For the SerializedVarTestConstructor, this writes the Var value as if
+ // it was just received off the wire, without any serialization rules.
+ void ForceSetVarValueForTest(PP_Var value);
+
+ void WriteToMessage(IPC::Message* m) const;
+ void WriteDataToMessage(IPC::Message* m,
+ const HandleWriter& handle_writer) const;
+ bool ReadFromMessage(const IPC::Message* m, PickleIterator* iter);
+
+ // Sets the cleanup mode. See the CleanupMode enum below.
+ void SetCleanupModeToEndSendPassRef();
+ 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.
+ scoped_refptr<VarSerializationRules> serialization_rules_;
+
+ // If this is set to VARTYPE_STRING and the 'value.id' is 0, then the
+ // string_from_ipc_ holds 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_;
+
+ PP_Instance instance_;
+
+ CleanupMode cleanup_mode_;
+
+ // If the var is not properly serialized, this will be false.
+ bool is_valid_var_;
+
+#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
+
+ // ReadFromMessage() may be called on the I/O thread, e.g., when reading the
+ // reply to a sync message. We cannot use the var tracker on the I/O thread,
+ // which means we cannot create some types of PP_Var
+ // (e.g. PP_VARTYPE_STRING). The data is stored in |raw_var_data_| and the
+ // PP_Var is constructed when |GetVar()| is called.
+ scoped_ptr<RawVarDataGraph> raw_var_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(Inner);
+ };
+
+ SerializedVar(VarSerializationRules* serialization_rules);
+
+ 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(dispatcher, param));
+// }
+class PPAPI_PROXY_EXPORT 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();
+};
+
+// Specialization for optionally sending over shared memory.
+class PPAPI_PROXY_EXPORT SerializedVarSendInputShmem : public SerializedVar {
+ public:
+ SerializedVarSendInputShmem(Dispatcher* dispatcher, const PP_Var& var,
+ const PP_Instance& instance);
+
+ private:
+ // Disallow the empty constructor, but keep the default copy constructor
+ // which is required to send the object to the IPC system.
+ SerializedVarSendInputShmem();
+};
+
+
+// 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());
+// }
+//
+// TODO(yzshen): Move the dispatcher parameter to the constructor and store a
+// VarSerializationRules reference instead, in case the dispatcher is destroyed
+// while waiting for reply to the sync message.
+class PPAPI_PROXY_EXPORT 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 PPAPI_PROXY_EXPORT 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:
+ // 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 PPAPI_PROXY_EXPORT 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 PPAPI_PROXY_EXPORT 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);
+ PP_Var GetForInstance(Dispatcher* dispatcher, PP_Instance instance);
+ bool is_valid_var() { return serialized_.is_valid_var(); }
+
+ private:
+ const SerializedVar& serialized_;
+};
+
+// 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 PPAPI_PROXY_EXPORT 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 PPAPI_PROXY_EXPORT 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 PPAPI_PROXY_EXPORT 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 PPAPI_PROXY_EXPORT 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. This emulates a SerializedVar just received over the
+// wire from another process.
+class PPAPI_PROXY_EXPORT 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 PPAPI_PROXY_EXPORT SerializedVarTestReader : public SerializedVar {
+ public:
+ explicit SerializedVarTestReader(const SerializedVar& var);
+
+ PP_Var GetVar() const { return inner_->GetVar(); }
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_SERIALIZED_VAR_H_
diff --git a/chromium/ppapi/proxy/serialized_var_unittest.cc b/chromium/ppapi/proxy/serialized_var_unittest.cc
new file mode 100644
index 00000000000..fcde77795a3
--- /dev/null
+++ b/chromium/ppapi/proxy/serialized_var_unittest.cc
@@ -0,0 +1,354 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppapi_proxy_test.h"
+
+#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+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 in the plugin. This is when the host calls into the
+// plugin and the plugin returns something via an out param, like an exception.
+TEST_F(SerializedVarTest, PluginSerializedVarInOutParam) {
+ ProxyAutoLock lock;
+ PP_Var host_object = MakeObjectVar(0x31337);
+
+ PP_Var plugin_object;
+ {
+ // Receive the object param, we should be tracking it with no refcount, and
+ // no messages sent.
+ SerializedVarTestConstructor input(host_object);
+ SerializedVarReceiveInput receive_input(input);
+ plugin_object = receive_input.Get(plugin_dispatcher());
+ EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_object));
+ EXPECT_EQ(0u, sink().message_count());
+
+ 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);
+ // An out-param needs to pass a reference to the caller, so it's the
+ // responsibility of the plugin to bump the ref-count on an input
+ // parameter.
+ var_tracker().AddRefVar(plugin_object);
+ EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
+ // We should have informed the host that a reference was taken.
+ EXPECT_EQ(1u, sink().message_count());
+ *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.GetVar().value.as_id);
+ EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
+ EXPECT_EQ(1u, sink().message_count());
+ }
+
+ // The out param should have done an "end receive caller owned" on the plugin
+ // var serialization rules, which should have released the "track-with-no-
+ // reference" count in the var tracker as well as the 1 reference we passed
+ // back to the host, so the object should no longer be in the tracker. The
+ // reference we added has been removed, so another message should be sent to
+ // the host to tell it we're done with the object.
+ EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_object));
+ EXPECT_EQ(2u, sink().message_count());
+}
+
+// Tests output strings in the plugin. This is when the host calls into the
+// plugin with a string and the plugin returns it via an out param.
+TEST_F(SerializedVarTest, PluginSerializedStringVarInOutParam) {
+ ProxyAutoLock lock;
+ PP_Var plugin_string;
+ const std::string kTestString("elite");
+ {
+ // Receive the string param. We should track it with 1 refcount.
+ SerializedVarTestConstructor input(kTestString);
+ SerializedVarReceiveInput receive_input(input);
+ plugin_string = receive_input.Get(plugin_dispatcher());
+ EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_string));
+ EXPECT_EQ(0u, sink().message_count());
+
+ 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);
+ // An out-param needs to pass a reference to the caller, so it's the
+ // responsibility of the plugin to bump the ref-count of an input
+ // parameter.
+ var_tracker().AddRefVar(plugin_string);
+ EXPECT_EQ(2, var_tracker().GetRefCountForObject(plugin_string));
+ EXPECT_EQ(0u, sink().message_count());
+ *out_param.OutParam(plugin_dispatcher()) = plugin_string;
+ }
+
+ // The SerializedVar should have set the string value internally. Nothing in
+ // the var tracker should have changed yet, and no messages should have been
+ // sent.
+ SerializedVarTestReader reader(sv);
+ //EXPECT_EQ(kTestString, *reader.GetTrackerStringPtr());
+ EXPECT_EQ(2, var_tracker().GetRefCountForObject(plugin_string));
+ EXPECT_EQ(0u, sink().message_count());
+ }
+ // The reference the string had initially should be gone, and the reference we
+ // passed to the host should also be gone, so the string should be removed.
+ EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_string));
+ EXPECT_EQ(0u, sink().message_count());
+}
+
+// Tests receiving an argument and passing it back to the browser as an output
+// parameter.
+TEST_F(SerializedVarTest, PluginSerializedVarOutParam) {
+ ProxyAutoLock lock;
+ 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.GetVar().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.
+}
+
+// Tests the case that the plugin receives the same var twice as an input
+// parameter (not passing ownership).
+TEST_F(SerializedVarTest, PluginReceiveInput) {
+ ProxyAutoLock lock;
+ PP_Var host_object = MakeObjectVar(0x31337);
+
+ PP_Var plugin_object;
+ {
+ // Receive the first param, we should be tracking it with no refcount, and
+ // no messages sent.
+ SerializedVarTestConstructor input1(host_object);
+ SerializedVarReceiveInput receive_input(input1);
+ plugin_object = receive_input.Get(plugin_dispatcher());
+ EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_object));
+ EXPECT_EQ(0u, sink().message_count());
+
+ // Receive the second param, it should be resolved to the same plugin
+ // object and there should still be no refcount.
+ SerializedVarTestConstructor input2(host_object);
+ SerializedVarReceiveInput receive_input2(input2);
+ PP_Var plugin_object2 = receive_input2.Get(plugin_dispatcher());
+ EXPECT_EQ(plugin_object.value.as_id, plugin_object2.value.as_id);
+ EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_object));
+ EXPECT_EQ(0u, sink().message_count());
+
+ // Take a reference to the object, as if the plugin was using it, and then
+ // release it, we should still be tracking the object since the
+ // ReceiveInputs keep the "track_with_no_reference_count" alive until
+ // they're destroyed.
+ var_tracker().AddRefVar(plugin_object);
+ EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
+ var_tracker().ReleaseVar(plugin_object);
+ EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_object));
+ EXPECT_EQ(2u, sink().message_count());
+ }
+
+ // Since we didn't keep any refs to the objects, it should have freed the
+ // object.
+ EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_object));
+}
+
+// Tests the case that the plugin receives the same vars twice as an input
+// parameter (not passing ownership) within a vector.
+TEST_F(SerializedVarTest, PluginVectorReceiveInput) {
+ ProxyAutoLock lock;
+ PP_Var host_object = MakeObjectVar(0x31337);
+
+ std::vector<PP_Var> plugin_objects;
+ std::vector<PP_Var> plugin_objects2;
+ {
+ // Receive the params. The object should be tracked with no refcount and
+ // no messages sent. The string should is plugin-side only and should have
+ // a reference-count of 1.
+ std::vector<SerializedVar> input1;
+ input1.push_back(SerializedVarTestConstructor(host_object));
+ input1.push_back(SerializedVarTestConstructor("elite"));
+ SerializedVarVectorReceiveInput receive_input(input1);
+ uint32_t array_size = 0;
+ PP_Var* plugin_objects_array =
+ receive_input.Get(plugin_dispatcher(), &array_size);
+ plugin_objects.insert(plugin_objects.begin(), plugin_objects_array,
+ plugin_objects_array + array_size);
+ ASSERT_EQ(2u, array_size);
+ EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_objects[0]));
+ EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_objects[1]));
+ EXPECT_EQ(0u, sink().message_count());
+
+ // Receive the second param, it should be resolved to the same plugin
+ // object and there should still be no refcount.
+ std::vector<SerializedVar> input2;
+ input2.push_back(SerializedVarTestConstructor(host_object));
+ input2.push_back(SerializedVarTestConstructor("elite"));
+ SerializedVarVectorReceiveInput receive_input2(input2);
+ uint32_t array_size2 = 0;
+ PP_Var* plugin_objects_array2 =
+ receive_input2.Get(plugin_dispatcher(), &array_size2);
+ plugin_objects2.insert(plugin_objects2.begin(), plugin_objects_array2,
+ plugin_objects_array2 + array_size2);
+ ASSERT_EQ(2u, array_size2);
+ EXPECT_EQ(plugin_objects[0].value.as_id, plugin_objects2[0].value.as_id);
+ EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_objects[0]));
+ // Strings get re-created with a new ID. We don't try to reuse strings in
+ // the tracker, so the string should get a new ID.
+ EXPECT_NE(plugin_objects[1].value.as_id, plugin_objects2[1].value.as_id);
+ EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_objects2[1]));
+ EXPECT_EQ(0u, sink().message_count());
+
+ // Take a reference to the object, as if the plugin was using it, and then
+ // release it, we should still be tracking the object since the
+ // ReceiveInputs keep the "track_with_no_reference_count" alive until
+ // they're destroyed.
+ var_tracker().AddRefVar(plugin_objects[0]);
+ EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_objects[0]));
+ var_tracker().ReleaseVar(plugin_objects[0]);
+ EXPECT_EQ(0, var_tracker().GetRefCountForObject(plugin_objects[0]));
+ EXPECT_EQ(2u, sink().message_count());
+
+ // Take a reference to a string and then release it. Make sure no messages
+ // are sent.
+ uint32_t old_message_count = sink().message_count();
+ var_tracker().AddRefVar(plugin_objects[1]);
+ EXPECT_EQ(2, var_tracker().GetRefCountForObject(plugin_objects[1]));
+ var_tracker().ReleaseVar(plugin_objects[1]);
+ EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_objects[1]));
+ EXPECT_EQ(old_message_count, sink().message_count());
+ }
+
+ // Since we didn't keep any refs to the objects or strings, so they should
+ // have been freed.
+ EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_objects[0]));
+ EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_objects[1]));
+ EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_objects2[1]));
+}
+
+// Tests the plugin receiving a var as a return value from the browser
+// two different times (passing ownership).
+TEST_F(SerializedVarTest, PluginReceiveReturn) {
+ ProxyAutoLock lock;
+ PP_Var host_object = MakeObjectVar(0x31337);
+
+ PP_Var plugin_object;
+ {
+ // Receive the first param, we should be tracking it with a refcount of 1.
+ SerializedVarTestConstructor input1(host_object);
+ ReceiveSerializedVarReturnValue receive_input(input1);
+ plugin_object = receive_input.Return(plugin_dispatcher());
+ EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
+ EXPECT_EQ(0u, sink().message_count());
+
+ // Receive the second param, it should be resolved to the same plugin
+ // object and there should be a plugin refcount of 2. There should have
+ // been an IPC message sent that released the duplicated ref in the browser
+ // (so both of our refs are represented by one in the browser).
+ SerializedVarTestConstructor input2(host_object);
+ ReceiveSerializedVarReturnValue receive_input2(input2);
+ PP_Var plugin_object2 = receive_input2.Return(plugin_dispatcher());
+ EXPECT_EQ(plugin_object.value.as_id, plugin_object2.value.as_id);
+ EXPECT_EQ(2, var_tracker().GetRefCountForObject(plugin_object));
+ EXPECT_EQ(1u, sink().message_count());
+ }
+
+ // The ReceiveSerializedVarReturnValue destructor shouldn't have affected
+ // the refcount or sent any messages.
+ EXPECT_EQ(2, var_tracker().GetRefCountForObject(plugin_object));
+ EXPECT_EQ(1u, sink().message_count());
+
+ // Manually release one refcount, it shouldn't have sent any more messages.
+ var_tracker().ReleaseVar(plugin_object);
+ EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
+ EXPECT_EQ(1u, sink().message_count());
+
+ // Manually release the last refcount, it should have freed it and sent a
+ // release message to the browser.
+ var_tracker().ReleaseVar(plugin_object);
+ EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_object));
+ EXPECT_EQ(2u, sink().message_count());
+}
+
+// Returns a value from the browser to the plugin, then return that one ref
+// back to the browser.
+TEST_F(SerializedVarTest, PluginReturnValue) {
+ ProxyAutoLock lock;
+ PP_Var host_object = MakeObjectVar(0x31337);
+
+ PP_Var plugin_object;
+ {
+ // Receive the param in the plugin.
+ SerializedVarTestConstructor input1(host_object);
+ ReceiveSerializedVarReturnValue receive_input(input1);
+ plugin_object = receive_input.Return(plugin_dispatcher());
+ EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
+ EXPECT_EQ(0u, sink().message_count());
+ }
+
+ {
+ // Now return to the browser.
+ SerializedVar output;
+ SerializedVarReturnValue return_output(&output);
+ return_output.Return(plugin_dispatcher(), plugin_object);
+
+ // The ref in the plugin should be alive until the ReturnValue goes out of
+ // scope, since the release needs to be after the browser processes the
+ // message.
+ EXPECT_EQ(1, var_tracker().GetRefCountForObject(plugin_object));
+ }
+
+ // When the ReturnValue object goes out of scope, it should have sent a
+ // release message to the browser.
+ EXPECT_EQ(-1, var_tracker().GetRefCountForObject(plugin_object));
+ EXPECT_EQ(1u, sink().message_count());
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/talk_resource.cc b/chromium/ppapi/proxy/talk_resource.cc
new file mode 100644
index 00000000000..2e60abfd331
--- /dev/null
+++ b/chromium/ppapi/proxy/talk_resource.cc
@@ -0,0 +1,114 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/talk_resource.h"
+
+#include "base/bind.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace ppapi {
+namespace proxy {
+
+TalkResource::TalkResource(Connection connection, PP_Instance instance)
+ : PluginResource(connection, instance),
+ event_callback_(NULL),
+ event_callback_user_data_(NULL) {
+ SendCreate(BROWSER, PpapiHostMsg_Talk_Create());
+}
+
+TalkResource::~TalkResource() {
+}
+
+thunk::PPB_Talk_Private_API* TalkResource::AsPPB_Talk_Private_API() {
+ return this;
+}
+
+int32_t TalkResource::RequestPermission(
+ PP_TalkPermission permission,
+ scoped_refptr<TrackedCallback> callback) {
+ if (TrackedCallback::IsPending(permission_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ permission_callback_ = callback;
+
+ Call<PpapiPluginMsg_Talk_RequestPermissionReply>(
+ BROWSER,
+ PpapiHostMsg_Talk_RequestPermission(permission),
+ base::Bind(&TalkResource::OnRequestPermissionReply,
+ base::Unretained(this)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t TalkResource::StartRemoting(PP_TalkEventCallback event_callback,
+ void* user_data,
+ scoped_refptr<TrackedCallback> callback) {
+ if (TrackedCallback::IsPending(start_callback_) ||
+ event_callback_ != NULL)
+ return PP_ERROR_INPROGRESS;
+
+ start_callback_ = callback;
+ event_callback_ = event_callback;
+ event_callback_user_data_ = user_data;
+
+ Call<PpapiPluginMsg_Talk_StartRemotingReply>(
+ BROWSER,
+ PpapiHostMsg_Talk_StartRemoting(),
+ base::Bind(&TalkResource::OnStartRemotingReply,
+ base::Unretained(this)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t TalkResource::StopRemoting(scoped_refptr<TrackedCallback> callback) {
+ if (TrackedCallback::IsPending(stop_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ if (event_callback_ == NULL)
+ return PP_ERROR_FAILED;
+
+ stop_callback_ = callback;
+
+ Call<PpapiPluginMsg_Talk_StopRemotingReply>(
+ BROWSER,
+ PpapiHostMsg_Talk_StopRemoting(),
+ base::Bind(&TalkResource::OnStopRemotingReply,
+ base::Unretained(this)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void TalkResource::OnReplyReceived(const ResourceMessageReplyParams& params,
+ const IPC::Message& msg) {
+ IPC_BEGIN_MESSAGE_MAP(TalkResource, msg)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
+ PpapiPluginMsg_Talk_NotifyEvent,
+ OnNotifyEvent)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(
+ PluginResource::OnReplyReceived(params, msg))
+ IPC_END_MESSAGE_MAP()
+}
+
+void TalkResource::OnNotifyEvent(const ResourceMessageReplyParams& params,
+ PP_TalkEvent event) {
+ if (event_callback_ != NULL)
+ event_callback_(event_callback_user_data_, event);
+}
+
+void TalkResource::OnRequestPermissionReply(
+ const ResourceMessageReplyParams& params) {
+ permission_callback_->Run(params.result());
+}
+
+void TalkResource::OnStartRemotingReply(
+ const ResourceMessageReplyParams& params) {
+ start_callback_->Run(params.result());
+}
+
+void TalkResource::OnStopRemotingReply(
+ const ResourceMessageReplyParams& params) {
+ event_callback_ = NULL;
+ event_callback_user_data_ = NULL;
+ stop_callback_->Run(params.result());
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/talk_resource.h b/chromium/ppapi/proxy/talk_resource.h
new file mode 100644
index 00000000000..a2d88f00b6a
--- /dev/null
+++ b/chromium/ppapi/proxy/talk_resource.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_TALK_RESOURCE_H_
+#define PPAPI_PROXY_TALK_RESOURCE_H_
+
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/ppb_talk_private_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT TalkResource
+ : public PluginResource,
+ public NON_EXPORTED_BASE(thunk::PPB_Talk_Private_API) {
+ public:
+ TalkResource(Connection connection, PP_Instance instance);
+ virtual ~TalkResource();
+
+ // Resource overrides.
+ thunk::PPB_Talk_Private_API* AsPPB_Talk_Private_API();
+
+ private:
+ // PPB_Talk_API implementation.
+ virtual int32_t RequestPermission(
+ PP_TalkPermission permission,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t StartRemoting(
+ PP_TalkEventCallback event_callback,
+ void* user_data,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t StopRemoting(
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+
+ // PluginResource override.
+ virtual void OnReplyReceived(const ResourceMessageReplyParams& params,
+ const IPC::Message& msg) OVERRIDE;
+
+ void OnNotifyEvent(const ResourceMessageReplyParams& params,
+ PP_TalkEvent event);
+ void OnRequestPermissionReply(const ResourceMessageReplyParams& params);
+ void OnStartRemotingReply(const ResourceMessageReplyParams& params);
+ void OnStopRemotingReply(const ResourceMessageReplyParams& params);
+
+ scoped_refptr<TrackedCallback> permission_callback_;
+ scoped_refptr<TrackedCallback> start_callback_;
+ scoped_refptr<TrackedCallback> stop_callback_;
+ PP_TalkEventCallback event_callback_;
+ void* event_callback_user_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(TalkResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_TALK_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/talk_resource_unittest.cc b/chromium/ppapi/proxy/talk_resource_unittest.cc
new file mode 100644
index 00000000000..e81a8a6aca3
--- /dev/null
+++ b/chromium/ppapi/proxy/talk_resource_unittest.cc
@@ -0,0 +1,173 @@
+// Copyright 2013 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/locking_resource_releaser.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+#include "ppapi/proxy/talk_resource.h"
+#include "ppapi/thunk/thunk.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+template <class ResultType>
+class MockCallbackBase {
+ public:
+ MockCallbackBase() : called_(false) {
+ }
+
+ bool called() {
+ return called_;
+ }
+
+ ResultType result() {
+ return result_;
+ }
+
+ void Reset() {
+ called_ = false;
+ }
+
+ static void Callback(void* user_data, ResultType result) {
+ MockCallbackBase* that = reinterpret_cast<MockCallbackBase*>(user_data);
+ that->called_ = true;
+ that->result_ = result;
+ }
+
+ private:
+ bool called_;
+ ResultType result_;
+};
+
+typedef MockCallbackBase<int32_t> MockCompletionCallback;
+typedef MockCallbackBase<PP_TalkEvent> TalkEventCallback;
+
+class TalkResourceTest : public PluginProxyTest {
+ public:
+ void SendReply(
+ uint32_t id,
+ const IPC::Message& reply,
+ int32_t result) {
+ IPC::Message msg;
+ ResourceMessageCallParams params;
+ ASSERT_TRUE(sink().GetFirstResourceCallMatching(id, &params, &msg));
+
+ ResourceMessageReplyParams reply_params(params.pp_resource(),
+ params.sequence());
+ reply_params.set_result(result);
+ IPC::Message reply_msg = PpapiPluginMsg_ResourceReply(reply_params, reply);
+ ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(reply_msg));
+ }
+};
+
+
+} // namespace
+
+TEST_F(TalkResourceTest, GetPermission) {
+ const PPB_Talk_Private_1_0* talk = thunk::GetPPB_Talk_Private_1_0_Thunk();
+ LockingResourceReleaser res(talk->Create(pp_instance()));
+ MockCompletionCallback callback;
+
+ int32_t result = talk->GetPermission(
+ res.get(),
+ PP_MakeCompletionCallback(&MockCompletionCallback::Callback, &callback));
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
+
+ ResourceMessageCallParams params;
+ IPC::Message msg;
+ ASSERT_TRUE(sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_Talk_RequestPermission::ID, &params, &msg));
+
+ ResourceMessageReplyParams reply_params(params.pp_resource(),
+ params.sequence());
+ reply_params.set_result(1);
+ IPC::Message reply = PpapiPluginMsg_ResourceReply(
+ reply_params, PpapiPluginMsg_Talk_RequestPermissionReply());
+ ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(reply));
+
+ ASSERT_TRUE(callback.called());
+ ASSERT_EQ(1, callback.result());
+}
+
+TEST_F(TalkResourceTest, RequestPermission) {
+ const PPB_Talk_Private_2_0* talk = thunk::GetPPB_Talk_Private_2_0_Thunk();
+ LockingResourceReleaser res(talk->Create(pp_instance()));
+ MockCompletionCallback callback;
+
+ int32_t result = talk->RequestPermission(
+ res.get(),
+ PP_TALKPERMISSION_REMOTING_CONTINUE,
+ PP_MakeCompletionCallback(&MockCompletionCallback::Callback, &callback));
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
+
+ ResourceMessageCallParams params;
+ IPC::Message msg;
+ ASSERT_TRUE(sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_Talk_RequestPermission::ID, &params, &msg));
+
+ ResourceMessageReplyParams reply_params(params.pp_resource(),
+ params.sequence());
+ reply_params.set_result(1);
+ IPC::Message reply = PpapiPluginMsg_ResourceReply(
+ reply_params, PpapiPluginMsg_Talk_RequestPermissionReply());
+ ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(reply));
+
+ ASSERT_TRUE(callback.called());
+ ASSERT_EQ(1, callback.result());
+}
+
+TEST_F(TalkResourceTest, StartStopRemoting) {
+ const PPB_Talk_Private_2_0* talk = thunk::GetPPB_Talk_Private_2_0_Thunk();
+ LockingResourceReleaser res(talk->Create(pp_instance()));
+ MockCompletionCallback callback;
+ TalkEventCallback event_callback;
+
+ // Start
+ int32_t result = talk->StartRemoting(
+ res.get(),
+ &TalkEventCallback::Callback,
+ &event_callback,
+ PP_MakeCompletionCallback(&MockCompletionCallback::Callback, &callback));
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
+
+ SendReply(PpapiHostMsg_Talk_StartRemoting::ID,
+ PpapiPluginMsg_Talk_StartRemotingReply(),
+ PP_OK);
+
+ ASSERT_TRUE(callback.called());
+ ASSERT_EQ(PP_OK, callback.result());
+
+ // Receive an event
+ ASSERT_FALSE(event_callback.called());
+ ResourceMessageReplyParams notify_params(res.get(), 0);
+ IPC::Message notify = PpapiPluginMsg_ResourceReply(
+ notify_params, PpapiPluginMsg_Talk_NotifyEvent(PP_TALKEVENT_ERROR));
+ ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(notify));
+ ASSERT_TRUE(event_callback.called());
+ ASSERT_EQ(PP_TALKEVENT_ERROR, event_callback.result());
+
+ // Stop
+ callback.Reset();
+ result = talk->StopRemoting(
+ res.get(),
+ PP_MakeCompletionCallback(&MockCompletionCallback::Callback, &callback));
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
+
+ SendReply(PpapiHostMsg_Talk_StopRemoting::ID,
+ PpapiPluginMsg_Talk_StopRemotingReply(),
+ PP_OK);
+
+ ASSERT_TRUE(callback.called());
+ ASSERT_EQ(PP_OK, callback.result());
+
+ // Events should be discarded at this point
+ event_callback.Reset();
+ ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(notify));
+ ASSERT_FALSE(event_callback.called());
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/tcp_server_socket_private_resource.cc b/chromium/ppapi/proxy/tcp_server_socket_private_resource.cc
new file mode 100644
index 00000000000..6bbf4667ee7
--- /dev/null
+++ b/chromium/ppapi/proxy/tcp_server_socket_private_resource.cc
@@ -0,0 +1,138 @@
+// Copyright 2013 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/tcp_server_socket_private_resource.h"
+
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_tcp_socket_private_proxy.h"
+
+namespace ppapi {
+namespace proxy {
+
+TCPServerSocketPrivateResource::TCPServerSocketPrivateResource(
+ Connection connection,
+ PP_Instance instance)
+ : PluginResource(connection, instance),
+ state_(STATE_BEFORE_LISTENING),
+ local_addr_(),
+ plugin_dispatcher_id_(0) {
+ SendCreate(BROWSER, PpapiHostMsg_TCPServerSocket_CreatePrivate());
+
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (dispatcher)
+ plugin_dispatcher_id_ = dispatcher->plugin_dispatcher_id();
+ else
+ NOTREACHED();
+}
+
+TCPServerSocketPrivateResource::~TCPServerSocketPrivateResource() {
+}
+
+thunk::PPB_TCPServerSocket_Private_API*
+TCPServerSocketPrivateResource::AsPPB_TCPServerSocket_Private_API() {
+ return this;
+}
+
+int32_t TCPServerSocketPrivateResource::Listen(
+ const PP_NetAddress_Private* addr,
+ int32_t backlog,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!addr)
+ return PP_ERROR_BADARGUMENT;
+ if (state_ != STATE_BEFORE_LISTENING)
+ return PP_ERROR_FAILED;
+ if (TrackedCallback::IsPending(listen_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ listen_callback_ = callback;
+
+ // Send the request, the browser will call us back via ListenACK
+ Call<PpapiPluginMsg_TCPServerSocket_ListenReply>(
+ BROWSER,
+ PpapiHostMsg_TCPServerSocket_Listen(*addr, backlog),
+ base::Bind(&TCPServerSocketPrivateResource::OnPluginMsgListenReply,
+ base::Unretained(this)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t TCPServerSocketPrivateResource::Accept(
+ PP_Resource* tcp_socket,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!tcp_socket)
+ return PP_ERROR_BADARGUMENT;
+ if (state_ != STATE_LISTENING)
+ return PP_ERROR_FAILED;
+ if (TrackedCallback::IsPending(accept_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ accept_callback_ = callback;
+
+ Call<PpapiPluginMsg_TCPServerSocket_AcceptReply>(
+ BROWSER,
+ PpapiHostMsg_TCPServerSocket_Accept(plugin_dispatcher_id_),
+ base::Bind(&TCPServerSocketPrivateResource::OnPluginMsgAcceptReply,
+ base::Unretained(this), tcp_socket));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t TCPServerSocketPrivateResource::GetLocalAddress(
+ PP_NetAddress_Private* addr) {
+ if (!addr)
+ return PP_ERROR_BADARGUMENT;
+ if (state_ != STATE_LISTENING)
+ return PP_ERROR_FAILED;
+ *addr = local_addr_;
+ return PP_OK;
+}
+
+void TCPServerSocketPrivateResource::StopListening() {
+ if (state_ == STATE_CLOSED)
+ return;
+ state_ = STATE_CLOSED;
+ Post(BROWSER, PpapiHostMsg_TCPServerSocket_StopListening());
+ if (TrackedCallback::IsPending(listen_callback_))
+ listen_callback_->PostAbort();
+ if (TrackedCallback::IsPending(accept_callback_))
+ accept_callback_->PostAbort();
+}
+
+void TCPServerSocketPrivateResource::OnPluginMsgListenReply(
+ const ResourceMessageReplyParams& params,
+ const PP_NetAddress_Private& local_addr) {
+ if (state_ != STATE_BEFORE_LISTENING ||
+ !TrackedCallback::IsPending(listen_callback_)) {
+ return;
+ }
+ if (params.result() == PP_OK) {
+ local_addr_ = local_addr;
+ state_ = STATE_LISTENING;
+ }
+ listen_callback_->Run(params.result());
+}
+
+void TCPServerSocketPrivateResource::OnPluginMsgAcceptReply(
+ PP_Resource* tcp_socket,
+ const ResourceMessageReplyParams& params,
+ uint32 accepted_socket_id,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr) {
+ DCHECK(tcp_socket);
+ if (state_ != STATE_LISTENING ||
+ !TrackedCallback::IsPending(accept_callback_)) {
+ return;
+ }
+ if (params.result() == PP_OK) {
+ *tcp_socket =
+ PPB_TCPSocket_Private_Proxy::CreateProxyResourceForConnectedSocket(
+ pp_instance(),
+ accepted_socket_id,
+ local_addr,
+ remote_addr);
+ }
+ accept_callback_->Run(params.result());
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/tcp_server_socket_private_resource.h b/chromium/ppapi/proxy/tcp_server_socket_private_resource.h
new file mode 100644
index 00000000000..95febde92cd
--- /dev/null
+++ b/chromium/ppapi/proxy/tcp_server_socket_private_resource.h
@@ -0,0 +1,69 @@
+// Copyright 2013 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_TCP_SERVER_SOCKET_PRIVATE_RESOURCE_H_
+#define PPAPI_PROXY_TCP_SERVER_SOCKET_PRIVATE_RESOURCE_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/ppb_tcp_server_socket_private_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT TCPServerSocketPrivateResource
+ : public PluginResource,
+ public thunk::PPB_TCPServerSocket_Private_API {
+ public:
+ TCPServerSocketPrivateResource(Connection connection, PP_Instance instance);
+ virtual ~TCPServerSocketPrivateResource();
+
+ // PluginResource implementation.
+ virtual thunk::PPB_TCPServerSocket_Private_API*
+ AsPPB_TCPServerSocket_Private_API() OVERRIDE;
+
+ // PPB_TCPServerSocket_Private_API implementation.
+ virtual int32_t Listen(const PP_NetAddress_Private* addr,
+ int32_t backlog,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Accept(PP_Resource* tcp_socket,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t GetLocalAddress(PP_NetAddress_Private* addr) OVERRIDE;
+ virtual void StopListening() OVERRIDE;
+
+ private:
+ enum State {
+ STATE_BEFORE_LISTENING,
+ STATE_LISTENING,
+ STATE_CLOSED
+ };
+
+ // IPC message handlers.
+ void OnPluginMsgListenReply(const ResourceMessageReplyParams& params,
+ const PP_NetAddress_Private& local_addr);
+ void OnPluginMsgAcceptReply(PP_Resource* tcp_socket,
+ const ResourceMessageReplyParams& params,
+ uint32 accepted_socket_id,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr);
+
+ State state_;
+ PP_NetAddress_Private local_addr_;
+
+ uint32 plugin_dispatcher_id_;
+
+ scoped_refptr<TrackedCallback> listen_callback_;
+ scoped_refptr<TrackedCallback> accept_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(TCPServerSocketPrivateResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_TCP_SERVER_SOCKET_PRIVATE_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/truetype_font_resource.cc b/chromium/ppapi/proxy/truetype_font_resource.cc
new file mode 100644
index 00000000000..1de32abb434
--- /dev/null
+++ b/chromium/ppapi/proxy/truetype_font_resource.cc
@@ -0,0 +1,130 @@
+// Copyright (c) 2013 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/truetype_font_resource.h"
+
+#include "base/bind.h"
+#include "ipc/ipc_message.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/array_writer.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/resource_tracker.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/enter.h"
+
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_TrueTypeFont_API;
+
+namespace {
+
+} // namespace
+
+namespace ppapi {
+namespace proxy {
+
+TrueTypeFontResource::TrueTypeFontResource(
+ Connection connection,
+ PP_Instance instance,
+ const PP_TrueTypeFontDesc_Dev& desc)
+ : PluginResource(connection, instance) {
+ SerializedTrueTypeFontDesc serialized_desc;
+ serialized_desc.SetFromPPTrueTypeFontDesc(desc);
+ SendCreate(RENDERER, PpapiHostMsg_TrueTypeFont_Create(serialized_desc));
+}
+
+TrueTypeFontResource::~TrueTypeFontResource() {
+}
+
+PPB_TrueTypeFont_API* TrueTypeFontResource::AsPPB_TrueTypeFont_API() {
+ return this;
+}
+
+int32_t TrueTypeFontResource::Describe(
+ PP_TrueTypeFontDesc_Dev* desc,
+ scoped_refptr<TrackedCallback> callback) {
+ Call<PpapiPluginMsg_TrueTypeFont_DescribeReply>(RENDERER,
+ PpapiHostMsg_TrueTypeFont_Describe(),
+ base::Bind(&TrueTypeFontResource::OnPluginMsgDescribeComplete, this,
+ callback, desc));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t TrueTypeFontResource::GetTableTags(
+ const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback) {
+ Call<PpapiPluginMsg_TrueTypeFont_GetTableTagsReply>(RENDERER,
+ PpapiHostMsg_TrueTypeFont_GetTableTags(),
+ base::Bind(&TrueTypeFontResource::OnPluginMsgGetTableTagsComplete, this,
+ callback, output));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t TrueTypeFontResource::GetTable(
+ uint32_t table,
+ int32_t offset,
+ int32_t max_data_length,
+ const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback) {
+ Call<PpapiPluginMsg_TrueTypeFont_GetTableReply>(RENDERER,
+ PpapiHostMsg_TrueTypeFont_GetTable(table, offset, max_data_length),
+ base::Bind(&TrueTypeFontResource::OnPluginMsgGetTableComplete, this,
+ callback, output));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void TrueTypeFontResource::OnPluginMsgDescribeComplete(
+ scoped_refptr<TrackedCallback> callback,
+ PP_TrueTypeFontDesc_Dev* pp_desc,
+ const ResourceMessageReplyParams& params,
+ const ppapi::proxy::SerializedTrueTypeFontDesc& desc) {
+ int32_t result = params.result();
+ if (result == PP_OK)
+ desc.CopyToPPTrueTypeFontDesc(pp_desc);
+
+ callback->Run(result);
+}
+
+void TrueTypeFontResource::OnPluginMsgGetTableTagsComplete(
+ scoped_refptr<TrackedCallback> callback,
+ PP_ArrayOutput array_output,
+ const ResourceMessageReplyParams& params,
+ const std::vector<uint32_t>& tag_array) {
+ // The result code should contain the data size if it's positive.
+ int32_t result = params.result();
+ DCHECK((result < 0 && tag_array.size() == 0) ||
+ result == static_cast<int32_t>(tag_array.size()));
+
+ ArrayWriter output;
+ output.set_pp_array_output(array_output);
+ if (output.is_valid())
+ output.StoreArray(&tag_array[0], std::max(0, result));
+ else
+ result = PP_ERROR_FAILED;
+
+ callback->Run(result);
+}
+
+void TrueTypeFontResource::OnPluginMsgGetTableComplete(
+ scoped_refptr<TrackedCallback> callback,
+ PP_ArrayOutput array_output,
+ const ResourceMessageReplyParams& params,
+ const std::string& data) {
+ // The result code should contain the data size if it's positive.
+ int32_t result = params.result();
+ DCHECK((result < 0 && data.size() == 0) ||
+ result == static_cast<int32_t>(data.size()));
+
+ ArrayWriter output;
+ output.set_pp_array_output(array_output);
+ if (output.is_valid())
+ output.StoreArray(data.data(), std::max(0, result));
+ else
+ result = PP_ERROR_FAILED;
+
+ callback->Run(result);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/truetype_font_resource.h b/chromium/ppapi/proxy/truetype_font_resource.h
new file mode 100644
index 00000000000..6aac2d569e2
--- /dev/null
+++ b/chromium/ppapi/proxy/truetype_font_resource.h
@@ -0,0 +1,73 @@
+// Copyright (c) 2013 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_TRUETYPE_FONT_RESOURCE_H_
+#define PPAPI_PROXY_TRUETYPE_FONT_RESOURCE_H_
+
+#include <string>
+
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/ppb_truetype_font_api.h"
+
+namespace ppapi {
+
+class TrackedCallback;
+
+namespace proxy {
+
+struct SerializedTrueTypeFontDesc;
+
+class PPAPI_PROXY_EXPORT TrueTypeFontResource
+ : public PluginResource,
+ public thunk::PPB_TrueTypeFont_API {
+ public:
+ TrueTypeFontResource(Connection connection,
+ PP_Instance instance,
+ const PP_TrueTypeFontDesc_Dev& desc);
+ virtual ~TrueTypeFontResource();
+
+ // Resource overrides.
+ virtual thunk::PPB_TrueTypeFont_API* AsPPB_TrueTypeFont_API() OVERRIDE;
+
+ // PPB_TrueTypeFont_API implementation.
+ virtual int32_t Describe(
+ PP_TrueTypeFontDesc_Dev* desc,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t GetTableTags(
+ const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t GetTable(
+ uint32_t table,
+ int32_t offset,
+ int32_t max_data_length,
+ const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+
+ private:
+ void OnPluginMsgDescribeComplete(
+ scoped_refptr<TrackedCallback> callback,
+ PP_TrueTypeFontDesc_Dev* pp_desc,
+ const ResourceMessageReplyParams& params,
+ const ppapi::proxy::SerializedTrueTypeFontDesc& desc);
+ void OnPluginMsgGetTableTagsComplete(
+ scoped_refptr<TrackedCallback> callback,
+ PP_ArrayOutput array_output,
+ const ResourceMessageReplyParams& params,
+ const std::vector<uint32_t>& data);
+ void OnPluginMsgGetTableComplete(
+ scoped_refptr<TrackedCallback> callback,
+ PP_ArrayOutput array_output,
+ const ResourceMessageReplyParams& params,
+ const std::string& data);
+
+ DISALLOW_COPY_AND_ASSIGN(TrueTypeFontResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_TRUETYPE_FONT_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/truetype_font_singleton_resource.cc b/chromium/ppapi/proxy/truetype_font_singleton_resource.cc
new file mode 100644
index 00000000000..77a7432c549
--- /dev/null
+++ b/chromium/ppapi/proxy/truetype_font_singleton_resource.cc
@@ -0,0 +1,122 @@
+// Copyright (c) 2013 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/truetype_font_singleton_resource.h"
+
+#include "base/bind.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/serialized_structs.h"
+#include "ppapi/shared_impl/array_writer.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/shared_impl/var_tracker.h"
+
+namespace ppapi {
+namespace proxy {
+
+TrueTypeFontSingletonResource::TrueTypeFontSingletonResource(
+ Connection connection,
+ PP_Instance instance)
+ : PluginResource(connection, instance) {
+ SendCreate(BROWSER, PpapiHostMsg_TrueTypeFontSingleton_Create());
+}
+
+TrueTypeFontSingletonResource::~TrueTypeFontSingletonResource() {
+}
+
+thunk::PPB_TrueTypeFont_Singleton_API*
+TrueTypeFontSingletonResource::AsPPB_TrueTypeFont_Singleton_API() {
+ return this;
+}
+
+int32_t TrueTypeFontSingletonResource::GetFontFamilies(
+ PP_Instance instance,
+ const PP_ArrayOutput& output,
+ const scoped_refptr<TrackedCallback>& callback) {
+ Call<PpapiPluginMsg_TrueTypeFontSingleton_GetFontFamiliesReply>(BROWSER,
+ PpapiHostMsg_TrueTypeFontSingleton_GetFontFamilies(),
+ base::Bind(
+ &TrueTypeFontSingletonResource::OnPluginMsgGetFontFamiliesComplete,
+ this, callback, output));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t TrueTypeFontSingletonResource::GetFontsInFamily(
+ PP_Instance instance,
+ PP_Var family,
+ const PP_ArrayOutput& output,
+ const scoped_refptr<TrackedCallback>& callback) {
+ scoped_refptr<StringVar> family_var = StringVar::FromPPVar(family);
+ const uint32_t kMaxFamilySizeInBytes = 1024;
+ if (!family_var.get() || family_var->value().size() > kMaxFamilySizeInBytes)
+ return PP_ERROR_BADARGUMENT;
+ Call<PpapiPluginMsg_TrueTypeFontSingleton_GetFontsInFamilyReply>(BROWSER,
+ PpapiHostMsg_TrueTypeFontSingleton_GetFontsInFamily(family_var->value()),
+ base::Bind(
+ &TrueTypeFontSingletonResource::OnPluginMsgGetFontsInFamilyComplete,
+ this, callback, output));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void TrueTypeFontSingletonResource::OnPluginMsgGetFontFamiliesComplete(
+ scoped_refptr<TrackedCallback> callback,
+ PP_ArrayOutput array_output,
+ const ResourceMessageReplyParams& params,
+ const std::vector<std::string>& font_families) {
+ if (!TrackedCallback::IsPending(callback))
+ return;
+ // The result code should contain the data size if it's positive.
+ int32_t result = params.result();
+ DCHECK((result < 0 && font_families.size() == 0) ||
+ result == static_cast<int32_t>(font_families.size()));
+
+ ArrayWriter output;
+ output.set_pp_array_output(array_output);
+ if (output.is_valid()) {
+ std::vector< scoped_refptr<Var> > font_family_vars;
+ for (size_t i = 0; i < font_families.size(); i++)
+ font_family_vars.push_back(
+ scoped_refptr<Var>(new StringVar(font_families[i])));
+ output.StoreVarVector(font_family_vars);
+ } else {
+ result = PP_ERROR_FAILED;
+ }
+
+ callback->Run(result);
+}
+
+void TrueTypeFontSingletonResource::OnPluginMsgGetFontsInFamilyComplete(
+ scoped_refptr<TrackedCallback> callback,
+ PP_ArrayOutput array_output,
+ const ResourceMessageReplyParams& params,
+ const std::vector<SerializedTrueTypeFontDesc>& fonts) {
+ if (!TrackedCallback::IsPending(callback))
+ return;
+ // The result code should contain the data size if it's positive.
+ int32_t result = params.result();
+ DCHECK((result < 0 && fonts.size() == 0) ||
+ result == static_cast<int32_t>(fonts.size()));
+ ArrayWriter output;
+ output.set_pp_array_output(array_output);
+ if (output.is_valid()) {
+ // Convert the message data to an array of PP_TrueTypeFontDesc_Dev structs.
+ // Each desc has an embedded PP_Var containing the family name.
+ std::vector<PP_TrueTypeFontDesc_Dev> pp_fonts(fonts.size());
+ for (size_t i = 0; i < fonts.size(); i++)
+ fonts[i].CopyToPPTrueTypeFontDesc(&pp_fonts[i]);
+
+ if (!output.StoreVector(pp_fonts)) {
+ for (size_t i = 0; i < pp_fonts.size(); i++)
+ PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(pp_fonts[i].family);
+ }
+ } else {
+ result = PP_ERROR_FAILED;
+ }
+
+ callback->Run(result);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/truetype_font_singleton_resource.h b/chromium/ppapi/proxy/truetype_font_singleton_resource.h
new file mode 100644
index 00000000000..dee58632dcb
--- /dev/null
+++ b/chromium/ppapi/proxy/truetype_font_singleton_resource.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2013 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_TRUETYPE_FONT_SINGLETON_RESOURCE_H_
+#define PPAPI_PROXY_TRUETYPE_FONT_SINGLETON_RESOURCE_H_
+
+#include <string>
+#include <vector>
+
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/thunk/ppb_truetype_font_singleton_api.h"
+
+namespace ppapi {
+
+class TrackedCallback;
+
+namespace proxy {
+
+struct SerializedTrueTypeFontDesc;
+
+// This handles the singleton calls (that don't take a PP_Resource parameter)
+// on the TrueType font interface.
+class TrueTypeFontSingletonResource
+ : public PluginResource,
+ public thunk::PPB_TrueTypeFont_Singleton_API {
+ public:
+ TrueTypeFontSingletonResource(Connection connection, PP_Instance instance);
+ virtual ~TrueTypeFontSingletonResource();
+
+ // Resource override.
+ virtual thunk::PPB_TrueTypeFont_Singleton_API*
+ AsPPB_TrueTypeFont_Singleton_API() OVERRIDE;
+
+ // thunk::PPB_TrueTypeFont_Singleton_API implementation.
+ virtual int32_t GetFontFamilies(
+ PP_Instance instance,
+ const PP_ArrayOutput& output,
+ const scoped_refptr<TrackedCallback>& callback) OVERRIDE;
+ virtual int32_t GetFontsInFamily(
+ PP_Instance instance,
+ PP_Var family,
+ const PP_ArrayOutput& output,
+ const scoped_refptr<TrackedCallback>& callback) OVERRIDE;
+
+ private:
+ void OnPluginMsgGetFontFamiliesComplete(
+ scoped_refptr<TrackedCallback> callback,
+ PP_ArrayOutput array_output,
+ const ResourceMessageReplyParams& params,
+ const std::vector<std::string>& data);
+ void OnPluginMsgGetFontsInFamilyComplete(
+ scoped_refptr<TrackedCallback> callback,
+ PP_ArrayOutput array_output,
+ const ResourceMessageReplyParams& params,
+ const std::vector<SerializedTrueTypeFontDesc>& fonts);
+
+ DISALLOW_COPY_AND_ASSIGN(TrueTypeFontSingletonResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_TRUETYPE_FONT_SINGLETON_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/udp_socket_private_resource.cc b/chromium/ppapi/proxy/udp_socket_private_resource.cc
new file mode 100644
index 00000000000..af43c10fb05
--- /dev/null
+++ b/chromium/ppapi/proxy/udp_socket_private_resource.cc
@@ -0,0 +1,83 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/udp_socket_private_resource.h"
+
+#include "base/logging.h"
+#include "ppapi/c/ppb_udp_socket.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+
+namespace ppapi {
+namespace proxy {
+
+UDPSocketPrivateResource::UDPSocketPrivateResource(Connection connection,
+ PP_Instance instance)
+ : UDPSocketResourceBase(connection, instance, true) {
+}
+
+UDPSocketPrivateResource::~UDPSocketPrivateResource() {
+}
+
+thunk::PPB_UDPSocket_Private_API*
+UDPSocketPrivateResource::AsPPB_UDPSocket_Private_API() {
+ return this;
+}
+
+int32_t UDPSocketPrivateResource::SetSocketFeature(
+ PP_UDPSocketFeature_Private name,
+ PP_Var value) {
+ PP_UDPSocket_Option public_name = PP_UDPSOCKET_OPTION_ADDRESS_REUSE;
+ switch (name) {
+ case PP_UDPSOCKETFEATURE_PRIVATE_ADDRESS_REUSE:
+ // |public_name| has been initialized above.
+ break;
+ case PP_UDPSOCKETFEATURE_PRIVATE_BROADCAST:
+ public_name = PP_UDPSOCKET_OPTION_BROADCAST;
+ break;
+ case PP_UDPSOCKETFEATURE_PRIVATE_COUNT:
+ return PP_ERROR_BADARGUMENT;
+ default:
+ NOTREACHED();
+ return PP_ERROR_BADARGUMENT;
+ }
+ int32_t result = SetOptionImpl(public_name, value, NULL);
+ return result == PP_OK_COMPLETIONPENDING ? PP_OK : result;
+}
+
+int32_t UDPSocketPrivateResource::Bind(
+ const PP_NetAddress_Private* addr,
+ scoped_refptr<TrackedCallback> callback) {
+ return BindImpl(addr, callback);
+}
+
+PP_Bool UDPSocketPrivateResource::GetBoundAddress(PP_NetAddress_Private* addr) {
+ return GetBoundAddressImpl(addr);
+}
+
+int32_t UDPSocketPrivateResource::RecvFrom(
+ char* buffer,
+ int32_t num_bytes,
+ scoped_refptr<TrackedCallback> callback) {
+ return RecvFromImpl(buffer, num_bytes, NULL, callback);
+}
+
+PP_Bool UDPSocketPrivateResource::GetRecvFromAddress(
+ PP_NetAddress_Private* addr) {
+ return GetRecvFromAddressImpl(addr);
+}
+
+int32_t UDPSocketPrivateResource::SendTo(
+ const char* buffer,
+ int32_t num_bytes,
+ const PP_NetAddress_Private* addr,
+ scoped_refptr<TrackedCallback> callback) {
+ return SendToImpl(buffer, num_bytes, addr, callback);
+}
+
+void UDPSocketPrivateResource::Close() {
+ CloseImpl();
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/udp_socket_private_resource.h b/chromium/ppapi/proxy/udp_socket_private_resource.h
new file mode 100644
index 00000000000..48f5d71198b
--- /dev/null
+++ b/chromium/ppapi/proxy/udp_socket_private_resource.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_UDP_SOCKET_PRIVATE_RESOURCE_H_
+#define PPAPI_PROXY_UDP_SOCKET_PRIVATE_RESOURCE_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/proxy/udp_socket_resource_base.h"
+#include "ppapi/thunk/ppb_udp_socket_private_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT UDPSocketPrivateResource
+ : public UDPSocketResourceBase,
+ public thunk::PPB_UDPSocket_Private_API {
+ public:
+ UDPSocketPrivateResource(Connection connection, PP_Instance instance);
+ virtual ~UDPSocketPrivateResource();
+
+ // PluginResource implementation.
+ virtual thunk::PPB_UDPSocket_Private_API*
+ AsPPB_UDPSocket_Private_API() OVERRIDE;
+
+ // PPB_UDPSocket_Private_API implementation.
+ virtual int32_t SetSocketFeature(PP_UDPSocketFeature_Private name,
+ PP_Var value) OVERRIDE;
+ virtual int32_t Bind(const PP_NetAddress_Private* addr,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual PP_Bool GetBoundAddress(PP_NetAddress_Private* addr) OVERRIDE;
+ virtual int32_t RecvFrom(char* buffer,
+ int32_t num_bytes,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual PP_Bool GetRecvFromAddress(PP_NetAddress_Private* addr) OVERRIDE;
+ virtual int32_t SendTo(const char* buffer,
+ int32_t num_bytes,
+ const PP_NetAddress_Private* addr,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual void Close() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(UDPSocketPrivateResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_UDP_SOCKET_PRIVATE_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/udp_socket_resource.cc b/chromium/ppapi/proxy/udp_socket_resource.cc
new file mode 100644
index 00000000000..9ce7c91f130
--- /dev/null
+++ b/chromium/ppapi/proxy/udp_socket_resource.cc
@@ -0,0 +1,86 @@
+// Copyright 2013 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/udp_socket_resource.h"
+
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_net_address_api.h"
+#include "ppapi/thunk/resource_creation_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+typedef thunk::EnterResourceNoLock<thunk::PPB_NetAddress_API>
+ EnterNetAddressNoLock;
+
+} // namespace
+
+UDPSocketResource::UDPSocketResource(Connection connection,
+ PP_Instance instance)
+ : UDPSocketResourceBase(connection, instance, false) {
+}
+
+UDPSocketResource::~UDPSocketResource() {
+}
+
+thunk::PPB_UDPSocket_API* UDPSocketResource::AsPPB_UDPSocket_API() {
+ return this;
+}
+
+int32_t UDPSocketResource::Bind(PP_Resource addr,
+ scoped_refptr<TrackedCallback> callback) {
+ EnterNetAddressNoLock enter(addr, true);
+ if (enter.failed())
+ return PP_ERROR_BADARGUMENT;
+
+ return BindImpl(&enter.object()->GetNetAddressPrivate(), callback);
+}
+
+PP_Resource UDPSocketResource::GetBoundAddress() {
+ PP_NetAddress_Private addr_private;
+ if (!GetBoundAddressImpl(&addr_private))
+ return 0;
+
+ thunk::EnterResourceCreationNoLock enter(pp_instance());
+ if (enter.failed())
+ return 0;
+ return enter.functions()->CreateNetAddressFromNetAddressPrivate(
+ pp_instance(), addr_private);
+}
+
+int32_t UDPSocketResource::RecvFrom(char* buffer,
+ int32_t num_bytes,
+ PP_Resource* addr,
+ scoped_refptr<TrackedCallback> callback) {
+ return RecvFromImpl(buffer, num_bytes, addr, callback);
+}
+
+int32_t UDPSocketResource::SendTo(const char* buffer,
+ int32_t num_bytes,
+ PP_Resource addr,
+ scoped_refptr<TrackedCallback> callback) {
+ EnterNetAddressNoLock enter(addr, true);
+ if (enter.failed())
+ return PP_ERROR_BADARGUMENT;
+
+ return SendToImpl(buffer, num_bytes, &enter.object()->GetNetAddressPrivate(),
+ callback);
+}
+
+void UDPSocketResource::Close() {
+ CloseImpl();
+}
+
+int32_t UDPSocketResource::SetOption(
+ PP_UDPSocket_Option name,
+ const PP_Var& value,
+ scoped_refptr<TrackedCallback> callback) {
+ return SetOptionImpl(name, value, callback);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/udp_socket_resource.h b/chromium/ppapi/proxy/udp_socket_resource.h
new file mode 100644
index 00000000000..7df9797fb07
--- /dev/null
+++ b/chromium/ppapi/proxy/udp_socket_resource.h
@@ -0,0 +1,50 @@
+// Copyright 2013 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_UDP_SOCKET_RESOURCE_H_
+#define PPAPI_PROXY_UDP_SOCKET_RESOURCE_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/proxy/udp_socket_resource_base.h"
+#include "ppapi/thunk/ppb_udp_socket_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT UDPSocketResource : public UDPSocketResourceBase,
+ public thunk::PPB_UDPSocket_API {
+ public:
+ UDPSocketResource(Connection connection, PP_Instance instance);
+ virtual ~UDPSocketResource();
+
+ // PluginResource implementation.
+ virtual thunk::PPB_UDPSocket_API* AsPPB_UDPSocket_API() OVERRIDE;
+
+ // thunk::PPB_UDPSocket_API implementation.
+ virtual int32_t Bind(PP_Resource addr,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual PP_Resource GetBoundAddress() OVERRIDE;
+ virtual int32_t RecvFrom(char* buffer,
+ int32_t num_bytes,
+ PP_Resource* addr,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t SendTo(const char* buffer,
+ int32_t num_bytes,
+ PP_Resource addr,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual void Close() OVERRIDE;
+ virtual int32_t SetOption(PP_UDPSocket_Option name,
+ const PP_Var& value,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(UDPSocketResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_UDP_SOCKET_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/udp_socket_resource_base.cc b/chromium/ppapi/proxy/udp_socket_resource_base.cc
new file mode 100644
index 00000000000..166f2e30856
--- /dev/null
+++ b/chromium/ppapi/proxy/udp_socket_resource_base.cc
@@ -0,0 +1,301 @@
+// Copyright 2013 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/udp_socket_resource_base.h"
+
+#include <algorithm>
+#include <cstring>
+
+#include "base/logging.h"
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/socket_option_data.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/resource_creation_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+int32_t ConvertPPError(int32_t pp_error, bool private_api) {
+ // The private API doesn't return network-specific error codes or
+ // PP_ERROR_NOACCESS. In order to preserve the behavior, we convert those to
+ // PP_ERROR_FAILED.
+ if (private_api &&
+ (pp_error <= PP_ERROR_CONNECTION_CLOSED ||
+ pp_error == PP_ERROR_NOACCESS)) {
+ return PP_ERROR_FAILED;
+ }
+
+ return pp_error;
+}
+
+} // namespace
+
+const int32_t UDPSocketResourceBase::kMaxReadSize = 1024 * 1024;
+const int32_t UDPSocketResourceBase::kMaxWriteSize = 1024 * 1024;
+const int32_t UDPSocketResourceBase::kMaxSendBufferSize =
+ 1024 * UDPSocketResourceBase::kMaxWriteSize;
+const int32_t UDPSocketResourceBase::kMaxReceiveBufferSize =
+ 1024 * UDPSocketResourceBase::kMaxReadSize;
+
+
+UDPSocketResourceBase::UDPSocketResourceBase(Connection connection,
+ PP_Instance instance,
+ bool private_api)
+ : PluginResource(connection, instance),
+ private_api_(private_api),
+ bound_(false),
+ closed_(false),
+ read_buffer_(NULL),
+ bytes_to_read_(-1) {
+ recvfrom_addr_.size = 0;
+ memset(recvfrom_addr_.data, 0,
+ arraysize(recvfrom_addr_.data) * sizeof(*recvfrom_addr_.data));
+ bound_addr_.size = 0;
+ memset(bound_addr_.data, 0,
+ arraysize(bound_addr_.data) * sizeof(*bound_addr_.data));
+
+ if (private_api)
+ SendCreate(BROWSER, PpapiHostMsg_UDPSocket_CreatePrivate());
+ else
+ SendCreate(BROWSER, PpapiHostMsg_UDPSocket_Create());
+}
+
+UDPSocketResourceBase::~UDPSocketResourceBase() {
+}
+
+int32_t UDPSocketResourceBase::SetOptionImpl(
+ PP_UDPSocket_Option name,
+ const PP_Var& value,
+ scoped_refptr<TrackedCallback> callback) {
+ if (closed_)
+ return PP_ERROR_FAILED;
+
+ SocketOptionData option_data;
+ switch (name) {
+ case PP_UDPSOCKET_OPTION_ADDRESS_REUSE:
+ case PP_UDPSOCKET_OPTION_BROADCAST: {
+ if (bound_)
+ return PP_ERROR_FAILED;
+ if (value.type != PP_VARTYPE_BOOL)
+ return PP_ERROR_BADARGUMENT;
+ option_data.SetBool(PP_ToBool(value.value.as_bool));
+ break;
+ }
+ case PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE:
+ case PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE: {
+ if (!bound_)
+ return PP_ERROR_FAILED;
+ if (value.type != PP_VARTYPE_INT32)
+ return PP_ERROR_BADARGUMENT;
+ option_data.SetInt32(value.value.as_int);
+ break;
+ }
+ default: {
+ NOTREACHED();
+ return PP_ERROR_BADARGUMENT;
+ }
+ }
+
+ Call<PpapiPluginMsg_UDPSocket_SetOptionReply>(
+ BROWSER,
+ PpapiHostMsg_UDPSocket_SetOption(name, option_data),
+ base::Bind(&UDPSocketResourceBase::OnPluginMsgSetOptionReply,
+ base::Unretained(this),
+ callback));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t UDPSocketResourceBase::BindImpl(
+ const PP_NetAddress_Private* addr,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!addr)
+ return PP_ERROR_BADARGUMENT;
+ if (bound_ || closed_)
+ return PP_ERROR_FAILED;
+ if (TrackedCallback::IsPending(bind_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ bind_callback_ = callback;
+
+ // Send the request, the browser will call us back via BindReply.
+ Call<PpapiPluginMsg_UDPSocket_BindReply>(
+ BROWSER,
+ PpapiHostMsg_UDPSocket_Bind(*addr),
+ base::Bind(&UDPSocketResourceBase::OnPluginMsgBindReply,
+ base::Unretained(this)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+PP_Bool UDPSocketResourceBase::GetBoundAddressImpl(
+ PP_NetAddress_Private* addr) {
+ if (!addr || !bound_ || closed_)
+ return PP_FALSE;
+
+ *addr = bound_addr_;
+ return PP_TRUE;
+}
+
+int32_t UDPSocketResourceBase::RecvFromImpl(
+ char* buffer,
+ int32_t num_bytes,
+ PP_Resource* addr,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!buffer || num_bytes <= 0)
+ return PP_ERROR_BADARGUMENT;
+ if (!bound_)
+ return PP_ERROR_FAILED;
+ if (TrackedCallback::IsPending(recvfrom_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ read_buffer_ = buffer;
+ bytes_to_read_ = std::min(num_bytes, kMaxReadSize);
+ recvfrom_callback_ = callback;
+
+ // Send the request, the browser will call us back via RecvFromReply.
+ Call<PpapiPluginMsg_UDPSocket_RecvFromReply>(
+ BROWSER,
+ PpapiHostMsg_UDPSocket_RecvFrom(bytes_to_read_),
+ base::Bind(&UDPSocketResourceBase::OnPluginMsgRecvFromReply,
+ base::Unretained(this), addr));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+PP_Bool UDPSocketResourceBase::GetRecvFromAddressImpl(
+ PP_NetAddress_Private* addr) {
+ if (!addr)
+ return PP_FALSE;
+ *addr = recvfrom_addr_;
+ return PP_TRUE;
+}
+
+int32_t UDPSocketResourceBase::SendToImpl(
+ const char* buffer,
+ int32_t num_bytes,
+ const PP_NetAddress_Private* addr,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!buffer || num_bytes <= 0 || !addr)
+ return PP_ERROR_BADARGUMENT;
+ if (!bound_)
+ return PP_ERROR_FAILED;
+ if (TrackedCallback::IsPending(sendto_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ if (num_bytes > kMaxWriteSize)
+ num_bytes = kMaxWriteSize;
+
+ sendto_callback_ = callback;
+
+ // Send the request, the browser will call us back via SendToReply.
+ Call<PpapiPluginMsg_UDPSocket_SendToReply>(
+ BROWSER,
+ PpapiHostMsg_UDPSocket_SendTo(std::string(buffer, num_bytes), *addr),
+ base::Bind(&UDPSocketResourceBase::OnPluginMsgSendToReply,
+ base::Unretained(this)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void UDPSocketResourceBase::CloseImpl() {
+ if(closed_)
+ return;
+
+ bound_ = false;
+ closed_ = true;
+
+ Post(BROWSER, PpapiHostMsg_UDPSocket_Close());
+
+ PostAbortIfNecessary(&bind_callback_);
+ PostAbortIfNecessary(&recvfrom_callback_);
+ PostAbortIfNecessary(&sendto_callback_);
+
+ read_buffer_ = NULL;
+ bytes_to_read_ = -1;
+}
+
+void UDPSocketResourceBase::PostAbortIfNecessary(
+ scoped_refptr<TrackedCallback>* callback) {
+ if (TrackedCallback::IsPending(*callback))
+ (*callback)->PostAbort();
+}
+
+void UDPSocketResourceBase::OnPluginMsgSetOptionReply(
+ scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params) {
+ if (TrackedCallback::IsPending(callback))
+ callback->Run(ConvertPPError(params.result(), private_api_));
+}
+
+void UDPSocketResourceBase::OnPluginMsgBindReply(
+ const ResourceMessageReplyParams& params,
+ const PP_NetAddress_Private& bound_addr) {
+ // It is possible that |bind_callback_| is pending while |closed_| is true:
+ // CloseImpl() has been called, but a BindReply came earlier than the task to
+ // abort |bind_callback_|. We don't want to update |bound_| or |bound_addr_|
+ // in that case.
+ if (!TrackedCallback::IsPending(bind_callback_) || closed_)
+ return;
+
+ if (params.result() == PP_OK)
+ bound_ = true;
+ bound_addr_ = bound_addr;
+ bind_callback_->Run(ConvertPPError(params.result(), private_api_));
+}
+
+void UDPSocketResourceBase::OnPluginMsgRecvFromReply(
+ PP_Resource* output_addr,
+ const ResourceMessageReplyParams& params,
+ const std::string& data,
+ const PP_NetAddress_Private& addr) {
+ // It is possible that |recvfrom_callback_| is pending while |read_buffer_| is
+ // NULL: CloseImpl() has been called, but a RecvFromReply came earlier than
+ // the task to abort |recvfrom_callback_|. We shouldn't access the buffer in
+ // that case. The user may have released it.
+ if (!TrackedCallback::IsPending(recvfrom_callback_) || !read_buffer_)
+ return;
+
+ int32_t result = params.result();
+ if (result == PP_OK && output_addr) {
+ thunk::EnterResourceCreationNoLock enter(pp_instance());
+ if (enter.succeeded()) {
+ *output_addr = enter.functions()->CreateNetAddressFromNetAddressPrivate(
+ pp_instance(), addr);
+ } else {
+ result = PP_ERROR_FAILED;
+ }
+ }
+
+ if (result == PP_OK) {
+ 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;
+ recvfrom_addr_ = addr;
+
+ if (result == PP_OK)
+ recvfrom_callback_->Run(static_cast<int32_t>(data.size()));
+ else
+ recvfrom_callback_->Run(ConvertPPError(result, private_api_));
+}
+
+void UDPSocketResourceBase::OnPluginMsgSendToReply(
+ const ResourceMessageReplyParams& params,
+ int32_t bytes_written) {
+ if (!TrackedCallback::IsPending(sendto_callback_))
+ return;
+
+ if (params.result() == PP_OK)
+ sendto_callback_->Run(bytes_written);
+ else
+ sendto_callback_->Run(ConvertPPError(params.result(), private_api_));
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/udp_socket_resource_base.h b/chromium/ppapi/proxy/udp_socket_resource_base.h
new file mode 100644
index 00000000000..925475e0e1a
--- /dev/null
+++ b/chromium/ppapi/proxy/udp_socket_resource_base.h
@@ -0,0 +1,103 @@
+// Copyright 2013 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_UDP_SOCKET_RESOURCE_BASE_H_
+#define PPAPI_PROXY_UDP_SOCKET_RESOURCE_BASE_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "ppapi/c/ppb_udp_socket.h"
+#include "ppapi/c/private/ppb_net_address_private.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+
+namespace ppapi {
+namespace proxy {
+
+class ResourceMessageReplyParams;
+
+class PPAPI_PROXY_EXPORT UDPSocketResourceBase: public PluginResource {
+ public:
+ // The maximum number of bytes that each PpapiHostMsg_PPBUDPSocket_RecvFrom
+ // message is allowed to request.
+ static const int32_t kMaxReadSize;
+ // The maximum number of bytes that each PpapiHostMsg_PPBUDPSocket_SendTo
+ // message is allowed to carry.
+ static const int32_t kMaxWriteSize;
+
+ // The maximum number that we allow for setting
+ // PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE. This number is only for input
+ // argument sanity check, it doesn't mean the browser guarantees to support
+ // such a buffer size.
+ static const int32_t kMaxSendBufferSize;
+ // The maximum number that we allow for setting
+ // PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE. This number is only for input
+ // argument sanity check, it doesn't mean the browser guarantees to support
+ // such a buffer size.
+ static const int32_t kMaxReceiveBufferSize;
+
+ protected:
+ UDPSocketResourceBase(Connection connection,
+ PP_Instance instance,
+ bool private_api);
+ virtual ~UDPSocketResourceBase();
+
+ int32_t SetOptionImpl(PP_UDPSocket_Option name,
+ const PP_Var& value,
+ scoped_refptr<TrackedCallback> callback);
+ int32_t BindImpl(const PP_NetAddress_Private* addr,
+ scoped_refptr<TrackedCallback> callback);
+ PP_Bool GetBoundAddressImpl(PP_NetAddress_Private* addr);
+ // |addr| could be NULL to indicate that an output value is not needed.
+ int32_t RecvFromImpl(char* buffer,
+ int32_t num_bytes,
+ PP_Resource* addr,
+ scoped_refptr<TrackedCallback> callback);
+ PP_Bool GetRecvFromAddressImpl(PP_NetAddress_Private* addr);
+ int32_t SendToImpl(const char* buffer,
+ int32_t num_bytes,
+ const PP_NetAddress_Private* addr,
+ scoped_refptr<TrackedCallback> callback);
+ void CloseImpl();
+
+ private:
+ void PostAbortIfNecessary(scoped_refptr<TrackedCallback>* callback);
+
+ // IPC message handlers.
+ void OnPluginMsgSetOptionReply(scoped_refptr<TrackedCallback> callback,
+ const ResourceMessageReplyParams& params);
+ void OnPluginMsgBindReply(const ResourceMessageReplyParams& params,
+ const PP_NetAddress_Private& bound_addr);
+ void OnPluginMsgRecvFromReply(PP_Resource* output_addr,
+ const ResourceMessageReplyParams& params,
+ const std::string& data,
+ const PP_NetAddress_Private& addr);
+ void OnPluginMsgSendToReply(const ResourceMessageReplyParams& params,
+ int32_t bytes_written);
+
+ bool private_api_;
+ bool bound_;
+ bool closed_;
+
+ scoped_refptr<TrackedCallback> bind_callback_;
+ scoped_refptr<TrackedCallback> recvfrom_callback_;
+ scoped_refptr<TrackedCallback> sendto_callback_;
+
+ char* read_buffer_;
+ int32_t bytes_to_read_;
+
+ PP_NetAddress_Private recvfrom_addr_;
+ PP_NetAddress_Private bound_addr_;
+
+ DISALLOW_COPY_AND_ASSIGN(UDPSocketResourceBase);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_UDP_SOCKET_RESOURCE_BASE_H_
diff --git a/chromium/ppapi/proxy/url_loader_resource.cc b/chromium/ppapi/proxy/url_loader_resource.cc
new file mode 100644
index 00000000000..5bbc9372ff2
--- /dev/null
+++ b/chromium/ppapi/proxy/url_loader_resource.cc
@@ -0,0 +1,392 @@
+// Copyright (c) 2013 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/url_loader_resource.h"
+
+#include "base/logging.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_url_loader.h"
+#include "ppapi/proxy/dispatch_reply_message.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_file_ref_proxy.h"
+#include "ppapi/proxy/url_request_info_resource.h"
+#include "ppapi/proxy/url_response_info_resource.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/url_response_info_data.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/resource_creation_api.h"
+
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_URLLoader_API;
+using ppapi::thunk::PPB_URLRequestInfo_API;
+
+#ifdef _MSC_VER
+// Do not warn about use of std::copy with raw pointers.
+#pragma warning(disable : 4996)
+#endif
+
+namespace ppapi {
+namespace proxy {
+
+URLLoaderResource::URLLoaderResource(Connection connection,
+ PP_Instance instance)
+ : PluginResource(connection, instance),
+ mode_(MODE_WAITING_TO_OPEN),
+ status_callback_(NULL),
+ bytes_sent_(0),
+ total_bytes_to_be_sent_(-1),
+ bytes_received_(0),
+ total_bytes_to_be_received_(-1),
+ user_buffer_(NULL),
+ user_buffer_size_(0),
+ done_status_(PP_OK_COMPLETIONPENDING),
+ is_streaming_to_file_(false),
+ is_asynchronous_load_suspended_(false) {
+ SendCreate(RENDERER, PpapiHostMsg_URLLoader_Create());
+}
+
+URLLoaderResource::URLLoaderResource(Connection connection,
+ PP_Instance instance,
+ int pending_main_document_loader_id,
+ const ppapi::URLResponseInfoData& data)
+ : PluginResource(connection, instance),
+ mode_(MODE_OPENING),
+ status_callback_(NULL),
+ bytes_sent_(0),
+ total_bytes_to_be_sent_(-1),
+ bytes_received_(0),
+ total_bytes_to_be_received_(-1),
+ user_buffer_(NULL),
+ user_buffer_size_(0),
+ done_status_(PP_OK_COMPLETIONPENDING),
+ is_streaming_to_file_(false),
+ is_asynchronous_load_suspended_(false) {
+ AttachToPendingHost(RENDERER, pending_main_document_loader_id);
+ SaveResponseInfo(data);
+}
+
+URLLoaderResource::~URLLoaderResource() {
+}
+
+PPB_URLLoader_API* URLLoaderResource::AsPPB_URLLoader_API() {
+ return this;
+}
+
+int32_t URLLoaderResource::Open(PP_Resource request_id,
+ scoped_refptr<TrackedCallback> callback) {
+ EnterResourceNoLock<PPB_URLRequestInfo_API> enter_request(request_id, true);
+ if (enter_request.failed()) {
+ Log(PP_LOGLEVEL_ERROR,
+ "PPB_URLLoader.Open: invalid request resource ID. (Hint to C++ wrapper"
+ " users: use the ResourceRequest constructor that takes an instance or"
+ " else the request will be null.)");
+ return PP_ERROR_BADARGUMENT;
+ }
+ return Open(enter_request.object()->GetData(), 0, callback);
+}
+
+int32_t URLLoaderResource::Open(
+ const ::ppapi::URLRequestInfoData& request_data,
+ int requestor_pid,
+ scoped_refptr<TrackedCallback> callback) {
+ int32_t rv = ValidateCallback(callback);
+ if (rv != PP_OK)
+ return rv;
+ if (mode_ != MODE_WAITING_TO_OPEN)
+ return PP_ERROR_INPROGRESS;
+
+ request_data_ = request_data;
+
+ mode_ = MODE_OPENING;
+ is_asynchronous_load_suspended_ = false;
+
+ RegisterCallback(callback);
+ Post(RENDERER, PpapiHostMsg_URLLoader_Open(request_data));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t URLLoaderResource::FollowRedirect(
+ scoped_refptr<TrackedCallback> callback) {
+ int32_t rv = ValidateCallback(callback);
+ if (rv != PP_OK)
+ return rv;
+ if (mode_ != MODE_OPENING)
+ return PP_ERROR_INPROGRESS;
+
+ SetDefersLoading(false); // Allow the redirect to continue.
+ RegisterCallback(callback);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+PP_Bool URLLoaderResource::GetUploadProgress(int64_t* bytes_sent,
+ int64_t* total_bytes_to_be_sent) {
+ if (!request_data_.record_upload_progress) {
+ *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 URLLoaderResource::GetDownloadProgress(
+ int64_t* bytes_received,
+ int64_t* total_bytes_to_be_received) {
+ if (!request_data_.record_download_progress) {
+ *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 URLLoaderResource::GetResponseInfo() {
+ if (response_info_.get())
+ return response_info_->GetReference();
+ return 0;
+}
+
+int32_t URLLoaderResource::ReadResponseBody(
+ void* buffer,
+ int32_t bytes_to_read,
+ scoped_refptr<TrackedCallback> callback) {
+ int32_t rv = ValidateCallback(callback);
+ if (rv != PP_OK)
+ return rv;
+ if (!response_info_.get() ||
+ !response_info_->data().body_as_file_ref.resource.is_null())
+ return PP_ERROR_FAILED;
+ if (bytes_to_read <= 0 || !buffer)
+ return PP_ERROR_BADARGUMENT;
+
+ user_buffer_ = static_cast<char*>(buffer);
+ user_buffer_size_ = bytes_to_read;
+
+ if (!buffer_.empty())
+ return FillUserBuffer();
+
+ // We may have already reached EOF.
+ if (done_status_ != PP_OK_COMPLETIONPENDING) {
+ user_buffer_ = NULL;
+ user_buffer_size_ = 0;
+ return done_status_;
+ }
+
+ RegisterCallback(callback);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t URLLoaderResource::FinishStreamingToFile(
+ scoped_refptr<TrackedCallback> callback) {
+ int32_t rv = ValidateCallback(callback);
+ if (rv != PP_OK)
+ return rv;
+ if (!response_info_.get() ||
+ response_info_->data().body_as_file_ref.resource.is_null())
+ return PP_ERROR_FAILED;
+
+ // We may have already reached EOF.
+ if (done_status_ != PP_OK_COMPLETIONPENDING)
+ return done_status_;
+
+ is_streaming_to_file_ = true;
+ if (is_asynchronous_load_suspended_)
+ SetDefersLoading(false);
+
+ // Wait for didFinishLoading / didFail.
+ RegisterCallback(callback);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void URLLoaderResource::Close() {
+ mode_ = MODE_LOAD_COMPLETE;
+ done_status_ = PP_ERROR_ABORTED;
+
+ Post(RENDERER, PpapiHostMsg_URLLoader_Close());
+
+ // Abort the callbacks, the plugin doesn't want to be called back after this.
+ // TODO(brettw) this should fix bug 69457, mark it fixed. ============
+ if (TrackedCallback::IsPending(pending_callback_))
+ pending_callback_->PostAbort();
+}
+
+void URLLoaderResource::GrantUniversalAccess() {
+ Post(RENDERER, PpapiHostMsg_URLLoader_GrantUniversalAccess());
+}
+
+void URLLoaderResource::RegisterStatusCallback(
+ PP_URLLoaderTrusted_StatusCallback callback) {
+ status_callback_ = callback;
+}
+
+void URLLoaderResource::OnReplyReceived(
+ const ResourceMessageReplyParams& params,
+ const IPC::Message& msg) {
+ IPC_BEGIN_MESSAGE_MAP(URLLoaderResource, msg)
+ case PpapiPluginMsg_URLLoader_SendData::ID:
+ // Special message, manually dispatch since we don't want the automatic
+ // unpickling.
+ OnPluginMsgSendData(params, msg);
+ break;
+
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
+ PpapiPluginMsg_URLLoader_ReceivedResponse,
+ OnPluginMsgReceivedResponse)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
+ PpapiPluginMsg_URLLoader_FinishedLoading,
+ OnPluginMsgFinishedLoading)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
+ PpapiPluginMsg_URLLoader_UpdateProgress,
+ OnPluginMsgUpdateProgress)
+ IPC_END_MESSAGE_MAP()
+}
+
+void URLLoaderResource::OnPluginMsgReceivedResponse(
+ const ResourceMessageReplyParams& params,
+ const URLResponseInfoData& data) {
+ SaveResponseInfo(data);
+ RunCallback(PP_OK);
+}
+
+void URLLoaderResource::OnPluginMsgSendData(
+ const ResourceMessageReplyParams& params,
+ const IPC::Message& message) {
+ PickleIterator iter(message);
+ const char* data;
+ int data_length;
+ if (!iter.ReadData(&data, &data_length)) {
+ NOTREACHED() << "Expecting data";
+ return;
+ }
+
+ mode_ = MODE_STREAMING_DATA;
+ buffer_.insert(buffer_.end(), data, data + data_length);
+
+ // To avoid letting the network stack download an entire stream all at once,
+ // defer loading when we have enough buffer.
+ // Check for this before we run the callback, even though that could move
+ // data out of the buffer. Doing anything after the callback is unsafe.
+ DCHECK(request_data_.prefetch_buffer_lower_threshold <
+ request_data_.prefetch_buffer_upper_threshold);
+ if (!is_streaming_to_file_ &&
+ !is_asynchronous_load_suspended_ &&
+ (buffer_.size() >= static_cast<size_t>(
+ request_data_.prefetch_buffer_upper_threshold))) {
+ DVLOG(1) << "Suspending async load - buffer size: " << buffer_.size();
+ SetDefersLoading(true);
+ }
+
+ if (user_buffer_)
+ RunCallback(FillUserBuffer());
+ else
+ DCHECK(!TrackedCallback::IsPending(pending_callback_));
+}
+
+void URLLoaderResource::OnPluginMsgFinishedLoading(
+ const ResourceMessageReplyParams& params,
+ int32_t result) {
+ mode_ = MODE_LOAD_COMPLETE;
+ done_status_ = result;
+ user_buffer_ = NULL;
+ user_buffer_size_ = 0;
+
+ // If the client hasn't called any function that takes a callback since
+ // the initial call to Open, or called ReadResponseBody and got a
+ // synchronous return, then the callback will be NULL.
+ if (TrackedCallback::IsPending(pending_callback_))
+ RunCallback(done_status_);
+}
+
+void URLLoaderResource::OnPluginMsgUpdateProgress(
+ const ResourceMessageReplyParams& params,
+ int64_t bytes_sent,
+ int64_t total_bytes_to_be_sent,
+ int64_t bytes_received,
+ int64_t total_bytes_to_be_received) {
+ bytes_sent_ = bytes_sent;
+ total_bytes_to_be_sent_ = total_bytes_to_be_sent;
+ bytes_received_ = bytes_received;
+ total_bytes_to_be_received_ = total_bytes_to_be_received;
+
+ if (status_callback_)
+ status_callback_(pp_instance(), pp_resource(),
+ bytes_sent_, total_bytes_to_be_sent_,
+ bytes_received_, total_bytes_to_be_received_);
+}
+
+void URLLoaderResource::SetDefersLoading(bool defers_loading) {
+ Post(RENDERER, PpapiHostMsg_URLLoader_SetDeferLoading(defers_loading));
+}
+
+int32_t URLLoaderResource::ValidateCallback(
+ scoped_refptr<TrackedCallback> callback) {
+ DCHECK(callback.get());
+ if (TrackedCallback::IsPending(pending_callback_))
+ return PP_ERROR_INPROGRESS;
+ return PP_OK;
+}
+
+void URLLoaderResource::RegisterCallback(
+ scoped_refptr<TrackedCallback> callback) {
+ DCHECK(!TrackedCallback::IsPending(pending_callback_));
+ pending_callback_ = callback;
+}
+
+void URLLoaderResource::RunCallback(int32_t result) {
+ // This may be null when this is a main document loader.
+ if (!pending_callback_.get())
+ return;
+
+ // If |user_buffer_| was set as part of registering a callback, the paths
+ // which trigger that callack must have cleared it since the callback is now
+ // free to delete it.
+ DCHECK(!user_buffer_);
+
+ // As a second line of defense, clear the |user_buffer_| in case the
+ // callbacks get called in an unexpected order.
+ user_buffer_ = NULL;
+ user_buffer_size_ = 0;
+ pending_callback_->Run(result);
+}
+
+void URLLoaderResource::SaveResponseInfo(const URLResponseInfoData& data) {
+ // Create a proxy resource for the the file ref host resource if needed.
+ PP_Resource body_as_file_ref = 0;
+ if (!data.body_as_file_ref.resource.is_null()) {
+ thunk::EnterResourceCreationNoLock enter(pp_instance());
+ body_as_file_ref =
+ enter.functions()->CreateFileRef(data.body_as_file_ref);
+ }
+ response_info_ = new URLResponseInfoResource(
+ connection(), pp_instance(), data, body_as_file_ref);
+}
+
+size_t URLLoaderResource::FillUserBuffer() {
+ DCHECK(user_buffer_);
+ DCHECK(user_buffer_size_);
+
+ size_t bytes_to_copy = std::min(buffer_.size(), user_buffer_size_);
+ std::copy(buffer_.begin(), buffer_.begin() + bytes_to_copy, user_buffer_);
+ buffer_.erase(buffer_.begin(), buffer_.begin() + bytes_to_copy);
+
+ // If the buffer is getting too empty, resume asynchronous loading.
+ if (is_asynchronous_load_suspended_ &&
+ buffer_.size() <= static_cast<size_t>(
+ request_data_.prefetch_buffer_lower_threshold)) {
+ DVLOG(1) << "Resuming async load - buffer size: " << buffer_.size();
+ SetDefersLoading(false);
+ }
+
+ // Reset for next time.
+ user_buffer_ = NULL;
+ user_buffer_size_ = 0;
+ return bytes_to_copy;
+}
+
+} // namespace proxy
+} // namespace ppapi \ No newline at end of file
diff --git a/chromium/ppapi/proxy/url_loader_resource.h b/chromium/ppapi/proxy/url_loader_resource.h
new file mode 100644
index 00000000000..685ccfe1243
--- /dev/null
+++ b/chromium/ppapi/proxy/url_loader_resource.h
@@ -0,0 +1,146 @@
+// Copyright (c) 2013 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_URL_LOADER_RESOURCE_H_
+#define PPAPI_PROXY_URL_LOADER_RESOURCE_H_
+
+#include <deque>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ppapi/c/trusted/ppb_url_loader_trusted.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/url_request_info_data.h"
+#include "ppapi/thunk/ppb_url_loader_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class URLResponseInfoResource;
+
+class PPAPI_PROXY_EXPORT URLLoaderResource
+ : public PluginResource,
+ public NON_EXPORTED_BASE(thunk::PPB_URLLoader_API) {
+ public:
+ // Constructor for plugin-initiated loads.
+ URLLoaderResource(Connection connection,
+ PP_Instance instance);
+
+ // Constructor for renderer-initiated (document) loads. The loader ID is the
+ // pending host ID for the already-created host in the renderer, and the
+ // response data is the response for the already-opened connection.
+ URLLoaderResource(Connection connection,
+ PP_Instance instance,
+ int pending_main_document_loader_id,
+ const URLResponseInfoData& data);
+
+ virtual ~URLLoaderResource();
+
+ // Resource override.
+ thunk::PPB_URLLoader_API* AsPPB_URLLoader_API() OVERRIDE;
+
+ // PPB_URLLoader_API implementation.
+ virtual int32_t Open(PP_Resource request_id,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Open(const URLRequestInfoData& data,
+ int requestor_pid,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t FollowRedirect(
+ scoped_refptr<TrackedCallback> 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,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t FinishStreamingToFile(
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual void Close() OVERRIDE;
+ virtual void GrantUniversalAccess() OVERRIDE;
+ virtual void RegisterStatusCallback(
+ PP_URLLoaderTrusted_StatusCallback callback) OVERRIDE;
+
+ // PluginResource implementation.
+ virtual void OnReplyReceived(const ResourceMessageReplyParams& params,
+ const IPC::Message& msg) OVERRIDE;
+
+ private:
+ enum Mode {
+ // The plugin has not called Open() yet.
+ MODE_WAITING_TO_OPEN,
+
+ // The plugin is waiting for the Open() or FollowRedirect callback.
+ MODE_OPENING,
+
+ // We've started to receive data and may receive more.
+ MODE_STREAMING_DATA,
+
+ // All data has been streamed or there was an error.
+ MODE_LOAD_COMPLETE
+ };
+
+ // IPC message handlers.
+ void OnPluginMsgReceivedResponse(const ResourceMessageReplyParams& params,
+ const URLResponseInfoData& data);
+ void OnPluginMsgSendData(const ResourceMessageReplyParams& params,
+ const IPC::Message& message);
+ void OnPluginMsgFinishedLoading(const ResourceMessageReplyParams& params,
+ int32_t result);
+ void OnPluginMsgUpdateProgress(const ResourceMessageReplyParams& params,
+ int64_t bytes_sent,
+ int64_t total_bytes_to_be_sent,
+ int64_t bytes_received,
+ int64_t total_bytes_to_be_received);
+
+ // Sends the defers loading message to the renderer to block or unblock the
+ // load.
+ void SetDefersLoading(bool defers_loading);
+
+ int32_t ValidateCallback(scoped_refptr<TrackedCallback> callback);
+
+ // Sets up |callback| as the pending callback. This should only be called once
+ // it is certain that |PP_OK_COMPLETIONPENDING| will be returned.
+ void RegisterCallback(scoped_refptr<TrackedCallback> callback);
+
+ void RunCallback(int32_t result);
+
+ // Saves the given response info to response_info_, handling file refs if
+ // necessary. This does not issue any callbacks.
+ void SaveResponseInfo(const URLResponseInfoData& data);
+
+ size_t FillUserBuffer();
+
+ Mode mode_;
+ URLRequestInfoData request_data_;
+
+ scoped_refptr<TrackedCallback> pending_callback_;
+
+ PP_URLLoaderTrusted_StatusCallback status_callback_;
+
+ std::deque<char> buffer_;
+ int64_t bytes_sent_;
+ int64_t total_bytes_to_be_sent_;
+ int64_t bytes_received_;
+ int64_t total_bytes_to_be_received_;
+ char* user_buffer_;
+ size_t user_buffer_size_;
+ int32_t done_status_;
+ bool is_streaming_to_file_;
+ bool is_asynchronous_load_suspended_;
+
+ // The response info if we've received it.
+ scoped_refptr<URLResponseInfoResource> response_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(URLLoaderResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_URL_LOADER_RESOURCE_H_ \ No newline at end of file
diff --git a/chromium/ppapi/proxy/url_request_info_resource.cc b/chromium/ppapi/proxy/url_request_info_resource.cc
new file mode 100644
index 00000000000..19d02d726ce
--- /dev/null
+++ b/chromium/ppapi/proxy/url_request_info_resource.cc
@@ -0,0 +1,215 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/url_request_info_resource.h"
+
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_file_ref_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+URLRequestInfoResource::URLRequestInfoResource(Connection connection,
+ PP_Instance instance,
+ const URLRequestInfoData& data)
+ : PluginResource(connection, instance),
+ data_(data) {
+}
+
+URLRequestInfoResource::~URLRequestInfoResource() {
+}
+
+thunk::PPB_URLRequestInfo_API*
+URLRequestInfoResource::AsPPB_URLRequestInfo_API() {
+ return this;
+}
+
+PP_Bool URLRequestInfoResource::SetProperty(PP_URLRequestProperty property,
+ PP_Var var) {
+ // IMPORTANT: Do not do security validation of parameters at this level
+ // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. This
+ // code is used both in the plugin (which we don't trust) and in the renderer
+ // (which we trust more). When running out-of-process, the plugin calls this
+ // function to configure the URLRequestInfoData, which is then sent to
+ // the renderer and *not* run through SetProperty again.
+ //
+ // This means that anything in the PPB_URLRequestInfo_Data needs to be
+ // validated at the time the URL is requested (which is what ValidateData
+ // does). If your feature requires security checks, it should be in the
+ // implementation in the renderer when the WebKit request is actually
+ // constructed.
+ //
+ // It is legal to do some validation here if you want to report failure to
+ // the plugin as a convenience, as long as you also do it in the renderer
+ // later.
+ PP_Bool result = PP_FALSE;
+ switch (var.type) {
+ case PP_VARTYPE_UNDEFINED:
+ result = PP_FromBool(SetUndefinedProperty(property));
+ break;
+ case PP_VARTYPE_BOOL:
+ result = PP_FromBool(
+ SetBooleanProperty(property, PP_ToBool(var.value.as_bool)));
+ break;
+ case PP_VARTYPE_INT32:
+ result = PP_FromBool(
+ SetIntegerProperty(property, var.value.as_int));
+ break;
+ case PP_VARTYPE_STRING: {
+ StringVar* string = StringVar::FromPPVar(var);
+ if (string)
+ result = PP_FromBool(SetStringProperty(property, string->value()));
+ break;
+ }
+ default:
+ break;
+ }
+ return result;
+}
+
+PP_Bool URLRequestInfoResource::AppendDataToBody(const void* data,
+ uint32_t len) {
+ if (len > 0) {
+ data_.body.push_back(URLRequestInfoData::BodyItem(
+ std::string(static_cast<const char*>(data), len)));
+ }
+ return PP_TRUE;
+}
+
+PP_Bool URLRequestInfoResource::AppendFileToBody(
+ PP_Resource file_ref,
+ int64_t start_offset,
+ int64_t number_of_bytes,
+ PP_Time expected_last_modified_time) {
+ thunk::EnterResourceNoLock<thunk::PPB_FileRef_API> enter(file_ref, true);
+ if (enter.failed())
+ return PP_FALSE;
+
+ // Ignore a call to append nothing.
+ if (number_of_bytes == 0)
+ return PP_TRUE;
+
+ // Check for bad values. (-1 means read until end of file.)
+ if (start_offset < 0 || number_of_bytes < -1)
+ return PP_FALSE;
+
+ data_.body.push_back(URLRequestInfoData::BodyItem(
+ enter.resource(),
+ start_offset,
+ number_of_bytes,
+ expected_last_modified_time));
+ return PP_TRUE;
+}
+
+const URLRequestInfoData& URLRequestInfoResource::GetData() const {
+ return data_;
+}
+
+bool URLRequestInfoResource::SetUndefinedProperty(
+ PP_URLRequestProperty property) {
+ // IMPORTANT: Do not do security validation of parameters at this level
+ // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. See
+ // SetProperty() above for why.
+ switch (property) {
+ case PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL:
+ data_.has_custom_referrer_url = false;
+ data_.custom_referrer_url = std::string();
+ return true;
+ case PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING:
+ data_.has_custom_content_transfer_encoding = false;
+ data_.custom_content_transfer_encoding = std::string();
+ return true;
+ case PP_URLREQUESTPROPERTY_CUSTOMUSERAGENT:
+ data_.has_custom_user_agent = false;
+ data_.custom_user_agent = std::string();
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool URLRequestInfoResource::SetBooleanProperty(
+ PP_URLRequestProperty property,
+ bool value) {
+ // IMPORTANT: Do not do security validation of parameters at this level
+ // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. See
+ // SetProperty() above for why.
+ switch (property) {
+ case PP_URLREQUESTPROPERTY_STREAMTOFILE:
+ data_.stream_to_file = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_FOLLOWREDIRECTS:
+ data_.follow_redirects = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS:
+ data_.record_download_progress = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_RECORDUPLOADPROGRESS:
+ data_.record_upload_progress = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_ALLOWCROSSORIGINREQUESTS:
+ data_.allow_cross_origin_requests = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_ALLOWCREDENTIALS:
+ data_.allow_credentials = value;
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool URLRequestInfoResource::SetIntegerProperty(
+ PP_URLRequestProperty property,
+ int32_t value) {
+ // IMPORTANT: Do not do security validation of parameters at this level
+ // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. See
+ // SetProperty() above for why.
+ switch (property) {
+ case PP_URLREQUESTPROPERTY_PREFETCHBUFFERUPPERTHRESHOLD:
+ data_.prefetch_buffer_upper_threshold = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_PREFETCHBUFFERLOWERTHRESHOLD:
+ data_.prefetch_buffer_lower_threshold = value;
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool URLRequestInfoResource::SetStringProperty(
+ PP_URLRequestProperty property,
+ const std::string& value) {
+ // IMPORTANT: Do not do security validation of parameters at this level
+ // without also adding them to PPB_URLRequestInfo_Impl::ValidateData. See
+ // SetProperty() above for why.
+ switch (property) {
+ case PP_URLREQUESTPROPERTY_URL:
+ data_.url = value; // NOTE: This may be a relative URL.
+ return true;
+ case PP_URLREQUESTPROPERTY_METHOD:
+ data_.method = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_HEADERS:
+ data_.headers = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL:
+ data_.has_custom_referrer_url = true;
+ data_.custom_referrer_url = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING:
+ data_.has_custom_content_transfer_encoding = true;
+ data_.custom_content_transfer_encoding = value;
+ return true;
+ case PP_URLREQUESTPROPERTY_CUSTOMUSERAGENT:
+ data_.has_custom_user_agent = true;
+ data_.custom_user_agent = value;
+ return true;
+ default:
+ return false;
+ }
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/url_request_info_resource.h b/chromium/ppapi/proxy/url_request_info_resource.h
new file mode 100644
index 00000000000..e3906a6f4ed
--- /dev/null
+++ b/chromium/ppapi/proxy/url_request_info_resource.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_URL_REQUEST_INFO_RESOURCE_H_
+#define PPAPI_PROXY_URL_REQUEST_INFO_RESOURCE_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/url_request_info_data.h"
+#include "ppapi/thunk/ppb_url_request_info_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT URLRequestInfoResource
+ : public PluginResource,
+ public thunk::PPB_URLRequestInfo_API {
+ public:
+ URLRequestInfoResource(Connection connection, PP_Instance instance,
+ const URLRequestInfoData& data);
+ virtual ~URLRequestInfoResource();
+
+ // Resource overrides.
+ virtual thunk::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;
+ virtual const URLRequestInfoData& GetData() const OVERRIDE;
+
+ bool SetUndefinedProperty(PP_URLRequestProperty property);
+ bool SetBooleanProperty(PP_URLRequestProperty property, bool value);
+ bool SetIntegerProperty(PP_URLRequestProperty property, int32_t value);
+ bool SetStringProperty(PP_URLRequestProperty property,
+ const std::string& value);
+
+ private:
+ URLRequestInfoData data_;
+
+ DISALLOW_COPY_AND_ASSIGN(URLRequestInfoResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_URL_REQUEST_INFO_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/url_response_info_resource.cc b/chromium/ppapi/proxy/url_response_info_resource.cc
new file mode 100644
index 00000000000..85dae9a1aef
--- /dev/null
+++ b/chromium/ppapi/proxy/url_response_info_resource.cc
@@ -0,0 +1,73 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/url_response_info_resource.h"
+
+#include "ppapi/proxy/ppb_file_ref_proxy.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/resource_creation_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+bool IsRedirect(int32_t status) {
+ return status >= 300 && status <= 399;
+}
+
+} // namespace
+
+URLResponseInfoResource::URLResponseInfoResource(
+ Connection connection,
+ PP_Instance instance,
+ const URLResponseInfoData& data,
+ PP_Resource file_ref_resource)
+ : PluginResource(connection, instance),
+ data_(data),
+ body_as_file_ref_(ScopedPPResource::PassRef(), file_ref_resource) {
+}
+
+URLResponseInfoResource::~URLResponseInfoResource() {
+}
+
+thunk::PPB_URLResponseInfo_API*
+URLResponseInfoResource::AsPPB_URLResponseInfo_API() {
+ return this;
+}
+
+PP_Var URLResponseInfoResource::GetProperty(PP_URLResponseProperty property) {
+ switch (property) {
+ case PP_URLRESPONSEPROPERTY_URL:
+ return StringVar::StringToPPVar(data_.url);
+ case PP_URLRESPONSEPROPERTY_REDIRECTURL:
+ if (IsRedirect(data_.status_code))
+ return StringVar::StringToPPVar(data_.redirect_url);
+ break;
+ case PP_URLRESPONSEPROPERTY_REDIRECTMETHOD:
+ if (IsRedirect(data_.status_code))
+ return StringVar::StringToPPVar(data_.status_text);
+ break;
+ case PP_URLRESPONSEPROPERTY_STATUSCODE:
+ return PP_MakeInt32(data_.status_code);
+ case PP_URLRESPONSEPROPERTY_STATUSLINE:
+ return StringVar::StringToPPVar(data_.status_text);
+ case PP_URLRESPONSEPROPERTY_HEADERS:
+ return StringVar::StringToPPVar(data_.headers);
+ }
+ // The default is to return an undefined PP_Var.
+ return PP_MakeUndefined();
+}
+
+PP_Resource URLResponseInfoResource::GetBodyAsFileRef() {
+ if (!body_as_file_ref_.get())
+ return 0;
+ PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(
+ body_as_file_ref_.get());
+ return body_as_file_ref_.get();
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/url_response_info_resource.h b/chromium/ppapi/proxy/url_response_info_resource.h
new file mode 100644
index 00000000000..dfb1f8feb60
--- /dev/null
+++ b/chromium/ppapi/proxy/url_response_info_resource.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_URL_RESPONSE_INFO_RESOURCE_H_
+#define PPAPI_PROXY_URL_RESPONSE_INFO_RESOURCE_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/scoped_pp_resource.h"
+#include "ppapi/shared_impl/url_response_info_data.h"
+#include "ppapi/thunk/ppb_url_response_info_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT URLResponseInfoResource
+ : public PluginResource,
+ public NON_EXPORTED_BASE(thunk::PPB_URLResponseInfo_API) {
+ public:
+ // The file_ref_resource should be the body_as_file_ref host resource in the
+ // |data| converted to a resource valid in the current process (if we're
+ // downloading to a file; it will be 0 if we're not). A reference
+ // is passed from the caller and is taken over by this object.
+ URLResponseInfoResource(Connection connection,
+ PP_Instance instance,
+ const URLResponseInfoData& data,
+ PP_Resource file_ref_resource);
+ virtual ~URLResponseInfoResource();
+
+ // Resource 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;
+
+ const URLResponseInfoData& data() const { return data_; }
+
+ private:
+ URLResponseInfoData data_;
+
+ // Non-zero when the load is being streamed to a file.
+ ScopedPPResource body_as_file_ref_;
+
+ DISALLOW_COPY_AND_ASSIGN(URLResponseInfoResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_URL_RESPONSE_INFO_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/var_serialization_rules.h b/chromium/ppapi/proxy/var_serialization_rules.h
new file mode 100644
index 00000000000..399cff326ec
--- /dev/null
+++ b/chromium/ppapi/proxy/var_serialization_rules.h
@@ -0,0 +1,89 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_VAR_SERIALIZATION_RULES_H_
+#define PPAPI_PROXY_VAR_SERIALIZATION_RULES_H_
+
+#include "base/memory/ref_counted.h"
+#include "ppapi/c/pp_var.h"
+
+#include <string>
+
+namespace ppapi {
+namespace proxy {
+
+// 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 base::RefCounted<VarSerializationRules> {
+ public:
+ // 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 remote process. For object vars,
+ // the returned var will contain the id valid for the host process.
+ // Otherwise, the returned var is valid in the local process.
+ virtual PP_Var SendCallerOwned(const PP_Var& var) = 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, call the function, and then destroy the temporary string.
+ // These two functions handle that process.
+ //
+ // BeginReceiveCallerOwned takes a var from IPC and returns a new var
+ // representing the input in the local process.
+ //
+ // EndReceiveCallerOwned releases the reference count in the Var tracker for
+ // the object or string that was added to the tracker. (Note, if the recipient
+ // took a reference to the Var, it will remain in the tracker after
+ // EndReceiveCallerOwned).
+ virtual PP_Var BeginReceiveCallerOwned(const PP_Var& var) = 0;
+ virtual void EndReceiveCallerOwned(const PP_Var& var) = 0;
+
+ // Passing refs -------------------------------------------------------------
+ //
+ // A pass-ref transfer is when ownership of a reference is passed from
+ // one 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. The input var should be the result of calling
+ // SendPassRef in the remote process. The return value is the var valid in
+ // the host process for object vars. Otherwise, the return value is a var
+ // which is valid in the local process.
+ virtual PP_Var ReceivePassRef(const PP_Var& var) = 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
+ //
+ // For object vars, the return value from BeginSendPassRef will be the var
+ // valid for the host process. Otherwise, it is a var that is valid in the
+ // local process. This same var must be passed to EndSendPassRef.
+ virtual PP_Var BeginSendPassRef(const PP_Var& var) = 0;
+ virtual void EndSendPassRef(const PP_Var& var) = 0;
+
+ // ---------------------------------------------------------------------------
+
+ virtual void ReleaseObjectRef(const PP_Var& var) = 0;
+
+ protected:
+ VarSerializationRules() {}
+ virtual ~VarSerializationRules() {}
+
+ private:
+ friend class base::RefCounted<VarSerializationRules>;
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_VAR_SERIALIZATION_RULES_H_
diff --git a/chromium/ppapi/proxy/video_capture_resource.cc b/chromium/ppapi/proxy/video_capture_resource.cc
new file mode 100644
index 00000000000..6ea8bd50015
--- /dev/null
+++ b/chromium/ppapi/proxy/video_capture_resource.cc
@@ -0,0 +1,240 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/video_capture_resource.h"
+
+#include "ppapi/c/dev/ppp_video_capture_dev.h"
+#include "ppapi/proxy/dispatch_reply_message.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_buffer_proxy.h"
+#include "ppapi/proxy/resource_message_params.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+
+namespace ppapi {
+namespace proxy {
+
+VideoCaptureResource::VideoCaptureResource(
+ Connection connection,
+ PP_Instance instance,
+ PluginDispatcher* dispatcher)
+ : PluginResource(connection, instance),
+ open_state_(BEFORE_OPEN),
+ enumeration_helper_(this) {
+ SendCreate(RENDERER, PpapiHostMsg_VideoCapture_Create());
+
+ ppp_video_capture_impl_ = static_cast<const PPP_VideoCapture_Dev*>(
+ dispatcher->local_get_interface()(PPP_VIDEO_CAPTURE_DEV_INTERFACE));
+}
+
+VideoCaptureResource::~VideoCaptureResource() {
+}
+
+void VideoCaptureResource::OnReplyReceived(
+ const ResourceMessageReplyParams& params,
+ const IPC::Message& msg) {
+ if (enumeration_helper_.HandleReply(params, msg))
+ return;
+
+ if (params.sequence()) {
+ PluginResource::OnReplyReceived(params, msg);
+ return;
+ }
+
+ IPC_BEGIN_MESSAGE_MAP(VideoCaptureResource, msg)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
+ PpapiPluginMsg_VideoCapture_OnDeviceInfo,
+ OnPluginMsgOnDeviceInfo)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
+ PpapiPluginMsg_VideoCapture_OnStatus,
+ OnPluginMsgOnStatus)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
+ PpapiPluginMsg_VideoCapture_OnError,
+ OnPluginMsgOnError)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
+ PpapiPluginMsg_VideoCapture_OnBufferReady,
+ OnPluginMsgOnBufferReady)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(NOTREACHED())
+ IPC_END_MESSAGE_MAP()
+}
+
+int32_t VideoCaptureResource::EnumerateDevices0_2(
+ PP_Resource* devices,
+ scoped_refptr<TrackedCallback> callback) {
+ return enumeration_helper_.EnumerateDevices0_2(devices, callback);
+}
+
+int32_t VideoCaptureResource::EnumerateDevices(
+ const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback) {
+ return enumeration_helper_.EnumerateDevices(output, callback);
+}
+
+int32_t VideoCaptureResource::MonitorDeviceChange(
+ PP_MonitorDeviceChangeCallback callback,
+ void* user_data) {
+ return enumeration_helper_.MonitorDeviceChange(callback, user_data);
+}
+
+int32_t VideoCaptureResource::Open(
+ const std::string& device_id,
+ const PP_VideoCaptureDeviceInfo_Dev& requested_info,
+ uint32_t buffer_count,
+ scoped_refptr<TrackedCallback> callback) {
+ if (open_state_ != BEFORE_OPEN)
+ return PP_ERROR_FAILED;
+
+ if (TrackedCallback::IsPending(open_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ open_callback_ = callback;
+
+ Call<PpapiPluginMsg_VideoCapture_OpenReply>(
+ RENDERER,
+ PpapiHostMsg_VideoCapture_Open(device_id, requested_info, buffer_count),
+ base::Bind(&VideoCaptureResource::OnPluginMsgOpenReply, this));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t VideoCaptureResource::StartCapture() {
+ if (open_state_ != OPENED)
+ return PP_ERROR_FAILED;
+
+ Post(RENDERER, PpapiHostMsg_VideoCapture_StartCapture());
+ return PP_OK;
+}
+
+int32_t VideoCaptureResource::ReuseBuffer(uint32_t buffer) {
+ if (buffer >= buffer_in_use_.size() || !buffer_in_use_[buffer])
+ return PP_ERROR_BADARGUMENT;
+ Post(RENDERER, PpapiHostMsg_VideoCapture_ReuseBuffer(buffer));
+ return PP_OK;
+}
+
+int32_t VideoCaptureResource::StopCapture() {
+ if (open_state_ != OPENED)
+ return PP_ERROR_FAILED;
+
+ Post(RENDERER, PpapiHostMsg_VideoCapture_StopCapture());
+ return PP_OK;
+}
+
+void VideoCaptureResource::Close() {
+ if (open_state_ == CLOSED)
+ return;
+
+ Post(RENDERER, PpapiHostMsg_VideoCapture_Close());
+
+ open_state_ = CLOSED;
+
+ if (TrackedCallback::IsPending(open_callback_))
+ open_callback_->PostAbort();
+}
+
+int32_t VideoCaptureResource::EnumerateDevicesSync(
+ const PP_ArrayOutput& devices) {
+ return enumeration_helper_.EnumerateDevicesSync(devices);
+}
+
+void VideoCaptureResource::LastPluginRefWasDeleted() {
+ enumeration_helper_.LastPluginRefWasDeleted();
+}
+
+void VideoCaptureResource::OnPluginMsgOnDeviceInfo(
+ const ResourceMessageReplyParams& params,
+ const struct PP_VideoCaptureDeviceInfo_Dev& info,
+ const std::vector<HostResource>& buffers,
+ uint32_t buffer_size) {
+ if (!ppp_video_capture_impl_)
+ return;
+
+ std::vector<base::SharedMemoryHandle> handles;
+ params.TakeAllSharedMemoryHandles(&handles);
+ CHECK(handles.size() == buffers.size());
+
+ PluginResourceTracker* tracker =
+ PluginGlobals::Get()->plugin_resource_tracker();
+ scoped_ptr<PP_Resource[]> resources(new PP_Resource[buffers.size()]);
+ for (size_t i = 0; i < buffers.size(); ++i) {
+ // We assume that the browser created a new set of resources.
+ DCHECK(!tracker->PluginResourceForHostResource(buffers[i]));
+ resources[i] = ppapi::proxy::PPB_Buffer_Proxy::AddProxyResource(
+ buffers[i], handles[i], buffer_size);
+ }
+
+ buffer_in_use_ = std::vector<bool>(buffers.size());
+
+ CallWhileUnlocked(ppp_video_capture_impl_->OnDeviceInfo,
+ pp_instance(),
+ pp_resource(),
+ &info,
+ static_cast<uint32_t>(buffers.size()),
+ const_cast<const PP_Resource*>(resources.get()));
+
+ for (size_t i = 0; i < buffers.size(); ++i)
+ tracker->ReleaseResource(resources[i]);
+}
+
+void VideoCaptureResource::OnPluginMsgOnStatus(
+ const ResourceMessageReplyParams& params,
+ uint32_t status) {
+ switch (status) {
+ case PP_VIDEO_CAPTURE_STATUS_STARTING:
+ case PP_VIDEO_CAPTURE_STATUS_STOPPING:
+ // Those states are not sent by the browser.
+ NOTREACHED();
+ break;
+ }
+ if (ppp_video_capture_impl_) {
+ CallWhileUnlocked(ppp_video_capture_impl_->OnStatus,
+ pp_instance(),
+ pp_resource(),
+ status);
+ }
+}
+
+void VideoCaptureResource::OnPluginMsgOnError(
+ const ResourceMessageReplyParams& params,
+ uint32_t error_code) {
+ open_state_ = CLOSED;
+ if (ppp_video_capture_impl_) {
+ CallWhileUnlocked(ppp_video_capture_impl_->OnError,
+ pp_instance(),
+ pp_resource(),
+ error_code);
+ }
+}
+
+void VideoCaptureResource::OnPluginMsgOnBufferReady(
+ const ResourceMessageReplyParams& params,
+ uint32_t buffer) {
+ SetBufferInUse(buffer);
+ if (ppp_video_capture_impl_) {
+ CallWhileUnlocked(ppp_video_capture_impl_->OnBufferReady,
+ pp_instance(),
+ pp_resource(),
+ buffer);
+ }
+}
+
+void VideoCaptureResource::OnPluginMsgOpenReply(
+ const ResourceMessageReplyParams& params) {
+ if (open_state_ == BEFORE_OPEN && params.result() == PP_OK)
+ open_state_ = OPENED;
+
+ // The callback may have been aborted by Close().
+ if (TrackedCallback::IsPending(open_callback_))
+ open_callback_->Run(params.result());
+}
+
+void VideoCaptureResource::SetBufferInUse(uint32_t buffer_index) {
+ CHECK(buffer_index < buffer_in_use_.size());
+ buffer_in_use_[buffer_index] = true;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/video_capture_resource.h b/chromium/ppapi/proxy/video_capture_resource.h
new file mode 100644
index 00000000000..e533ef095fb
--- /dev/null
+++ b/chromium/ppapi/proxy/video_capture_resource.h
@@ -0,0 +1,99 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_VIDEO_CAPTURE_RESOURCE_H_
+#define PPAPI_PROXY_VIDEO_CAPTURE_RESOURCE_H_
+
+#include "base/compiler_specific.h"
+#include "ppapi/c/dev/ppp_video_capture_dev.h"
+#include "ppapi/proxy/device_enumeration_resource_helper.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/thunk/ppb_video_capture_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class VideoCaptureResource
+ : public PluginResource,
+ public ::ppapi::thunk::PPB_VideoCapture_API {
+ public:
+ VideoCaptureResource(Connection connection,
+ PP_Instance instance,
+ PluginDispatcher* dispatcher);
+ virtual ~VideoCaptureResource();
+
+ // PluginResource override.
+ virtual thunk::PPB_VideoCapture_API* AsPPB_VideoCapture_API() OVERRIDE {
+ return this;
+ }
+
+ // PPB_VideoCapture_API implementation.
+ virtual int32_t EnumerateDevices0_2(
+ PP_Resource* devices,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t EnumerateDevices(
+ const PP_ArrayOutput& output,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t MonitorDeviceChange(
+ PP_MonitorDeviceChangeCallback callback,
+ void* user_data) OVERRIDE;
+ virtual int32_t Open(const std::string& device_id,
+ const PP_VideoCaptureDeviceInfo_Dev& requested_info,
+ uint32_t buffer_count,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t StartCapture() OVERRIDE;
+ virtual int32_t ReuseBuffer(uint32_t buffer) OVERRIDE;
+ virtual int32_t StopCapture() OVERRIDE;
+ virtual void Close() OVERRIDE;
+ virtual int32_t EnumerateDevicesSync(const PP_ArrayOutput& devices) OVERRIDE;
+
+ protected:
+ // Resource override.
+ virtual void LastPluginRefWasDeleted() OVERRIDE;
+
+ private:
+ enum OpenState {
+ BEFORE_OPEN,
+ OPENED,
+ CLOSED
+ };
+
+ // PluginResource overrides.
+ virtual void OnReplyReceived(const ResourceMessageReplyParams& params,
+ const IPC::Message& msg) OVERRIDE;
+
+ void OnPluginMsgOnDeviceInfo(const ResourceMessageReplyParams& params,
+ const struct PP_VideoCaptureDeviceInfo_Dev& info,
+ const std::vector<HostResource>& buffers,
+ uint32_t buffer_size);
+ void OnPluginMsgOnStatus(const ResourceMessageReplyParams& params,
+ uint32_t status);
+ void OnPluginMsgOnError(const ResourceMessageReplyParams& params,
+ uint32_t error);
+ void OnPluginMsgOnBufferReady(const ResourceMessageReplyParams& params,
+ uint32_t buffer);
+
+ void OnPluginMsgOpenReply(const ResourceMessageReplyParams& params);
+
+ void SetBufferInUse(uint32_t buffer_index);
+
+ // Points to the C interface of client implementation.
+ const PPP_VideoCapture_Dev* ppp_video_capture_impl_;
+
+ // Indicates that the i-th buffer is currently in use.
+ std::vector<bool> buffer_in_use_;
+
+ // Holds a reference of the callback so that Close() can cancel it.
+ scoped_refptr<TrackedCallback> open_callback_;
+ OpenState open_state_;
+
+ DeviceEnumerationResourceHelper enumeration_helper_;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoCaptureResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_VIDEO_CAPTURE_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/video_destination_resource.cc b/chromium/ppapi/proxy/video_destination_resource.cc
new file mode 100644
index 00000000000..5175705160e
--- /dev/null
+++ b/chromium/ppapi/proxy/video_destination_resource.cc
@@ -0,0 +1,102 @@
+// Copyright (c) 2013 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/video_destination_resource.h"
+
+#include "base/bind.h"
+#include "ipc/ipc_message.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/private/pp_video_frame_private.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/resource_tracker.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_image_data_api.h"
+
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_VideoDestination_Private_API;
+
+namespace ppapi {
+namespace proxy {
+
+VideoDestinationResource::VideoDestinationResource(
+ Connection connection,
+ PP_Instance instance)
+ : PluginResource(connection, instance),
+ is_open_(false) {
+ SendCreate(RENDERER, PpapiHostMsg_VideoDestination_Create());
+}
+
+VideoDestinationResource::~VideoDestinationResource() {
+}
+
+PPB_VideoDestination_Private_API*
+ VideoDestinationResource::AsPPB_VideoDestination_Private_API() {
+ return this;
+}
+
+int32_t VideoDestinationResource::Open(
+ const PP_Var& stream_url,
+ scoped_refptr<TrackedCallback> callback) {
+ if (TrackedCallback::IsPending(open_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ open_callback_ = callback;
+
+ scoped_refptr<StringVar> stream_url_var = StringVar::FromPPVar(stream_url);
+ const uint32_t kMaxStreamIdSizeInBytes = 16384;
+ if (!stream_url_var.get() ||
+ stream_url_var->value().size() > kMaxStreamIdSizeInBytes)
+ return PP_ERROR_BADARGUMENT;
+ Call<PpapiPluginMsg_VideoDestination_OpenReply>(RENDERER,
+ PpapiHostMsg_VideoDestination_Open(stream_url_var->value()),
+ base::Bind(&VideoDestinationResource::OnPluginMsgOpenComplete, this));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t VideoDestinationResource::PutFrame(
+ const PP_VideoFrame_Private& frame) {
+ if (!is_open_)
+ return PP_ERROR_FAILED;
+
+ thunk::EnterResourceNoLock<thunk::PPB_ImageData_API> enter_image(
+ frame.image_data, true);
+ if (enter_image.failed())
+ return PP_ERROR_BADRESOURCE;
+
+ // Check that the PP_Instance matches.
+ Resource* image_object =
+ PpapiGlobals::Get()->GetResourceTracker()->GetResource(frame.image_data);
+ if (!image_object || pp_instance() != image_object->pp_instance()) {
+ Log(PP_LOGLEVEL_ERROR,
+ "VideoDestinationPrivateResource.PutFrame: Bad image resource.");
+ return PP_ERROR_BADRESOURCE;
+ }
+
+ Post(RENDERER,
+ PpapiHostMsg_VideoDestination_PutFrame(image_object->host_resource(),
+ frame.timestamp));
+ return PP_OK;
+}
+
+void VideoDestinationResource::Close() {
+ Post(RENDERER, PpapiHostMsg_VideoDestination_Close());
+
+ if (TrackedCallback::IsPending(open_callback_))
+ open_callback_->PostAbort();
+}
+
+void VideoDestinationResource::OnPluginMsgOpenComplete(
+ const ResourceMessageReplyParams& params) {
+ if (TrackedCallback::IsPending(open_callback_)) {
+ int32_t result = params.result();
+ if (result == PP_OK)
+ is_open_ = true;
+ open_callback_->Run(result);
+ }
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/video_destination_resource.h b/chromium/ppapi/proxy/video_destination_resource.h
new file mode 100644
index 00000000000..91c0d1da0c2
--- /dev/null
+++ b/chromium/ppapi/proxy/video_destination_resource.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2013 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_VIDEO_DESTINATION_RESOURCE_H_
+#define PPAPI_PROXY_VIDEO_DESTINATION_RESOURCE_H_
+
+#include <string>
+
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/thunk/ppb_video_destination_private_api.h"
+
+struct PP_VideoFrame_Private;
+
+namespace ppapi {
+
+class TrackedCallback;
+
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT VideoDestinationResource
+ : public PluginResource,
+ public thunk::PPB_VideoDestination_Private_API {
+ public:
+ VideoDestinationResource(Connection connection,
+ PP_Instance instance);
+ virtual ~VideoDestinationResource();
+
+ // Resource overrides.
+ virtual thunk::PPB_VideoDestination_Private_API*
+ AsPPB_VideoDestination_Private_API() OVERRIDE;
+
+ // PPB_VideoDestination_Private_API implementation.
+ virtual int32_t Open(
+ const PP_Var& stream_url,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t PutFrame(const PP_VideoFrame_Private& frame) OVERRIDE;
+ virtual void Close() OVERRIDE;
+
+ private:
+ void OnPluginMsgOpenComplete(
+ const ResourceMessageReplyParams& params);
+
+ scoped_refptr<TrackedCallback> open_callback_;
+ bool is_open_;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoDestinationResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_VIDEO_DESTINATION_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/video_source_resource.cc b/chromium/ppapi/proxy/video_source_resource.cc
new file mode 100644
index 00000000000..c2949031883
--- /dev/null
+++ b/chromium/ppapi/proxy/video_source_resource.cc
@@ -0,0 +1,120 @@
+// Copyright (c) 2013 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/video_source_resource.h"
+
+#include "base/bind.h"
+#include "ipc/ipc_message.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/private/pp_video_frame_private.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_image_data_proxy.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/resource_tracker.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/enter.h"
+
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_VideoSource_Private_API;
+
+namespace ppapi {
+namespace proxy {
+
+VideoSourceResource::VideoSourceResource(
+ Connection connection,
+ PP_Instance instance)
+ : PluginResource(connection, instance),
+ is_open_(false) {
+ SendCreate(RENDERER, PpapiHostMsg_VideoSource_Create());
+}
+
+VideoSourceResource::~VideoSourceResource() {
+}
+
+PPB_VideoSource_Private_API*
+ VideoSourceResource::AsPPB_VideoSource_Private_API() {
+ return this;
+}
+
+int32_t VideoSourceResource::Open(
+ const PP_Var& stream_url,
+ scoped_refptr<TrackedCallback> callback) {
+ if (TrackedCallback::IsPending(open_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ open_callback_ = callback;
+
+ scoped_refptr<StringVar> stream_url_var = StringVar::FromPPVar(stream_url);
+ const uint32_t kMaxStreamIdSizeInBytes = 16384;
+ if (!stream_url_var.get() ||
+ stream_url_var->value().size() > kMaxStreamIdSizeInBytes)
+ return PP_ERROR_BADARGUMENT;
+ Call<PpapiPluginMsg_VideoSource_OpenReply>(RENDERER,
+ PpapiHostMsg_VideoSource_Open(stream_url_var->value()),
+ base::Bind(&VideoSourceResource::OnPluginMsgOpenComplete, this));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t VideoSourceResource::GetFrame(
+ PP_VideoFrame_Private* frame,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!is_open_)
+ return PP_ERROR_FAILED;
+
+ if (TrackedCallback::IsPending(get_frame_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ get_frame_callback_ = callback;
+ Call<PpapiPluginMsg_VideoSource_GetFrameReply>(RENDERER,
+ PpapiHostMsg_VideoSource_GetFrame(),
+ base::Bind(&VideoSourceResource::OnPluginMsgGetFrameComplete, this,
+ frame));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void VideoSourceResource::Close() {
+ Post(RENDERER, PpapiHostMsg_VideoSource_Close());
+
+ if (TrackedCallback::IsPending(open_callback_))
+ open_callback_->PostAbort();
+ if (TrackedCallback::IsPending(get_frame_callback_))
+ get_frame_callback_->PostAbort();
+}
+
+void VideoSourceResource::OnPluginMsgOpenComplete(
+ const ResourceMessageReplyParams& reply_params) {
+ if (TrackedCallback::IsPending(open_callback_)) {
+ int32_t result = reply_params.result();
+ if (result == PP_OK)
+ is_open_ = true;
+ open_callback_->Run(result);
+ }
+}
+
+void VideoSourceResource::OnPluginMsgGetFrameComplete(
+ PP_VideoFrame_Private* frame,
+ const ResourceMessageReplyParams& reply_params,
+ const HostResource& image_data,
+ const PP_ImageDataDesc& image_desc,
+ PP_TimeTicks timestamp) {
+ // The callback may have been aborted by Close().
+ if (TrackedCallback::IsPending(get_frame_callback_)) {
+ int32_t result = reply_params.result();
+ if (result == PP_OK &&
+ PPB_ImageData_Shared::IsImageDataDescValid(image_desc)) {
+ frame->timestamp = timestamp;
+
+ base::SharedMemoryHandle handle;
+ if (!reply_params.TakeSharedMemoryHandleAtIndex(0, &handle))
+ frame->image_data = 0;
+ frame->image_data =
+ (new SimpleImageData(
+ image_data, image_desc, handle))->GetReference();
+ }
+ get_frame_callback_->Run(result);
+ }
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/video_source_resource.h b/chromium/ppapi/proxy/video_source_resource.h
new file mode 100644
index 00000000000..cdd4638a215
--- /dev/null
+++ b/chromium/ppapi/proxy/video_source_resource.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2013 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_VIDEO_SOURCE_RESOURCE_H_
+#define PPAPI_PROXY_VIDEO_SOURCE_RESOURCE_H_
+
+#include <string>
+
+#include "ppapi/c/pp_time.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/thunk/ppb_video_source_private_api.h"
+
+struct PP_ImageDataDesc;
+struct PP_VideoFrame_Private;
+
+namespace ppapi {
+
+class TrackedCallback;
+
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT VideoSourceResource
+ : public PluginResource,
+ public thunk::PPB_VideoSource_Private_API {
+ public:
+ VideoSourceResource(Connection connection,
+ PP_Instance instance);
+ virtual ~VideoSourceResource();
+
+ // Resource overrides.
+ virtual thunk::PPB_VideoSource_Private_API*
+ AsPPB_VideoSource_Private_API() OVERRIDE;
+
+ // PPB_VideoSource_Private_API implementation.
+ virtual int32_t Open(
+ const PP_Var& stream_url,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t GetFrame(
+ PP_VideoFrame_Private* frame,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual void Close() OVERRIDE;
+
+ private:
+ void OnPluginMsgOpenComplete(
+ const ResourceMessageReplyParams& reply_params);
+ void OnPluginMsgGetFrameComplete(
+ PP_VideoFrame_Private* frame,
+ const ResourceMessageReplyParams& reply_params,
+ const HostResource& image_data,
+ const PP_ImageDataDesc& image_desc_data,
+ PP_TimeTicks timestamp);
+
+ scoped_refptr<TrackedCallback> open_callback_;
+ scoped_refptr<TrackedCallback> get_frame_callback_;
+ bool is_open_;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoSourceResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_VIDEO_SOURCE_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/websocket_resource.cc b/chromium/ppapi/proxy/websocket_resource.cc
new file mode 100644
index 00000000000..394a2c54f9e
--- /dev/null
+++ b/chromium/ppapi/proxy/websocket_resource.cc
@@ -0,0 +1,494 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/websocket_resource.h"
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/dispatch_reply_message.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/shared_impl/var_tracker.h"
+#include "third_party/WebKit/public/web/WebSocket.h"
+
+namespace {
+
+const uint32_t kMaxReasonSizeInBytes = 123;
+const size_t kBaseFramingOverhead = 2;
+const size_t kMaskingKeyLength = 4;
+const size_t kMinimumPayloadSizeWithTwoByteExtendedPayloadLength = 126;
+const size_t kMinimumPayloadSizeWithEightByteExtendedPayloadLength = 0x10000;
+
+uint64_t SaturateAdd(uint64_t a, uint64_t b) {
+ if (kuint64max - a < b)
+ return kuint64max;
+ return a + b;
+}
+
+uint64_t GetFrameSize(uint64_t payload_size) {
+ uint64_t overhead = kBaseFramingOverhead + kMaskingKeyLength;
+ if (payload_size > kMinimumPayloadSizeWithEightByteExtendedPayloadLength)
+ overhead += 8;
+ else if (payload_size > kMinimumPayloadSizeWithTwoByteExtendedPayloadLength)
+ overhead += 2;
+ return SaturateAdd(payload_size, overhead);
+}
+
+bool InValidStateToReceive(PP_WebSocketReadyState state) {
+ return state == PP_WEBSOCKETREADYSTATE_OPEN ||
+ state == PP_WEBSOCKETREADYSTATE_CLOSING;
+}
+
+} // namespace
+
+
+namespace ppapi {
+namespace proxy {
+
+WebSocketResource::WebSocketResource(Connection connection,
+ PP_Instance instance)
+ : PluginResource(connection, instance),
+ state_(PP_WEBSOCKETREADYSTATE_INVALID),
+ error_was_received_(false),
+ receive_callback_var_(NULL),
+ empty_string_(new StringVar(std::string())),
+ close_code_(0),
+ close_reason_(NULL),
+ close_was_clean_(PP_FALSE),
+ extensions_(NULL),
+ protocol_(NULL),
+ url_(NULL),
+ buffered_amount_(0),
+ buffered_amount_after_close_(0) {
+}
+
+WebSocketResource::~WebSocketResource() {
+}
+
+thunk::PPB_WebSocket_API* WebSocketResource::AsPPB_WebSocket_API() {
+ return this;
+}
+
+int32_t WebSocketResource::Connect(
+ const PP_Var& url,
+ const PP_Var protocols[],
+ uint32_t protocol_count,
+ scoped_refptr<TrackedCallback> callback) {
+ if (TrackedCallback::IsPending(connect_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ // Connect() can be called at most once.
+ if (state_ != PP_WEBSOCKETREADYSTATE_INVALID)
+ return PP_ERROR_INPROGRESS;
+ state_ = PP_WEBSOCKETREADYSTATE_CLOSED;
+
+ // Get the URL.
+ url_ = StringVar::FromPPVar(url);
+ if (!url_.get())
+ return PP_ERROR_BADARGUMENT;
+
+ // Get the protocols.
+ std::set<std::string> protocol_set;
+ std::vector<std::string> protocol_strings;
+ protocol_strings.reserve(protocol_count);
+ for (uint32_t i = 0; i < protocol_count; ++i) {
+ scoped_refptr<StringVar> protocol(StringVar::FromPPVar(protocols[i]));
+
+ // Check invalid and empty entries.
+ if (!protocol.get() || !protocol->value().length())
+ return PP_ERROR_BADARGUMENT;
+
+ // Check duplicated protocol entries.
+ if (protocol_set.find(protocol->value()) != protocol_set.end())
+ return PP_ERROR_BADARGUMENT;
+ protocol_set.insert(protocol->value());
+
+ protocol_strings.push_back(protocol->value());
+ }
+
+ // Install callback.
+ connect_callback_ = callback;
+
+ // Create remote host in the renderer, then request to check the URL and
+ // establish the connection.
+ state_ = PP_WEBSOCKETREADYSTATE_CONNECTING;
+ SendCreate(RENDERER, PpapiHostMsg_WebSocket_Create());
+ PpapiHostMsg_WebSocket_Connect msg(url_->value(), protocol_strings);
+ Call<PpapiPluginMsg_WebSocket_ConnectReply>(RENDERER, msg,
+ base::Bind(&WebSocketResource::OnPluginMsgConnectReply, this));
+
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t WebSocketResource::Close(uint16_t code,
+ const PP_Var& reason,
+ scoped_refptr<TrackedCallback> callback) {
+ if (TrackedCallback::IsPending(close_callback_))
+ return PP_ERROR_INPROGRESS;
+ if (state_ == PP_WEBSOCKETREADYSTATE_INVALID)
+ return PP_ERROR_FAILED;
+
+ // Validate |code| and |reason|.
+ scoped_refptr<StringVar> reason_string_var;
+ std::string reason_string;
+ WebKit::WebSocket::CloseEventCode event_code =
+ static_cast<WebKit::WebSocket::CloseEventCode>(code);
+ if (code == PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED) {
+ // PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED and CloseEventCodeNotSpecified are
+ // assigned to different values. A conversion is needed if
+ // PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED is specified.
+ event_code = WebKit::WebSocket::CloseEventCodeNotSpecified;
+ } else {
+ if (!(code == PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE ||
+ (PP_WEBSOCKETSTATUSCODE_USER_REGISTERED_MIN <= code &&
+ code <= PP_WEBSOCKETSTATUSCODE_USER_PRIVATE_MAX)))
+ // RFC 6455 limits applications to use reserved connection close code in
+ // section 7.4.2.. The WebSocket API (http://www.w3.org/TR/websockets/)
+ // defines this out of range error as InvalidAccessError in JavaScript.
+ return PP_ERROR_NOACCESS;
+
+ // |reason| must be ignored if it is PP_VARTYPE_UNDEFINED or |code| is
+ // PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED.
+ if (reason.type != PP_VARTYPE_UNDEFINED) {
+ // Validate |reason|.
+ reason_string_var = StringVar::FromPPVar(reason);
+ if (!reason_string_var.get() ||
+ reason_string_var->value().size() > kMaxReasonSizeInBytes)
+ return PP_ERROR_BADARGUMENT;
+ reason_string = reason_string_var->value();
+ }
+ }
+
+ // Check state.
+ if (state_ == PP_WEBSOCKETREADYSTATE_CLOSING)
+ return PP_ERROR_INPROGRESS;
+ if (state_ == PP_WEBSOCKETREADYSTATE_CLOSED)
+ return PP_OK;
+
+ // Install |callback|.
+ close_callback_ = callback;
+
+ // Abort ongoing connect.
+ if (TrackedCallback::IsPending(connect_callback_)) {
+ state_ = PP_WEBSOCKETREADYSTATE_CLOSING;
+ // Need to do a "Post" to avoid reentering the plugin.
+ connect_callback_->PostAbort();
+ connect_callback_ = NULL;
+ Post(RENDERER, PpapiHostMsg_WebSocket_Fail(
+ "WebSocket was closed before the connection was established."));
+ return PP_OK_COMPLETIONPENDING;
+ }
+
+ // Abort ongoing receive.
+ if (TrackedCallback::IsPending(receive_callback_)) {
+ receive_callback_var_ = NULL;
+ // Need to do a "Post" to avoid reentering the plugin.
+ receive_callback_->PostAbort();
+ receive_callback_ = NULL;
+ }
+
+ // Close connection.
+ state_ = PP_WEBSOCKETREADYSTATE_CLOSING;
+ PpapiHostMsg_WebSocket_Close msg(static_cast<int32_t>(event_code),
+ reason_string);
+ Call<PpapiPluginMsg_WebSocket_CloseReply>(RENDERER, msg,
+ base::Bind(&WebSocketResource::OnPluginMsgCloseReply, this));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t WebSocketResource::ReceiveMessage(
+ PP_Var* message,
+ scoped_refptr<TrackedCallback> callback) {
+ if (TrackedCallback::IsPending(receive_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ // Check state.
+ if (state_ == PP_WEBSOCKETREADYSTATE_INVALID ||
+ state_ == PP_WEBSOCKETREADYSTATE_CONNECTING)
+ return PP_ERROR_BADARGUMENT;
+
+ // Just return received message if any received message is queued.
+ if (!received_messages_.empty()) {
+ receive_callback_var_ = message;
+ return DoReceive();
+ }
+
+ // Check state again. In CLOSED state, no more messages will be received.
+ if (state_ == PP_WEBSOCKETREADYSTATE_CLOSED)
+ return PP_ERROR_BADARGUMENT;
+
+ // Returns PP_ERROR_FAILED after an error is received and received messages
+ // is exhausted.
+ if (error_was_received_)
+ return PP_ERROR_FAILED;
+
+ // Or retain |message| as buffer to store and install |callback|.
+ receive_callback_var_ = message;
+ receive_callback_ = callback;
+
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t WebSocketResource::SendMessage(const PP_Var& message) {
+ // Check state.
+ if (state_ == PP_WEBSOCKETREADYSTATE_INVALID ||
+ state_ == PP_WEBSOCKETREADYSTATE_CONNECTING)
+ return PP_ERROR_BADARGUMENT;
+
+ if (state_ == PP_WEBSOCKETREADYSTATE_CLOSING ||
+ state_ == PP_WEBSOCKETREADYSTATE_CLOSED) {
+ // Handle buffered_amount_after_close_.
+ uint64_t payload_size = 0;
+ if (message.type == PP_VARTYPE_STRING) {
+ scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message);
+ if (message_string.get())
+ payload_size += message_string->value().length();
+ } else if (message.type == PP_VARTYPE_ARRAY_BUFFER) {
+ scoped_refptr<ArrayBufferVar> message_array_buffer =
+ ArrayBufferVar::FromPPVar(message);
+ if (message_array_buffer.get())
+ payload_size += message_array_buffer->ByteLength();
+ } else {
+ // TODO(toyoshim): Support Blob.
+ return PP_ERROR_NOTSUPPORTED;
+ }
+
+ buffered_amount_after_close_ =
+ SaturateAdd(buffered_amount_after_close_, GetFrameSize(payload_size));
+
+ return PP_ERROR_FAILED;
+ }
+
+ // Send the message.
+ if (message.type == PP_VARTYPE_STRING) {
+ // Convert message to std::string, then send it.
+ scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message);
+ if (!message_string.get())
+ return PP_ERROR_BADARGUMENT;
+ Post(RENDERER, PpapiHostMsg_WebSocket_SendText(message_string->value()));
+ } else if (message.type == PP_VARTYPE_ARRAY_BUFFER) {
+ // Convert message to std::vector<uint8_t>, then send it.
+ scoped_refptr<ArrayBufferVar> message_arraybuffer =
+ ArrayBufferVar::FromPPVar(message);
+ if (!message_arraybuffer.get())
+ return PP_ERROR_BADARGUMENT;
+ uint8_t* message_data = static_cast<uint8_t*>(message_arraybuffer->Map());
+ uint32 message_length = message_arraybuffer->ByteLength();
+ std::vector<uint8_t> message_vector(message_data,
+ message_data + message_length);
+ Post(RENDERER, PpapiHostMsg_WebSocket_SendBinary(message_vector));
+ } else {
+ // TODO(toyoshim): Support Blob.
+ return PP_ERROR_NOTSUPPORTED;
+ }
+ return PP_OK;
+}
+
+uint64_t WebSocketResource::GetBufferedAmount() {
+ return SaturateAdd(buffered_amount_, buffered_amount_after_close_);
+}
+
+uint16_t WebSocketResource::GetCloseCode() {
+ return close_code_;
+}
+
+PP_Var WebSocketResource::GetCloseReason() {
+ if (!close_reason_.get())
+ return empty_string_->GetPPVar();
+ return close_reason_->GetPPVar();
+}
+
+PP_Bool WebSocketResource::GetCloseWasClean() {
+ return close_was_clean_;
+}
+
+PP_Var WebSocketResource::GetExtensions() {
+ return StringVar::StringToPPVar(std::string());
+}
+
+PP_Var WebSocketResource::GetProtocol() {
+ if (!protocol_.get())
+ return empty_string_->GetPPVar();
+ return protocol_->GetPPVar();
+}
+
+PP_WebSocketReadyState WebSocketResource::GetReadyState() {
+ return state_;
+}
+
+PP_Var WebSocketResource::GetURL() {
+ if (!url_.get())
+ return empty_string_->GetPPVar();
+ return url_->GetPPVar();
+}
+
+void WebSocketResource::OnReplyReceived(
+ const ResourceMessageReplyParams& params,
+ const IPC::Message& msg) {
+ if (params.sequence()) {
+ PluginResource::OnReplyReceived(params, msg);
+ return;
+ }
+
+ IPC_BEGIN_MESSAGE_MAP(WebSocketResource, msg)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
+ PpapiPluginMsg_WebSocket_ReceiveTextReply,
+ OnPluginMsgReceiveTextReply)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
+ PpapiPluginMsg_WebSocket_ReceiveBinaryReply,
+ OnPluginMsgReceiveBinaryReply)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_0(
+ PpapiPluginMsg_WebSocket_ErrorReply,
+ OnPluginMsgErrorReply)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
+ PpapiPluginMsg_WebSocket_BufferedAmountReply,
+ OnPluginMsgBufferedAmountReply)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
+ PpapiPluginMsg_WebSocket_StateReply,
+ OnPluginMsgStateReply)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
+ PpapiPluginMsg_WebSocket_ClosedReply,
+ OnPluginMsgClosedReply)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(NOTREACHED())
+ IPC_END_MESSAGE_MAP()
+}
+
+void WebSocketResource::OnPluginMsgConnectReply(
+ const ResourceMessageReplyParams& params,
+ const std::string& url,
+ const std::string& protocol) {
+ if (!TrackedCallback::IsPending(connect_callback_) ||
+ TrackedCallback::IsScheduledToRun(connect_callback_)) {
+ return;
+ }
+
+ int32_t result = params.result();
+ if (result == PP_OK) {
+ state_ = PP_WEBSOCKETREADYSTATE_OPEN;
+ protocol_ = new StringVar(protocol);
+ url_ = new StringVar(url);
+ }
+ connect_callback_->Run(params.result());
+}
+
+void WebSocketResource::OnPluginMsgCloseReply(
+ const ResourceMessageReplyParams& params,
+ unsigned long buffered_amount,
+ bool was_clean,
+ unsigned short code,
+ const std::string& reason) {
+ // Set close related properties.
+ state_ = PP_WEBSOCKETREADYSTATE_CLOSED;
+ buffered_amount_ = buffered_amount;
+ close_was_clean_ = PP_FromBool(was_clean);
+ close_code_ = code;
+ close_reason_ = new StringVar(reason);
+
+ if (TrackedCallback::IsPending(receive_callback_)) {
+ receive_callback_var_ = NULL;
+ if (!TrackedCallback::IsScheduledToRun(receive_callback_))
+ receive_callback_->PostRun(PP_ERROR_FAILED);
+ receive_callback_ = NULL;
+ }
+
+ if (TrackedCallback::IsPending(close_callback_)) {
+ if (!TrackedCallback::IsScheduledToRun(close_callback_))
+ close_callback_->PostRun(params.result());
+ close_callback_ = NULL;
+ }
+}
+
+void WebSocketResource::OnPluginMsgReceiveTextReply(
+ const ResourceMessageReplyParams& params,
+ const std::string& message) {
+ // Dispose packets after receiving an error or in invalid state.
+ if (error_was_received_ || !InValidStateToReceive(state_))
+ return;
+
+ // Append received data to queue.
+ received_messages_.push(scoped_refptr<Var>(new StringVar(message)));
+
+ if (!TrackedCallback::IsPending(receive_callback_) ||
+ TrackedCallback::IsScheduledToRun(receive_callback_)) {
+ return;
+ }
+
+ receive_callback_->Run(DoReceive());
+}
+
+void WebSocketResource::OnPluginMsgReceiveBinaryReply(
+ const ResourceMessageReplyParams& params,
+ const std::vector<uint8_t>& message) {
+ // Dispose packets after receiving an error or in invalid state.
+ if (error_was_received_ || !InValidStateToReceive(state_))
+ return;
+
+ // Append received data to queue.
+ scoped_refptr<Var> message_var(
+ PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferVar(
+ message.size(),
+ &message.front()));
+ received_messages_.push(message_var);
+
+ if (!TrackedCallback::IsPending(receive_callback_) ||
+ TrackedCallback::IsScheduledToRun(receive_callback_)) {
+ return;
+ }
+
+ receive_callback_->Run(DoReceive());
+}
+
+void WebSocketResource::OnPluginMsgErrorReply(
+ const ResourceMessageReplyParams& params) {
+ error_was_received_ = true;
+
+ if (!TrackedCallback::IsPending(receive_callback_) ||
+ TrackedCallback::IsScheduledToRun(receive_callback_)) {
+ return;
+ }
+
+ // No more text or binary messages will be received. If there is ongoing
+ // ReceiveMessage(), we must invoke the callback with error code here.
+ receive_callback_var_ = NULL;
+ receive_callback_->Run(PP_ERROR_FAILED);
+}
+
+void WebSocketResource::OnPluginMsgBufferedAmountReply(
+ const ResourceMessageReplyParams& params,
+ unsigned long buffered_amount) {
+ buffered_amount_ = buffered_amount;
+}
+
+void WebSocketResource::OnPluginMsgStateReply(
+ const ResourceMessageReplyParams& params,
+ int32_t state) {
+ state_ = static_cast<PP_WebSocketReadyState>(state);
+}
+
+void WebSocketResource::OnPluginMsgClosedReply(
+ const ResourceMessageReplyParams& params,
+ unsigned long buffered_amount,
+ bool was_clean,
+ unsigned short code,
+ const std::string& reason) {
+ OnPluginMsgCloseReply(params, buffered_amount, was_clean, code, reason);
+}
+
+int32_t WebSocketResource::DoReceive() {
+ if (!receive_callback_var_)
+ return PP_OK;
+
+ *receive_callback_var_ = received_messages_.front()->GetPPVar();
+ received_messages_.pop();
+ receive_callback_var_ = NULL;
+ return PP_OK;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/chromium/ppapi/proxy/websocket_resource.h b/chromium/ppapi/proxy/websocket_resource.h
new file mode 100644
index 00000000000..49353e4b0b5
--- /dev/null
+++ b/chromium/ppapi/proxy/websocket_resource.h
@@ -0,0 +1,157 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_WEBSOCKET_RESOURCE_H_
+#define PPAPI_PROXY_WEBSOCKET_RESOURCE_H_
+
+#include <queue>
+
+#include "ppapi/c/ppb_websocket.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/ppb_websocket_api.h"
+
+namespace ppapi {
+
+class StringVar;
+class Var;
+
+namespace proxy {
+
+// This class contains protocol checks which doesn't affect security when it
+// run with untrusted code.
+class PPAPI_PROXY_EXPORT WebSocketResource
+ : public PluginResource,
+ public NON_EXPORTED_BASE(thunk::PPB_WebSocket_API) {
+ public:
+ WebSocketResource(Connection connection, PP_Instance instance);
+ virtual ~WebSocketResource();
+
+ // PluginResource implementation.
+ virtual thunk::PPB_WebSocket_API* AsPPB_WebSocket_API() OVERRIDE;
+
+ // PPB_WebSocket_API implementation.
+ virtual int32_t Connect(const PP_Var& url,
+ const PP_Var protocols[],
+ uint32_t protocol_count,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Close(uint16_t code,
+ const PP_Var& reason,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t ReceiveMessage(
+ PP_Var* message,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t SendMessage(const PP_Var& message) OVERRIDE;
+ virtual uint64_t GetBufferedAmount() OVERRIDE;
+ virtual uint16_t GetCloseCode() OVERRIDE;
+ virtual PP_Var GetCloseReason() OVERRIDE;
+ virtual PP_Bool GetCloseWasClean() OVERRIDE;
+ virtual PP_Var GetExtensions() OVERRIDE;
+ virtual PP_Var GetProtocol() OVERRIDE;
+ virtual PP_WebSocketReadyState GetReadyState() OVERRIDE;
+ virtual PP_Var GetURL() OVERRIDE;
+
+ private:
+ // PluginResource override.
+ virtual void OnReplyReceived(const ResourceMessageReplyParams& params,
+ const IPC::Message& msg) OVERRIDE;
+
+ // IPC message handlers.
+ void OnPluginMsgConnectReply(const ResourceMessageReplyParams& params,
+ const std::string& url,
+ const std::string& protocol);
+ void OnPluginMsgCloseReply(const ResourceMessageReplyParams& params,
+ unsigned long buffered_amount,
+ bool was_clean,
+ unsigned short code,
+ const std::string& reason);
+ void OnPluginMsgReceiveTextReply(const ResourceMessageReplyParams& params,
+ const std::string& message);
+ void OnPluginMsgReceiveBinaryReply(const ResourceMessageReplyParams& params,
+ const std::vector<uint8_t>& message);
+ void OnPluginMsgErrorReply(const ResourceMessageReplyParams& params);
+ void OnPluginMsgBufferedAmountReply(const ResourceMessageReplyParams& params,
+ unsigned long buffered_amount);
+ void OnPluginMsgStateReply(const ResourceMessageReplyParams& params,
+ int32_t state);
+ void OnPluginMsgClosedReply(const ResourceMessageReplyParams& params,
+ unsigned long buffered_amount,
+ bool was_clean,
+ unsigned short code,
+ const std::string& reason);
+
+ // Picks up a received message and moves it to user receiving buffer. This
+ // function is used in both ReceiveMessage for fast returning path, and
+ // OnPluginMsgReceiveTextReply and OnPluginMsgReceiveBinaryReply for delayed
+ // callback invocations.
+ int32_t DoReceive();
+
+ // Holds user callbacks to invoke later.
+ scoped_refptr<TrackedCallback> connect_callback_;
+ scoped_refptr<TrackedCallback> close_callback_;
+ scoped_refptr<TrackedCallback> receive_callback_;
+
+ // Represents readyState described in the WebSocket API specification. It can
+ // be read via GetReadyState().
+ PP_WebSocketReadyState state_;
+
+ // Becomes true if any error is detected. Incoming data will be disposed
+ // if this variable is true, then ReceiveMessage() returns PP_ERROR_FAILED
+ // after returning all received data.
+ bool error_was_received_;
+
+ // Keeps a pointer to PP_Var which is provided via ReceiveMessage().
+ // Received data will be copied to this PP_Var on ready.
+ PP_Var* receive_callback_var_;
+
+ // Keeps received data until ReceiveMessage() requests.
+ std::queue<scoped_refptr<Var> > received_messages_;
+
+ // Keeps empty string for functions to return empty string.
+ scoped_refptr<StringVar> empty_string_;
+
+ // Keeps the status code field of closing handshake. It can be read via
+ // GetCloseCode().
+ uint16_t close_code_;
+
+ // Keeps the reason field of closing handshake. It can be read via
+ // GetCloseReason().
+ scoped_refptr<StringVar> close_reason_;
+
+ // Becomes true when closing handshake is performed successfully. It can be
+ // read via GetCloseWasClean().
+ PP_Bool close_was_clean_;
+
+ // Represents extensions described in the WebSocket API specification. It can
+ // be read via GetExtensions().
+ scoped_refptr<StringVar> extensions_;
+
+ // Represents protocol described in the WebSocket API specification. It can be
+ // read via GetProtocol().
+ scoped_refptr<StringVar> protocol_;
+
+ // Represents url described in the WebSocket API specification. It can be
+ // read via GetURL().
+ scoped_refptr<StringVar> url_;
+
+ // Keeps the number of bytes of application data that have been queued using
+ // SendMessage(). WebKit side implementation calculates the actual amount.
+ // This is a cached value which is notified through a WebKit callback.
+ // This value is used to calculate bufferedAmount in the WebSocket API
+ // specification. The calculated value can be read via GetBufferedAmount().
+ uint64_t buffered_amount_;
+
+ // Keeps the number of bytes of application data that have been ignored
+ // because the connection was already closed.
+ // This value is used to calculate bufferedAmount in the WebSocket API
+ // specification. The calculated value can be read via GetBufferedAmount().
+ uint64_t buffered_amount_after_close_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSocketResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_WEBSOCKET_RESOURCE_H_
diff --git a/chromium/ppapi/proxy/websocket_resource_unittest.cc b/chromium/ppapi/proxy/websocket_resource_unittest.cc
new file mode 100644
index 00000000000..ecd9111c980
--- /dev/null
+++ b/chromium/ppapi/proxy/websocket_resource_unittest.cc
@@ -0,0 +1,169 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/c/ppb_websocket.h"
+#include "ppapi/proxy/locking_resource_releaser.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+#include "ppapi/proxy/websocket_resource.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/ppb_var_shared.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/resource_tracker.h"
+#include "ppapi/shared_impl/scoped_pp_resource.h"
+#include "ppapi/shared_impl/scoped_pp_var.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/thunk.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+typedef PluginProxyTest WebSocketResourceTest;
+
+bool g_callback_called;
+int32_t g_callback_result;
+const PPB_Var* ppb_var_ = NULL;
+
+void Callback(void* user_data, int32_t result) {
+ g_callback_called = true;
+ g_callback_result = result;
+}
+
+PP_CompletionCallback MakeCallback() {
+ g_callback_called = false;
+ g_callback_result = PP_OK;
+ return PP_MakeCompletionCallback(Callback, NULL);
+}
+
+PP_Var MakeStringVar(const std::string& string) {
+ if (!ppb_var_)
+ ppb_var_ = ppapi::PPB_Var_Shared::GetVarInterface1_1();
+ return ppb_var_->VarFromUtf8(string.c_str(), string.length());
+}
+
+} // namespace
+
+
+// Does a test of Connect().
+TEST_F(WebSocketResourceTest, Connect) {
+ const PPB_WebSocket_1_0* websocket_iface =
+ thunk::GetPPB_WebSocket_1_0_Thunk();
+
+ std::string url("ws://ws.google.com");
+ std::string protocol0("x-foo");
+ std::string protocol1("x-bar");
+ PP_Var url_var = MakeStringVar(url);
+ PP_Var protocols[] = { MakeStringVar(protocol0), MakeStringVar(protocol1) };
+
+ LockingResourceReleaser res(websocket_iface->Create(pp_instance()));
+
+ int32_t result = websocket_iface->Connect(res.get(), url_var, protocols, 2,
+ MakeCallback());
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
+
+ // Should be sent a "Connect" message.
+ ResourceMessageCallParams params;
+ IPC::Message msg;
+ ASSERT_TRUE(sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_WebSocket_Connect::ID, &params, &msg));
+ PpapiHostMsg_WebSocket_Connect::Schema::Param p;
+ PpapiHostMsg_WebSocket_Connect::Read(&msg, &p);
+ EXPECT_EQ(url, p.a);
+ EXPECT_EQ(protocol0, p.b[0]);
+ EXPECT_EQ(protocol1, p.b[1]);
+
+ // Synthesize a response.
+ ResourceMessageReplyParams reply_params(params.pp_resource(),
+ params.sequence());
+ reply_params.set_result(PP_OK);
+ ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(
+ PpapiPluginMsg_ResourceReply(reply_params,
+ PpapiPluginMsg_WebSocket_ConnectReply(url, protocol1))));
+
+ EXPECT_EQ(PP_OK, g_callback_result);
+ EXPECT_EQ(true, g_callback_called);
+}
+
+// Does a test for unsolicited replies.
+TEST_F(WebSocketResourceTest, UnsolicitedReplies) {
+ const PPB_WebSocket_1_0* websocket_iface =
+ thunk::GetPPB_WebSocket_1_0_Thunk();
+
+ LockingResourceReleaser res(websocket_iface->Create(pp_instance()));
+
+ // Check if BufferedAmountReply is handled.
+ ResourceMessageReplyParams reply_params(res.get(), 0);
+ reply_params.set_result(PP_OK);
+ ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(
+ PpapiPluginMsg_ResourceReply(
+ reply_params,
+ PpapiPluginMsg_WebSocket_BufferedAmountReply(19760227u))));
+
+ uint64_t amount = websocket_iface->GetBufferedAmount(res.get());
+ EXPECT_EQ(19760227u, amount);
+
+ // Check if StateReply is handled.
+ ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(
+ PpapiPluginMsg_ResourceReply(
+ reply_params,
+ PpapiPluginMsg_WebSocket_StateReply(
+ static_cast<int32_t>(PP_WEBSOCKETREADYSTATE_CLOSING)))));
+
+ PP_WebSocketReadyState state = websocket_iface->GetReadyState(res.get());
+ EXPECT_EQ(PP_WEBSOCKETREADYSTATE_CLOSING, state);
+}
+
+TEST_F(WebSocketResourceTest, MessageError) {
+ const PPB_WebSocket_1_0* websocket_iface =
+ thunk::GetPPB_WebSocket_1_0_Thunk();
+
+ std::string url("ws://ws.google.com");
+ PP_Var url_var = MakeStringVar(url);
+
+ LockingResourceReleaser res(websocket_iface->Create(pp_instance()));
+
+ // Establish the connection virtually.
+ int32_t result =
+ websocket_iface->Connect(res.get(), url_var, NULL, 0, MakeCallback());
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
+
+ ResourceMessageCallParams params;
+ IPC::Message msg;
+ ASSERT_TRUE(sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_WebSocket_Connect::ID, &params, &msg));
+
+ ResourceMessageReplyParams connect_reply_params(params.pp_resource(),
+ params.sequence());
+ connect_reply_params.set_result(PP_OK);
+ ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(
+ PpapiPluginMsg_ResourceReply(connect_reply_params,
+ PpapiPluginMsg_WebSocket_ConnectReply(url, std::string()))));
+
+ EXPECT_EQ(PP_OK, g_callback_result);
+ EXPECT_TRUE(g_callback_called);
+
+ PP_Var message;
+ result = websocket_iface->ReceiveMessage(res.get(), &message, MakeCallback());
+ EXPECT_FALSE(g_callback_called);
+
+ // Synthesize a WebSocket_ErrorReply message.
+ ResourceMessageReplyParams error_reply_params(res.get(), 0);
+ error_reply_params.set_result(PP_OK);
+ ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(
+ PpapiPluginMsg_ResourceReply(error_reply_params,
+ PpapiPluginMsg_WebSocket_ErrorReply())));
+
+ EXPECT_EQ(PP_ERROR_FAILED, g_callback_result);
+ EXPECT_TRUE(g_callback_called);
+}
+
+} // namespace proxy
+} // namespace ppapi