OLD | NEW |
1 // Copyright (c) 2011 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 "webkit/plugins/ppapi/ppb_audio_impl.h" | 5 #include "webkit/plugins/ppapi/ppb_audio_impl.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "ppapi/c/pp_completion_callback.h" | 8 #include "ppapi/c/pp_completion_callback.h" |
9 #include "ppapi/c/ppb_audio.h" | 9 #include "ppapi/c/ppb_audio.h" |
10 #include "ppapi/c/ppb_audio_config.h" | 10 #include "ppapi/c/ppb_audio_config.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 using ppapi::thunk::PPB_Audio_API; | 21 using ppapi::thunk::PPB_Audio_API; |
22 using ppapi::thunk::PPB_AudioConfig_API; | 22 using ppapi::thunk::PPB_AudioConfig_API; |
23 | 23 |
24 namespace webkit { | 24 namespace webkit { |
25 namespace ppapi { | 25 namespace ppapi { |
26 | 26 |
27 // PPB_Audio_Impl -------------------------------------------------------------- | 27 // PPB_Audio_Impl -------------------------------------------------------------- |
28 | 28 |
29 PPB_Audio_Impl::PPB_Audio_Impl(PP_Instance instance) | 29 PPB_Audio_Impl::PPB_Audio_Impl(PP_Instance instance) |
30 : Resource(instance), | 30 : Resource(instance), |
31 audio_(NULL) { | 31 audio_(NULL), |
| 32 create_callback_pending_(false), |
| 33 shared_memory_size_for_create_callback_(0) { |
| 34 create_callback_ = PP_MakeCompletionCallback(NULL, NULL); |
32 } | 35 } |
33 | 36 |
34 PPB_Audio_Impl::~PPB_Audio_Impl() { | 37 PPB_Audio_Impl::~PPB_Audio_Impl() { |
35 // Calling ShutDown() makes sure StreamCreated cannot be called anymore and | 38 // Calling ShutDown() makes sure StreamCreated cannot be called anymore and |
36 // releases the audio data associated with the pointer. Note however, that | 39 // releases the audio data associated with the pointer. Note however, that |
37 // until ShutDown returns, StreamCreated may still be called. This will be | 40 // until ShutDown returns, StreamCreated may still be called. This will be |
38 // OK since we'll just immediately clean up the data it stored later in this | 41 // OK since we'll just immediately clean up the data it stored later in this |
39 // destructor. | 42 // destructor. |
40 if (audio_) { | 43 if (audio_) { |
41 audio_->ShutDown(); | 44 audio_->ShutDown(); |
42 audio_ = NULL; | 45 audio_ = NULL; |
43 } | 46 } |
| 47 |
| 48 // If the completion callback hasn't fired yet, do so here |
| 49 // with an error condition. |
| 50 if (create_callback_pending_) { |
| 51 PP_RunCompletionCallback(&create_callback_, PP_ERROR_ABORTED); |
| 52 create_callback_pending_ = false; |
| 53 } |
44 } | 54 } |
45 | 55 |
46 // static | 56 // static |
47 PP_Resource PPB_Audio_Impl::Create(PP_Instance instance, | 57 PP_Resource PPB_Audio_Impl::Create(PP_Instance instance, |
48 PP_Resource config, | 58 PP_Resource config, |
49 PPB_Audio_Callback audio_callback, | 59 PPB_Audio_Callback audio_callback, |
50 void* user_data) { | 60 void* user_data) { |
51 scoped_refptr<PPB_Audio_Impl> audio(new PPB_Audio_Impl(instance)); | 61 scoped_refptr<PPB_Audio_Impl> audio(new PPB_Audio_Impl(instance)); |
52 if (!audio->Init(config, audio_callback, user_data)) | 62 if (!audio->Init(config, audio_callback, user_data)) |
53 return 0; | 63 return 0; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 DCHECK(!audio_); | 134 DCHECK(!audio_); |
125 audio_ = plugin_delegate->CreateAudio(enter.object()->GetSampleRate(), | 135 audio_ = plugin_delegate->CreateAudio(enter.object()->GetSampleRate(), |
126 enter.object()->GetSampleFrameCount(), | 136 enter.object()->GetSampleFrameCount(), |
127 this); | 137 this); |
128 if (!audio_) | 138 if (!audio_) |
129 return PP_ERROR_FAILED; | 139 return PP_ERROR_FAILED; |
130 | 140 |
131 // At this point, we are guaranteeing ownership of the completion | 141 // At this point, we are guaranteeing ownership of the completion |
132 // callback. Audio promises to fire the completion callback | 142 // callback. Audio promises to fire the completion callback |
133 // once and only once. | 143 // once and only once. |
134 SetCallbackInfo(true, create_callback); | 144 create_callback_ = create_callback; |
135 | 145 create_callback_pending_ = true; |
136 return PP_OK_COMPLETIONPENDING; | 146 return PP_OK_COMPLETIONPENDING; |
137 } | 147 } |
138 | 148 |
139 int32_t PPB_Audio_Impl::GetSyncSocket(int* sync_socket) { | 149 int32_t PPB_Audio_Impl::GetSyncSocket(int* sync_socket) { |
140 return GetSyncSocketImpl(sync_socket); | 150 if (socket_for_create_callback_.get()) { |
| 151 #if defined(OS_POSIX) |
| 152 *sync_socket = socket_for_create_callback_->handle(); |
| 153 #elif defined(OS_WIN) |
| 154 *sync_socket = reinterpret_cast<int>(socket_for_create_callback_->handle()); |
| 155 #else |
| 156 #error "Platform not supported." |
| 157 #endif |
| 158 return PP_OK; |
| 159 } |
| 160 return PP_ERROR_FAILED; |
141 } | 161 } |
142 | 162 |
143 int32_t PPB_Audio_Impl::GetSharedMemory(int* shm_handle, | 163 int32_t PPB_Audio_Impl::GetSharedMemory(int* shm_handle, uint32_t* shm_size) { |
144 uint32_t* shm_size) { | 164 if (shared_memory_for_create_callback_.get()) { |
145 return GetSharedMemoryImpl(shm_handle, shm_size); | 165 #if defined(OS_POSIX) |
| 166 *shm_handle = shared_memory_for_create_callback_->handle().fd; |
| 167 #elif defined(OS_WIN) |
| 168 *shm_handle = reinterpret_cast<int>( |
| 169 shared_memory_for_create_callback_->handle()); |
| 170 #else |
| 171 #error "Platform not supported." |
| 172 #endif |
| 173 *shm_size = shared_memory_size_for_create_callback_; |
| 174 return PP_OK; |
| 175 } |
| 176 return PP_ERROR_FAILED; |
146 } | 177 } |
147 | 178 |
148 void PPB_Audio_Impl::OnSetStreamInfo( | 179 void PPB_Audio_Impl::StreamCreated( |
149 base::SharedMemoryHandle shared_memory_handle, | 180 base::SharedMemoryHandle shared_memory_handle, |
150 size_t shared_memory_size, | 181 size_t shared_memory_size, |
151 base::SyncSocket::Handle socket_handle) { | 182 base::SyncSocket::Handle socket_handle) { |
152 SetStreamInfo(shared_memory_handle, shared_memory_size, socket_handle); | 183 if (create_callback_pending_) { |
| 184 // Trusted side of proxy can specify a callback to recieve handles. In |
| 185 // this case we don't need to map any data or start the thread since it |
| 186 // will be handled by the proxy. |
| 187 shared_memory_for_create_callback_.reset( |
| 188 new base::SharedMemory(shared_memory_handle, false)); |
| 189 shared_memory_size_for_create_callback_ = shared_memory_size; |
| 190 socket_for_create_callback_.reset(new base::SyncSocket(socket_handle)); |
| 191 |
| 192 PP_RunCompletionCallback(&create_callback_, 0); |
| 193 create_callback_pending_ = false; |
| 194 |
| 195 // It might be nice to close the handles here to free up some system |
| 196 // resources, but we can't since there's a race condition. The handles must |
| 197 // be valid until they're sent over IPC, which is done from the I/O thread |
| 198 // which will often get done after this code executes. We could do |
| 199 // something more elaborate like an ACK from the plugin or post a task to |
| 200 // the I/O thread and back, but this extra complexity doesn't seem worth it |
| 201 // just to clean up these handles faster. |
| 202 } else { |
| 203 SetStreamInfo(shared_memory_handle, shared_memory_size, socket_handle); |
| 204 } |
153 } | 205 } |
154 | 206 |
155 } // namespace ppapi | 207 } // namespace ppapi |
156 } // namespace webkit | 208 } // namespace webkit |
OLD | NEW |