| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/media/webrtc/media_stream_devices_controller.h" | 5 #include "chrome/browser/media/webrtc/media_stream_devices_controller.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 // device id is non-empty, then the corresponding device list must not be | 199 // device id is non-empty, then the corresponding device list must not be |
| 200 // NULL. | 200 // NULL. |
| 201 if (!device_id.empty() && !devices->FindById(device_id)) | 201 if (!device_id.empty() && !devices->FindById(device_id)) |
| 202 return false; | 202 return false; |
| 203 | 203 |
| 204 return true; | 204 return true; |
| 205 } | 205 } |
| 206 | 206 |
| 207 } // namespace | 207 } // namespace |
| 208 | 208 |
| 209 // Stores whether a permission has been requested or blocked during the course | |
| 210 // of a permission request, as well as the denial reason | |
| 211 class MediaStreamDevicesController::MediaPermissionStatus { | |
| 212 public: | |
| 213 explicit MediaPermissionStatus(const content::MediaStreamRequest& request) | |
| 214 : audio_requested_( | |
| 215 ContentTypeIsRequested(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, | |
| 216 request)), | |
| 217 video_requested_( | |
| 218 ContentTypeIsRequested(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, | |
| 219 request)) {} | |
| 220 | |
| 221 ~MediaPermissionStatus() {} | |
| 222 | |
| 223 bool audio_requested() const { return audio_requested_; } | |
| 224 bool video_requested() const { return video_requested_; } | |
| 225 | |
| 226 bool audio_blocked() const { return audio_blocked_; } | |
| 227 bool video_blocked() const { return video_blocked_; } | |
| 228 | |
| 229 content::MediaStreamRequestResult denial_reason() const { | |
| 230 return denial_reason_; | |
| 231 } | |
| 232 | |
| 233 void SetAudioBlocked(content::MediaStreamRequestResult denial_reason) { | |
| 234 DCHECK(audio_requested_); | |
| 235 audio_blocked_ = true; | |
| 236 denial_reason_ = denial_reason; | |
| 237 } | |
| 238 | |
| 239 void SetVideoBlocked(content::MediaStreamRequestResult denial_reason) { | |
| 240 DCHECK(video_requested_); | |
| 241 video_blocked_ = true; | |
| 242 denial_reason_ = denial_reason; | |
| 243 } | |
| 244 | |
| 245 private: | |
| 246 bool audio_requested_ = false; | |
| 247 bool video_requested_ = false; | |
| 248 bool audio_blocked_ = false; | |
| 249 bool video_blocked_ = false; | |
| 250 | |
| 251 content::MediaStreamRequestResult denial_reason_ = content::MEDIA_DEVICE_OK; | |
| 252 }; | |
| 253 | |
| 254 // Implementation of PermissionPromptDelegate which actually shows a permission | 209 // Implementation of PermissionPromptDelegate which actually shows a permission |
| 255 // prompt. | 210 // prompt. |
| 256 class MediaStreamDevicesController::PermissionPromptDelegateImpl | 211 class MediaStreamDevicesController::PermissionPromptDelegateImpl |
| 257 : public internal::PermissionPromptDelegate { | 212 : public internal::PermissionPromptDelegate { |
| 258 public: | 213 public: |
| 259 void ShowPrompt( | 214 void ShowPrompt( |
| 260 bool user_gesture, | 215 bool user_gesture, |
| 261 content::WebContents* web_contents, | 216 content::WebContents* web_contents, |
| 262 std::unique_ptr<MediaStreamDevicesController> controller) override { | 217 std::unique_ptr<MediaStreamDevicesController> controller) override { |
| 263 #if defined(OS_ANDROID) | 218 #if defined(OS_ANDROID) |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 content::WebContents* web_contents = | 362 content::WebContents* web_contents = |
| 408 content::WebContents::FromRenderFrameHost( | 363 content::WebContents::FromRenderFrameHost( |
| 409 content::RenderFrameHost::FromID(request.render_process_id, | 364 content::RenderFrameHost::FromID(request.render_process_id, |
| 410 request.render_frame_id)); | 365 request.render_frame_id)); |
| 411 if (request.request_type == content::MEDIA_OPEN_DEVICE_PEPPER_ONLY) { | 366 if (request.request_type == content::MEDIA_OPEN_DEVICE_PEPPER_ONLY) { |
| 412 MediaPermissionRequestLogger::LogRequest( | 367 MediaPermissionRequestLogger::LogRequest( |
| 413 web_contents, request.render_process_id, request.render_frame_id, | 368 web_contents, request.render_process_id, request.render_frame_id, |
| 414 content::IsOriginSecure(request.security_origin)); | 369 content::IsOriginSecure(request.security_origin)); |
| 415 } | 370 } |
| 416 | 371 |
| 417 MediaPermissionStatus initial_permission(request); | |
| 418 if (initial_permission.audio_requested() && | |
| 419 !HasAvailableDevices(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, | |
| 420 request.requested_audio_device_id)) { | |
| 421 initial_permission.SetAudioBlocked(content::MEDIA_DEVICE_NO_HARDWARE); | |
| 422 } | |
| 423 | |
| 424 if (initial_permission.video_requested() && | |
| 425 !HasAvailableDevices(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, | |
| 426 request.requested_video_device_id)) { | |
| 427 initial_permission.SetVideoBlocked(content::MEDIA_DEVICE_NO_HARDWARE); | |
| 428 } | |
| 429 | |
| 430 std::unique_ptr<MediaStreamDevicesController> controller( | 372 std::unique_ptr<MediaStreamDevicesController> controller( |
| 431 new MediaStreamDevicesController(web_contents, request, callback, | 373 new MediaStreamDevicesController(web_contents, request, callback)); |
| 432 initial_permission)); | |
| 433 if (!controller->IsAskingForAudio() && !controller->IsAskingForVideo()) { | 374 if (!controller->IsAskingForAudio() && !controller->IsAskingForVideo()) { |
| 434 #if defined(OS_ANDROID) | 375 #if defined(OS_ANDROID) |
| 435 // If either audio or video was previously allowed and Chrome no longer has | 376 // If either audio or video was previously allowed and Chrome no longer has |
| 436 // the necessary permissions, show a infobar to attempt to address this | 377 // the necessary permissions, show a infobar to attempt to address this |
| 437 // mismatch. | 378 // mismatch. |
| 438 std::vector<ContentSettingsType> content_settings_types; | 379 std::vector<ContentSettingsType> content_settings_types; |
| 439 if (controller->IsAllowedForAudio()) | 380 if (controller->IsAllowedForAudio()) |
| 440 content_settings_types.push_back(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC); | 381 content_settings_types.push_back(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC); |
| 441 | 382 |
| 442 if (controller->IsAllowedForVideo()) { | 383 if (controller->IsAllowedForVideo()) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 454 return; | 395 return; |
| 455 } | 396 } |
| 456 | 397 |
| 457 delegate->ShowPrompt(request.user_gesture, web_contents, | 398 delegate->ShowPrompt(request.user_gesture, web_contents, |
| 458 std::move(controller)); | 399 std::move(controller)); |
| 459 } | 400 } |
| 460 | 401 |
| 461 MediaStreamDevicesController::MediaStreamDevicesController( | 402 MediaStreamDevicesController::MediaStreamDevicesController( |
| 462 content::WebContents* web_contents, | 403 content::WebContents* web_contents, |
| 463 const content::MediaStreamRequest& request, | 404 const content::MediaStreamRequest& request, |
| 464 const content::MediaResponseCallback& callback, | 405 const content::MediaResponseCallback& callback) |
| 465 const MediaPermissionStatus& initial_permission) | |
| 466 : web_contents_(web_contents), request_(request), callback_(callback) { | 406 : web_contents_(web_contents), request_(request), callback_(callback) { |
| 467 profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 407 profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
| 468 content_settings_ = TabSpecificContentSettings::FromWebContents(web_contents); | 408 content_settings_ = TabSpecificContentSettings::FromWebContents(web_contents); |
| 469 | 409 |
| 470 content::MediaStreamRequestResult denial_reason = | 410 content::MediaStreamRequestResult denial_reason = content::MEDIA_DEVICE_OK; |
| 471 initial_permission.denial_reason(); | 411 old_audio_setting_ = GetContentSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, |
| 472 old_audio_setting_ = | 412 request, &denial_reason); |
| 473 GetContentSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, request, | 413 old_video_setting_ = GetContentSetting( |
| 474 initial_permission.audio_requested(), | 414 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, request, &denial_reason); |
| 475 initial_permission.audio_blocked(), &denial_reason); | |
| 476 old_video_setting_ = | |
| 477 GetContentSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, request, | |
| 478 initial_permission.video_requested(), | |
| 479 initial_permission.video_blocked(), &denial_reason); | |
| 480 | 415 |
| 481 // If either setting is ask, we show the infobar. | 416 // If either setting is ask, we show the infobar. |
| 482 if (old_audio_setting_ == CONTENT_SETTING_ASK || | 417 if (old_audio_setting_ == CONTENT_SETTING_ASK || |
| 483 old_video_setting_ == CONTENT_SETTING_ASK) { | 418 old_video_setting_ == CONTENT_SETTING_ASK) { |
| 484 return; | 419 return; |
| 485 } | 420 } |
| 486 | 421 |
| 487 #if defined(OS_ANDROID) | 422 #if defined(OS_ANDROID) |
| 488 std::vector<ContentSettingsType> content_settings_types; | 423 std::vector<ContentSettingsType> content_settings_types; |
| 489 if (IsAllowedForAudio()) | 424 if (IsAllowedForAudio()) |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 707 } | 642 } |
| 708 | 643 |
| 709 content_settings_->OnMediaStreamPermissionSet( | 644 content_settings_->OnMediaStreamPermissionSet( |
| 710 request_.security_origin, microphone_camera_state, selected_audio_device, | 645 request_.security_origin, microphone_camera_state, selected_audio_device, |
| 711 selected_video_device, requested_audio_device, requested_video_device); | 646 selected_video_device, requested_audio_device, requested_video_device); |
| 712 } | 647 } |
| 713 | 648 |
| 714 ContentSetting MediaStreamDevicesController::GetContentSetting( | 649 ContentSetting MediaStreamDevicesController::GetContentSetting( |
| 715 ContentSettingsType content_type, | 650 ContentSettingsType content_type, |
| 716 const content::MediaStreamRequest& request, | 651 const content::MediaStreamRequest& request, |
| 717 bool was_requested, | |
| 718 bool was_initially_blocked, | |
| 719 content::MediaStreamRequestResult* denial_reason) const { | 652 content::MediaStreamRequestResult* denial_reason) const { |
| 720 DCHECK(content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC || | 653 DCHECK(content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC || |
| 721 content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA); | 654 content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA); |
| 722 DCHECK(!request_.security_origin.is_empty()); | 655 DCHECK(!request_.security_origin.is_empty()); |
| 723 DCHECK(content::IsOriginSecure(request_.security_origin) || | 656 DCHECK(content::IsOriginSecure(request_.security_origin) || |
| 724 request_.request_type == content::MEDIA_OPEN_DEVICE_PEPPER_ONLY); | 657 request_.request_type == content::MEDIA_OPEN_DEVICE_PEPPER_ONLY); |
| 725 if (!was_requested) { | 658 if (!ContentTypeIsRequested(content_type, request)) { |
| 726 // No denial reason set as it will have been previously set. | 659 // No denial reason set as it will have been previously set. |
| 727 return CONTENT_SETTING_DEFAULT; | 660 return CONTENT_SETTING_DEFAULT; |
| 728 } | 661 } |
| 729 | 662 |
| 730 if (was_initially_blocked) { | 663 std::string device_id; |
| 731 // No denial reason set as it will have been previously set. | 664 if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC) |
| 665 device_id = request.requested_audio_device_id; |
| 666 else |
| 667 device_id = request.requested_video_device_id; |
| 668 if (!HasAvailableDevices(content_type, device_id)) { |
| 669 *denial_reason = content::MEDIA_DEVICE_NO_HARDWARE; |
| 732 return CONTENT_SETTING_BLOCK; | 670 return CONTENT_SETTING_BLOCK; |
| 733 } | 671 } |
| 734 | 672 |
| 735 if (!IsUserAcceptAllowed(content_type)) { | 673 if (!IsUserAcceptAllowed(content_type)) { |
| 736 *denial_reason = content::MEDIA_DEVICE_PERMISSION_DENIED; | 674 *denial_reason = content::MEDIA_DEVICE_PERMISSION_DENIED; |
| 737 return CONTENT_SETTING_BLOCK; | 675 return CONTENT_SETTING_BLOCK; |
| 738 } | 676 } |
| 739 | 677 |
| 740 PermissionResult result = | 678 PermissionResult result = |
| 741 PermissionManager::Get(profile_)->GetPermissionStatus( | 679 PermissionManager::Get(profile_)->GetPermissionStatus( |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 784 } | 722 } |
| 785 } | 723 } |
| 786 | 724 |
| 787 // Don't approve device requests if the tab was hidden. | 725 // Don't approve device requests if the tab was hidden. |
| 788 // TODO(qinmin): Add a test for this. http://crbug.com/396869. | 726 // TODO(qinmin): Add a test for this. http://crbug.com/396869. |
| 789 // TODO(raymes): Shouldn't this apply to all permissions not just audio/video? | 727 // TODO(raymes): Shouldn't this apply to all permissions not just audio/video? |
| 790 return web_contents_->GetRenderWidgetHostView()->IsShowing(); | 728 return web_contents_->GetRenderWidgetHostView()->IsShowing(); |
| 791 #endif | 729 #endif |
| 792 return true; | 730 return true; |
| 793 } | 731 } |
| OLD | NEW |