| 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 |