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.
5 #include "chrome/browser/media/media_stream_devices_controller.h"
7 #include "base/command_line.h"
8 #include "base/metrics/histogram.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/prefs/scoped_user_pref_update.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/values.h"
13 #include "chrome/browser/content_settings/content_settings_provider.h"
14 #include "chrome/browser/content_settings/host_content_settings_map.h"
15 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
16 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
17 #include "chrome/browser/media/media_stream_capture_indicator.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/ui/browser.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "chrome/common/content_settings.h"
22 #include "chrome/common/content_settings_pattern.h"
23 #include "chrome/common/pref_names.h"
24 #include "components/pref_registry/pref_registry_syncable.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/render_widget_host_view.h"
27 #include "content/public/common/media_stream_request.h"
28 #include "extensions/common/constants.h"
29 #include "grit/generated_resources.h"
30 #include "grit/theme_resources.h"
31 #include "ui/base/l10n/l10n_util.h"
33 #if defined(OS_CHROMEOS)
34 #include "chrome/browser/chromeos/login/users/user_manager.h"
37 using content::BrowserThread;
41 bool HasAvailableDevicesForRequest(const content::MediaStreamRequest& request) {
42 const content::MediaStreamDevices* audio_devices =
43 request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE ?
44 &MediaCaptureDevicesDispatcher::GetInstance()
45 ->GetAudioCaptureDevices() :
48 const content::MediaStreamDevices* video_devices =
49 request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE ?
50 &MediaCaptureDevicesDispatcher::GetInstance()
51 ->GetVideoCaptureDevices() :
54 // Check if we're being asked for audio and/or video and that either of those
55 // lists is empty. If they are, we do not have devices available for the
57 // TODO(tommi): It's kind of strange to have this here since if we fail this
58 // test, there'll be a UI shown that indicates to the user that access to
59 // non-existing audio/video devices has been denied. The user won't have
60 // any way to change that but there will be a UI shown which indicates that
62 if ((audio_devices != NULL && audio_devices->empty()) ||
63 (video_devices != NULL && video_devices->empty())) {
67 // Note: we check requested_[audio|video]_device_id before dereferencing
68 // [audio|video]_devices. If the requested device id is non-empty, then
69 // the corresponding device list must not be NULL.
71 if (!request.requested_audio_device_id.empty() &&
72 !audio_devices->FindById(request.requested_audio_device_id)) {
76 if (!request.requested_video_device_id.empty() &&
77 !video_devices->FindById(request.requested_video_device_id)) {
84 bool IsInKioskMode() {
85 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode))
88 #if defined(OS_CHROMEOS)
89 const chromeos::UserManager* user_manager = chromeos::UserManager::Get();
90 return user_manager && user_manager->IsLoggedInAsKioskApp();
96 enum DevicePermissionActions {
101 kPermissionActionsMax // Must always be last!
106 MediaStreamDevicesController::MediaStreamTypeSettings::MediaStreamTypeSettings(
107 Permission permission, const std::string& requested_device_id):
108 permission(permission), requested_device_id(requested_device_id) {}
110 MediaStreamDevicesController::MediaStreamTypeSettings::
111 MediaStreamTypeSettings(): permission(MEDIA_NONE) {}
113 MediaStreamDevicesController::MediaStreamTypeSettings::
114 ~MediaStreamTypeSettings() {}
116 MediaStreamDevicesController::MediaStreamDevicesController(
117 content::WebContents* web_contents,
118 const content::MediaStreamRequest& request,
119 const content::MediaResponseCallback& callback)
120 : web_contents_(web_contents),
122 callback_(callback) {
123 profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext());
124 content_settings_ = TabSpecificContentSettings::FromWebContents(web_contents);
126 // For MEDIA_OPEN_DEVICE requests (Pepper) we always request both webcam
127 // and microphone to avoid popping two infobars.
128 // We start with setting the requested media type to allowed or blocked
129 // depending on the policy. If not blocked by policy it may be blocked later
130 // in the two remaining filtering steps (by user setting or by user when
131 // clicking the infobar).
132 // TODO(grunell): It's not the nicest solution to let the MEDIA_OPEN_DEVICE
133 // case take a ride on the MEDIA_DEVICE_*_CAPTURE permission. Should be fixed.
134 if (request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE ||
135 request.request_type == content::MEDIA_OPEN_DEVICE) {
136 if (GetDevicePolicy(prefs::kAudioCaptureAllowed,
137 prefs::kAudioCaptureAllowedUrls) == ALWAYS_DENY) {
138 request_permissions_.insert(std::make_pair(
139 content::MEDIA_DEVICE_AUDIO_CAPTURE,
140 MediaStreamTypeSettings(MEDIA_BLOCKED_BY_POLICY,
141 request.requested_audio_device_id)));
143 request_permissions_.insert(std::make_pair(
144 content::MEDIA_DEVICE_AUDIO_CAPTURE,
145 MediaStreamTypeSettings(MEDIA_ALLOWED,
146 request.requested_audio_device_id)));
149 if (request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE ||
150 request.request_type == content::MEDIA_OPEN_DEVICE) {
151 if (GetDevicePolicy(prefs::kVideoCaptureAllowed,
152 prefs::kVideoCaptureAllowedUrls) == ALWAYS_DENY) {
153 request_permissions_.insert(std::make_pair(
154 content::MEDIA_DEVICE_VIDEO_CAPTURE,
155 MediaStreamTypeSettings(MEDIA_BLOCKED_BY_POLICY,
156 request.requested_video_device_id)));
158 request_permissions_.insert(std::make_pair(
159 content::MEDIA_DEVICE_VIDEO_CAPTURE,
160 MediaStreamTypeSettings(MEDIA_ALLOWED,
161 request.requested_video_device_id)));
166 MediaStreamDevicesController::~MediaStreamDevicesController() {
167 if (!callback_.is_null()) {
168 callback_.Run(content::MediaStreamDevices(),
169 content::MEDIA_DEVICE_INVALID_STATE,
170 scoped_ptr<content::MediaStreamUI>());
175 void MediaStreamDevicesController::RegisterProfilePrefs(
176 user_prefs::PrefRegistrySyncable* prefs) {
177 prefs->RegisterBooleanPref(prefs::kVideoCaptureAllowed,
179 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
180 prefs->RegisterBooleanPref(prefs::kAudioCaptureAllowed,
182 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
183 prefs->RegisterListPref(prefs::kVideoCaptureAllowedUrls,
184 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
185 prefs->RegisterListPref(prefs::kAudioCaptureAllowedUrls,
186 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
189 // TODO(gbillock): rename? doesn't actually dismiss. More of a 'check profile
190 // and system for compatibility' thing.
191 bool MediaStreamDevicesController::DismissInfoBarAndTakeActionOnSettings() {
192 // Tab capture is allowed for extensions only and infobar is not shown for
194 if (request_.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE ||
195 request_.video_type == content::MEDIA_TAB_VIDEO_CAPTURE) {
196 Deny(false, content::MEDIA_DEVICE_INVALID_STATE);
200 // Deny the request if the security origin is empty, this happens with
201 // file access without |--allow-file-access-from-files| flag.
202 if (request_.security_origin.is_empty()) {
203 Deny(false, content::MEDIA_DEVICE_INVALID_SECURITY_ORIGIN);
207 // Deny the request if there is no device attached to the OS of the
208 // requested type. If both audio and video is requested, both types must be
210 if (!HasAvailableDevicesForRequest(request_)) {
211 Deny(false, content::MEDIA_DEVICE_NO_HARDWARE);
215 // Check if any allow exception has been made for this request.
216 if (IsRequestAllowedByDefault()) {
221 // Filter any parts of the request that have been blocked by default and deny
222 // it if nothing is left to accept.
223 if (FilterBlockedByDefaultDevices() == 0) {
224 Deny(false, content::MEDIA_DEVICE_PERMISSION_DENIED);
228 // Check if the media default setting is set to block.
229 if (IsDefaultMediaAccessBlocked()) {
230 Deny(false, content::MEDIA_DEVICE_PERMISSION_DENIED);
238 bool MediaStreamDevicesController::HasAudio() const {
239 return IsDeviceAudioCaptureRequestedAndAllowed();
242 bool MediaStreamDevicesController::HasVideo() const {
243 return IsDeviceVideoCaptureRequestedAndAllowed();
246 const std::string& MediaStreamDevicesController::GetSecurityOriginSpec() const {
247 return request_.security_origin.spec();
250 void MediaStreamDevicesController::Accept(bool update_content_setting) {
251 NotifyUIRequestAccepted();
253 // Get the default devices for the request.
254 content::MediaStreamDevices devices;
255 bool audio_allowed = IsDeviceAudioCaptureRequestedAndAllowed();
256 bool video_allowed = IsDeviceVideoCaptureRequestedAndAllowed();
257 if (audio_allowed || video_allowed) {
258 switch (request_.request_type) {
259 case content::MEDIA_OPEN_DEVICE: {
260 const content::MediaStreamDevice* device = NULL;
261 // For open device request, when requested device_id is empty, pick
262 // the first available of the given type. If requested device_id is
263 // not empty, return the desired device if it's available. Otherwise,
266 request_.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
267 if (!request_.requested_audio_device_id.empty()) {
268 device = MediaCaptureDevicesDispatcher::GetInstance()->
269 GetRequestedAudioDevice(request_.requested_audio_device_id);
271 device = MediaCaptureDevicesDispatcher::GetInstance()->
272 GetFirstAvailableAudioDevice();
274 } else if (video_allowed &&
275 request_.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE) {
276 // Pepper API opens only one device at a time.
277 if (!request_.requested_video_device_id.empty()) {
278 device = MediaCaptureDevicesDispatcher::GetInstance()->
279 GetRequestedVideoDevice(request_.requested_video_device_id);
281 device = MediaCaptureDevicesDispatcher::GetInstance()->
282 GetFirstAvailableVideoDevice();
286 devices.push_back(*device);
289 case content::MEDIA_GENERATE_STREAM: {
290 bool get_default_audio_device = audio_allowed;
291 bool get_default_video_device = video_allowed;
293 // Get the exact audio or video device if an id is specified.
294 if (audio_allowed && !request_.requested_audio_device_id.empty()) {
295 const content::MediaStreamDevice* audio_device =
296 MediaCaptureDevicesDispatcher::GetInstance()->
297 GetRequestedAudioDevice(request_.requested_audio_device_id);
299 devices.push_back(*audio_device);
300 get_default_audio_device = false;
303 if (video_allowed && !request_.requested_video_device_id.empty()) {
304 const content::MediaStreamDevice* video_device =
305 MediaCaptureDevicesDispatcher::GetInstance()->
306 GetRequestedVideoDevice(request_.requested_video_device_id);
308 devices.push_back(*video_device);
309 get_default_video_device = false;
313 // If either or both audio and video devices were requested but not
314 // specified by id, get the default devices.
315 if (get_default_audio_device || get_default_video_device) {
316 MediaCaptureDevicesDispatcher::GetInstance()->
317 GetDefaultDevicesForProfile(profile_,
318 get_default_audio_device,
319 get_default_video_device,
324 case content::MEDIA_DEVICE_ACCESS: {
325 // Get the default devices for the request.
326 MediaCaptureDevicesDispatcher::GetInstance()->
327 GetDefaultDevicesForProfile(profile_,
333 case content::MEDIA_ENUMERATE_DEVICES: {
340 // TODO(raymes): We currently set the content permission for non-https
341 // websites for Pepper requests as well. This is temporary and should be
343 if (update_content_setting) {
344 if ((IsSchemeSecure() && !devices.empty()) ||
345 request_.request_type == content::MEDIA_OPEN_DEVICE) {
351 scoped_ptr<content::MediaStreamUI> ui;
352 if (!devices.empty()) {
353 ui = MediaCaptureDevicesDispatcher::GetInstance()->
354 GetMediaStreamCaptureIndicator()->RegisterMediaStream(
355 web_contents_, devices);
357 content::MediaResponseCallback cb = callback_;
361 content::MEDIA_DEVICE_NO_HARDWARE : content::MEDIA_DEVICE_OK,
365 void MediaStreamDevicesController::Deny(
366 bool update_content_setting,
367 content::MediaStreamRequestResult result) {
368 DLOG(WARNING) << "MediaStreamDevicesController::Deny: " << result;
369 NotifyUIRequestDenied();
371 if (update_content_setting) {
372 CHECK_EQ(content::MEDIA_DEVICE_PERMISSION_DENIED, result);
373 SetPermission(false);
376 content::MediaResponseCallback cb = callback_;
378 cb.Run(content::MediaStreamDevices(),
380 scoped_ptr<content::MediaStreamUI>());
383 int MediaStreamDevicesController::GetIconID() const {
385 return IDR_INFOBAR_MEDIA_STREAM_CAMERA;
387 return IDR_INFOBAR_MEDIA_STREAM_MIC;
390 base::string16 MediaStreamDevicesController::GetMessageText() const {
391 int message_id = IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO;
393 message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY;
394 else if (!HasVideo())
395 message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY;
396 return l10n_util::GetStringFUTF16(
397 message_id, base::UTF8ToUTF16(GetSecurityOriginSpec()));
400 base::string16 MediaStreamDevicesController::GetMessageTextFragment() const {
401 int message_id = IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO_PERMISSION_FRAGMENT;
403 message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY_PERMISSION_FRAGMENT;
404 else if (!HasVideo())
405 message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY_PERMISSION_FRAGMENT;
406 return l10n_util::GetStringUTF16(message_id);
409 bool MediaStreamDevicesController::HasUserGesture() const {
410 return request_.user_gesture;
413 GURL MediaStreamDevicesController::GetRequestingHostname() const {
414 return request_.security_origin;
417 void MediaStreamDevicesController::PermissionGranted() {
418 GURL origin(GetSecurityOriginSpec());
419 if (origin.SchemeIsSecure()) {
420 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions",
421 kAllowHttps, kPermissionActionsMax);
423 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions",
424 kAllowHttp, kPermissionActionsMax);
429 void MediaStreamDevicesController::PermissionDenied() {
430 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions",
431 kDeny, kPermissionActionsMax);
432 Deny(true, content::MEDIA_DEVICE_PERMISSION_DENIED);
435 void MediaStreamDevicesController::Cancelled() {
436 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions",
437 kCancel, kPermissionActionsMax);
438 Deny(false, content::MEDIA_DEVICE_PERMISSION_DISMISSED);
441 void MediaStreamDevicesController::RequestFinished() {
445 MediaStreamDevicesController::DevicePolicy
446 MediaStreamDevicesController::GetDevicePolicy(
447 const char* policy_name,
448 const char* whitelist_policy_name) const {
449 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
451 // If the security origin policy matches a value in the whitelist, allow it.
452 // Otherwise, check the |policy_name| master switch for the default behavior.
454 PrefService* prefs = profile_->GetPrefs();
456 // TODO(tommi): Remove the kiosk mode check when the whitelist below
457 // is visible in the media exceptions UI.
458 // See discussion here: https://codereview.chromium.org/15738004/
459 if (IsInKioskMode()) {
460 const base::ListValue* list = prefs->GetList(whitelist_policy_name);
462 for (size_t i = 0; i < list->GetSize(); ++i) {
463 if (list->GetString(i, &value)) {
464 ContentSettingsPattern pattern =
465 ContentSettingsPattern::FromString(value);
466 if (pattern == ContentSettingsPattern::Wildcard()) {
467 DLOG(WARNING) << "Ignoring wildcard URL pattern: " << value;
470 DLOG_IF(ERROR, !pattern.IsValid()) << "Invalid URL pattern: " << value;
471 if (pattern.IsValid() && pattern.Matches(request_.security_origin))
477 // If a match was not found, check if audio capture is otherwise disallowed
478 // or if the user should be prompted. Setting the policy value to "true"
479 // is equal to not setting it at all, so from hereon out, we will return
480 // either POLICY_NOT_SET (prompt) or ALWAYS_DENY (no prompt, no access).
481 if (!prefs->GetBoolean(policy_name))
484 return POLICY_NOT_SET;
487 bool MediaStreamDevicesController::IsRequestAllowedByDefault() const {
488 // The request from internal objects like chrome://URLs is always allowed.
489 if (ShouldAlwaysAllowOrigin())
494 const char* policy_name;
495 const char* list_policy_name;
496 ContentSettingsType settings_type;
497 } device_checks[] = {
498 { IsDeviceAudioCaptureRequestedAndAllowed(), prefs::kAudioCaptureAllowed,
499 prefs::kAudioCaptureAllowedUrls, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC },
500 { IsDeviceVideoCaptureRequestedAndAllowed(), prefs::kVideoCaptureAllowed,
501 prefs::kVideoCaptureAllowedUrls,
502 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA },
505 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(device_checks); ++i) {
506 if (!device_checks[i].has_capability)
509 DevicePolicy policy = GetDevicePolicy(device_checks[i].policy_name,
510 device_checks[i].list_policy_name);
512 if (policy == ALWAYS_DENY)
515 if (policy == POLICY_NOT_SET) {
516 // Only load content settings from secure origins unless it is a
517 // content::MEDIA_OPEN_DEVICE (Pepper) request.
518 if (!IsSchemeSecure() &&
519 request_.request_type != content::MEDIA_OPEN_DEVICE) {
522 if (profile_->GetHostContentSettingsMap()->GetContentSetting(
523 request_.security_origin, request_.security_origin,
524 device_checks[i].settings_type, NO_RESOURCE_IDENTIFIER) !=
525 CONTENT_SETTING_ALLOW) {
529 // If we get here, then either policy is set to ALWAYS_ALLOW or the content
530 // settings allow the request by default.
536 int MediaStreamDevicesController::FilterBlockedByDefaultDevices() {
537 int requested_devices = 0;
539 if (IsDeviceAudioCaptureRequestedAndAllowed()) {
540 if (profile_->GetHostContentSettingsMap()->GetContentSetting(
541 request_.security_origin,
542 request_.security_origin,
543 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
544 NO_RESOURCE_IDENTIFIER) == CONTENT_SETTING_BLOCK) {
545 request_permissions_[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission =
546 MEDIA_BLOCKED_BY_USER_SETTING;
552 if (IsDeviceVideoCaptureRequestedAndAllowed()) {
553 if (profile_->GetHostContentSettingsMap()->GetContentSetting(
554 request_.security_origin,
555 request_.security_origin,
556 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
557 NO_RESOURCE_IDENTIFIER) == CONTENT_SETTING_BLOCK) {
558 request_permissions_[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission =
559 MEDIA_BLOCKED_BY_USER_SETTING;
565 return requested_devices;
568 bool MediaStreamDevicesController::IsDefaultMediaAccessBlocked() const {
569 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
570 // TODO(markusheintz): Replace CONTENT_SETTINGS_TYPE_MEDIA_STREAM with the
571 // appropriate new CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC and
572 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
573 ContentSetting current_setting =
574 profile_->GetHostContentSettingsMap()->GetDefaultContentSetting(
575 CONTENT_SETTINGS_TYPE_MEDIASTREAM, NULL);
576 return (current_setting == CONTENT_SETTING_BLOCK);
579 bool MediaStreamDevicesController::IsSchemeSecure() const {
580 return request_.security_origin.SchemeIsSecure() ||
581 request_.security_origin.SchemeIs(extensions::kExtensionScheme);
584 bool MediaStreamDevicesController::ShouldAlwaysAllowOrigin() const {
585 // TODO(markusheintz): Replace CONTENT_SETTINGS_TYPE_MEDIA_STREAM with the
586 // appropriate new CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC and
587 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
588 return profile_->GetHostContentSettingsMap()->ShouldAllowAllContent(
589 request_.security_origin, request_.security_origin,
590 CONTENT_SETTINGS_TYPE_MEDIASTREAM);
593 void MediaStreamDevicesController::SetPermission(bool allowed) const {
594 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
595 ContentSettingsPattern primary_pattern =
596 ContentSettingsPattern::FromURLNoWildcard(request_.security_origin);
597 // Check the pattern is valid or not. When the request is from a file access,
598 // no exception will be made.
599 if (!primary_pattern.IsValid())
602 ContentSetting content_setting = allowed ?
603 CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
604 if (request_permissions_.find(content::MEDIA_DEVICE_AUDIO_CAPTURE) !=
605 request_permissions_.end()) {
606 profile_->GetHostContentSettingsMap()->SetContentSetting(
608 ContentSettingsPattern::Wildcard(),
609 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
613 if (request_permissions_.find(content::MEDIA_DEVICE_VIDEO_CAPTURE) !=
614 request_permissions_.end()) {
615 profile_->GetHostContentSettingsMap()->SetContentSetting(
617 ContentSettingsPattern::Wildcard(),
618 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
624 void MediaStreamDevicesController::NotifyUIRequestAccepted() const {
625 if (!content_settings_)
628 content_settings_->OnMediaStreamPermissionSet(request_.security_origin,
629 request_permissions_);
632 void MediaStreamDevicesController::NotifyUIRequestDenied() {
633 if (!content_settings_)
636 if (IsDeviceAudioCaptureRequestedAndAllowed()) {
637 request_permissions_[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission =
638 MEDIA_BLOCKED_BY_USER;
640 if (IsDeviceVideoCaptureRequestedAndAllowed()) {
641 request_permissions_[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission =
642 MEDIA_BLOCKED_BY_USER;
645 content_settings_->OnMediaStreamPermissionSet(request_.security_origin,
646 request_permissions_);
649 bool MediaStreamDevicesController::IsDeviceAudioCaptureRequestedAndAllowed()
651 MediaStreamTypeSettingsMap::const_iterator it =
652 request_permissions_.find(content::MEDIA_DEVICE_AUDIO_CAPTURE);
653 return (it != request_permissions_.end() && IsCaptureDeviceRequestAllowed() &&
654 it->second.permission == MEDIA_ALLOWED);
657 bool MediaStreamDevicesController::IsDeviceVideoCaptureRequestedAndAllowed()
659 MediaStreamTypeSettingsMap::const_iterator it =
660 request_permissions_.find(content::MEDIA_DEVICE_VIDEO_CAPTURE);
661 return (it != request_permissions_.end() && IsCaptureDeviceRequestAllowed() &&
662 it->second.permission == MEDIA_ALLOWED);
665 bool MediaStreamDevicesController::IsCaptureDeviceRequestAllowed() const {
666 #if defined(OS_ANDROID)
667 // Don't approve device requests if the tab was hidden.
668 // TODO(qinmin): Add a test for this. http://crbug.com/396869.
669 return web_contents_->GetRenderWidgetHostView()->IsShowing();