1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/pepper/pepper_audio_input_host.h"
7 #include "base/logging.h"
8 #include "build/build_config.h"
9 #include "content/renderer/pepper/pepper_media_device_manager.h"
10 #include "content/renderer/pepper/pepper_platform_audio_input.h"
11 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
12 #include "content/renderer/pepper/renderer_ppapi_host_impl.h"
13 #include "content/renderer/render_frame_impl.h"
14 #include "ipc/ipc_message.h"
15 #include "ppapi/c/pp_errors.h"
16 #include "ppapi/host/dispatch_host_message.h"
17 #include "ppapi/host/ppapi_host.h"
18 #include "ppapi/proxy/ppapi_messages.h"
19 #include "ppapi/proxy/serialized_structs.h"
25 base::PlatformFile
ConvertSyncSocketHandle(const base::SyncSocket
& socket
) {
26 return socket
.handle();
29 base::PlatformFile
ConvertSharedMemoryHandle(
30 const base::SharedMemory
& shared_memory
) {
32 return shared_memory
.handle().fd
;
34 return shared_memory
.handle();
36 #error "Platform not supported."
42 PepperAudioInputHost::PepperAudioInputHost(RendererPpapiHostImpl
* host
,
45 : ResourceHost(host
->GetPpapiHost(), instance
, resource
),
46 renderer_ppapi_host_(host
),
48 enumeration_helper_(this,
49 PepperMediaDeviceManager::GetForRenderFrame(
50 host
->GetRenderFrameForInstance(pp_instance())),
51 PP_DEVICETYPE_DEV_AUDIOCAPTURE
,
52 host
->GetDocumentURL(instance
)) {}
54 PepperAudioInputHost::~PepperAudioInputHost() { Close(); }
56 int32_t PepperAudioInputHost::OnResourceMessageReceived(
57 const IPC::Message
& msg
,
58 ppapi::host::HostMessageContext
* context
) {
59 int32_t result
= PP_ERROR_FAILED
;
60 if (enumeration_helper_
.HandleResourceMessage(msg
, context
, &result
))
63 PPAPI_BEGIN_MESSAGE_MAP(PepperAudioInputHost
, msg
)
64 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_AudioInput_Open
, OnOpen
)
65 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_AudioInput_StartOrStop
,
67 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_AudioInput_Close
, OnClose
)
68 PPAPI_END_MESSAGE_MAP()
69 return PP_ERROR_FAILED
;
72 void PepperAudioInputHost::StreamCreated(
73 base::SharedMemoryHandle shared_memory_handle
,
74 size_t shared_memory_size
,
75 base::SyncSocket::Handle socket
) {
76 OnOpenComplete(PP_OK
, shared_memory_handle
, shared_memory_size
, socket
);
79 void PepperAudioInputHost::StreamCreationFailed() {
80 OnOpenComplete(PP_ERROR_FAILED
,
81 base::SharedMemory::NULLHandle(),
83 base::SyncSocket::kInvalidHandle
);
86 int32_t PepperAudioInputHost::OnOpen(ppapi::host::HostMessageContext
* context
,
87 const std::string
& device_id
,
88 PP_AudioSampleRate sample_rate
,
89 uint32_t sample_frame_count
) {
90 if (open_context_
.is_valid())
91 return PP_ERROR_INPROGRESS
;
93 return PP_ERROR_FAILED
;
95 GURL document_url
= renderer_ppapi_host_
->GetDocumentURL(pp_instance());
96 if (!document_url
.is_valid())
97 return PP_ERROR_FAILED
;
99 // When it is done, we'll get called back on StreamCreated() or
100 // StreamCreationFailed().
101 audio_input_
= PepperPlatformAudioInput::Create(
102 renderer_ppapi_host_
->GetRenderFrameForInstance(pp_instance())->
106 static_cast<int>(sample_rate
),
107 static_cast<int>(sample_frame_count
),
110 open_context_
= context
->MakeReplyMessageContext();
111 return PP_OK_COMPLETIONPENDING
;
113 return PP_ERROR_FAILED
;
117 int32_t PepperAudioInputHost::OnStartOrStop(
118 ppapi::host::HostMessageContext
* /* context */,
121 return PP_ERROR_FAILED
;
123 audio_input_
->StartCapture();
125 audio_input_
->StopCapture();
129 int32_t PepperAudioInputHost::OnClose(
130 ppapi::host::HostMessageContext
* /* context */) {
135 void PepperAudioInputHost::OnOpenComplete(
137 base::SharedMemoryHandle shared_memory_handle
,
138 size_t shared_memory_size
,
139 base::SyncSocket::Handle socket_handle
) {
140 // Make sure the handles are cleaned up.
141 base::SyncSocket
scoped_socket(socket_handle
);
142 base::SharedMemory
scoped_shared_memory(shared_memory_handle
, false);
144 if (!open_context_
.is_valid()) {
149 ppapi::proxy::SerializedHandle
serialized_socket_handle(
150 ppapi::proxy::SerializedHandle::SOCKET
);
151 ppapi::proxy::SerializedHandle
serialized_shared_memory_handle(
152 ppapi::proxy::SerializedHandle::SHARED_MEMORY
);
154 if (result
== PP_OK
) {
155 IPC::PlatformFileForTransit temp_socket
=
156 IPC::InvalidPlatformFileForTransit();
157 base::SharedMemoryHandle temp_shmem
= base::SharedMemory::NULLHandle();
158 result
= GetRemoteHandles(
159 scoped_socket
, scoped_shared_memory
, &temp_socket
, &temp_shmem
);
161 serialized_socket_handle
.set_socket(temp_socket
);
162 serialized_shared_memory_handle
.set_shmem(temp_shmem
, shared_memory_size
);
165 // Send all the values, even on error. This simplifies some of our cleanup
166 // code since the handles will be in the other process and could be
167 // inconvenient to clean up. Our IPC code will automatically handle this for
168 // us, as long as the remote side always closes the handles it receives, even
169 // in the failure case.
170 open_context_
.params
.AppendHandle(serialized_socket_handle
);
171 open_context_
.params
.AppendHandle(serialized_shared_memory_handle
);
172 SendOpenReply(result
);
175 int32_t PepperAudioInputHost::GetRemoteHandles(
176 const base::SyncSocket
& socket
,
177 const base::SharedMemory
& shared_memory
,
178 IPC::PlatformFileForTransit
* remote_socket_handle
,
179 base::SharedMemoryHandle
* remote_shared_memory_handle
) {
180 *remote_socket_handle
= renderer_ppapi_host_
->ShareHandleWithRemote(
181 ConvertSyncSocketHandle(socket
), false);
182 if (*remote_socket_handle
== IPC::InvalidPlatformFileForTransit())
183 return PP_ERROR_FAILED
;
185 *remote_shared_memory_handle
= renderer_ppapi_host_
->ShareHandleWithRemote(
186 ConvertSharedMemoryHandle(shared_memory
), false);
187 if (*remote_shared_memory_handle
== IPC::InvalidPlatformFileForTransit())
188 return PP_ERROR_FAILED
;
193 void PepperAudioInputHost::Close() {
197 audio_input_
->ShutDown();
200 if (open_context_
.is_valid())
201 SendOpenReply(PP_ERROR_ABORTED
);
204 void PepperAudioInputHost::SendOpenReply(int32_t result
) {
205 open_context_
.params
.set_result(result
);
206 host()->SendReply(open_context_
, PpapiPluginMsg_AudioInput_OpenReply());
207 open_context_
= ppapi::host::ReplyMessageContext();
210 } // namespace content