Prevent chrome://net-internals/#export from flickering
[chromium-blink-merge.git] / chrome / browser / media / media_stream_devices_controller.cc
blobcc371d52d592f293d56bd227a80b3e7f64914d6e
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;
34 namespace {
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() :
41 NULL;
43 const content::MediaStreamDevices* video_devices =
44 request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE ?
45 &MediaCaptureDevicesDispatcher::GetInstance()
46 ->GetVideoCaptureDevices() :
47 NULL;
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
51 // request.
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
56 // access is blocked.
57 if ((audio_devices != NULL && audio_devices->empty()) ||
58 (video_devices != NULL && video_devices->empty())) {
59 return false;
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)) {
68 return false;
71 if (!request.requested_video_device_id.empty() &&
72 !video_devices->FindById(request.requested_video_device_id)) {
73 return false;
76 return true;
79 enum DevicePermissionActions {
80 kAllowHttps = 0,
81 kAllowHttp,
82 kDeny,
83 kCancel,
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);
113 bool mic_allowed =
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);
127 bool cam_allowed =
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);
142 } // namespace
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),
159 request_(request),
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)));
182 } else {
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)));
199 } else {
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>());
216 // static
217 void MediaStreamDevicesController::RegisterProfilePrefs(
218 user_prefs::PrefRegistrySyncable* prefs) {
219 prefs->RegisterBooleanPref(prefs::kVideoCaptureAllowed,
220 true,
221 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
222 prefs->RegisterBooleanPref(prefs::kAudioCaptureAllowed,
223 true,
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
235 // extensions.
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);
239 return true;
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);
246 return true;
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
251 // available.
252 if (!HasAvailableDevicesForRequest(request_)) {
253 Deny(false, content::MEDIA_DEVICE_NO_HARDWARE);
254 return true;
257 // Check if any allow exception has been made for this request.
258 if (IsRequestAllowedByDefault()) {
259 Accept(false);
260 return true;
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);
267 return true;
270 // Check if the media default setting is set to block.
271 if (IsDefaultMediaAccessBlocked()) {
272 Deny(false, content::MEDIA_DEVICE_PERMISSION_DENIED);
273 return true;
276 // Show the infobar.
277 return false;
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,
306 // return no device.
307 if (audio_allowed &&
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);
312 } else {
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);
322 } else {
323 device = MediaCaptureDevicesDispatcher::GetInstance()->
324 GetFirstAvailableVideoDevice();
327 if (device)
328 devices.push_back(*device);
329 break;
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);
340 if (audio_device) {
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);
349 if (video_device) {
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,
362 &devices);
364 break;
366 case content::MEDIA_DEVICE_ACCESS: {
367 // Get the default devices for the request.
368 MediaCaptureDevicesDispatcher::GetInstance()->
369 GetDefaultDevicesForProfile(profile_,
370 audio_allowed,
371 video_allowed,
372 &devices);
373 break;
375 case content::MEDIA_ENUMERATE_DEVICES: {
376 // Do nothing.
377 NOTREACHED();
378 break;
380 } // switch
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
384 // removed.
385 if (update_content_setting) {
386 if ((IsSchemeSecure() && !devices.empty()) ||
387 request_.request_type == content::MEDIA_OPEN_DEVICE) {
388 StorePermission(true);
392 if (audio_allowed) {
393 profile_->GetHostContentSettingsMap()->UpdateLastUsageByPattern(
394 ContentSettingsPattern::FromURLNoWildcard(request_.security_origin),
395 ContentSettingsPattern::Wildcard(),
396 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC);
398 if (video_allowed) {
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_;
413 callback_.Reset();
414 cb.Run(devices,
415 devices.empty() ?
416 content::MEDIA_DEVICE_NO_HARDWARE : content::MEDIA_DEVICE_OK,
417 ui.Pass());
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_;
433 callback_.Reset();
434 cb.Run(content::MediaStreamDevices(),
435 result,
436 scoped_ptr<content::MediaStreamUI>());
439 int MediaStreamDevicesController::GetIconID() const {
440 if (HasVideo())
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;
448 if (!HasAudio())
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;
458 if (!HasAudio())
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);
478 } else {
479 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions",
480 kAllowHttp, kPermissionActionsMax);
482 Accept(true);
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() {
498 delete this;
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)) {
505 return true;
508 struct {
509 bool has_capability;
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)
523 continue;
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)
532 return false;
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) {
539 return false;
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) {
545 return false;
548 // If we get here, then either policy is set to ALWAYS_ALLOW or the content
549 // settings allow the request by default.
552 return true;
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;
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 NO_RESOURCE_IDENTIFIER) == CONTENT_SETTING_BLOCK) {
577 request_permissions_[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission =
578 MEDIA_BLOCKED_BY_USER_SETTING;
579 } else {
580 ++requested_devices;
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())
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;