Home | History | Annotate | Download | only in media
      1 // Copyright 2013 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/browser/renderer_host/media/device_request_message_filter.h"
      6 
      7 #include "content/browser/browser_main_loop.h"
      8 #include "content/browser/child_process_security_policy_impl.h"
      9 #include "content/browser/renderer_host/media/media_stream_manager.h"
     10 #include "content/common/media/media_stream_messages.h"
     11 #include "content/public/browser/resource_context.h"
     12 
     13 namespace content {
     14 
     15 DeviceRequestMessageFilter::DeviceRequestMessageFilter(
     16     ResourceContext* resource_context,
     17     MediaStreamManager* media_stream_manager,
     18     int render_process_id)
     19     : BrowserMessageFilter(MediaStreamMsgStart),
     20       resource_context_(resource_context),
     21       media_stream_manager_(media_stream_manager),
     22       render_process_id_(render_process_id) {
     23   DCHECK(resource_context);
     24   DCHECK(media_stream_manager);
     25 }
     26 
     27 DeviceRequestMessageFilter::~DeviceRequestMessageFilter() {
     28   // CHECK rather than DCHECK to make sure this never happens in the
     29   // wild. We want to be sure due to http://crbug.com/341211
     30   CHECK(requests_.empty());
     31 }
     32 
     33 struct DeviceRequestMessageFilter::DeviceRequest {
     34   DeviceRequest(int request_id,
     35                 const GURL& origin,
     36                 const std::string& audio_devices_label,
     37                 const std::string& video_devices_label)
     38       : request_id(request_id),
     39         origin(origin),
     40         has_audio_returned(false),
     41         has_video_returned(false),
     42         audio_devices_label(audio_devices_label),
     43         video_devices_label(video_devices_label) {}
     44 
     45   int request_id;
     46   GURL origin;
     47   bool has_audio_returned;
     48   bool has_video_returned;
     49   std::string audio_devices_label;
     50   std::string video_devices_label;
     51   StreamDeviceInfoArray audio_devices;
     52   StreamDeviceInfoArray video_devices;
     53 };
     54 
     55 void DeviceRequestMessageFilter::DevicesEnumerated(
     56     int render_view_id,
     57     int page_request_id,
     58     const std::string& label,
     59     const StreamDeviceInfoArray& new_devices) {
     60   DCHECK_CURRENTLY_ON(BrowserThread::IO);
     61 
     62   // Look up the DeviceRequest by id.
     63   DeviceRequestList::iterator request_it = requests_.begin();
     64   for (; request_it != requests_.end(); ++request_it) {
     65     if (label == request_it->audio_devices_label ||
     66         label == request_it->video_devices_label) {
     67       break;
     68     }
     69   }
     70   DCHECK(request_it != requests_.end());
     71 
     72   StreamDeviceInfoArray* audio_devices = &request_it->audio_devices;
     73   StreamDeviceInfoArray* video_devices = &request_it->video_devices;
     74 
     75   // Store hmac'd device ids instead of raw device ids.
     76   if (label == request_it->audio_devices_label) {
     77     request_it->has_audio_returned = true;
     78     DCHECK(audio_devices->empty());
     79     *audio_devices = new_devices;
     80   } else {
     81     DCHECK(label == request_it->video_devices_label);
     82     request_it->has_video_returned = true;
     83     DCHECK(video_devices->empty());
     84     *video_devices = new_devices;
     85   }
     86 
     87   if (!request_it->has_audio_returned || !request_it->has_video_returned) {
     88     // Wait for the rest of the devices to complete.
     89     return;
     90   }
     91 
     92   // Both audio and video devices are ready for copying.
     93   StreamDeviceInfoArray all_devices = *audio_devices;
     94   all_devices.insert(
     95       all_devices.end(), video_devices->begin(), video_devices->end());
     96 
     97   Send(new MediaStreamMsg_GetSourcesACK(request_it->request_id, all_devices));
     98 
     99   media_stream_manager_->CancelRequest(request_it->audio_devices_label);
    100   media_stream_manager_->CancelRequest(request_it->video_devices_label);
    101   requests_.erase(request_it);
    102 }
    103 
    104 bool DeviceRequestMessageFilter::OnMessageReceived(
    105     const IPC::Message& message) {
    106   bool handled = true;
    107   IPC_BEGIN_MESSAGE_MAP(DeviceRequestMessageFilter, message)
    108     IPC_MESSAGE_HANDLER(MediaStreamHostMsg_GetSources, OnGetSources)
    109     IPC_MESSAGE_UNHANDLED(handled = false)
    110   IPC_END_MESSAGE_MAP()
    111   return handled;
    112 }
    113 
    114 void DeviceRequestMessageFilter::OnChannelClosing() {
    115   // Since the IPC channel is gone, cancel outstanding device requests.
    116   for (DeviceRequestList::iterator request_it = requests_.begin();
    117        request_it != requests_.end(); ++request_it) {
    118     media_stream_manager_->CancelRequest(request_it->audio_devices_label);
    119     media_stream_manager_->CancelRequest(request_it->video_devices_label);
    120   }
    121   requests_.clear();
    122 }
    123 
    124 void DeviceRequestMessageFilter::OnGetSources(int request_id,
    125                                               const GURL& security_origin) {
    126   if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
    127           render_process_id_, security_origin)) {
    128     LOG(ERROR) << "Disallowed URL in DRMF::OnGetSources: " << security_origin;
    129     return;
    130   }
    131 
    132   // Make request to get audio devices.
    133   const std::string& audio_label = media_stream_manager_->EnumerateDevices(
    134       this, -1, -1, resource_context_->GetMediaDeviceIDSalt(), -1,
    135       MEDIA_DEVICE_AUDIO_CAPTURE, security_origin,
    136       resource_context_->AllowMicAccess(security_origin));
    137   DCHECK(!audio_label.empty());
    138 
    139   // Make request for video devices.
    140   const std::string& video_label = media_stream_manager_->EnumerateDevices(
    141       this, -1, -1, resource_context_->GetMediaDeviceIDSalt(), -1,
    142       MEDIA_DEVICE_VIDEO_CAPTURE, security_origin,
    143       resource_context_->AllowCameraAccess(security_origin));
    144   DCHECK(!video_label.empty());
    145 
    146   requests_.push_back(DeviceRequest(
    147       request_id, security_origin, audio_label, video_label));
    148 }
    149 
    150 }  // namespace content
    151