media_stream_devices_controller.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/command_line.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/content_settings/content_settings_provider.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/content_settings/host_content_settings_map.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/content_settings/tab_specific_content_settings.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/media/media_capture_devices_dispatcher.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/media/media_stream_capture_indicator.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prefs/scoped_user_pref_update.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/chrome_switches.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/content_settings.h"
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/common/content_settings_pattern.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/user_prefs/pref_registry_syncable.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/media_stream_request.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_CHROMEOS)
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/chromeos/login/user_manager.h"
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool HasAnyAvailableDevice() {
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const content::MediaStreamDevices& audio_devices =
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MediaCaptureDevicesDispatcher::GetInstance()->GetAudioCaptureDevices();
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const content::MediaStreamDevices& video_devices =
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MediaCaptureDevicesDispatcher::GetInstance()->GetVideoCaptureDevices();
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return !audio_devices.empty() || !video_devices.empty();
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool IsInKioskMode() {
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode))
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return true;
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_CHROMEOS)
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const chromeos::UserManager* user_manager = chromeos::UserManager::Get();
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return user_manager && user_manager->IsLoggedInAsKioskApp();
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#else
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return false;
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamDevicesController::MediaStreamDevicesController(
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    content::WebContents* web_contents,
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::MediaStreamRequest& request,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::MediaResponseCallback& callback)
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : web_contents_(web_contents),
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      request_(request),
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      callback_(callback),
647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      // For MEDIA_OPEN_DEVICE requests (Pepper) we always request both webcam
657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      // and microphone to avoid popping two infobars.
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      microphone_requested_(
677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE ||
687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          request.request_type == content::MEDIA_OPEN_DEVICE),
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      webcam_requested_(
707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE ||
717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          request.request_type == content::MEDIA_OPEN_DEVICE) {
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext());
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  content_settings_ = TabSpecificContentSettings::FromWebContents(web_contents);
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Don't call GetDevicePolicy from the initializer list since the
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // implementation depends on member variables.
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (microphone_requested_ &&
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      GetDevicePolicy(prefs::kAudioCaptureAllowed,
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                      prefs::kAudioCaptureAllowedUrls) == ALWAYS_DENY) {
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    microphone_requested_ = false;
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (webcam_requested_ &&
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      GetDevicePolicy(prefs::kVideoCaptureAllowed,
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                      prefs::kVideoCaptureAllowedUrls) == ALWAYS_DENY) {
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    webcam_requested_ = false;
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)MediaStreamDevicesController::~MediaStreamDevicesController() {
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!callback_.is_null()) {
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    callback_.Run(content::MediaStreamDevices(),
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  scoped_ptr<content::MediaStreamUI>());
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid MediaStreamDevicesController::RegisterProfilePrefs(
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    user_prefs::PrefRegistrySyncable* prefs) {
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prefs->RegisterBooleanPref(prefs::kVideoCaptureAllowed,
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             true,
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prefs->RegisterBooleanPref(prefs::kAudioCaptureAllowed,
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             true,
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  prefs->RegisterListPref(prefs::kVideoCaptureAllowedUrls,
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                          user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  prefs->RegisterListPref(prefs::kAudioCaptureAllowedUrls,
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                          user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool MediaStreamDevicesController::DismissInfoBarAndTakeActionOnSettings() {
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Tab capture is allowed for extensions only and infobar is not shown for
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // extensions.
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (request_.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE ||
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      request_.video_type == content::MEDIA_TAB_VIDEO_CAPTURE) {
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Deny(false);
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Deny the request if the security origin is empty, this happens with
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // file access without |--allow-file-access-from-files| flag.
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (request_.security_origin.is_empty()) {
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Deny(false);
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Deny the request if there is no device attached to the OS.
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!HasAnyAvailableDevice()) {
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Deny(false);
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check if any allow exception has been made for this request.
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (IsRequestAllowedByDefault()) {
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Accept(false);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Filter any parts of the request that have been blocked by default and deny
1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // it if nothing is left to accept.
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (FilterBlockedByDefaultDevices() == 0) {
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Deny(false);
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check if the media default setting is set to block.
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (IsDefaultMediaAccessBlocked()) {
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Deny(false);
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Show the infobar.
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const std::string& MediaStreamDevicesController::GetSecurityOriginSpec() const {
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return request_.security_origin.spec();
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MediaStreamDevicesController::Accept(bool update_content_setting) {
1637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  NotifyUIRequestAccepted();
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Get the default devices for the request.
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  content::MediaStreamDevices devices;
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (microphone_requested_ || webcam_requested_) {
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    switch (request_.request_type) {
1697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      case content::MEDIA_OPEN_DEVICE: {
1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        const content::MediaStreamDevice* device = NULL;
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // For open device request pick the desired device or fall back to the
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // first available of the given type.
1737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (request_.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
1747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          device = MediaCaptureDevicesDispatcher::GetInstance()->
1757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              GetRequestedAudioDevice(request_.requested_audio_device_id);
1767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          // TODO(wjia): Confirm this is the intended behavior.
1777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          if (!device) {
1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            device = MediaCaptureDevicesDispatcher::GetInstance()->
1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                GetFirstAvailableAudioDevice();
1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          }
1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        } else if (request_.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE) {
1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          // Pepper API opens only one device at a time.
1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          device = MediaCaptureDevicesDispatcher::GetInstance()->
1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              GetRequestedVideoDevice(request_.requested_video_device_id);
1857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          // TODO(wjia): Confirm this is the intended behavior.
1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          if (!device) {
1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            device = MediaCaptureDevicesDispatcher::GetInstance()->
1887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                GetFirstAvailableVideoDevice();
1897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          }
1907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        }
1917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (device)
1927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          devices.push_back(*device);
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
1947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      } case content::MEDIA_GENERATE_STREAM: {
1957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        bool needs_audio_device = microphone_requested_;
1967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        bool needs_video_device = webcam_requested_;
1977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        // Get the exact audio or video device if an id is specified.
1997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (!request_.requested_audio_device_id.empty()) {
2007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          const content::MediaStreamDevice* audio_device =
2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              MediaCaptureDevicesDispatcher::GetInstance()->
2027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                  GetRequestedAudioDevice(request_.requested_audio_device_id);
2037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          if (audio_device) {
2047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            devices.push_back(*audio_device);
2057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            needs_audio_device = false;
2067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          }
2077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        }
2087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (!request_.requested_video_device_id.empty()) {
2097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          const content::MediaStreamDevice* video_device =
2107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              MediaCaptureDevicesDispatcher::GetInstance()->
2117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                  GetRequestedVideoDevice(request_.requested_video_device_id);
2127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          if (video_device) {
2137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            devices.push_back(*video_device);
2147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            needs_video_device = false;
2157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          }
2167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        }
2177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        // If either or both audio and video devices were requested but not
2197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        // specified by id, get the default devices.
2207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (needs_audio_device || needs_video_device) {
2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          MediaCaptureDevicesDispatcher::GetInstance()->
2227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              GetDefaultDevicesForProfile(profile_,
2237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                          needs_audio_device,
2247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                          needs_video_device,
2257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                          &devices);
2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        }
2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        break;
2287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      } case content::MEDIA_DEVICE_ACCESS:
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // Get the default devices for the request.
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        MediaCaptureDevicesDispatcher::GetInstance()->
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            GetDefaultDevicesForProfile(profile_,
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                        microphone_requested_,
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                        webcam_requested_,
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                        &devices);
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
2367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      case content::MEDIA_ENUMERATE_DEVICES:
2377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        // Do nothing.
2387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        NOTREACHED();
2397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        break;
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // TODO(raymes): We currently set the content permission for non-https
2437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // websites for Pepper requests as well. This is temporary and should be
2447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // removed.
2457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (update_content_setting) {
2467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if ((IsSchemeSecure() && !devices.empty()) ||
2477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          request_.request_type == content::MEDIA_OPEN_DEVICE) {
2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SetPermission(true);
2497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      }
2507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<content::MediaStreamUI> ui;
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!devices.empty()) {
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ui = MediaCaptureDevicesDispatcher::GetInstance()->
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        GetMediaStreamCaptureIndicator()->RegisterMediaStream(
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            web_contents_, devices);
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  content::MediaResponseCallback cb = callback_;
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callback_.Reset();
261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  cb.Run(devices, ui.Pass());
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MediaStreamDevicesController::Deny(bool update_content_setting) {
2657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  NotifyUIRequestDenied();
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (update_content_setting)
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetPermission(false);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  content::MediaResponseCallback cb = callback_;
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callback_.Reset();
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  cb.Run(content::MediaStreamDevices(), scoped_ptr<content::MediaStreamUI>());
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)MediaStreamDevicesController::DevicePolicy
27690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)MediaStreamDevicesController::GetDevicePolicy(
27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const char* policy_name,
27890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const char* whitelist_policy_name) const {
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If the security origin policy matches a value in the whitelist, allow it.
28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Otherwise, check the |policy_name| master switch for the default behavior.
28390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PrefService* prefs = profile_->GetPrefs();
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // TODO(tommi): Remove the kiosk mode check when the whitelist below
28790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // is visible in the media exceptions UI.
28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // See discussion here: https://codereview.chromium.org/15738004/
28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (IsInKioskMode()) {
29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::ListValue* list = prefs->GetList(whitelist_policy_name);
29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    std::string value;
29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (size_t i = 0; i < list->GetSize(); ++i) {
29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (list->GetString(i, &value)) {
29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ContentSettingsPattern pattern =
29590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            ContentSettingsPattern::FromString(value);
29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (pattern == ContentSettingsPattern::Wildcard()) {
29790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          DLOG(WARNING) << "Ignoring wildcard URL pattern: " << value;
29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          continue;
29990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        }
30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        DLOG_IF(ERROR, !pattern.IsValid()) << "Invalid URL pattern: " << value;
30190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (pattern.IsValid() && pattern.Matches(request_.security_origin))
30290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          return ALWAYS_ALLOW;
30390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
30690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If a match was not found, check if audio capture is otherwise disallowed
30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // or if the user should be prompted.  Setting the policy value to "true"
30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // is equal to not setting it at all, so from hereon out, we will return
31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // either POLICY_NOT_SET (prompt) or ALWAYS_DENY (no prompt, no access).
31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!prefs->GetBoolean(policy_name))
31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return ALWAYS_DENY;
31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return POLICY_NOT_SET;
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool MediaStreamDevicesController::IsRequestAllowedByDefault() const {
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The request from internal objects like chrome://URLs is always allowed.
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (ShouldAlwaysAllowOrigin())
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  struct {
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool has_capability;
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const char* policy_name;
32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const char* list_policy_name;
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ContentSettingsType settings_type;
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } device_checks[] = {
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { microphone_requested_, prefs::kAudioCaptureAllowed,
32990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      prefs::kAudioCaptureAllowedUrls, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC },
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { webcam_requested_, prefs::kVideoCaptureAllowed,
33190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      prefs::kVideoCaptureAllowedUrls,
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA },
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(device_checks); ++i) {
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!device_checks[i].has_capability)
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      continue;
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
33990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DevicePolicy policy = GetDevicePolicy(device_checks[i].policy_name,
34090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                          device_checks[i].list_policy_name);
3417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (policy == ALWAYS_DENY)
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return false;
3447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (policy == POLICY_NOT_SET) {
3467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      // Only load content settings from secure origins unless it is a
3477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      // content::MEDIA_OPEN_DEVICE (Pepper) request.
3487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (!IsSchemeSecure() &&
3497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          request_.request_type != content::MEDIA_OPEN_DEVICE) {
3507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return false;
3517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      }
3527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (profile_->GetHostContentSettingsMap()->GetContentSetting(
3537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              request_.security_origin, request_.security_origin,
3547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              device_checks[i].settings_type, NO_RESOURCE_IDENTIFIER) !=
3557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              CONTENT_SETTING_ALLOW) {
3567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return false;
3577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      }
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // If we get here, then either policy is set to ALWAYS_ALLOW or the content
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // settings allow the request by default.
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint MediaStreamDevicesController::FilterBlockedByDefaultDevices() {
3677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int requested_devices = microphone_requested_ + webcam_requested_;
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (microphone_requested_ &&
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      profile_->GetHostContentSettingsMap()->GetContentSetting(
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          request_.security_origin,
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          request_.security_origin,
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
3737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          NO_RESOURCE_IDENTIFIER) == CONTENT_SETTING_BLOCK) {
3747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    requested_devices--;
3757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    microphone_requested_ = false;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (webcam_requested_ &&
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      profile_->GetHostContentSettingsMap()->GetContentSetting(
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          request_.security_origin,
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          request_.security_origin,
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
3837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          NO_RESOURCE_IDENTIFIER) == CONTENT_SETTING_BLOCK) {
3847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    requested_devices--;
3857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    webcam_requested_ = false;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return requested_devices;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool MediaStreamDevicesController::IsDefaultMediaAccessBlocked() const {
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(markusheintz): Replace CONTENT_SETTINGS_TYPE_MEDIA_STREAM with the
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // appropriate new CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC and
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ContentSetting current_setting =
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      profile_->GetHostContentSettingsMap()->GetDefaultContentSetting(
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          CONTENT_SETTINGS_TYPE_MEDIASTREAM, NULL);
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return (current_setting == CONTENT_SETTING_BLOCK);
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool MediaStreamDevicesController::IsSchemeSecure() const {
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return (request_.security_origin.SchemeIsSecure());
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool MediaStreamDevicesController::ShouldAlwaysAllowOrigin() const {
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(markusheintz): Replace CONTENT_SETTINGS_TYPE_MEDIA_STREAM with the
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // appropriate new CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC and
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return profile_->GetHostContentSettingsMap()->ShouldAllowAllContent(
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      request_.security_origin, request_.security_origin,
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CONTENT_SETTINGS_TYPE_MEDIASTREAM);
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MediaStreamDevicesController::SetPermission(bool allowed) const {
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_ANDROID)
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We do not support sticky operations on Android yet.
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return;
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ContentSettingsPattern primary_pattern =
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ContentSettingsPattern::FromURLNoWildcard(request_.security_origin);
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check the pattern is valid or not. When the request is from a file access,
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // no exception will be made.
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!primary_pattern.IsValid())
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ContentSetting content_setting = allowed ?
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (microphone_requested_) {
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      profile_->GetHostContentSettingsMap()->SetContentSetting(
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        primary_pattern,
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        ContentSettingsPattern::Wildcard(),
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        std::string(),
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        content_setting);
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (webcam_requested_) {
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    profile_->GetHostContentSettingsMap()->SetContentSetting(
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        primary_pattern,
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        ContentSettingsPattern::Wildcard(),
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        std::string(),
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        content_setting);
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void MediaStreamDevicesController::NotifyUIRequestAccepted() const {
4497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!content_settings_)
4507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
4517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // We need to figure out which part of the request is accepted or denied here.
4537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // For example, when the request contains both audio and video, but audio is
4547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // blocked by the policy, then we will prompt the infobar to ask for video
4557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // permission. In case the users approve the permission,
4567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // we need to show an allowed icon for video but blocked icon for audio.
4577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (request_.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
4587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // The request might contain audio while |webcam_requested_| is false,
4597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // this happens when the policy is blocking the audio.
4607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (microphone_requested_)
4617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      content_settings_->OnMicrophoneAccessed();
4627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    else
4637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      content_settings_->OnMicrophoneAccessBlocked();
4647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
4657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (request_.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE) {
4677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // The request might contain video while |webcam_requested_| is false,
4687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // this happens when the policy is blocking the video.
4697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (webcam_requested_)
4707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      content_settings_->OnCameraAccessed();
4717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    else
4727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      content_settings_->OnCameraAccessBlocked();
4737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
4747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
4757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void MediaStreamDevicesController::NotifyUIRequestDenied() const {
4777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!content_settings_)
4787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
4797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Do not show the block icons for tab capture.
4817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (request_.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE ||
4827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      request_.video_type == content::MEDIA_TAB_VIDEO_CAPTURE) {
4837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return;
4847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
4857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (request_.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE)
4877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    content_settings_->OnMicrophoneAccessBlocked();
4887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (request_.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE)
4897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    content_settings_->OnCameraAccessBlocked();
4907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
491