Home | History | Annotate | Download | only in media
      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 "chrome/browser/media/media_stream_devices_controller.h"
      6 
      7 #include "base/command_line.h"
      8 #include "base/prefs/pref_service.h"
      9 #include "base/prefs/scoped_user_pref_update.h"
     10 #include "base/values.h"
     11 #include "chrome/browser/content_settings/content_settings_provider.h"
     12 #include "chrome/browser/content_settings/host_content_settings_map.h"
     13 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
     14 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
     15 #include "chrome/browser/media/media_stream_capture_indicator.h"
     16 #include "chrome/browser/profiles/profile.h"
     17 #include "chrome/browser/ui/browser.h"
     18 #include "chrome/common/chrome_switches.h"
     19 #include "chrome/common/content_settings.h"
     20 #include "chrome/common/content_settings_pattern.h"
     21 #include "chrome/common/pref_names.h"
     22 #include "components/user_prefs/pref_registry_syncable.h"
     23 #include "content/public/browser/browser_thread.h"
     24 #include "content/public/common/media_stream_request.h"
     25 #include "extensions/common/constants.h"
     26 
     27 #if defined(OS_CHROMEOS)
     28 #include "chrome/browser/chromeos/login/user_manager.h"
     29 #endif
     30 
     31 using content::BrowserThread;
     32 
     33 namespace {
     34 
     35 bool HasAnyAvailableDevice() {
     36   const content::MediaStreamDevices& audio_devices =
     37       MediaCaptureDevicesDispatcher::GetInstance()->GetAudioCaptureDevices();
     38   const content::MediaStreamDevices& video_devices =
     39       MediaCaptureDevicesDispatcher::GetInstance()->GetVideoCaptureDevices();
     40 
     41   return !audio_devices.empty() || !video_devices.empty();
     42 }
     43 
     44 bool IsInKioskMode() {
     45   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode))
     46     return true;
     47 
     48 #if defined(OS_CHROMEOS)
     49   const chromeos::UserManager* user_manager = chromeos::UserManager::Get();
     50   return user_manager && user_manager->IsLoggedInAsKioskApp();
     51 #else
     52   return false;
     53 #endif
     54 }
     55 
     56 }  // namespace
     57 
     58 MediaStreamDevicesController::MediaStreamTypeSettings::MediaStreamTypeSettings(
     59     Permission permission, const std::string& requested_device_id):
     60     permission(permission), requested_device_id(requested_device_id) {}
     61 
     62 MediaStreamDevicesController::MediaStreamTypeSettings::
     63     MediaStreamTypeSettings(): permission(MEDIA_NONE) {}
     64 
     65 MediaStreamDevicesController::MediaStreamTypeSettings::
     66     ~MediaStreamTypeSettings() {}
     67 
     68 MediaStreamDevicesController::MediaStreamDevicesController(
     69     content::WebContents* web_contents,
     70     const content::MediaStreamRequest& request,
     71     const content::MediaResponseCallback& callback)
     72     : web_contents_(web_contents),
     73       request_(request),
     74       callback_(callback) {
     75   profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext());
     76   content_settings_ = TabSpecificContentSettings::FromWebContents(web_contents);
     77 
     78   // For MEDIA_OPEN_DEVICE requests (Pepper) we always request both webcam
     79   // and microphone to avoid popping two infobars.
     80   // We start with setting the requested media type to allowed or blocked
     81   // depending on the policy. If not blocked by policy it may be blocked later
     82   // in the two remaining filtering steps (by user setting or by user when
     83   // clicking the infobar).
     84   // TODO(grunell): It's not the nicest solution to let the MEDIA_OPEN_DEVICE
     85   // case take a ride on the MEDIA_DEVICE_*_CAPTURE permission. Should be fixed.
     86   if (request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE ||
     87       request.request_type == content::MEDIA_OPEN_DEVICE) {
     88     if (GetDevicePolicy(prefs::kAudioCaptureAllowed,
     89                         prefs::kAudioCaptureAllowedUrls) == ALWAYS_DENY) {
     90       request_permissions_.insert(std::make_pair(
     91           content::MEDIA_DEVICE_AUDIO_CAPTURE,
     92           MediaStreamTypeSettings(MEDIA_BLOCKED_BY_POLICY,
     93                                   request.requested_audio_device_id)));
     94     } else {
     95       request_permissions_.insert(std::make_pair(
     96           content::MEDIA_DEVICE_AUDIO_CAPTURE,
     97           MediaStreamTypeSettings(MEDIA_ALLOWED,
     98                                   request.requested_audio_device_id)));
     99     }
    100   }
    101   if (request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE ||
    102       request.request_type == content::MEDIA_OPEN_DEVICE) {
    103     if (GetDevicePolicy(prefs::kVideoCaptureAllowed,
    104                         prefs::kVideoCaptureAllowedUrls) == ALWAYS_DENY) {
    105       request_permissions_.insert(std::make_pair(
    106           content::MEDIA_DEVICE_VIDEO_CAPTURE,
    107           MediaStreamTypeSettings(MEDIA_BLOCKED_BY_POLICY,
    108                                   request.requested_video_device_id)));
    109     } else {
    110       request_permissions_.insert(std::make_pair(
    111           content::MEDIA_DEVICE_VIDEO_CAPTURE,
    112           MediaStreamTypeSettings(MEDIA_ALLOWED,
    113                                   request.requested_video_device_id)));
    114     }
    115   }
    116 }
    117 
    118 MediaStreamDevicesController::~MediaStreamDevicesController() {
    119   if (!callback_.is_null()) {
    120     callback_.Run(content::MediaStreamDevices(),
    121                   scoped_ptr<content::MediaStreamUI>());
    122   }
    123 }
    124 
    125 // static
    126 void MediaStreamDevicesController::RegisterProfilePrefs(
    127     user_prefs::PrefRegistrySyncable* prefs) {
    128   prefs->RegisterBooleanPref(prefs::kVideoCaptureAllowed,
    129                              true,
    130                              user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
    131   prefs->RegisterBooleanPref(prefs::kAudioCaptureAllowed,
    132                              true,
    133                              user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
    134   prefs->RegisterListPref(prefs::kVideoCaptureAllowedUrls,
    135                           user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
    136   prefs->RegisterListPref(prefs::kAudioCaptureAllowedUrls,
    137                           user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
    138 }
    139 
    140 
    141 bool MediaStreamDevicesController::DismissInfoBarAndTakeActionOnSettings() {
    142   // Tab capture is allowed for extensions only and infobar is not shown for
    143   // extensions.
    144   if (request_.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE ||
    145       request_.video_type == content::MEDIA_TAB_VIDEO_CAPTURE) {
    146     Deny(false);
    147     return true;
    148   }
    149 
    150   // Deny the request if the security origin is empty, this happens with
    151   // file access without |--allow-file-access-from-files| flag.
    152   if (request_.security_origin.is_empty()) {
    153     Deny(false);
    154     return true;
    155   }
    156 
    157   // Deny the request if there is no device attached to the OS.
    158   if (!HasAnyAvailableDevice()) {
    159     Deny(false);
    160     return true;
    161   }
    162 
    163   // Check if any allow exception has been made for this request.
    164   if (IsRequestAllowedByDefault()) {
    165     Accept(false);
    166     return true;
    167   }
    168 
    169   // Filter any parts of the request that have been blocked by default and deny
    170   // it if nothing is left to accept.
    171   if (FilterBlockedByDefaultDevices() == 0) {
    172     Deny(false);
    173     return true;
    174   }
    175 
    176   // Check if the media default setting is set to block.
    177   if (IsDefaultMediaAccessBlocked()) {
    178     Deny(false);
    179     return true;
    180   }
    181 
    182   if (request_.request_type == content::MEDIA_OPEN_DEVICE) {
    183     bool no_matched_audio_device =
    184         (request_.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE &&
    185          !request_.requested_audio_device_id.empty() &&
    186          MediaCaptureDevicesDispatcher::GetInstance()->GetRequestedAudioDevice(
    187              request_.requested_audio_device_id) == NULL);
    188     bool no_matched_video_device =
    189         (request_.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE &&
    190          !request_.requested_video_device_id.empty() &&
    191          MediaCaptureDevicesDispatcher::GetInstance()->GetRequestedVideoDevice(
    192              request_.requested_video_device_id) == NULL);
    193     if (no_matched_audio_device || no_matched_video_device) {
    194       Deny(false);
    195       return true;
    196     }
    197   }
    198 
    199   // Show the infobar.
    200   return false;
    201 }
    202 
    203 bool MediaStreamDevicesController::HasAudio() const {
    204   return IsDeviceAudioCaptureRequestedAndAllowed();
    205 }
    206 
    207 bool MediaStreamDevicesController::HasVideo() const {
    208   return IsDeviceVideoCaptureRequestedAndAllowed();
    209 }
    210 
    211 const std::string& MediaStreamDevicesController::GetSecurityOriginSpec() const {
    212   return request_.security_origin.spec();
    213 }
    214 
    215 void MediaStreamDevicesController::Accept(bool update_content_setting) {
    216   NotifyUIRequestAccepted();
    217 
    218   // Get the default devices for the request.
    219   content::MediaStreamDevices devices;
    220   bool audio_allowed = IsDeviceAudioCaptureRequestedAndAllowed();
    221   bool video_allowed = IsDeviceVideoCaptureRequestedAndAllowed();
    222   if (audio_allowed || video_allowed) {
    223     switch (request_.request_type) {
    224       case content::MEDIA_OPEN_DEVICE: {
    225         const content::MediaStreamDevice* device = NULL;
    226         // For open device request, when requested device_id is empty, pick
    227         // the first available of the given type. If requested device_id is
    228         // not empty, return the desired device if it's available. Otherwise,
    229         // return no device.
    230         if (audio_allowed &&
    231             request_.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
    232           if (!request_.requested_audio_device_id.empty()) {
    233             device = MediaCaptureDevicesDispatcher::GetInstance()->
    234                 GetRequestedAudioDevice(request_.requested_audio_device_id);
    235           } else {
    236             device = MediaCaptureDevicesDispatcher::GetInstance()->
    237                 GetFirstAvailableAudioDevice();
    238           }
    239         } else if (video_allowed &&
    240             request_.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE) {
    241           // Pepper API opens only one device at a time.
    242           if (!request_.requested_video_device_id.empty()) {
    243             device = MediaCaptureDevicesDispatcher::GetInstance()->
    244                 GetRequestedVideoDevice(request_.requested_video_device_id);
    245           } else {
    246             device = MediaCaptureDevicesDispatcher::GetInstance()->
    247                 GetFirstAvailableVideoDevice();
    248           }
    249         }
    250         if (device)
    251           devices.push_back(*device);
    252         break;
    253       }
    254       case content::MEDIA_GENERATE_STREAM: {
    255         bool get_default_audio_device = audio_allowed;
    256         bool get_default_video_device = video_allowed;
    257 
    258         // Get the exact audio or video device if an id is specified.
    259         if (audio_allowed && !request_.requested_audio_device_id.empty()) {
    260           const content::MediaStreamDevice* audio_device =
    261               MediaCaptureDevicesDispatcher::GetInstance()->
    262                   GetRequestedAudioDevice(request_.requested_audio_device_id);
    263           if (audio_device) {
    264             devices.push_back(*audio_device);
    265             get_default_audio_device = false;
    266           }
    267         }
    268         if (video_allowed && !request_.requested_video_device_id.empty()) {
    269           const content::MediaStreamDevice* video_device =
    270               MediaCaptureDevicesDispatcher::GetInstance()->
    271                   GetRequestedVideoDevice(request_.requested_video_device_id);
    272           if (video_device) {
    273             devices.push_back(*video_device);
    274             get_default_video_device = false;
    275           }
    276         }
    277 
    278         // If either or both audio and video devices were requested but not
    279         // specified by id, get the default devices.
    280         if (get_default_audio_device || get_default_video_device) {
    281           MediaCaptureDevicesDispatcher::GetInstance()->
    282               GetDefaultDevicesForProfile(profile_,
    283                                           get_default_audio_device,
    284                                           get_default_video_device,
    285                                           &devices);
    286         }
    287         break;
    288       }
    289       case content::MEDIA_DEVICE_ACCESS: {
    290         // Get the default devices for the request.
    291         MediaCaptureDevicesDispatcher::GetInstance()->
    292             GetDefaultDevicesForProfile(profile_,
    293                                         audio_allowed,
    294                                         video_allowed,
    295                                         &devices);
    296         break;
    297       }
    298       case content::MEDIA_ENUMERATE_DEVICES: {
    299         // Do nothing.
    300         NOTREACHED();
    301         break;
    302       }
    303     }  // switch
    304 
    305     // TODO(raymes): We currently set the content permission for non-https
    306     // websites for Pepper requests as well. This is temporary and should be
    307     // removed.
    308     if (update_content_setting) {
    309       if ((IsSchemeSecure() && !devices.empty()) ||
    310           request_.request_type == content::MEDIA_OPEN_DEVICE) {
    311         SetPermission(true);
    312       }
    313     }
    314   }
    315 
    316   scoped_ptr<content::MediaStreamUI> ui;
    317   if (!devices.empty()) {
    318     ui = MediaCaptureDevicesDispatcher::GetInstance()->
    319         GetMediaStreamCaptureIndicator()->RegisterMediaStream(
    320             web_contents_, devices);
    321   }
    322   content::MediaResponseCallback cb = callback_;
    323   callback_.Reset();
    324   cb.Run(devices, ui.Pass());
    325 }
    326 
    327 void MediaStreamDevicesController::Deny(bool update_content_setting) {
    328   NotifyUIRequestDenied();
    329 
    330   if (update_content_setting)
    331     SetPermission(false);
    332 
    333   content::MediaResponseCallback cb = callback_;
    334   callback_.Reset();
    335   cb.Run(content::MediaStreamDevices(), scoped_ptr<content::MediaStreamUI>());
    336 }
    337 
    338 MediaStreamDevicesController::DevicePolicy
    339 MediaStreamDevicesController::GetDevicePolicy(
    340     const char* policy_name,
    341     const char* whitelist_policy_name) const {
    342   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    343 
    344   // If the security origin policy matches a value in the whitelist, allow it.
    345   // Otherwise, check the |policy_name| master switch for the default behavior.
    346 
    347   PrefService* prefs = profile_->GetPrefs();
    348 
    349   // TODO(tommi): Remove the kiosk mode check when the whitelist below
    350   // is visible in the media exceptions UI.
    351   // See discussion here: https://codereview.chromium.org/15738004/
    352   if (IsInKioskMode()) {
    353     const base::ListValue* list = prefs->GetList(whitelist_policy_name);
    354     std::string value;
    355     for (size_t i = 0; i < list->GetSize(); ++i) {
    356       if (list->GetString(i, &value)) {
    357         ContentSettingsPattern pattern =
    358             ContentSettingsPattern::FromString(value);
    359         if (pattern == ContentSettingsPattern::Wildcard()) {
    360           DLOG(WARNING) << "Ignoring wildcard URL pattern: " << value;
    361           continue;
    362         }
    363         DLOG_IF(ERROR, !pattern.IsValid()) << "Invalid URL pattern: " << value;
    364         if (pattern.IsValid() && pattern.Matches(request_.security_origin))
    365           return ALWAYS_ALLOW;
    366       }
    367     }
    368   }
    369 
    370   // If a match was not found, check if audio capture is otherwise disallowed
    371   // or if the user should be prompted.  Setting the policy value to "true"
    372   // is equal to not setting it at all, so from hereon out, we will return
    373   // either POLICY_NOT_SET (prompt) or ALWAYS_DENY (no prompt, no access).
    374   if (!prefs->GetBoolean(policy_name))
    375     return ALWAYS_DENY;
    376 
    377   return POLICY_NOT_SET;
    378 }
    379 
    380 bool MediaStreamDevicesController::IsRequestAllowedByDefault() const {
    381   // The request from internal objects like chrome://URLs is always allowed.
    382   if (ShouldAlwaysAllowOrigin())
    383     return true;
    384 
    385   struct {
    386     bool has_capability;
    387     const char* policy_name;
    388     const char* list_policy_name;
    389     ContentSettingsType settings_type;
    390   } device_checks[] = {
    391     { IsDeviceAudioCaptureRequestedAndAllowed(), prefs::kAudioCaptureAllowed,
    392       prefs::kAudioCaptureAllowedUrls, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC },
    393     { IsDeviceVideoCaptureRequestedAndAllowed(), prefs::kVideoCaptureAllowed,
    394       prefs::kVideoCaptureAllowedUrls,
    395       CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA },
    396   };
    397 
    398   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(device_checks); ++i) {
    399     if (!device_checks[i].has_capability)
    400       continue;
    401 
    402     DevicePolicy policy = GetDevicePolicy(device_checks[i].policy_name,
    403                                           device_checks[i].list_policy_name);
    404 
    405     if (policy == ALWAYS_DENY)
    406       return false;
    407 
    408     if (policy == POLICY_NOT_SET) {
    409       // Only load content settings from secure origins unless it is a
    410       // content::MEDIA_OPEN_DEVICE (Pepper) request.
    411       if (!IsSchemeSecure() &&
    412           request_.request_type != content::MEDIA_OPEN_DEVICE) {
    413         return false;
    414       }
    415       if (profile_->GetHostContentSettingsMap()->GetContentSetting(
    416               request_.security_origin, request_.security_origin,
    417               device_checks[i].settings_type, NO_RESOURCE_IDENTIFIER) !=
    418               CONTENT_SETTING_ALLOW) {
    419         return false;
    420       }
    421     }
    422     // If we get here, then either policy is set to ALWAYS_ALLOW or the content
    423     // settings allow the request by default.
    424   }
    425 
    426   return true;
    427 }
    428 
    429 int MediaStreamDevicesController::FilterBlockedByDefaultDevices() {
    430   int requested_devices = 0;
    431 
    432   if (IsDeviceAudioCaptureRequestedAndAllowed()) {
    433     if (profile_->GetHostContentSettingsMap()->GetContentSetting(
    434         request_.security_origin,
    435         request_.security_origin,
    436         CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
    437         NO_RESOURCE_IDENTIFIER) == CONTENT_SETTING_BLOCK) {
    438       request_permissions_[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission =
    439           MEDIA_BLOCKED_BY_USER_SETTING;
    440     } else {
    441       ++requested_devices;
    442     }
    443   }
    444 
    445   if (IsDeviceVideoCaptureRequestedAndAllowed()) {
    446     if (profile_->GetHostContentSettingsMap()->GetContentSetting(
    447         request_.security_origin,
    448         request_.security_origin,
    449         CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
    450         NO_RESOURCE_IDENTIFIER) == CONTENT_SETTING_BLOCK) {
    451       request_permissions_[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission =
    452           MEDIA_BLOCKED_BY_USER_SETTING;
    453     } else {
    454       ++requested_devices;
    455     }
    456   }
    457 
    458   return requested_devices;
    459 }
    460 
    461 bool MediaStreamDevicesController::IsDefaultMediaAccessBlocked() const {
    462   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    463   // TODO(markusheintz): Replace CONTENT_SETTINGS_TYPE_MEDIA_STREAM with the
    464   // appropriate new CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC and
    465   // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
    466   ContentSetting current_setting =
    467       profile_->GetHostContentSettingsMap()->GetDefaultContentSetting(
    468           CONTENT_SETTINGS_TYPE_MEDIASTREAM, NULL);
    469   return (current_setting == CONTENT_SETTING_BLOCK);
    470 }
    471 
    472 bool MediaStreamDevicesController::IsSchemeSecure() const {
    473   return request_.security_origin.SchemeIsSecure() ||
    474       request_.security_origin.SchemeIs(extensions::kExtensionScheme) ||
    475       CommandLine::ForCurrentProcess()->HasSwitch(
    476           switches::kDisableUserMediaSecurity);
    477 }
    478 
    479 bool MediaStreamDevicesController::ShouldAlwaysAllowOrigin() const {
    480   // TODO(markusheintz): Replace CONTENT_SETTINGS_TYPE_MEDIA_STREAM with the
    481   // appropriate new CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC and
    482   // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
    483   return profile_->GetHostContentSettingsMap()->ShouldAllowAllContent(
    484       request_.security_origin, request_.security_origin,
    485       CONTENT_SETTINGS_TYPE_MEDIASTREAM);
    486 }
    487 
    488 void MediaStreamDevicesController::SetPermission(bool allowed) const {
    489   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    490   ContentSettingsPattern primary_pattern =
    491       ContentSettingsPattern::FromURLNoWildcard(request_.security_origin);
    492   // Check the pattern is valid or not. When the request is from a file access,
    493   // no exception will be made.
    494   if (!primary_pattern.IsValid())
    495     return;
    496 
    497   ContentSetting content_setting = allowed ?
    498       CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
    499   if (request_permissions_.find(content::MEDIA_DEVICE_AUDIO_CAPTURE) !=
    500       request_permissions_.end()) {
    501       profile_->GetHostContentSettingsMap()->SetContentSetting(
    502         primary_pattern,
    503         ContentSettingsPattern::Wildcard(),
    504         CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
    505         std::string(),
    506         content_setting);
    507   }
    508   if (request_permissions_.find(content::MEDIA_DEVICE_VIDEO_CAPTURE) !=
    509       request_permissions_.end()) {
    510     profile_->GetHostContentSettingsMap()->SetContentSetting(
    511         primary_pattern,
    512         ContentSettingsPattern::Wildcard(),
    513         CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
    514         std::string(),
    515         content_setting);
    516   }
    517 }
    518 
    519 void MediaStreamDevicesController::NotifyUIRequestAccepted() const {
    520   if (!content_settings_)
    521     return;
    522 
    523   content_settings_->OnMediaStreamPermissionSet(request_.security_origin,
    524                                                 request_permissions_);
    525 }
    526 
    527 void MediaStreamDevicesController::NotifyUIRequestDenied() {
    528   if (!content_settings_)
    529     return;
    530 
    531   if (IsDeviceAudioCaptureRequestedAndAllowed()) {
    532     request_permissions_[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission =
    533         MEDIA_BLOCKED_BY_USER;
    534   }
    535   if (IsDeviceVideoCaptureRequestedAndAllowed()) {
    536     request_permissions_[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission =
    537         MEDIA_BLOCKED_BY_USER;
    538   }
    539 
    540   content_settings_->OnMediaStreamPermissionSet(request_.security_origin,
    541                                                 request_permissions_);
    542 }
    543 
    544 bool MediaStreamDevicesController::IsDeviceAudioCaptureRequestedAndAllowed()
    545     const {
    546   MediaStreamTypeSettingsMap::const_iterator it =
    547       request_permissions_.find(content::MEDIA_DEVICE_AUDIO_CAPTURE);
    548   return (it != request_permissions_.end() &&
    549           it->second.permission == MEDIA_ALLOWED);
    550 }
    551 
    552 bool MediaStreamDevicesController::IsDeviceVideoCaptureRequestedAndAllowed()
    553     const {
    554   MediaStreamTypeSettingsMap::const_iterator it =
    555       request_permissions_.find(content::MEDIA_DEVICE_VIDEO_CAPTURE);
    556   return (it != request_permissions_.end() &&
    557           it->second.permission == MEDIA_ALLOWED);
    558 }
    559