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_dependency_factory.h"
13 #include "content/renderer/media/mock_media_stream_dispatcher.h"
14 #include "content/renderer/media/mock_media_stream_video_source.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/WebKit/public/platform/WebMediaStream.h"
17 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
18 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
19 #include "third_party/WebKit/public/platform/WebString.h"
20 #include "third_party/WebKit/public/platform/WebVector.h"
24 class MockMediaStreamVideoCapturerSource : public MockMediaStreamVideoSource {
26 MockMediaStreamVideoCapturerSource(
27 const StreamDeviceInfo& device,
28 const SourceStoppedCallback& stop_callback,
29 MediaStreamDependencyFactory* factory)
30 : MockMediaStreamVideoSource(false) {
31 SetDeviceInfo(device);
32 SetStopCallback(stop_callback);
36 class MediaStreamImplUnderTest : public MediaStreamImpl {
45 MediaStreamImplUnderTest(MediaStreamDispatcher* media_stream_dispatcher,
46 MediaStreamDependencyFactory* dependency_factory)
47 : MediaStreamImpl(NULL, media_stream_dispatcher, dependency_factory),
48 state_(REQUEST_NOT_STARTED),
49 result_(NUM_MEDIA_REQUEST_RESULTS),
50 factory_(dependency_factory),
54 void RequestUserMedia() {
55 blink::WebUserMediaRequest user_media_request;
56 state_ = REQUEST_NOT_COMPLETE;
57 requestUserMedia(user_media_request);
60 virtual void GetUserMediaRequestSucceeded(
61 const blink::WebMediaStream& stream,
62 blink::WebUserMediaRequest* request_info) OVERRIDE {
63 last_generated_stream_ = stream;
64 state_ = REQUEST_SUCCEEDED;
67 virtual void GetUserMediaRequestFailed(
68 blink::WebUserMediaRequest* request_info,
69 content::MediaStreamRequestResult result) OVERRIDE {
70 last_generated_stream_.reset();
71 state_ = REQUEST_FAILED;
75 virtual MediaStreamVideoSource* CreateVideoSource(
76 const StreamDeviceInfo& device,
77 const MediaStreamSource::SourceStoppedCallback& stop_callback) OVERRIDE {
78 video_source_ = new MockMediaStreamVideoCapturerSource(device,
84 const blink::WebMediaStream& last_generated_stream() {
85 return last_generated_stream_;
88 void ClearLastGeneratedStream() {
89 last_generated_stream_.reset();
92 MockMediaStreamVideoCapturerSource* last_created_video_source() const {
96 RequestState request_state() const { return state_; }
97 content::MediaStreamRequestResult error_reason() const { return result_; }
100 blink::WebMediaStream last_generated_stream_;
102 content::MediaStreamRequestResult result_;
103 MediaStreamDependencyFactory* factory_;
104 MockMediaStreamVideoCapturerSource* video_source_;
107 class MediaStreamImplTest : public ::testing::Test {
109 virtual void SetUp() {
110 // Create our test object.
111 child_process_.reset(new ChildProcess());
112 ms_dispatcher_.reset(new MockMediaStreamDispatcher());
113 dependency_factory_.reset(new MockMediaStreamDependencyFactory());
114 ms_impl_.reset(new MediaStreamImplUnderTest(ms_dispatcher_.get(),
115 dependency_factory_.get()));
118 blink::WebMediaStream RequestLocalMediaStream() {
119 ms_impl_->RequestUserMedia();
120 FakeMediaStreamDispatcherComplete();
121 StartMockedVideoSource();
123 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_SUCCEEDED,
124 ms_impl_->request_state());
126 blink::WebMediaStream desc = ms_impl_->last_generated_stream();
127 content::MediaStream* native_stream =
128 content::MediaStream::GetMediaStream(desc);
129 if (!native_stream) {
134 blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
135 desc.audioTracks(audio_tracks);
136 blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
137 desc.videoTracks(video_tracks);
139 EXPECT_EQ(1u, audio_tracks.size());
140 EXPECT_EQ(1u, video_tracks.size());
141 EXPECT_NE(audio_tracks[0].id(), video_tracks[0].id());
145 void FakeMediaStreamDispatcherComplete() {
146 ms_impl_->OnStreamGenerated(ms_dispatcher_->request_id(),
147 ms_dispatcher_->stream_label(),
148 ms_dispatcher_->audio_array(),
149 ms_dispatcher_->video_array());
152 void StartMockedVideoSource() {
153 MockMediaStreamVideoCapturerSource* video_source =
154 ms_impl_->last_created_video_source();
155 if (video_source->SourceHasAttemptedToStart())
156 video_source->StartMockedSource();
159 void FailToStartMockedVideoSource() {
160 MockMediaStreamVideoCapturerSource* video_source =
161 ms_impl_->last_created_video_source();
162 if (video_source->SourceHasAttemptedToStart())
163 video_source->FailToStartMockedSource();
166 void FailToCreateNextAudioCapturer() {
167 dependency_factory_->FailToCreateNextAudioCapturer();
171 base::MessageLoop message_loop_;
172 scoped_ptr<ChildProcess> child_process_;
173 scoped_ptr<MockMediaStreamDispatcher> ms_dispatcher_;
174 scoped_ptr<MediaStreamImplUnderTest> ms_impl_;
175 scoped_ptr<MockMediaStreamDependencyFactory> dependency_factory_;
178 TEST_F(MediaStreamImplTest, GenerateMediaStream) {
179 // Generate a stream with both audio and video.
180 blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
183 // Test that the same source object is used if two MediaStreams are generated
184 // using the same source.
185 TEST_F(MediaStreamImplTest, GenerateTwoMediaStreamsWithSameSource) {
186 blink::WebMediaStream desc1 = RequestLocalMediaStream();
187 blink::WebMediaStream desc2 = RequestLocalMediaStream();
189 blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks;
190 desc1.videoTracks(desc1_video_tracks);
191 blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks;
192 desc2.videoTracks(desc2_video_tracks);
193 EXPECT_EQ(desc1_video_tracks[0].source().id(),
194 desc2_video_tracks[0].source().id());
196 EXPECT_EQ(desc1_video_tracks[0].source().extraData(),
197 desc2_video_tracks[0].source().extraData());
199 blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks;
200 desc1.audioTracks(desc1_audio_tracks);
201 blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks;
202 desc2.audioTracks(desc2_audio_tracks);
203 EXPECT_EQ(desc1_audio_tracks[0].source().id(),
204 desc2_audio_tracks[0].source().id());
206 EXPECT_EQ(desc1_audio_tracks[0].source().extraData(),
207 desc2_audio_tracks[0].source().extraData());
210 // Test that the same source object is not used if two MediaStreams are
211 // generated using different sources.
212 TEST_F(MediaStreamImplTest, GenerateTwoMediaStreamsWithDifferentSources) {
213 blink::WebMediaStream desc1 = RequestLocalMediaStream();
214 // Make sure another device is selected (another |session_id|) in the next
216 ms_dispatcher_->IncrementSessionId();
217 blink::WebMediaStream desc2 = RequestLocalMediaStream();
219 blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks;
220 desc1.videoTracks(desc1_video_tracks);
221 blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks;
222 desc2.videoTracks(desc2_video_tracks);
223 EXPECT_NE(desc1_video_tracks[0].source().id(),
224 desc2_video_tracks[0].source().id());
226 EXPECT_NE(desc1_video_tracks[0].source().extraData(),
227 desc2_video_tracks[0].source().extraData());
229 blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks;
230 desc1.audioTracks(desc1_audio_tracks);
231 blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks;
232 desc2.audioTracks(desc2_audio_tracks);
233 EXPECT_NE(desc1_audio_tracks[0].source().id(),
234 desc2_audio_tracks[0].source().id());
236 EXPECT_NE(desc1_audio_tracks[0].source().extraData(),
237 desc2_audio_tracks[0].source().extraData());
240 TEST_F(MediaStreamImplTest, StopLocalTracks) {
241 // Generate a stream with both audio and video.
242 blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
244 blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
245 mixed_desc.audioTracks(audio_tracks);
246 MediaStreamTrack* audio_track = MediaStreamTrack::GetTrack(audio_tracks[0]);
248 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
250 blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
251 mixed_desc.videoTracks(video_tracks);
252 MediaStreamTrack* video_track = MediaStreamTrack::GetTrack(video_tracks[0]);
254 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
257 // This test that a source is not stopped even if the tracks in a
258 // MediaStream is stopped if there are two MediaStreams with tracks using the
259 // same device. The source is stopped
260 // if there are no more MediaStream tracks using the device.
261 TEST_F(MediaStreamImplTest, StopLocalTracksWhenTwoStreamUseSameDevices) {
262 // Generate a stream with both audio and video.
263 blink::WebMediaStream desc1 = RequestLocalMediaStream();
264 blink::WebMediaStream desc2 = RequestLocalMediaStream();
266 blink::WebVector<blink::WebMediaStreamTrack> audio_tracks1;
267 desc1.audioTracks(audio_tracks1);
268 MediaStreamTrack* audio_track1 = MediaStreamTrack::GetTrack(audio_tracks1[0]);
269 audio_track1->Stop();
270 EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter());
272 blink::WebVector<blink::WebMediaStreamTrack> audio_tracks2;
273 desc2.audioTracks(audio_tracks2);
274 MediaStreamTrack* audio_track2 = MediaStreamTrack::GetTrack(audio_tracks2[0]);
275 audio_track2->Stop();
276 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
278 blink::WebVector<blink::WebMediaStreamTrack> video_tracks1;
279 desc1.videoTracks(video_tracks1);
280 MediaStreamTrack* video_track1 = MediaStreamTrack::GetTrack(video_tracks1[0]);
281 video_track1->Stop();
282 EXPECT_EQ(0, ms_dispatcher_->stop_video_device_counter());
284 blink::WebVector<blink::WebMediaStreamTrack> video_tracks2;
285 desc2.videoTracks(video_tracks2);
286 MediaStreamTrack* video_track2 = MediaStreamTrack::GetTrack(video_tracks2[0]);
287 video_track2->Stop();
288 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
291 TEST_F(MediaStreamImplTest, StopSourceWhenMediaStreamGoesOutOfScope) {
292 // Generate a stream with both audio and video.
293 RequestLocalMediaStream();
294 // Makes sure the test itself don't hold a reference to the created
296 ms_impl_->ClearLastGeneratedStream();
298 // Expect the sources to be stopped when the MediaStream goes out of scope.
299 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
300 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
303 // Test that the MediaStreams are deleted if the owning WebFrame is deleted.
304 // In the unit test the owning frame is NULL.
305 TEST_F(MediaStreamImplTest, FrameWillClose) {
306 // Test a stream with both audio and video.
307 blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
308 blink::WebMediaStream desc2 = RequestLocalMediaStream();
310 // Test that the MediaStreams are deleted if the owning WebFrame is deleted.
311 // In the unit test the owning frame is NULL.
312 ms_impl_->FrameWillClose(NULL);
313 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
314 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
317 // This test what happens if a video source to a MediaSteam fails to start.
318 TEST_F(MediaStreamImplTest, MediaVideoSourceFailToStart) {
319 ms_impl_->RequestUserMedia();
320 FakeMediaStreamDispatcherComplete();
321 FailToStartMockedVideoSource();
322 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_FAILED,
323 ms_impl_->request_state());
324 EXPECT_EQ(MEDIA_DEVICE_TRACK_START_FAILURE,
325 ms_impl_->error_reason());
326 EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
327 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
328 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
331 // This test what happens if an audio source fail to initialize.
332 TEST_F(MediaStreamImplTest, MediaAudioSourceFailToInitialize) {
333 FailToCreateNextAudioCapturer();
334 ms_impl_->RequestUserMedia();
335 FakeMediaStreamDispatcherComplete();
336 StartMockedVideoSource();
337 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_FAILED,
338 ms_impl_->request_state());
339 EXPECT_EQ(MEDIA_DEVICE_TRACK_START_FAILURE,
340 ms_impl_->error_reason());
341 EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
342 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
343 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
346 // This test what happens if MediaStreamImpl is deleted before a source has
348 TEST_F(MediaStreamImplTest, MediaStreamImplShutDown) {
349 ms_impl_->RequestUserMedia();
350 FakeMediaStreamDispatcherComplete();
351 EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
352 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE,
353 ms_impl_->request_state());
357 // This test what happens if the WebFrame is closed while the MediaStream is
358 // being generated by the MediaStreamDispatcher.
359 TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingStream) {
360 ms_impl_->RequestUserMedia();
361 ms_impl_->FrameWillClose(NULL);
362 EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
363 EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter());
364 EXPECT_EQ(0, ms_dispatcher_->stop_video_device_counter());
365 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE,
366 ms_impl_->request_state());
369 // This test what happens if the WebFrame is closed while the sources are being
371 TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingSources) {
372 ms_impl_->RequestUserMedia();
373 FakeMediaStreamDispatcherComplete();
374 EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
375 ms_impl_->FrameWillClose(NULL);
376 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
377 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
378 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE,
379 ms_impl_->request_state());
382 // This test what happens if stop is called on a track after the frame has
384 TEST_F(MediaStreamImplTest, StopTrackAfterReload) {
385 blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
386 EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
387 ms_impl_->FrameWillClose(NULL);
388 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
389 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
391 blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
392 mixed_desc.audioTracks(audio_tracks);
393 MediaStreamTrack* audio_track = MediaStreamTrack::GetTrack(audio_tracks[0]);
395 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
397 blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
398 mixed_desc.videoTracks(video_tracks);
399 MediaStreamTrack* video_track = MediaStreamTrack::GetTrack(video_tracks[0]);
401 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
404 } // namespace content