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 |