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/common/pepper_file_util.h"
10 #include "content/renderer/pepper/pepper_media_device_manager.h"
11 #include "content/renderer/pepper/pepper_platform_audio_input.h"
12 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
13 #include "content/renderer/pepper/renderer_ppapi_host_impl.h"
14 #include "content/renderer/render_frame_impl.h"
15 #include "ipc/ipc_message.h"
16 #include "ppapi/c/pp_errors.h"
17 #include "ppapi/host/dispatch_host_message.h"
18 #include "ppapi/host/ppapi_host.h"
19 #include "ppapi/proxy/ppapi_messages.h"
20 #include "ppapi/proxy/serialized_structs.h"
26 base::PlatformFile
ConvertSyncSocketHandle(const base::SyncSocket
& socket
) {
27 return socket
.handle();
32 PepperAudioInputHost::PepperAudioInputHost(RendererPpapiHostImpl
* host
,
35 : ResourceHost(host
->GetPpapiHost(), instance
, resource
),
36 renderer_ppapi_host_(host
),
38 enumeration_helper_(this,
39 PepperMediaDeviceManager::GetForRenderFrame(
40 host
->GetRenderFrameForInstance(pp_instance())),
41 PP_DEVICETYPE_DEV_AUDIOCAPTURE
,
42 host
->GetDocumentURL(instance
)) {}
44 PepperAudioInputHost::~PepperAudioInputHost() { Close(); }
46 int32_t PepperAudioInputHost::OnResourceMessageReceived(
47 const IPC::Message
& msg
,
48 ppapi::host::HostMessageContext
* context
) {
49 int32_t result
= PP_ERROR_FAILED
;
50 if (enumeration_helper_
.HandleResourceMessage(msg
, context
, &result
))
53 PPAPI_BEGIN_MESSAGE_MAP(PepperAudioInputHost
, msg
)
54 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_AudioInput_Open
, OnOpen
)
55 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_AudioInput_StartOrStop
,
57 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_AudioInput_Close
, OnClose
)
58 PPAPI_END_MESSAGE_MAP()
59 return PP_ERROR_FAILED
;
62 void PepperAudioInputHost::StreamCreated(
63 base::SharedMemoryHandle shared_memory_handle
,
64 size_t shared_memory_size
,
65 base::SyncSocket::Handle socket
) {
66 OnOpenComplete(PP_OK
, shared_memory_handle
, shared_memory_size
, socket
);
69 void PepperAudioInputHost::StreamCreationFailed() {
70 OnOpenComplete(PP_ERROR_FAILED
,
71 base::SharedMemory::NULLHandle(),
73 base::SyncSocket::kInvalidHandle
);
76 int32_t PepperAudioInputHost::OnOpen(ppapi::host::HostMessageContext
* context
,
77 const std::string
& device_id
,
78 PP_AudioSampleRate sample_rate
,
79 uint32_t sample_frame_count
) {
80 if (open_context_
.is_valid())
81 return PP_ERROR_INPROGRESS
;
83 return PP_ERROR_FAILED
;
85 GURL document_url
= renderer_ppapi_host_
->GetDocumentURL(pp_instance());
86 if (!document_url
.is_valid())
87 return PP_ERROR_FAILED
;
89 // When it is done, we'll get called back on StreamCreated() or
90 // StreamCreationFailed().
91 audio_input_
= PepperPlatformAudioInput::Create(
92 renderer_ppapi_host_
->GetRenderFrameForInstance(pp_instance())->
96 static_cast<int>(sample_rate
),
97 static_cast<int>(sample_frame_count
),
100 open_context_
= context
->MakeReplyMessageContext();
101 return PP_OK_COMPLETIONPENDING
;
103 return PP_ERROR_FAILED
;
107 int32_t PepperAudioInputHost::OnStartOrStop(
108 ppapi::host::HostMessageContext
* /* context */,
111 return PP_ERROR_FAILED
;
113 audio_input_
->StartCapture();
115 audio_input_
->StopCapture();
119 int32_t PepperAudioInputHost::OnClose(
120 ppapi::host::HostMessageContext
* /* context */) {
125 void PepperAudioInputHost::OnOpenComplete(
127 base::SharedMemoryHandle shared_memory_handle
,
128 size_t shared_memory_size
,
129 base::SyncSocket::Handle socket_handle
) {
130 // Make sure the handles are cleaned up.
131 base::SyncSocket
scoped_socket(socket_handle
);
132 base::SharedMemory
scoped_shared_memory(shared_memory_handle
, false);
134 if (!open_context_
.is_valid()) {
139 ppapi::proxy::SerializedHandle
serialized_socket_handle(
140 ppapi::proxy::SerializedHandle::SOCKET
);
141 ppapi::proxy::SerializedHandle
serialized_shared_memory_handle(
142 ppapi::proxy::SerializedHandle::SHARED_MEMORY
);
144 if (result
== PP_OK
) {
145 IPC::PlatformFileForTransit temp_socket
=
146 IPC::InvalidPlatformFileForTransit();
147 base::SharedMemoryHandle temp_shmem
= base::SharedMemory::NULLHandle();
148 result
= GetRemoteHandles(
149 scoped_socket
, scoped_shared_memory
, &temp_socket
, &temp_shmem
);
151 serialized_socket_handle
.set_socket(temp_socket
);
152 serialized_shared_memory_handle
.set_shmem(temp_shmem
, shared_memory_size
);
155 // Send all the values, even on error. This simplifies some of our cleanup
156 // code since the handles will be in the other process and could be
157 // inconvenient to clean up. Our IPC code will automatically handle this for
158 // us, as long as the remote side always closes the handles it receives, even
159 // in the failure case.
160 open_context_
.params
.AppendHandle(serialized_socket_handle
);
161 open_context_
.params
.AppendHandle(serialized_shared_memory_handle
);
162 SendOpenReply(result
);
165 int32_t PepperAudioInputHost::GetRemoteHandles(
166 const base::SyncSocket
& socket
,
167 const base::SharedMemory
& shared_memory
,
168 IPC::PlatformFileForTransit
* remote_socket_handle
,
169 base::SharedMemoryHandle
* remote_shared_memory_handle
) {
170 *remote_socket_handle
= renderer_ppapi_host_
->ShareHandleWithRemote(
171 ConvertSyncSocketHandle(socket
), false);
172 if (*remote_socket_handle
== IPC::InvalidPlatformFileForTransit())
173 return PP_ERROR_FAILED
;
175 *remote_shared_memory_handle
=
176 renderer_ppapi_host_
->ShareSharedMemoryHandleWithRemote(
177 shared_memory
.handle());
178 if (!base::SharedMemory::IsHandleValid(*remote_shared_memory_handle
))
179 return PP_ERROR_FAILED
;
184 void PepperAudioInputHost::Close() {
188 audio_input_
->ShutDown();
191 if (open_context_
.is_valid())
192 SendOpenReply(PP_ERROR_ABORTED
);
195 void PepperAudioInputHost::SendOpenReply(int32_t result
) {
196 open_context_
.params
.set_result(result
);
197 host()->SendReply(open_context_
, PpapiPluginMsg_AudioInput_OpenReply());
198 open_context_
= ppapi::host::ReplyMessageContext();
201 } // namespace content