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.
4
5 #include "base/memory/scoped_ptr.h"
6 #include "base/strings/utf_string_conversions.h"
7 #include "content/renderer/media/media_stream_extra_data.h"
8 #include "content/renderer/media/media_stream_impl.h"
9 #include "content/renderer/media/mock_media_stream_dependency_factory.h"
10 #include "content/renderer/media/mock_media_stream_dispatcher.h"
11 #include "content/renderer/media/video_capture_impl_manager.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/WebKit/public/platform/WebMediaStream.h"
14 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
15 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
16 #include "third_party/WebKit/public/platform/WebString.h"
17 #include "third_party/WebKit/public/platform/WebVector.h"
18
19 namespace content {
20
21 class MediaStreamImplUnderTest : public MediaStreamImpl {
22 public:
23 enum RequestState {
24 REQUEST_NOT_STARTED,
25 REQUEST_NOT_COMPLETE,
26 REQUEST_SUCCEEDED,
27 REQUEST_FAILED,
28 };
29
MediaStreamImplUnderTest(MediaStreamDispatcher * media_stream_dispatcher,MediaStreamDependencyFactory * dependency_factory)30 MediaStreamImplUnderTest(MediaStreamDispatcher* media_stream_dispatcher,
31 MediaStreamDependencyFactory* dependency_factory)
32 : MediaStreamImpl(NULL, media_stream_dispatcher, dependency_factory),
33 state_(REQUEST_NOT_STARTED) {
34 }
35
RequestUserMedia()36 void RequestUserMedia() {
37 blink::WebUserMediaRequest user_media_request;
38 state_ = REQUEST_NOT_COMPLETE;
39 requestUserMedia(user_media_request);
40 }
41
CompleteGetUserMediaRequest(const blink::WebMediaStream & stream,blink::WebUserMediaRequest * request_info,bool request_succeeded)42 virtual void CompleteGetUserMediaRequest(
43 const blink::WebMediaStream& stream,
44 blink::WebUserMediaRequest* request_info,
45 bool request_succeeded) OVERRIDE {
46 last_generated_stream_ = stream;
47 state_ = request_succeeded ? REQUEST_SUCCEEDED : REQUEST_FAILED;
48 }
49
GetMediaStream(const GURL & url)50 virtual blink::WebMediaStream GetMediaStream(
51 const GURL& url) OVERRIDE {
52 return last_generated_stream_;
53 }
54
55 using MediaStreamImpl::OnLocalMediaStreamStop;
56 using MediaStreamImpl::OnLocalSourceStop;
57
last_generated_stream()58 const blink::WebMediaStream& last_generated_stream() {
59 return last_generated_stream_;
60 }
61
request_state() const62 RequestState request_state() const { return state_; }
63
64 private:
65 blink::WebMediaStream last_generated_stream_;
66 RequestState state_;
67 };
68
69 class MediaStreamImplTest : public ::testing::Test {
70 public:
SetUp()71 virtual void SetUp() {
72 // Create our test object.
73 ms_dispatcher_.reset(new MockMediaStreamDispatcher());
74 dependency_factory_.reset(new MockMediaStreamDependencyFactory());
75 ms_impl_.reset(new MediaStreamImplUnderTest(ms_dispatcher_.get(),
76 dependency_factory_.get()));
77 }
78
RequestLocalMediaStream()79 blink::WebMediaStream RequestLocalMediaStream() {
80 ms_impl_->RequestUserMedia();
81 FakeMediaStreamDispatcherComplete();
82 ChangeVideoSourceStateToLive();
83 ChangeAudioSourceStateToLive();
84
85 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_SUCCEEDED,
86 ms_impl_->request_state());
87
88 blink::WebMediaStream desc = ms_impl_->last_generated_stream();
89 content::MediaStreamExtraData* extra_data =
90 static_cast<content::MediaStreamExtraData*>(desc.extraData());
91 if (!extra_data || !extra_data->stream().get()) {
92 ADD_FAILURE();
93 return desc;
94 }
95
96 EXPECT_EQ(1u, extra_data->stream()->GetAudioTracks().size());
97 EXPECT_EQ(1u, extra_data->stream()->GetVideoTracks().size());
98 EXPECT_NE(extra_data->stream()->GetAudioTracks()[0]->id(),
99 extra_data->stream()->GetVideoTracks()[0]->id());
100 return desc;
101 }
102
FakeMediaStreamDispatcherComplete()103 void FakeMediaStreamDispatcherComplete() {
104 ms_impl_->OnStreamGenerated(ms_dispatcher_->request_id(),
105 ms_dispatcher_->stream_label(),
106 ms_dispatcher_->audio_array(),
107 ms_dispatcher_->video_array());
108 }
109
ChangeVideoSourceStateToLive()110 void ChangeVideoSourceStateToLive() {
111 if (dependency_factory_->last_video_source() != NULL) {
112 dependency_factory_->last_video_source()->SetLive();
113 }
114 }
115
ChangeAudioSourceStateToLive()116 void ChangeAudioSourceStateToLive() {
117 if (dependency_factory_->last_audio_source() != NULL) {
118 dependency_factory_->last_audio_source()->SetLive();
119 }
120 }
121
ChangeVideoSourceStateToEnded()122 void ChangeVideoSourceStateToEnded() {
123 if (dependency_factory_->last_video_source() != NULL) {
124 dependency_factory_->last_video_source()->SetEnded();
125 }
126 }
127
ChangeAudioSourceStateToEnded()128 void ChangeAudioSourceStateToEnded() {
129 if (dependency_factory_->last_audio_source() != NULL) {
130 dependency_factory_->last_audio_source()->SetEnded();
131 }
132 }
133
134 protected:
135 scoped_ptr<MockMediaStreamDispatcher> ms_dispatcher_;
136 scoped_ptr<MediaStreamImplUnderTest> ms_impl_;
137 scoped_ptr<MockMediaStreamDependencyFactory> dependency_factory_;
138 };
139
TEST_F(MediaStreamImplTest,GenerateMediaStream)140 TEST_F(MediaStreamImplTest, GenerateMediaStream) {
141 // Generate a stream with both audio and video.
142 blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
143 }
144
145 // Test that the same source object is used if two MediaStreams are generated
146 // using the same source.
TEST_F(MediaStreamImplTest,GenerateTwoMediaStreamsWithSameSource)147 TEST_F(MediaStreamImplTest, GenerateTwoMediaStreamsWithSameSource) {
148 blink::WebMediaStream desc1 = RequestLocalMediaStream();
149 blink::WebMediaStream desc2 = RequestLocalMediaStream();
150
151 blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks;
152 desc1.videoTracks(desc1_video_tracks);
153 blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks;
154 desc2.videoTracks(desc2_video_tracks);
155 EXPECT_EQ(desc1_video_tracks[0].source().id(),
156 desc2_video_tracks[0].source().id());
157
158 EXPECT_EQ(desc1_video_tracks[0].source().extraData(),
159 desc2_video_tracks[0].source().extraData());
160
161 blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks;
162 desc1.audioTracks(desc1_audio_tracks);
163 blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks;
164 desc2.audioTracks(desc2_audio_tracks);
165 EXPECT_EQ(desc1_audio_tracks[0].source().id(),
166 desc2_audio_tracks[0].source().id());
167
168 EXPECT_EQ(desc1_audio_tracks[0].source().extraData(),
169 desc2_audio_tracks[0].source().extraData());
170 }
171
172 // Test that the same source object is not used if two MediaStreams are
173 // generated using different sources.
TEST_F(MediaStreamImplTest,GenerateTwoMediaStreamsWithDifferentSources)174 TEST_F(MediaStreamImplTest, GenerateTwoMediaStreamsWithDifferentSources) {
175 blink::WebMediaStream desc1 = RequestLocalMediaStream();
176 // Make sure another device is selected (another |session_id|) in the next
177 // gUM request.
178 ms_dispatcher_->IncrementSessionId();
179 blink::WebMediaStream desc2 = RequestLocalMediaStream();
180
181 blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks;
182 desc1.videoTracks(desc1_video_tracks);
183 blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks;
184 desc2.videoTracks(desc2_video_tracks);
185 EXPECT_NE(desc1_video_tracks[0].source().id(),
186 desc2_video_tracks[0].source().id());
187
188 EXPECT_NE(desc1_video_tracks[0].source().extraData(),
189 desc2_video_tracks[0].source().extraData());
190
191 blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks;
192 desc1.audioTracks(desc1_audio_tracks);
193 blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks;
194 desc2.audioTracks(desc2_audio_tracks);
195 EXPECT_NE(desc1_audio_tracks[0].source().id(),
196 desc2_audio_tracks[0].source().id());
197
198 EXPECT_NE(desc1_audio_tracks[0].source().extraData(),
199 desc2_audio_tracks[0].source().extraData());
200 }
201
TEST_F(MediaStreamImplTest,StopLocalMediaStream)202 TEST_F(MediaStreamImplTest, StopLocalMediaStream) {
203 // Generate a stream with both audio and video.
204 blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
205
206 // Stop generated local streams.
207 ms_impl_->OnLocalMediaStreamStop(mixed_desc.id().utf8());
208 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
209 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
210 }
211
212 // This test that a source is not stopped even if the MediaStream is stopped if
213 // there are two MediaStreams using the same device. The source is stopped
214 // if there are no more MediaStreams using the device.
TEST_F(MediaStreamImplTest,StopLocalMediaStreamWhenTwoStreamUseSameDevices)215 TEST_F(MediaStreamImplTest, StopLocalMediaStreamWhenTwoStreamUseSameDevices) {
216 // Generate a stream with both audio and video.
217 blink::WebMediaStream desc1 = RequestLocalMediaStream();
218 blink::WebMediaStream desc2 = RequestLocalMediaStream();
219
220 ms_impl_->OnLocalMediaStreamStop(desc2.id().utf8());
221 EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter());
222 EXPECT_EQ(0, ms_dispatcher_->stop_video_device_counter());
223
224 ms_impl_->OnLocalMediaStreamStop(desc1.id().utf8());
225 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
226 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
227 }
228
229 // Test that the source is stopped even if there are two MediaStreams using
230 // the same source.
TEST_F(MediaStreamImplTest,StopSource)231 TEST_F(MediaStreamImplTest, StopSource) {
232 // Generate a stream with both audio and video.
233 blink::WebMediaStream desc1 = RequestLocalMediaStream();
234 blink::WebMediaStream desc2 = RequestLocalMediaStream();
235
236 // Stop the video source.
237 blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
238 desc1.videoTracks(video_tracks);
239 ms_impl_->OnLocalSourceStop(video_tracks[0].source());
240 EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter());
241 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
242
243 // Stop the audio source.
244 blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
245 desc1.audioTracks(audio_tracks);
246 ms_impl_->OnLocalSourceStop(audio_tracks[0].source());
247 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
248 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
249 }
250
251 // Test that the MediaStreams are deleted if the owning WebFrame is deleted.
252 // In the unit test the owning frame is NULL.
TEST_F(MediaStreamImplTest,FrameWillClose)253 TEST_F(MediaStreamImplTest, FrameWillClose) {
254 // Test a stream with both audio and video.
255 blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
256
257 // Test that the MediaStreams are deleted if the owning WebFrame is deleted.
258 // In the unit test the owning frame is NULL.
259 ms_impl_->FrameWillClose(NULL);
260 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
261 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
262 }
263
264 // This test what happens if a source to a MediaSteam fails to start.
TEST_F(MediaStreamImplTest,MediaSourceFailToStart)265 TEST_F(MediaStreamImplTest, MediaSourceFailToStart) {
266 ms_impl_->RequestUserMedia();
267 FakeMediaStreamDispatcherComplete();
268 ChangeVideoSourceStateToEnded();
269 ChangeAudioSourceStateToEnded();
270 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_FAILED,
271 ms_impl_->request_state());
272 EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
273 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
274 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
275 }
276
277 // This test what happens if MediaStreamImpl is deleted while the sources of a
278 // MediaStream is being started.
TEST_F(MediaStreamImplTest,MediaStreamImplShutDown)279 TEST_F(MediaStreamImplTest, MediaStreamImplShutDown) {
280 ms_impl_->RequestUserMedia();
281 FakeMediaStreamDispatcherComplete();
282 EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
283 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE,
284 ms_impl_->request_state());
285 ms_impl_.reset();
286 ChangeAudioSourceStateToLive();
287 ChangeVideoSourceStateToLive();
288 }
289
290 // This test what happens if the WebFrame is closed while the MediaStream is
291 // being generated by the MediaStreamDispatcher.
TEST_F(MediaStreamImplTest,ReloadFrameWhileGeneratingStream)292 TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingStream) {
293 ms_impl_->RequestUserMedia();
294 ms_impl_->FrameWillClose(NULL);
295 EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
296 EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter());
297 EXPECT_EQ(0, ms_dispatcher_->stop_video_device_counter());
298 ChangeAudioSourceStateToLive();
299 ChangeVideoSourceStateToLive();
300 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE,
301 ms_impl_->request_state());
302 }
303
304 // This test what happens if the WebFrame is closed while the sources are being
305 // started by MediaStreamDependencyFactory.
TEST_F(MediaStreamImplTest,ReloadFrameWhileGeneratingSources)306 TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingSources) {
307 ms_impl_->RequestUserMedia();
308 FakeMediaStreamDispatcherComplete();
309 EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
310 ms_impl_->FrameWillClose(NULL);
311 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
312 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
313 ChangeAudioSourceStateToLive();
314 ChangeVideoSourceStateToLive();
315 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE,
316 ms_impl_->request_state());
317 }
318
319 // This test what happens if stop is called on a stream after the frame has
320 // been reloaded.
TEST_F(MediaStreamImplTest,StopStreamAfterReload)321 TEST_F(MediaStreamImplTest, StopStreamAfterReload) {
322 blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
323 EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
324 ms_impl_->FrameWillClose(NULL);
325 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
326 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
327 ms_impl_->OnLocalMediaStreamStop(mixed_desc.id().utf8());
328 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
329 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
330 }
331
332 } // namespace content
333