1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
9 #include "base/callback_helpers.h"
10 #include "base/command_line.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h"
13 #include "content/browser/browser_thread_impl.h"
14 #include "content/browser/renderer_host/media/audio_input_device_manager.h"
15 #include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
16 #include "content/browser/renderer_host/media/media_stream_manager.h"
17 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
18 #include "content/browser/renderer_host/media/video_capture_manager.h"
19 #include "content/common/media/media_stream_messages.h"
20 #include "content/common/media/media_stream_options.h"
21 #include "content/public/browser/media_device_id.h"
22 #include "content/public/common/content_switches.h"
23 #include "content/public/test/mock_resource_context.h"
24 #include "content/public/test/test_browser_context.h"
25 #include "content/public/test/test_browser_thread_bundle.h"
26 #include "content/test/test_content_browser_client.h"
27 #include "content/test/test_content_client.h"
28 #include "ipc/ipc_message_macros.h"
29 #include "media/audio/mock_audio_manager.h"
30 #include "media/base/media_switches.h"
31 #include "media/video/capture/fake_video_capture_device_factory.h"
32 #include "net/url_request/url_request_context.h"
33 #include "testing/gmock/include/gmock/gmock.h"
34 #include "testing/gtest/include/gtest/gtest.h"
36 #if defined(OS_CHROMEOS)
37 #include "chromeos/audio/cras_audio_handler.h"
41 using ::testing::DeleteArg
;
42 using ::testing::DoAll
;
43 using ::testing::InSequence
;
44 using ::testing::Return
;
45 using ::testing::SaveArg
;
47 const int kProcessId
= 5;
48 const int kRenderId
= 6;
49 const int kPageRequestId
= 7;
53 class MockMediaStreamDispatcherHost
: public MediaStreamDispatcherHost
,
54 public TestContentBrowserClient
{
56 MockMediaStreamDispatcherHost(
57 const ResourceContext::SaltCallback salt_callback
,
58 const scoped_refptr
<base::MessageLoopProxy
>& message_loop
,
59 MediaStreamManager
* manager
)
60 : MediaStreamDispatcherHost(kProcessId
, salt_callback
, manager
),
61 message_loop_(message_loop
),
64 // A list of mock methods.
65 MOCK_METHOD4(OnStreamGenerated
,
66 void(int routing_id
, int request_id
, int audio_array_size
,
67 int video_array_size
));
68 MOCK_METHOD3(OnStreamGenerationFailed
, void(int routing_id
,
70 MediaStreamRequestResult result
));
71 MOCK_METHOD1(OnDeviceStopped
, void(int routing_id
));
72 MOCK_METHOD2(OnDeviceOpened
, void(int routing_id
, int request_id
));
74 // Accessor to private functions.
75 void OnGenerateStream(int render_frame_id
,
77 const StreamOptions
& components
,
78 const GURL
& security_origin
,
79 const base::Closure
& quit_closure
) {
80 quit_closures_
.push(quit_closure
);
81 MediaStreamDispatcherHost::OnGenerateStream(
82 render_frame_id
, page_request_id
, components
, security_origin
, false);
85 void OnStopStreamDevice(int render_frame_id
,
86 const std::string
& device_id
) {
87 MediaStreamDispatcherHost::OnStopStreamDevice(render_frame_id
, device_id
);
90 void OnOpenDevice(int render_frame_id
,
92 const std::string
& device_id
,
94 const GURL
& security_origin
,
95 const base::Closure
& quit_closure
) {
96 quit_closures_
.push(quit_closure
);
97 MediaStreamDispatcherHost::OnOpenDevice(
98 render_frame_id
, page_request_id
, device_id
, type
, security_origin
);
101 void OnEnumerateDevices(int render_frame_id
,
103 MediaStreamType type
,
104 const GURL
& security_origin
,
105 const base::Closure
& quit_closure
) {
106 quit_closures_
.push(quit_closure
);
107 MediaStreamDispatcherHost::OnEnumerateDevices(
108 render_frame_id
, page_request_id
, type
, security_origin
);
112 StreamDeviceInfoArray audio_devices_
;
113 StreamDeviceInfoArray video_devices_
;
114 StreamDeviceInfo opened_device_
;
115 StreamDeviceInfoArray enumerated_devices_
;
118 virtual ~MockMediaStreamDispatcherHost() {}
120 // This method is used to dispatch IPC messages to the renderer. We intercept
121 // these messages here and dispatch to our mock methods to verify the
122 // conversation between this object and the renderer.
123 virtual bool Send(IPC::Message
* message
) override
{
125 current_ipc_
= message
;
127 // In this method we dispatch the messages to the according handlers as if
128 // we are the renderer.
130 IPC_BEGIN_MESSAGE_MAP(MockMediaStreamDispatcherHost
, *message
)
131 IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerated
,
132 OnStreamGeneratedInternal
)
133 IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerationFailed
,
134 OnStreamGenerationFailedInternal
)
135 IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceStopped
, OnDeviceStoppedInternal
)
136 IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpened
, OnDeviceOpenedInternal
)
137 IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerated
, OnDevicesEnumerated
)
138 IPC_MESSAGE_UNHANDLED(handled
= false)
139 IPC_END_MESSAGE_MAP()
140 EXPECT_TRUE(handled
);
147 // These handler methods do minimal things and delegate to the mock methods.
148 void OnStreamGeneratedInternal(
151 StreamDeviceInfoArray audio_device_list
,
152 StreamDeviceInfoArray video_device_list
) {
153 OnStreamGenerated(current_ipc_
->routing_id(), request_id
,
154 audio_device_list
.size(), video_device_list
.size());
155 // Notify that the event have occurred.
156 base::Closure quit_closure
= quit_closures_
.front();
157 quit_closures_
.pop();
158 message_loop_
->PostTask(FROM_HERE
, base::ResetAndReturn(&quit_closure
));
161 audio_devices_
= audio_device_list
;
162 video_devices_
= video_device_list
;
165 void OnStreamGenerationFailedInternal(
167 content::MediaStreamRequestResult result
) {
168 OnStreamGenerationFailed(current_ipc_
->routing_id(), request_id
, result
);
169 if (!quit_closures_
.empty()) {
170 base::Closure quit_closure
= quit_closures_
.front();
171 quit_closures_
.pop();
172 message_loop_
->PostTask(FROM_HERE
, base::ResetAndReturn(&quit_closure
));
178 void OnDeviceStoppedInternal(const std::string
& label
,
179 const content::StreamDeviceInfo
& device
) {
180 if (IsVideoMediaType(device
.device
.type
))
181 EXPECT_TRUE(StreamDeviceInfo::IsEqual(device
, video_devices_
[0]));
182 if (IsAudioInputMediaType(device
.device
.type
))
183 EXPECT_TRUE(StreamDeviceInfo::IsEqual(device
, audio_devices_
[0]));
185 OnDeviceStopped(current_ipc_
->routing_id());
188 void OnDeviceOpenedInternal(int request_id
,
189 const std::string
& label
,
190 const StreamDeviceInfo
& device
) {
191 base::Closure quit_closure
= quit_closures_
.front();
192 quit_closures_
.pop();
193 message_loop_
->PostTask(FROM_HERE
, base::ResetAndReturn(&quit_closure
));
195 opened_device_
= device
;
198 void OnDevicesEnumerated(int request_id
,
199 const StreamDeviceInfoArray
& devices
) {
200 base::Closure quit_closure
= quit_closures_
.front();
201 quit_closures_
.pop();
202 message_loop_
->PostTask(FROM_HERE
, base::ResetAndReturn(&quit_closure
));
203 enumerated_devices_
= devices
;
206 scoped_refptr
<base::MessageLoopProxy
> message_loop_
;
207 IPC::Message
* current_ipc_
;
208 std::queue
<base::Closure
> quit_closures_
;
211 class MockMediaStreamUIProxy
: public FakeMediaStreamUIProxy
{
215 void(const base::Closure
& stop
,
216 const MediaStreamUIProxy::WindowIdCallback
& window_id_callback
));
219 class MediaStreamDispatcherHostTest
: public testing::Test
{
221 MediaStreamDispatcherHostTest()
222 : old_browser_client_(NULL
),
223 thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP
),
224 origin_("https://test.com") {
225 audio_manager_
.reset(
226 new media::MockAudioManager(base::MessageLoopProxy::current()));
227 // Make sure we use fake devices to avoid long delays.
228 base::CommandLine::ForCurrentProcess()->AppendSwitch(
229 switches::kUseFakeDeviceForMediaStream
);
230 // Create our own MediaStreamManager.
231 media_stream_manager_
.reset(new MediaStreamManager(audio_manager_
.get()));
232 video_capture_device_factory_
=
233 static_cast<media::FakeVideoCaptureDeviceFactory
*>(
234 media_stream_manager_
->video_capture_manager()
235 ->video_capture_device_factory());
236 DCHECK(video_capture_device_factory_
);
238 MockResourceContext
* mock_resource_context
=
239 static_cast<MockResourceContext
*>(
240 browser_context_
.GetResourceContext());
242 host_
= new MockMediaStreamDispatcherHost(
243 mock_resource_context
->GetMediaDeviceIDSalt(),
244 base::MessageLoopProxy::current(),
245 media_stream_manager_
.get());
247 // Use the fake content client and browser.
248 content_client_
.reset(new TestContentClient());
249 SetContentClient(content_client_
.get());
250 old_browser_client_
= SetBrowserClientForTesting(host_
.get());
252 #if defined(OS_CHROMEOS)
253 chromeos::CrasAudioHandler::InitializeForTesting();
257 virtual ~MediaStreamDispatcherHostTest() {
258 #if defined(OS_CHROMEOS)
259 chromeos::CrasAudioHandler::Shutdown();
263 virtual void SetUp() override
{
264 video_capture_device_factory_
->GetDeviceNames(&physical_video_devices_
);
265 ASSERT_GT(physical_video_devices_
.size(), 0u);
267 media_stream_manager_
->audio_input_device_manager()->GetFakeDeviceNames(
268 &physical_audio_devices_
);
269 ASSERT_GT(physical_audio_devices_
.size(), 0u);
272 virtual void TearDown() override
{
273 host_
->OnChannelClosing();
277 virtual void SetupFakeUI(bool expect_started
) {
278 stream_ui_
= new MockMediaStreamUIProxy();
279 if (expect_started
) {
280 EXPECT_CALL(*stream_ui_
, OnStarted(_
, _
));
282 media_stream_manager_
->UseFakeUI(
283 scoped_ptr
<FakeMediaStreamUIProxy
>(stream_ui_
));
286 void GenerateStreamAndWaitForResult(int render_frame_id
,
288 const StreamOptions
& options
) {
289 base::RunLoop run_loop
;
290 int expected_audio_array_size
=
291 (options
.audio_requested
&&
292 physical_audio_devices_
.size() > 0) ? 1 : 0;
293 int expected_video_array_size
=
294 (options
.video_requested
&&
295 physical_video_devices_
.size() > 0) ? 1 : 0;
296 EXPECT_CALL(*host_
.get(), OnStreamGenerated(render_frame_id
,
298 expected_audio_array_size
,
299 expected_video_array_size
));
300 host_
->OnGenerateStream(render_frame_id
, page_request_id
, options
, origin_
,
301 run_loop
.QuitClosure());
303 EXPECT_FALSE(DoesContainRawIds(host_
->audio_devices_
));
304 EXPECT_FALSE(DoesContainRawIds(host_
->video_devices_
));
305 EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_
->audio_devices_
, origin_
));
306 EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_
->video_devices_
, origin_
));
309 void GenerateStreamAndWaitForFailure(
312 const StreamOptions
& options
,
313 MediaStreamRequestResult expected_result
) {
314 base::RunLoop run_loop
;
315 EXPECT_CALL(*host_
.get(),
316 OnStreamGenerationFailed(render_frame_id
,
319 host_
->OnGenerateStream(render_frame_id
, page_request_id
, options
,
320 origin_
, run_loop
.QuitClosure());
324 void OpenVideoDeviceAndWaitForResult(int render_frame_id
,
326 const std::string
& device_id
) {
327 base::RunLoop run_loop
;
328 host_
->OnOpenDevice(render_frame_id
, page_request_id
, device_id
,
329 MEDIA_DEVICE_VIDEO_CAPTURE
, origin_
,
330 run_loop
.QuitClosure());
332 EXPECT_FALSE(DoesContainRawIds(host_
->video_devices_
));
333 EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_
->video_devices_
, origin_
));
336 void EnumerateDevicesAndWaitForResult(int render_frame_id
,
338 MediaStreamType type
) {
339 base::RunLoop run_loop
;
340 host_
->OnEnumerateDevices(render_frame_id
, page_request_id
, type
, origin_
,
341 run_loop
.QuitClosure());
343 ASSERT_FALSE(host_
->enumerated_devices_
.empty());
344 EXPECT_FALSE(DoesContainRawIds(host_
->enumerated_devices_
));
345 EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_
->enumerated_devices_
, origin_
));
348 bool DoesContainRawIds(const StreamDeviceInfoArray
& devices
) {
349 for (size_t i
= 0; i
< devices
.size(); ++i
) {
350 media::AudioDeviceNames::const_iterator audio_it
=
351 physical_audio_devices_
.begin();
352 for (; audio_it
!= physical_audio_devices_
.end(); ++audio_it
) {
353 if (audio_it
->unique_id
== devices
[i
].device
.id
)
356 media::VideoCaptureDevice::Names::const_iterator video_it
=
357 physical_video_devices_
.begin();
358 for (; video_it
!= physical_video_devices_
.end(); ++video_it
) {
359 if (video_it
->id() == devices
[i
].device
.id
)
366 bool DoesEveryDeviceMapToRawId(const StreamDeviceInfoArray
& devices
,
367 const GURL
& origin
) {
368 for (size_t i
= 0; i
< devices
.size(); ++i
) {
369 bool found_match
= false;
370 media::AudioDeviceNames::const_iterator audio_it
=
371 physical_audio_devices_
.begin();
372 for (; audio_it
!= physical_audio_devices_
.end(); ++audio_it
) {
373 if (content::DoesMediaDeviceIDMatchHMAC(
374 browser_context_
.GetResourceContext()->GetMediaDeviceIDSalt(),
376 devices
[i
].device
.id
,
377 audio_it
->unique_id
)) {
378 EXPECT_FALSE(found_match
);
382 media::VideoCaptureDevice::Names::const_iterator video_it
=
383 physical_video_devices_
.begin();
384 for (; video_it
!= physical_video_devices_
.end(); ++video_it
) {
385 if (content::DoesMediaDeviceIDMatchHMAC(
386 browser_context_
.GetResourceContext()->GetMediaDeviceIDSalt(),
388 devices
[i
].device
.id
,
390 EXPECT_FALSE(found_match
);
400 // Returns true if all devices have labels, false otherwise.
401 bool DoesContainLabels(const StreamDeviceInfoArray
& devices
) {
402 for (size_t i
= 0; i
< devices
.size(); ++i
) {
403 if (devices
[i
].device
.name
.empty())
409 // Returns true if no devices have labels, false otherwise.
410 bool DoesNotContainLabels(const StreamDeviceInfoArray
& devices
) {
411 for (size_t i
= 0; i
< devices
.size(); ++i
) {
412 if (!devices
[i
].device
.name
.empty())
418 void AddSourceIdConstraint(const std::string
& source_id
,
419 StreamOptions::Constraints
* constraints
) {
420 constraints
->push_back(StreamOptions::Constraint(kMediaStreamSourceInfoId
,
424 scoped_refptr
<MockMediaStreamDispatcherHost
> host_
;
425 scoped_ptr
<media::AudioManager
> audio_manager_
;
426 scoped_ptr
<MediaStreamManager
> media_stream_manager_
;
427 MockMediaStreamUIProxy
* stream_ui_
;
428 ContentBrowserClient
* old_browser_client_
;
429 scoped_ptr
<ContentClient
> content_client_
;
430 content::TestBrowserThreadBundle thread_bundle_
;
431 content::TestBrowserContext browser_context_
;
432 media::AudioDeviceNames physical_audio_devices_
;
433 media::VideoCaptureDevice::Names physical_video_devices_
;
435 media::FakeVideoCaptureDeviceFactory
* video_capture_device_factory_
;
438 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamWithVideoOnly
) {
439 StreamOptions
options(false, true);
442 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
444 EXPECT_EQ(host_
->audio_devices_
.size(), 0u);
445 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
448 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamWithAudioOnly
) {
449 StreamOptions
options(true, false);
452 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
454 EXPECT_EQ(host_
->audio_devices_
.size(), 1u);
455 EXPECT_EQ(host_
->video_devices_
.size(), 0u);
458 // This test simulates a shutdown scenario: we don't setup a fake UI proxy for
459 // MediaStreamManager, so it will create an ordinary one which will not find
460 // a RenderFrameHostDelegate. This normally should only be the case at shutdown.
461 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamWithNothing
) {
462 StreamOptions
options(false, false);
464 GenerateStreamAndWaitForFailure(
468 MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN
);
471 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamWithAudioAndVideo
) {
472 StreamOptions
options(true, true);
475 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
477 EXPECT_EQ(host_
->audio_devices_
.size(), 1u);
478 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
481 // This test generates two streams with video only using the same render frame
482 // id. The same capture device with the same device and session id is expected
484 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamsFromSameRenderId
) {
485 StreamOptions
options(false, true);
487 // Generate first stream.
489 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
491 // Check the latest generated stream.
492 EXPECT_EQ(host_
->audio_devices_
.size(), 0u);
493 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
494 const std::string label1
= host_
->label_
;
495 const std::string device_id1
= host_
->video_devices_
.front().device
.id
;
496 const int session_id1
= host_
->video_devices_
.front().session_id
;
498 // Generate second stream.
500 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
+ 1, options
);
502 // Check the latest generated stream.
503 EXPECT_EQ(host_
->audio_devices_
.size(), 0u);
504 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
505 const std::string label2
= host_
->label_
;
506 const std::string device_id2
= host_
->video_devices_
.front().device
.id
;
507 int session_id2
= host_
->video_devices_
.front().session_id
;
508 EXPECT_EQ(device_id1
, device_id2
);
509 EXPECT_EQ(session_id1
, session_id2
);
510 EXPECT_NE(label1
, label2
);
513 TEST_F(MediaStreamDispatcherHostTest
,
514 GenerateStreamAndOpenDeviceFromSameRenderId
) {
515 StreamOptions
options(false, true);
517 // Generate first stream.
519 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
521 EXPECT_EQ(host_
->audio_devices_
.size(), 0u);
522 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
523 const std::string label1
= host_
->label_
;
524 const std::string device_id1
= host_
->video_devices_
.front().device
.id
;
525 const int session_id1
= host_
->video_devices_
.front().session_id
;
527 // Generate second stream.
528 OpenVideoDeviceAndWaitForResult(kRenderId
, kPageRequestId
, device_id1
);
530 const std::string device_id2
= host_
->opened_device_
.device
.id
;
531 const int session_id2
= host_
->opened_device_
.session_id
;
532 const std::string label2
= host_
->label_
;
534 EXPECT_EQ(device_id1
, device_id2
);
535 EXPECT_NE(session_id1
, session_id2
);
536 EXPECT_NE(label1
, label2
);
540 // This test generates two streams with video only using two separate render
541 // frame ids. The same device id but different session ids are expected.
542 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamsDifferentRenderId
) {
543 StreamOptions
options(false, true);
545 // Generate first stream.
547 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
549 // Check the latest generated stream.
550 EXPECT_EQ(host_
->audio_devices_
.size(), 0u);
551 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
552 const std::string label1
= host_
->label_
;
553 const std::string device_id1
= host_
->video_devices_
.front().device
.id
;
554 const int session_id1
= host_
->video_devices_
.front().session_id
;
556 // Generate second stream from another render frame.
558 GenerateStreamAndWaitForResult(kRenderId
+1, kPageRequestId
+ 1, options
);
560 // Check the latest generated stream.
561 EXPECT_EQ(host_
->audio_devices_
.size(), 0u);
562 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
563 const std::string label2
= host_
->label_
;
564 const std::string device_id2
= host_
->video_devices_
.front().device
.id
;
565 const int session_id2
= host_
->video_devices_
.front().session_id
;
566 EXPECT_EQ(device_id1
, device_id2
);
567 EXPECT_NE(session_id1
, session_id2
);
568 EXPECT_NE(label1
, label2
);
571 // This test request two streams with video only without waiting for the first
572 // stream to be generated before requesting the second.
573 // The same device id and session ids are expected.
574 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamsWithoutWaiting
) {
575 StreamOptions
options(false, true);
577 // Generate first stream.
581 EXPECT_CALL(*host_
.get(),
582 OnStreamGenerated(kRenderId
, kPageRequestId
, 0, 1));
584 // Generate second stream.
585 EXPECT_CALL(*host_
.get(),
586 OnStreamGenerated(kRenderId
, kPageRequestId
+ 1, 0, 1));
588 base::RunLoop run_loop1
;
589 base::RunLoop run_loop2
;
590 host_
->OnGenerateStream(kRenderId
, kPageRequestId
, options
, origin_
,
591 run_loop1
.QuitClosure());
592 host_
->OnGenerateStream(kRenderId
, kPageRequestId
+ 1, options
, origin_
,
593 run_loop2
.QuitClosure());
599 // Test that we can generate streams where a mandatory sourceId is specified in
601 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamsWithMandatorySourceId
) {
602 ASSERT_GE(physical_audio_devices_
.size(), 1u);
603 ASSERT_GE(physical_video_devices_
.size(), 1u);
605 media::AudioDeviceNames::const_iterator audio_it
=
606 physical_audio_devices_
.begin();
607 for (; audio_it
!= physical_audio_devices_
.end(); ++audio_it
) {
608 std::string source_id
= content::GetHMACForMediaDeviceID(
609 browser_context_
.GetResourceContext()->GetMediaDeviceIDSalt(),
611 audio_it
->unique_id
);
612 ASSERT_FALSE(source_id
.empty());
613 StreamOptions
options(true, true);
614 AddSourceIdConstraint(source_id
, &options
.mandatory_audio
);
617 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
618 EXPECT_EQ(host_
->audio_devices_
[0].device
.id
, source_id
);
621 media::VideoCaptureDevice::Names::const_iterator video_it
=
622 physical_video_devices_
.begin();
623 for (; video_it
!= physical_video_devices_
.end(); ++video_it
) {
624 std::string source_id
= content::GetHMACForMediaDeviceID(
625 browser_context_
.GetResourceContext()->GetMediaDeviceIDSalt(),
628 ASSERT_FALSE(source_id
.empty());
629 StreamOptions
options(true, true);
630 AddSourceIdConstraint(source_id
, &options
.mandatory_video
);
633 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
634 EXPECT_EQ(host_
->video_devices_
[0].device
.id
, source_id
);
638 // Test that we can generate streams where a optional sourceId is specified in
640 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamsWithOptionalSourceId
) {
641 ASSERT_GE(physical_audio_devices_
.size(), 1u);
642 ASSERT_GE(physical_video_devices_
.size(), 1u);
644 media::AudioDeviceNames::const_iterator audio_it
=
645 physical_audio_devices_
.begin();
646 for (; audio_it
!= physical_audio_devices_
.end(); ++audio_it
) {
647 std::string source_id
= content::GetHMACForMediaDeviceID(
648 browser_context_
.GetResourceContext()->GetMediaDeviceIDSalt(),
650 audio_it
->unique_id
);
651 ASSERT_FALSE(source_id
.empty());
652 StreamOptions
options(true, true);
653 AddSourceIdConstraint(source_id
, &options
.optional_audio
);
656 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
657 EXPECT_EQ(host_
->audio_devices_
[0].device
.id
, source_id
);
660 media::VideoCaptureDevice::Names::const_iterator video_it
=
661 physical_video_devices_
.begin();
662 for (; video_it
!= physical_video_devices_
.end(); ++video_it
) {
663 std::string source_id
= content::GetHMACForMediaDeviceID(
664 browser_context_
.GetResourceContext()->GetMediaDeviceIDSalt(),
667 ASSERT_FALSE(source_id
.empty());
668 StreamOptions
options(true, true);
669 AddSourceIdConstraint(source_id
, &options
.optional_video
);
672 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
673 EXPECT_EQ(host_
->video_devices_
[0].device
.id
, source_id
);
677 // Test that generating a stream with an invalid mandatory video source id fail.
678 TEST_F(MediaStreamDispatcherHostTest
,
679 GenerateStreamsWithInvalidMandatoryVideoSourceId
) {
680 StreamOptions
options(true, true);
681 AddSourceIdConstraint("invalid source id", &options
.mandatory_video
);
683 GenerateStreamAndWaitForFailure(
687 MEDIA_DEVICE_NO_HARDWARE
);
690 // Test that generating a stream with an invalid mandatory audio source id fail.
691 TEST_F(MediaStreamDispatcherHostTest
,
692 GenerateStreamsWithInvalidMandatoryAudioSourceId
) {
693 StreamOptions
options(true, true);
694 AddSourceIdConstraint("invalid source id", &options
.mandatory_audio
);
696 GenerateStreamAndWaitForFailure(
700 MEDIA_DEVICE_NO_HARDWARE
);
703 // Test that generating a stream with an invalid optional video source id
705 TEST_F(MediaStreamDispatcherHostTest
,
706 GenerateStreamsWithInvalidOptionalVideoSourceId
) {
707 StreamOptions
options(true, true);
708 AddSourceIdConstraint("invalid source id", &options
.optional_video
);
711 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
714 // Test that generating a stream with an invalid optional audio source id
716 TEST_F(MediaStreamDispatcherHostTest
,
717 GenerateStreamsWithInvalidOptionalAudioSourceId
) {
718 StreamOptions
options(true, true);
719 AddSourceIdConstraint("invalid source id", &options
.optional_audio
);
722 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
725 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamsNoAvailableVideoDevice
) {
726 physical_video_devices_
.clear();
727 video_capture_device_factory_
->set_number_of_devices(0);
728 video_capture_device_factory_
->GetDeviceNames(&physical_video_devices_
);
729 StreamOptions
options(true, true);
732 GenerateStreamAndWaitForFailure(kRenderId
, kPageRequestId
, options
,
733 MEDIA_DEVICE_NO_HARDWARE
);
736 // Test that if a OnStopStreamDevice message is received for a device that has
737 // been opened in a MediaStream and by pepper, the device is only stopped for
739 TEST_F(MediaStreamDispatcherHostTest
, StopDeviceInStream
) {
740 StreamOptions
options(false, true);
743 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
745 std::string stream_request_label
= host_
->label_
;
746 StreamDeviceInfo video_device_info
= host_
->video_devices_
.front();
747 ASSERT_EQ(1u, media_stream_manager_
->GetDevicesOpenedByRequest(
748 stream_request_label
).size());
750 // Open the same device by Pepper.
751 OpenVideoDeviceAndWaitForResult(kRenderId
, kPageRequestId
,
752 video_device_info
.device
.id
);
753 std::string open_device_request_label
= host_
->label_
;
755 // Stop the device in the MediaStream.
756 host_
->OnStopStreamDevice(kRenderId
, video_device_info
.device
.id
);
758 EXPECT_EQ(0u, media_stream_manager_
->GetDevicesOpenedByRequest(
759 stream_request_label
).size());
760 EXPECT_EQ(1u, media_stream_manager_
->GetDevicesOpenedByRequest(
761 open_device_request_label
).size());
764 TEST_F(MediaStreamDispatcherHostTest
, StopDeviceInStreamAndRestart
) {
765 StreamOptions
options(true, true);
768 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
770 std::string request_label1
= host_
->label_
;
771 StreamDeviceInfo video_device_info
= host_
->video_devices_
.front();
772 // Expect that 1 audio and 1 video device has been opened.
773 EXPECT_EQ(2u, media_stream_manager_
->GetDevicesOpenedByRequest(
774 request_label1
).size());
776 host_
->OnStopStreamDevice(kRenderId
, video_device_info
.device
.id
);
777 EXPECT_EQ(1u, media_stream_manager_
->GetDevicesOpenedByRequest(
778 request_label1
).size());
780 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
781 std::string request_label2
= host_
->label_
;
783 StreamDeviceInfoArray request1_devices
=
784 media_stream_manager_
->GetDevicesOpenedByRequest(request_label1
);
785 StreamDeviceInfoArray request2_devices
=
786 media_stream_manager_
->GetDevicesOpenedByRequest(request_label2
);
788 ASSERT_EQ(1u, request1_devices
.size());
789 ASSERT_EQ(2u, request2_devices
.size());
791 // Test that the same audio device has been opened in both streams.
792 EXPECT_TRUE(StreamDeviceInfo::IsEqual(request1_devices
[0],
793 request2_devices
[0]) ||
794 StreamDeviceInfo::IsEqual(request1_devices
[0],
795 request2_devices
[1]));
798 TEST_F(MediaStreamDispatcherHostTest
,
799 GenerateTwoStreamsAndStopDeviceWhileWaitingForSecondStream
) {
800 StreamOptions
options(false, true);
803 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
804 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
806 // Generate a second stream.
807 EXPECT_CALL(*host_
.get(),
808 OnStreamGenerated(kRenderId
, kPageRequestId
+ 1, 0, 1));
810 base::RunLoop run_loop1
;
811 host_
->OnGenerateStream(kRenderId
, kPageRequestId
+ 1, options
, origin_
,
812 run_loop1
.QuitClosure());
814 // Stop the video stream device from stream 1 while waiting for the
815 // second stream to be generated.
816 host_
->OnStopStreamDevice(kRenderId
, host_
->video_devices_
[0].device
.id
);
819 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
822 TEST_F(MediaStreamDispatcherHostTest
, CancelPendingStreamsOnChannelClosing
) {
823 StreamOptions
options(false, true);
825 base::RunLoop run_loop
;
827 // Create multiple GenerateStream requests.
829 for (size_t i
= 1; i
<= streams
; ++i
) {
830 host_
->OnGenerateStream(kRenderId
, kPageRequestId
+ i
, options
, origin_
,
831 run_loop
.QuitClosure());
834 // Calling OnChannelClosing() to cancel all the pending requests.
835 host_
->OnChannelClosing();
836 run_loop
.RunUntilIdle();
839 TEST_F(MediaStreamDispatcherHostTest
, StopGeneratedStreamsOnChannelClosing
) {
840 StreamOptions
options(false, true);
842 // Create first group of streams.
843 size_t generated_streams
= 3;
844 for (size_t i
= 0; i
< generated_streams
; ++i
) {
846 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
+ i
, options
);
849 // Calling OnChannelClosing() to cancel all the pending/generated streams.
850 host_
->OnChannelClosing();
851 base::RunLoop().RunUntilIdle();
854 TEST_F(MediaStreamDispatcherHostTest
, CloseFromUI
) {
855 StreamOptions
options(false, true);
857 base::Closure close_callback
;
858 scoped_ptr
<MockMediaStreamUIProxy
> stream_ui(new MockMediaStreamUIProxy());
859 EXPECT_CALL(*stream_ui
, OnStarted(_
, _
))
860 .WillOnce(SaveArg
<0>(&close_callback
));
861 media_stream_manager_
->UseFakeUI(stream_ui
.Pass());
863 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
865 EXPECT_EQ(host_
->audio_devices_
.size(), 0u);
866 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
868 ASSERT_FALSE(close_callback
.is_null());
869 EXPECT_CALL(*host_
.get(), OnDeviceStopped(kRenderId
));
870 close_callback
.Run();
871 base::RunLoop().RunUntilIdle();
874 // Test that the dispatcher is notified if a video device that is in use is
876 TEST_F(MediaStreamDispatcherHostTest
, VideoDeviceUnplugged
) {
877 StreamOptions
options(true, true);
879 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
880 EXPECT_EQ(host_
->audio_devices_
.size(), 1u);
881 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
883 video_capture_device_factory_
->set_number_of_devices(0);
885 base::RunLoop run_loop
;
886 EXPECT_CALL(*host_
.get(), OnDeviceStopped(kRenderId
))
887 .WillOnce(testing::InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
));
888 media_stream_manager_
->OnDevicesChanged(
889 base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE
);
894 TEST_F(MediaStreamDispatcherHostTest
, EnumerateAudioDevices
) {
896 EnumerateDevicesAndWaitForResult(kRenderId
, kPageRequestId
,
897 MEDIA_DEVICE_AUDIO_CAPTURE
);
898 EXPECT_TRUE(DoesContainLabels(host_
->enumerated_devices_
));
901 TEST_F(MediaStreamDispatcherHostTest
, EnumerateVideoDevices
) {
903 EnumerateDevicesAndWaitForResult(kRenderId
, kPageRequestId
,
904 MEDIA_DEVICE_VIDEO_CAPTURE
);
905 EXPECT_TRUE(DoesContainLabels(host_
->enumerated_devices_
));
908 TEST_F(MediaStreamDispatcherHostTest
, EnumerateAudioDevicesNoAccess
) {
910 stream_ui_
->SetMicAccess(false);
911 EnumerateDevicesAndWaitForResult(kRenderId
, kPageRequestId
,
912 MEDIA_DEVICE_AUDIO_CAPTURE
);
913 EXPECT_TRUE(DoesNotContainLabels(host_
->enumerated_devices_
));
916 TEST_F(MediaStreamDispatcherHostTest
, EnumerateVideoDevicesNoAccess
) {
918 stream_ui_
->SetCameraAccess(false);
919 EnumerateDevicesAndWaitForResult(kRenderId
, kPageRequestId
,
920 MEDIA_DEVICE_VIDEO_CAPTURE
);
921 EXPECT_TRUE(DoesNotContainLabels(host_
->enumerated_devices_
));
924 }; // namespace content