| 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/media_capture_devices_dispatcher.h" | 5 #include "chrome/browser/media/media_capture_devices_dispatcher.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/prefs/pref_service.h" | 9 #include "base/prefs/pref_service.h" |
| 10 #include "base/prefs/scoped_user_pref_update.h" | 10 #include "base/prefs/scoped_user_pref_update.h" |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 bool IsOriginWhitelistedForScreenCapture(const GURL& origin) { | 82 bool IsOriginWhitelistedForScreenCapture(const GURL& origin) { |
| 83 #if defined(OFFICIAL_BUILD) | 83 #if defined(OFFICIAL_BUILD) |
| 84 if (// Google Hangouts. | 84 if (// Google Hangouts. |
| 85 (origin.SchemeIs("https") && | 85 (origin.SchemeIs("https") && |
| 86 EndsWith(origin.spec(), ".talkgadget.google.com/", true)) || | 86 EndsWith(origin.spec(), ".talkgadget.google.com/", true)) || |
| 87 origin.spec() == "https://talkgadget.google.com/" || | 87 origin.spec() == "https://talkgadget.google.com/" || |
| 88 origin.spec() == "https://plus.google.com/" || | 88 origin.spec() == "https://plus.google.com/" || |
| 89 origin.spec() == "chrome-extension://pkedcjkdefgpdelpbcmbmeomcjbeemfm/" || | 89 origin.spec() == "chrome-extension://pkedcjkdefgpdelpbcmbmeomcjbeemfm/" || |
| 90 origin.spec() == "chrome-extension://fmfcbgogabcbclcofgocippekhfcmgfj/" || | 90 origin.spec() == "chrome-extension://fmfcbgogabcbclcofgocippekhfcmgfj/" || |
| 91 origin.spec() == "chrome-extension://hfaagokkkhdbgiakmmlclaapfelnkoah/" || | 91 origin.spec() == "chrome-extension://hfaagokkkhdbgiakmmlclaapfelnkoah/" || |
| 92 origin.spec() == "chrome-extension://boadgeojelhgndaghljhdicfkmllpafd/" || |
| 92 origin.spec() == "chrome-extension://gfdkimpbcpahaombhbimeihdjnejgicl/") { | 93 origin.spec() == "chrome-extension://gfdkimpbcpahaombhbimeihdjnejgicl/") { |
| 93 return true; | 94 return true; |
| 94 } | 95 } |
| 95 // Check against hashed origins. | 96 // Check against hashed origins. |
| 97 // TODO(hshi): remove this when trusted tester becomes public. |
| 96 const std::string origin_hash = base::SHA1HashString(origin.spec()); | 98 const std::string origin_hash = base::SHA1HashString(origin.spec()); |
| 97 DCHECK_EQ(origin_hash.length(), base::kSHA1Length); | 99 DCHECK_EQ(origin_hash.length(), base::kSHA1Length); |
| 98 const std::string hexencoded_origin_hash = | 100 const std::string hexencoded_origin_hash = |
| 99 base::HexEncode(origin_hash.data(), origin_hash.length()); | 101 base::HexEncode(origin_hash.data(), origin_hash.length()); |
| 100 return | 102 return |
| 101 hexencoded_origin_hash == "3C2705BC432E7C51CA8553FDC5BEE873FF2468EE" || | 103 hexencoded_origin_hash == "3C2705BC432E7C51CA8553FDC5BEE873FF2468EE"; |
| 102 hexencoded_origin_hash == "50F02B8A668CAB274527D58356F07C2143080FCC"; | |
| 103 #else | 104 #else |
| 104 return false; | 105 return false; |
| 105 #endif | 106 #endif |
| 106 } | 107 } |
| 107 | 108 |
| 109 #if defined(OS_CHROMEOS) |
| 110 // Returns true of the security origin is associated with casting. |
| 111 bool IsOriginForCasting(const GURL& origin) { |
| 112 #if defined(OFFICIAL_BUILD) |
| 113 // Whitelisted tab casting extensions. |
| 114 if (origin.spec() == "chrome-extension://pkedcjkdefgpdelpbcmbmeomcjbeemfm/" || |
| 115 origin.spec() == "chrome-extension://fmfcbgogabcbclcofgocippekhfcmgfj/" || |
| 116 origin.spec() == "chrome-extension://hfaagokkkhdbgiakmmlclaapfelnkoah/" || |
| 117 origin.spec() == "chrome-extension://boadgeojelhgndaghljhdicfkmllpafd/") { |
| 118 return true; |
| 119 } |
| 120 // Check against hashed origins. |
| 121 // TODO(hshi): remove this when trusted tester becomes public. |
| 122 const std::string origin_hash = base::SHA1HashString(origin.spec()); |
| 123 DCHECK_EQ(origin_hash.length(), base::kSHA1Length); |
| 124 const std::string hexencoded_origin_hash = |
| 125 base::HexEncode(origin_hash.data(), origin_hash.length()); |
| 126 return |
| 127 hexencoded_origin_hash == "3C2705BC432E7C51CA8553FDC5BEE873FF2468EE"; |
| 128 #else |
| 129 return false; |
| 130 #endif |
| 131 } |
| 132 #endif |
| 133 |
| 108 // Helper to get title of the calling application shown in the screen capture | 134 // Helper to get title of the calling application shown in the screen capture |
| 109 // notification. | 135 // notification. |
| 110 base::string16 GetApplicationTitle(content::WebContents* web_contents, | 136 base::string16 GetApplicationTitle(content::WebContents* web_contents, |
| 111 const extensions::Extension* extension) { | 137 const extensions::Extension* extension) { |
| 112 // Use extension name as title for extensions and origin for drive-by web. | 138 // Use extension name as title for extensions and origin for drive-by web. |
| 113 std::string title; | 139 std::string title; |
| 114 if (extension) { | 140 if (extension) { |
| 115 title = extension->name(); | 141 title = extension->name(); |
| 116 } else { | 142 } else { |
| 117 title = web_contents->GetURL().GetOrigin().spec(); | 143 title = web_contents->GetURL().GetOrigin().spec(); |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 #endif // !defined(OS_CHROMEOS) | 414 #endif // !defined(OS_CHROMEOS) |
| 389 | 415 |
| 390 bool capture_audio = | 416 bool capture_audio = |
| 391 (request.audio_type == content::MEDIA_LOOPBACK_AUDIO_CAPTURE && | 417 (request.audio_type == content::MEDIA_LOOPBACK_AUDIO_CAPTURE && |
| 392 loopback_audio_supported); | 418 loopback_audio_supported); |
| 393 | 419 |
| 394 // Unless we're being invoked from a component extension, register to | 420 // Unless we're being invoked from a component extension, register to |
| 395 // display the notification for stream capture. | 421 // display the notification for stream capture. |
| 396 bool display_notification = !component_extension; | 422 bool display_notification = !component_extension; |
| 397 | 423 |
| 398 ui = GetDevicesForDesktopCapture(devices, screen_id, capture_audio, | 424 ui = GetDevicesForDesktopCapture(devices, screen_id, capture_audio, |
| 399 display_notification, application_title); | 425 display_notification, application_title); |
| 400 } | 426 } |
| 401 } | 427 } |
| 402 | 428 |
| 403 callback.Run(devices, ui.Pass()); | 429 callback.Run(devices, ui.Pass()); |
| 404 } | 430 } |
| 405 | 431 |
| 406 void MediaCaptureDevicesDispatcher::ProcessTabCaptureAccessRequest( | 432 void MediaCaptureDevicesDispatcher::ProcessTabCaptureAccessRequest( |
| 407 content::WebContents* web_contents, | 433 content::WebContents* web_contents, |
| 408 const content::MediaStreamRequest& request, | 434 const content::MediaStreamRequest& request, |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 BrowserThread::PostTask( | 676 BrowserThread::PostTask( |
| 651 BrowserThread::UI, FROM_HERE, | 677 BrowserThread::UI, FROM_HERE, |
| 652 base::Bind(&MediaCaptureDevicesDispatcher::UpdateVideoDevicesOnUIThread, | 678 base::Bind(&MediaCaptureDevicesDispatcher::UpdateVideoDevicesOnUIThread, |
| 653 base::Unretained(this), devices)); | 679 base::Unretained(this), devices)); |
| 654 } | 680 } |
| 655 | 681 |
| 656 void MediaCaptureDevicesDispatcher::OnMediaRequestStateChanged( | 682 void MediaCaptureDevicesDispatcher::OnMediaRequestStateChanged( |
| 657 int render_process_id, | 683 int render_process_id, |
| 658 int render_view_id, | 684 int render_view_id, |
| 659 int page_request_id, | 685 int page_request_id, |
| 686 const GURL& security_origin, |
| 660 const content::MediaStreamDevice& device, | 687 const content::MediaStreamDevice& device, |
| 661 content::MediaRequestState state) { | 688 content::MediaRequestState state) { |
| 662 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 689 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 663 BrowserThread::PostTask( | 690 BrowserThread::PostTask( |
| 664 BrowserThread::UI, FROM_HERE, | 691 BrowserThread::UI, FROM_HERE, |
| 665 base::Bind( | 692 base::Bind( |
| 666 &MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread, | 693 &MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread, |
| 667 base::Unretained(this), render_process_id, render_view_id, | 694 base::Unretained(this), render_process_id, render_view_id, |
| 668 page_request_id, device, state)); | 695 page_request_id, security_origin, device, state)); |
| 669 } | 696 } |
| 670 | 697 |
| 671 void MediaCaptureDevicesDispatcher::OnAudioStreamPlayingChanged( | 698 void MediaCaptureDevicesDispatcher::OnAudioStreamPlayingChanged( |
| 672 int render_process_id, int render_view_id, int stream_id, | 699 int render_process_id, int render_view_id, int stream_id, |
| 673 bool is_playing, float power_dbfs, bool clipped) { | 700 bool is_playing, float power_dbfs, bool clipped) { |
| 674 audio_stream_indicator_->UpdateWebContentsStatus( | 701 audio_stream_indicator_->UpdateWebContentsStatus( |
| 675 render_process_id, render_view_id, stream_id, | 702 render_process_id, render_view_id, stream_id, |
| 676 is_playing, power_dbfs, clipped); | 703 is_playing, power_dbfs, clipped); |
| 677 } | 704 } |
| 678 | 705 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 702 devices_enumerated_ = true; | 729 devices_enumerated_ = true; |
| 703 video_devices_ = devices; | 730 video_devices_ = devices; |
| 704 FOR_EACH_OBSERVER(Observer, observers_, | 731 FOR_EACH_OBSERVER(Observer, observers_, |
| 705 OnUpdateVideoDevices(video_devices_)); | 732 OnUpdateVideoDevices(video_devices_)); |
| 706 } | 733 } |
| 707 | 734 |
| 708 void MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread( | 735 void MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread( |
| 709 int render_process_id, | 736 int render_process_id, |
| 710 int render_view_id, | 737 int render_view_id, |
| 711 int page_request_id, | 738 int page_request_id, |
| 739 const GURL& security_origin, |
| 712 const content::MediaStreamDevice& device, | 740 const content::MediaStreamDevice& device, |
| 713 content::MediaRequestState state) { | 741 content::MediaRequestState state) { |
| 714 // Track desktop capture sessions. Tracking is necessary to avoid unbalanced | 742 // Track desktop capture sessions. Tracking is necessary to avoid unbalanced |
| 715 // session counts since not all requests will reach MEDIA_REQUEST_STATE_DONE, | 743 // session counts since not all requests will reach MEDIA_REQUEST_STATE_DONE, |
| 716 // but they will all reach MEDIA_REQUEST_STATE_CLOSING. | 744 // but they will all reach MEDIA_REQUEST_STATE_CLOSING. |
| 717 if (device.type == content::MEDIA_DESKTOP_VIDEO_CAPTURE) { | 745 if (device.type == content::MEDIA_DESKTOP_VIDEO_CAPTURE) { |
| 718 if (state == content::MEDIA_REQUEST_STATE_DONE) { | 746 if (state == content::MEDIA_REQUEST_STATE_DONE) { |
| 719 DesktopCaptureSession session = { render_process_id, render_view_id, | 747 DesktopCaptureSession session = { render_process_id, render_view_id, |
| 720 page_request_id }; | 748 page_request_id }; |
| 721 desktop_capture_sessions_.push_back(session); | 749 desktop_capture_sessions_.push_back(session); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 748 queue.erase(it); | 776 queue.erase(it); |
| 749 found = true; | 777 found = true; |
| 750 break; | 778 break; |
| 751 } | 779 } |
| 752 } | 780 } |
| 753 if (found) | 781 if (found) |
| 754 break; | 782 break; |
| 755 } | 783 } |
| 756 } | 784 } |
| 757 | 785 |
| 786 #if defined(OS_CHROMEOS) |
| 787 if (IsOriginForCasting(security_origin) && IsVideoMediaType(device.type)) { |
| 788 // Notify ash that casting state has changed. |
| 789 if (state == content::MEDIA_REQUEST_STATE_DONE) { |
| 790 ash::Shell::GetInstance()->OnCastingSessionStartedOrStopped(true); |
| 791 } else if (state == content::MEDIA_REQUEST_STATE_CLOSING) { |
| 792 ash::Shell::GetInstance()->OnCastingSessionStartedOrStopped(false); |
| 793 } |
| 794 } |
| 795 #endif |
| 796 |
| 758 FOR_EACH_OBSERVER(Observer, observers_, | 797 FOR_EACH_OBSERVER(Observer, observers_, |
| 759 OnRequestUpdate(render_process_id, | 798 OnRequestUpdate(render_process_id, |
| 760 render_view_id, | 799 render_view_id, |
| 761 device, | 800 device, |
| 762 state)); | 801 state)); |
| 763 } | 802 } |
| 764 | 803 |
| 765 void MediaCaptureDevicesDispatcher::OnCreatingAudioStreamOnUIThread( | 804 void MediaCaptureDevicesDispatcher::OnCreatingAudioStreamOnUIThread( |
| 766 int render_process_id, | 805 int render_process_id, |
| 767 int render_view_id) { | 806 int render_view_id) { |
| 768 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 807 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 769 FOR_EACH_OBSERVER(Observer, observers_, | 808 FOR_EACH_OBSERVER(Observer, observers_, |
| 770 OnCreatingAudioStream(render_process_id, render_view_id)); | 809 OnCreatingAudioStream(render_process_id, render_view_id)); |
| 771 } | 810 } |
| 772 | 811 |
| 773 bool MediaCaptureDevicesDispatcher::IsDesktopCaptureInProgress() { | 812 bool MediaCaptureDevicesDispatcher::IsDesktopCaptureInProgress() { |
| 774 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 813 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 775 return desktop_capture_sessions_.size() > 0; | 814 return desktop_capture_sessions_.size() > 0; |
| 776 } | 815 } |
| OLD | NEW |