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.
7 #include "base/memory/ref_counted.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "content/common/media/media_stream_messages.h"
12 #include "content/public/common/media_stream_request.h"
13 #include "content/renderer/media/media_stream_dispatcher.h"
14 #include "content/renderer/media/media_stream_dispatcher_eventhandler.h"
15 #include "media/audio/audio_parameters.h"
16 #include "testing/gtest/include/gtest/gtest.h"
22 const int kRouteId
= 0;
23 const int kAudioSessionId
= 3;
24 const int kVideoSessionId
= 5;
25 const int kRequestId1
= 10;
26 const int kRequestId2
= 20;
27 const int kRequestId3
= 30;
28 const int kRequestId4
= 40;
30 const MediaStreamType kAudioType
= MEDIA_DEVICE_AUDIO_CAPTURE
;
31 const MediaStreamType kVideoType
= MEDIA_DEVICE_VIDEO_CAPTURE
;
33 class MockMediaStreamDispatcherEventHandler
34 : public MediaStreamDispatcherEventHandler
,
35 public base::SupportsWeakPtr
<MockMediaStreamDispatcherEventHandler
> {
37 MockMediaStreamDispatcherEventHandler()
40 virtual void OnStreamGenerated(
42 const std::string
&label
,
43 const StreamDeviceInfoArray
& audio_device_array
,
44 const StreamDeviceInfoArray
& video_device_array
) OVERRIDE
{
45 request_id_
= request_id
;
47 if (audio_device_array
.size()) {
48 DCHECK(audio_device_array
.size() == 1);
49 audio_device_
= audio_device_array
[0];
51 if (video_device_array
.size()) {
52 DCHECK(video_device_array
.size() == 1);
53 video_device_
= video_device_array
[0];
57 virtual void OnStreamGenerationFailed(
59 content::MediaStreamRequestResult result
) OVERRIDE
{
60 request_id_
= request_id
;
63 virtual void OnDeviceStopped(const std::string
& label
,
64 const StreamDeviceInfo
& device_info
) OVERRIDE
{
65 device_stopped_label_
= label
;
66 if (IsVideoMediaType(device_info
.device
.type
)) {
67 EXPECT_TRUE(StreamDeviceInfo::IsEqual(video_device_
, device_info
));
69 if (IsAudioInputMediaType(device_info
.device
.type
)) {
70 EXPECT_TRUE(StreamDeviceInfo::IsEqual(audio_device_
, device_info
));
74 virtual void OnDevicesEnumerated(
76 const StreamDeviceInfoArray
& device_array
) OVERRIDE
{
77 request_id_
= request_id
;
80 virtual void OnDeviceOpened(
82 const std::string
& label
,
83 const StreamDeviceInfo
& video_device
) OVERRIDE
{
84 request_id_
= request_id
;
88 virtual void OnDeviceOpenFailed(int request_id
) OVERRIDE
{
89 request_id_
= request_id
;
92 void ResetStoredParameters() {
95 device_stopped_label_
= "";
96 audio_device_
= StreamDeviceInfo();
97 video_device_
= StreamDeviceInfo();
102 std::string device_stopped_label_
;
103 StreamDeviceInfo audio_device_
;
104 StreamDeviceInfo video_device_
;
107 class MediaStreamDispatcherUnderTest
: public MediaStreamDispatcher
{
109 MediaStreamDispatcherUnderTest() : MediaStreamDispatcher(NULL
) {}
111 using MediaStreamDispatcher::GetNextIpcIdForTest
;
112 using RenderFrameObserver::OnMessageReceived
;
115 class MediaStreamDispatcherTest
: public ::testing::Test
{
117 MediaStreamDispatcherTest()
118 : dispatcher_(new MediaStreamDispatcherUnderTest()),
119 handler_(new MockMediaStreamDispatcherEventHandler
),
120 security_origin_("http://test.com"),
124 // Generates a request for a MediaStream and returns the request id that is
125 // used in IPC. Use this returned id in CompleteGenerateStream to identify
127 int GenerateStream(const StreamOptions
& options
, int request_id
) {
128 int next_ipc_id
= dispatcher_
->GetNextIpcIdForTest();
129 dispatcher_
->GenerateStream(request_id
, handler_
.get()->AsWeakPtr(),
130 options
, security_origin_
);
134 // CompleteGenerateStream create a MediaStreamMsg_StreamGenerated instance
135 // and call the MediaStreamDispathcer::OnMessageReceived. |ipc_id| must be the
136 // the id returned by GenerateStream.
137 std::string
CompleteGenerateStream(int ipc_id
, const StreamOptions
& options
,
139 StreamDeviceInfoArray
audio_device_array(options
.audio_requested
? 1 : 0);
140 if (options
.audio_requested
) {
141 StreamDeviceInfo audio_device_info
;
142 audio_device_info
.device
.name
= "Microphone";
143 audio_device_info
.device
.type
= kAudioType
;
144 audio_device_info
.session_id
= kAudioSessionId
;
145 audio_device_array
[0] = audio_device_info
;
148 StreamDeviceInfoArray
video_device_array(options
.video_requested
? 1 : 0);
149 if (options
.video_requested
) {
150 StreamDeviceInfo video_device_info
;
151 video_device_info
.device
.name
= "Camera";
152 video_device_info
.device
.type
= kVideoType
;
153 video_device_info
.session_id
= kVideoSessionId
;
154 video_device_array
[0] = video_device_info
;
157 std::string label
= "stream" + base::IntToString(ipc_id
);
159 handler_
->ResetStoredParameters();
160 dispatcher_
->OnMessageReceived(MediaStreamMsg_StreamGenerated(
161 kRouteId
, ipc_id
, label
,
162 audio_device_array
, video_device_array
));
164 EXPECT_EQ(handler_
->request_id_
, request_id
);
165 EXPECT_EQ(handler_
->label_
, label
);
167 if (options
.audio_requested
)
168 EXPECT_EQ(dispatcher_
->audio_session_id(label
, 0), kAudioSessionId
);
170 if (options
.video_requested
)
171 EXPECT_EQ(dispatcher_
->video_session_id(label
, 0), kVideoSessionId
);
177 base::MessageLoop message_loop_
;
178 scoped_ptr
<MediaStreamDispatcherUnderTest
> dispatcher_
;
179 scoped_ptr
<MockMediaStreamDispatcherEventHandler
> handler_
;
180 GURL security_origin_
;
186 TEST_F(MediaStreamDispatcherTest
, GenerateStreamAndStopDevices
) {
187 StreamOptions
options(true, true);
189 int ipc_request_id1
= GenerateStream(options
, kRequestId1
);
190 int ipc_request_id2
= GenerateStream(options
, kRequestId2
);
191 EXPECT_NE(ipc_request_id1
, ipc_request_id2
);
193 // Complete the creation of stream1.
194 const std::string
& label1
= CompleteGenerateStream(ipc_request_id1
, options
,
197 // Complete the creation of stream2.
198 const std::string
& label2
= CompleteGenerateStream(ipc_request_id2
, options
,
201 // Stop the actual audio device and verify that there is no valid
203 dispatcher_
->StopStreamDevice(handler_
->audio_device_
);
204 EXPECT_EQ(dispatcher_
->audio_session_id(label1
, 0),
205 StreamDeviceInfo::kNoId
);
206 EXPECT_EQ(dispatcher_
->audio_session_id(label2
, 0),
207 StreamDeviceInfo::kNoId
);
209 // Stop the actual video device and verify that there is no valid
211 dispatcher_
->StopStreamDevice(handler_
->video_device_
);
212 EXPECT_EQ(dispatcher_
->video_session_id(label1
, 0),
213 StreamDeviceInfo::kNoId
);
214 EXPECT_EQ(dispatcher_
->video_session_id(label2
, 0),
215 StreamDeviceInfo::kNoId
);
218 TEST_F(MediaStreamDispatcherTest
, BasicVideoDevice
) {
219 scoped_ptr
<MediaStreamDispatcher
> dispatcher(new MediaStreamDispatcher(NULL
));
220 scoped_ptr
<MockMediaStreamDispatcherEventHandler
>
221 handler1(new MockMediaStreamDispatcherEventHandler
);
222 scoped_ptr
<MockMediaStreamDispatcherEventHandler
>
223 handler2(new MockMediaStreamDispatcherEventHandler
);
224 GURL security_origin
;
226 int ipc_request_id1
= dispatcher
->next_ipc_id_
;
227 dispatcher
->EnumerateDevices(
228 kRequestId1
, handler1
.get()->AsWeakPtr(),
231 int ipc_request_id2
= dispatcher
->next_ipc_id_
;
232 EXPECT_NE(ipc_request_id1
, ipc_request_id2
);
233 dispatcher
->EnumerateDevices(
234 kRequestId2
, handler2
.get()->AsWeakPtr(),
237 EXPECT_EQ(dispatcher
->requests_
.size(), size_t(2));
239 StreamDeviceInfoArray
video_device_array(1);
240 StreamDeviceInfo video_device_info
;
241 video_device_info
.device
.name
= "Camera";
242 video_device_info
.device
.id
= "device_path";
243 video_device_info
.device
.type
= kVideoType
;
244 video_device_info
.session_id
= kVideoSessionId
;
245 video_device_array
[0] = video_device_info
;
247 // Complete the first enumeration request.
248 dispatcher
->OnMessageReceived(MediaStreamMsg_DevicesEnumerated(
249 kRouteId
, ipc_request_id1
, video_device_array
));
250 EXPECT_EQ(handler1
->request_id_
, kRequestId1
);
252 dispatcher
->OnMessageReceived(MediaStreamMsg_DevicesEnumerated(
253 kRouteId
, ipc_request_id2
, video_device_array
));
254 EXPECT_EQ(handler2
->request_id_
, kRequestId2
);
256 EXPECT_EQ(dispatcher
->requests_
.size(), size_t(2));
257 EXPECT_EQ(dispatcher
->label_stream_map_
.size(), size_t(0));
259 int ipc_request_id3
= dispatcher
->next_ipc_id_
;
260 dispatcher
->OpenDevice(kRequestId3
, handler1
.get()->AsWeakPtr(),
261 video_device_info
.device
.id
,
264 int ipc_request_id4
= dispatcher
->next_ipc_id_
;
265 EXPECT_NE(ipc_request_id3
, ipc_request_id4
);
266 dispatcher
->OpenDevice(kRequestId4
, handler1
.get()->AsWeakPtr(),
267 video_device_info
.device
.id
,
270 EXPECT_EQ(dispatcher
->requests_
.size(), size_t(4));
272 // Complete the OpenDevice of request 1.
273 std::string stream_label1
= std::string("stream1");
274 dispatcher
->OnMessageReceived(MediaStreamMsg_DeviceOpened(
275 kRouteId
, ipc_request_id3
, stream_label1
, video_device_info
));
276 EXPECT_EQ(handler1
->request_id_
, kRequestId3
);
278 // Complete the OpenDevice of request 2.
279 std::string stream_label2
= std::string("stream2");
280 dispatcher
->OnMessageReceived(MediaStreamMsg_DeviceOpened(
281 kRouteId
, ipc_request_id4
, stream_label2
, video_device_info
));
282 EXPECT_EQ(handler1
->request_id_
, kRequestId4
);
284 EXPECT_EQ(dispatcher
->requests_
.size(), size_t(2));
285 EXPECT_EQ(dispatcher
->label_stream_map_
.size(), size_t(2));
287 // Check the video_session_id.
288 EXPECT_EQ(dispatcher
->video_session_id(stream_label1
, 0), kVideoSessionId
);
289 EXPECT_EQ(dispatcher
->video_session_id(stream_label2
, 0), kVideoSessionId
);
291 // Close the device from request 2.
292 dispatcher
->CloseDevice(stream_label2
);
293 EXPECT_EQ(dispatcher
->video_session_id(stream_label2
, 0),
294 StreamDeviceInfo::kNoId
);
296 // Close the device from request 1.
297 dispatcher
->CloseDevice(stream_label1
);
298 EXPECT_EQ(dispatcher
->video_session_id(stream_label1
, 0),
299 StreamDeviceInfo::kNoId
);
300 EXPECT_EQ(dispatcher
->label_stream_map_
.size(), size_t(0));
302 // Verify that the request have been completed.
303 EXPECT_EQ(dispatcher
->label_stream_map_
.size(), size_t(0));
304 EXPECT_EQ(dispatcher
->requests_
.size(), size_t(2));
307 TEST_F(MediaStreamDispatcherTest
, TestFailure
) {
308 scoped_ptr
<MediaStreamDispatcher
> dispatcher(new MediaStreamDispatcher(NULL
));
309 scoped_ptr
<MockMediaStreamDispatcherEventHandler
>
310 handler(new MockMediaStreamDispatcherEventHandler
);
311 StreamOptions
components(true, true);
312 GURL security_origin
;
314 // Test failure when creating a stream.
315 int ipc_request_id1
= dispatcher
->next_ipc_id_
;
316 dispatcher
->GenerateStream(kRequestId1
, handler
.get()->AsWeakPtr(),
317 components
, security_origin
);
318 dispatcher
->OnMessageReceived(MediaStreamMsg_StreamGenerationFailed(
319 kRouteId
, ipc_request_id1
, MEDIA_DEVICE_PERMISSION_DENIED
));
321 // Verify that the request have been completed.
322 EXPECT_EQ(handler
->request_id_
, kRequestId1
);
323 EXPECT_EQ(dispatcher
->requests_
.size(), size_t(0));
325 // Create a new stream.
326 ipc_request_id1
= dispatcher
->next_ipc_id_
;
327 dispatcher
->GenerateStream(kRequestId1
, handler
.get()->AsWeakPtr(),
328 components
, security_origin
);
330 StreamDeviceInfoArray
audio_device_array(1);
331 StreamDeviceInfo audio_device_info
;
332 audio_device_info
.device
.name
= "Microphone";
333 audio_device_info
.device
.type
= kAudioType
;
334 audio_device_info
.session_id
= kAudioSessionId
;
335 audio_device_array
[0] = audio_device_info
;
337 StreamDeviceInfoArray
video_device_array(1);
338 StreamDeviceInfo video_device_info
;
339 video_device_info
.device
.name
= "Camera";
340 video_device_info
.device
.type
= kVideoType
;
341 video_device_info
.session_id
= kVideoSessionId
;
342 video_device_array
[0] = video_device_info
;
344 // Complete the creation of stream1.
345 std::string stream_label1
= std::string("stream1");
346 dispatcher
->OnMessageReceived(MediaStreamMsg_StreamGenerated(
347 kRouteId
, ipc_request_id1
, stream_label1
,
348 audio_device_array
, video_device_array
));
349 EXPECT_EQ(handler
->request_id_
, kRequestId1
);
350 EXPECT_EQ(handler
->label_
, stream_label1
);
351 EXPECT_EQ(dispatcher
->video_session_id(stream_label1
, 0), kVideoSessionId
);
354 TEST_F(MediaStreamDispatcherTest
, CancelGenerateStream
) {
355 scoped_ptr
<MediaStreamDispatcher
> dispatcher(new MediaStreamDispatcher(NULL
));
356 scoped_ptr
<MockMediaStreamDispatcherEventHandler
>
357 handler(new MockMediaStreamDispatcherEventHandler
);
358 StreamOptions
components(true, true);
359 int ipc_request_id1
= dispatcher
->next_ipc_id_
;
361 dispatcher
->GenerateStream(kRequestId1
, handler
.get()->AsWeakPtr(),
363 dispatcher
->GenerateStream(kRequestId2
, handler
.get()->AsWeakPtr(),
366 EXPECT_EQ(2u, dispatcher
->requests_
.size());
367 dispatcher
->CancelGenerateStream(kRequestId2
, handler
.get()->AsWeakPtr());
368 EXPECT_EQ(1u, dispatcher
->requests_
.size());
370 // Complete the creation of stream1.
371 StreamDeviceInfo audio_device_info
;
372 audio_device_info
.device
.name
= "Microphone";
373 audio_device_info
.device
.type
= kAudioType
;
374 audio_device_info
.session_id
= kAudioSessionId
;
375 StreamDeviceInfoArray
audio_device_array(1);
376 audio_device_array
[0] = audio_device_info
;
378 StreamDeviceInfo video_device_info
;
379 video_device_info
.device
.name
= "Camera";
380 video_device_info
.device
.type
= kVideoType
;
381 video_device_info
.session_id
= kVideoSessionId
;
382 StreamDeviceInfoArray
video_device_array(1);
383 video_device_array
[0] = video_device_info
;
385 std::string stream_label1
= "stream1";
386 dispatcher
->OnMessageReceived(MediaStreamMsg_StreamGenerated(
387 kRouteId
, ipc_request_id1
, stream_label1
,
388 audio_device_array
, video_device_array
));
389 EXPECT_EQ(handler
->request_id_
, kRequestId1
);
390 EXPECT_EQ(handler
->label_
, stream_label1
);
391 EXPECT_EQ(0u, dispatcher
->requests_
.size());
394 // Test that the MediaStreamDispatcherEventHandler is notified when the message
395 // MediaStreamMsg_DeviceStopped is received.
396 TEST_F(MediaStreamDispatcherTest
, DeviceClosed
) {
397 StreamOptions
options(true, true);
399 int ipc_request_id
= GenerateStream(options
, kRequestId1
);
400 const std::string
& label
= CompleteGenerateStream(ipc_request_id
, options
,
403 dispatcher_
->OnMessageReceived(
404 MediaStreamMsg_DeviceStopped(kRouteId
, label
, handler_
->video_device_
));
405 // Verify that MediaStreamDispatcherEventHandler::OnDeviceStopped has been
407 EXPECT_EQ(label
, handler_
->device_stopped_label_
);
408 EXPECT_EQ(dispatcher_
->video_session_id(label
, 0),
409 StreamDeviceInfo::kNoId
);
412 TEST_F(MediaStreamDispatcherTest
, CheckDuckingState
) {
413 scoped_ptr
<MediaStreamDispatcher
> dispatcher(new MediaStreamDispatcher(NULL
));
414 scoped_ptr
<MockMediaStreamDispatcherEventHandler
>
415 handler(new MockMediaStreamDispatcherEventHandler
);
416 StreamOptions
components(true, false); // audio only.
417 int ipc_request_id1
= dispatcher
->next_ipc_id_
;
419 dispatcher
->GenerateStream(kRequestId1
, handler
.get()->AsWeakPtr(),
421 EXPECT_EQ(1u, dispatcher
->requests_
.size());
423 // Ducking isn't active at this point.
424 EXPECT_FALSE(dispatcher
->IsAudioDuckingActive());
426 // Complete the creation of stream1 with a single audio track that has
428 StreamDeviceInfoArray
audio_device_array(1);
429 StreamDeviceInfo
& audio_device_info
= audio_device_array
[0];
430 audio_device_info
.device
.name
= "Microphone";
431 audio_device_info
.device
.type
= kAudioType
;
432 audio_device_info
.session_id
= kAudioSessionId
;
433 audio_device_info
.device
.input
.effects
= media::AudioParameters::DUCKING
;
435 StreamDeviceInfoArray video_device_array
; // Empty for this test.
437 const char kStreamLabel
[] = "stream1";
438 dispatcher
->OnMessageReceived(MediaStreamMsg_StreamGenerated(
439 kRouteId
, ipc_request_id1
, kStreamLabel
,
440 audio_device_array
, video_device_array
));
441 EXPECT_EQ(handler
->request_id_
, kRequestId1
);
442 EXPECT_EQ(0u, dispatcher
->requests_
.size());
444 // Ducking should now be reported as active.
445 EXPECT_TRUE(dispatcher
->IsAudioDuckingActive());
447 // Stop the device (removes the stream).
448 dispatcher
->OnMessageReceived(
449 MediaStreamMsg_DeviceStopped(kRouteId
, kStreamLabel
,
450 handler
->audio_device_
));
452 // Ducking should now be reported as inactive again.
453 EXPECT_FALSE(dispatcher
->IsAudioDuckingActive());
455 // Now do the same sort of test with the DUCKING flag off.
456 audio_device_info
.device
.input
.effects
=
457 media::AudioParameters::ECHO_CANCELLER
;
459 dispatcher
->OnMessageReceived(MediaStreamMsg_StreamGenerated(
460 kRouteId
, ipc_request_id1
, kStreamLabel
,
461 audio_device_array
, video_device_array
));
462 EXPECT_EQ(handler
->request_id_
, kRequestId1
);
463 EXPECT_EQ(0u, dispatcher
->requests_
.size());
465 // Ducking should still be reported as not active.
466 EXPECT_FALSE(dispatcher
->IsAudioDuckingActive());
468 // Stop the device (removes the stream).
469 dispatcher
->OnMessageReceived(
470 MediaStreamMsg_DeviceStopped(kRouteId
, kStreamLabel
,
471 handler
->audio_device_
));
474 } // namespace content