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 12namespace content { 13 14namespace { 15 16ppapi::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 28base::WeakPtr<PepperMediaDeviceManager> 29PepperMediaDeviceManager::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 38PepperMediaDeviceManager::PepperMediaDeviceManager(RenderFrame* render_frame) 39 : RenderFrameObserver(render_frame), 40 RenderFrameObserverTracker<PepperMediaDeviceManager>(render_frame), 41 next_id_(1) {} 42 43PepperMediaDeviceManager::~PepperMediaDeviceManager() { 44 DCHECK(enumerate_callbacks_.empty()); 45 DCHECK(open_callbacks_.empty()); 46} 47 48int 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 73void 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 87void 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 98int 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 123void 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 131void PepperMediaDeviceManager::CloseDevice(const std::string& label) { 132#if defined(ENABLE_WEBRTC) 133 GetMediaStreamDispatcher()->CloseDevice(label); 134#endif 135} 136 137int 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 154void PepperMediaDeviceManager::OnStreamGenerated( 155 int request_id, 156 const std::string& label, 157 const StreamDeviceInfoArray& audio_device_array, 158 const StreamDeviceInfoArray& video_device_array) {} 159 160void PepperMediaDeviceManager::OnStreamGenerationFailed( 161 int request_id, 162 content::MediaStreamRequestResult result) {} 163 164void PepperMediaDeviceManager::OnDeviceStopped( 165 const std::string& label, 166 const StreamDeviceInfo& device_info) {} 167 168void 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 190void PepperMediaDeviceManager::OnDeviceOpened( 191 int request_id, 192 const std::string& label, 193 const StreamDeviceInfo& device_info) { 194 NotifyDeviceOpened(request_id, true, label); 195} 196 197void PepperMediaDeviceManager::OnDeviceOpenFailed(int request_id) { 198 NotifyDeviceOpened(request_id, false, std::string()); 199} 200 201// static 202MediaStreamType 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 218PP_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 233void 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 248MediaStreamDispatcher* 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