Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / chrome / browser / media / media_stream_devices_controller.cc
blob0f08b8c6a39bcea91cab7eb5d8685c0b7edc5773
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;
33 namespace {
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() :
40 NULL;
42 const content::MediaStreamDevices* video_devices =
43 request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE ?
44 &MediaCaptureDevicesDispatcher::GetInstance()
45 ->GetVideoCaptureDevices() :
46 NULL;
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
50 // request.
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
55 // access is blocked.
56 if ((audio_devices != NULL && audio_devices->empty()) ||
57 (video_devices != NULL && video_devices->empty())) {
58 return false;
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)) {
67 return false;
70 if (!request.requested_video_device_id.empty() &&
71 !video_devices->FindById(request.requested_video_device_id)) {
72 return false;
75 return true;
78 enum DevicePermissionActions {
79 kAllowHttps = 0,
80 kAllowHttp,
81 kDeny,
82 kCancel,
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);
112 bool mic_allowed =
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);
126 bool cam_allowed =
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);
141 } // namespace
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),
158 request_(request),
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)));
181 } else {
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)));
198 } else {
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>());
215 // static
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
228 // extensions.
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);
232 return true;
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);
239 return true;
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
244 // available.
245 if (!HasAvailableDevicesForRequest(request_)) {
246 Deny(false, content::MEDIA_DEVICE_NO_HARDWARE);
247 return true;
250 // Check if any allow exception has been made for this request.
251 if (IsRequestAllowedByDefault()) {
252 Accept(false);
253 return true;
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);
260 return true;
263 // Check if the media default setting is set to block.
264 if (IsDefaultMediaAccessBlocked()) {
265 Deny(false, content::MEDIA_DEVICE_PERMISSION_DENIED);
266 return true;
269 // Show the infobar.
270 return false;
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,
299 // return no device.
300 if (audio_allowed &&
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);
305 } else {
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);
315 } else {
316 device = MediaCaptureDevicesDispatcher::GetInstance()->
317 GetFirstAvailableVideoDevice();
320 if (device)
321 devices.push_back(*device);
322 break;
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);
333 if (audio_device) {
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);
342 if (video_device) {
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,
355 &devices);
357 break;
359 case content::MEDIA_DEVICE_ACCESS: {
360 // Get the default devices for the request.
361 MediaCaptureDevicesDispatcher::GetInstance()->
362 GetDefaultDevicesForProfile(profile_,
363 audio_allowed,
364 video_allowed,
365 &devices);
366 break;
368 case content::MEDIA_ENUMERATE_DEVICES: {
369 // Do nothing.
370 NOTREACHED();
371 break;
373 } // switch
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
377 // removed.
378 if (update_content_setting) {
379 if ((IsSchemeSecure() && !devices.empty()) ||
380 request_.request_type == content::MEDIA_OPEN_DEVICE) {
381 StorePermission(true);
385 if (audio_allowed) {
386 profile_->GetHostContentSettingsMap()->UpdateLastUsageByPattern(
387 ContentSettingsPattern::FromURLNoWildcard(request_.security_origin),
388 ContentSettingsPattern::Wildcard(),
389 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC);
391 if (video_allowed) {
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_;
406 callback_.Reset();
407 cb.Run(devices,
408 devices.empty() ?
409 content::MEDIA_DEVICE_NO_HARDWARE : content::MEDIA_DEVICE_OK,
410 ui.Pass());
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_;
426 callback_.Reset();
427 cb.Run(content::MediaStreamDevices(),
428 result,
429 scoped_ptr<content::MediaStreamUI>());
432 int MediaStreamDevicesController::GetIconID() const {
433 if (HasVideo())
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;
441 if (!HasAudio())
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;
451 if (!HasAudio())
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);
471 } else {
472 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions",
473 kAllowHttp, kPermissionActionsMax);
475 Accept(true);
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() {
491 delete this;
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)) {
502 return true;
505 struct {
506 bool has_capability;
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)
520 continue;
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)
529 return false;
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) {
536 return false;
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) {
544 return false;
547 // If we get here, then either policy is set to ALWAYS_ALLOW or the content
548 // settings allow the request by default.
551 return true;
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;
566 } else {
567 ++requested_devices;
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;
580 } else {
581 ++requested_devices;
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())
610 return;
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(
617 primary_pattern,
618 ContentSettingsPattern::Wildcard(),
619 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
620 std::string(),
621 content_setting);
623 if (request_permissions_.find(content::MEDIA_DEVICE_VIDEO_CAPTURE) !=
624 request_permissions_.end()) {
625 profile_->GetHostContentSettingsMap()->SetContentSetting(
626 primary_pattern,
627 ContentSettingsPattern::Wildcard(),
628 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
629 std::string(),
630 content_setting);
634 void MediaStreamDevicesController::NotifyUIRequestAccepted() const {
635 if (!content_settings_)
636 return;
638 OnMediaStreamPermissionSet(content_settings_,
639 web_contents_,
640 request_.security_origin,
641 request_permissions_);
644 void MediaStreamDevicesController::NotifyUIRequestDenied() {
645 if (!content_settings_)
646 return;
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_,
658 web_contents_,
659 request_.security_origin,
660 request_permissions_);
663 bool MediaStreamDevicesController::IsDeviceAudioCaptureRequestedAndAllowed()
664 const {
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()
672 const {
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();
684 #endif
685 return true;