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. 4 5 #include "content/renderer/pepper/pepper_media_device_manager.h" 6 7 #include "base/logging.h" 8 #include "content/renderer/media/media_stream_dispatcher.h" 9 #include "content/renderer/render_frame_impl.h" 10 #include "ppapi/shared_impl/ppb_device_ref_shared.h" 11 12 namespace content { 13 14 namespace { 15 16 ppapi::DeviceRefData FromStreamDeviceInfo(const StreamDeviceInfo& info) { 17 ppapi::DeviceRefData data; 18 data.id = info.device.id; 19 // Some Flash content can't handle an empty string, so stick a space in to 20 // make them happy. See crbug.com/408404. 21 data.name = info.device.name.empty() ? std::string(" ") : info.device.name; 22 data.type = PepperMediaDeviceManager::FromMediaStreamType(info.device.type); 23 return data; 24 } 25 26 } // namespace 27 28 base::WeakPtr<PepperMediaDeviceManager> 29 PepperMediaDeviceManager::GetForRenderFrame( 30 RenderFrame* render_frame) { 31 PepperMediaDeviceManager* handler = 32 PepperMediaDeviceManager::Get(render_frame); 33 if (!handler) 34 handler = new PepperMediaDeviceManager(render_frame); 35 return handler->AsWeakPtr(); 36 } 37 38 PepperMediaDeviceManager::PepperMediaDeviceManager(RenderFrame* render_frame) 39 : RenderFrameObserver(render_frame), 40 RenderFrameObserverTracker<PepperMediaDeviceManager>(render_frame), 41 next_id_(1) {} 42 43 PepperMediaDeviceManager::~PepperMediaDeviceManager() { 44 DCHECK(enumerate_callbacks_.empty()); 45 DCHECK(open_callbacks_.empty()); 46 } 47 48 int PepperMediaDeviceManager::EnumerateDevices( 49 PP_DeviceType_Dev type, 50 const GURL& document_url, 51 const EnumerateDevicesCallback& callback) { 52 enumerate_callbacks_[next_id_] = callback; 53 int request_id = next_id_++; 54 55 #if defined(ENABLE_WEBRTC) 56 GetMediaStreamDispatcher()->EnumerateDevices( 57 request_id, 58 AsWeakPtr(), 59 PepperMediaDeviceManager::FromPepperDeviceType(type), 60 document_url.GetOrigin()); 61 #else 62 base::MessageLoop::current()->PostTask( 63 FROM_HERE, 64 base::Bind(&PepperMediaDeviceManager::OnDevicesEnumerated, 65 AsWeakPtr(), 66 request_id, 67 StreamDeviceInfoArray())); 68 #endif 69 70 return request_id; 71 } 72 73 void PepperMediaDeviceManager::StopEnumerateDevices(int request_id) { 74 enumerate_callbacks_.erase(request_id); 75 76 #if defined(ENABLE_WEBRTC) 77 // Need to post task since this function might be called inside the callback 78 // of EnumerateDevices. 79 base::MessageLoop::current()->PostTask( 80 FROM_HERE, 81 base::Bind(&PepperMediaDeviceManager::StopEnumerateDevicesDelayed, 82 AsWeakPtr(), 83 request_id)); 84 #endif 85 } 86 87 void PepperMediaDeviceManager::StopEnumerateDevicesDelayed(int request_id) { 88 #if defined(ENABLE_WEBRTC) 89 // This method is being invoked by the message loop at some unknown 90 // point-in-time after StopEnumerateDevices(). Therefore, check that 91 // render_frame() is not NULL, in order to guarantee 92 // GetMediaStreamDispatcher() won't return NULL. 93 if (render_frame()) 94 GetMediaStreamDispatcher()->StopEnumerateDevices(request_id, AsWeakPtr()); 95 #endif 96 } 97 98 int PepperMediaDeviceManager::OpenDevice(PP_DeviceType_Dev type, 99 const std::string& device_id, 100 const GURL& document_url, 101 const OpenDeviceCallback& callback) { 102 open_callbacks_[next_id_] = callback; 103 int request_id = next_id_++; 104 105 #if defined(ENABLE_WEBRTC) 106 GetMediaStreamDispatcher()->OpenDevice( 107 request_id, 108 AsWeakPtr(), 109 device_id, 110 PepperMediaDeviceManager::FromPepperDeviceType(type), 111 document_url.GetOrigin()); 112 #else 113 base::MessageLoop::current()->PostTask( 114 FROM_HERE, 115 base::Bind(&PepperMediaDeviceManager::OnDeviceOpenFailed, 116 AsWeakPtr(), 117 request_id)); 118 #endif 119 120 return request_id; 121 } 122 123 void PepperMediaDeviceManager::CancelOpenDevice(int request_id) { 124 open_callbacks_.erase(request_id); 125 126 #if defined(ENABLE_WEBRTC) 127 GetMediaStreamDispatcher()->CancelOpenDevice(request_id, AsWeakPtr()); 128 #endif 129 } 130 131 void PepperMediaDeviceManager::CloseDevice(const std::string& label) { 132 #if defined(ENABLE_WEBRTC) 133 GetMediaStreamDispatcher()->CloseDevice(label); 134 #endif 135 } 136 137 int PepperMediaDeviceManager::GetSessionID(PP_DeviceType_Dev type, 138 const std::string& label) { 139 #if defined(ENABLE_WEBRTC) 140 switch (type) { 141 case PP_DEVICETYPE_DEV_AUDIOCAPTURE: 142 return GetMediaStreamDispatcher()->audio_session_id(label, 0); 143 case PP_DEVICETYPE_DEV_VIDEOCAPTURE: 144 return GetMediaStreamDispatcher()->video_session_id(label, 0); 145 default: 146 NOTREACHED(); 147 return 0; 148 } 149 #else 150 return 0; 151 #endif 152 } 153 154 void PepperMediaDeviceManager::OnStreamGenerated( 155 int request_id, 156 const std::string& label, 157 const StreamDeviceInfoArray& audio_device_array, 158 const StreamDeviceInfoArray& video_device_array) {} 159 160 void PepperMediaDeviceManager::OnStreamGenerationFailed( 161 int request_id, 162 content::MediaStreamRequestResult result) {} 163 164 void PepperMediaDeviceManager::OnDeviceStopped( 165 const std::string& label, 166 const StreamDeviceInfo& device_info) {} 167 168 void PepperMediaDeviceManager::OnDevicesEnumerated( 169 int request_id, 170 const StreamDeviceInfoArray& device_array) { 171 EnumerateCallbackMap::iterator iter = enumerate_callbacks_.find(request_id); 172 if (iter == enumerate_callbacks_.end()) { 173 // This might be enumerated result sent before StopEnumerateDevices is 174 // called since EnumerateDevices is persistent request. 175 return; 176 } 177 178 EnumerateDevicesCallback callback = iter->second; 179 180 std::vector<ppapi::DeviceRefData> devices; 181 devices.reserve(device_array.size()); 182 for (StreamDeviceInfoArray::const_iterator info = device_array.begin(); 183 info != device_array.end(); 184 ++info) { 185 devices.push_back(FromStreamDeviceInfo(*info)); 186 } 187 callback.Run(request_id, devices); 188 } 189 190 void PepperMediaDeviceManager::OnDeviceOpened( 191 int request_id, 192 const std::string& label, 193 const StreamDeviceInfo& device_info) { 194 NotifyDeviceOpened(request_id, true, label); 195 } 196 197 void PepperMediaDeviceManager::OnDeviceOpenFailed(int request_id) { 198 NotifyDeviceOpened(request_id, false, std::string()); 199 } 200 201 // static 202 MediaStreamType PepperMediaDeviceManager::FromPepperDeviceType( 203 PP_DeviceType_Dev type) { 204 switch (type) { 205 case PP_DEVICETYPE_DEV_INVALID: 206 return MEDIA_NO_SERVICE; 207 case PP_DEVICETYPE_DEV_AUDIOCAPTURE: 208 return MEDIA_DEVICE_AUDIO_CAPTURE; 209 case PP_DEVICETYPE_DEV_VIDEOCAPTURE: 210 return MEDIA_DEVICE_VIDEO_CAPTURE; 211 default: 212 NOTREACHED(); 213 return MEDIA_NO_SERVICE; 214 } 215 } 216 217 // static 218 PP_DeviceType_Dev PepperMediaDeviceManager::FromMediaStreamType( 219 MediaStreamType type) { 220 switch (type) { 221 case MEDIA_NO_SERVICE: 222 return PP_DEVICETYPE_DEV_INVALID; 223 case MEDIA_DEVICE_AUDIO_CAPTURE: 224 return PP_DEVICETYPE_DEV_AUDIOCAPTURE; 225 case MEDIA_DEVICE_VIDEO_CAPTURE: 226 return PP_DEVICETYPE_DEV_VIDEOCAPTURE; 227 default: 228 NOTREACHED(); 229 return PP_DEVICETYPE_DEV_INVALID; 230 } 231 } 232 233 void PepperMediaDeviceManager::NotifyDeviceOpened(int request_id, 234 bool succeeded, 235 const std::string& label) { 236 OpenCallbackMap::iterator iter = open_callbacks_.find(request_id); 237 if (iter == open_callbacks_.end()) { 238 // The callback may have been unregistered. 239 return; 240 } 241 242 OpenDeviceCallback callback = iter->second; 243 open_callbacks_.erase(iter); 244 245 callback.Run(request_id, succeeded, label); 246 } 247 248 MediaStreamDispatcher* PepperMediaDeviceManager::GetMediaStreamDispatcher() 249 const { 250 DCHECK(render_frame()); 251 MediaStreamDispatcher* const dispatcher = 252 static_cast<RenderFrameImpl*>(render_frame())->GetMediaStreamDispatcher(); 253 DCHECK(dispatcher); 254 return dispatcher; 255 } 256 257 } // namespace content 258