Home | History | Annotate | Download | only in pepper
      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