diff options
19 files changed, 666 insertions, 414 deletions
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc index 0a6b9b9..5f25087 100644 --- a/chrome/browser/policy/policy_browsertest.cc +++ b/chrome/browser/policy/policy_browsertest.cc @@ -2634,7 +2634,7 @@ class MediaStreamDevicesControllerBrowserTest } void FinishAudioTest() { - content::MediaStreamRequest request(0, 0, 0, std::string(), + content::MediaStreamRequest request(0, 0, 0, request_url_.GetOrigin(), content::MEDIA_DEVICE_ACCESS, std::string(), std::string(), @@ -2653,7 +2653,7 @@ class MediaStreamDevicesControllerBrowserTest void FinishVideoTest() { // TODO(raymes): Test MEDIA_DEVICE_OPEN (Pepper) which grants both webcam // and microphone permissions at the same time. - content::MediaStreamRequest request(0, 0, 0, std::string(), + content::MediaStreamRequest request(0, 0, 0, request_url_.GetOrigin(), content::MEDIA_DEVICE_ACCESS, std::string(), diff --git a/content/browser/renderer_host/media/device_request_message_filter.cc b/content/browser/renderer_host/media/device_request_message_filter.cc index 7baa6f3..60729ca 100644 --- a/content/browser/renderer_host/media/device_request_message_filter.cc +++ b/content/browser/renderer_host/media/device_request_message_filter.cc @@ -7,7 +7,6 @@ #include "content/browser/browser_main_loop.h" #include "content/browser/renderer_host/media/media_stream_manager.h" #include "content/common/media/media_stream_messages.h" -#include "content/public/browser/media_device_id.h" #include "content/public/browser/resource_context.h" // Clears the MediaStreamDevice.name from all devices in |device_list|. @@ -96,12 +95,12 @@ void DeviceRequestMessageFilter::DevicesEnumerated( if (label == request_it->audio_devices_label) { request_it->has_audio_returned = true; DCHECK(audio_devices->empty()); - HmacDeviceIds(request_it->origin, new_devices, audio_devices); + *audio_devices = new_devices; } else { DCHECK(label == request_it->video_devices_label); request_it->has_video_returned = true; DCHECK(video_devices->empty()); - HmacDeviceIds(request_it->origin, new_devices, video_devices); + *video_devices = new_devices; } if (!request_it->has_audio_returned || !request_it->has_video_returned) { @@ -150,23 +149,6 @@ void DeviceRequestMessageFilter::OnChannelClosing() { requests_.clear(); } -void DeviceRequestMessageFilter::HmacDeviceIds( - const GURL& origin, - const StreamDeviceInfoArray& raw_devices, - StreamDeviceInfoArray* devices_with_guids) { - DCHECK(devices_with_guids); - - // Replace raw ids with hmac'd ids before returning to renderer process. - for (StreamDeviceInfoArray::const_iterator device_itr = raw_devices.begin(); - device_itr != raw_devices.end(); - ++device_itr) { - StreamDeviceInfo current_device_info = *device_itr; - current_device_info.device.id = - content::GetHMACForMediaDeviceID(origin, device_itr->device.id); - devices_with_guids->push_back(current_device_info); - } -} - void DeviceRequestMessageFilter::OnGetSources(int request_id, const GURL& security_origin) { // Make request to get audio devices. diff --git a/content/browser/renderer_host/media/device_request_message_filter.h b/content/browser/renderer_host/media/device_request_message_filter.h index 2f31f08..6c164ab 100644 --- a/content/browser/renderer_host/media/device_request_message_filter.h +++ b/content/browser/renderer_host/media/device_request_message_filter.h @@ -52,9 +52,6 @@ class CONTENT_EXPORT DeviceRequestMessageFilter : public BrowserMessageFilter, private: void OnGetSources(int request_id, const GURL& security_origin); - void HmacDeviceIds(const GURL& origin, - const StreamDeviceInfoArray& raw_devices, - StreamDeviceInfoArray* devices_with_guids); // Owned by ProfileIOData which is guaranteed to outlive DRMF. ResourceContext* resource_context_; diff --git a/content/browser/renderer_host/media/device_request_message_filter_unittest.cc b/content/browser/renderer_host/media/device_request_message_filter_unittest.cc index c3ffe95..13a1cdb 100644 --- a/content/browser/renderer_host/media/device_request_message_filter_unittest.cc +++ b/content/browser/renderer_host/media/device_request_message_filter_unittest.cc @@ -6,7 +6,6 @@ #include "content/browser/renderer_host/media/device_request_message_filter.h" #include "content/browser/renderer_host/media/media_stream_manager.h" #include "content/common/media/media_stream_messages.h" -#include "content/public/browser/media_device_id.h" #include "content/public/test/mock_resource_context.h" #include "content/public/test/test_browser_thread.h" #include "testing/gmock/include/gmock/gmock.h" @@ -118,11 +117,6 @@ class DeviceRequestMessageFilterTest : public testing::Test { host_->requested_devices().size()); EXPECT_EQ(kRequestId, host_->received_id()); - // Check to make sure no devices have raw ids. - EXPECT_FALSE(DoesContainRawIds(host_->requested_devices())); - - // Check to make sure every GUID produced matches a raw device id. - EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->requested_devices(), origin)); } bool AreLabelsPresent(MediaStreamType type) { @@ -199,48 +193,6 @@ class DeviceRequestMessageFilterTest : public testing::Test { host_->DevicesEnumerated(kVideoLabel, physical_video_devices_); } - bool DoesContainRawIds(const StreamDeviceInfoArray& devices) { - for (size_t i = 0; i < devices.size(); i++) { - for (size_t j = 0; j < physical_audio_devices_.size(); ++j) { - if (physical_audio_devices_[j].device.id == devices[i].device.id) - return true; - } - for (size_t j = 0; j < physical_video_devices_.size(); ++j) { - if (physical_video_devices_[j].device.id == devices[i].device.id) - return true; - } - } - return false; - } - - bool DoesEveryDeviceMapToRawId(const StreamDeviceInfoArray& devices, - const GURL& origin) { - for (size_t i = 0; i < devices.size(); i++) { - bool found_match = false; - for (size_t j = 0; j < physical_audio_devices_.size(); ++j) { - if (content::DoesMediaDeviceIDMatchHMAC( - origin, - devices[i].device.id, - physical_audio_devices_[j].device.id)) { - EXPECT_FALSE(found_match); - found_match = true; - } - } - for (size_t j = 0; j < physical_video_devices_.size(); ++j) { - if (content::DoesMediaDeviceIDMatchHMAC( - origin, - devices[i].device.id, - physical_video_devices_[j].device.id)) { - EXPECT_FALSE(found_match); - found_match = true; - } - } - if (!found_match) - return false; - } - return true; - } - int next_device_id_; }; diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc index e235d80..f428ee0 100644 --- a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc +++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc @@ -133,12 +133,8 @@ void MediaStreamDispatcherHost::OnGenerateStream( const std::string& label = media_stream_manager_->GenerateStream( this, render_process_id_, render_view_id, page_request_id, components, security_origin); - if (label.empty()) { - Send(new MediaStreamMsg_StreamGenerationFailed(render_view_id, - page_request_id)); - } else { - StoreRequest(render_view_id, page_request_id, label); - } + CHECK(!label.empty()); + StoreRequest(render_view_id, page_request_id, label); } void MediaStreamDispatcherHost::OnCancelGenerateStream(int render_view_id, diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc index 12f41fb..3e5bc34 100644 --- a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc @@ -15,12 +15,13 @@ #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" #include "content/common/media/media_stream_messages.h" #include "content/common/media/media_stream_options.h" +#include "content/public/browser/media_device_id.h" #include "content/public/test/mock_resource_context.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/test/test_content_browser_client.h" #include "content/test/test_content_client.h" #include "ipc/ipc_message_macros.h" -#include "media/audio/audio_manager.h" +#include "media/audio/mock_audio_manager.h" #include "media/video/capture/fake_video_capture_device.h" #include "net/url_request/url_request_context.h" #include "testing/gmock/include/gmock/gmock.h" @@ -61,10 +62,11 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, void OnGenerateStream(int render_view_id, int page_request_id, const StreamOptions& components, + const GURL& security_origin, const base::Closure& quit_closure) { quit_closures_.push(quit_closure); MediaStreamDispatcherHost::OnGenerateStream( - render_view_id, page_request_id, components, GURL()); + render_view_id, page_request_id, components, security_origin); } void OnStopStreamDevice(int render_view_id, @@ -76,25 +78,28 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, int page_request_id, const std::string& device_id, MediaStreamType type, + const GURL& security_origin, const base::Closure& quit_closure) { quit_closures_.push(quit_closure); MediaStreamDispatcherHost::OnOpenDevice( - render_view_id, page_request_id, device_id, type, GURL()); + render_view_id, page_request_id, device_id, type, security_origin); } - bool FindExistingRequestedDeviceInfo(const std::string& device_id, - MediaStreamRequestType request_type, - StreamDeviceInfo* device_info) { - MediaRequestState request_state; - return media_stream_manager_->FindExistingRequestedDeviceInfo( - kProcessId, kRenderId, request_type, device_id, device_info, - &request_state); + void OnEnumerateDevices(int render_view_id, + int page_request_id, + MediaStreamType type, + const GURL& security_origin, + const base::Closure& quit_closure) { + quit_closures_.push(quit_closure); + MediaStreamDispatcherHost::OnEnumerateDevices( + render_view_id, page_request_id, type, security_origin); } std::string label_; StreamDeviceInfoArray audio_devices_; StreamDeviceInfoArray video_devices_; StreamDeviceInfo opened_device_; + StreamDeviceInfoArray enumerated_devices_; private: virtual ~MockMediaStreamDispatcherHost() {} @@ -115,6 +120,8 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, IPC_MESSAGE_HANDLER(MediaStreamMsg_StopGeneratedStream, OnStopGeneratedStreamFromBrowser) IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpened, OnDeviceOpened) + IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerated, + OnDevicesEnumerated) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() EXPECT_TRUE(handled); @@ -176,6 +183,17 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, opened_device_ = device; } + void OnDevicesEnumerated(const IPC::Message& msg, + int request_id, + const std::string& label, + const StreamDeviceInfoArray& devices) { + base::Closure quit_closure = quit_closures_.front(); + quit_closures_.pop(); + message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure)); + label_ = label; + enumerated_devices_ = devices; + } + scoped_refptr<base::MessageLoopProxy> message_loop_; std::queue<base::Closure> quit_closures_; @@ -190,9 +208,11 @@ class MediaStreamDispatcherHostTest : public testing::Test { public: MediaStreamDispatcherHostTest() : old_browser_client_(NULL), - thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) { + thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), + origin_("https://test.com") { + audio_manager_.reset( + new media::MockAudioManager(base::MessageLoopProxy::current())); // Create our own MediaStreamManager. - audio_manager_.reset(media::AudioManager::Create()); media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); // Make sure we use fake devices to avoid long delays. media_stream_manager_->UseFakeDevice(); @@ -207,10 +227,14 @@ class MediaStreamDispatcherHostTest : public testing::Test { } virtual ~MediaStreamDispatcherHostTest() { - // Recover the old browser client and content client. - SetBrowserClientForTesting(old_browser_client_); - content_client_.reset(); - media_stream_manager_->WillDestroyCurrentMessageLoop(); + } + + virtual void SetUp() OVERRIDE { + media::FakeVideoCaptureDevice::GetDeviceNames(&physical_video_devices_); + ASSERT_GT(physical_video_devices_.size(), 0u); + + audio_manager_->GetAudioInputDeviceNames(&physical_audio_devices_); + ASSERT_GT(physical_audio_devices_.size(), 0u); } virtual void TearDown() OVERRIDE { @@ -231,9 +255,28 @@ class MediaStreamDispatcherHostTest : public testing::Test { int page_request_id, const StreamOptions& options) { base::RunLoop run_loop; - host_->OnGenerateStream(render_view_id, page_request_id, options, + EXPECT_CALL(*host_.get(), OnStreamGenerated( + render_view_id, page_request_id, + options.audio_type != MEDIA_NO_SERVICE ? 1 : 0, + options.video_type != MEDIA_NO_SERVICE ? 1 : 0)); + host_->OnGenerateStream(render_view_id, page_request_id, options, origin_, run_loop.QuitClosure()); run_loop.Run(); + EXPECT_FALSE(DoesContainRawIds(host_->audio_devices_)); + EXPECT_FALSE(DoesContainRawIds(host_->video_devices_)); + EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->audio_devices_, origin_)); + EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->video_devices_, origin_)); + } + + void GenerateStreamAndWaitForFailure(int render_view_id, + int page_request_id, + const StreamOptions& options) { + base::RunLoop run_loop; + EXPECT_CALL(*host_.get(), + OnStreamGenerationFailed(render_view_id, page_request_id)); + host_->OnGenerateStream(render_view_id, page_request_id, options, origin_, + run_loop.QuitClosure()); + run_loop.Run(); } void OpenVideoDeviceAndWaitForResult(int render_view_id, @@ -241,9 +284,96 @@ class MediaStreamDispatcherHostTest : public testing::Test { const std::string& device_id) { base::RunLoop run_loop; host_->OnOpenDevice(render_view_id, page_request_id, device_id, - MEDIA_DEVICE_VIDEO_CAPTURE, + MEDIA_DEVICE_VIDEO_CAPTURE, origin_, run_loop.QuitClosure()); run_loop.Run(); + EXPECT_FALSE(DoesContainRawIds(host_->video_devices_)); + EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->video_devices_, origin_)); + } + + void StopStreamDeviceAndWait(const std::string& device_id) { + EXPECT_TRUE(FindRequestedDeviceInfo(device_id, MEDIA_GENERATE_STREAM, + NULL)); + host_->OnStopStreamDevice(kRenderId, device_id); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(FindRequestedDeviceInfo(device_id, MEDIA_GENERATE_STREAM, + NULL)); + } + + void EnumerateDevicesAndWaitForResult(int render_view_id, + int page_request_id, + MediaStreamType type) { + base::RunLoop run_loop; + host_->OnEnumerateDevices(render_view_id, page_request_id, type, origin_, + run_loop.QuitClosure()); + run_loop.Run(); + ASSERT_FALSE(host_->enumerated_devices_.empty()); + EXPECT_FALSE(DoesContainRawIds(host_->enumerated_devices_)); + EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->enumerated_devices_, origin_)); + } + + bool FindRequestedDeviceInfo(const std::string& device_id, + MediaStreamRequestType request_type, + StreamDeviceInfo* device_info) { + const StreamDeviceInfo* found_device = + media_stream_manager_->FindRequestedDeviceInfoForTest(device_id, + kProcessId, + kRenderId, + request_type); + if (found_device && device_info) { + *device_info = *found_device; + } + return found_device; + } + + bool DoesContainRawIds(const StreamDeviceInfoArray& devices) { + for (size_t i = 0; i < devices.size(); ++i) { + media::AudioDeviceNames::const_iterator audio_it = + physical_audio_devices_.begin(); + for (; audio_it != physical_audio_devices_.end(); ++audio_it) { + if (audio_it->unique_id == devices[i].device.id) + return true; + } + media::VideoCaptureDevice::Names::const_iterator video_it = + physical_video_devices_.begin(); + for (; video_it != physical_video_devices_.end(); ++video_it) { + if (video_it->id() == devices[i].device.id) + return true; + } + } + return false; + } + + bool DoesEveryDeviceMapToRawId(const StreamDeviceInfoArray& devices, + const GURL& origin) { + for (size_t i = 0; i < devices.size(); ++i) { + bool found_match = false; + media::AudioDeviceNames::const_iterator audio_it = + physical_audio_devices_.begin(); + for (; audio_it != physical_audio_devices_.end(); ++audio_it) { + if (content::DoesMediaDeviceIDMatchHMAC( + origin, + devices[i].device.id, + audio_it->unique_id)) { + EXPECT_FALSE(found_match); + found_match = true; + } + } + media::VideoCaptureDevice::Names::const_iterator video_it = + physical_video_devices_.begin(); + for (; video_it != physical_video_devices_.end(); ++video_it) { + if (content::DoesMediaDeviceIDMatchHMAC( + origin, + devices[i].device.id, + video_it->id())) { + EXPECT_FALSE(found_match); + found_match = true; + } + } + if (!found_match) + return false; + } + return true; } scoped_refptr<MockMediaStreamDispatcherHost> host_; @@ -252,19 +382,31 @@ class MediaStreamDispatcherHostTest : public testing::Test { ContentBrowserClient* old_browser_client_; scoped_ptr<ContentClient> content_client_; content::TestBrowserThreadBundle thread_bundle_; + media::AudioDeviceNames physical_audio_devices_; + media::VideoCaptureDevice::Names physical_video_devices_; + GURL origin_; }; TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithVideoOnly) { StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE); SetupFakeUI(true); - EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1)); GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); EXPECT_EQ(host_->audio_devices_.size(), 0u); EXPECT_EQ(host_->video_devices_.size(), 1u); } +TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioOnly) { + StreamOptions options(MEDIA_DEVICE_AUDIO_CAPTURE, MEDIA_NO_SERVICE); + + SetupFakeUI(true); + GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); + + EXPECT_EQ(host_->audio_devices_.size(), 1u); + EXPECT_EQ(host_->video_devices_.size(), 0u); +} + // This test generates two streams with video only using the same render view // id. The same capture device with the same device and session id is expected // to be used. @@ -273,7 +415,6 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsFromSameRenderId) { // Generate first stream. SetupFakeUI(true); - EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1)); GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); // Check the latest generated stream. @@ -285,8 +426,6 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsFromSameRenderId) { // Generate second stream. SetupFakeUI(true); - EXPECT_CALL(*host_.get(), - OnStreamGenerated(kRenderId, kPageRequestId + 1, 0, 1)); GenerateStreamAndWaitForResult(kRenderId, kPageRequestId + 1, options); // Check the latest generated stream. @@ -306,7 +445,6 @@ TEST_F(MediaStreamDispatcherHostTest, // Generate first stream. SetupFakeUI(true); - EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1)); GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); EXPECT_EQ(host_->audio_devices_.size(), 0u); @@ -335,7 +473,6 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsDifferentRenderId) { // Generate first stream. SetupFakeUI(true); - EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1)); GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); // Check the latest generated stream. @@ -347,8 +484,6 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsDifferentRenderId) { // Generate second stream from another render view. SetupFakeUI(true); - EXPECT_CALL(*host_.get(), - OnStreamGenerated(kRenderId+1, kPageRequestId + 1, 0, 1)); GenerateStreamAndWaitForResult(kRenderId+1, kPageRequestId + 1, options); // Check the latest generated stream. @@ -378,41 +513,93 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithoutWaiting) { base::RunLoop run_loop1; base::RunLoop run_loop2; - host_->OnGenerateStream(kRenderId, kPageRequestId, options, + host_->OnGenerateStream(kRenderId, kPageRequestId, options, origin_, run_loop1.QuitClosure()); - host_->OnGenerateStream(kRenderId, kPageRequestId + 1, options, + host_->OnGenerateStream(kRenderId, kPageRequestId + 1, options, origin_, run_loop2.QuitClosure()); run_loop1.Run(); run_loop2.Run(); } +// Test that we can generate streams where a sourceId is specified in the +// request. +TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithSourceId) { + ASSERT_GE(physical_audio_devices_.size(), 1u); + ASSERT_GE(physical_video_devices_.size(), 1u); + + media::AudioDeviceNames::const_iterator audio_it = + physical_audio_devices_.begin(); + for (; audio_it != physical_audio_devices_.end(); ++audio_it) { + StreamOptions options(MEDIA_DEVICE_AUDIO_CAPTURE, + MEDIA_DEVICE_VIDEO_CAPTURE); + options.audio_device_id = content::GetHMACForMediaDeviceID( + origin_, + audio_it->unique_id); + ASSERT_FALSE(options.audio_device_id.empty()); + + // Generate first stream. + SetupFakeUI(true); + GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); + EXPECT_EQ(host_->audio_devices_[0].device.id, options.audio_device_id); + } + + media::VideoCaptureDevice::Names::const_iterator video_it = + physical_video_devices_.begin(); + for (; video_it != physical_video_devices_.end(); ++video_it) { + StreamOptions options(MEDIA_DEVICE_AUDIO_CAPTURE, + MEDIA_DEVICE_VIDEO_CAPTURE); + options.video_device_id = content::GetHMACForMediaDeviceID( + origin_, + video_it->id()); + ASSERT_FALSE(options.video_device_id.empty()); + + // Generate first stream. + SetupFakeUI(true); + GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); + EXPECT_EQ(host_->video_devices_[0].device.id, options.video_device_id); + } +} + +// Test that generating a stream with an invalid video source id fail. +TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithInvalidVideoSourceId) { + StreamOptions options(MEDIA_DEVICE_AUDIO_CAPTURE, + MEDIA_DEVICE_VIDEO_CAPTURE); + std::string invalid_source_id = "invalid source id"; + options.video_device_id = invalid_source_id; + + GenerateStreamAndWaitForFailure(kRenderId, kRenderId, options); +} + +// Test that generating a stream with an invalid audio source id fail. +TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithInvalidAudioSourceId) { + StreamOptions options(MEDIA_DEVICE_AUDIO_CAPTURE, + MEDIA_DEVICE_VIDEO_CAPTURE); + std::string invalid_source_id = "invalid source id"; + options.audio_device_id = invalid_source_id; + + GenerateStreamAndWaitForFailure(kRenderId, kRenderId, options); +} + TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStream) { StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE); SetupFakeUI(true); - EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1)); GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); const std::string device_id = host_->video_devices_.front().device.id; const int session_id = host_->video_devices_.front().session_id; StreamDeviceInfo video_device_info; - EXPECT_TRUE(host_->FindExistingRequestedDeviceInfo(device_id, - MEDIA_GENERATE_STREAM, - &video_device_info)); + EXPECT_TRUE(FindRequestedDeviceInfo(device_id, MEDIA_GENERATE_STREAM, + &video_device_info)); EXPECT_EQ(video_device_info.device.id, device_id); EXPECT_EQ(video_device_info.session_id, session_id); OpenVideoDeviceAndWaitForResult(kRenderId, kPageRequestId, device_id); - host_->OnStopStreamDevice(kRenderId, device_id); + StopStreamDeviceAndWait(device_id); - EXPECT_FALSE(host_->FindExistingRequestedDeviceInfo(device_id, - MEDIA_GENERATE_STREAM, - &video_device_info)); - EXPECT_TRUE(host_->FindExistingRequestedDeviceInfo(device_id, - MEDIA_OPEN_DEVICE, - &video_device_info)); + EXPECT_TRUE(FindRequestedDeviceInfo(device_id, MEDIA_OPEN_DEVICE, NULL)); } TEST_F(MediaStreamDispatcherHostTest, CancelPendingStreamsOnChannelClosing) { @@ -423,13 +610,15 @@ TEST_F(MediaStreamDispatcherHostTest, CancelPendingStreamsOnChannelClosing) { // Create multiple GenerateStream requests. size_t streams = 5; for (size_t i = 1; i <= streams; ++i) { - host_->OnGenerateStream(kRenderId, kPageRequestId + i, options, + host_->OnGenerateStream(kRenderId, kPageRequestId + i, options, origin_, run_loop.QuitClosure()); } // Calling OnChannelClosing() to cancel all the pending requests. host_->OnChannelClosing(); run_loop.RunUntilIdle(); + + media_stream_manager_->WillDestroyCurrentMessageLoop(); } TEST_F(MediaStreamDispatcherHostTest, StopGeneratedStreamsOnChannelClosing) { @@ -439,8 +628,6 @@ TEST_F(MediaStreamDispatcherHostTest, StopGeneratedStreamsOnChannelClosing) { size_t generated_streams = 3; for (size_t i = 0; i < generated_streams; ++i) { SetupFakeUI(true); - EXPECT_CALL(*host_.get(), - OnStreamGenerated(kRenderId, kPageRequestId + i, 0, 1)); GenerateStreamAndWaitForResult(kRenderId, kPageRequestId + i, options); } @@ -458,9 +645,8 @@ TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) { .WillOnce(SaveArg<0>(&close_callback)); media_stream_manager_->UseFakeUI(stream_ui.PassAs<FakeMediaStreamUIProxy>()); - EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1)); - EXPECT_CALL(*host_.get(), OnStopGeneratedStreamFromBrowser(kRenderId)); GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); + EXPECT_CALL(*host_.get(), OnStopGeneratedStreamFromBrowser(kRenderId)); EXPECT_EQ(host_->audio_devices_.size(), 0u); EXPECT_EQ(host_->video_devices_.size(), 1u); @@ -470,4 +656,15 @@ TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) { base::RunLoop().RunUntilIdle(); } +TEST_F(MediaStreamDispatcherHostTest, EnumerateAudioDevices) { + EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId, + MEDIA_DEVICE_AUDIO_CAPTURE); +} + +TEST_F(MediaStreamDispatcherHostTest, EnumerateVideoDevices) { + EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId, + MEDIA_DEVICE_VIDEO_CAPTURE); +} + + }; // namespace content diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc index ff0cdd9..110abfbd 100644 --- a/content/browser/renderer_host/media/media_stream_manager.cc +++ b/content/browser/renderer_host/media/media_stream_manager.cc @@ -12,6 +12,7 @@ #include "base/compiler_specific.h" #include "base/logging.h" #include "base/rand_util.h" +#include "base/run_loop.h" #include "base/threading/thread.h" #include "content/browser/renderer_host/media/audio_input_device_manager.h" #include "content/browser/renderer_host/media/device_request_message_filter.h" @@ -181,6 +182,7 @@ MediaStreamManager::MediaStreamManager(media::AudioManager* audio_manager) } MediaStreamManager::~MediaStreamManager() { + DVLOG(1) << "~MediaStreamManager"; DCHECK(requests_.empty()); DCHECK(!device_thread_.get()); } @@ -207,7 +209,7 @@ std::string MediaStreamManager::MakeMediaAccessRequest( DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); // Create a new request based on options. MediaStreamRequest stream_request( - render_process_id, render_view_id, page_request_id, std::string(), + render_process_id, render_view_id, page_request_id, security_origin, MEDIA_DEVICE_ACCESS, std::string(), std::string(), options.audio_type, options.video_type); DeviceRequest* request = new DeviceRequest(NULL, stream_request, @@ -215,9 +217,10 @@ std::string MediaStreamManager::MakeMediaAccessRequest( const std::string& label = AddRequest(request); request->callback = callback; - - HandleRequest(label); - + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&MediaStreamManager::HandleRequest, + base::Unretained(this), label)); return label; } @@ -238,91 +241,46 @@ std::string MediaStreamManager::GenerateStream( UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy>()); } - int target_render_process_id = render_process_id; - int target_render_view_id = render_view_id; - std::string tab_capture_device_id; - - // Customize options for a WebContents based capture. - if (options.audio_type == MEDIA_TAB_AUDIO_CAPTURE || - options.video_type == MEDIA_TAB_VIDEO_CAPTURE) { - // TODO(justinlin): Can't plumb audio mirroring using stream type right - // now, so plumbing by device_id. Will revisit once it's refactored. - // http://crbug.com/163100 - tab_capture_device_id = - WebContentsCaptureUtil::AppendWebContentsDeviceScheme( - !options.video_device_id.empty() ? - options.video_device_id : options.audio_device_id); - - bool has_valid_device_id = WebContentsCaptureUtil::ExtractTabCaptureTarget( - tab_capture_device_id, &target_render_process_id, - &target_render_view_id); - if (!has_valid_device_id || - (options.audio_type != MEDIA_TAB_AUDIO_CAPTURE && - options.audio_type != MEDIA_NO_SERVICE) || - (options.video_type != MEDIA_TAB_VIDEO_CAPTURE && - options.video_type != MEDIA_NO_SERVICE)) { - LOG(ERROR) << "Invalid request."; - return std::string(); - } - } - - std::string translated_audio_device_id; - std::string translated_video_device_id; - if (options.audio_type == MEDIA_DEVICE_AUDIO_CAPTURE) { - bool found_match = TranslateGUIDToRawId( - MEDIA_DEVICE_AUDIO_CAPTURE, security_origin, options.audio_device_id, - &translated_audio_device_id); - DCHECK(found_match || translated_audio_device_id.empty()); - } - - if (options.video_type == MEDIA_DEVICE_VIDEO_CAPTURE) { - bool found_match = TranslateGUIDToRawId( - MEDIA_DEVICE_VIDEO_CAPTURE, security_origin, options.video_device_id, - &translated_video_device_id); - DCHECK(found_match || translated_video_device_id.empty()); - } - - if (options.video_type == MEDIA_DESKTOP_VIDEO_CAPTURE || - options.audio_type == MEDIA_LOOPBACK_AUDIO_CAPTURE) { - // For screen capture we only support two valid combinations: - // (1) screen video capture only, or - // (2) screen video capture with loopback audio capture. - if (options.video_type != MEDIA_DESKTOP_VIDEO_CAPTURE || - (options.audio_type != MEDIA_NO_SERVICE && - options.audio_type != MEDIA_LOOPBACK_AUDIO_CAPTURE)) { - // TODO(sergeyu): Surface error message to the calling JS code. - LOG(ERROR) << "Invalid screen capture request."; - return std::string(); - } - translated_video_device_id = options.video_device_id; - } - // Create a new request based on options. MediaStreamRequest stream_request( - target_render_process_id, target_render_view_id, page_request_id, - tab_capture_device_id, security_origin, MEDIA_GENERATE_STREAM, - translated_audio_device_id, translated_video_device_id, + render_process_id, render_view_id, page_request_id, + security_origin, MEDIA_GENERATE_STREAM, + options.audio_device_id, options.video_device_id, options.audio_type, options.video_type); DeviceRequest* request = new DeviceRequest(requester, stream_request, render_process_id, render_view_id); const std::string& label = AddRequest(request); - HandleRequest(label); + + // Need to post a task since the requester won't have label till + // this function returns. + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&MediaStreamManager::HandleRequest, + base::Unretained(this), label)); return label; } void MediaStreamManager::CancelRequest(const std::string& label) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - DeviceRequests::iterator request_it = requests_.find(label); - if (request_it == requests_.end()) { - NOTREACHED(); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&MediaStreamManager::DoCancelRequest, + base::Unretained(this), label)); +} + +void MediaStreamManager::DoCancelRequest(const std::string& label) { + DVLOG(1) << "DoCancelRequest({label = " << label << "})"; + + DeviceRequest* request = FindRequest(label); + if (!request) { + // This can happen if the request completes before DoCancelRequest is + // executed or if a client call cancel request on a stream that has failed. return; } - scoped_ptr<DeviceRequest> request(request_it->second); - RemoveRequest(request_it); - if (request->request.request_type == MEDIA_ENUMERATE_DEVICES) { + DeleteRequest(label); return; } @@ -341,6 +299,7 @@ void MediaStreamManager::CancelRequest(const std::string& label) { // Cancel the request if still pending at UI side. request->SetState(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_CLOSING); + DeleteRequest(label); } void MediaStreamManager::CancelAllRequests(int render_process_id) { @@ -353,7 +312,10 @@ void MediaStreamManager::CancelAllRequests(int render_process_id) { std::string label = request_it->first; ++request_it; - CancelRequest(label); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&MediaStreamManager::DoCancelRequest, + base::Unretained(this), label)); } } @@ -363,7 +325,16 @@ void MediaStreamManager::StopStreamDevice(int render_process_id, DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); DVLOG(1) << "StopStreamDevice({render_view_id = " << render_view_id << "} " << ", {device_id = " << device_id << "})"; + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&MediaStreamManager::DoStopStreamDevice, + base::Unretained(this), render_process_id, render_view_id, + device_id)); +} +void MediaStreamManager::DoStopStreamDevice(int render_process_id, + int render_view_id, + const std::string& device_id) { // Find all requests for this |render_process_id| and |render_view_id| of type // MEDIA_GENERATE_STREAM that has requested to use |device_id|. DeviceRequests::iterator request_it = requests_.begin(); @@ -393,10 +364,9 @@ void MediaStreamManager::StopStreamDevice(int render_process_id, // If this request doesn't have any active devices, remove the request. if (devices->empty()) { - DeviceRequests::iterator del_itor(request_it); + std::string label = request_it->first; ++request_it; - scoped_ptr<DeviceRequest> request(del_itor->second); - RemoveRequest(del_itor); + DeleteRequest(label); } else { ++request_it; } @@ -447,42 +417,55 @@ std::string MediaStreamManager::EnumerateDevices( // Create a new request. StreamOptions options; - EnumerationCache* cache = NULL; if (type == MEDIA_DEVICE_AUDIO_CAPTURE) { options.audio_type = type; - cache = &audio_enumeration_cache_; } else if (type == MEDIA_DEVICE_VIDEO_CAPTURE) { options.video_type = type; - cache = &video_enumeration_cache_; } else { NOTREACHED(); return std::string(); } MediaStreamRequest stream_request( - render_process_id, render_view_id, page_request_id, std::string(), + render_process_id, render_view_id, page_request_id, security_origin, MEDIA_ENUMERATE_DEVICES, std::string(), std::string(), options.audio_type, options.video_type); DeviceRequest* request = new DeviceRequest(requester, stream_request, render_process_id, render_view_id); const std::string& label = AddRequest(request); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&MediaStreamManager::DoEnumerateDevices, + base::Unretained(this), label)); + + return label; +} + +void MediaStreamManager::DoEnumerateDevices(const std::string& label) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DeviceRequest* request = FindRequest(label);; + + MediaStreamType type; + EnumerationCache* cache; + if (request->request.audio_type == MEDIA_DEVICE_AUDIO_CAPTURE) { + DCHECK(request->request.video_type == MEDIA_NO_SERVICE); + type = MEDIA_DEVICE_AUDIO_CAPTURE; + cache = &audio_enumeration_cache_; + } else { + DCHECK(request->request.video_type == MEDIA_DEVICE_VIDEO_CAPTURE); + type = MEDIA_DEVICE_VIDEO_CAPTURE; + cache = &video_enumeration_cache_; + } if (cache->valid) { // Cached device list of this type exists. Just send it out. request->SetState(type, MEDIA_REQUEST_STATE_REQUESTED); - - // Need to post a task since the requester won't have label till - // this function returns. - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&MediaStreamManager::SendCachedDeviceList, - base::Unretained(this), cache, label)); + request->devices = cache->devices; + FinalizeEnumerateDevices(label, request); } else { StartEnumeration(request); } - - return label; } std::string MediaStreamManager::OpenDevice( @@ -511,30 +494,21 @@ std::string MediaStreamManager::OpenDevice( } MediaStreamRequest stream_request( - render_process_id, render_view_id, page_request_id, std::string(), + render_process_id, render_view_id, page_request_id, security_origin, MEDIA_OPEN_DEVICE, options.audio_device_id, options.video_device_id, options.audio_type, options.video_type); DeviceRequest* request = new DeviceRequest(requester, stream_request, render_process_id, render_view_id); const std::string& label = AddRequest(request); - StartEnumeration(request); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&MediaStreamManager::HandleRequest, + base::Unretained(this), label)); return label; } -void MediaStreamManager::SendCachedDeviceList( - EnumerationCache* cache, - const std::string& label) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - if (cache->valid) { - DeviceRequests::iterator it = requests_.find(label); - if (it != requests_.end()) { - it->second->requester->DevicesEnumerated(label, cache->devices); - } - } -} - void MediaStreamManager::StartMonitoring() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); if (!base::SystemMonitor::Get()) @@ -563,14 +537,61 @@ void MediaStreamManager::StopMonitoring() { } } -bool MediaStreamManager::TranslateGUIDToRawId(MediaStreamType stream_type, - const GURL& security_origin, - const std::string& device_guid, - std::string* raw_device_id) { +bool MediaStreamManager::TranslateRequestedSourceIdToDeviceId( + MediaStreamRequest* request) { + // If a specific device has been requested we need to find the real device id. + if (request->audio_type == MEDIA_DEVICE_AUDIO_CAPTURE && + !request->requested_audio_device_id.empty()) { + if (!TranslateSourceIdToDeviceId(MEDIA_DEVICE_AUDIO_CAPTURE, + request->security_origin, + request->requested_audio_device_id, + &request->requested_audio_device_id)) { + // TODO(perkj): gUM should support mandatory and optional constraints. + // Ie - if the sourceId is optional but it does not match - gUM should + // not fail. For now we treat sourceId as a mandatory constraint. + LOG(ERROR) << "Requested device does not exist."; + return false; + } + } + + if (request->video_type == MEDIA_DEVICE_VIDEO_CAPTURE && + !request->requested_video_device_id.empty()) { + if (!TranslateSourceIdToDeviceId(MEDIA_DEVICE_VIDEO_CAPTURE, + request->security_origin, + request->requested_video_device_id, + &request->requested_video_device_id)) { + // TODO(perkj): guM should support mandatory and optional constraints. + // Ie - if the sourceId is optional but it does not match - guM should + // not fail. For now we treat sourceId as a mandatory constraint. + return false; + } + } + DVLOG(3) << "Requested audio device " << request->requested_audio_device_id + << "Requested video device " << request->requested_video_device_id; + return true; +} + +void MediaStreamManager::TranslateDeviceIdToSourceId( + const MediaStreamRequest& request, + MediaStreamDevice* device) { + if (request.audio_type == MEDIA_DEVICE_AUDIO_CAPTURE || + request.video_type == MEDIA_DEVICE_VIDEO_CAPTURE) { + device->id = content::GetHMACForMediaDeviceID( + request.security_origin, + device->id); + return; + } + return; +} + +bool MediaStreamManager::TranslateSourceIdToDeviceId( + MediaStreamType stream_type, + const GURL& security_origin, + const std::string& source_id, + std::string* device_id) { DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE || stream_type == MEDIA_DEVICE_VIDEO_CAPTURE); - if (device_guid.empty()) - return false; + DCHECK(!source_id.empty()); EnumerationCache* cache = stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ? @@ -583,9 +604,9 @@ bool MediaStreamManager::TranslateGUIDToRawId(MediaStreamType stream_type, for (StreamDeviceInfoArray::const_iterator it = cache->devices.begin(); it != cache->devices.end(); ++it) { - if (content::DoesMediaDeviceIDMatchHMAC( - security_origin, device_guid, it->device.id)) { - *raw_device_id = it->device.id; + if (content::DoesMediaDeviceIDMatchHMAC(security_origin, source_id, + it->device.id)) { + *device_id = it->device.id; return true; } } @@ -633,13 +654,21 @@ std::string MediaStreamManager::AddRequest(DeviceRequest* request) { return unique_label; } -void MediaStreamManager::RemoveRequest(DeviceRequests::iterator it) { +MediaStreamManager::DeviceRequest* +MediaStreamManager::FindRequest(const std::string& label) { + DeviceRequests::iterator request_it = requests_.find(label); + return request_it == requests_.end() ? NULL : request_it->second; +} + +void MediaStreamManager::DeleteRequest(const std::string& label) { + DeviceRequests::iterator it = requests_.find(label); + scoped_ptr<DeviceRequest> request(it->second); requests_.erase(it); } void MediaStreamManager::PostRequestToUI(const std::string& label) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - DeviceRequest* request = requests_[label]; + DeviceRequest* request = FindRequest(label); if (use_fake_ui_) { if (!fake_ui_) @@ -676,7 +705,7 @@ void MediaStreamManager::PostRequestToUI(const std::string& label) { void MediaStreamManager::HandleRequest(const std::string& label) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - DeviceRequest* request = requests_[label]; + DeviceRequest* request = FindRequest(label); const MediaStreamType audio_type = request->request.audio_type; const MediaStreamType video_type = request->request.video_type; @@ -684,9 +713,17 @@ void MediaStreamManager::HandleRequest(const std::string& label) { bool is_web_contents_capture = audio_type == MEDIA_TAB_AUDIO_CAPTURE || video_type == MEDIA_TAB_VIDEO_CAPTURE; + if (is_web_contents_capture && !SetupTabCaptureRequest(request)) { + FinalizeRequestFailed(label, request); + return; + } bool is_screen_capture = video_type == MEDIA_DESKTOP_VIDEO_CAPTURE; + if (is_screen_capture && !SetupScreenCaptureRequest(request)) { + FinalizeRequestFailed(label, request); + return; + } if (!is_web_contents_capture && !is_screen_capture && @@ -697,6 +734,12 @@ void MediaStreamManager::HandleRequest(const std::string& label) { return; } + // If a specific device has been requested we need to find the real device id. + if (!TranslateRequestedSourceIdToDeviceId(&request->request)) { + FinalizeRequestFailed(label, request); + return; + } + // No need to do new device enumerations, post the request to UI // immediately. if (IsAudioMediaType(audio_type)) @@ -707,25 +750,114 @@ void MediaStreamManager::HandleRequest(const std::string& label) { PostRequestToUI(label); } +bool MediaStreamManager::SetupTabCaptureRequest(DeviceRequest* request) { + DCHECK(request->request.audio_type == MEDIA_TAB_AUDIO_CAPTURE || + request->request.video_type == MEDIA_TAB_VIDEO_CAPTURE); + + MediaStreamRequest* ms_request = &request->request; + // Customize options for a WebContents based capture. + int target_render_process_id = 0; + int target_render_view_id = 0; + + // TODO(justinlin): Can't plumb audio mirroring using stream type right + // now, so plumbing by device_id. Will revisit once it's refactored. + // http://crbug.com/163100 + std::string tab_capture_device_id = + WebContentsCaptureUtil::AppendWebContentsDeviceScheme( + !ms_request->requested_video_device_id.empty() ? + ms_request->requested_video_device_id : + ms_request->requested_audio_device_id); + + bool has_valid_device_id = WebContentsCaptureUtil::ExtractTabCaptureTarget( + tab_capture_device_id, &target_render_process_id, + &target_render_view_id); + if (!has_valid_device_id || + (ms_request->audio_type != MEDIA_TAB_AUDIO_CAPTURE && + ms_request->audio_type != MEDIA_NO_SERVICE) || + (ms_request->video_type != MEDIA_TAB_VIDEO_CAPTURE && + ms_request->video_type != MEDIA_NO_SERVICE)) { + return false; + } + ms_request->tab_capture_device_id = tab_capture_device_id; + ms_request->render_process_id = target_render_process_id; + ms_request->render_view_id = target_render_view_id; + DVLOG(3) << "SetupTabCaptureRequest " + << ", {tab_capture_device_id = " << tab_capture_device_id << "}" + << ", {target_render_process_id = " << target_render_process_id + << "}" + << ", {target_render_view_id = " << target_render_view_id << "}"; + return true; +} + +bool MediaStreamManager::SetupScreenCaptureRequest(DeviceRequest* request) { + DCHECK(request->request.audio_type == MEDIA_LOOPBACK_AUDIO_CAPTURE || + request->request.video_type == MEDIA_DESKTOP_VIDEO_CAPTURE); + const MediaStreamRequest& ms_request = request->request; + + // For screen capture we only support two valid combinations: + // (1) screen video capture only, or + // (2) screen video capture with loopback audio capture. + if (ms_request.video_type != MEDIA_DESKTOP_VIDEO_CAPTURE || + (ms_request.audio_type != MEDIA_NO_SERVICE && + ms_request.audio_type != MEDIA_LOOPBACK_AUDIO_CAPTURE)) { + // TODO(sergeyu): Surface error message to the calling JS code. + LOG(ERROR) << "Invalid screen capture request."; + return false; + } + return true; +} + +const StreamDeviceInfo* MediaStreamManager::FindRequestedDeviceInfoForTest( + const std::string& source_id, + int render_process_id, + int render_view_id, + MediaStreamRequestType type) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + for (DeviceRequests::const_iterator it = requests_.begin(); + it != requests_.end() ; ++it) { + const DeviceRequest* request = it->second; + if (request->request.render_process_id == render_process_id && + request->request.render_view_id == render_view_id && + request->request.request_type == type) { + for (StreamDeviceInfoArray::const_iterator device_it = + request->devices.begin(); + device_it != request->devices.end(); ++device_it) { + if (source_id == device_it->device.id) { + return &*device_it; + } + } + } + } + return NULL; +} + bool MediaStreamManager::FindExistingRequestedDeviceInfo( int render_process_id, int render_view_id, + const GURL& security_origin, MediaStreamRequestType type, const std::string& device_id, + MediaStreamType device_type, StreamDeviceInfo* device_info, MediaRequestState* request_state) const { DCHECK(device_info); DCHECK(request_state); + + std::string source_id = content::GetHMACForMediaDeviceID( + security_origin, + device_id); + for (DeviceRequests::const_iterator it = requests_.begin(); it != requests_.end() ; ++it) { const DeviceRequest* request = it->second; - if (request->requesting_process_id ==render_process_id && + if (request->requesting_process_id == render_process_id && request->requesting_view_id == render_view_id && request->request.request_type == type) { for (StreamDeviceInfoArray::const_iterator device_it = request->devices.begin(); device_it != request->devices.end(); ++device_it) { - if (device_it->device.id == device_id) { + if (device_it->device.id == source_id && + device_it->device.type == device_type) { *device_info = *device_it; *request_state = request->state(device_it->device.type); return true; @@ -736,6 +868,67 @@ bool MediaStreamManager::FindExistingRequestedDeviceInfo( return false; } +void MediaStreamManager::FinalizeGenerateStream(const std::string& label, + DeviceRequest* request) { + const StreamDeviceInfoArray& requested_devices = request->devices; + + // Partition the array of devices into audio vs video. + StreamDeviceInfoArray audio_devices, video_devices; + for (StreamDeviceInfoArray::const_iterator device_it = + requested_devices.begin(); + device_it != requested_devices.end(); ++device_it) { + if (IsAudioMediaType(device_it->device.type)) { + audio_devices.push_back(*device_it); + } else if (IsVideoMediaType(device_it->device.type)) { + video_devices.push_back(*device_it); + } else { + NOTREACHED(); + } + } + + request->requester->StreamGenerated(label, audio_devices, video_devices); +} + +void MediaStreamManager::FinalizeRequestFailed( + const std::string& label, + DeviceRequest* request) { + if (request->requester) + request->requester->StreamGenerationFailed(label); + + if (request->request.request_type == MEDIA_DEVICE_ACCESS && + !request->callback.is_null()) { + request->callback.Run(MediaStreamDevices(), request->ui_proxy.Pass()); + } + + DeleteRequest(label); +} + +void MediaStreamManager::FinalizeOpenDevice(const std::string& label, + DeviceRequest* request) { + const StreamDeviceInfoArray& requested_devices = request->devices; + request->requester->DeviceOpened(label, requested_devices.front()); +} + +void MediaStreamManager::FinalizeEnumerateDevices(const std::string& label, + DeviceRequest* request) { + for (StreamDeviceInfoArray::iterator it = request->devices.begin(); + it != request->devices.end(); ++it) { + TranslateDeviceIdToSourceId(request->request, &it->device); + } + request->requester->DevicesEnumerated(label, request->devices); +} + +void MediaStreamManager::FinalizeMediaAccessRequest( + const std::string& label, + DeviceRequest* request, + const MediaStreamDevices& devices) { + if (!request->callback.is_null()) + request->callback.Run(devices, request->ui_proxy.Pass()); + + // Delete the request since it is done. + DeleteRequest(label); +} + void MediaStreamManager::InitializeDeviceManagersOnIOThread() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); if (device_thread_) @@ -790,7 +983,6 @@ void MediaStreamManager::Opened(MediaStreamType stream_type, const StreamDeviceInfo* info = audio_input_device_manager_->GetOpenedDeviceInfoById( device_it->session_id); - DCHECK_EQ(info->device.id, device_it->device.id); device_it->device.input = info->device.input; device_it->device.matched_output = info->device.matched_output; } @@ -809,27 +1001,12 @@ void MediaStreamManager::HandleRequestDone(const std::string& label, DVLOG(1) << "HandleRequestDone(" << ", {label = " << label << "})"; - const StreamDeviceInfoArray& requested_devices = request->devices; switch (request->request.request_type) { case MEDIA_OPEN_DEVICE: - request->requester->DeviceOpened(label, requested_devices.front()); + FinalizeOpenDevice(label, request); break; case MEDIA_GENERATE_STREAM: { - // Partition the array of devices into audio vs video. - StreamDeviceInfoArray audio_devices, video_devices; - for (StreamDeviceInfoArray::const_iterator device_it = - requested_devices.begin(); - device_it != requested_devices.end(); ++device_it) { - if (IsAudioMediaType(device_it->device.type)) { - audio_devices.push_back(*device_it); - } else if (IsVideoMediaType(device_it->device.type)) { - video_devices.push_back(*device_it); - } else { - NOTREACHED(); - } - } - - request->requester->StreamGenerated(label, audio_devices, video_devices); + FinalizeGenerateStream(label, request); break; } default: @@ -852,6 +1029,7 @@ void MediaStreamManager::Closed(MediaStreamType stream_type, void MediaStreamManager::DevicesEnumerated( MediaStreamType stream_type, const StreamDeviceInfoArray& devices) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DVLOG(1) << "DevicesEnumerated"; // Only cache the device list when the device list has been changed. bool need_update_clients = false; @@ -886,11 +1064,13 @@ void MediaStreamManager::DevicesEnumerated( } for (std::list<std::string>::iterator it = label_list.begin(); it != label_list.end(); ++it) { - DeviceRequest* request = requests_[*it]; + DeviceRequest* request = FindRequest(*it); switch (request->request.request_type) { case MEDIA_ENUMERATE_DEVICES: - if (need_update_clients && request->requester) - request->requester->DevicesEnumerated(*it, devices); + if (need_update_clients && request->requester) { + request->devices = devices; + FinalizeEnumerateDevices(*it, request); + } break; default: if (request->state(request->request.audio_type) == @@ -903,8 +1083,8 @@ void MediaStreamManager::DevicesEnumerated( break; } - // Post the request to UI for permission approval. - PostRequestToUI(*it); + // Continue to handle the request. + HandleRequest(*it); break; } } @@ -913,69 +1093,6 @@ void MediaStreamManager::DevicesEnumerated( DCHECK_GE(active_enumeration_ref_count_[stream_type], 0); } -void MediaStreamManager::Error(MediaStreamType stream_type, - int capture_session_id, - MediaStreamProviderError error) { - // Find the device for the error call. - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - DVLOG(1) << "Error(" - << "{stream_type = " << stream_type << "} ," - << "{capture_session_id = " << capture_session_id << "})"; - - - for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end(); - ++it) { - StreamDeviceInfoArray& devices = it->second->devices; - - // TODO(miu): BUG. It's possible for the audio (or video) device array in - // the "requester" to become out-of-sync with the order of devices we have - // here. See http://crbug.com/147650 - int audio_device_idx = -1; - int video_device_idx = -1; - for (StreamDeviceInfoArray::iterator device_it = devices.begin(); - device_it != devices.end(); ++device_it) { - if (IsAudioMediaType(device_it->device.type)) { - ++audio_device_idx; - } else if (IsVideoMediaType(device_it->device.type)) { - ++video_device_idx; - } else { - NOTREACHED(); - continue; - } - if (device_it->device.type != stream_type || - device_it->session_id != capture_session_id) { - continue; - } - // We've found the failing device. Find the error case: - // An error should only be reported to the MediaStreamManager if - // the request has not been fulfilled yet. - DCHECK(it->second->state(stream_type) != MEDIA_REQUEST_STATE_DONE); - if (it->second->state(stream_type) != MEDIA_REQUEST_STATE_DONE) { - // Request is not done, devices are not opened in this case. - if (devices.size() <= 1) { - scoped_ptr<DeviceRequest> request(it->second); - // 1. Device not opened and no other devices for this request -> - // signal stream error and remove the request. - if (request->requester) - request->requester->StreamGenerationFailed(it->first); - - RemoveRequest(it); - } else { - // 2. Not opened but other devices exists for this request -> remove - // device from list, but don't signal an error. - devices.erase(device_it); // NOTE: This invalidates device_it! - it->second->SetState(stream_type, MEDIA_REQUEST_STATE_ERROR); - DVLOG(1) << "Error(" - << ", {capture_session_id = " << capture_session_id << "})"; - } - } - if (RequestDone(*it->second)) - HandleRequestDone(it->first, it->second); - break; - } - } -} - void MediaStreamManager::HandleAccessRequestResponse( const std::string& label, const MediaStreamDevices& devices) { @@ -983,39 +1100,24 @@ void MediaStreamManager::HandleAccessRequestResponse( DVLOG(1) << "HandleAccessRequestResponse(" << ", {label = " << label << "})"; - DeviceRequests::iterator request_it = requests_.find(label); - if (request_it == requests_.end()) { + DeviceRequest* request = FindRequest(label); + if (!request) { + // The request has been canceled before the UI returns. return; } - // Handle the case when the request was denied. - if (devices.empty()) { - // Notify the users about the request result. - scoped_ptr<DeviceRequest> request(request_it->second); - if (request->requester) - request->requester->StreamGenerationFailed(label); - - if (request->request.request_type == MEDIA_DEVICE_ACCESS && - !request->callback.is_null()) { - request->callback.Run(MediaStreamDevices(), request->ui_proxy.Pass()); - } - - RemoveRequest(request_it); + if (request->request.request_type == MEDIA_DEVICE_ACCESS) { + FinalizeMediaAccessRequest(label, request, devices); return; } - if (request_it->second->request.request_type == MEDIA_DEVICE_ACCESS) { - scoped_ptr<DeviceRequest> request(request_it->second); - if (!request->callback.is_null()) - request->callback.Run(devices, request->ui_proxy.Pass()); - - // Delete the request since it is done. - RemoveRequest(request_it); + // Handle the case when the request was denied. + if (devices.empty()) { + FinalizeRequestFailed(label, request); return; } // Process all newly-accepted devices for this request. - DeviceRequest* request = request_it->second; bool found_audio = false; bool found_video = false; for (MediaStreamDevices::const_iterator device_it = devices.begin(); @@ -1056,13 +1158,14 @@ void MediaStreamManager::HandleAccessRequestResponse( // per render view. This is so that the permission to use a device can be // revoked by a single call to StopStreamDevice regardless of how many // MediaStreams it is being used in. - if (request->request.request_type == MEDIA_GENERATE_STREAM) { MediaRequestState state; if (FindExistingRequestedDeviceInfo(request->requesting_process_id, request->requesting_view_id, + request->request.security_origin, request->request.request_type, - device_it->id, + device_info.device.id, + device_info.device.type, &device_info, &state)) { request->devices.push_back(device_info); @@ -1075,11 +1178,13 @@ void MediaStreamManager::HandleAccessRequestResponse( } device_info.session_id = GetDeviceManager(device_info.device.type)->Open(device_info); + TranslateDeviceIdToSourceId(request->request, &device_info.device); request->devices.push_back(device_info); + request->SetState(device_info.device.type, MEDIA_REQUEST_STATE_OPENING); DVLOG(1) << "HandleAccessRequestResponse - opening device " << ", {label = " << label << "}" - << ", {device_id = " << device_it->id << "}" + << ", {device_id = " << device_info.device.id << "}" << ", {session_id = " << device_info.session_id << "}"; } @@ -1099,15 +1204,15 @@ void MediaStreamManager::HandleAccessRequestResponse( void MediaStreamManager::StopStreamFromUI(const std::string& label) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - DeviceRequests::iterator it = requests_.find(label); - if (it == requests_.end()) + DeviceRequest* request = FindRequest(label); + if (!request) return; // Notify renderers that the stream has been stopped. - if (it->second->requester) - it->second->requester->StopGeneratedStream( - it->second->request.render_view_id, - label); + if (request->requester) { + request->requester->StopGeneratedStream(request->request.render_view_id, + label); + } CancelRequest(label); } @@ -1125,6 +1230,7 @@ void MediaStreamManager::UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy> fake_ui) { } void MediaStreamManager::WillDestroyCurrentMessageLoop() { + DVLOG(3) << "MediaStreamManager::WillDestroyCurrentMessageLoop()"; DCHECK_EQ(base::MessageLoop::current(), io_loop_); DCHECK(requests_.empty()); if (device_thread_) { diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h index 4349a70..6d4bc65 100644 --- a/content/browser/renderer_host/media/media_stream_manager.h +++ b/content/browser/renderer_host/media/media_stream_manager.h @@ -141,9 +141,6 @@ class CONTENT_EXPORT MediaStreamManager int capture_session_id) OVERRIDE; virtual void DevicesEnumerated(MediaStreamType stream_type, const StreamDeviceInfoArray& devices) OVERRIDE; - virtual void Error(MediaStreamType stream_type, - int capture_session_id, - MediaStreamProviderError error) OVERRIDE; // Implements base::SystemMonitor::DevicesChangedObserver. virtual void OnDevicesChanged( @@ -158,12 +155,23 @@ class CONTENT_EXPORT MediaStreamManager // generated stream (or when using --use-fake-ui-for-media-stream). void UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy> fake_ui); + // Used by test to find a StreamDeviceInfo that currently has been + // requested and match the input arguments. If such a StreamDeviceInfo is + // found it is copied to |device_info|. + const StreamDeviceInfo* FindRequestedDeviceInfoForTest( + const std::string& source_id, + int render_process_id, + int render_view_id, + MediaStreamRequestType type); + // This object gets deleted on the UI thread after the IO thread has been // destroyed. So we need to know when IO thread is being destroyed so that - // we can delete VideoCaptureManager and AudioInputDeviceManager. - // We also must call this function explicitly in tests which use - // TestBrowserThreadBundle, because the notification happens too late in that - // case (see http://crbug.com/247525#c14). + // we can delete VideoCaptureManager and AudioInputDeviceManager. Normally + // this is handled by + // base::MessageLoop::DestructionObserver::WillDestroyCurrentMessageLoop. + // But for some tests which use TestBrowserThreadBundle, we need to call + // WillDestroyCurrentMessageLoop explicitly because the notification happens + // too late. (see http://crbug.com/247525#c14). virtual void WillDestroyCurrentMessageLoop() OVERRIDE; protected: @@ -171,8 +179,6 @@ class CONTENT_EXPORT MediaStreamManager MediaStreamManager(); private: - friend class MockMediaStreamDispatcherHost; - // Contains all data needed to keep track of requests. class DeviceRequest; @@ -196,16 +202,23 @@ class CONTENT_EXPORT MediaStreamManager void NotifyDevicesChanged(MediaStreamType stream_type, const StreamDeviceInfoArray& devices); - void HandleAccessRequestResponse(const std::string& label, const MediaStreamDevices& devices); void StopStreamFromUI(const std::string& label); + void DoCancelRequest(const std::string& label); + + void DoStopStreamDevice(int render_process_id, + int render_view_id, + const std::string& device_id); + + void DoEnumerateDevices(const std::string& label); + // Helpers. // Checks if all devices that was requested in the request identififed by // |label| has been opened and set the request state accordingly. void HandleRequestDone(const std::string& label, - DeviceRequest* request); + DeviceRequest* request); void StopDevice(const StreamDeviceInfo& device_info); // Returns true if a request for devices has been completed and the devices // has either been opened or an error has occurred. @@ -213,36 +226,53 @@ class CONTENT_EXPORT MediaStreamManager MediaStreamProvider* GetDeviceManager(MediaStreamType stream_type); void StartEnumeration(DeviceRequest* request); std::string AddRequest(DeviceRequest* request); - void RemoveRequest(DeviceRequests::iterator it); + DeviceRequest* FindRequest(const std::string& label); + void DeleteRequest(const std::string& label); void ClearEnumerationCache(EnumerationCache* cache); void PostRequestToUI(const std::string& label); void HandleRequest(const std::string& label); + bool SetupTabCaptureRequest(DeviceRequest* request); + bool SetupScreenCaptureRequest(DeviceRequest* request); // Returns true if a device with |device_id| has already been requested by // |render_process_id| and |render_view_id| of type |type|. If it has been - // requested, |device_info| contain information about the the device. + // requested, |device_info| contain information about the device. bool FindExistingRequestedDeviceInfo(int render_process_id, int render_view_id, + const GURL& security_origin, MediaStreamRequestType type, const std::string& device_id, + MediaStreamType device_type, StreamDeviceInfo* device_info, MediaRequestState* request_state) const; - // Sends cached device list to a client corresponding to the request - // identified by |label|. - void SendCachedDeviceList(EnumerationCache* cache, const std::string& label); + void FinalizeGenerateStream(const std::string& label, + DeviceRequest* request); + void FinalizeRequestFailed(const std::string& label, + DeviceRequest* request); + void FinalizeOpenDevice(const std::string& label, + DeviceRequest* request); + void FinalizeMediaAccessRequest(const std::string& label, + DeviceRequest* request, + const MediaStreamDevices& devices); + void FinalizeEnumerateDevices(const std::string& label, + DeviceRequest* request); // Helpers to start and stop monitoring devices. void StartMonitoring(); void StopMonitoring(); - // Finds and returns the raw device id corresponding to the given - // |device_guid|. Returns true if there was a raw device id that matched the - // given |device_guid|, false if nothing matched it. - bool TranslateGUIDToRawId( + bool TranslateRequestedSourceIdToDeviceId(MediaStreamRequest* request); + void TranslateDeviceIdToSourceId(const MediaStreamRequest& request, + MediaStreamDevice* device); + + // Finds and returns the device id corresponding to the given + // |source_id|. Returns true if there was a raw device id that matched the + // given |source_id|, false if nothing matched it. + bool TranslateSourceIdToDeviceId( MediaStreamType stream_type, const GURL& security_origin, - const std::string& device_guid, - std::string* raw_device_id); + const std::string& source_id, + std::string* device_id); // Device thread shared by VideoCaptureManager and AudioInputDeviceManager. scoped_ptr<base::Thread> device_thread_; diff --git a/content/browser/renderer_host/media/media_stream_manager_unittest.cc b/content/browser/renderer_host/media/media_stream_manager_unittest.cc index a67237a..887d8b6 100644 --- a/content/browser/renderer_host/media/media_stream_manager_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_manager_unittest.cc @@ -77,7 +77,6 @@ class MediaStreamManagerTest : public ::testing::Test { } virtual ~MediaStreamManagerTest() { - media_stream_manager_->WillDestroyCurrentMessageLoop(); } MOCK_METHOD1(Response, void(int index)); @@ -129,6 +128,8 @@ TEST_F(MediaStreamManagerTest, MakeAndCancelMediaAccessRequest) { std::string label = MakeMediaAccessRequest(0); // No callback is expected. media_stream_manager_->CancelRequest(label); + run_loop_.RunUntilIdle(); + media_stream_manager_->WillDestroyCurrentMessageLoop(); } TEST_F(MediaStreamManagerTest, MakeMultipleRequests) { diff --git a/content/browser/renderer_host/media/media_stream_provider.h b/content/browser/renderer_host/media/media_stream_provider.h index 7f0ff17..3389388 100644 --- a/content/browser/renderer_host/media/media_stream_provider.h +++ b/content/browser/renderer_host/media/media_stream_provider.h @@ -52,11 +52,6 @@ class CONTENT_EXPORT MediaStreamProviderListener { virtual void DevicesEnumerated(MediaStreamType stream_type, const StreamDeviceInfoArray& devices) = 0; - // Called by a MediaStreamProvider when an error has occured. - virtual void Error(MediaStreamType stream_type, - int capture_session_id, - MediaStreamProviderError error) = 0; - protected: virtual ~MediaStreamProviderListener() {} }; diff --git a/content/browser/renderer_host/media/media_stream_ui_proxy.cc b/content/browser/renderer_host/media/media_stream_ui_proxy.cc index 3e4edbc..b91ccb1 100644 --- a/content/browser/renderer_host/media/media_stream_ui_proxy.cc +++ b/content/browser/renderer_host/media/media_stream_ui_proxy.cc @@ -193,12 +193,16 @@ void FakeMediaStreamUIProxy::RequestAccess( it != devices_.end(); ++it) { if (!accepted_audio && IsAudioMediaType(request.audio_type) && - IsAudioMediaType(it->type)) { + IsAudioMediaType(it->type) && + (request.requested_audio_device_id.empty() || + request.requested_audio_device_id == it->id)) { devices_to_use.push_back(*it); accepted_audio = true; } else if (!accepted_video && IsVideoMediaType(request.video_type) && - IsVideoMediaType(it->type)) { + IsVideoMediaType(it->type) && + (request.requested_video_device_id.empty() || + request.requested_video_device_id == it->id)) { devices_to_use.push_back(*it); accepted_video = true; } diff --git a/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc b/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc index 82219a6..bff55c6 100644 --- a/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc @@ -92,7 +92,7 @@ MATCHER_P(SameRequest, expected, "") { } TEST_F(MediaStreamUIProxyTest, Deny) { - MediaStreamRequest request(0, 0, 0, std::string(), GURL("http://origin/"), + MediaStreamRequest request(0, 0, 0, GURL("http://origin/"), MEDIA_GENERATE_STREAM, std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE, @@ -118,7 +118,7 @@ TEST_F(MediaStreamUIProxyTest, Deny) { } TEST_F(MediaStreamUIProxyTest, AcceptAndStart) { - MediaStreamRequest request(0, 0, 0, std::string(), GURL("http://origin/"), + MediaStreamRequest request(0, 0, 0, GURL("http://origin/"), MEDIA_GENERATE_STREAM, std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE, @@ -152,7 +152,7 @@ TEST_F(MediaStreamUIProxyTest, AcceptAndStart) { // Verify that the proxy can be deleted before the request is processed. TEST_F(MediaStreamUIProxyTest, DeleteBeforeAccepted) { - MediaStreamRequest request(0, 0, 0, std::string(), GURL("http://origin/"), + MediaStreamRequest request(0, 0, 0, GURL("http://origin/"), MEDIA_GENERATE_STREAM, std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE, @@ -174,7 +174,7 @@ TEST_F(MediaStreamUIProxyTest, DeleteBeforeAccepted) { } TEST_F(MediaStreamUIProxyTest, StopFromUI) { - MediaStreamRequest request(0, 0, 0, std::string(), GURL("http://origin/"), + MediaStreamRequest request(0, 0, 0, GURL("http://origin/"), MEDIA_GENERATE_STREAM, std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE, diff --git a/content/browser/renderer_host/media/video_capture_host_unittest.cc b/content/browser/renderer_host/media/video_capture_host_unittest.cc index f57cfdb..3189d2c 100644 --- a/content/browser/renderer_host/media/video_capture_host_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_host_unittest.cc @@ -270,15 +270,13 @@ class VideoCaptureHostTest : public testing::Test { // Release the reference to the mock object. The object will be destructed // on the current message loop. host_ = NULL; - - media_stream_manager_->WillDestroyCurrentMessageLoop(); } void OpenSession() { const int render_process_id = 1; const int render_view_id = 1; const int page_request_id = 1; - const GURL security_origin; + const GURL security_origin("http://test.com"); ASSERT_TRUE(opened_device_label_.empty()); diff --git a/content/public/common/media_stream_request.cc b/content/public/common/media_stream_request.cc index 738874e..d9bf5ad 100644 --- a/content/public/common/media_stream_request.cc +++ b/content/public/common/media_stream_request.cc @@ -62,7 +62,6 @@ MediaStreamRequest::MediaStreamRequest( int render_process_id, int render_view_id, int page_request_id, - const std::string& tab_capture_device_id, const GURL& security_origin, MediaStreamRequestType request_type, const std::string& requested_audio_device_id, @@ -72,7 +71,6 @@ MediaStreamRequest::MediaStreamRequest( : render_process_id(render_process_id), render_view_id(render_view_id), page_request_id(page_request_id), - tab_capture_device_id(tab_capture_device_id), security_origin(security_origin), request_type(request_type), requested_audio_device_id(requested_audio_device_id), diff --git a/content/public/common/media_stream_request.h b/content/public/common/media_stream_request.h index 9e612ad..e5400a0 100644 --- a/content/public/common/media_stream_request.h +++ b/content/public/common/media_stream_request.h @@ -26,9 +26,6 @@ enum MediaStreamType { MEDIA_DEVICE_VIDEO_CAPTURE, // Mirroring of a browser tab. - // - // TODO(serygeu): Remove these values and use MEDIA_DESKTOP_VIDEO_CAPTURE and - // MEDIA_DESKTOP_AUDIO_CAPTURE. MEDIA_TAB_AUDIO_CAPTURE, MEDIA_TAB_VIDEO_CAPTURE, @@ -164,7 +161,6 @@ struct CONTENT_EXPORT MediaStreamRequest { int render_process_id, int render_view_id, int page_request_id, - const std::string& tab_capture_device_id, const GURL& security_origin, MediaStreamRequestType request_type, const std::string& requested_audio_device_id, diff --git a/content/renderer/media/media_stream_impl.cc b/content/renderer/media/media_stream_impl.cc index db5dc1e..ba23860 100644 --- a/content/renderer/media/media_stream_impl.cc +++ b/content/renderer/media/media_stream_impl.cc @@ -419,12 +419,6 @@ void MediaStreamImpl::CreateWebKitSourceVector( WebKit::WebVector<WebKit::WebMediaStreamSource>& webkit_sources) { CHECK_EQ(devices.size(), webkit_sources.size()); for (size_t i = 0; i < devices.size(); ++i) { - const char* track_type = - (type == WebKit::WebMediaStreamSource::TypeAudio) ? "a" : "v"; - std::string source_id = base::StringPrintf("%s%s%u", label.c_str(), - track_type, - static_cast<unsigned int>(i)); - const WebKit::WebMediaStreamSource* existing_source = FindLocalSource(devices[i]); if (existing_source) { @@ -434,7 +428,7 @@ void MediaStreamImpl::CreateWebKitSourceVector( continue; } webkit_sources[i].initialize( - UTF8ToUTF16(source_id), + UTF8ToUTF16(devices[i].device.id), type, UTF8ToUTF16(devices[i].device.name)); MediaStreamSourceExtraData* source_extra_data( @@ -530,7 +524,7 @@ const WebKit::WebMediaStreamSource* MediaStreamImpl::FindLocalSource( it->source.extraData()); const StreamDeviceInfo& active_device = extra_data->device_info(); if (active_device.device.id == device.device.id && - active_device.session_id == device.session_id) { + active_device.device.type == device.device.type) { return &it->source; } } diff --git a/content/renderer/media/mock_media_stream_dispatcher.cc b/content/renderer/media/mock_media_stream_dispatcher.cc index a1b9527..793fe3a 100644 --- a/content/renderer/media/mock_media_stream_dispatcher.cc +++ b/content/renderer/media/mock_media_stream_dispatcher.cc @@ -4,7 +4,7 @@ #include "content/renderer/media/mock_media_stream_dispatcher.h" -#include "base/strings/stringprintf.h" +#include "base/strings/string_number_conversions.h" #include "content/public/common/media_stream_request.h" #include "testing/gtest/include/gtest/gtest.h" @@ -28,13 +28,13 @@ void MockMediaStreamDispatcher::GenerateStream( const GURL& url) { request_id_ = request_id; - stream_label_ = base::StringPrintf("%s%d","local_stream",request_id); + stream_label_ = "local_stream" + base::IntToString(request_id); audio_array_.clear(); video_array_.clear(); if (IsAudioMediaType(components.audio_type)) { StreamDeviceInfo audio; - audio.device.id = "audio_device_id"; + audio.device.id = "audio_device_id" + base::IntToString(session_id_); audio.device.name = "microphone"; audio.device.type = components.audio_type; audio.session_id = session_id_; @@ -42,7 +42,7 @@ void MockMediaStreamDispatcher::GenerateStream( } if (IsVideoMediaType(components.video_type)) { StreamDeviceInfo video; - video.device.id = "video_device_id"; + video.device.id = "video_device_id" + base::IntToString(session_id_); video.device.name = "usb video camera"; video.device.type = components.video_type; video.session_id = session_id_; diff --git a/media/audio/mock_audio_manager.cc b/media/audio/mock_audio_manager.cc index a164332..6b54be2 100644 --- a/media/audio/mock_audio_manager.cc +++ b/media/audio/mock_audio_manager.cc @@ -34,6 +34,11 @@ void MockAudioManager::ShowAudioInputSettings() { void MockAudioManager::GetAudioInputDeviceNames( AudioDeviceNames* device_names) { + DCHECK(device_names->empty()); + device_names->push_back(media::AudioDeviceName("fake_device_name_1", + "fake_device_id_1")); + device_names->push_back(media::AudioDeviceName("fake_device_name_2", + "fake_device_id_2")); } void MockAudioManager::GetAudioOutputDeviceNames( diff --git a/media/audio/mock_audio_manager.h b/media/audio/mock_audio_manager.h index 2e2f49b..6b2b4c3 100644 --- a/media/audio/mock_audio_manager.h +++ b/media/audio/mock_audio_manager.h @@ -70,6 +70,7 @@ class MockAudioManager : public media::AudioManager { protected: virtual ~MockAudioManager(); + private: scoped_refptr<base::MessageLoopProxy> message_loop_proxy_; DISALLOW_COPY_AND_ASSIGN(MockAudioManager); |