media_stream_devices_controller.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/media/media_stream_devices_controller.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/content_settings/content_settings_provider.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/content_settings/host_content_settings_map.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/tab_capture/tab_capture_registry.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/tab_capture/tab_capture_registry_factory.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prefs/scoped_user_pref_update.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/content_settings.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/media_stream_request.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A predicate that checks if a StreamDeviceInfo object has the same device
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// name as the device name specified at construction.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DeviceNameEquals {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit DeviceNameEquals(const std::string& device_name)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : device_name_(device_name) {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator() (const content::MediaStreamDevice& device) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return device.name == device_name_;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string device_name_;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kAudioKey[] = "audio";
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kVideoKey[] = "video";
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamDevicesController::MediaStreamDevicesController(
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::MediaStreamRequest* request,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::MediaResponseCallback& callback)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : has_audio_(false),
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_video_(false),
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_(profile),
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_(*request),
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_(callback) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (content::MediaStreamDeviceMap::const_iterator it =
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           request_.devices.begin();
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != request_.devices.end(); ++it) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (content::IsAudioMediaType(it->first)) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_audio_ |= !it->second.empty();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (content::IsVideoMediaType(it->first)) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_video_ |= !it->second.empty();
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamDevicesController::~MediaStreamDevicesController() {}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MediaStreamDevicesController::DismissInfoBarAndTakeActionOnSettings() {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For tab media requests, we need to make sure the request came from the
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extension API, so we check the registry here.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::MediaStreamDeviceMap::const_iterator tab_video =
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_.devices.find(content::MEDIA_TAB_VIDEO_CAPTURE);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::MediaStreamDeviceMap::const_iterator tab_audio =
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_.devices.find(content::MEDIA_TAB_AUDIO_CAPTURE);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tab_video != request_.devices.end() ||
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_audio != request_.devices.end()) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions::TabCaptureRegistry* registry =
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extensions::TabCaptureRegistryFactory::GetForProfile(profile_);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!tab_audio->second.empty() || !tab_video->second.empty());
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string audio_device_id;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string video_device_id;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!tab_audio->second.empty())
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      audio_device_id = tab_audio->second[0].device_id;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!tab_video->second.empty())
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      video_device_id = tab_video->second[0].device_id;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!registry->VerifyRequest(!video_device_id.empty() ?
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 video_device_id : audio_device_id)) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Deny();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Accept(audio_device_id, video_device_id, false);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Deny the request if the security origin is empty, this happens with
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // file access without |--allow-file-access-from-files| flag.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_.security_origin.is_empty()) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Deny();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Deny the request and don't show the infobar if there is no devices.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_audio_ && !has_video_) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(xians): We should detect this in a early state, and post a callback
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to tell the users that no device is available. Remove the code and add
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // a DCHECK when this is done.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Deny();
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Checks if any exception has been made for this request, get the "always
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // allowed" devices if they are available.
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string audio, video;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetAlwaysAllowedDevices(&audio, &video);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((has_audio_ && audio.empty()) || (has_video_ && video.empty())) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If there is no "always allowed" device for the origin, or the device is
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // not available in the device lists, Check the default setting to see if
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the user has blocked the access to the media device.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IsMediaDeviceBlocked()) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Deny();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Show the infobar.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Dismiss the infobar by selecting the "always allowed" devices.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Accept(audio, video, false);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)content::MediaStreamDevices
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamDevicesController::GetAudioDevices() const {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::MediaStreamDevices all_audio_devices;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_audio_)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FindSubsetOfDevices(&content::IsAudioMediaType, &all_audio_devices);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return all_audio_devices;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)content::MediaStreamDevices
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamDevicesController::GetVideoDevices() const {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::MediaStreamDevices all_video_devices;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_video_)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FindSubsetOfDevices(&content::IsVideoMediaType, &all_video_devices);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return all_video_devices;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string& MediaStreamDevicesController::GetSecurityOriginSpec() const {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return request_.security_origin.spec();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MediaStreamDevicesController::IsSafeToAlwaysAllowAudio() const {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return IsSafeToAlwaysAllow(
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &content::IsAudioMediaType, content::MEDIA_DEVICE_AUDIO_CAPTURE);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MediaStreamDevicesController::IsSafeToAlwaysAllowVideo() const {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return IsSafeToAlwaysAllow(
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &content::IsVideoMediaType, content::MEDIA_DEVICE_VIDEO_CAPTURE);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamDevicesController::Accept(const std::string& audio_id,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const std::string& video_id,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          bool always_allow) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::MediaStreamDevices devices;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string audio_device_name, video_device_name;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const content::MediaStreamDevice* const audio_device =
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FindFirstDeviceWithIdInSubset(&content::IsAudioMediaType, audio_id);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (audio_device) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (audio_device->type != content::MEDIA_DEVICE_AUDIO_CAPTURE)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      always_allow = false;  // Override for virtual audio device type.
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    devices.push_back(*audio_device);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    audio_device_name = audio_device->name;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const content::MediaStreamDevice* const video_device =
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FindFirstDeviceWithIdInSubset(&content::IsVideoMediaType, video_id);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (video_device) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (video_device->type != content::MEDIA_DEVICE_VIDEO_CAPTURE)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      always_allow = false;  // Override for virtual video device type.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    devices.push_back(*video_device);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    video_device_name = video_device->name;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!devices.empty());
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (always_allow)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AlwaysAllowOriginAndDevices(audio_device_name, video_device_name);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_.Run(devices);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamDevicesController::Deny() {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_.Run(content::MediaStreamDevices());
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MediaStreamDevicesController::IsSafeToAlwaysAllow(
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FilterByDeviceTypeFunc is_included,
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::MediaStreamDeviceType device_type) const {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(device_type == content::MEDIA_DEVICE_AUDIO_CAPTURE ||
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         device_type == content::MEDIA_DEVICE_VIDEO_CAPTURE);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!request_.security_origin.SchemeIsSecure())
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If non-physical devices are available for the choosing, then it's not safe.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool safe_devices_found = false;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (content::MediaStreamDeviceMap::const_iterator it =
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           request_.devices.begin();
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != request_.devices.end(); ++it) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->first != device_type && is_included(it->first))
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    safe_devices_found = true;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return safe_devices_found;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MediaStreamDevicesController::ShouldAlwaysAllowOrigin() {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return profile_->GetHostContentSettingsMap()->ShouldAllowAllContent(
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_.security_origin, request_.security_origin,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_MEDIASTREAM);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MediaStreamDevicesController::IsMediaDeviceBlocked() {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContentSetting current_setting =
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_->GetHostContentSettingsMap()->GetDefaultContentSetting(
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CONTENT_SETTINGS_TYPE_MEDIASTREAM, NULL);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (current_setting == CONTENT_SETTING_BLOCK);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamDevicesController::AlwaysAllowOriginAndDevices(
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& audio_device,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& video_device) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!audio_device.empty() || !video_device.empty());
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue* dictionary_value = new DictionaryValue();
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!audio_device.empty())
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dictionary_value->SetString(kAudioKey, audio_device);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!video_device.empty())
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dictionary_value->SetString(kVideoKey, video_device);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContentSettingsPattern primary_pattern =
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ContentSettingsPattern::FromURLNoWildcard(request_.security_origin);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_->GetHostContentSettingsMap()->SetWebsiteSetting(
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      primary_pattern,
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ContentSettingsPattern::Wildcard(),
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_MEDIASTREAM,
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NO_RESOURCE_IDENTIFIER,
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dictionary_value);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamDevicesController::GetAlwaysAllowedDevices(
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* audio_id, std::string* video_id) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(audio_id->empty());
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(video_id->empty());
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the request is from internal objects like chrome://URLs, use the first
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // devices on the lists.
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ShouldAlwaysAllowOrigin()) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (has_audio_)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *audio_id = GetFirstDeviceId(content::MEDIA_DEVICE_AUDIO_CAPTURE);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (has_video_)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *video_id = GetFirstDeviceId(content::MEDIA_DEVICE_VIDEO_CAPTURE);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "Always allowed" option is only available for secure connection.
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!request_.security_origin.SchemeIsSecure())
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Checks the media exceptions to get the "always allowed" devices.
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Value> value(
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_->GetHostContentSettingsMap()->GetWebsiteSetting(
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          request_.security_origin,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          request_.security_origin,
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CONTENT_SETTINGS_TYPE_MEDIASTREAM,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NO_RESOURCE_IDENTIFIER,
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL));
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!value.get()) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const DictionaryValue* value_dict = NULL;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!value->GetAsDictionary(&value_dict) || value_dict->empty())
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string audio_name, video_name;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value_dict->GetString(kAudioKey, &audio_name);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value_dict->GetString(kVideoKey, &video_name);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_audio_ && !audio_name.empty())
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *audio_id = GetDeviceIdByName(content::MEDIA_DEVICE_AUDIO_CAPTURE,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  audio_name);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_video_ && !video_name.empty())
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *video_id = GetDeviceIdByName(content::MEDIA_DEVICE_VIDEO_CAPTURE,
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  video_name);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string MediaStreamDevicesController::GetDeviceIdByName(
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::MediaStreamDeviceType type,
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& name) {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::MediaStreamDeviceMap::const_iterator device_it =
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_.devices.find(type);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (device_it != request_.devices.end()) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::MediaStreamDevices::const_iterator it = std::find_if(
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        device_it->second.begin(), device_it->second.end(),
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DeviceNameEquals(name));
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it != device_it->second.end())
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return it->device_id;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Device is not available, return an empty string.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::string();
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string MediaStreamDevicesController::GetFirstDeviceId(
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::MediaStreamDeviceType type) {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::MediaStreamDeviceMap::const_iterator device_it =
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_.devices.find(type);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (device_it != request_.devices.end())
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return device_it->second.begin()->device_id;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::string();
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamDevicesController::FindSubsetOfDevices(
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FilterByDeviceTypeFunc is_included,
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::MediaStreamDevices* out) const {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (content::MediaStreamDeviceMap::const_iterator it =
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           request_.devices.begin();
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != request_.devices.end(); ++it) {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (is_included(it->first))
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out->insert(out->end(), it->second.begin(), it->second.end());
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const content::MediaStreamDevice*
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamDevicesController::FindFirstDeviceWithIdInSubset(
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FilterByDeviceTypeFunc is_included,
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& device_id) const {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (content::MediaStreamDeviceMap::const_iterator it =
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           request_.devices.begin();
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != request_.devices.end(); ++it) {
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!is_included(it->first)) continue;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (content::MediaStreamDevices::const_iterator device_it =
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             it->second.begin();
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         device_it != it->second.end(); ++device_it) {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const content::MediaStreamDevice& candidate = *device_it;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (candidate.device_id == device_id)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return &candidate;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
364