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/metrics/histogram.h"
8 #include "base/prefs/scoped_user_pref_update.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/values.h"
11 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
12 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
13 #include "chrome/browser/media/media_stream_capture_indicator.h"
14 #include "chrome/browser/media/media_stream_device_permissions.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/common/pref_names.h"
19 #include "chrome/grit/generated_resources.h"
20 #include "components/content_settings/core/browser/host_content_settings_map.h"
21 #include "components/content_settings/core/common/content_settings.h"
22 #include "components/content_settings/core/common/content_settings_pattern.h"
23 #include "components/pref_registry/pref_registry_syncable.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/render_widget_host_view.h"
26 #include "content/public/common/media_stream_request.h"
27 #include "extensions/common/constants.h"
28 #include "grit/theme_resources.h"
29 #include "ui/base/l10n/l10n_util.h"
31 using content::BrowserThread
;
35 bool HasAvailableDevicesForRequest(const content::MediaStreamRequest
& request
) {
36 const content::MediaStreamDevices
* audio_devices
=
37 request
.audio_type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
?
38 &MediaCaptureDevicesDispatcher::GetInstance()
39 ->GetAudioCaptureDevices() :
42 const content::MediaStreamDevices
* video_devices
=
43 request
.video_type
== content::MEDIA_DEVICE_VIDEO_CAPTURE
?
44 &MediaCaptureDevicesDispatcher::GetInstance()
45 ->GetVideoCaptureDevices() :
48 // Check if we're being asked for audio and/or video and that either of those
49 // lists is empty. If they are, we do not have devices available for the
51 // TODO(tommi): It's kind of strange to have this here since if we fail this
52 // test, there'll be a UI shown that indicates to the user that access to
53 // non-existing audio/video devices has been denied. The user won't have
54 // any way to change that but there will be a UI shown which indicates that
56 if ((audio_devices
!= NULL
&& audio_devices
->empty()) ||
57 (video_devices
!= NULL
&& video_devices
->empty())) {
61 // Note: we check requested_[audio|video]_device_id before dereferencing
62 // [audio|video]_devices. If the requested device id is non-empty, then
63 // the corresponding device list must not be NULL.
65 if (!request
.requested_audio_device_id
.empty() &&
66 !audio_devices
->FindById(request
.requested_audio_device_id
)) {
70 if (!request
.requested_video_device_id
.empty() &&
71 !video_devices
->FindById(request
.requested_video_device_id
)) {
78 enum DevicePermissionActions
{
83 kPermissionActionsMax
// Must always be last!
86 // This is a wrapper around the call to
87 // TabSpecificContentSettings::OnMediaStreamPermissionSet, precomputing the
88 // information from |request_permissions| to a form which is understood by
89 // TabSpecificContentSettings.
90 void OnMediaStreamPermissionSet(
91 TabSpecificContentSettings
* content_settings
,
92 content::WebContents
* web_contents
,
93 const GURL
& request_origin
,
94 const MediaStreamDevicesController::MediaStreamTypeSettingsMap
&
95 request_permissions
) {
96 TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state
=
97 TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED
;
98 std::string selected_audio_device
;
99 std::string selected_video_device
;
100 std::string requested_audio_device
;
101 std::string requested_video_device
;
103 PrefService
* prefs
= Profile::FromBrowserContext(
104 web_contents
->GetBrowserContext())->GetPrefs();
105 auto it
= request_permissions
.find(content::MEDIA_DEVICE_AUDIO_CAPTURE
);
106 if (it
!= request_permissions
.end()) {
107 requested_audio_device
= it
->second
.requested_device_id
;
108 selected_audio_device
= requested_audio_device
.empty() ?
109 prefs
->GetString(prefs::kDefaultAudioCaptureDevice
) :
110 requested_audio_device
;
111 DCHECK_NE(MediaStreamDevicesController::MEDIA_NONE
, it
->second
.permission
);
113 it
->second
.permission
== MediaStreamDevicesController::MEDIA_ALLOWED
;
114 microphone_camera_state
|=
115 TabSpecificContentSettings::MICROPHONE_ACCESSED
|
116 (mic_allowed
? 0 : TabSpecificContentSettings::MICROPHONE_BLOCKED
);
119 it
= request_permissions
.find(content::MEDIA_DEVICE_VIDEO_CAPTURE
);
120 if (it
!= request_permissions
.end()) {
121 requested_video_device
= it
->second
.requested_device_id
;
122 selected_video_device
= requested_video_device
.empty() ?
123 prefs
->GetString(prefs::kDefaultVideoCaptureDevice
) :
124 requested_video_device
;
125 DCHECK_NE(MediaStreamDevicesController::MEDIA_NONE
, it
->second
.permission
);
127 it
->second
.permission
== MediaStreamDevicesController::MEDIA_ALLOWED
;
128 microphone_camera_state
|=
129 TabSpecificContentSettings::CAMERA_ACCESSED
|
130 (cam_allowed
? 0 : TabSpecificContentSettings::CAMERA_BLOCKED
);
133 content_settings
->OnMediaStreamPermissionSet(request_origin
,
134 microphone_camera_state
,
135 selected_audio_device
,
136 selected_video_device
,
137 requested_audio_device
,
138 requested_video_device
);
143 MediaStreamDevicesController::MediaStreamTypeSettings::MediaStreamTypeSettings(
144 Permission permission
, const std::string
& requested_device_id
):
145 permission(permission
), requested_device_id(requested_device_id
) {}
147 MediaStreamDevicesController::MediaStreamTypeSettings::
148 MediaStreamTypeSettings(): permission(MEDIA_NONE
) {}
150 MediaStreamDevicesController::MediaStreamTypeSettings::
151 ~MediaStreamTypeSettings() {}
153 MediaStreamDevicesController::MediaStreamDevicesController(
154 content::WebContents
* web_contents
,
155 const content::MediaStreamRequest
& request
,
156 const content::MediaResponseCallback
& callback
)
157 : web_contents_(web_contents
),
159 callback_(callback
) {
160 profile_
= Profile::FromBrowserContext(web_contents
->GetBrowserContext());
161 content_settings_
= TabSpecificContentSettings::FromWebContents(web_contents
);
163 // For MEDIA_OPEN_DEVICE requests (Pepper) we always request both webcam
164 // and microphone to avoid popping two infobars.
165 // We start with setting the requested media type to allowed or blocked
166 // depending on the policy. If not blocked by policy it may be blocked later
167 // in the two remaining filtering steps (by user setting or by user when
168 // clicking the infobar).
169 // TODO(grunell): It's not the nicest solution to let the MEDIA_OPEN_DEVICE
170 // case take a ride on the MEDIA_DEVICE_*_CAPTURE permission. Should be fixed.
171 if (request
.audio_type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
||
172 request
.request_type
== content::MEDIA_OPEN_DEVICE
) {
173 if (GetDevicePolicy(profile_
,
174 request_
.security_origin
,
175 prefs::kAudioCaptureAllowed
,
176 prefs::kAudioCaptureAllowedUrls
) == ALWAYS_DENY
) {
177 request_permissions_
.insert(std::make_pair(
178 content::MEDIA_DEVICE_AUDIO_CAPTURE
,
179 MediaStreamTypeSettings(MEDIA_BLOCKED_BY_POLICY
,
180 request
.requested_audio_device_id
)));
182 request_permissions_
.insert(std::make_pair(
183 content::MEDIA_DEVICE_AUDIO_CAPTURE
,
184 MediaStreamTypeSettings(MEDIA_ALLOWED
,
185 request
.requested_audio_device_id
)));
188 if (request
.video_type
== content::MEDIA_DEVICE_VIDEO_CAPTURE
||
189 request
.request_type
== content::MEDIA_OPEN_DEVICE
) {
190 if (GetDevicePolicy(profile_
,
191 request_
.security_origin
,
192 prefs::kVideoCaptureAllowed
,
193 prefs::kVideoCaptureAllowedUrls
) == ALWAYS_DENY
) {
194 request_permissions_
.insert(std::make_pair(
195 content::MEDIA_DEVICE_VIDEO_CAPTURE
,
196 MediaStreamTypeSettings(MEDIA_BLOCKED_BY_POLICY
,
197 request
.requested_video_device_id
)));
199 request_permissions_
.insert(std::make_pair(
200 content::MEDIA_DEVICE_VIDEO_CAPTURE
,
201 MediaStreamTypeSettings(MEDIA_ALLOWED
,
202 request
.requested_video_device_id
)));
207 MediaStreamDevicesController::~MediaStreamDevicesController() {
208 if (!callback_
.is_null()) {
209 callback_
.Run(content::MediaStreamDevices(),
210 content::MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN
,
211 scoped_ptr
<content::MediaStreamUI
>());
216 void MediaStreamDevicesController::RegisterProfilePrefs(
217 user_prefs::PrefRegistrySyncable
* prefs
) {
218 prefs
->RegisterBooleanPref(prefs::kVideoCaptureAllowed
, true);
219 prefs
->RegisterBooleanPref(prefs::kAudioCaptureAllowed
, true);
220 prefs
->RegisterListPref(prefs::kVideoCaptureAllowedUrls
);
221 prefs
->RegisterListPref(prefs::kAudioCaptureAllowedUrls
);
224 // TODO(gbillock): rename? doesn't actually dismiss. More of a 'check profile
225 // and system for compatibility' thing.
226 bool MediaStreamDevicesController::DismissInfoBarAndTakeActionOnSettings() {
227 // Tab capture is allowed for extensions only and infobar is not shown for
229 if (request_
.audio_type
== content::MEDIA_TAB_AUDIO_CAPTURE
||
230 request_
.video_type
== content::MEDIA_TAB_VIDEO_CAPTURE
) {
231 Deny(false, content::MEDIA_DEVICE_INVALID_STATE
);
235 // Deny the request if the security origin is empty, this happens with
236 // file access without |--allow-file-access-from-files| flag.
237 if (request_
.security_origin
.is_empty()) {
238 Deny(false, content::MEDIA_DEVICE_INVALID_SECURITY_ORIGIN
);
242 // Deny the request if there is no device attached to the OS of the
243 // requested type. If both audio and video is requested, both types must be
245 if (!HasAvailableDevicesForRequest(request_
)) {
246 Deny(false, content::MEDIA_DEVICE_NO_HARDWARE
);
250 // Check if any allow exception has been made for this request.
251 if (IsRequestAllowedByDefault()) {
256 // Filter any parts of the request that have been blocked by default and deny
257 // it if nothing is left to accept.
258 if (FilterBlockedByDefaultDevices() == 0) {
259 Deny(false, content::MEDIA_DEVICE_PERMISSION_DENIED
);
263 // Check if the media default setting is set to block.
264 if (IsDefaultMediaAccessBlocked()) {
265 Deny(false, content::MEDIA_DEVICE_PERMISSION_DENIED
);
273 bool MediaStreamDevicesController::HasAudio() const {
274 return IsDeviceAudioCaptureRequestedAndAllowed();
277 bool MediaStreamDevicesController::HasVideo() const {
278 return IsDeviceVideoCaptureRequestedAndAllowed();
281 const std::string
& MediaStreamDevicesController::GetSecurityOriginSpec() const {
282 return request_
.security_origin
.spec();
285 void MediaStreamDevicesController::Accept(bool update_content_setting
) {
286 NotifyUIRequestAccepted();
288 // Get the default devices for the request.
289 content::MediaStreamDevices devices
;
290 bool audio_allowed
= IsDeviceAudioCaptureRequestedAndAllowed();
291 bool video_allowed
= IsDeviceVideoCaptureRequestedAndAllowed();
292 if (audio_allowed
|| video_allowed
) {
293 switch (request_
.request_type
) {
294 case content::MEDIA_OPEN_DEVICE
: {
295 const content::MediaStreamDevice
* device
= NULL
;
296 // For open device request, when requested device_id is empty, pick
297 // the first available of the given type. If requested device_id is
298 // not empty, return the desired device if it's available. Otherwise,
301 request_
.audio_type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
) {
302 if (!request_
.requested_audio_device_id
.empty()) {
303 device
= MediaCaptureDevicesDispatcher::GetInstance()->
304 GetRequestedAudioDevice(request_
.requested_audio_device_id
);
306 device
= MediaCaptureDevicesDispatcher::GetInstance()->
307 GetFirstAvailableAudioDevice();
309 } else if (video_allowed
&&
310 request_
.video_type
== content::MEDIA_DEVICE_VIDEO_CAPTURE
) {
311 // Pepper API opens only one device at a time.
312 if (!request_
.requested_video_device_id
.empty()) {
313 device
= MediaCaptureDevicesDispatcher::GetInstance()->
314 GetRequestedVideoDevice(request_
.requested_video_device_id
);
316 device
= MediaCaptureDevicesDispatcher::GetInstance()->
317 GetFirstAvailableVideoDevice();
321 devices
.push_back(*device
);
324 case content::MEDIA_GENERATE_STREAM
: {
325 bool get_default_audio_device
= audio_allowed
;
326 bool get_default_video_device
= video_allowed
;
328 // Get the exact audio or video device if an id is specified.
329 if (audio_allowed
&& !request_
.requested_audio_device_id
.empty()) {
330 const content::MediaStreamDevice
* audio_device
=
331 MediaCaptureDevicesDispatcher::GetInstance()->
332 GetRequestedAudioDevice(request_
.requested_audio_device_id
);
334 devices
.push_back(*audio_device
);
335 get_default_audio_device
= false;
338 if (video_allowed
&& !request_
.requested_video_device_id
.empty()) {
339 const content::MediaStreamDevice
* video_device
=
340 MediaCaptureDevicesDispatcher::GetInstance()->
341 GetRequestedVideoDevice(request_
.requested_video_device_id
);
343 devices
.push_back(*video_device
);
344 get_default_video_device
= false;
348 // If either or both audio and video devices were requested but not
349 // specified by id, get the default devices.
350 if (get_default_audio_device
|| get_default_video_device
) {
351 MediaCaptureDevicesDispatcher::GetInstance()->
352 GetDefaultDevicesForProfile(profile_
,
353 get_default_audio_device
,
354 get_default_video_device
,
359 case content::MEDIA_DEVICE_ACCESS
: {
360 // Get the default devices for the request.
361 MediaCaptureDevicesDispatcher::GetInstance()->
362 GetDefaultDevicesForProfile(profile_
,
368 case content::MEDIA_ENUMERATE_DEVICES
: {
375 // TODO(raymes): We currently set the content permission for non-https
376 // websites for Pepper requests as well. This is temporary and should be
378 if (update_content_setting
) {
379 if ((IsSchemeSecure() && !devices
.empty()) ||
380 request_
.request_type
== content::MEDIA_OPEN_DEVICE
) {
381 StorePermission(true);
386 profile_
->GetHostContentSettingsMap()->UpdateLastUsageByPattern(
387 ContentSettingsPattern::FromURLNoWildcard(request_
.security_origin
),
388 ContentSettingsPattern::Wildcard(),
389 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
);
392 profile_
->GetHostContentSettingsMap()->UpdateLastUsageByPattern(
393 ContentSettingsPattern::FromURLNoWildcard(request_
.security_origin
),
394 ContentSettingsPattern::Wildcard(),
395 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
);
399 scoped_ptr
<content::MediaStreamUI
> ui
;
400 if (!devices
.empty()) {
401 ui
= MediaCaptureDevicesDispatcher::GetInstance()->
402 GetMediaStreamCaptureIndicator()->RegisterMediaStream(
403 web_contents_
, devices
);
405 content::MediaResponseCallback cb
= callback_
;
409 content::MEDIA_DEVICE_NO_HARDWARE
: content::MEDIA_DEVICE_OK
,
413 void MediaStreamDevicesController::Deny(
414 bool update_content_setting
,
415 content::MediaStreamRequestResult result
) {
416 DLOG(WARNING
) << "MediaStreamDevicesController::Deny: " << result
;
417 NotifyUIRequestDenied();
419 if (update_content_setting
) {
420 // Store sticky permissions if |update_content_setting|.
421 CHECK_EQ(content::MEDIA_DEVICE_PERMISSION_DENIED
, result
);
422 StorePermission(false);
425 content::MediaResponseCallback cb
= callback_
;
427 cb
.Run(content::MediaStreamDevices(),
429 scoped_ptr
<content::MediaStreamUI
>());
432 int MediaStreamDevicesController::GetIconID() const {
434 return IDR_INFOBAR_MEDIA_STREAM_CAMERA
;
436 return IDR_INFOBAR_MEDIA_STREAM_MIC
;
439 base::string16
MediaStreamDevicesController::GetMessageText() const {
440 int message_id
= IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO
;
442 message_id
= IDS_MEDIA_CAPTURE_VIDEO_ONLY
;
443 else if (!HasVideo())
444 message_id
= IDS_MEDIA_CAPTURE_AUDIO_ONLY
;
445 return l10n_util::GetStringFUTF16(
446 message_id
, base::UTF8ToUTF16(GetSecurityOriginSpec()));
449 base::string16
MediaStreamDevicesController::GetMessageTextFragment() const {
450 int message_id
= IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO_PERMISSION_FRAGMENT
;
452 message_id
= IDS_MEDIA_CAPTURE_VIDEO_ONLY_PERMISSION_FRAGMENT
;
453 else if (!HasVideo())
454 message_id
= IDS_MEDIA_CAPTURE_AUDIO_ONLY_PERMISSION_FRAGMENT
;
455 return l10n_util::GetStringUTF16(message_id
);
458 bool MediaStreamDevicesController::HasUserGesture() const {
459 return request_
.user_gesture
;
462 GURL
MediaStreamDevicesController::GetRequestingHostname() const {
463 return request_
.security_origin
;
466 void MediaStreamDevicesController::PermissionGranted() {
467 GURL
origin(GetSecurityOriginSpec());
468 if (origin
.SchemeIsSecure()) {
469 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions",
470 kAllowHttps
, kPermissionActionsMax
);
472 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions",
473 kAllowHttp
, kPermissionActionsMax
);
478 void MediaStreamDevicesController::PermissionDenied() {
479 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions",
480 kDeny
, kPermissionActionsMax
);
481 Deny(true, content::MEDIA_DEVICE_PERMISSION_DENIED
);
484 void MediaStreamDevicesController::Cancelled() {
485 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions",
486 kCancel
, kPermissionActionsMax
);
487 Deny(false, content::MEDIA_DEVICE_PERMISSION_DISMISSED
);
490 void MediaStreamDevicesController::RequestFinished() {
494 bool MediaStreamDevicesController::IsRequestAllowedByDefault() const {
495 // The request from internal objects like chrome://URLs is always allowed.
496 if (CheckAllowAllMediaStreamContentForOrigin(
497 profile_
, request_
.security_origin
,
498 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
) &&
499 CheckAllowAllMediaStreamContentForOrigin(
500 profile_
, request_
.security_origin
,
501 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
)) {
507 const char* policy_name
;
508 const char* list_policy_name
;
509 ContentSettingsType settings_type
;
510 } device_checks
[] = {
511 { IsDeviceAudioCaptureRequestedAndAllowed(), prefs::kAudioCaptureAllowed
,
512 prefs::kAudioCaptureAllowedUrls
, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
},
513 { IsDeviceVideoCaptureRequestedAndAllowed(), prefs::kVideoCaptureAllowed
,
514 prefs::kVideoCaptureAllowedUrls
,
515 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
},
518 for (size_t i
= 0; i
< arraysize(device_checks
); ++i
) {
519 if (!device_checks
[i
].has_capability
)
522 MediaStreamDevicePolicy policy
=
523 GetDevicePolicy(profile_
,
524 request_
.security_origin
,
525 device_checks
[i
].policy_name
,
526 device_checks
[i
].list_policy_name
);
528 if (policy
== ALWAYS_DENY
)
531 if (policy
== POLICY_NOT_SET
) {
532 // Only load content settings from secure origins unless it is a
533 // content::MEDIA_OPEN_DEVICE (Pepper) request.
534 if (!IsSchemeSecure() &&
535 request_
.request_type
!= content::MEDIA_OPEN_DEVICE
) {
538 if (profile_
->GetHostContentSettingsMap()->GetContentSetting(
539 request_
.security_origin
,
540 request_
.security_origin
,
541 device_checks
[i
].settings_type
,
542 content_settings::ResourceIdentifier()) !=
543 CONTENT_SETTING_ALLOW
) {
547 // If we get here, then either policy is set to ALWAYS_ALLOW or the content
548 // settings allow the request by default.
554 int MediaStreamDevicesController::FilterBlockedByDefaultDevices() {
555 int requested_devices
= 0;
557 if (IsDeviceAudioCaptureRequestedAndAllowed()) {
558 if (profile_
->GetHostContentSettingsMap()->GetContentSetting(
559 request_
.security_origin
,
560 request_
.security_origin
,
561 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
,
562 content_settings::ResourceIdentifier()) ==
563 CONTENT_SETTING_BLOCK
) {
564 request_permissions_
[content::MEDIA_DEVICE_AUDIO_CAPTURE
].permission
=
565 MEDIA_BLOCKED_BY_USER_SETTING
;
571 if (IsDeviceVideoCaptureRequestedAndAllowed()) {
572 if (profile_
->GetHostContentSettingsMap()->GetContentSetting(
573 request_
.security_origin
,
574 request_
.security_origin
,
575 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
,
576 content_settings::ResourceIdentifier()) ==
577 CONTENT_SETTING_BLOCK
) {
578 request_permissions_
[content::MEDIA_DEVICE_VIDEO_CAPTURE
].permission
=
579 MEDIA_BLOCKED_BY_USER_SETTING
;
585 return requested_devices
;
588 bool MediaStreamDevicesController::IsDefaultMediaAccessBlocked() const {
589 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
590 return (profile_
->GetHostContentSettingsMap()->GetDefaultContentSetting(
591 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
, NULL
)
592 == CONTENT_SETTING_BLOCK
&&
593 profile_
->GetHostContentSettingsMap()->GetDefaultContentSetting(
594 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
, NULL
)
595 == CONTENT_SETTING_BLOCK
);
598 bool MediaStreamDevicesController::IsSchemeSecure() const {
599 return request_
.security_origin
.SchemeIsSecure() ||
600 request_
.security_origin
.SchemeIs(extensions::kExtensionScheme
);
603 void MediaStreamDevicesController::StorePermission(bool allowed
) const {
604 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
605 ContentSettingsPattern primary_pattern
=
606 ContentSettingsPattern::FromURLNoWildcard(request_
.security_origin
);
607 // Check the pattern is valid or not. When the request is from a file access,
608 // no exception will be made.
609 if (!primary_pattern
.IsValid())
612 ContentSetting content_setting
= allowed
?
613 CONTENT_SETTING_ALLOW
: CONTENT_SETTING_BLOCK
;
614 if (request_permissions_
.find(content::MEDIA_DEVICE_AUDIO_CAPTURE
) !=
615 request_permissions_
.end()) {
616 profile_
->GetHostContentSettingsMap()->SetContentSetting(
618 ContentSettingsPattern::Wildcard(),
619 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
,
623 if (request_permissions_
.find(content::MEDIA_DEVICE_VIDEO_CAPTURE
) !=
624 request_permissions_
.end()) {
625 profile_
->GetHostContentSettingsMap()->SetContentSetting(
627 ContentSettingsPattern::Wildcard(),
628 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
,
634 void MediaStreamDevicesController::NotifyUIRequestAccepted() const {
635 if (!content_settings_
)
638 OnMediaStreamPermissionSet(content_settings_
,
640 request_
.security_origin
,
641 request_permissions_
);
644 void MediaStreamDevicesController::NotifyUIRequestDenied() {
645 if (!content_settings_
)
648 if (IsDeviceAudioCaptureRequestedAndAllowed()) {
649 request_permissions_
[content::MEDIA_DEVICE_AUDIO_CAPTURE
].permission
=
650 MEDIA_BLOCKED_BY_USER
;
652 if (IsDeviceVideoCaptureRequestedAndAllowed()) {
653 request_permissions_
[content::MEDIA_DEVICE_VIDEO_CAPTURE
].permission
=
654 MEDIA_BLOCKED_BY_USER
;
657 OnMediaStreamPermissionSet(content_settings_
,
659 request_
.security_origin
,
660 request_permissions_
);
663 bool MediaStreamDevicesController::IsDeviceAudioCaptureRequestedAndAllowed()
665 MediaStreamTypeSettingsMap::const_iterator it
=
666 request_permissions_
.find(content::MEDIA_DEVICE_AUDIO_CAPTURE
);
667 return (it
!= request_permissions_
.end() && IsCaptureDeviceRequestAllowed() &&
668 it
->second
.permission
== MEDIA_ALLOWED
);
671 bool MediaStreamDevicesController::IsDeviceVideoCaptureRequestedAndAllowed()
673 MediaStreamTypeSettingsMap::const_iterator it
=
674 request_permissions_
.find(content::MEDIA_DEVICE_VIDEO_CAPTURE
);
675 return (it
!= request_permissions_
.end() && IsCaptureDeviceRequestAllowed() &&
676 it
->second
.permission
== MEDIA_ALLOWED
);
679 bool MediaStreamDevicesController::IsCaptureDeviceRequestAllowed() const {
680 #if defined(OS_ANDROID)
681 // Don't approve device requests if the tab was hidden.
682 // TODO(qinmin): Add a test for this. http://crbug.com/396869.
683 return web_contents_
->GetRenderWidgetHostView()->IsShowing();