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/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" 22 23 namespace content { 24 25 class MockMediaStreamVideoCapturerSource : public MockMediaStreamVideoSource { 26 public: 27 MockMediaStreamVideoCapturerSource( 28 const StreamDeviceInfo& device, 29 const SourceStoppedCallback& stop_callback, 30 PeerConnectionDependencyFactory* factory) 31 : MockMediaStreamVideoSource(false) { 32 SetDeviceInfo(device); 33 SetStopCallback(stop_callback); 34 } 35 }; 36 37 class MediaStreamImplUnderTest : public MediaStreamImpl { 38 public: 39 enum RequestState { 40 REQUEST_NOT_STARTED, 41 REQUEST_NOT_COMPLETE, 42 REQUEST_SUCCEEDED, 43 REQUEST_FAILED, 44 }; 45 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), 52 video_source_(NULL) { 53 } 54 55 void RequestUserMedia() { 56 blink::WebUserMediaRequest user_media_request; 57 state_ = REQUEST_NOT_COMPLETE; 58 requestUserMedia(user_media_request); 59 } 60 61 void RequestMediaDevices() { 62 blink::WebMediaDevicesRequest media_devices_request; 63 state_ = REQUEST_NOT_COMPLETE; 64 requestMediaDevices(media_devices_request); 65 } 66 67 virtual void GetUserMediaRequestSucceeded( 68 const blink::WebMediaStream& stream, 69 blink::WebUserMediaRequest* request_info) OVERRIDE { 70 last_generated_stream_ = stream; 71 state_ = REQUEST_SUCCEEDED; 72 } 73 74 virtual void GetUserMediaRequestFailed( 75 blink::WebUserMediaRequest* request_info, 76 content::MediaStreamRequestResult result) OVERRIDE { 77 last_generated_stream_.reset(); 78 state_ = REQUEST_FAILED; 79 result_ = result; 80 } 81 82 virtual void EnumerateDevicesSucceded( 83 blink::WebMediaDevicesRequest* request, 84 blink::WebVector<blink::WebMediaDeviceInfo>& devices) OVERRIDE { 85 state_ = REQUEST_SUCCEEDED; 86 last_devices_ = devices; 87 } 88 89 virtual MediaStreamVideoSource* CreateVideoSource( 90 const StreamDeviceInfo& device, 91 const MediaStreamSource::SourceStoppedCallback& stop_callback) OVERRIDE { 92 video_source_ = new MockMediaStreamVideoCapturerSource(device, 93 stop_callback, 94 factory_); 95 return video_source_; 96 } 97 98 const blink::WebMediaStream& last_generated_stream() { 99 return last_generated_stream_; 100 } 101 102 const blink::WebVector<blink::WebMediaDeviceInfo>& last_devices() { 103 return last_devices_; 104 } 105 106 void ClearLastGeneratedStream() { 107 last_generated_stream_.reset(); 108 } 109 110 MockMediaStreamVideoCapturerSource* last_created_video_source() const { 111 return video_source_; 112 } 113 114 RequestState request_state() const { return state_; } 115 content::MediaStreamRequestResult error_reason() const { return result_; } 116 117 private: 118 blink::WebMediaStream last_generated_stream_; 119 RequestState state_; 120 content::MediaStreamRequestResult result_; 121 blink::WebVector<blink::WebMediaDeviceInfo> last_devices_; 122 PeerConnectionDependencyFactory* factory_; 123 MockMediaStreamVideoCapturerSource* video_source_; 124 }; 125 126 class MediaStreamImplTest : public ::testing::Test { 127 public: 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())); 135 } 136 137 blink::WebMediaStream RequestLocalMediaStream() { 138 ms_impl_->RequestUserMedia(); 139 FakeMediaStreamDispatcherRequestUserMediaComplete(); 140 StartMockedVideoSource(); 141 142 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_SUCCEEDED, 143 ms_impl_->request_state()); 144 145 blink::WebMediaStream desc = ms_impl_->last_generated_stream(); 146 content::MediaStream* native_stream = 147 content::MediaStream::GetMediaStream(desc); 148 if (!native_stream) { 149 ADD_FAILURE(); 150 return desc; 151 } 152 153 blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; 154 desc.audioTracks(audio_tracks); 155 blink::WebVector<blink::WebMediaStreamTrack> video_tracks; 156 desc.videoTracks(video_tracks); 157 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()); 161 return desc; 162 } 163 164 void FakeMediaStreamDispatcherRequestUserMediaComplete() { 165 // Audio request ID is used as the shared request ID. 166 ms_impl_->OnStreamGenerated(ms_dispatcher_->audio_input_request_id(), 167 ms_dispatcher_->stream_label(), 168 ms_dispatcher_->audio_input_array(), 169 ms_dispatcher_->video_array()); 170 } 171 172 void FakeMediaStreamDispatcherRequestMediaDevicesComplete() { 173 ms_impl_->OnDevicesEnumerated(ms_dispatcher_->audio_input_request_id(), 174 ms_dispatcher_->audio_input_array()); 175 ms_impl_->OnDevicesEnumerated(ms_dispatcher_->audio_output_request_id(), 176 ms_dispatcher_->audio_output_array()); 177 ms_impl_->OnDevicesEnumerated(ms_dispatcher_->video_request_id(), 178 ms_dispatcher_->video_array()); 179 } 180 181 void StartMockedVideoSource() { 182 MockMediaStreamVideoCapturerSource* video_source = 183 ms_impl_->last_created_video_source(); 184 if (video_source->SourceHasAttemptedToStart()) 185 video_source->StartMockedSource(); 186 } 187 188 void FailToStartMockedVideoSource() { 189 MockMediaStreamVideoCapturerSource* video_source = 190 ms_impl_->last_created_video_source(); 191 if (video_source->SourceHasAttemptedToStart()) 192 video_source->FailToStartMockedSource(); 193 } 194 195 void FailToCreateNextAudioCapturer() { 196 dependency_factory_->FailToCreateNextAudioCapturer(); 197 } 198 199 protected: 200 base::MessageLoop message_loop_; 201 scoped_ptr<ChildProcess> child_process_; 202 scoped_ptr<MockMediaStreamDispatcher> ms_dispatcher_; 203 scoped_ptr<MediaStreamImplUnderTest> ms_impl_; 204 scoped_ptr<MockPeerConnectionDependencyFactory> dependency_factory_; 205 }; 206 207 TEST_F(MediaStreamImplTest, GenerateMediaStream) { 208 // Generate a stream with both audio and video. 209 blink::WebMediaStream mixed_desc = RequestLocalMediaStream(); 210 } 211 212 // Test that the same source object is used if two MediaStreams are generated 213 // using the same source. 214 TEST_F(MediaStreamImplTest, GenerateTwoMediaStreamsWithSameSource) { 215 blink::WebMediaStream desc1 = RequestLocalMediaStream(); 216 blink::WebMediaStream desc2 = RequestLocalMediaStream(); 217 218 blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks; 219 desc1.videoTracks(desc1_video_tracks); 220 blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks; 221 desc2.videoTracks(desc2_video_tracks); 222 EXPECT_EQ(desc1_video_tracks[0].source().id(), 223 desc2_video_tracks[0].source().id()); 224 225 EXPECT_EQ(desc1_video_tracks[0].source().extraData(), 226 desc2_video_tracks[0].source().extraData()); 227 228 blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks; 229 desc1.audioTracks(desc1_audio_tracks); 230 blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks; 231 desc2.audioTracks(desc2_audio_tracks); 232 EXPECT_EQ(desc1_audio_tracks[0].source().id(), 233 desc2_audio_tracks[0].source().id()); 234 235 EXPECT_EQ(desc1_audio_tracks[0].source().extraData(), 236 desc2_audio_tracks[0].source().extraData()); 237 } 238 239 // Test that the same source object is not used if two MediaStreams are 240 // generated using different sources. 241 TEST_F(MediaStreamImplTest, GenerateTwoMediaStreamsWithDifferentSources) { 242 blink::WebMediaStream desc1 = RequestLocalMediaStream(); 243 // Make sure another device is selected (another |session_id|) in the next 244 // gUM request. 245 ms_dispatcher_->IncrementSessionId(); 246 blink::WebMediaStream desc2 = RequestLocalMediaStream(); 247 248 blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks; 249 desc1.videoTracks(desc1_video_tracks); 250 blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks; 251 desc2.videoTracks(desc2_video_tracks); 252 EXPECT_NE(desc1_video_tracks[0].source().id(), 253 desc2_video_tracks[0].source().id()); 254 255 EXPECT_NE(desc1_video_tracks[0].source().extraData(), 256 desc2_video_tracks[0].source().extraData()); 257 258 blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks; 259 desc1.audioTracks(desc1_audio_tracks); 260 blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks; 261 desc2.audioTracks(desc2_audio_tracks); 262 EXPECT_NE(desc1_audio_tracks[0].source().id(), 263 desc2_audio_tracks[0].source().id()); 264 265 EXPECT_NE(desc1_audio_tracks[0].source().extraData(), 266 desc2_audio_tracks[0].source().extraData()); 267 } 268 269 TEST_F(MediaStreamImplTest, StopLocalTracks) { 270 // Generate a stream with both audio and video. 271 blink::WebMediaStream mixed_desc = RequestLocalMediaStream(); 272 273 blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; 274 mixed_desc.audioTracks(audio_tracks); 275 MediaStreamTrack* audio_track = MediaStreamTrack::GetTrack(audio_tracks[0]); 276 audio_track->Stop(); 277 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); 278 279 blink::WebVector<blink::WebMediaStreamTrack> video_tracks; 280 mixed_desc.videoTracks(video_tracks); 281 MediaStreamTrack* video_track = MediaStreamTrack::GetTrack(video_tracks[0]); 282 video_track->Stop(); 283 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); 284 } 285 286 // This test that a source is not stopped even if the tracks in a 287 // MediaStream is stopped if there are two MediaStreams with tracks using the 288 // same device. The source is stopped 289 // if there are no more MediaStream tracks using the device. 290 TEST_F(MediaStreamImplTest, StopLocalTracksWhenTwoStreamUseSameDevices) { 291 // Generate a stream with both audio and video. 292 blink::WebMediaStream desc1 = RequestLocalMediaStream(); 293 blink::WebMediaStream desc2 = RequestLocalMediaStream(); 294 295 blink::WebVector<blink::WebMediaStreamTrack> audio_tracks1; 296 desc1.audioTracks(audio_tracks1); 297 MediaStreamTrack* audio_track1 = MediaStreamTrack::GetTrack(audio_tracks1[0]); 298 audio_track1->Stop(); 299 EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter()); 300 301 blink::WebVector<blink::WebMediaStreamTrack> audio_tracks2; 302 desc2.audioTracks(audio_tracks2); 303 MediaStreamTrack* audio_track2 = MediaStreamTrack::GetTrack(audio_tracks2[0]); 304 audio_track2->Stop(); 305 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); 306 307 blink::WebVector<blink::WebMediaStreamTrack> video_tracks1; 308 desc1.videoTracks(video_tracks1); 309 MediaStreamTrack* video_track1 = MediaStreamTrack::GetTrack(video_tracks1[0]); 310 video_track1->Stop(); 311 EXPECT_EQ(0, ms_dispatcher_->stop_video_device_counter()); 312 313 blink::WebVector<blink::WebMediaStreamTrack> video_tracks2; 314 desc2.videoTracks(video_tracks2); 315 MediaStreamTrack* video_track2 = MediaStreamTrack::GetTrack(video_tracks2[0]); 316 video_track2->Stop(); 317 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); 318 } 319 320 TEST_F(MediaStreamImplTest, StopSourceWhenMediaStreamGoesOutOfScope) { 321 // Generate a stream with both audio and video. 322 RequestLocalMediaStream(); 323 // Makes sure the test itself don't hold a reference to the created 324 // MediaStream. 325 ms_impl_->ClearLastGeneratedStream(); 326 327 // Expect the sources to be stopped when the MediaStream goes out of scope. 328 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); 329 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); 330 } 331 332 // Test that the MediaStreams are deleted if the owning WebFrame is deleted. 333 // In the unit test the owning frame is NULL. 334 TEST_F(MediaStreamImplTest, FrameWillClose) { 335 // Test a stream with both audio and video. 336 blink::WebMediaStream mixed_desc = RequestLocalMediaStream(); 337 blink::WebMediaStream desc2 = RequestLocalMediaStream(); 338 339 // Test that the MediaStreams are deleted if the owning WebFrame is deleted. 340 // In the unit test the owning frame is NULL. 341 ms_impl_->FrameWillClose(NULL); 342 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); 343 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); 344 } 345 346 // This test what happens if a video source to a MediaSteam fails to start. 347 TEST_F(MediaStreamImplTest, MediaVideoSourceFailToStart) { 348 ms_impl_->RequestUserMedia(); 349 FakeMediaStreamDispatcherRequestUserMediaComplete(); 350 FailToStartMockedVideoSource(); 351 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_FAILED, 352 ms_impl_->request_state()); 353 EXPECT_EQ(MEDIA_DEVICE_TRACK_START_FAILURE, 354 ms_impl_->error_reason()); 355 EXPECT_EQ(1, ms_dispatcher_->request_stream_counter()); 356 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); 357 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); 358 } 359 360 // This test what happens if an audio source fail to initialize. 361 TEST_F(MediaStreamImplTest, MediaAudioSourceFailToInitialize) { 362 FailToCreateNextAudioCapturer(); 363 ms_impl_->RequestUserMedia(); 364 FakeMediaStreamDispatcherRequestUserMediaComplete(); 365 StartMockedVideoSource(); 366 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_FAILED, 367 ms_impl_->request_state()); 368 EXPECT_EQ(MEDIA_DEVICE_TRACK_START_FAILURE, 369 ms_impl_->error_reason()); 370 EXPECT_EQ(1, ms_dispatcher_->request_stream_counter()); 371 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); 372 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); 373 } 374 375 // This test what happens if MediaStreamImpl is deleted before a source has 376 // started. 377 TEST_F(MediaStreamImplTest, MediaStreamImplShutDown) { 378 ms_impl_->RequestUserMedia(); 379 FakeMediaStreamDispatcherRequestUserMediaComplete(); 380 EXPECT_EQ(1, ms_dispatcher_->request_stream_counter()); 381 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE, 382 ms_impl_->request_state()); 383 ms_impl_.reset(); 384 } 385 386 // This test what happens if the WebFrame is closed while the MediaStream is 387 // being generated by the MediaStreamDispatcher. 388 TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingStream) { 389 ms_impl_->RequestUserMedia(); 390 ms_impl_->FrameWillClose(NULL); 391 EXPECT_EQ(1, ms_dispatcher_->request_stream_counter()); 392 EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter()); 393 EXPECT_EQ(0, ms_dispatcher_->stop_video_device_counter()); 394 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE, 395 ms_impl_->request_state()); 396 } 397 398 // This test what happens if the WebFrame is closed while the sources are being 399 // started. 400 TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingSources) { 401 ms_impl_->RequestUserMedia(); 402 FakeMediaStreamDispatcherRequestUserMediaComplete(); 403 EXPECT_EQ(1, ms_dispatcher_->request_stream_counter()); 404 ms_impl_->FrameWillClose(NULL); 405 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); 406 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); 407 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE, 408 ms_impl_->request_state()); 409 } 410 411 // This test what happens if stop is called on a track after the frame has 412 // been reloaded. 413 TEST_F(MediaStreamImplTest, StopTrackAfterReload) { 414 blink::WebMediaStream mixed_desc = RequestLocalMediaStream(); 415 EXPECT_EQ(1, ms_dispatcher_->request_stream_counter()); 416 ms_impl_->FrameWillClose(NULL); 417 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); 418 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); 419 420 blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; 421 mixed_desc.audioTracks(audio_tracks); 422 MediaStreamTrack* audio_track = MediaStreamTrack::GetTrack(audio_tracks[0]); 423 audio_track->Stop(); 424 EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); 425 426 blink::WebVector<blink::WebMediaStreamTrack> video_tracks; 427 mixed_desc.videoTracks(video_tracks); 428 MediaStreamTrack* video_track = MediaStreamTrack::GetTrack(video_tracks[0]); 429 video_track->Stop(); 430 EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); 431 } 432 433 TEST_F(MediaStreamImplTest, EnumerateMediaDevices) { 434 ms_impl_->RequestMediaDevices(); 435 FakeMediaStreamDispatcherRequestMediaDevicesComplete(); 436 437 EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_SUCCEEDED, 438 ms_impl_->request_state()); 439 440 // Audio input device with matched output ID. 441 EXPECT_FALSE(ms_impl_->last_devices()[0].deviceId().isEmpty()); 442 EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindAudioInput, 443 ms_impl_->last_devices()[0].kind()); 444 EXPECT_FALSE(ms_impl_->last_devices()[0].label().isEmpty()); 445 EXPECT_FALSE(ms_impl_->last_devices()[0].groupId().isEmpty()); 446 447 // Audio input device without matched output ID. 448 EXPECT_FALSE(ms_impl_->last_devices()[1].deviceId().isEmpty()); 449 EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindAudioInput, 450 ms_impl_->last_devices()[1].kind()); 451 EXPECT_FALSE(ms_impl_->last_devices()[1].label().isEmpty()); 452 EXPECT_FALSE(ms_impl_->last_devices()[1].groupId().isEmpty()); 453 454 // Video input device. 455 EXPECT_FALSE(ms_impl_->last_devices()[2].deviceId().isEmpty()); 456 EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindVideoInput, 457 ms_impl_->last_devices()[2].kind()); 458 EXPECT_FALSE(ms_impl_->last_devices()[2].label().isEmpty()); 459 EXPECT_TRUE(ms_impl_->last_devices()[2].groupId().isEmpty()); 460 461 // Audio output device. 462 EXPECT_FALSE(ms_impl_->last_devices()[3].deviceId().isEmpty()); 463 EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindAudioOutput, 464 ms_impl_->last_devices()[3].kind()); 465 EXPECT_FALSE(ms_impl_->last_devices()[3].label().isEmpty()); 466 EXPECT_FALSE(ms_impl_->last_devices()[3].groupId().isEmpty()); 467 468 // Verfify group IDs. 469 EXPECT_TRUE(ms_impl_->last_devices()[0].groupId().equals( 470 ms_impl_->last_devices()[3].groupId())); 471 EXPECT_FALSE(ms_impl_->last_devices()[1].groupId().equals( 472 ms_impl_->last_devices()[3].groupId())); 473 } 474 475 } // namespace content 476