OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ppapi/proxy/ppb_audio_proxy.h" | 5 #include "ppapi/proxy/ppb_audio_proxy.h" |
6 | 6 |
7 #include "base/threading/simple_thread.h" | 7 #include "base/threading/simple_thread.h" |
8 #include "ppapi/c/pp_errors.h" | 8 #include "ppapi/c/pp_errors.h" |
9 #include "ppapi/c/ppb_audio.h" | 9 #include "ppapi/c/ppb_audio.h" |
10 #include "ppapi/c/trusted/ppb_audio_trusted.h" | 10 #include "ppapi/c/trusted/ppb_audio_trusted.h" |
11 #include "ppapi/proxy/interface_id.h" | 11 #include "ppapi/proxy/interface_id.h" |
12 #include "ppapi/proxy/plugin_dispatcher.h" | 12 #include "ppapi/proxy/plugin_dispatcher.h" |
13 #include "ppapi/proxy/plugin_resource.h" | 13 #include "ppapi/proxy/plugin_resource.h" |
14 #include "ppapi/proxy/ppapi_messages.h" | 14 #include "ppapi/proxy/ppapi_messages.h" |
15 #include "ppapi/shared_impl/audio_impl.h" | 15 #include "ppapi/shared_impl/audio_impl.h" |
16 | 16 |
17 namespace pp { | 17 namespace pp { |
18 namespace proxy { | 18 namespace proxy { |
19 | 19 |
20 class Audio : public PluginResource, public pp::shared_impl::AudioImpl { | 20 class Audio : public PluginResource, public pp::shared_impl::AudioImpl { |
21 public: | 21 public: |
22 Audio(PP_Instance instance, | 22 Audio(PP_Instance instance, |
| 23 SerializedResource audio_id, |
23 PP_Resource config_id, | 24 PP_Resource config_id, |
24 PPB_Audio_Callback callback, | 25 PPB_Audio_Callback callback, |
25 void* user_data) | 26 void* user_data) |
26 : PluginResource(instance), | 27 : PluginResource(instance, audio_id), |
27 config_(config_id) { | 28 config_(config_id) { |
28 SetCallback(callback, user_data); | 29 SetCallback(callback, user_data); |
29 PluginResourceTracker::GetInstance()->AddRefResource(config_); | 30 PluginResourceTracker::GetInstance()->AddRefResource(config_); |
30 } | 31 } |
31 virtual ~Audio() { | 32 virtual ~Audio() { |
32 PluginResourceTracker::GetInstance()->ReleaseResource(config_); | 33 PluginResourceTracker::GetInstance()->ReleaseResource(config_); |
33 } | 34 } |
34 | 35 |
35 // Resource overrides. | 36 // Resource overrides. |
36 virtual Audio* AsAudio() { return this; } | 37 virtual Audio* AsAudio() { return this; } |
37 | 38 |
38 PP_Resource config() const { return config_; } | 39 PP_Resource config() const { return config_; } |
39 | 40 |
40 void StartPlayback(PP_Resource resource) { | 41 void StartPlayback(PP_Resource resource) { |
41 if (playing()) | 42 if (playing()) |
42 return; | 43 return; |
43 SetStartPlaybackState(); | 44 SetStartPlaybackState(); |
44 PluginDispatcher::GetForInstance(instance())->Send( | 45 PluginDispatcher::GetForInstance(instance())->Send( |
45 new PpapiHostMsg_PPBAudio_StartOrStop( | 46 new PpapiHostMsg_PPBAudio_StartOrStop( |
46 INTERFACE_ID_PPB_AUDIO, resource, true)); | 47 INTERFACE_ID_PPB_AUDIO, host_resource(), true)); |
47 } | 48 } |
48 | 49 |
49 void StopPlayback(PP_Resource resource) { | 50 void StopPlayback(PP_Resource resource) { |
50 if (!playing()) | 51 if (!playing()) |
51 return; | 52 return; |
52 PluginDispatcher::GetForInstance(instance())->Send( | 53 PluginDispatcher::GetForInstance(instance())->Send( |
53 new PpapiHostMsg_PPBAudio_StartOrStop( | 54 new PpapiHostMsg_PPBAudio_StartOrStop( |
54 INTERFACE_ID_PPB_AUDIO, resource, false)); | 55 INTERFACE_ID_PPB_AUDIO, host_resource(), false)); |
55 SetStopPlaybackState(); | 56 SetStopPlaybackState(); |
56 } | 57 } |
57 | 58 |
58 private: | 59 private: |
59 PP_Resource config_; | 60 PP_Resource config_; |
60 | 61 |
61 DISALLOW_COPY_AND_ASSIGN(Audio); | 62 DISALLOW_COPY_AND_ASSIGN(Audio); |
62 }; | 63 }; |
63 | 64 |
| 65 // Closure data for the AudioChannelConnected callback. |
| 66 struct AudioChannelConnectedTracking { |
| 67 PP_Instance instance; |
| 68 SerializedResource resource; |
| 69 }; |
| 70 |
64 namespace { | 71 namespace { |
65 | 72 |
66 PP_Resource Create(PP_Instance instance_id, | 73 PP_Resource Create(PP_Instance instance_id, |
67 PP_Resource config_id, | 74 PP_Resource config_id, |
68 PPB_Audio_Callback callback, | 75 PPB_Audio_Callback callback, |
69 void* user_data) { | 76 void* user_data) { |
70 PP_Resource result; | 77 PluginResource* config = PluginResourceTracker::GetInstance()-> |
71 PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBAudio_Create( | 78 GetResourceObject(config_id); |
72 INTERFACE_ID_PPB_AUDIO, instance_id, config_id, &result)); | 79 if (!config) |
73 if (!result) | |
74 return 0; | 80 return 0; |
75 | 81 |
76 linked_ptr<Audio> object(new Audio(instance_id, config_id, | 82 SerializedResource result; |
| 83 PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBAudio_Create( |
| 84 INTERFACE_ID_PPB_AUDIO, instance_id, config->host_resource(), &result)); |
| 85 if (result.is_null()) |
| 86 return 0; |
| 87 |
| 88 linked_ptr<Audio> object(new Audio(instance_id, result, config_id, |
77 callback, user_data)); | 89 callback, user_data)); |
78 PluginResourceTracker::GetInstance()->AddResource(result, object); | 90 return PluginResourceTracker::GetInstance()->AddResource(object); |
79 return result; | |
80 } | 91 } |
81 | 92 |
82 PP_Bool IsAudio(PP_Resource resource) { | 93 PP_Bool IsAudio(PP_Resource resource) { |
83 Audio* object = PluginResource::GetAs<Audio>(resource); | 94 Audio* object = PluginResource::GetAs<Audio>(resource); |
84 return BoolToPPBool(!!object); | 95 return BoolToPPBool(!!object); |
85 } | 96 } |
86 | 97 |
87 PP_Resource GetCurrentConfiguration(PP_Resource audio_id) { | 98 PP_Resource GetCurrentConfiguration(PP_Resource audio_id) { |
88 Audio* object = PluginResource::GetAs<Audio>(audio_id); | 99 Audio* object = PluginResource::GetAs<Audio>(audio_id); |
89 if (!object) | 100 if (!object) |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBAudio_StartOrStop, | 154 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBAudio_StartOrStop, |
144 OnMsgStartOrStop) | 155 OnMsgStartOrStop) |
145 IPC_MESSAGE_HANDLER(PpapiMsg_PPBAudio_NotifyAudioStreamCreated, | 156 IPC_MESSAGE_HANDLER(PpapiMsg_PPBAudio_NotifyAudioStreamCreated, |
146 OnMsgNotifyAudioStreamCreated) | 157 OnMsgNotifyAudioStreamCreated) |
147 IPC_MESSAGE_UNHANDLED(handled = false) | 158 IPC_MESSAGE_UNHANDLED(handled = false) |
148 IPC_END_MESSAGE_MAP() | 159 IPC_END_MESSAGE_MAP() |
149 return handled; | 160 return handled; |
150 } | 161 } |
151 | 162 |
152 void PPB_Audio_Proxy::OnMsgCreate(PP_Instance instance_id, | 163 void PPB_Audio_Proxy::OnMsgCreate(PP_Instance instance_id, |
153 PP_Resource config_id, | 164 SerializedResource config_id, |
154 PP_Resource* result) { | 165 SerializedResource* result) { |
155 const PPB_AudioTrusted* audio_trusted = | 166 const PPB_AudioTrusted* audio_trusted = |
156 reinterpret_cast<const PPB_AudioTrusted*>( | 167 reinterpret_cast<const PPB_AudioTrusted*>( |
157 dispatcher()->GetLocalInterface(PPB_AUDIO_TRUSTED_INTERFACE)); | 168 dispatcher()->GetLocalInterface(PPB_AUDIO_TRUSTED_INTERFACE)); |
158 if (!audio_trusted) { | 169 if (!audio_trusted) |
159 *result = 0; | |
160 return; | |
161 } | |
162 | |
163 *result = audio_trusted->CreateTrusted(instance_id); | |
164 if (!result) | |
165 return; | 170 return; |
166 | 171 |
| 172 result->set_host_resource(audio_trusted->CreateTrusted(instance_id)); |
| 173 if (result->is_null()) |
| 174 return; |
| 175 |
| 176 // The callback will be in charge of deleting this pointer. |
| 177 AudioChannelConnectedTracking* tracking = new AudioChannelConnectedTracking; |
| 178 tracking->instance = instance_id; |
| 179 tracking->resource = *result; |
167 CompletionCallback callback = callback_factory_.NewCallback( | 180 CompletionCallback callback = callback_factory_.NewCallback( |
168 &PPB_Audio_Proxy::AudioChannelConnected, *result); | 181 &PPB_Audio_Proxy::AudioChannelConnected, tracking); |
169 int32_t open_error = audio_trusted->Open(*result, config_id, | 182 int32_t open_error = audio_trusted->Open(result->host_resource(), |
| 183 config_id.host_resource(), |
170 callback.pp_completion_callback()); | 184 callback.pp_completion_callback()); |
171 if (open_error != PP_ERROR_WOULDBLOCK) | 185 if (open_error != PP_ERROR_WOULDBLOCK) |
172 callback.Run(open_error); | 186 callback.Run(open_error); |
173 } | 187 } |
174 | 188 |
175 void PPB_Audio_Proxy::OnMsgStartOrStop(PP_Resource audio_id, bool play) { | 189 void PPB_Audio_Proxy::OnMsgStartOrStop(SerializedResource audio_id, bool play) { |
176 if (play) | 190 if (play) |
177 ppb_audio_target()->StartPlayback(audio_id); | 191 ppb_audio_target()->StartPlayback(audio_id.host_resource()); |
178 else | 192 else |
179 ppb_audio_target()->StopPlayback(audio_id); | 193 ppb_audio_target()->StopPlayback(audio_id.host_resource()); |
180 } | 194 } |
181 | 195 |
| 196 // Processed in the plugin (message from host). |
182 void PPB_Audio_Proxy::OnMsgNotifyAudioStreamCreated( | 197 void PPB_Audio_Proxy::OnMsgNotifyAudioStreamCreated( |
183 PP_Resource audio_id, | 198 const PPBAudio_NotifyAudioStreamCreated_Params& params) { |
184 int32_t result_code, | 199 PP_Resource plugin_resource = |
185 IPC::PlatformFileForTransit socket_handle, | 200 PluginResourceTracker::GetInstance()->PluginResourceForHostResource( |
186 base::SharedMemoryHandle handle, | 201 params.instance, params.audio_id); |
187 uint32_t length) { | 202 Audio* object = plugin_resource ? |
188 Audio* object = PluginResource::GetAs<Audio>(audio_id); | 203 PluginResource::GetAs<Audio>(plugin_resource) : NULL; |
189 if (!object || result_code != PP_OK) { | 204 if (!object || params.result_code != PP_OK) { |
190 // The caller may still have given us these handles in the failure case. | 205 // The caller may still have given us these handles in the failure case. |
191 // The easiest way to clean these up is to just put them in the objects | 206 // The easiest way to clean these up is to just put them in the objects |
192 // and then close them. This failure case is not performance critical. | 207 // and then close them. This failure case is not performance critical. |
193 base::SyncSocket temp_socket( | 208 base::SyncSocket temp_socket( |
194 IPC::PlatformFileForTransitToPlatformFile(socket_handle)); | 209 IPC::PlatformFileForTransitToPlatformFile(params.socket_handle)); |
195 base::SharedMemory temp_mem(handle, false); | 210 base::SharedMemory temp_mem(params.handle, false); |
196 return; | 211 return; |
197 } | 212 } |
198 object->SetStreamInfo( | 213 object->SetStreamInfo( |
199 handle, length, IPC::PlatformFileForTransitToPlatformFile(socket_handle)); | 214 params.handle, params.length, |
| 215 IPC::PlatformFileForTransitToPlatformFile(params.socket_handle)); |
200 } | 216 } |
201 | 217 |
202 void PPB_Audio_Proxy::AudioChannelConnected(int32_t result, | 218 void PPB_Audio_Proxy::AudioChannelConnected( |
203 PP_Resource resource) { | 219 int32_t result, |
| 220 AudioChannelConnectedTracking* tracking) { |
| 221 // Ownership of the pointer was transferred to us. |
| 222 scoped_ptr<AudioChannelConnectedTracking> tracking_deleter(tracking); |
| 223 |
204 IPC::PlatformFileForTransit socket_handle = | 224 IPC::PlatformFileForTransit socket_handle = |
205 IPC::InvalidPlatformFileForTransit(); | 225 IPC::InvalidPlatformFileForTransit(); |
206 #if defined(OS_WIN) | 226 #if defined(OS_WIN) |
207 base::SharedMemoryHandle shared_memory = NULL; | 227 base::SharedMemoryHandle shared_memory = NULL; |
208 #elif defined(OS_POSIX) | 228 #elif defined(OS_POSIX) |
209 base::SharedMemoryHandle shared_memory(-1, false); | 229 base::SharedMemoryHandle shared_memory(-1, false); |
210 #else | 230 #else |
211 #error Not implemented. | 231 #error Not implemented. |
212 #endif | 232 #endif |
213 uint32_t shared_memory_length = 0; | 233 uint32_t shared_memory_length = 0; |
214 | 234 |
215 int32_t result_code = result; | 235 int32_t result_code = result; |
216 if (result_code == PP_OK) { | 236 if (result_code == PP_OK) { |
217 result_code = GetAudioConnectedHandles(resource, &socket_handle, | 237 result_code = GetAudioConnectedHandles(tracking->resource, &socket_handle, |
218 &shared_memory, | 238 &shared_memory, |
219 &shared_memory_length); | 239 &shared_memory_length); |
220 } | 240 } |
221 | 241 |
222 // Send all the values, even on error. This simplifies some of our cleanup | 242 // Send all the values, even on error. This simplifies some of our cleanup |
223 // code since the handles will be in the other process and could be | 243 // code since the handles will be in the other process and could be |
224 // inconvenient to clean up. Our IPC code will automatically handle this for | 244 // inconvenient to clean up. Our IPC code will automatically handle this for |
225 // us, as long as the remote side always closes the handles it receives | 245 // us, as long as the remote side always closes the handles it receives |
226 // (in OnMsgNotifyAudioStreamCreated), even in the failure case. | 246 // (in OnMsgNotifyAudioStreamCreated), even in the failure case. |
| 247 PPBAudio_NotifyAudioStreamCreated_Params params; |
| 248 params.instance = tracking->instance; |
| 249 params.audio_id = tracking->resource; |
| 250 params.result_code = result; |
| 251 params.socket_handle = socket_handle; |
| 252 params.handle = shared_memory; |
| 253 params.length = shared_memory_length; |
227 dispatcher()->Send(new PpapiMsg_PPBAudio_NotifyAudioStreamCreated( | 254 dispatcher()->Send(new PpapiMsg_PPBAudio_NotifyAudioStreamCreated( |
228 INTERFACE_ID_PPB_AUDIO, resource, result_code, socket_handle, | 255 INTERFACE_ID_PPB_AUDIO, params)); |
229 shared_memory, shared_memory_length)); | |
230 } | 256 } |
231 | 257 |
232 int32_t PPB_Audio_Proxy::GetAudioConnectedHandles( | 258 int32_t PPB_Audio_Proxy::GetAudioConnectedHandles( |
233 PP_Resource resource, | 259 SerializedResource resource, |
234 IPC::PlatformFileForTransit* foreign_socket_handle, | 260 IPC::PlatformFileForTransit* foreign_socket_handle, |
235 base::SharedMemoryHandle* foreign_shared_memory_handle, | 261 base::SharedMemoryHandle* foreign_shared_memory_handle, |
236 uint32_t* shared_memory_length) { | 262 uint32_t* shared_memory_length) { |
237 // Get the trusted audio interface which will give us the handles. | 263 // Get the trusted audio interface which will give us the handles. |
238 const PPB_AudioTrusted* audio_trusted = | 264 const PPB_AudioTrusted* audio_trusted = |
239 reinterpret_cast<const PPB_AudioTrusted*>( | 265 reinterpret_cast<const PPB_AudioTrusted*>( |
240 dispatcher()->GetLocalInterface(PPB_AUDIO_TRUSTED_INTERFACE)); | 266 dispatcher()->GetLocalInterface(PPB_AUDIO_TRUSTED_INTERFACE)); |
241 if (!audio_trusted) | 267 if (!audio_trusted) |
242 return PP_ERROR_NOINTERFACE; | 268 return PP_ERROR_NOINTERFACE; |
243 | 269 |
244 // Get the socket handle for signaling. | 270 // Get the socket handle for signaling. |
245 int32_t socket_handle; | 271 int32_t socket_handle; |
246 int32_t result = audio_trusted->GetSyncSocket(resource, &socket_handle); | 272 int32_t result = audio_trusted->GetSyncSocket(resource.host_resource(), |
| 273 &socket_handle); |
247 if (result != PP_OK) | 274 if (result != PP_OK) |
248 return result; | 275 return result; |
249 | 276 |
250 #if defined(OS_WIN) | 277 #if defined(OS_WIN) |
251 // On Windows, duplicate the socket into the plugin process, this will | 278 // On Windows, duplicate the socket into the plugin process, this will |
252 // automatically close the source handle. | 279 // automatically close the source handle. |
253 ::DuplicateHandle( | 280 ::DuplicateHandle( |
254 GetCurrentProcess(), | 281 GetCurrentProcess(), |
255 reinterpret_cast<HANDLE>(static_cast<intptr_t>(socket_handle)), | 282 reinterpret_cast<HANDLE>(static_cast<intptr_t>(socket_handle)), |
256 dispatcher()->remote_process_handle(), foreign_socket_handle, | 283 dispatcher()->remote_process_handle(), foreign_socket_handle, |
257 STANDARD_RIGHTS_REQUIRED | FILE_MAP_READ | FILE_MAP_WRITE, | 284 STANDARD_RIGHTS_REQUIRED | FILE_MAP_READ | FILE_MAP_WRITE, |
258 FALSE, DUPLICATE_CLOSE_SOURCE); | 285 FALSE, DUPLICATE_CLOSE_SOURCE); |
259 #else | 286 #else |
260 // On Posix, the socket handle will be auto-duplicated when we send the | 287 // On Posix, the socket handle will be auto-duplicated when we send the |
261 // FileDescriptor. Set AutoClose since we don't need the handle any more. | 288 // FileDescriptor. Set AutoClose since we don't need the handle any more. |
262 *foreign_socket_handle = base::FileDescriptor(socket_handle, true); | 289 *foreign_socket_handle = base::FileDescriptor(socket_handle, true); |
263 #endif | 290 #endif |
264 | 291 |
265 // Get the shared memory for the buffer. | 292 // Get the shared memory for the buffer. |
266 // TODO(brettw) remove the reinterpret cast when the interface is updated. | 293 // TODO(brettw) remove the reinterpret cast when the interface is updated. |
267 int shared_memory_handle; | 294 int shared_memory_handle; |
268 result = audio_trusted->GetSharedMemory(resource, &shared_memory_handle, | 295 result = audio_trusted->GetSharedMemory(resource.host_resource(), |
269 shared_memory_length); | 296 &shared_memory_handle, |
| 297 shared_memory_length); |
270 if (result != PP_OK) | 298 if (result != PP_OK) |
271 return result; | 299 return result; |
272 | 300 |
273 base::SharedMemory shared_memory( | 301 base::SharedMemory shared_memory( |
274 #if defined(OS_WIN) | 302 #if defined(OS_WIN) |
275 reinterpret_cast<HANDLE>(static_cast<intptr_t>(shared_memory_handle)), | 303 reinterpret_cast<HANDLE>(static_cast<intptr_t>(shared_memory_handle)), |
276 #else | 304 #else |
277 base::FileDescriptor(shared_memory_handle, false), | 305 base::FileDescriptor(shared_memory_handle, false), |
278 #endif | 306 #endif |
279 false); | 307 false); |
280 | 308 |
281 // Duplicate the shared memory to the plugin process. This will automatically | 309 // Duplicate the shared memory to the plugin process. This will automatically |
282 // close the source handle. | 310 // close the source handle. |
283 if (!shared_memory.GiveToProcess(dispatcher()->remote_process_handle(), | 311 if (!shared_memory.GiveToProcess(dispatcher()->remote_process_handle(), |
284 foreign_shared_memory_handle)) | 312 foreign_shared_memory_handle)) |
285 return PP_ERROR_FAILED; | 313 return PP_ERROR_FAILED; |
286 | 314 |
287 return PP_OK; | 315 return PP_OK; |
288 } | 316 } |
289 | 317 |
290 } // namespace proxy | 318 } // namespace proxy |
291 } // namespace pp | 319 } // namespace pp |
OLD | NEW |