summaryrefslogtreecommitdiffstats
path: root/ppapi/proxy
diff options
context:
space:
mode:
Diffstat (limited to 'ppapi/proxy')
-rw-r--r--ppapi/proxy/DEPS3
-rw-r--r--ppapi/proxy/dispatcher.cc12
-rw-r--r--ppapi/proxy/dispatcher.h13
-rw-r--r--ppapi/proxy/host_dispatcher.cc5
-rw-r--r--ppapi/proxy/host_dispatcher.h4
-rw-r--r--ppapi/proxy/interface_id.h4
-rw-r--r--ppapi/proxy/plugin_dispatcher.cc5
-rw-r--r--ppapi/proxy/plugin_dispatcher.h5
-rw-r--r--ppapi/proxy/plugin_resource.h2
-rw-r--r--ppapi/proxy/ppapi_messages.h4
-rw-r--r--ppapi/proxy/ppapi_messages_internal.h49
-rw-r--r--ppapi/proxy/ppb_audio_config_proxy.cc135
-rw-r--r--ppapi/proxy/ppb_audio_config_proxy.h46
-rw-r--r--ppapi/proxy/ppb_audio_proxy.cc285
-rw-r--r--ppapi/proxy/ppb_audio_proxy.h78
15 files changed, 635 insertions, 15 deletions
diff --git a/ppapi/proxy/DEPS b/ppapi/proxy/DEPS
index d5d2f9c..7ef8f98 100644
--- a/ppapi/proxy/DEPS
+++ b/ppapi/proxy/DEPS
@@ -1,4 +1,7 @@
include_rules = [
+ "+base",
+ "+ipc",
+
# These files are really Chrome-only and we don't want to expose them, but
# we need to use them for the proxy. Allow the code here to pull these
# headers (which don't depend on anything else).
diff --git a/ppapi/proxy/dispatcher.cc b/ppapi/proxy/dispatcher.cc
index b1ce1c4..df7383f 100644
--- a/ppapi/proxy/dispatcher.cc
+++ b/ppapi/proxy/dispatcher.cc
@@ -12,6 +12,8 @@
#include "base/logging.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_sync_channel.h"
+#include "ppapi/c/dev/ppb_audio_config_dev.h"
+#include "ppapi/c/dev/ppb_audio_dev.h"
#include "ppapi/c/dev/ppb_buffer_dev.h"
#include "ppapi/c/dev/ppb_char_set_dev.h"
#include "ppapi/c/dev/ppb_cursor_control_dev.h"
@@ -31,6 +33,8 @@
#include "ppapi/c/ppb_url_response_info.h"
#include "ppapi/c/ppp_instance.h"
#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_audio_config_proxy.h"
+#include "ppapi/proxy/ppb_audio_proxy.h"
#include "ppapi/proxy/ppb_buffer_proxy.h"
#include "ppapi/proxy/ppb_char_set_proxy.h"
#include "ppapi/proxy/ppb_core_proxy.h"
@@ -54,8 +58,10 @@
namespace pp {
namespace proxy {
-Dispatcher::Dispatcher(GetInterfaceFunc local_get_interface)
+Dispatcher::Dispatcher(base::ProcessHandle remote_process_handle,
+ GetInterfaceFunc local_get_interface)
: pp_module_(0),
+ remote_process_handle_(remote_process_handle),
disallow_trusted_interfaces_(true),
local_get_interface_(local_get_interface),
declared_supported_remote_interfaces_(false),
@@ -216,6 +222,10 @@ void Dispatcher::OnMsgDeclareInterfaces(
InterfaceProxy* Dispatcher::CreateProxyForInterface(
const std::string& interface_name,
const void* interface_functions) {
+ if (interface_name == PPB_AUDIO_CONFIG_DEV_INTERFACE)
+ return new PPB_AudioConfig_Proxy(this, interface_functions);
+ if (interface_name == PPB_AUDIO_DEV_INTERFACE)
+ return new PPB_Audio_Proxy(this, interface_functions);
if (interface_name == PPB_BUFFER_DEV_INTERFACE)
return new PPB_Buffer_Proxy(this, interface_functions);
if (interface_name == PPB_CHAR_SET_DEV_INTERFACE)
diff --git a/ppapi/proxy/dispatcher.h b/ppapi/proxy/dispatcher.h
index 356dbcf..deee5fc 100644
--- a/ppapi/proxy/dispatcher.h
+++ b/ppapi/proxy/dispatcher.h
@@ -10,6 +10,7 @@
#include <vector>
#include "base/linked_ptr.h"
+#include "base/process.h"
#include "base/scoped_ptr.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_channel_handle.h"
@@ -86,6 +87,14 @@ class Dispatcher : public IPC::Channel::Listener,
// or not supported by the remote side, returns NULL.
const void* GetProxiedInterface(const std::string& interface);
+ // Returns the remote process' handle. For the host dispatcher, this will be
+ // the plugin process, and for the plugin dispatcher, this will be the
+ // renderer process. This is used for sharing memory and such and is
+ // guaranteed valid (unless the remote process has suddenly died).
+ base::ProcessHandle remote_process_handle() const {
+ return remote_process_handle_;
+ }
+
// 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.
@@ -105,7 +114,8 @@ class Dispatcher : public IPC::Channel::Listener,
}
protected:
- Dispatcher(GetInterfaceFunc local_get_interface);
+ Dispatcher(base::ProcessHandle remote_process_handle,
+ GetInterfaceFunc local_get_interface);
// Setter for the derived classes to set the appropriate var serialization.
// Takes ownership of the given pointer, which must be on the heap.
@@ -154,6 +164,7 @@ class Dispatcher : public IPC::Channel::Listener,
// this dispatcher.
PP_Module pp_module_;
+ base::ProcessHandle remote_process_handle_; // See getter above.
scoped_ptr<IPC::SyncChannel> channel_;
bool disallow_trusted_interfaces_;
diff --git a/ppapi/proxy/host_dispatcher.cc b/ppapi/proxy/host_dispatcher.cc
index bb70796..a717af8 100644
--- a/ppapi/proxy/host_dispatcher.cc
+++ b/ppapi/proxy/host_dispatcher.cc
@@ -19,10 +19,11 @@ InstanceToDispatcherMap* g_instance_to_dispatcher = NULL;
} // namespace
-HostDispatcher::HostDispatcher(const PPB_Var_Deprecated* var_interface,
+HostDispatcher::HostDispatcher(base::ProcessHandle remote_process_handle,
+ const PPB_Var_Deprecated* var_interface,
PP_Module module,
GetInterfaceFunc local_get_interface)
- : Dispatcher(local_get_interface) {
+ : Dispatcher(remote_process_handle, local_get_interface) {
SetSerializationRules(new HostVarSerializationRules(var_interface, module));
}
diff --git a/ppapi/proxy/host_dispatcher.h b/ppapi/proxy/host_dispatcher.h
index 94d45d2..f968652 100644
--- a/ppapi/proxy/host_dispatcher.h
+++ b/ppapi/proxy/host_dispatcher.h
@@ -9,6 +9,7 @@
#include <string>
#include <vector>
+#include "base/process.h"
#include "base/scoped_ptr.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/proxy/dispatcher.h"
@@ -36,7 +37,8 @@ class HostDispatcher : public Dispatcher {
// Constructor for the renderer side.
//
// You must call Dispatcher::InitWithChannel after the constructor.
- HostDispatcher(const PPB_Var_Deprecated* var_interface,
+ HostDispatcher(base::ProcessHandle host_process_handle,
+ const PPB_Var_Deprecated* var_interface,
PP_Module module,
GetInterfaceFunc local_get_interface);
~HostDispatcher();
diff --git a/ppapi/proxy/interface_id.h b/ppapi/proxy/interface_id.h
index f0ae597..8d85f03 100644
--- a/ppapi/proxy/interface_id.h
+++ b/ppapi/proxy/interface_id.h
@@ -12,7 +12,9 @@ namespace proxy {
// to route messages to the appropriate message handler.
enum InterfaceID {
// Zero is reserved for control messages.
- INTERFACE_ID_PPB_BUFFER = 1,
+ INTERFACE_ID_PPB_AUDIO = 1,
+ INTERFACE_ID_PPB_AUDIO_CONFIG,
+ INTERFACE_ID_PPB_BUFFER,
INTERFACE_ID_PPB_CHAR_SET,
INTERFACE_ID_PPB_CORE,
INTERFACE_ID_PPB_CURSORCONTROL,
diff --git a/ppapi/proxy/plugin_dispatcher.cc b/ppapi/proxy/plugin_dispatcher.cc
index 085c15c..4c9adca 100644
--- a/ppapi/proxy/plugin_dispatcher.cc
+++ b/ppapi/proxy/plugin_dispatcher.cc
@@ -30,10 +30,11 @@ const void* GetInterfaceFromDispatcher(const char* interface) {
} // namespace
-PluginDispatcher::PluginDispatcher(GetInterfaceFunc get_interface,
+PluginDispatcher::PluginDispatcher(base::ProcessHandle remote_process_handle,
+ GetInterfaceFunc get_interface,
InitModuleFunc init_module,
ShutdownModuleFunc shutdown_module)
- : Dispatcher(get_interface),
+ : Dispatcher(remote_process_handle, get_interface),
init_module_(init_module),
shutdown_module_(shutdown_module),
plugin_resource_tracker_(new PluginResourceTracker(
diff --git a/ppapi/proxy/plugin_dispatcher.h b/ppapi/proxy/plugin_dispatcher.h
index 0a97965..79eafb1 100644
--- a/ppapi/proxy/plugin_dispatcher.h
+++ b/ppapi/proxy/plugin_dispatcher.h
@@ -7,6 +7,7 @@
#include <string>
+#include "base/process.h"
#include "base/scoped_ptr.h"
#include "ppapi/proxy/callback_tracker.h"
#include "ppapi/proxy/dispatcher.h"
@@ -29,7 +30,8 @@ class PluginDispatcher : public Dispatcher {
// module ID will be set upon receipt of the InitializeModule message.
//
// You must call Dispatcher::InitWithChannel after the constructor.
- PluginDispatcher(GetInterfaceFunc get_interface,
+ PluginDispatcher(base::ProcessHandle remote_process_handle,
+ GetInterfaceFunc get_interface,
InitModuleFunc init_module,
ShutdownModuleFunc shutdown_module);
~PluginDispatcher();
@@ -59,6 +61,7 @@ class PluginDispatcher : public Dispatcher {
}
private:
+ // IPC message handler.
void OnInitializeModule(PP_Module pp_module, bool* result);
InitModuleFunc init_module_;
diff --git a/ppapi/proxy/plugin_resource.h b/ppapi/proxy/plugin_resource.h
index 09ed59f..52a8609 100644
--- a/ppapi/proxy/plugin_resource.h
+++ b/ppapi/proxy/plugin_resource.h
@@ -11,6 +11,8 @@
// If you inherit from resource, make sure you add the class name here.
#define FOR_ALL_RESOURCES(F) \
+ F(Audio) \
+ F(AudioConfig) \
F(Buffer) \
F(Font) \
F(Graphics2D) \
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
index d0f5bed..dd2b246 100644
--- a/ppapi/proxy/ppapi_messages.h
+++ b/ppapi/proxy/ppapi_messages.h
@@ -10,8 +10,12 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/process.h"
+#include "base/shared_memory.h"
#include "base/string16.h"
+#include "base/sync_socket.h"
#include "ipc/ipc_message_utils.h"
+#include "ipc/ipc_platform_file.h"
#include "ppapi/c/pp_bool.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_module.h"
diff --git a/ppapi/proxy/ppapi_messages_internal.h b/ppapi/proxy/ppapi_messages_internal.h
index 22d8a52..d7f317e 100644
--- a/ppapi/proxy/ppapi_messages_internal.h
+++ b/ppapi/proxy/ppapi_messages_internal.h
@@ -13,7 +13,8 @@
// These are from the plugin to the renderer
IPC_BEGIN_MESSAGES(Ppapi)
// Loads the given plugin.
- IPC_MESSAGE_CONTROL2(PpapiMsg_LoadPlugin,
+ IPC_MESSAGE_CONTROL3(PpapiMsg_LoadPlugin,
+ base::ProcessHandle /* host_process_handle */,
FilePath /* path */,
int /* renderer_id */)
@@ -36,6 +37,27 @@ IPC_BEGIN_MESSAGES(Ppapi)
uint32 /* serialized_callback */,
int32 /* param */)
+ // PPB_Audio.
+
+ // Notifies the result of the audio stream create call. This is called in
+ // both error cases and in the normal success case. These cases are
+ // differentiated by the result code, which is one of the standard PPAPI
+ // result codes.
+ //
+ // The handler of this message should always close all of the handles passed
+ // in, since some could be valid even in the error case.
+ IPC_MESSAGE_ROUTED5(PpapiMsg_PPBAudio_NotifyAudioStreamCreated,
+ PP_Resource /* audio_id */,
+ int32_t /* result_code (will be != PP_OK on failure) */,
+ IPC::PlatformFileForTransit /* socket_handle */,
+ base::SharedMemoryHandle /* handle */,
+ int32_t /* length */)
+
+ // PPB_Graphics2D.
+ IPC_MESSAGE_ROUTED2(PpapiMsg_PPBGraphics2D_FlushACK,
+ PP_Resource /* graphics_2d */,
+ int32_t /* pp_error */)
+
// PPP_Class.
IPC_SYNC_MESSAGE_ROUTED3_2(PpapiMsg_PPPClass_HasProperty,
int64 /* ppp_class */,
@@ -88,11 +110,6 @@ IPC_BEGIN_MESSAGES(Ppapi)
int64 /* ppp_class */,
int64 /* object */)
- // PPB_Graphics2D.
- IPC_MESSAGE_ROUTED2(PpapiMsg_PPBGraphics2D_FlushACK,
- PP_Resource /* graphics_2d */,
- int32_t /* pp_error */)
-
// PPP_Instance.
IPC_SYNC_MESSAGE_ROUTED3_1(PpapiMsg_PPPInstance_DidCreate,
PP_Instance /* instance */,
@@ -142,6 +159,26 @@ IPC_BEGIN_MESSAGES(PpapiHost)
IPC_MESSAGE_CONTROL1(PpapiHostMsg_PluginLoaded,
IPC::ChannelHandle /* handle */)
+ // PPB_Audio.
+ IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBAudio_Create,
+ PP_Instance /* instance_id */,
+ PP_Resource /* config_id */,
+ PP_Resource /* result */)
+ IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBAudio_StartOrStop,
+ PP_Resource /* audio_id */,
+ bool /* play */)
+
+ // PPB_AudioConfig.
+ IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBAudioConfig_Create,
+ PP_Module /* module */,
+ int32_t /* sample_rate */,
+ uint32_t /* sample_frame_count */,
+ PP_Resource /* result */)
+ IPC_SYNC_MESSAGE_ROUTED1_1(
+ PpapiHostMsg_PPBAudioConfig_RecommendSampleFrameCount,
+ uint32_t /* requested */,
+ uint32_t /* result */)
+
// PPB_Buffer.
IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBBuffer_Create,
PP_Module /* module */,
diff --git a/ppapi/proxy/ppb_audio_config_proxy.cc b/ppapi/proxy/ppb_audio_config_proxy.cc
new file mode 100644
index 0000000..7ec3e8f
--- /dev/null
+++ b/ppapi/proxy/ppb_audio_config_proxy.cc
@@ -0,0 +1,135 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppb_audio_config_proxy.h"
+
+#include "ppapi/c/dev/ppb_audio_config_dev.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace pp {
+namespace proxy {
+
+class AudioConfig : public PluginResource {
+ public:
+ AudioConfig(PP_AudioSampleRate_Dev sample_rate, uint32_t sample_frame_count)
+ : sample_rate_(sample_rate),
+ sample_frame_count_(sample_frame_count) {
+ }
+ virtual ~AudioConfig() {}
+
+ // Resource overrides.
+ virtual AudioConfig* AsAudioConfig() { return this; }
+
+ PP_AudioSampleRate_Dev sample_rate() const { return sample_rate_; }
+ uint32_t sample_frame_count() const { return sample_frame_count_; }
+
+ private:
+ PP_AudioSampleRate_Dev sample_rate_;
+ uint32_t sample_frame_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioConfig);
+};
+
+namespace {
+
+PP_Resource CreateStereo16bit(PP_Module module_id,
+ PP_AudioSampleRate_Dev sample_rate,
+ uint32_t sample_frame_count) {
+ PP_Resource result = 0;
+ PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBAudioConfig_Create(
+ INTERFACE_ID_PPB_AUDIO_CONFIG, module_id,
+ static_cast<int32_t>(sample_rate), sample_frame_count,
+ &result));
+ if (!result)
+ return 0;
+
+ linked_ptr<AudioConfig> object(
+ new AudioConfig(sample_rate, sample_frame_count));
+ PluginDispatcher::Get()->plugin_resource_tracker()->AddResource(
+ result, object);
+ return result;
+}
+
+uint32_t RecommendSampleFrameCount(uint32_t requested_sample_frame_count) {
+ uint32_t result = 0;
+ PluginDispatcher::Get()->Send(
+ new PpapiHostMsg_PPBAudioConfig_RecommendSampleFrameCount(
+ INTERFACE_ID_PPB_AUDIO_CONFIG, requested_sample_frame_count,
+ &result));
+ return result;
+}
+
+PP_Bool IsAudioConfig(PP_Resource resource) {
+ AudioConfig* object = PluginResource::GetAs<AudioConfig>(resource);
+ return BoolToPPBool(!!object);
+}
+
+PP_AudioSampleRate_Dev GetSampleRate(PP_Resource config_id) {
+ AudioConfig* object = PluginResource::GetAs<AudioConfig>(config_id);
+ if (!object)
+ return PP_AUDIOSAMPLERATE_NONE;
+ return object->sample_rate();
+}
+
+uint32_t GetSampleFrameCount(PP_Resource config_id) {
+ AudioConfig* object = PluginResource::GetAs<AudioConfig>(config_id);
+ if (!object)
+ return 0;
+ return object->sample_frame_count();
+}
+
+const PPB_AudioConfig_Dev audio_config_interface = {
+ &CreateStereo16bit,
+ &RecommendSampleFrameCount,
+ &IsAudioConfig,
+ &GetSampleRate,
+ &GetSampleFrameCount
+};
+
+} // namespace
+
+PPB_AudioConfig_Proxy::PPB_AudioConfig_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface) {
+}
+
+PPB_AudioConfig_Proxy::~PPB_AudioConfig_Proxy() {
+}
+
+const void* PPB_AudioConfig_Proxy::GetSourceInterface() const {
+ return &audio_config_interface;
+}
+
+InterfaceID PPB_AudioConfig_Proxy::GetInterfaceId() const {
+ return INTERFACE_ID_PPB_AUDIO_CONFIG;
+}
+
+void PPB_AudioConfig_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ IPC_BEGIN_MESSAGE_MAP(PPB_AudioConfig_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBAudioConfig_Create,
+ OnMsgCreateStereo16Bit)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBAudioConfig_RecommendSampleFrameCount,
+ OnMsgRecommendSampleFrameCount)
+ IPC_END_MESSAGE_MAP()
+}
+
+void PPB_AudioConfig_Proxy::OnMsgCreateStereo16Bit(PP_Module module,
+ int32_t sample_rate,
+ uint32_t sample_frame_count,
+ PP_Resource* result) {
+ *result = ppb_audio_config_target()->CreateStereo16Bit(
+ module, static_cast<PP_AudioSampleRate_Dev>(sample_rate),
+ sample_frame_count);
+}
+
+void PPB_AudioConfig_Proxy::OnMsgRecommendSampleFrameCount(
+ uint32_t requested,
+ uint32_t* result) {
+ *result = ppb_audio_config_target()->RecommendSampleFrameCount(requested);
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_audio_config_proxy.h b/ppapi/proxy/ppb_audio_config_proxy.h
new file mode 100644
index 0000000..b80ea31
--- /dev/null
+++ b/ppapi/proxy/ppb_audio_config_proxy.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPB_AUDIO_CONFIG_PROXY_H_
+#define PPAPI_PROXY_PPB_AUDIO_CONFIG_PROXY_H_
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+
+struct PPB_AudioConfig_Dev;
+
+namespace pp {
+namespace proxy {
+
+class PPB_AudioConfig_Proxy : public InterfaceProxy {
+ public:
+ PPB_AudioConfig_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_AudioConfig_Proxy();
+
+ const PPB_AudioConfig_Dev* ppb_audio_config_target() const {
+ return static_cast<const PPB_AudioConfig_Dev*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual const void* GetSourceInterface() const;
+ virtual InterfaceID GetInterfaceId() const;
+ virtual void OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Message handlers.
+ void OnMsgCreateStereo16Bit(PP_Module module,
+ int32_t sample_rate,
+ uint32_t sample_frame_count,
+ PP_Resource* result);
+ void OnMsgRecommendSampleFrameCount(uint32_t requested, uint32_t* result);
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_AudioConfig_Proxy);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_AUDIO_CONFIG_PROXY_H_
diff --git a/ppapi/proxy/ppb_audio_proxy.cc b/ppapi/proxy/ppb_audio_proxy.cc
new file mode 100644
index 0000000..bb40693
--- /dev/null
+++ b/ppapi/proxy/ppb_audio_proxy.cc
@@ -0,0 +1,285 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppb_audio_proxy.h"
+
+#include "base/simple_thread.h"
+#include "ppapi/c/dev/ppb_audio_dev.h"
+#include "ppapi/c/dev/ppb_audio_trusted_dev.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/interface_id.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/audio_impl.h"
+
+namespace pp {
+namespace proxy {
+
+class Audio : public PluginResource, public pp::shared_impl::AudioImpl {
+ public:
+ Audio(PP_Resource config_id, PPB_Audio_Callback callback, void* user_data)
+ : config_(config_id) {
+ SetCallback(callback, user_data);
+ PluginDispatcher::Get()->plugin_resource_tracker()->AddRefResource(
+ config_);
+ }
+ virtual ~Audio() {
+ PluginDispatcher::Get()->plugin_resource_tracker()->ReleaseResource(
+ config_);
+ }
+
+ // Resource overrides.
+ virtual Audio* AsAudio() { return this; }
+
+ PP_Resource config() const { return config_; }
+
+ void StartPlayback(PP_Resource resource) {
+ if (playing())
+ return;
+ SetStartPlaybackState();
+ PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBAudio_StartOrStop(
+ INTERFACE_ID_PPB_AUDIO, resource, true));
+ }
+
+ void StopPlayback(PP_Resource resource) {
+ if (!playing())
+ return;
+ PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBAudio_StartOrStop(
+ INTERFACE_ID_PPB_AUDIO, resource, false));
+ SetStopPlaybackState();
+ }
+
+ private:
+ PP_Resource config_;
+
+ DISALLOW_COPY_AND_ASSIGN(Audio);
+};
+
+namespace {
+
+PP_Resource Create(PP_Instance instance_id,
+ PP_Resource config_id,
+ PPB_Audio_Callback callback,
+ void* user_data) {
+ PP_Resource result;
+ PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBAudio_Create(
+ INTERFACE_ID_PPB_AUDIO, instance_id, config_id, &result));
+ if (!result)
+ return 0;
+
+ linked_ptr<Audio> object(new Audio(config_id, callback, user_data));
+ PluginDispatcher::Get()->plugin_resource_tracker()->AddResource(
+ result, object);
+ return result;
+}
+
+PP_Bool IsAudio(PP_Resource resource) {
+ Audio* object = PluginResource::GetAs<Audio>(resource);
+ return BoolToPPBool(!!object);
+}
+
+PP_Resource GetCurrentConfiguration(PP_Resource audio_id) {
+ Audio* object = PluginResource::GetAs<Audio>(audio_id);
+ if (!object)
+ return 0;
+ PP_Resource result = object->config();
+ PluginDispatcher::Get()->plugin_resource_tracker()->AddRefResource(result);
+ return result;
+}
+
+PP_Bool StartPlayback(PP_Resource audio_id) {
+ Audio* object = PluginResource::GetAs<Audio>(audio_id);
+ if (!object)
+ return PP_FALSE;
+ object->StartPlayback(audio_id);
+ return PP_TRUE;
+}
+
+PP_Bool StopPlayback(PP_Resource audio_id) {
+ Audio* object = PluginResource::GetAs<Audio>(audio_id);
+ if (!object)
+ return PP_FALSE;
+ object->StopPlayback(audio_id);
+ return PP_TRUE;
+}
+
+const PPB_Audio_Dev audio_interface = {
+ &Create,
+ &IsAudio,
+ &GetCurrentConfiguration,
+ &StartPlayback,
+ &StopPlayback
+};
+
+} // namespace
+
+PPB_Audio_Proxy::PPB_Audio_Proxy(Dispatcher* dispatcher,
+ const void* target_interface)
+ : InterfaceProxy(dispatcher, target_interface),
+ callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+}
+
+PPB_Audio_Proxy::~PPB_Audio_Proxy() {
+}
+
+const void* PPB_Audio_Proxy::GetSourceInterface() const {
+ return &audio_interface;
+}
+
+InterfaceID PPB_Audio_Proxy::GetInterfaceId() const {
+ return INTERFACE_ID_PPB_AUDIO;
+}
+
+void PPB_Audio_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ IPC_BEGIN_MESSAGE_MAP(PPB_Audio_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBAudio_Create, OnMsgCreate)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBAudio_StartOrStop,
+ OnMsgStartOrStop)
+
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBAudio_NotifyAudioStreamCreated,
+ OnMsgNotifyAudioStreamCreated)
+ IPC_END_MESSAGE_MAP()
+}
+
+void PPB_Audio_Proxy::OnMsgCreate(PP_Instance instance_id,
+ PP_Resource config_id,
+ PP_Resource* result) {
+ const PPB_AudioTrusted_Dev* audio_trusted =
+ reinterpret_cast<const PPB_AudioTrusted_Dev*>(
+ dispatcher()->GetLocalInterface(PPB_AUDIO_TRUSTED_DEV_INTERFACE));
+ if (!audio_trusted) {
+ *result = 0;
+ return;
+ }
+
+ *result = audio_trusted->CreateTrusted(instance_id);
+ if (!result)
+ return;
+
+ CompletionCallback callback = callback_factory_.NewCallback(
+ &PPB_Audio_Proxy::AudioChannelConnected, *result);
+ int32_t open_error = audio_trusted->Open(*result, config_id,
+ callback.pp_completion_callback());
+ if (open_error != PP_ERROR_WOULDBLOCK)
+ callback.Run(open_error);
+}
+
+void PPB_Audio_Proxy::OnMsgStartOrStop(PP_Resource audio_id, bool play) {
+ if (play)
+ ppb_audio_target()->StartPlayback(audio_id);
+ else
+ ppb_audio_target()->StopPlayback(audio_id);
+}
+
+void PPB_Audio_Proxy::OnMsgNotifyAudioStreamCreated(
+ PP_Resource audio_id,
+ int32_t result_code,
+ IPC::PlatformFileForTransit socket_handle,
+ base::SharedMemoryHandle handle,
+ uint32_t length) {
+ Audio* object = PluginResource::GetAs<Audio>(audio_id);
+ if (!object || result_code != PP_OK) {
+ // The caller may still have given us these handles in the failure case.
+ // The easiest way to clean these up is to just put them in the objects
+ // and then close them. This failure case is not performance critical.
+ base::SyncSocket temp_socket(
+ IPC::PlatformFileForTransitToPlatformFile(socket_handle));
+ base::SharedMemory temp_mem(handle, false);
+ return;
+ }
+ object->SetStreamInfo(
+ handle, length, IPC::PlatformFileForTransitToPlatformFile(socket_handle));
+}
+
+void PPB_Audio_Proxy::AudioChannelConnected(int32_t result,
+ PP_Resource resource) {
+ IPC::PlatformFileForTransit socket_handle =
+ IPC::InvalidPlatformFileForTransit();
+#if defined(OS_WIN)
+ base::SharedMemoryHandle shared_memory = NULL;
+#elif defined(OS_POSIX)
+ base::SharedMemoryHandle shared_memory(-1, false);
+#else
+ #error Not implemented.
+#endif
+ uint32_t shared_memory_length = 0;
+
+ int32_t result_code = result;
+ if (result_code == PP_OK) {
+ result_code = GetAudioConnectedHandles(resource, &socket_handle,
+ &shared_memory,
+ &shared_memory_length);
+ }
+
+ // Send all the values, even on error. This simplifies some of our cleanup
+ // code since the handles will be in the other process and could be
+ // inconvenient to clean up. Our IPC code will automatically handle this for
+ // us, as long as the remote side always closes the handles it receives
+ // (in OnMsgNotifyAudioStreamCreated), even in the failure case.
+ dispatcher()->Send(new PpapiMsg_PPBAudio_NotifyAudioStreamCreated(
+ INTERFACE_ID_PPB_AUDIO, resource, result_code, shared_memory,
+ socket_handle, shared_memory_length));
+}
+
+int32_t PPB_Audio_Proxy::GetAudioConnectedHandles(
+ PP_Resource resource,
+ IPC::PlatformFileForTransit* foreign_socket_handle,
+ base::SharedMemoryHandle* foreign_shared_memory_handle,
+ uint32_t* shared_memory_length) {
+ // Get the trusted audio interface which will give us the handles.
+ const PPB_AudioTrusted_Dev* audio_trusted =
+ reinterpret_cast<const PPB_AudioTrusted_Dev*>(
+ dispatcher()->GetLocalInterface(PPB_AUDIO_TRUSTED_DEV_INTERFACE));
+ if (!audio_trusted)
+ return PP_ERROR_NOINTERFACE;
+
+ // Get the socket handle for signaling.
+ int32_t socket_handle;
+ int32_t result = audio_trusted->GetSyncSocket(resource, &socket_handle);
+ if (result != PP_OK)
+ return result;
+
+#if defined(OS_WIN)
+ // On Windows, duplicate the socket into the plugin process, this will
+ // automatically close the source handle.
+ ::DuplicateHandle(
+ GetCurrentProcess(),
+ reinterpret_cast<HANDLE>(static_cast<intptr_t>(socket_handle)),
+ dispatcher()->remote_process_handle(), foreign_socket_handle,
+ STANDARD_RIGHTS_REQUIRED | FILE_MAP_READ | FILE_MAP_WRITE,
+ FALSE, DUPLICATE_CLOSE_SOURCE);
+#else
+ // On Posix, the socket handle will be auto-duplicated when we send the
+ // FileDescriptor. Set AutoClose since we don't need the handle any more.
+ *foreign_socket_handle = base::FileDescriptor(socket_handle, true);
+#endif
+
+ // Get the shared memory for the buffer.
+ // TODO(brettw) remove the reinterpret cast when the interface is updated.
+ int shared_memory_handle;
+ result = audio_trusted->GetSharedMemory(resource, &shared_memory_handle,
+ shared_memory_length);
+ if (result != PP_OK)
+ return result;
+
+ base::SharedMemory shared_memory(
+#if defined(OS_WIN)
+ reinterpret_cast<HANDLE>(static_cast<intptr_t>(shared_memory_handle)),
+#else
+ base::FileDescriptor(shared_memory_handle, false),
+#endif
+ false);
+
+ // Duplicate the shared memory to the plugin process. This will automatically
+ // close the source handle.
+ if (!shared_memory.GiveToProcess(dispatcher()->remote_process_handle(),
+ foreign_shared_memory_handle))
+ return PP_ERROR_FAILED;
+
+ return PP_OK;
+}
+
+} // namespace proxy
+} // namespace pp
diff --git a/ppapi/proxy/ppb_audio_proxy.h b/ppapi/proxy/ppb_audio_proxy.h
new file mode 100644
index 0000000..a6d2738
--- /dev/null
+++ b/ppapi/proxy/ppb_audio_proxy.h
@@ -0,0 +1,78 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPB_AUDIO_PROXY_H_
+#define PPAPI_PROXY_PPB_AUDIO_PROXY_H_
+
+#include "base/basictypes.h"
+#include "base/shared_memory.h"
+#include "base/sync_socket.h"
+#include "ipc/ipc_platform_file.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/cpp/completion_callback.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h"
+
+struct PPB_Audio_Dev;
+
+namespace pp {
+namespace proxy {
+
+class PPB_Audio_Proxy : public InterfaceProxy {
+ public:
+ PPB_Audio_Proxy(Dispatcher* dispatcher, const void* target_interface);
+ virtual ~PPB_Audio_Proxy();
+
+ const PPB_Audio_Dev* ppb_audio_target() const {
+ return static_cast<const PPB_Audio_Dev*>(target_interface());
+ }
+
+ // InterfaceProxy implementation.
+ virtual const void* GetSourceInterface() const;
+ virtual InterfaceID GetInterfaceId() const;
+ virtual void OnMessageReceived(const IPC::Message& msg);
+
+ private:
+ // Plugin->renderer message handlers.
+ void OnMsgCreate(PP_Instance instance_id,
+ PP_Resource config_id,
+ PP_Resource* result);
+ void OnMsgStartOrStop(PP_Resource audio_id, bool play);
+
+ // Renderer->plugin message handlers.
+ void OnMsgNotifyAudioStreamCreated(
+ PP_Resource audio_id,
+ int32_t result_code,
+ IPC::PlatformFileForTransit socket_handle,
+ base::SharedMemoryHandle shared_memory_handle,
+ uint32_t shared_memory_length);
+
+ void AudioChannelConnected(int32_t result, PP_Resource 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(
+ PP_Resource resource,
+ IPC::PlatformFileForTransit* foreign_socket_handle,
+ base::SharedMemoryHandle* foreign_shared_memory_handle,
+ uint32_t* shared_memory_length);
+
+ CompletionCallbackFactory<PPB_Audio_Proxy,
+ ProxyNonThreadSafeRefCount> callback_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_Audio_Proxy);
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PPB_AUDIO_PROXY_H_