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(MediaStreamDispatcher
* media_stream_dispatcher
,
47 PeerConnectionDependencyFactory
* dependency_factory
)
48 : MediaStreamImpl(NULL
, media_stream_dispatcher
, dependency_factory
),
49 state_(REQUEST_NOT_STARTED
),
50 result_(NUM_MEDIA_REQUEST_RESULTS
),
51 factory_(dependency_factory
),
55 void RequestUserMedia() {
56 blink::WebUserMediaRequest user_media_request
;
57 state_
= REQUEST_NOT_COMPLETE
;
58 requestUserMedia(user_media_request
);
61 void RequestMediaDevices() {
62 blink::WebMediaDevicesRequest media_devices_request
;
63 state_
= REQUEST_NOT_COMPLETE
;
64 requestMediaDevices(media_devices_request
);
67 virtual void GetUserMediaRequestSucceeded(
68 const blink::WebMediaStream
& stream
,
69 blink::WebUserMediaRequest
* request_info
) OVERRIDE
{
70 last_generated_stream_
= stream
;
71 state_
= REQUEST_SUCCEEDED
;
74 virtual void GetUserMediaRequestFailed(
75 blink::WebUserMediaRequest
* request_info
,
76 content::MediaStreamRequestResult result
) OVERRIDE
{
77 last_generated_stream_
.reset();
78 state_
= REQUEST_FAILED
;
82 virtual void EnumerateDevicesSucceded(
83 blink::WebMediaDevicesRequest
* request
,
84 blink::WebVector
<blink::WebMediaDeviceInfo
>& devices
) OVERRIDE
{
85 state_
= REQUEST_SUCCEEDED
;
86 last_devices_
= devices
;
89 virtual MediaStreamVideoSource
* CreateVideoSource(
90 const StreamDeviceInfo
& device
,
91 const MediaStreamSource::SourceStoppedCallback
& stop_callback
) OVERRIDE
{
92 video_source_
= new MockMediaStreamVideoCapturerSource(device
,
98 const blink::WebMediaStream
& last_generated_stream() {
99 return last_generated_stream_
;
102 const blink::WebVector
<blink::WebMediaDeviceInfo
>& last_devices() {
103 return last_devices_
;
106 void ClearLastGeneratedStream() {
107 last_generated_stream_
.reset();
110 MockMediaStreamVideoCapturerSource
* last_created_video_source() const {
111 return video_source_
;
114 RequestState
request_state() const { return state_
; }
115 content::MediaStreamRequestResult
error_reason() const { return result_
; }
118 blink::WebMediaStream last_generated_stream_
;
120 content::MediaStreamRequestResult result_
;
121 blink::WebVector
<blink::WebMediaDeviceInfo
> last_devices_
;
122 PeerConnectionDependencyFactory
* factory_
;
123 MockMediaStreamVideoCapturerSource
* video_source_
;
126 class MediaStreamImplTest
: public ::testing::Test
{
128 virtual void SetUp() {
129 // Create our test object.
130 child_process_
.reset(new ChildProcess());
131 ms_dispatcher_
.reset(new MockMediaStreamDispatcher());
132 dependency_factory_
.reset(new MockPeerConnectionDependencyFactory());
133 ms_impl_
.reset(new MediaStreamImplUnderTest(ms_dispatcher_
.get(),
134 dependency_factory_
.get()));
137 blink::WebMediaStream
RequestLocalMediaStream() {
138 ms_impl_
->RequestUserMedia();
139 FakeMediaStreamDispatcherRequestUserMediaComplete();
140 StartMockedVideoSource();
142 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_SUCCEEDED
,
143 ms_impl_
->request_state());
145 blink::WebMediaStream desc
= ms_impl_
->last_generated_stream();
146 content::MediaStream
* native_stream
=
147 content::MediaStream::GetMediaStream(desc
);
148 if (!native_stream
) {
153 blink::WebVector
<blink::WebMediaStreamTrack
> audio_tracks
;
154 desc
.audioTracks(audio_tracks
);
155 blink::WebVector
<blink::WebMediaStreamTrack
> video_tracks
;
156 desc
.videoTracks(video_tracks
);
158 EXPECT_EQ(1u, audio_tracks
.size());
159 EXPECT_EQ(1u, video_tracks
.size());
160 EXPECT_NE(audio_tracks
[0].id(), video_tracks
[0].id());
164 void FakeMediaStreamDispatcherRequestUserMediaComplete() {
165 // Audio request ID is used as the shared request ID.
166 ms_impl_
->OnStreamGenerated(ms_dispatcher_
->audio_request_id(),
167 ms_dispatcher_
->stream_label(),
168 ms_dispatcher_
->audio_array(),
169 ms_dispatcher_
->video_array());
172 void FakeMediaStreamDispatcherRequestMediaDevicesComplete() {
173 ms_impl_
->OnDevicesEnumerated(ms_dispatcher_
->audio_request_id(),
174 ms_dispatcher_
->audio_array());
175 ms_impl_
->OnDevicesEnumerated(ms_dispatcher_
->video_request_id(),
176 ms_dispatcher_
->video_array());
179 void StartMockedVideoSource() {
180 MockMediaStreamVideoCapturerSource
* video_source
=
181 ms_impl_
->last_created_video_source();
182 if (video_source
->SourceHasAttemptedToStart())
183 video_source
->StartMockedSource();
186 void FailToStartMockedVideoSource() {
187 MockMediaStreamVideoCapturerSource
* video_source
=
188 ms_impl_
->last_created_video_source();
189 if (video_source
->SourceHasAttemptedToStart())
190 video_source
->FailToStartMockedSource();
193 void FailToCreateNextAudioCapturer() {
194 dependency_factory_
->FailToCreateNextAudioCapturer();
198 base::MessageLoop message_loop_
;
199 scoped_ptr
<ChildProcess
> child_process_
;
200 scoped_ptr
<MockMediaStreamDispatcher
> ms_dispatcher_
;
201 scoped_ptr
<MediaStreamImplUnderTest
> ms_impl_
;
202 scoped_ptr
<MockPeerConnectionDependencyFactory
> dependency_factory_
;
205 TEST_F(MediaStreamImplTest
, GenerateMediaStream
) {
206 // Generate a stream with both audio and video.
207 blink::WebMediaStream mixed_desc
= RequestLocalMediaStream();
210 // Test that the same source object is used if two MediaStreams are generated
211 // using the same source.
212 TEST_F(MediaStreamImplTest
, GenerateTwoMediaStreamsWithSameSource
) {
213 blink::WebMediaStream desc1
= RequestLocalMediaStream();
214 blink::WebMediaStream desc2
= RequestLocalMediaStream();
216 blink::WebVector
<blink::WebMediaStreamTrack
> desc1_video_tracks
;
217 desc1
.videoTracks(desc1_video_tracks
);
218 blink::WebVector
<blink::WebMediaStreamTrack
> desc2_video_tracks
;
219 desc2
.videoTracks(desc2_video_tracks
);
220 EXPECT_EQ(desc1_video_tracks
[0].source().id(),
221 desc2_video_tracks
[0].source().id());
223 EXPECT_EQ(desc1_video_tracks
[0].source().extraData(),
224 desc2_video_tracks
[0].source().extraData());
226 blink::WebVector
<blink::WebMediaStreamTrack
> desc1_audio_tracks
;
227 desc1
.audioTracks(desc1_audio_tracks
);
228 blink::WebVector
<blink::WebMediaStreamTrack
> desc2_audio_tracks
;
229 desc2
.audioTracks(desc2_audio_tracks
);
230 EXPECT_EQ(desc1_audio_tracks
[0].source().id(),
231 desc2_audio_tracks
[0].source().id());
233 EXPECT_EQ(desc1_audio_tracks
[0].source().extraData(),
234 desc2_audio_tracks
[0].source().extraData());
237 // Test that the same source object is not used if two MediaStreams are
238 // generated using different sources.
239 TEST_F(MediaStreamImplTest
, GenerateTwoMediaStreamsWithDifferentSources
) {
240 blink::WebMediaStream desc1
= RequestLocalMediaStream();
241 // Make sure another device is selected (another |session_id|) in the next
243 ms_dispatcher_
->IncrementSessionId();
244 blink::WebMediaStream desc2
= RequestLocalMediaStream();
246 blink::WebVector
<blink::WebMediaStreamTrack
> desc1_video_tracks
;
247 desc1
.videoTracks(desc1_video_tracks
);
248 blink::WebVector
<blink::WebMediaStreamTrack
> desc2_video_tracks
;
249 desc2
.videoTracks(desc2_video_tracks
);
250 EXPECT_NE(desc1_video_tracks
[0].source().id(),
251 desc2_video_tracks
[0].source().id());
253 EXPECT_NE(desc1_video_tracks
[0].source().extraData(),
254 desc2_video_tracks
[0].source().extraData());
256 blink::WebVector
<blink::WebMediaStreamTrack
> desc1_audio_tracks
;
257 desc1
.audioTracks(desc1_audio_tracks
);
258 blink::WebVector
<blink::WebMediaStreamTrack
> desc2_audio_tracks
;
259 desc2
.audioTracks(desc2_audio_tracks
);
260 EXPECT_NE(desc1_audio_tracks
[0].source().id(),
261 desc2_audio_tracks
[0].source().id());
263 EXPECT_NE(desc1_audio_tracks
[0].source().extraData(),
264 desc2_audio_tracks
[0].source().extraData());
267 TEST_F(MediaStreamImplTest
, StopLocalTracks
) {
268 // Generate a stream with both audio and video.
269 blink::WebMediaStream mixed_desc
= RequestLocalMediaStream();
271 blink::WebVector
<blink::WebMediaStreamTrack
> audio_tracks
;
272 mixed_desc
.audioTracks(audio_tracks
);
273 MediaStreamTrack
* audio_track
= MediaStreamTrack::GetTrack(audio_tracks
[0]);
275 EXPECT_EQ(1, ms_dispatcher_
->stop_audio_device_counter());
277 blink::WebVector
<blink::WebMediaStreamTrack
> video_tracks
;
278 mixed_desc
.videoTracks(video_tracks
);
279 MediaStreamTrack
* video_track
= MediaStreamTrack::GetTrack(video_tracks
[0]);
281 EXPECT_EQ(1, ms_dispatcher_
->stop_video_device_counter());
284 // This test that a source is not stopped even if the tracks in a
285 // MediaStream is stopped if there are two MediaStreams with tracks using the
286 // same device. The source is stopped
287 // if there are no more MediaStream tracks using the device.
288 TEST_F(MediaStreamImplTest
, StopLocalTracksWhenTwoStreamUseSameDevices
) {
289 // Generate a stream with both audio and video.
290 blink::WebMediaStream desc1
= RequestLocalMediaStream();
291 blink::WebMediaStream desc2
= RequestLocalMediaStream();
293 blink::WebVector
<blink::WebMediaStreamTrack
> audio_tracks1
;
294 desc1
.audioTracks(audio_tracks1
);
295 MediaStreamTrack
* audio_track1
= MediaStreamTrack::GetTrack(audio_tracks1
[0]);
296 audio_track1
->Stop();
297 EXPECT_EQ(0, ms_dispatcher_
->stop_audio_device_counter());
299 blink::WebVector
<blink::WebMediaStreamTrack
> audio_tracks2
;
300 desc2
.audioTracks(audio_tracks2
);
301 MediaStreamTrack
* audio_track2
= MediaStreamTrack::GetTrack(audio_tracks2
[0]);
302 audio_track2
->Stop();
303 EXPECT_EQ(1, ms_dispatcher_
->stop_audio_device_counter());
305 blink::WebVector
<blink::WebMediaStreamTrack
> video_tracks1
;
306 desc1
.videoTracks(video_tracks1
);
307 MediaStreamTrack
* video_track1
= MediaStreamTrack::GetTrack(video_tracks1
[0]);
308 video_track1
->Stop();
309 EXPECT_EQ(0, ms_dispatcher_
->stop_video_device_counter());
311 blink::WebVector
<blink::WebMediaStreamTrack
> video_tracks2
;
312 desc2
.videoTracks(video_tracks2
);
313 MediaStreamTrack
* video_track2
= MediaStreamTrack::GetTrack(video_tracks2
[0]);
314 video_track2
->Stop();
315 EXPECT_EQ(1, ms_dispatcher_
->stop_video_device_counter());
318 TEST_F(MediaStreamImplTest
, StopSourceWhenMediaStreamGoesOutOfScope
) {
319 // Generate a stream with both audio and video.
320 RequestLocalMediaStream();
321 // Makes sure the test itself don't hold a reference to the created
323 ms_impl_
->ClearLastGeneratedStream();
325 // Expect the sources to be stopped when the MediaStream goes out of scope.
326 EXPECT_EQ(1, ms_dispatcher_
->stop_audio_device_counter());
327 EXPECT_EQ(1, ms_dispatcher_
->stop_video_device_counter());
330 // Test that the MediaStreams are deleted if the owning WebFrame is deleted.
331 // In the unit test the owning frame is NULL.
332 TEST_F(MediaStreamImplTest
, FrameWillClose
) {
333 // Test a stream with both audio and video.
334 blink::WebMediaStream mixed_desc
= RequestLocalMediaStream();
335 blink::WebMediaStream desc2
= RequestLocalMediaStream();
337 // Test that the MediaStreams are deleted if the owning WebFrame is deleted.
338 // In the unit test the owning frame is NULL.
339 ms_impl_
->FrameWillClose(NULL
);
340 EXPECT_EQ(1, ms_dispatcher_
->stop_audio_device_counter());
341 EXPECT_EQ(1, ms_dispatcher_
->stop_video_device_counter());
344 // This test what happens if a video source to a MediaSteam fails to start.
345 TEST_F(MediaStreamImplTest
, MediaVideoSourceFailToStart
) {
346 ms_impl_
->RequestUserMedia();
347 FakeMediaStreamDispatcherRequestUserMediaComplete();
348 FailToStartMockedVideoSource();
349 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_FAILED
,
350 ms_impl_
->request_state());
351 EXPECT_EQ(MEDIA_DEVICE_TRACK_START_FAILURE
,
352 ms_impl_
->error_reason());
353 EXPECT_EQ(1, ms_dispatcher_
->request_stream_counter());
354 EXPECT_EQ(1, ms_dispatcher_
->stop_audio_device_counter());
355 EXPECT_EQ(1, ms_dispatcher_
->stop_video_device_counter());
358 // This test what happens if an audio source fail to initialize.
359 TEST_F(MediaStreamImplTest
, MediaAudioSourceFailToInitialize
) {
360 FailToCreateNextAudioCapturer();
361 ms_impl_
->RequestUserMedia();
362 FakeMediaStreamDispatcherRequestUserMediaComplete();
363 StartMockedVideoSource();
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 MediaStreamImpl is deleted before a source has
375 TEST_F(MediaStreamImplTest
, MediaStreamImplShutDown
) {
376 ms_impl_
->RequestUserMedia();
377 FakeMediaStreamDispatcherRequestUserMediaComplete();
378 EXPECT_EQ(1, ms_dispatcher_
->request_stream_counter());
379 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE
,
380 ms_impl_
->request_state());
384 // This test what happens if the WebFrame is closed while the MediaStream is
385 // being generated by the MediaStreamDispatcher.
386 TEST_F(MediaStreamImplTest
, ReloadFrameWhileGeneratingStream
) {
387 ms_impl_
->RequestUserMedia();
388 ms_impl_
->FrameWillClose(NULL
);
389 EXPECT_EQ(1, ms_dispatcher_
->request_stream_counter());
390 EXPECT_EQ(0, ms_dispatcher_
->stop_audio_device_counter());
391 EXPECT_EQ(0, ms_dispatcher_
->stop_video_device_counter());
392 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE
,
393 ms_impl_
->request_state());
396 // This test what happens if the WebFrame is closed while the sources are being
398 TEST_F(MediaStreamImplTest
, ReloadFrameWhileGeneratingSources
) {
399 ms_impl_
->RequestUserMedia();
400 FakeMediaStreamDispatcherRequestUserMediaComplete();
401 EXPECT_EQ(1, ms_dispatcher_
->request_stream_counter());
402 ms_impl_
->FrameWillClose(NULL
);
403 EXPECT_EQ(1, ms_dispatcher_
->stop_audio_device_counter());
404 EXPECT_EQ(1, ms_dispatcher_
->stop_video_device_counter());
405 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE
,
406 ms_impl_
->request_state());
409 // This test what happens if stop is called on a track after the frame has
411 TEST_F(MediaStreamImplTest
, StopTrackAfterReload
) {
412 blink::WebMediaStream mixed_desc
= RequestLocalMediaStream();
413 EXPECT_EQ(1, ms_dispatcher_
->request_stream_counter());
414 ms_impl_
->FrameWillClose(NULL
);
415 EXPECT_EQ(1, ms_dispatcher_
->stop_audio_device_counter());
416 EXPECT_EQ(1, ms_dispatcher_
->stop_video_device_counter());
418 blink::WebVector
<blink::WebMediaStreamTrack
> audio_tracks
;
419 mixed_desc
.audioTracks(audio_tracks
);
420 MediaStreamTrack
* audio_track
= MediaStreamTrack::GetTrack(audio_tracks
[0]);
422 EXPECT_EQ(1, ms_dispatcher_
->stop_audio_device_counter());
424 blink::WebVector
<blink::WebMediaStreamTrack
> video_tracks
;
425 mixed_desc
.videoTracks(video_tracks
);
426 MediaStreamTrack
* video_track
= MediaStreamTrack::GetTrack(video_tracks
[0]);
428 EXPECT_EQ(1, ms_dispatcher_
->stop_video_device_counter());
431 TEST_F(MediaStreamImplTest
, EnumerateMediaDevices
) {
432 ms_impl_
->RequestMediaDevices();
433 FakeMediaStreamDispatcherRequestMediaDevicesComplete();
435 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_SUCCEEDED
,
436 ms_impl_
->request_state());
438 EXPECT_FALSE(ms_impl_
->last_devices()[0].deviceId().isEmpty());
439 EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindAudioInput
,
440 ms_impl_
->last_devices()[0].kind());
441 EXPECT_FALSE(ms_impl_
->last_devices()[0].label().isEmpty());
443 EXPECT_FALSE(ms_impl_
->last_devices()[1].deviceId().isEmpty());
444 EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindVideoInput
,
445 ms_impl_
->last_devices()[1].kind());
446 EXPECT_FALSE(ms_impl_
->last_devices()[1].label().isEmpty());
449 } // namespace content