[content shell] implement testRunner.overridePreference
[chromium-blink-merge.git] / content / renderer / pepper / pepper_audio_input_host.cc
blob89a08f1bc8daa11bb3230eb5faad2f7a7eb2a3e9
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/public/renderer/renderer_ppapi_host.h"
10 #include "ipc/ipc_message.h"
11 #include "media/audio/shared_memory_util.h"
12 #include "ppapi/c/pp_errors.h"
13 #include "ppapi/host/dispatch_host_message.h"
14 #include "ppapi/host/ppapi_host.h"
15 #include "ppapi/proxy/ppapi_messages.h"
16 #include "ppapi/proxy/serialized_structs.h"
17 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
19 namespace content {
21 namespace {
23 base::PlatformFile ConvertSyncSocketHandle(const base::SyncSocket& socket) {
24 return socket.handle();
27 base::PlatformFile ConvertSharedMemoryHandle(
28 const base::SharedMemory& shared_memory) {
29 #if defined(OS_POSIX)
30 return shared_memory.handle().fd;
31 #elif defined(OS_WIN)
32 return shared_memory.handle();
33 #else
34 #error "Platform not supported."
35 #endif
38 } // namespace
40 PepperAudioInputHost::PepperAudioInputHost(
41 RendererPpapiHost* host,
42 PP_Instance instance,
43 PP_Resource resource)
44 : ResourceHost(host->GetPpapiHost(), instance, resource),
45 renderer_ppapi_host_(host),
46 audio_input_(NULL),
47 ALLOW_THIS_IN_INITIALIZER_LIST(
48 enumeration_helper_(this, this, PP_DEVICETYPE_DEV_AUDIOCAPTURE)) {
51 PepperAudioInputHost::~PepperAudioInputHost() {
52 Close();
55 int32_t PepperAudioInputHost::OnResourceMessageReceived(
56 const IPC::Message& msg,
57 ppapi::host::HostMessageContext* context) {
58 int32_t result = PP_ERROR_FAILED;
59 if (enumeration_helper_.HandleResourceMessage(msg, context, &result))
60 return result;
62 IPC_BEGIN_MESSAGE_MAP(PepperAudioInputHost, msg)
63 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_AudioInput_Open, OnMsgOpen)
64 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_AudioInput_StartOrStop,
65 OnMsgStartOrStop);
66 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_AudioInput_Close,
67 OnMsgClose);
68 IPC_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, base::SharedMemory::NULLHandle(), 0,
81 base::SyncSocket::kInvalidHandle);
84 webkit::ppapi::PluginDelegate* PepperAudioInputHost::GetPluginDelegate() {
85 webkit::ppapi::PluginInstance* instance =
86 renderer_ppapi_host_->GetPluginInstance(pp_instance());
87 if (instance)
88 return instance->delegate();
89 return NULL;
92 int32_t PepperAudioInputHost::OnMsgOpen(
93 ppapi::host::HostMessageContext* context,
94 const std::string& device_id,
95 PP_AudioSampleRate sample_rate,
96 uint32_t sample_frame_count) {
97 if (open_context_.get())
98 return PP_ERROR_INPROGRESS;
99 if (audio_input_)
100 return PP_ERROR_FAILED;
102 webkit::ppapi::PluginDelegate* plugin_delegate = GetPluginDelegate();
103 if (!plugin_delegate)
104 return PP_ERROR_FAILED;
106 // When it is done, we'll get called back on StreamCreated() or
107 // StreamCreationFailed().
108 audio_input_ = plugin_delegate->CreateAudioInput(
109 device_id, sample_rate, sample_frame_count, this);
110 if (audio_input_) {
111 open_context_.reset(new ppapi::host::ReplyMessageContext(
112 context->MakeReplyMessageContext()));
113 return PP_OK_COMPLETIONPENDING;
114 } else {
115 return PP_ERROR_FAILED;
119 int32_t PepperAudioInputHost::OnMsgStartOrStop(
120 ppapi::host::HostMessageContext* /* context */,
121 bool capture) {
122 if (!audio_input_)
123 return PP_ERROR_FAILED;
124 if (capture)
125 audio_input_->StartCapture();
126 else
127 audio_input_->StopCapture();
128 return PP_OK;
131 int32_t PepperAudioInputHost::OnMsgClose(
132 ppapi::host::HostMessageContext* /* context */) {
133 Close();
134 return PP_OK;
137 void PepperAudioInputHost::OnOpenComplete(
138 int32_t result,
139 base::SharedMemoryHandle shared_memory_handle,
140 size_t shared_memory_size,
141 base::SyncSocket::Handle socket_handle) {
142 // Make sure the handles are cleaned up.
143 base::SyncSocket scoped_socket(socket_handle);
144 base::SharedMemory scoped_shared_memory(shared_memory_handle, false);
146 if (!open_context_.get()) {
147 NOTREACHED();
148 return;
151 ppapi::proxy::SerializedHandle serialized_socket_handle(
152 ppapi::proxy::SerializedHandle::SOCKET);
153 ppapi::proxy::SerializedHandle serialized_shared_memory_handle(
154 ppapi::proxy::SerializedHandle::SHARED_MEMORY);
156 if (result == PP_OK) {
157 IPC::PlatformFileForTransit temp_socket =
158 IPC::InvalidPlatformFileForTransit();
159 base::SharedMemoryHandle temp_shmem = base::SharedMemory::NULLHandle();
160 result = GetRemoteHandles(
161 scoped_socket, scoped_shared_memory, &temp_socket, &temp_shmem);
163 serialized_socket_handle.set_socket(temp_socket);
164 // Note that we must call TotalSharedMemorySizeInBytes() because extra space
165 // in shared memory is allocated for book-keeping, so the actual size of the
166 // shared memory buffer is larger than |shared_memory_size|. When sending to
167 // NaCl, NaClIPCAdapter expects this size to match the size of the full
168 // shared memory buffer.
169 serialized_shared_memory_handle.set_shmem(
170 temp_shmem, media::TotalSharedMemorySizeInBytes(shared_memory_size));
173 // Send all the values, even on error. This simplifies some of our cleanup
174 // code since the handles will be in the other process and could be
175 // inconvenient to clean up. Our IPC code will automatically handle this for
176 // us, as long as the remote side always closes the handles it receives, even
177 // in the failure case.
178 open_context_->params.set_result(result);
179 open_context_->params.AppendHandle(serialized_socket_handle);
180 open_context_->params.AppendHandle(serialized_shared_memory_handle);
182 host()->SendReply(*open_context_, PpapiPluginMsg_AudioInput_OpenReply());
183 open_context_.reset();
186 int32_t PepperAudioInputHost::GetRemoteHandles(
187 const base::SyncSocket& socket,
188 const base::SharedMemory& shared_memory,
189 IPC::PlatformFileForTransit* remote_socket_handle,
190 base::SharedMemoryHandle* remote_shared_memory_handle) {
191 *remote_socket_handle = renderer_ppapi_host_->ShareHandleWithRemote(
192 ConvertSyncSocketHandle(socket), false);
193 if (*remote_socket_handle == IPC::InvalidPlatformFileForTransit())
194 return PP_ERROR_FAILED;
196 *remote_shared_memory_handle = renderer_ppapi_host_->ShareHandleWithRemote(
197 ConvertSharedMemoryHandle(shared_memory), false);
198 if (*remote_shared_memory_handle == IPC::InvalidPlatformFileForTransit())
199 return PP_ERROR_FAILED;
201 return PP_OK;
204 void PepperAudioInputHost::Close() {
205 if (!audio_input_)
206 return;
208 audio_input_->ShutDown();
209 audio_input_ = NULL;
211 if (open_context_.get()) {
212 open_context_->params.set_result(PP_ERROR_ABORTED);
213 host()->SendReply(*open_context_, PpapiPluginMsg_AudioInput_OpenReply());
214 open_context_.reset();
218 } // namespace content