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