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. 4 5 #include "chrome/browser/media/media_stream_devices_controller.h" 6 7 #include "base/command_line.h" 8 #include "base/metrics/histogram.h" 9 #include "base/prefs/pref_service.h" 10 #include "base/prefs/scoped_user_pref_update.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "base/values.h" 13 #include "chrome/browser/content_settings/content_settings_provider.h" 14 #include "chrome/browser/content_settings/host_content_settings_map.h" 15 #include "chrome/browser/content_settings/tab_specific_content_settings.h" 16 #include "chrome/browser/media/media_capture_devices_dispatcher.h" 17 #include "chrome/browser/media/media_stream_capture_indicator.h" 18 #include "chrome/browser/profiles/profile.h" 19 #include "chrome/browser/ui/browser.h" 20 #include "chrome/common/chrome_switches.h" 21 #include "chrome/common/content_settings.h" 22 #include "chrome/common/content_settings_pattern.h" 23 #include "chrome/common/pref_names.h" 24 #include "components/pref_registry/pref_registry_syncable.h" 25 #include "content/public/browser/browser_thread.h" 26 #include "content/public/browser/render_widget_host_view.h" 27 #include "content/public/common/media_stream_request.h" 28 #include "extensions/common/constants.h" 29 #include "grit/generated_resources.h" 30 #include "grit/theme_resources.h" 31 #include "ui/base/l10n/l10n_util.h" 32 33 #if defined(OS_CHROMEOS) 34 #include "chrome/browser/chromeos/login/users/user_manager.h" 35 #endif 36 37 using content::BrowserThread; 38 39 namespace { 40 41 bool HasAvailableDevicesForRequest(const content::MediaStreamRequest& request) { 42 const content::MediaStreamDevices* audio_devices = 43 request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE ? 44 &MediaCaptureDevicesDispatcher::GetInstance() 45 ->GetAudioCaptureDevices() : 46 NULL; 47 48 const content::MediaStreamDevices* video_devices = 49 request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE ? 50 &MediaCaptureDevicesDispatcher::GetInstance() 51 ->GetVideoCaptureDevices() : 52 NULL; 53 54 // Check if we're being asked for audio and/or video and that either of those 55 // lists is empty. If they are, we do not have devices available for the 56 // request. 57 // TODO(tommi): It's kind of strange to have this here since if we fail this 58 // test, there'll be a UI shown that indicates to the user that access to 59 // non-existing audio/video devices has been denied. The user won't have 60 // any way to change that but there will be a UI shown which indicates that 61 // access is blocked. 62 if ((audio_devices != NULL && audio_devices->empty()) || 63 (video_devices != NULL && video_devices->empty())) { 64 return false; 65 } 66 67 // Note: we check requested_[audio|video]_device_id before dereferencing 68 // [audio|video]_devices. If the requested device id is non-empty, then 69 // the corresponding device list must not be NULL. 70 71 if (!request.requested_audio_device_id.empty() && 72 !audio_devices->FindById(request.requested_audio_device_id)) { 73 return false; 74 } 75 76 if (!request.requested_video_device_id.empty() && 77 !video_devices->FindById(request.requested_video_device_id)) { 78 return false; 79 } 80 81 return true; 82 } 83 84 bool IsInKioskMode() { 85 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode)) 86 return true; 87 88 #if defined(OS_CHROMEOS) 89 const chromeos::UserManager* user_manager = chromeos::UserManager::Get(); 90 return user_manager && user_manager->IsLoggedInAsKioskApp(); 91 #else 92 return false; 93 #endif 94 } 95 96 enum DevicePermissionActions { 97 kAllowHttps = 0, 98 kAllowHttp, 99 kDeny, 100 kCancel, 101 kPermissionActionsMax // Must always be last! 102 }; 103 104 } // namespace 105 106 MediaStreamDevicesController::MediaStreamTypeSettings::MediaStreamTypeSettings( 107 Permission permission, const std::string& requested_device_id): 108 permission(permission), requested_device_id(requested_device_id) {} 109 110 MediaStreamDevicesController::MediaStreamTypeSettings:: 111 MediaStreamTypeSettings(): permission(MEDIA_NONE) {} 112 113 MediaStreamDevicesController::MediaStreamTypeSettings:: 114 ~MediaStreamTypeSettings() {} 115 116 MediaStreamDevicesController::MediaStreamDevicesController( 117 content::WebContents* web_contents, 118 const content::MediaStreamRequest& request, 119 const content::MediaResponseCallback& callback) 120 : web_contents_(web_contents), 121 request_(request), 122 callback_(callback) { 123 profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext()); 124 content_settings_ = TabSpecificContentSettings::FromWebContents(web_contents); 125 126 // For MEDIA_OPEN_DEVICE requests (Pepper) we always request both webcam 127 // and microphone to avoid popping two infobars. 128 // We start with setting the requested media type to allowed or blocked 129 // depending on the policy. If not blocked by policy it may be blocked later 130 // in the two remaining filtering steps (by user setting or by user when 131 // clicking the infobar). 132 // TODO(grunell): It's not the nicest solution to let the MEDIA_OPEN_DEVICE 133 // case take a ride on the MEDIA_DEVICE_*_CAPTURE permission. Should be fixed. 134 if (request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE || 135 request.request_type == content::MEDIA_OPEN_DEVICE) { 136 if (GetDevicePolicy(prefs::kAudioCaptureAllowed, 137 prefs::kAudioCaptureAllowedUrls) == ALWAYS_DENY) { 138 request_permissions_.insert(std::make_pair( 139 content::MEDIA_DEVICE_AUDIO_CAPTURE, 140 MediaStreamTypeSettings(MEDIA_BLOCKED_BY_POLICY, 141 request.requested_audio_device_id))); 142 } else { 143 request_permissions_.insert(std::make_pair( 144 content::MEDIA_DEVICE_AUDIO_CAPTURE, 145 MediaStreamTypeSettings(MEDIA_ALLOWED, 146 request.requested_audio_device_id))); 147 } 148 } 149 if (request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE || 150 request.request_type == content::MEDIA_OPEN_DEVICE) { 151 if (GetDevicePolicy(prefs::kVideoCaptureAllowed, 152 prefs::kVideoCaptureAllowedUrls) == ALWAYS_DENY) { 153 request_permissions_.insert(std::make_pair( 154 content::MEDIA_DEVICE_VIDEO_CAPTURE, 155 MediaStreamTypeSettings(MEDIA_BLOCKED_BY_POLICY, 156 request.requested_video_device_id))); 157 } else { 158 request_permissions_.insert(std::make_pair( 159 content::MEDIA_DEVICE_VIDEO_CAPTURE, 160 MediaStreamTypeSettings(MEDIA_ALLOWED, 161 request.requested_video_device_id))); 162 } 163 } 164 } 165 166 MediaStreamDevicesController::~MediaStreamDevicesController() { 167 if (!callback_.is_null()) { 168 callback_.Run(content::MediaStreamDevices(), 169 content::MEDIA_DEVICE_INVALID_STATE, 170 scoped_ptr<content::MediaStreamUI>()); 171 } 172 } 173 174 // static 175 void MediaStreamDevicesController::RegisterProfilePrefs( 176 user_prefs::PrefRegistrySyncable* prefs) { 177 prefs->RegisterBooleanPref(prefs::kVideoCaptureAllowed, 178 true, 179 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 180 prefs->RegisterBooleanPref(prefs::kAudioCaptureAllowed, 181 true, 182 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 183 prefs->RegisterListPref(prefs::kVideoCaptureAllowedUrls, 184 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 185 prefs->RegisterListPref(prefs::kAudioCaptureAllowedUrls, 186 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 187 } 188 189 // TODO(gbillock): rename? doesn't actually dismiss. More of a 'check profile 190 // and system for compatibility' thing. 191 bool MediaStreamDevicesController::DismissInfoBarAndTakeActionOnSettings() { 192 // Tab capture is allowed for extensions only and infobar is not shown for 193 // extensions. 194 if (request_.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE || 195 request_.video_type == content::MEDIA_TAB_VIDEO_CAPTURE) { 196 Deny(false, content::MEDIA_DEVICE_INVALID_STATE); 197 return true; 198 } 199 200 // Deny the request if the security origin is empty, this happens with 201 // file access without |--allow-file-access-from-files| flag. 202 if (request_.security_origin.is_empty()) { 203 Deny(false, content::MEDIA_DEVICE_INVALID_SECURITY_ORIGIN); 204 return true; 205 } 206 207 // Deny the request if there is no device attached to the OS of the 208 // requested type. If both audio and video is requested, both types must be 209 // available. 210 if (!HasAvailableDevicesForRequest(request_)) { 211 Deny(false, content::MEDIA_DEVICE_NO_HARDWARE); 212 return true; 213 } 214 215 // Check if any allow exception has been made for this request. 216 if (IsRequestAllowedByDefault()) { 217 Accept(false); 218 return true; 219 } 220 221 // Filter any parts of the request that have been blocked by default and deny 222 // it if nothing is left to accept. 223 if (FilterBlockedByDefaultDevices() == 0) { 224 Deny(false, content::MEDIA_DEVICE_PERMISSION_DENIED); 225 return true; 226 } 227 228 // Check if the media default setting is set to block. 229 if (IsDefaultMediaAccessBlocked()) { 230 Deny(false, content::MEDIA_DEVICE_PERMISSION_DENIED); 231 return true; 232 } 233 234 // Show the infobar. 235 return false; 236 } 237 238 bool MediaStreamDevicesController::HasAudio() const { 239 return IsDeviceAudioCaptureRequestedAndAllowed(); 240 } 241 242 bool MediaStreamDevicesController::HasVideo() const { 243 return IsDeviceVideoCaptureRequestedAndAllowed(); 244 } 245 246 const std::string& MediaStreamDevicesController::GetSecurityOriginSpec() const { 247 return request_.security_origin.spec(); 248 } 249 250 void MediaStreamDevicesController::Accept(bool update_content_setting) { 251 NotifyUIRequestAccepted(); 252 253 // Get the default devices for the request. 254 content::MediaStreamDevices devices; 255 bool audio_allowed = IsDeviceAudioCaptureRequestedAndAllowed(); 256 bool video_allowed = IsDeviceVideoCaptureRequestedAndAllowed(); 257 if (audio_allowed || video_allowed) { 258 switch (request_.request_type) { 259 case content::MEDIA_OPEN_DEVICE: { 260 const content::MediaStreamDevice* device = NULL; 261 // For open device request, when requested device_id is empty, pick 262 // the first available of the given type. If requested device_id is 263 // not empty, return the desired device if it's available. Otherwise, 264 // return no device. 265 if (audio_allowed && 266 request_.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE) { 267 if (!request_.requested_audio_device_id.empty()) { 268 device = MediaCaptureDevicesDispatcher::GetInstance()-> 269 GetRequestedAudioDevice(request_.requested_audio_device_id); 270 } else { 271 device = MediaCaptureDevicesDispatcher::GetInstance()-> 272 GetFirstAvailableAudioDevice(); 273 } 274 } else if (video_allowed && 275 request_.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE) { 276 // Pepper API opens only one device at a time. 277 if (!request_.requested_video_device_id.empty()) { 278 device = MediaCaptureDevicesDispatcher::GetInstance()-> 279 GetRequestedVideoDevice(request_.requested_video_device_id); 280 } else { 281 device = MediaCaptureDevicesDispatcher::GetInstance()-> 282 GetFirstAvailableVideoDevice(); 283 } 284 } 285 if (device) 286 devices.push_back(*device); 287 break; 288 } 289 case content::MEDIA_GENERATE_STREAM: { 290 bool get_default_audio_device = audio_allowed; 291 bool get_default_video_device = video_allowed; 292 293 // Get the exact audio or video device if an id is specified. 294 if (audio_allowed && !request_.requested_audio_device_id.empty()) { 295 const content::MediaStreamDevice* audio_device = 296 MediaCaptureDevicesDispatcher::GetInstance()-> 297 GetRequestedAudioDevice(request_.requested_audio_device_id); 298 if (audio_device) { 299 devices.push_back(*audio_device); 300 get_default_audio_device = false; 301 } 302 } 303 if (video_allowed && !request_.requested_video_device_id.empty()) { 304 const content::MediaStreamDevice* video_device = 305 MediaCaptureDevicesDispatcher::GetInstance()-> 306 GetRequestedVideoDevice(request_.requested_video_device_id); 307 if (video_device) { 308 devices.push_back(*video_device); 309 get_default_video_device = false; 310 } 311 } 312 313 // If either or both audio and video devices were requested but not 314 // specified by id, get the default devices. 315 if (get_default_audio_device || get_default_video_device) { 316 MediaCaptureDevicesDispatcher::GetInstance()-> 317 GetDefaultDevicesForProfile(profile_, 318 get_default_audio_device, 319 get_default_video_device, 320 &devices); 321 } 322 break; 323 } 324 case content::MEDIA_DEVICE_ACCESS: { 325 // Get the default devices for the request. 326 MediaCaptureDevicesDispatcher::GetInstance()-> 327 GetDefaultDevicesForProfile(profile_, 328 audio_allowed, 329 video_allowed, 330 &devices); 331 break; 332 } 333 case content::MEDIA_ENUMERATE_DEVICES: { 334 // Do nothing. 335 NOTREACHED(); 336 break; 337 } 338 } // switch 339 340 // TODO(raymes): We currently set the content permission for non-https 341 // websites for Pepper requests as well. This is temporary and should be 342 // removed. 343 if (update_content_setting) { 344 if ((IsSchemeSecure() && !devices.empty()) || 345 request_.request_type == content::MEDIA_OPEN_DEVICE) { 346 SetPermission(true); 347 } 348 } 349 } 350 351 scoped_ptr<content::MediaStreamUI> ui; 352 if (!devices.empty()) { 353 ui = MediaCaptureDevicesDispatcher::GetInstance()-> 354 GetMediaStreamCaptureIndicator()->RegisterMediaStream( 355 web_contents_, devices); 356 } 357 content::MediaResponseCallback cb = callback_; 358 callback_.Reset(); 359 cb.Run(devices, 360 devices.empty() ? 361 content::MEDIA_DEVICE_NO_HARDWARE : content::MEDIA_DEVICE_OK, 362 ui.Pass()); 363 } 364 365 void MediaStreamDevicesController::Deny( 366 bool update_content_setting, 367 content::MediaStreamRequestResult result) { 368 DLOG(WARNING) << "MediaStreamDevicesController::Deny: " << result; 369 NotifyUIRequestDenied(); 370 371 if (update_content_setting) { 372 CHECK_EQ(content::MEDIA_DEVICE_PERMISSION_DENIED, result); 373 SetPermission(false); 374 } 375 376 content::MediaResponseCallback cb = callback_; 377 callback_.Reset(); 378 cb.Run(content::MediaStreamDevices(), 379 result, 380 scoped_ptr<content::MediaStreamUI>()); 381 } 382 383 int MediaStreamDevicesController::GetIconID() const { 384 if (HasVideo()) 385 return IDR_INFOBAR_MEDIA_STREAM_CAMERA; 386 387 return IDR_INFOBAR_MEDIA_STREAM_MIC; 388 } 389 390 base::string16 MediaStreamDevicesController::GetMessageText() const { 391 int message_id = IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO; 392 if (!HasAudio()) 393 message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY; 394 else if (!HasVideo()) 395 message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY; 396 return l10n_util::GetStringFUTF16( 397 message_id, base::UTF8ToUTF16(GetSecurityOriginSpec())); 398 } 399 400 base::string16 MediaStreamDevicesController::GetMessageTextFragment() const { 401 int message_id = IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO_PERMISSION_FRAGMENT; 402 if (!HasAudio()) 403 message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY_PERMISSION_FRAGMENT; 404 else if (!HasVideo()) 405 message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY_PERMISSION_FRAGMENT; 406 return l10n_util::GetStringUTF16(message_id); 407 } 408 409 bool MediaStreamDevicesController::HasUserGesture() const { 410 return request_.user_gesture; 411 } 412 413 GURL MediaStreamDevicesController::GetRequestingHostname() const { 414 return request_.security_origin; 415 } 416 417 void MediaStreamDevicesController::PermissionGranted() { 418 GURL origin(GetSecurityOriginSpec()); 419 if (origin.SchemeIsSecure()) { 420 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions", 421 kAllowHttps, kPermissionActionsMax); 422 } else { 423 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions", 424 kAllowHttp, kPermissionActionsMax); 425 } 426 Accept(true); 427 } 428 429 void MediaStreamDevicesController::PermissionDenied() { 430 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions", 431 kDeny, kPermissionActionsMax); 432 Deny(true, content::MEDIA_DEVICE_PERMISSION_DENIED); 433 } 434 435 void MediaStreamDevicesController::Cancelled() { 436 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions", 437 kCancel, kPermissionActionsMax); 438 Deny(false, content::MEDIA_DEVICE_PERMISSION_DISMISSED); 439 } 440 441 void MediaStreamDevicesController::RequestFinished() { 442 delete this; 443 } 444 445 MediaStreamDevicesController::DevicePolicy 446 MediaStreamDevicesController::GetDevicePolicy( 447 const char* policy_name, 448 const char* whitelist_policy_name) const { 449 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 450 451 // If the security origin policy matches a value in the whitelist, allow it. 452 // Otherwise, check the |policy_name| master switch for the default behavior. 453 454 PrefService* prefs = profile_->GetPrefs(); 455 456 // TODO(tommi): Remove the kiosk mode check when the whitelist below 457 // is visible in the media exceptions UI. 458 // See discussion here: https://codereview.chromium.org/15738004/ 459 if (IsInKioskMode()) { 460 const base::ListValue* list = prefs->GetList(whitelist_policy_name); 461 std::string value; 462 for (size_t i = 0; i < list->GetSize(); ++i) { 463 if (list->GetString(i, &value)) { 464 ContentSettingsPattern pattern = 465 ContentSettingsPattern::FromString(value); 466 if (pattern == ContentSettingsPattern::Wildcard()) { 467 DLOG(WARNING) << "Ignoring wildcard URL pattern: " << value; 468 continue; 469 } 470 DLOG_IF(ERROR, !pattern.IsValid()) << "Invalid URL pattern: " << value; 471 if (pattern.IsValid() && pattern.Matches(request_.security_origin)) 472 return ALWAYS_ALLOW; 473 } 474 } 475 } 476 477 // If a match was not found, check if audio capture is otherwise disallowed 478 // or if the user should be prompted. Setting the policy value to "true" 479 // is equal to not setting it at all, so from hereon out, we will return 480 // either POLICY_NOT_SET (prompt) or ALWAYS_DENY (no prompt, no access). 481 if (!prefs->GetBoolean(policy_name)) 482 return ALWAYS_DENY; 483 484 return POLICY_NOT_SET; 485 } 486 487 bool MediaStreamDevicesController::IsRequestAllowedByDefault() const { 488 // The request from internal objects like chrome://URLs is always allowed. 489 if (ShouldAlwaysAllowOrigin()) 490 return true; 491 492 struct { 493 bool has_capability; 494 const char* policy_name; 495 const char* list_policy_name; 496 ContentSettingsType settings_type; 497 } device_checks[] = { 498 { IsDeviceAudioCaptureRequestedAndAllowed(), prefs::kAudioCaptureAllowed, 499 prefs::kAudioCaptureAllowedUrls, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC }, 500 { IsDeviceVideoCaptureRequestedAndAllowed(), prefs::kVideoCaptureAllowed, 501 prefs::kVideoCaptureAllowedUrls, 502 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA }, 503 }; 504 505 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(device_checks); ++i) { 506 if (!device_checks[i].has_capability) 507 continue; 508 509 DevicePolicy policy = GetDevicePolicy(device_checks[i].policy_name, 510 device_checks[i].list_policy_name); 511 512 if (policy == ALWAYS_DENY) 513 return false; 514 515 if (policy == POLICY_NOT_SET) { 516 // Only load content settings from secure origins unless it is a 517 // content::MEDIA_OPEN_DEVICE (Pepper) request. 518 if (!IsSchemeSecure() && 519 request_.request_type != content::MEDIA_OPEN_DEVICE) { 520 return false; 521 } 522 if (profile_->GetHostContentSettingsMap()->GetContentSetting( 523 request_.security_origin, request_.security_origin, 524 device_checks[i].settings_type, NO_RESOURCE_IDENTIFIER) != 525 CONTENT_SETTING_ALLOW) { 526 return false; 527 } 528 } 529 // If we get here, then either policy is set to ALWAYS_ALLOW or the content 530 // settings allow the request by default. 531 } 532 533 return true; 534 } 535 536 int MediaStreamDevicesController::FilterBlockedByDefaultDevices() { 537 int requested_devices = 0; 538 539 if (IsDeviceAudioCaptureRequestedAndAllowed()) { 540 if (profile_->GetHostContentSettingsMap()->GetContentSetting( 541 request_.security_origin, 542 request_.security_origin, 543 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, 544 NO_RESOURCE_IDENTIFIER) == CONTENT_SETTING_BLOCK) { 545 request_permissions_[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission = 546 MEDIA_BLOCKED_BY_USER_SETTING; 547 } else { 548 ++requested_devices; 549 } 550 } 551 552 if (IsDeviceVideoCaptureRequestedAndAllowed()) { 553 if (profile_->GetHostContentSettingsMap()->GetContentSetting( 554 request_.security_origin, 555 request_.security_origin, 556 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, 557 NO_RESOURCE_IDENTIFIER) == CONTENT_SETTING_BLOCK) { 558 request_permissions_[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission = 559 MEDIA_BLOCKED_BY_USER_SETTING; 560 } else { 561 ++requested_devices; 562 } 563 } 564 565 return requested_devices; 566 } 567 568 bool MediaStreamDevicesController::IsDefaultMediaAccessBlocked() const { 569 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 570 // TODO(markusheintz): Replace CONTENT_SETTINGS_TYPE_MEDIA_STREAM with the 571 // appropriate new CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC and 572 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA. 573 ContentSetting current_setting = 574 profile_->GetHostContentSettingsMap()->GetDefaultContentSetting( 575 CONTENT_SETTINGS_TYPE_MEDIASTREAM, NULL); 576 return (current_setting == CONTENT_SETTING_BLOCK); 577 } 578 579 bool MediaStreamDevicesController::IsSchemeSecure() const { 580 return request_.security_origin.SchemeIsSecure() || 581 request_.security_origin.SchemeIs(extensions::kExtensionScheme); 582 } 583 584 bool MediaStreamDevicesController::ShouldAlwaysAllowOrigin() const { 585 // TODO(markusheintz): Replace CONTENT_SETTINGS_TYPE_MEDIA_STREAM with the 586 // appropriate new CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC and 587 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA. 588 return profile_->GetHostContentSettingsMap()->ShouldAllowAllContent( 589 request_.security_origin, request_.security_origin, 590 CONTENT_SETTINGS_TYPE_MEDIASTREAM); 591 } 592 593 void MediaStreamDevicesController::SetPermission(bool allowed) const { 594 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 595 ContentSettingsPattern primary_pattern = 596 ContentSettingsPattern::FromURLNoWildcard(request_.security_origin); 597 // Check the pattern is valid or not. When the request is from a file access, 598 // no exception will be made. 599 if (!primary_pattern.IsValid()) 600 return; 601 602 ContentSetting content_setting = allowed ? 603 CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; 604 if (request_permissions_.find(content::MEDIA_DEVICE_AUDIO_CAPTURE) != 605 request_permissions_.end()) { 606 profile_->GetHostContentSettingsMap()->SetContentSetting( 607 primary_pattern, 608 ContentSettingsPattern::Wildcard(), 609 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, 610 std::string(), 611 content_setting); 612 } 613 if (request_permissions_.find(content::MEDIA_DEVICE_VIDEO_CAPTURE) != 614 request_permissions_.end()) { 615 profile_->GetHostContentSettingsMap()->SetContentSetting( 616 primary_pattern, 617 ContentSettingsPattern::Wildcard(), 618 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, 619 std::string(), 620 content_setting); 621 } 622 } 623 624 void MediaStreamDevicesController::NotifyUIRequestAccepted() const { 625 if (!content_settings_) 626 return; 627 628 content_settings_->OnMediaStreamPermissionSet(request_.security_origin, 629 request_permissions_); 630 } 631 632 void MediaStreamDevicesController::NotifyUIRequestDenied() { 633 if (!content_settings_) 634 return; 635 636 if (IsDeviceAudioCaptureRequestedAndAllowed()) { 637 request_permissions_[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission = 638 MEDIA_BLOCKED_BY_USER; 639 } 640 if (IsDeviceVideoCaptureRequestedAndAllowed()) { 641 request_permissions_[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission = 642 MEDIA_BLOCKED_BY_USER; 643 } 644 645 content_settings_->OnMediaStreamPermissionSet(request_.security_origin, 646 request_permissions_); 647 } 648 649 bool MediaStreamDevicesController::IsDeviceAudioCaptureRequestedAndAllowed() 650 const { 651 MediaStreamTypeSettingsMap::const_iterator it = 652 request_permissions_.find(content::MEDIA_DEVICE_AUDIO_CAPTURE); 653 return (it != request_permissions_.end() && IsCaptureDeviceRequestAllowed() && 654 it->second.permission == MEDIA_ALLOWED); 655 } 656 657 bool MediaStreamDevicesController::IsDeviceVideoCaptureRequestedAndAllowed() 658 const { 659 MediaStreamTypeSettingsMap::const_iterator it = 660 request_permissions_.find(content::MEDIA_DEVICE_VIDEO_CAPTURE); 661 return (it != request_permissions_.end() && IsCaptureDeviceRequestAllowed() && 662 it->second.permission == MEDIA_ALLOWED); 663 } 664 665 bool MediaStreamDevicesController::IsCaptureDeviceRequestAllowed() const { 666 #if defined(OS_ANDROID) 667 // Don't approve device requests if the tab was hidden. 668 // TODO(qinmin): Add a test for this. http://crbug.com/396869. 669 return web_contents_->GetRenderWidgetHostView()->IsShowing(); 670 #endif 671 return true; 672 } 673