summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/policy/policy_browsertest.cc4
-rw-r--r--content/browser/renderer_host/media/device_request_message_filter.cc22
-rw-r--r--content/browser/renderer_host/media/device_request_message_filter.h3
-rw-r--r--content/browser/renderer_host/media/device_request_message_filter_unittest.cc48
-rw-r--r--content/browser/renderer_host/media/media_stream_dispatcher_host.cc8
-rw-r--r--content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc285
-rw-r--r--content/browser/renderer_host/media/media_stream_manager.cc578
-rw-r--r--content/browser/renderer_host/media/media_stream_manager.h74
-rw-r--r--content/browser/renderer_host/media/media_stream_manager_unittest.cc3
-rw-r--r--content/browser/renderer_host/media/media_stream_provider.h5
-rw-r--r--content/browser/renderer_host/media/media_stream_ui_proxy.cc8
-rw-r--r--content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc8
-rw-r--r--content/browser/renderer_host/media/video_capture_host_unittest.cc4
-rw-r--r--content/public/common/media_stream_request.cc2
-rw-r--r--content/public/common/media_stream_request.h4
-rw-r--r--content/renderer/media/media_stream_impl.cc10
-rw-r--r--content/renderer/media/mock_media_stream_dispatcher.cc8
-rw-r--r--media/audio/mock_audio_manager.cc5
-rw-r--r--media/audio/mock_audio_manager.h1
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);