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"
37 using ::testing::DeleteArg
;
38 using ::testing::DoAll
;
39 using ::testing::Return
;
40 using ::testing::SaveArg
;
42 const int kProcessId
= 5;
43 const int kRenderId
= 6;
44 const int kPageRequestId
= 7;
48 class MockMediaStreamDispatcherHost
: public MediaStreamDispatcherHost
,
49 public TestContentBrowserClient
{
51 MockMediaStreamDispatcherHost(
52 const ResourceContext::SaltCallback salt_callback
,
53 const scoped_refptr
<base::MessageLoopProxy
>& message_loop
,
54 MediaStreamManager
* manager
,
55 ResourceContext
* resource_context
)
56 : MediaStreamDispatcherHost(kProcessId
, salt_callback
, manager
,
58 message_loop_(message_loop
),
61 // A list of mock methods.
62 MOCK_METHOD4(OnStreamGenerated
,
63 void(int routing_id
, int request_id
, int audio_array_size
,
64 int video_array_size
));
65 MOCK_METHOD3(OnStreamGenerationFailed
, void(int routing_id
,
67 MediaStreamRequestResult result
));
68 MOCK_METHOD1(OnDeviceStopped
, void(int routing_id
));
69 MOCK_METHOD2(OnDeviceOpened
, void(int routing_id
, int request_id
));
71 // Accessor to private functions.
72 void OnGenerateStream(int render_view_id
,
74 const StreamOptions
& components
,
75 const GURL
& security_origin
,
76 const base::Closure
& quit_closure
) {
77 quit_closures_
.push(quit_closure
);
78 MediaStreamDispatcherHost::OnGenerateStream(
79 render_view_id
, page_request_id
, components
, security_origin
, false);
82 void OnStopStreamDevice(int render_view_id
,
83 const std::string
& device_id
) {
84 MediaStreamDispatcherHost::OnStopStreamDevice(render_view_id
, device_id
);
87 void OnOpenDevice(int render_view_id
,
89 const std::string
& device_id
,
91 const GURL
& security_origin
,
92 const base::Closure
& quit_closure
) {
93 quit_closures_
.push(quit_closure
);
94 MediaStreamDispatcherHost::OnOpenDevice(
95 render_view_id
, page_request_id
, device_id
, type
, security_origin
);
98 void OnEnumerateDevices(int render_view_id
,
100 MediaStreamType type
,
101 const GURL
& security_origin
,
102 const base::Closure
& quit_closure
) {
103 quit_closures_
.push(quit_closure
);
104 MediaStreamDispatcherHost::OnEnumerateDevices(
105 render_view_id
, page_request_id
, type
, security_origin
);
109 StreamDeviceInfoArray audio_devices_
;
110 StreamDeviceInfoArray video_devices_
;
111 StreamDeviceInfo opened_device_
;
112 StreamDeviceInfoArray enumerated_devices_
;
115 virtual ~MockMediaStreamDispatcherHost() {}
117 // This method is used to dispatch IPC messages to the renderer. We intercept
118 // these messages here and dispatch to our mock methods to verify the
119 // conversation between this object and the renderer.
120 virtual bool Send(IPC::Message
* message
) OVERRIDE
{
122 current_ipc_
= message
;
124 // In this method we dispatch the messages to the according handlers as if
125 // we are the renderer.
127 IPC_BEGIN_MESSAGE_MAP(MockMediaStreamDispatcherHost
, *message
)
128 IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerated
,
129 OnStreamGeneratedInternal
)
130 IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerationFailed
,
131 OnStreamGenerationFailedInternal
)
132 IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceStopped
, OnDeviceStoppedInternal
)
133 IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpened
, OnDeviceOpenedInternal
)
134 IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerated
, OnDevicesEnumerated
)
135 IPC_MESSAGE_UNHANDLED(handled
= false)
136 IPC_END_MESSAGE_MAP()
137 EXPECT_TRUE(handled
);
144 // These handler methods do minimal things and delegate to the mock methods.
145 void OnStreamGeneratedInternal(
148 StreamDeviceInfoArray audio_device_list
,
149 StreamDeviceInfoArray video_device_list
) {
150 OnStreamGenerated(current_ipc_
->routing_id(), request_id
,
151 audio_device_list
.size(), video_device_list
.size());
152 // Notify that the event have occurred.
153 base::Closure quit_closure
= quit_closures_
.front();
154 quit_closures_
.pop();
155 message_loop_
->PostTask(FROM_HERE
, base::ResetAndReturn(&quit_closure
));
158 audio_devices_
= audio_device_list
;
159 video_devices_
= video_device_list
;
162 void OnStreamGenerationFailedInternal(
164 content::MediaStreamRequestResult result
) {
165 OnStreamGenerationFailed(current_ipc_
->routing_id(), request_id
, result
);
166 if (!quit_closures_
.empty()) {
167 base::Closure quit_closure
= quit_closures_
.front();
168 quit_closures_
.pop();
169 message_loop_
->PostTask(FROM_HERE
, base::ResetAndReturn(&quit_closure
));
175 void OnDeviceStoppedInternal(const std::string
& label
,
176 const content::StreamDeviceInfo
& device
) {
177 if (IsVideoMediaType(device
.device
.type
))
178 EXPECT_TRUE(StreamDeviceInfo::IsEqual(device
, video_devices_
[0]));
179 if (IsAudioMediaType(device
.device
.type
))
180 EXPECT_TRUE(StreamDeviceInfo::IsEqual(device
, audio_devices_
[0]));
182 OnDeviceStopped(current_ipc_
->routing_id());
185 void OnDeviceOpenedInternal(int request_id
,
186 const std::string
& label
,
187 const StreamDeviceInfo
& device
) {
188 base::Closure quit_closure
= quit_closures_
.front();
189 quit_closures_
.pop();
190 message_loop_
->PostTask(FROM_HERE
, base::ResetAndReturn(&quit_closure
));
192 opened_device_
= device
;
195 void OnDevicesEnumerated(int request_id
,
196 const StreamDeviceInfoArray
& devices
) {
197 base::Closure quit_closure
= quit_closures_
.front();
198 quit_closures_
.pop();
199 message_loop_
->PostTask(FROM_HERE
, base::ResetAndReturn(&quit_closure
));
200 enumerated_devices_
= devices
;
203 scoped_refptr
<base::MessageLoopProxy
> message_loop_
;
204 IPC::Message
* current_ipc_
;
205 std::queue
<base::Closure
> quit_closures_
;
208 class MockMediaStreamUIProxy
: public FakeMediaStreamUIProxy
{
212 void(const base::Closure
& stop
,
213 const MediaStreamUIProxy::WindowIdCallback
& window_id_callback
));
216 class MediaStreamDispatcherHostTest
: public testing::Test
{
218 MediaStreamDispatcherHostTest()
219 : old_browser_client_(NULL
),
220 thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP
),
221 origin_("https://test.com") {
222 audio_manager_
.reset(
223 new media::MockAudioManager(base::MessageLoopProxy::current()));
224 // Make sure we use fake devices to avoid long delays.
225 CommandLine::ForCurrentProcess()->AppendSwitch(
226 switches::kUseFakeDeviceForMediaStream
);
227 // Create our own MediaStreamManager.
228 media_stream_manager_
.reset(new MediaStreamManager(audio_manager_
.get()));
229 video_capture_device_factory_
=
230 static_cast<media::FakeVideoCaptureDeviceFactory
*>(
231 media_stream_manager_
->video_capture_manager()
232 ->video_capture_device_factory());
233 DCHECK(video_capture_device_factory_
);
235 MockResourceContext
* mock_resource_context
=
236 static_cast<MockResourceContext
*>(
237 browser_context_
.GetResourceContext());
238 mock_resource_context
->set_mic_access(true);
239 mock_resource_context
->set_camera_access(true);
241 host_
= new MockMediaStreamDispatcherHost(
242 mock_resource_context
->GetMediaDeviceIDSalt(),
243 base::MessageLoopProxy::current(),
244 media_stream_manager_
.get(),
245 mock_resource_context
);
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());
253 virtual ~MediaStreamDispatcherHostTest() {
256 virtual void SetUp() OVERRIDE
{
257 video_capture_device_factory_
->GetDeviceNames(&physical_video_devices_
);
258 ASSERT_GT(physical_video_devices_
.size(), 0u);
260 media_stream_manager_
->audio_input_device_manager()->GetFakeDeviceNames(
261 &physical_audio_devices_
);
262 ASSERT_GT(physical_audio_devices_
.size(), 0u);
265 virtual void TearDown() OVERRIDE
{
266 host_
->OnChannelClosing();
270 virtual void SetupFakeUI(bool expect_started
) {
271 scoped_ptr
<MockMediaStreamUIProxy
> stream_ui(new MockMediaStreamUIProxy());
272 if (expect_started
) {
273 EXPECT_CALL(*stream_ui
, OnStarted(_
, _
));
275 media_stream_manager_
->UseFakeUI(
276 stream_ui
.PassAs
<FakeMediaStreamUIProxy
>());
279 void GenerateStreamAndWaitForResult(int render_view_id
,
281 const StreamOptions
& options
) {
282 base::RunLoop run_loop
;
283 int expected_audio_array_size
=
284 (options
.audio_requested
&&
285 physical_audio_devices_
.size() > 0) ? 1 : 0;
286 int expected_video_array_size
=
287 (options
.video_requested
&&
288 physical_video_devices_
.size() > 0) ? 1 : 0;
289 EXPECT_CALL(*host_
.get(), OnStreamGenerated(render_view_id
, page_request_id
,
290 expected_audio_array_size
,
291 expected_video_array_size
));
292 host_
->OnGenerateStream(render_view_id
, page_request_id
, options
, origin_
,
293 run_loop
.QuitClosure());
295 EXPECT_FALSE(DoesContainRawIds(host_
->audio_devices_
));
296 EXPECT_FALSE(DoesContainRawIds(host_
->video_devices_
));
297 EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_
->audio_devices_
, origin_
));
298 EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_
->video_devices_
, origin_
));
301 void GenerateStreamAndWaitForFailure(
304 const StreamOptions
& options
,
305 MediaStreamRequestResult expected_result
) {
306 base::RunLoop run_loop
;
307 EXPECT_CALL(*host_
.get(),
308 OnStreamGenerationFailed(render_view_id
,
311 host_
->OnGenerateStream(render_view_id
, page_request_id
, options
, origin_
,
312 run_loop
.QuitClosure());
316 void OpenVideoDeviceAndWaitForResult(int render_view_id
,
318 const std::string
& device_id
) {
319 base::RunLoop run_loop
;
320 host_
->OnOpenDevice(render_view_id
, page_request_id
, device_id
,
321 MEDIA_DEVICE_VIDEO_CAPTURE
, origin_
,
322 run_loop
.QuitClosure());
324 EXPECT_FALSE(DoesContainRawIds(host_
->video_devices_
));
325 EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_
->video_devices_
, origin_
));
328 void EnumerateDevicesAndWaitForResult(int render_view_id
,
330 MediaStreamType type
) {
331 base::RunLoop run_loop
;
332 host_
->OnEnumerateDevices(render_view_id
, page_request_id
, type
, origin_
,
333 run_loop
.QuitClosure());
335 ASSERT_FALSE(host_
->enumerated_devices_
.empty());
336 EXPECT_FALSE(DoesContainRawIds(host_
->enumerated_devices_
));
337 EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_
->enumerated_devices_
, origin_
));
340 bool DoesContainRawIds(const StreamDeviceInfoArray
& devices
) {
341 for (size_t i
= 0; i
< devices
.size(); ++i
) {
342 media::AudioDeviceNames::const_iterator audio_it
=
343 physical_audio_devices_
.begin();
344 for (; audio_it
!= physical_audio_devices_
.end(); ++audio_it
) {
345 if (audio_it
->unique_id
== devices
[i
].device
.id
)
348 media::VideoCaptureDevice::Names::const_iterator video_it
=
349 physical_video_devices_
.begin();
350 for (; video_it
!= physical_video_devices_
.end(); ++video_it
) {
351 if (video_it
->id() == devices
[i
].device
.id
)
358 bool DoesEveryDeviceMapToRawId(const StreamDeviceInfoArray
& devices
,
359 const GURL
& origin
) {
360 for (size_t i
= 0; i
< devices
.size(); ++i
) {
361 bool found_match
= false;
362 media::AudioDeviceNames::const_iterator audio_it
=
363 physical_audio_devices_
.begin();
364 for (; audio_it
!= physical_audio_devices_
.end(); ++audio_it
) {
365 if (content::DoesMediaDeviceIDMatchHMAC(
366 browser_context_
.GetResourceContext()->GetMediaDeviceIDSalt(),
368 devices
[i
].device
.id
,
369 audio_it
->unique_id
)) {
370 EXPECT_FALSE(found_match
);
374 media::VideoCaptureDevice::Names::const_iterator video_it
=
375 physical_video_devices_
.begin();
376 for (; video_it
!= physical_video_devices_
.end(); ++video_it
) {
377 if (content::DoesMediaDeviceIDMatchHMAC(
378 browser_context_
.GetResourceContext()->GetMediaDeviceIDSalt(),
380 devices
[i
].device
.id
,
382 EXPECT_FALSE(found_match
);
392 // Returns true if all devices have labels, false otherwise.
393 bool DoesContainLabels(const StreamDeviceInfoArray
& devices
) {
394 for (size_t i
= 0; i
< devices
.size(); ++i
) {
395 if (devices
[i
].device
.name
.empty())
401 // Returns true if no devices have labels, false otherwise.
402 bool DoesNotContainLabels(const StreamDeviceInfoArray
& devices
) {
403 for (size_t i
= 0; i
< devices
.size(); ++i
) {
404 if (!devices
[i
].device
.name
.empty())
410 void AddSourceIdConstraint(const std::string
& source_id
,
411 StreamOptions::Constraints
* constraints
) {
412 constraints
->push_back(StreamOptions::Constraint(kMediaStreamSourceInfoId
,
416 scoped_refptr
<MockMediaStreamDispatcherHost
> host_
;
417 scoped_ptr
<media::AudioManager
> audio_manager_
;
418 scoped_ptr
<MediaStreamManager
> media_stream_manager_
;
419 ContentBrowserClient
* old_browser_client_
;
420 scoped_ptr
<ContentClient
> content_client_
;
421 content::TestBrowserThreadBundle thread_bundle_
;
422 content::TestBrowserContext browser_context_
;
423 media::AudioDeviceNames physical_audio_devices_
;
424 media::VideoCaptureDevice::Names physical_video_devices_
;
426 media::FakeVideoCaptureDeviceFactory
* video_capture_device_factory_
;
429 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamWithVideoOnly
) {
430 StreamOptions
options(false, true);
433 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
435 EXPECT_EQ(host_
->audio_devices_
.size(), 0u);
436 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
439 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamWithAudioOnly
) {
440 StreamOptions
options(true, false);
443 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
445 EXPECT_EQ(host_
->audio_devices_
.size(), 1u);
446 EXPECT_EQ(host_
->video_devices_
.size(), 0u);
449 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamWithNothing
) {
450 StreamOptions
options(false, false);
452 GenerateStreamAndWaitForFailure(
456 MEDIA_DEVICE_INVALID_STATE
);
459 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamWithAudioAndVideo
) {
460 StreamOptions
options(true, true);
463 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
465 EXPECT_EQ(host_
->audio_devices_
.size(), 1u);
466 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
469 // This test generates two streams with video only using the same render view
470 // id. The same capture device with the same device and session id is expected
472 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamsFromSameRenderId
) {
473 StreamOptions
options(false, true);
475 // Generate first stream.
477 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
479 // Check the latest generated stream.
480 EXPECT_EQ(host_
->audio_devices_
.size(), 0u);
481 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
482 const std::string label1
= host_
->label_
;
483 const std::string device_id1
= host_
->video_devices_
.front().device
.id
;
484 const int session_id1
= host_
->video_devices_
.front().session_id
;
486 // Generate second stream.
488 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
+ 1, options
);
490 // Check the latest generated stream.
491 EXPECT_EQ(host_
->audio_devices_
.size(), 0u);
492 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
493 const std::string label2
= host_
->label_
;
494 const std::string device_id2
= host_
->video_devices_
.front().device
.id
;
495 int session_id2
= host_
->video_devices_
.front().session_id
;
496 EXPECT_EQ(device_id1
, device_id2
);
497 EXPECT_EQ(session_id1
, session_id2
);
498 EXPECT_NE(label1
, label2
);
501 TEST_F(MediaStreamDispatcherHostTest
,
502 GenerateStreamAndOpenDeviceFromSameRenderId
) {
503 StreamOptions
options(false, true);
505 // Generate first stream.
507 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
509 EXPECT_EQ(host_
->audio_devices_
.size(), 0u);
510 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
511 const std::string label1
= host_
->label_
;
512 const std::string device_id1
= host_
->video_devices_
.front().device
.id
;
513 const int session_id1
= host_
->video_devices_
.front().session_id
;
515 // Generate second stream.
516 OpenVideoDeviceAndWaitForResult(kRenderId
, kPageRequestId
, device_id1
);
518 const std::string device_id2
= host_
->opened_device_
.device
.id
;
519 const int session_id2
= host_
->opened_device_
.session_id
;
520 const std::string label2
= host_
->label_
;
522 EXPECT_EQ(device_id1
, device_id2
);
523 EXPECT_NE(session_id1
, session_id2
);
524 EXPECT_NE(label1
, label2
);
528 // This test generates two streams with video only using two separate render
529 // view ids. The same device id but different session ids are expected.
530 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamsDifferentRenderId
) {
531 StreamOptions
options(false, true);
533 // Generate first stream.
535 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
537 // Check the latest generated stream.
538 EXPECT_EQ(host_
->audio_devices_
.size(), 0u);
539 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
540 const std::string label1
= host_
->label_
;
541 const std::string device_id1
= host_
->video_devices_
.front().device
.id
;
542 const int session_id1
= host_
->video_devices_
.front().session_id
;
544 // Generate second stream from another render view.
546 GenerateStreamAndWaitForResult(kRenderId
+1, kPageRequestId
+ 1, options
);
548 // Check the latest generated stream.
549 EXPECT_EQ(host_
->audio_devices_
.size(), 0u);
550 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
551 const std::string label2
= host_
->label_
;
552 const std::string device_id2
= host_
->video_devices_
.front().device
.id
;
553 const int session_id2
= host_
->video_devices_
.front().session_id
;
554 EXPECT_EQ(device_id1
, device_id2
);
555 EXPECT_NE(session_id1
, session_id2
);
556 EXPECT_NE(label1
, label2
);
559 // This test request two streams with video only without waiting for the first
560 // stream to be generated before requesting the second.
561 // The same device id and session ids are expected.
562 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamsWithoutWaiting
) {
563 StreamOptions
options(false, true);
565 // Generate first stream.
567 EXPECT_CALL(*host_
.get(), OnStreamGenerated(kRenderId
, kPageRequestId
, 0, 1));
569 // Generate second stream.
570 EXPECT_CALL(*host_
.get(),
571 OnStreamGenerated(kRenderId
, kPageRequestId
+ 1, 0, 1));
573 base::RunLoop run_loop1
;
574 base::RunLoop run_loop2
;
575 host_
->OnGenerateStream(kRenderId
, kPageRequestId
, options
, origin_
,
576 run_loop1
.QuitClosure());
577 host_
->OnGenerateStream(kRenderId
, kPageRequestId
+ 1, options
, origin_
,
578 run_loop2
.QuitClosure());
584 // Test that we can generate streams where a mandatory sourceId is specified in
586 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamsWithMandatorySourceId
) {
587 ASSERT_GE(physical_audio_devices_
.size(), 1u);
588 ASSERT_GE(physical_video_devices_
.size(), 1u);
590 media::AudioDeviceNames::const_iterator audio_it
=
591 physical_audio_devices_
.begin();
592 for (; audio_it
!= physical_audio_devices_
.end(); ++audio_it
) {
593 std::string source_id
= content::GetHMACForMediaDeviceID(
594 browser_context_
.GetResourceContext()->GetMediaDeviceIDSalt(),
596 audio_it
->unique_id
);
597 ASSERT_FALSE(source_id
.empty());
598 StreamOptions
options(true, true);
599 AddSourceIdConstraint(source_id
, &options
.mandatory_audio
);
602 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
603 EXPECT_EQ(host_
->audio_devices_
[0].device
.id
, source_id
);
606 media::VideoCaptureDevice::Names::const_iterator video_it
=
607 physical_video_devices_
.begin();
608 for (; video_it
!= physical_video_devices_
.end(); ++video_it
) {
609 std::string source_id
= content::GetHMACForMediaDeviceID(
610 browser_context_
.GetResourceContext()->GetMediaDeviceIDSalt(),
613 ASSERT_FALSE(source_id
.empty());
614 StreamOptions
options(true, true);
615 AddSourceIdConstraint(source_id
, &options
.mandatory_video
);
618 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
619 EXPECT_EQ(host_
->video_devices_
[0].device
.id
, source_id
);
623 // Test that we can generate streams where a optional sourceId is specified in
625 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamsWithOptionalSourceId
) {
626 ASSERT_GE(physical_audio_devices_
.size(), 1u);
627 ASSERT_GE(physical_video_devices_
.size(), 1u);
629 media::AudioDeviceNames::const_iterator audio_it
=
630 physical_audio_devices_
.begin();
631 for (; audio_it
!= physical_audio_devices_
.end(); ++audio_it
) {
632 std::string source_id
= content::GetHMACForMediaDeviceID(
633 browser_context_
.GetResourceContext()->GetMediaDeviceIDSalt(),
635 audio_it
->unique_id
);
636 ASSERT_FALSE(source_id
.empty());
637 StreamOptions
options(true, true);
638 AddSourceIdConstraint(source_id
, &options
.optional_audio
);
641 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
642 EXPECT_EQ(host_
->audio_devices_
[0].device
.id
, source_id
);
645 media::VideoCaptureDevice::Names::const_iterator video_it
=
646 physical_video_devices_
.begin();
647 for (; video_it
!= physical_video_devices_
.end(); ++video_it
) {
648 std::string source_id
= content::GetHMACForMediaDeviceID(
649 browser_context_
.GetResourceContext()->GetMediaDeviceIDSalt(),
652 ASSERT_FALSE(source_id
.empty());
653 StreamOptions
options(true, true);
654 AddSourceIdConstraint(source_id
, &options
.optional_video
);
657 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
658 EXPECT_EQ(host_
->video_devices_
[0].device
.id
, source_id
);
662 // Test that generating a stream with an invalid mandatory video source id fail.
663 TEST_F(MediaStreamDispatcherHostTest
,
664 GenerateStreamsWithInvalidMandatoryVideoSourceId
) {
665 StreamOptions
options(true, true);
666 AddSourceIdConstraint("invalid source id", &options
.mandatory_video
);
668 GenerateStreamAndWaitForFailure(
672 MEDIA_DEVICE_NO_HARDWARE
);
675 // Test that generating a stream with an invalid mandatory audio source id fail.
676 TEST_F(MediaStreamDispatcherHostTest
,
677 GenerateStreamsWithInvalidMandatoryAudioSourceId
) {
678 StreamOptions
options(true, true);
679 AddSourceIdConstraint("invalid source id", &options
.mandatory_audio
);
681 GenerateStreamAndWaitForFailure(
685 MEDIA_DEVICE_NO_HARDWARE
);
688 // Test that generating a stream with an invalid optional video source id
690 TEST_F(MediaStreamDispatcherHostTest
,
691 GenerateStreamsWithInvalidOptionalVideoSourceId
) {
692 StreamOptions
options(true, true);
693 AddSourceIdConstraint("invalid source id", &options
.optional_video
);
696 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
699 // Test that generating a stream with an invalid optional audio source id
701 TEST_F(MediaStreamDispatcherHostTest
,
702 GenerateStreamsWithInvalidOptionalAudioSourceId
) {
703 StreamOptions
options(true, true);
704 AddSourceIdConstraint("invalid source id", &options
.optional_audio
);
707 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
710 TEST_F(MediaStreamDispatcherHostTest
, GenerateStreamsNoAvailableVideoDevice
) {
711 physical_video_devices_
.clear();
712 video_capture_device_factory_
->set_number_of_devices(0);
713 video_capture_device_factory_
->GetDeviceNames(&physical_video_devices_
);
714 StreamOptions
options(true, true);
717 GenerateStreamAndWaitForFailure(kRenderId
, kPageRequestId
, options
,
718 MEDIA_DEVICE_NO_HARDWARE
);
721 // Test that if a OnStopStreamDevice message is received for a device that has
722 // been opened in a MediaStream and by pepper, the device is only stopped for
724 TEST_F(MediaStreamDispatcherHostTest
, StopDeviceInStream
) {
725 StreamOptions
options(false, true);
728 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
730 std::string stream_request_label
= host_
->label_
;
731 StreamDeviceInfo video_device_info
= host_
->video_devices_
.front();
732 ASSERT_EQ(1u, media_stream_manager_
->GetDevicesOpenedByRequest(
733 stream_request_label
).size());
735 // Open the same device by Pepper.
736 OpenVideoDeviceAndWaitForResult(kRenderId
, kPageRequestId
,
737 video_device_info
.device
.id
);
738 std::string open_device_request_label
= host_
->label_
;
740 // Stop the device in the MediaStream.
741 host_
->OnStopStreamDevice(kRenderId
, video_device_info
.device
.id
);
743 EXPECT_EQ(0u, media_stream_manager_
->GetDevicesOpenedByRequest(
744 stream_request_label
).size());
745 EXPECT_EQ(1u, media_stream_manager_
->GetDevicesOpenedByRequest(
746 open_device_request_label
).size());
749 TEST_F(MediaStreamDispatcherHostTest
, StopDeviceInStreamAndRestart
) {
750 StreamOptions
options(true, true);
753 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
755 std::string request_label1
= host_
->label_
;
756 StreamDeviceInfo video_device_info
= host_
->video_devices_
.front();
757 // Expect that 1 audio and 1 video device has been opened.
758 EXPECT_EQ(2u, media_stream_manager_
->GetDevicesOpenedByRequest(
759 request_label1
).size());
761 host_
->OnStopStreamDevice(kRenderId
, video_device_info
.device
.id
);
762 EXPECT_EQ(1u, media_stream_manager_
->GetDevicesOpenedByRequest(
763 request_label1
).size());
765 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
766 std::string request_label2
= host_
->label_
;
768 StreamDeviceInfoArray request1_devices
=
769 media_stream_manager_
->GetDevicesOpenedByRequest(request_label1
);
770 StreamDeviceInfoArray request2_devices
=
771 media_stream_manager_
->GetDevicesOpenedByRequest(request_label2
);
773 ASSERT_EQ(1u, request1_devices
.size());
774 ASSERT_EQ(2u, request2_devices
.size());
776 // Test that the same audio device has been opened in both streams.
777 EXPECT_TRUE(StreamDeviceInfo::IsEqual(request1_devices
[0],
778 request2_devices
[0]) ||
779 StreamDeviceInfo::IsEqual(request1_devices
[0],
780 request2_devices
[1]));
783 TEST_F(MediaStreamDispatcherHostTest
,
784 GenerateTwoStreamsAndStopDeviceWhileWaitingForSecondStream
) {
785 StreamOptions
options(false, true);
788 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
789 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
791 // Generate a second stream.
792 EXPECT_CALL(*host_
.get(),
793 OnStreamGenerated(kRenderId
, kPageRequestId
+ 1, 0, 1));
795 base::RunLoop run_loop1
;
796 host_
->OnGenerateStream(kRenderId
, kPageRequestId
+ 1, options
, origin_
,
797 run_loop1
.QuitClosure());
799 // Stop the video stream device from stream 1 while waiting for the
800 // second stream to be generated.
801 host_
->OnStopStreamDevice(kRenderId
, host_
->video_devices_
[0].device
.id
);
804 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
807 TEST_F(MediaStreamDispatcherHostTest
, CancelPendingStreamsOnChannelClosing
) {
808 StreamOptions
options(false, true);
810 base::RunLoop run_loop
;
812 // Create multiple GenerateStream requests.
814 for (size_t i
= 1; i
<= streams
; ++i
) {
815 host_
->OnGenerateStream(kRenderId
, kPageRequestId
+ i
, options
, origin_
,
816 run_loop
.QuitClosure());
819 // Calling OnChannelClosing() to cancel all the pending requests.
820 host_
->OnChannelClosing();
821 run_loop
.RunUntilIdle();
824 TEST_F(MediaStreamDispatcherHostTest
, StopGeneratedStreamsOnChannelClosing
) {
825 StreamOptions
options(false, true);
827 // Create first group of streams.
828 size_t generated_streams
= 3;
829 for (size_t i
= 0; i
< generated_streams
; ++i
) {
831 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
+ i
, options
);
834 // Calling OnChannelClosing() to cancel all the pending/generated streams.
835 host_
->OnChannelClosing();
836 base::RunLoop().RunUntilIdle();
839 TEST_F(MediaStreamDispatcherHostTest
, CloseFromUI
) {
840 StreamOptions
options(false, true);
842 base::Closure close_callback
;
843 scoped_ptr
<MockMediaStreamUIProxy
> stream_ui(new MockMediaStreamUIProxy());
844 EXPECT_CALL(*stream_ui
, OnStarted(_
, _
))
845 .WillOnce(SaveArg
<0>(&close_callback
));
846 media_stream_manager_
->UseFakeUI(stream_ui
.PassAs
<FakeMediaStreamUIProxy
>());
848 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
850 EXPECT_EQ(host_
->audio_devices_
.size(), 0u);
851 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
853 ASSERT_FALSE(close_callback
.is_null());
854 EXPECT_CALL(*host_
.get(), OnDeviceStopped(kRenderId
));
855 close_callback
.Run();
856 base::RunLoop().RunUntilIdle();
859 // Test that the dispatcher is notified if a video device that is in use is
861 TEST_F(MediaStreamDispatcherHostTest
, VideoDeviceUnplugged
) {
862 StreamOptions
options(true, true);
864 GenerateStreamAndWaitForResult(kRenderId
, kPageRequestId
, options
);
865 EXPECT_EQ(host_
->audio_devices_
.size(), 1u);
866 EXPECT_EQ(host_
->video_devices_
.size(), 1u);
868 video_capture_device_factory_
->set_number_of_devices(0);
870 base::RunLoop run_loop
;
871 EXPECT_CALL(*host_
.get(), OnDeviceStopped(kRenderId
))
872 .WillOnce(testing::InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
));
873 media_stream_manager_
->OnDevicesChanged(
874 base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE
);
879 TEST_F(MediaStreamDispatcherHostTest
, EnumerateAudioDevices
) {
880 EnumerateDevicesAndWaitForResult(kRenderId
, kPageRequestId
,
881 MEDIA_DEVICE_AUDIO_CAPTURE
);
882 EXPECT_TRUE(DoesContainLabels(host_
->enumerated_devices_
));
885 TEST_F(MediaStreamDispatcherHostTest
, EnumerateVideoDevices
) {
886 EnumerateDevicesAndWaitForResult(kRenderId
, kPageRequestId
,
887 MEDIA_DEVICE_VIDEO_CAPTURE
);
888 EXPECT_TRUE(DoesContainLabels(host_
->enumerated_devices_
));
891 TEST_F(MediaStreamDispatcherHostTest
, EnumerateAudioDevicesNoAccess
) {
892 MockResourceContext
* mock_resource_context
=
893 static_cast<MockResourceContext
*>(browser_context_
.GetResourceContext());
894 mock_resource_context
->set_mic_access(false);
895 EnumerateDevicesAndWaitForResult(kRenderId
, kPageRequestId
,
896 MEDIA_DEVICE_AUDIO_CAPTURE
);
897 EXPECT_TRUE(DoesNotContainLabels(host_
->enumerated_devices_
));
900 TEST_F(MediaStreamDispatcherHostTest
, EnumerateVideoDevicesNoAccess
) {
901 MockResourceContext
* mock_resource_context
=
902 static_cast<MockResourceContext
*>(browser_context_
.GetResourceContext());
903 mock_resource_context
->set_camera_access(false);
904 EnumerateDevicesAndWaitForResult(kRenderId
, kPageRequestId
,
905 MEDIA_DEVICE_VIDEO_CAPTURE
);
906 EXPECT_TRUE(DoesNotContainLabels(host_
->enumerated_devices_
));
909 }; // namespace content