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/content_settings_provider.h"
21 #include "components/content_settings/core/browser/host_content_settings_map.h"
22 #include "components/content_settings/core/common/content_settings.h"
23 #include "components/content_settings/core/common/content_settings_pattern.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/theme_resources.h"
30 #include "ui/base/l10n/l10n_util.h"
32 using content::BrowserThread
;
36 bool HasAvailableDevicesForRequest(const content::MediaStreamRequest
& request
) {
37 const content::MediaStreamDevices
* audio_devices
=
38 request
.audio_type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
?
39 &MediaCaptureDevicesDispatcher::GetInstance()
40 ->GetAudioCaptureDevices() :
43 const content::MediaStreamDevices
* video_devices
=
44 request
.video_type
== content::MEDIA_DEVICE_VIDEO_CAPTURE
?
45 &MediaCaptureDevicesDispatcher::GetInstance()
46 ->GetVideoCaptureDevices() :
49 // Check if we're being asked for audio and/or video and that either of those
50 // lists is empty. If they are, we do not have devices available for the
52 // TODO(tommi): It's kind of strange to have this here since if we fail this
53 // test, there'll be a UI shown that indicates to the user that access to
54 // non-existing audio/video devices has been denied. The user won't have
55 // any way to change that but there will be a UI shown which indicates that
57 if ((audio_devices
!= NULL
&& audio_devices
->empty()) ||
58 (video_devices
!= NULL
&& video_devices
->empty())) {
62 // Note: we check requested_[audio|video]_device_id before dereferencing
63 // [audio|video]_devices. If the requested device id is non-empty, then
64 // the corresponding device list must not be NULL.
66 if (!request
.requested_audio_device_id
.empty() &&
67 !audio_devices
->FindById(request
.requested_audio_device_id
)) {
71 if (!request
.requested_video_device_id
.empty() &&
72 !video_devices
->FindById(request
.requested_video_device_id
)) {
79 enum DevicePermissionActions
{
84 kPermissionActionsMax
// Must always be last!
87 // This is a wrapper around the call to
88 // TabSpecificContentSettings::OnMediaStreamPermissionSet, precomputing the
89 // information from |request_permissions| to a form which is understood by
90 // TabSpecificContentSettings.
91 void OnMediaStreamPermissionSet(
92 TabSpecificContentSettings
* content_settings
,
93 content::WebContents
* web_contents
,
94 const GURL
& request_origin
,
95 const MediaStreamDevicesController::MediaStreamTypeSettingsMap
&
96 request_permissions
) {
97 TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state
=
98 TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED
;
99 std::string selected_audio_device
;
100 std::string selected_video_device
;
101 std::string requested_audio_device
;
102 std::string requested_video_device
;
104 PrefService
* prefs
= Profile::FromBrowserContext(
105 web_contents
->GetBrowserContext())->GetPrefs();
106 auto it
= request_permissions
.find(content::MEDIA_DEVICE_AUDIO_CAPTURE
);
107 if (it
!= request_permissions
.end()) {
108 requested_audio_device
= it
->second
.requested_device_id
;
109 selected_audio_device
= requested_audio_device
.empty() ?
110 prefs
->GetString(prefs::kDefaultAudioCaptureDevice
) :
111 requested_audio_device
;
112 DCHECK_NE(MediaStreamDevicesController::MEDIA_NONE
, it
->second
.permission
);
114 it
->second
.permission
== MediaStreamDevicesController::MEDIA_ALLOWED
;
115 microphone_camera_state
|=
116 TabSpecificContentSettings::MICROPHONE_ACCESSED
|
117 (mic_allowed
? 0 : TabSpecificContentSettings::MICROPHONE_BLOCKED
);
120 it
= request_permissions
.find(content::MEDIA_DEVICE_VIDEO_CAPTURE
);
121 if (it
!= request_permissions
.end()) {
122 requested_video_device
= it
->second
.requested_device_id
;
123 selected_video_device
= requested_video_device
.empty() ?
124 prefs
->GetString(prefs::kDefaultVideoCaptureDevice
) :
125 requested_video_device
;
126 DCHECK_NE(MediaStreamDevicesController::MEDIA_NONE
, it
->second
.permission
);
128 it
->second
.permission
== MediaStreamDevicesController::MEDIA_ALLOWED
;
129 microphone_camera_state
|=
130 TabSpecificContentSettings::CAMERA_ACCESSED
|
131 (cam_allowed
? 0 : TabSpecificContentSettings::CAMERA_BLOCKED
);
134 content_settings
->OnMediaStreamPermissionSet(request_origin
,
135 microphone_camera_state
,
136 selected_audio_device
,
137 selected_video_device
,
138 requested_audio_device
,
139 requested_video_device
);
144 MediaStreamDevicesController::MediaStreamTypeSettings::MediaStreamTypeSettings(
145 Permission permission
, const std::string
& requested_device_id
):
146 permission(permission
), requested_device_id(requested_device_id
) {}
148 MediaStreamDevicesController::MediaStreamTypeSettings::
149 MediaStreamTypeSettings(): permission(MEDIA_NONE
) {}
151 MediaStreamDevicesController::MediaStreamTypeSettings::
152 ~MediaStreamTypeSettings() {}
154 MediaStreamDevicesController::MediaStreamDevicesController(
155 content::WebContents
* web_contents
,
156 const content::MediaStreamRequest
& request
,
157 const content::MediaResponseCallback
& callback
)
158 : web_contents_(web_contents
),
160 callback_(callback
) {
161 profile_
= Profile::FromBrowserContext(web_contents
->GetBrowserContext());
162 content_settings_
= TabSpecificContentSettings::FromWebContents(web_contents
);
164 // For MEDIA_OPEN_DEVICE requests (Pepper) we always request both webcam
165 // and microphone to avoid popping two infobars.
166 // We start with setting the requested media type to allowed or blocked
167 // depending on the policy. If not blocked by policy it may be blocked later
168 // in the two remaining filtering steps (by user setting or by user when
169 // clicking the infobar).
170 // TODO(grunell): It's not the nicest solution to let the MEDIA_OPEN_DEVICE
171 // case take a ride on the MEDIA_DEVICE_*_CAPTURE permission. Should be fixed.
172 if (request
.audio_type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
||
173 request
.request_type
== content::MEDIA_OPEN_DEVICE
) {
174 if (GetDevicePolicy(profile_
,
175 request_
.security_origin
,
176 prefs::kAudioCaptureAllowed
,
177 prefs::kAudioCaptureAllowedUrls
) == ALWAYS_DENY
) {
178 request_permissions_
.insert(std::make_pair(
179 content::MEDIA_DEVICE_AUDIO_CAPTURE
,
180 MediaStreamTypeSettings(MEDIA_BLOCKED_BY_POLICY
,
181 request
.requested_audio_device_id
)));
183 request_permissions_
.insert(std::make_pair(
184 content::MEDIA_DEVICE_AUDIO_CAPTURE
,
185 MediaStreamTypeSettings(MEDIA_ALLOWED
,
186 request
.requested_audio_device_id
)));
189 if (request
.video_type
== content::MEDIA_DEVICE_VIDEO_CAPTURE
||
190 request
.request_type
== content::MEDIA_OPEN_DEVICE
) {
191 if (GetDevicePolicy(profile_
,
192 request_
.security_origin
,
193 prefs::kVideoCaptureAllowed
,
194 prefs::kVideoCaptureAllowedUrls
) == ALWAYS_DENY
) {
195 request_permissions_
.insert(std::make_pair(
196 content::MEDIA_DEVICE_VIDEO_CAPTURE
,
197 MediaStreamTypeSettings(MEDIA_BLOCKED_BY_POLICY
,
198 request
.requested_video_device_id
)));
200 request_permissions_
.insert(std::make_pair(
201 content::MEDIA_DEVICE_VIDEO_CAPTURE
,
202 MediaStreamTypeSettings(MEDIA_ALLOWED
,
203 request
.requested_video_device_id
)));
208 MediaStreamDevicesController::~MediaStreamDevicesController() {
209 if (!callback_
.is_null()) {
210 callback_
.Run(content::MediaStreamDevices(),
211 content::MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN
,
212 scoped_ptr
<content::MediaStreamUI
>());
217 void MediaStreamDevicesController::RegisterProfilePrefs(
218 user_prefs::PrefRegistrySyncable
* prefs
) {
219 prefs
->RegisterBooleanPref(prefs::kVideoCaptureAllowed
,
221 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
222 prefs
->RegisterBooleanPref(prefs::kAudioCaptureAllowed
,
224 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
225 prefs
->RegisterListPref(prefs::kVideoCaptureAllowedUrls
,
226 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
227 prefs
->RegisterListPref(prefs::kAudioCaptureAllowedUrls
,
228 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
231 // TODO(gbillock): rename? doesn't actually dismiss. More of a 'check profile
232 // and system for compatibility' thing.
233 bool MediaStreamDevicesController::DismissInfoBarAndTakeActionOnSettings() {
234 // Tab capture is allowed for extensions only and infobar is not shown for
236 if (request_
.audio_type
== content::MEDIA_TAB_AUDIO_CAPTURE
||
237 request_
.video_type
== content::MEDIA_TAB_VIDEO_CAPTURE
) {
238 Deny(false, content::MEDIA_DEVICE_INVALID_STATE
);
242 // Deny the request if the security origin is empty, this happens with
243 // file access without |--allow-file-access-from-files| flag.
244 if (request_
.security_origin
.is_empty()) {
245 Deny(false, content::MEDIA_DEVICE_INVALID_SECURITY_ORIGIN
);
249 // Deny the request if there is no device attached to the OS of the
250 // requested type. If both audio and video is requested, both types must be
252 if (!HasAvailableDevicesForRequest(request_
)) {
253 Deny(false, content::MEDIA_DEVICE_NO_HARDWARE
);
257 // Check if any allow exception has been made for this request.
258 if (IsRequestAllowedByDefault()) {
263 // Filter any parts of the request that have been blocked by default and deny
264 // it if nothing is left to accept.
265 if (FilterBlockedByDefaultDevices() == 0) {
266 Deny(false, content::MEDIA_DEVICE_PERMISSION_DENIED
);
270 // Check if the media default setting is set to block.
271 if (IsDefaultMediaAccessBlocked()) {
272 Deny(false, content::MEDIA_DEVICE_PERMISSION_DENIED
);
280 bool MediaStreamDevicesController::HasAudio() const {
281 return IsDeviceAudioCaptureRequestedAndAllowed();
284 bool MediaStreamDevicesController::HasVideo() const {
285 return IsDeviceVideoCaptureRequestedAndAllowed();
288 const std::string
& MediaStreamDevicesController::GetSecurityOriginSpec() const {
289 return request_
.security_origin
.spec();
292 void MediaStreamDevicesController::Accept(bool update_content_setting
) {
293 NotifyUIRequestAccepted();
295 // Get the default devices for the request.
296 content::MediaStreamDevices devices
;
297 bool audio_allowed
= IsDeviceAudioCaptureRequestedAndAllowed();
298 bool video_allowed
= IsDeviceVideoCaptureRequestedAndAllowed();
299 if (audio_allowed
|| video_allowed
) {
300 switch (request_
.request_type
) {
301 case content::MEDIA_OPEN_DEVICE
: {
302 const content::MediaStreamDevice
* device
= NULL
;
303 // For open device request, when requested device_id is empty, pick
304 // the first available of the given type. If requested device_id is
305 // not empty, return the desired device if it's available. Otherwise,
308 request_
.audio_type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
) {
309 if (!request_
.requested_audio_device_id
.empty()) {
310 device
= MediaCaptureDevicesDispatcher::GetInstance()->
311 GetRequestedAudioDevice(request_
.requested_audio_device_id
);
313 device
= MediaCaptureDevicesDispatcher::GetInstance()->
314 GetFirstAvailableAudioDevice();
316 } else if (video_allowed
&&
317 request_
.video_type
== content::MEDIA_DEVICE_VIDEO_CAPTURE
) {
318 // Pepper API opens only one device at a time.
319 if (!request_
.requested_video_device_id
.empty()) {
320 device
= MediaCaptureDevicesDispatcher::GetInstance()->
321 GetRequestedVideoDevice(request_
.requested_video_device_id
);
323 device
= MediaCaptureDevicesDispatcher::GetInstance()->
324 GetFirstAvailableVideoDevice();
328 devices
.push_back(*device
);
331 case content::MEDIA_GENERATE_STREAM
: {
332 bool get_default_audio_device
= audio_allowed
;
333 bool get_default_video_device
= video_allowed
;
335 // Get the exact audio or video device if an id is specified.
336 if (audio_allowed
&& !request_
.requested_audio_device_id
.empty()) {
337 const content::MediaStreamDevice
* audio_device
=
338 MediaCaptureDevicesDispatcher::GetInstance()->
339 GetRequestedAudioDevice(request_
.requested_audio_device_id
);
341 devices
.push_back(*audio_device
);
342 get_default_audio_device
= false;
345 if (video_allowed
&& !request_
.requested_video_device_id
.empty()) {
346 const content::MediaStreamDevice
* video_device
=
347 MediaCaptureDevicesDispatcher::GetInstance()->
348 GetRequestedVideoDevice(request_
.requested_video_device_id
);
350 devices
.push_back(*video_device
);
351 get_default_video_device
= false;
355 // If either or both audio and video devices were requested but not
356 // specified by id, get the default devices.
357 if (get_default_audio_device
|| get_default_video_device
) {
358 MediaCaptureDevicesDispatcher::GetInstance()->
359 GetDefaultDevicesForProfile(profile_
,
360 get_default_audio_device
,
361 get_default_video_device
,
366 case content::MEDIA_DEVICE_ACCESS
: {
367 // Get the default devices for the request.
368 MediaCaptureDevicesDispatcher::GetInstance()->
369 GetDefaultDevicesForProfile(profile_
,
375 case content::MEDIA_ENUMERATE_DEVICES
: {
382 // TODO(raymes): We currently set the content permission for non-https
383 // websites for Pepper requests as well. This is temporary and should be
385 if (update_content_setting
) {
386 if ((IsSchemeSecure() && !devices
.empty()) ||
387 request_
.request_type
== content::MEDIA_OPEN_DEVICE
) {
388 StorePermission(true);
393 profile_
->GetHostContentSettingsMap()->UpdateLastUsageByPattern(
394 ContentSettingsPattern::FromURLNoWildcard(request_
.security_origin
),
395 ContentSettingsPattern::Wildcard(),
396 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
);
399 profile_
->GetHostContentSettingsMap()->UpdateLastUsageByPattern(
400 ContentSettingsPattern::FromURLNoWildcard(request_
.security_origin
),
401 ContentSettingsPattern::Wildcard(),
402 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
);
406 scoped_ptr
<content::MediaStreamUI
> ui
;
407 if (!devices
.empty()) {
408 ui
= MediaCaptureDevicesDispatcher::GetInstance()->
409 GetMediaStreamCaptureIndicator()->RegisterMediaStream(
410 web_contents_
, devices
);
412 content::MediaResponseCallback cb
= callback_
;
416 content::MEDIA_DEVICE_NO_HARDWARE
: content::MEDIA_DEVICE_OK
,
420 void MediaStreamDevicesController::Deny(
421 bool update_content_setting
,
422 content::MediaStreamRequestResult result
) {
423 DLOG(WARNING
) << "MediaStreamDevicesController::Deny: " << result
;
424 NotifyUIRequestDenied();
426 if (update_content_setting
) {
427 // Store sticky permissions if |update_content_setting|.
428 CHECK_EQ(content::MEDIA_DEVICE_PERMISSION_DENIED
, result
);
429 StorePermission(false);
432 content::MediaResponseCallback cb
= callback_
;
434 cb
.Run(content::MediaStreamDevices(),
436 scoped_ptr
<content::MediaStreamUI
>());
439 int MediaStreamDevicesController::GetIconID() const {
441 return IDR_INFOBAR_MEDIA_STREAM_CAMERA
;
443 return IDR_INFOBAR_MEDIA_STREAM_MIC
;
446 base::string16
MediaStreamDevicesController::GetMessageText() const {
447 int message_id
= IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO
;
449 message_id
= IDS_MEDIA_CAPTURE_VIDEO_ONLY
;
450 else if (!HasVideo())
451 message_id
= IDS_MEDIA_CAPTURE_AUDIO_ONLY
;
452 return l10n_util::GetStringFUTF16(
453 message_id
, base::UTF8ToUTF16(GetSecurityOriginSpec()));
456 base::string16
MediaStreamDevicesController::GetMessageTextFragment() const {
457 int message_id
= IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO_PERMISSION_FRAGMENT
;
459 message_id
= IDS_MEDIA_CAPTURE_VIDEO_ONLY_PERMISSION_FRAGMENT
;
460 else if (!HasVideo())
461 message_id
= IDS_MEDIA_CAPTURE_AUDIO_ONLY_PERMISSION_FRAGMENT
;
462 return l10n_util::GetStringUTF16(message_id
);
465 bool MediaStreamDevicesController::HasUserGesture() const {
466 return request_
.user_gesture
;
469 GURL
MediaStreamDevicesController::GetRequestingHostname() const {
470 return request_
.security_origin
;
473 void MediaStreamDevicesController::PermissionGranted() {
474 GURL
origin(GetSecurityOriginSpec());
475 if (origin
.SchemeIsSecure()) {
476 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions",
477 kAllowHttps
, kPermissionActionsMax
);
479 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions",
480 kAllowHttp
, kPermissionActionsMax
);
485 void MediaStreamDevicesController::PermissionDenied() {
486 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions",
487 kDeny
, kPermissionActionsMax
);
488 Deny(true, content::MEDIA_DEVICE_PERMISSION_DENIED
);
491 void MediaStreamDevicesController::Cancelled() {
492 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions",
493 kCancel
, kPermissionActionsMax
);
494 Deny(false, content::MEDIA_DEVICE_PERMISSION_DISMISSED
);
497 void MediaStreamDevicesController::RequestFinished() {
501 bool MediaStreamDevicesController::IsRequestAllowedByDefault() const {
502 // The request from internal objects like chrome://URLs is always allowed.
503 if (CheckAllowAllMediaStreamContentForOrigin(profile_
,
504 request_
.security_origin
)) {
510 const char* policy_name
;
511 const char* list_policy_name
;
512 ContentSettingsType settings_type
;
513 } device_checks
[] = {
514 { IsDeviceAudioCaptureRequestedAndAllowed(), prefs::kAudioCaptureAllowed
,
515 prefs::kAudioCaptureAllowedUrls
, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
},
516 { IsDeviceVideoCaptureRequestedAndAllowed(), prefs::kVideoCaptureAllowed
,
517 prefs::kVideoCaptureAllowedUrls
,
518 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
},
521 for (size_t i
= 0; i
< arraysize(device_checks
); ++i
) {
522 if (!device_checks
[i
].has_capability
)
525 MediaStreamDevicePolicy policy
=
526 GetDevicePolicy(profile_
,
527 request_
.security_origin
,
528 device_checks
[i
].policy_name
,
529 device_checks
[i
].list_policy_name
);
531 if (policy
== ALWAYS_DENY
)
534 if (policy
== POLICY_NOT_SET
) {
535 // Only load content settings from secure origins unless it is a
536 // content::MEDIA_OPEN_DEVICE (Pepper) request.
537 if (!IsSchemeSecure() &&
538 request_
.request_type
!= content::MEDIA_OPEN_DEVICE
) {
541 if (profile_
->GetHostContentSettingsMap()->GetContentSetting(
542 request_
.security_origin
, request_
.security_origin
,
543 device_checks
[i
].settings_type
, NO_RESOURCE_IDENTIFIER
) !=
544 CONTENT_SETTING_ALLOW
) {
548 // If we get here, then either policy is set to ALWAYS_ALLOW or the content
549 // settings allow the request by default.
555 int MediaStreamDevicesController::FilterBlockedByDefaultDevices() {
556 int requested_devices
= 0;
558 if (IsDeviceAudioCaptureRequestedAndAllowed()) {
559 if (profile_
->GetHostContentSettingsMap()->GetContentSetting(
560 request_
.security_origin
,
561 request_
.security_origin
,
562 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
,
563 NO_RESOURCE_IDENTIFIER
) == 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 NO_RESOURCE_IDENTIFIER
) == CONTENT_SETTING_BLOCK
) {
577 request_permissions_
[content::MEDIA_DEVICE_VIDEO_CAPTURE
].permission
=
578 MEDIA_BLOCKED_BY_USER_SETTING
;
584 return requested_devices
;
587 bool MediaStreamDevicesController::IsDefaultMediaAccessBlocked() const {
588 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
589 // TODO(markusheintz): Replace CONTENT_SETTINGS_TYPE_MEDIA_STREAM with the
590 // appropriate new CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC and
591 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
592 ContentSetting current_setting
=
593 profile_
->GetHostContentSettingsMap()->GetDefaultContentSetting(
594 CONTENT_SETTINGS_TYPE_MEDIASTREAM
, NULL
);
595 return (current_setting
== 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(BrowserThread::CurrentlyOn(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();