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.
5 #include "base/memory/scoped_ptr.h"
6 #include "base/message_loop/message_loop.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "content/child/child_process.h"
9 #include "content/renderer/media/media_stream.h"
10 #include "content/renderer/media/media_stream_impl.h"
11 #include "content/renderer/media/media_stream_track.h"
12 #include "content/renderer/media/mock_media_stream_dispatcher.h"
13 #include "content/renderer/media/mock_media_stream_video_source.h"
14 #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/WebKit/public/platform/WebMediaDeviceInfo.h"
17 #include "third_party/WebKit/public/platform/WebMediaStream.h"
18 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
19 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
20 #include "third_party/WebKit/public/platform/WebString.h"
21 #include "third_party/WebKit/public/platform/WebVector.h"
25 class MockMediaStreamVideoCapturerSource
: public MockMediaStreamVideoSource
{
27 MockMediaStreamVideoCapturerSource(
28 const StreamDeviceInfo
& device
,
29 const SourceStoppedCallback
& stop_callback
,
30 PeerConnectionDependencyFactory
* factory
)
31 : MockMediaStreamVideoSource(false) {
32 SetDeviceInfo(device
);
33 SetStopCallback(stop_callback
);
37 class MediaStreamImplUnderTest
: public MediaStreamImpl
{
46 MediaStreamImplUnderTest(
47 PeerConnectionDependencyFactory
* dependency_factory
,
48 scoped_ptr
<MediaStreamDispatcher
> media_stream_dispatcher
)
50 NULL
, dependency_factory
, media_stream_dispatcher
.Pass()),
51 state_(REQUEST_NOT_STARTED
),
52 result_(NUM_MEDIA_REQUEST_RESULTS
),
54 factory_(dependency_factory
),
58 void RequestUserMedia() {
59 blink::WebUserMediaRequest user_media_request
;
60 state_
= REQUEST_NOT_COMPLETE
;
61 requestUserMedia(user_media_request
);
64 void RequestMediaDevices() {
65 blink::WebMediaDevicesRequest media_devices_request
;
66 state_
= REQUEST_NOT_COMPLETE
;
67 requestMediaDevices(media_devices_request
);
70 virtual void GetUserMediaRequestSucceeded(
71 const blink::WebMediaStream
& stream
,
72 blink::WebUserMediaRequest
* request_info
) OVERRIDE
{
73 last_generated_stream_
= stream
;
74 state_
= REQUEST_SUCCEEDED
;
77 virtual void GetUserMediaRequestFailed(
78 blink::WebUserMediaRequest
* request_info
,
79 content::MediaStreamRequestResult result
) OVERRIDE
{
80 last_generated_stream_
.reset();
81 state_
= REQUEST_FAILED
;
85 virtual void GetUserMediaRequestTrackStartedFailed(
86 blink::WebUserMediaRequest
* request_info
,
87 MediaStreamRequestResult result
,
88 const blink::WebString
& result_name
) OVERRIDE
{
89 last_generated_stream_
.reset();
90 state_
= REQUEST_FAILED
;
92 result_name_
= result_name
;
95 virtual void EnumerateDevicesSucceded(
96 blink::WebMediaDevicesRequest
* request
,
97 blink::WebVector
<blink::WebMediaDeviceInfo
>& devices
) OVERRIDE
{
98 state_
= REQUEST_SUCCEEDED
;
99 last_devices_
= devices
;
102 virtual MediaStreamVideoSource
* CreateVideoSource(
103 const StreamDeviceInfo
& device
,
104 const MediaStreamSource::SourceStoppedCallback
& stop_callback
) OVERRIDE
{
105 video_source_
= new MockMediaStreamVideoCapturerSource(device
,
108 return video_source_
;
111 const blink::WebMediaStream
& last_generated_stream() {
112 return last_generated_stream_
;
115 const blink::WebVector
<blink::WebMediaDeviceInfo
>& last_devices() {
116 return last_devices_
;
119 void ClearLastGeneratedStream() {
120 last_generated_stream_
.reset();
123 MockMediaStreamVideoCapturerSource
* last_created_video_source() const {
124 return video_source_
;
127 RequestState
request_state() const { return state_
; }
128 content::MediaStreamRequestResult
error_reason() const { return result_
; }
129 blink::WebString
error_name() const { return result_name_
; }
132 blink::WebMediaStream last_generated_stream_
;
134 content::MediaStreamRequestResult result_
;
135 blink::WebString result_name_
;
136 blink::WebVector
<blink::WebMediaDeviceInfo
> last_devices_
;
137 PeerConnectionDependencyFactory
* factory_
;
138 MockMediaStreamVideoCapturerSource
* video_source_
;
141 class MediaStreamImplTest
: public ::testing::Test
{
143 virtual void SetUp() {
144 // Create our test object.
145 child_process_
.reset(new ChildProcess());
146 dependency_factory_
.reset(new MockPeerConnectionDependencyFactory());
147 ms_dispatcher_
= new MockMediaStreamDispatcher();
148 ms_impl_
.reset(new MediaStreamImplUnderTest(
149 dependency_factory_
.get(),
150 scoped_ptr
<MediaStreamDispatcher
>(ms_dispatcher_
).Pass()));
153 blink::WebMediaStream
RequestLocalMediaStream() {
154 ms_impl_
->RequestUserMedia();
155 FakeMediaStreamDispatcherRequestUserMediaComplete();
156 StartMockedVideoSource();
158 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_SUCCEEDED
,
159 ms_impl_
->request_state());
161 blink::WebMediaStream desc
= ms_impl_
->last_generated_stream();
162 content::MediaStream
* native_stream
=
163 content::MediaStream::GetMediaStream(desc
);
164 if (!native_stream
) {
169 blink::WebVector
<blink::WebMediaStreamTrack
> audio_tracks
;
170 desc
.audioTracks(audio_tracks
);
171 blink::WebVector
<blink::WebMediaStreamTrack
> video_tracks
;
172 desc
.videoTracks(video_tracks
);
174 EXPECT_EQ(1u, audio_tracks
.size());
175 EXPECT_EQ(1u, video_tracks
.size());
176 EXPECT_NE(audio_tracks
[0].id(), video_tracks
[0].id());
180 void FakeMediaStreamDispatcherRequestUserMediaComplete() {
181 // Audio request ID is used as the shared request ID.
182 ms_impl_
->OnStreamGenerated(ms_dispatcher_
->audio_input_request_id(),
183 ms_dispatcher_
->stream_label(),
184 ms_dispatcher_
->audio_input_array(),
185 ms_dispatcher_
->video_array());
188 void FakeMediaStreamDispatcherRequestMediaDevicesComplete() {
189 ms_impl_
->OnDevicesEnumerated(ms_dispatcher_
->audio_input_request_id(),
190 ms_dispatcher_
->audio_input_array());
191 ms_impl_
->OnDevicesEnumerated(ms_dispatcher_
->audio_output_request_id(),
192 ms_dispatcher_
->audio_output_array());
193 ms_impl_
->OnDevicesEnumerated(ms_dispatcher_
->video_request_id(),
194 ms_dispatcher_
->video_array());
197 void StartMockedVideoSource() {
198 MockMediaStreamVideoCapturerSource
* video_source
=
199 ms_impl_
->last_created_video_source();
200 if (video_source
->SourceHasAttemptedToStart())
201 video_source
->StartMockedSource();
204 void FailToStartMockedVideoSource() {
205 MockMediaStreamVideoCapturerSource
* video_source
=
206 ms_impl_
->last_created_video_source();
207 if (video_source
->SourceHasAttemptedToStart())
208 video_source
->FailToStartMockedSource();
211 void FailToCreateNextAudioCapturer() {
212 dependency_factory_
->FailToCreateNextAudioCapturer();
216 base::MessageLoop message_loop_
;
217 scoped_ptr
<ChildProcess
> child_process_
;
218 MockMediaStreamDispatcher
* ms_dispatcher_
; // Owned my |ms_impl_|.
219 scoped_ptr
<MediaStreamImplUnderTest
> ms_impl_
;
220 scoped_ptr
<MockPeerConnectionDependencyFactory
> dependency_factory_
;
223 TEST_F(MediaStreamImplTest
, GenerateMediaStream
) {
224 // Generate a stream with both audio and video.
225 blink::WebMediaStream mixed_desc
= RequestLocalMediaStream();
228 // Test that the same source object is used if two MediaStreams are generated
229 // using the same source.
230 TEST_F(MediaStreamImplTest
, GenerateTwoMediaStreamsWithSameSource
) {
231 blink::WebMediaStream desc1
= RequestLocalMediaStream();
232 blink::WebMediaStream desc2
= RequestLocalMediaStream();
234 blink::WebVector
<blink::WebMediaStreamTrack
> desc1_video_tracks
;
235 desc1
.videoTracks(desc1_video_tracks
);
236 blink::WebVector
<blink::WebMediaStreamTrack
> desc2_video_tracks
;
237 desc2
.videoTracks(desc2_video_tracks
);
238 EXPECT_EQ(desc1_video_tracks
[0].source().id(),
239 desc2_video_tracks
[0].source().id());
241 EXPECT_EQ(desc1_video_tracks
[0].source().extraData(),
242 desc2_video_tracks
[0].source().extraData());
244 blink::WebVector
<blink::WebMediaStreamTrack
> desc1_audio_tracks
;
245 desc1
.audioTracks(desc1_audio_tracks
);
246 blink::WebVector
<blink::WebMediaStreamTrack
> desc2_audio_tracks
;
247 desc2
.audioTracks(desc2_audio_tracks
);
248 EXPECT_EQ(desc1_audio_tracks
[0].source().id(),
249 desc2_audio_tracks
[0].source().id());
251 EXPECT_EQ(desc1_audio_tracks
[0].source().extraData(),
252 desc2_audio_tracks
[0].source().extraData());
255 // Test that the same source object is not used if two MediaStreams are
256 // generated using different sources.
257 TEST_F(MediaStreamImplTest
, GenerateTwoMediaStreamsWithDifferentSources
) {
258 blink::WebMediaStream desc1
= RequestLocalMediaStream();
259 // Make sure another device is selected (another |session_id|) in the next
261 ms_dispatcher_
->IncrementSessionId();
262 blink::WebMediaStream desc2
= RequestLocalMediaStream();
264 blink::WebVector
<blink::WebMediaStreamTrack
> desc1_video_tracks
;
265 desc1
.videoTracks(desc1_video_tracks
);
266 blink::WebVector
<blink::WebMediaStreamTrack
> desc2_video_tracks
;
267 desc2
.videoTracks(desc2_video_tracks
);
268 EXPECT_NE(desc1_video_tracks
[0].source().id(),
269 desc2_video_tracks
[0].source().id());
271 EXPECT_NE(desc1_video_tracks
[0].source().extraData(),
272 desc2_video_tracks
[0].source().extraData());
274 blink::WebVector
<blink::WebMediaStreamTrack
> desc1_audio_tracks
;
275 desc1
.audioTracks(desc1_audio_tracks
);
276 blink::WebVector
<blink::WebMediaStreamTrack
> desc2_audio_tracks
;
277 desc2
.audioTracks(desc2_audio_tracks
);
278 EXPECT_NE(desc1_audio_tracks
[0].source().id(),
279 desc2_audio_tracks
[0].source().id());
281 EXPECT_NE(desc1_audio_tracks
[0].source().extraData(),
282 desc2_audio_tracks
[0].source().extraData());
285 TEST_F(MediaStreamImplTest
, StopLocalTracks
) {
286 // Generate a stream with both audio and video.
287 blink::WebMediaStream mixed_desc
= RequestLocalMediaStream();
289 blink::WebVector
<blink::WebMediaStreamTrack
> audio_tracks
;
290 mixed_desc
.audioTracks(audio_tracks
);
291 MediaStreamTrack
* audio_track
= MediaStreamTrack::GetTrack(audio_tracks
[0]);
293 EXPECT_EQ(1, ms_dispatcher_
->stop_audio_device_counter());
295 blink::WebVector
<blink::WebMediaStreamTrack
> video_tracks
;
296 mixed_desc
.videoTracks(video_tracks
);
297 MediaStreamTrack
* video_track
= MediaStreamTrack::GetTrack(video_tracks
[0]);
299 EXPECT_EQ(1, ms_dispatcher_
->stop_video_device_counter());
302 // This test that a source is not stopped even if the tracks in a
303 // MediaStream is stopped if there are two MediaStreams with tracks using the
304 // same device. The source is stopped
305 // if there are no more MediaStream tracks using the device.
306 TEST_F(MediaStreamImplTest
, StopLocalTracksWhenTwoStreamUseSameDevices
) {
307 // Generate a stream with both audio and video.
308 blink::WebMediaStream desc1
= RequestLocalMediaStream();
309 blink::WebMediaStream desc2
= RequestLocalMediaStream();
311 blink::WebVector
<blink::WebMediaStreamTrack
> audio_tracks1
;
312 desc1
.audioTracks(audio_tracks1
);
313 MediaStreamTrack
* audio_track1
= MediaStreamTrack::GetTrack(audio_tracks1
[0]);
314 audio_track1
->Stop();
315 EXPECT_EQ(0, ms_dispatcher_
->stop_audio_device_counter());
317 blink::WebVector
<blink::WebMediaStreamTrack
> audio_tracks2
;
318 desc2
.audioTracks(audio_tracks2
);
319 MediaStreamTrack
* audio_track2
= MediaStreamTrack::GetTrack(audio_tracks2
[0]);
320 audio_track2
->Stop();
321 EXPECT_EQ(1, ms_dispatcher_
->stop_audio_device_counter());
323 blink::WebVector
<blink::WebMediaStreamTrack
> video_tracks1
;
324 desc1
.videoTracks(video_tracks1
);
325 MediaStreamTrack
* video_track1
= MediaStreamTrack::GetTrack(video_tracks1
[0]);
326 video_track1
->Stop();
327 EXPECT_EQ(0, ms_dispatcher_
->stop_video_device_counter());
329 blink::WebVector
<blink::WebMediaStreamTrack
> video_tracks2
;
330 desc2
.videoTracks(video_tracks2
);
331 MediaStreamTrack
* video_track2
= MediaStreamTrack::GetTrack(video_tracks2
[0]);
332 video_track2
->Stop();
333 EXPECT_EQ(1, ms_dispatcher_
->stop_video_device_counter());
336 TEST_F(MediaStreamImplTest
, StopSourceWhenMediaStreamGoesOutOfScope
) {
337 // Generate a stream with both audio and video.
338 RequestLocalMediaStream();
339 // Makes sure the test itself don't hold a reference to the created
341 ms_impl_
->ClearLastGeneratedStream();
343 // Expect the sources to be stopped when the MediaStream goes out of scope.
344 EXPECT_EQ(1, ms_dispatcher_
->stop_audio_device_counter());
345 EXPECT_EQ(1, ms_dispatcher_
->stop_video_device_counter());
348 // Test that the MediaStreams are deleted if the owning WebFrame is closing.
349 // In the unit test the owning frame is NULL.
350 TEST_F(MediaStreamImplTest
, FrameWillClose
) {
351 // Test a stream with both audio and video.
352 blink::WebMediaStream mixed_desc
= RequestLocalMediaStream();
353 blink::WebMediaStream desc2
= RequestLocalMediaStream();
354 ms_impl_
->FrameWillClose();
355 EXPECT_EQ(1, ms_dispatcher_
->stop_audio_device_counter());
356 EXPECT_EQ(1, ms_dispatcher_
->stop_video_device_counter());
359 // This test what happens if a video source to a MediaSteam fails to start.
360 TEST_F(MediaStreamImplTest
, MediaVideoSourceFailToStart
) {
361 ms_impl_
->RequestUserMedia();
362 FakeMediaStreamDispatcherRequestUserMediaComplete();
363 FailToStartMockedVideoSource();
364 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_FAILED
,
365 ms_impl_
->request_state());
366 EXPECT_EQ(MEDIA_DEVICE_TRACK_START_FAILURE
,
367 ms_impl_
->error_reason());
368 EXPECT_EQ(1, ms_dispatcher_
->request_stream_counter());
369 EXPECT_EQ(1, ms_dispatcher_
->stop_audio_device_counter());
370 EXPECT_EQ(1, ms_dispatcher_
->stop_video_device_counter());
373 // This test what happens if an audio source fail to initialize.
374 TEST_F(MediaStreamImplTest
, MediaAudioSourceFailToInitialize
) {
375 FailToCreateNextAudioCapturer();
376 ms_impl_
->RequestUserMedia();
377 FakeMediaStreamDispatcherRequestUserMediaComplete();
378 StartMockedVideoSource();
379 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_FAILED
,
380 ms_impl_
->request_state());
381 EXPECT_EQ(MEDIA_DEVICE_TRACK_START_FAILURE
,
382 ms_impl_
->error_reason());
383 EXPECT_EQ(1, ms_dispatcher_
->request_stream_counter());
384 EXPECT_EQ(1, ms_dispatcher_
->stop_audio_device_counter());
385 EXPECT_EQ(1, ms_dispatcher_
->stop_video_device_counter());
388 // This test what happens if MediaStreamImpl is deleted before a source has
390 TEST_F(MediaStreamImplTest
, MediaStreamImplShutDown
) {
391 ms_impl_
->RequestUserMedia();
392 FakeMediaStreamDispatcherRequestUserMediaComplete();
393 EXPECT_EQ(1, ms_dispatcher_
->request_stream_counter());
394 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE
,
395 ms_impl_
->request_state());
399 // This test what happens if the WebFrame is closed while the MediaStream is
400 // being generated by the MediaStreamDispatcher.
401 TEST_F(MediaStreamImplTest
, ReloadFrameWhileGeneratingStream
) {
402 ms_impl_
->RequestUserMedia();
403 ms_impl_
->FrameWillClose();
404 EXPECT_EQ(1, ms_dispatcher_
->request_stream_counter());
405 EXPECT_EQ(0, ms_dispatcher_
->stop_audio_device_counter());
406 EXPECT_EQ(0, ms_dispatcher_
->stop_video_device_counter());
407 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE
,
408 ms_impl_
->request_state());
411 // This test what happens if the WebFrame is closed while the sources are being
413 TEST_F(MediaStreamImplTest
, ReloadFrameWhileGeneratingSources
) {
414 ms_impl_
->RequestUserMedia();
415 FakeMediaStreamDispatcherRequestUserMediaComplete();
416 EXPECT_EQ(1, ms_dispatcher_
->request_stream_counter());
417 ms_impl_
->FrameWillClose();
418 EXPECT_EQ(1, ms_dispatcher_
->stop_audio_device_counter());
419 EXPECT_EQ(1, ms_dispatcher_
->stop_video_device_counter());
420 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE
,
421 ms_impl_
->request_state());
424 // This test what happens if stop is called on a track after the frame has
426 TEST_F(MediaStreamImplTest
, StopTrackAfterReload
) {
427 blink::WebMediaStream mixed_desc
= RequestLocalMediaStream();
428 EXPECT_EQ(1, ms_dispatcher_
->request_stream_counter());
429 ms_impl_
->FrameWillClose();
430 EXPECT_EQ(1, ms_dispatcher_
->stop_audio_device_counter());
431 EXPECT_EQ(1, ms_dispatcher_
->stop_video_device_counter());
433 blink::WebVector
<blink::WebMediaStreamTrack
> audio_tracks
;
434 mixed_desc
.audioTracks(audio_tracks
);
435 MediaStreamTrack
* audio_track
= MediaStreamTrack::GetTrack(audio_tracks
[0]);
437 EXPECT_EQ(1, ms_dispatcher_
->stop_audio_device_counter());
439 blink::WebVector
<blink::WebMediaStreamTrack
> video_tracks
;
440 mixed_desc
.videoTracks(video_tracks
);
441 MediaStreamTrack
* video_track
= MediaStreamTrack::GetTrack(video_tracks
[0]);
443 EXPECT_EQ(1, ms_dispatcher_
->stop_video_device_counter());
446 TEST_F(MediaStreamImplTest
, EnumerateMediaDevices
) {
447 ms_impl_
->RequestMediaDevices();
448 FakeMediaStreamDispatcherRequestMediaDevicesComplete();
450 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_SUCCEEDED
,
451 ms_impl_
->request_state());
453 // Audio input device with matched output ID.
454 EXPECT_FALSE(ms_impl_
->last_devices()[0].deviceId().isEmpty());
455 EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindAudioInput
,
456 ms_impl_
->last_devices()[0].kind());
457 EXPECT_FALSE(ms_impl_
->last_devices()[0].label().isEmpty());
458 EXPECT_FALSE(ms_impl_
->last_devices()[0].groupId().isEmpty());
460 // Audio input device without matched output ID.
461 EXPECT_FALSE(ms_impl_
->last_devices()[1].deviceId().isEmpty());
462 EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindAudioInput
,
463 ms_impl_
->last_devices()[1].kind());
464 EXPECT_FALSE(ms_impl_
->last_devices()[1].label().isEmpty());
465 EXPECT_FALSE(ms_impl_
->last_devices()[1].groupId().isEmpty());
467 // Video input device.
468 EXPECT_FALSE(ms_impl_
->last_devices()[2].deviceId().isEmpty());
469 EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindVideoInput
,
470 ms_impl_
->last_devices()[2].kind());
471 EXPECT_FALSE(ms_impl_
->last_devices()[2].label().isEmpty());
472 EXPECT_TRUE(ms_impl_
->last_devices()[2].groupId().isEmpty());
474 // Audio output device.
475 EXPECT_FALSE(ms_impl_
->last_devices()[3].deviceId().isEmpty());
476 EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindAudioOutput
,
477 ms_impl_
->last_devices()[3].kind());
478 EXPECT_FALSE(ms_impl_
->last_devices()[3].label().isEmpty());
479 EXPECT_FALSE(ms_impl_
->last_devices()[3].groupId().isEmpty());
481 // Verfify group IDs.
482 EXPECT_TRUE(ms_impl_
->last_devices()[0].groupId().equals(
483 ms_impl_
->last_devices()[3].groupId()));
484 EXPECT_FALSE(ms_impl_
->last_devices()[1].groupId().equals(
485 ms_impl_
->last_devices()[3].groupId()));
488 } // namespace content