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 <string> 6 #include <queue> 7 8 #include "base/bind.h" 9 #include "base/callback_helpers.h" 10 #include "base/command_line.h" 11 #include "base/message_loop/message_loop.h" 12 #include "base/run_loop.h" 13 #include "content/browser/browser_thread_impl.h" 14 #include "content/browser/renderer_host/media/audio_input_device_manager.h" 15 #include "content/browser/renderer_host/media/media_stream_dispatcher_host.h" 16 #include "content/browser/renderer_host/media/media_stream_manager.h" 17 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" 18 #include "content/browser/renderer_host/media/video_capture_manager.h" 19 #include "content/common/media/media_stream_messages.h" 20 #include "content/common/media/media_stream_options.h" 21 #include "content/public/browser/media_device_id.h" 22 #include "content/public/common/content_switches.h" 23 #include "content/public/test/mock_resource_context.h" 24 #include "content/public/test/test_browser_context.h" 25 #include "content/public/test/test_browser_thread_bundle.h" 26 #include "content/test/test_content_browser_client.h" 27 #include "content/test/test_content_client.h" 28 #include "ipc/ipc_message_macros.h" 29 #include "media/audio/mock_audio_manager.h" 30 #include "media/base/media_switches.h" 31 #include "media/video/capture/fake_video_capture_device_factory.h" 32 #include "net/url_request/url_request_context.h" 33 #include "testing/gmock/include/gmock/gmock.h" 34 #include "testing/gtest/include/gtest/gtest.h" 35 36 #if defined(OS_CHROMEOS) 37 #include "chromeos/audio/cras_audio_handler.h" 38 #endif 39 40 using ::testing::_; 41 using ::testing::DeleteArg; 42 using ::testing::DoAll; 43 using ::testing::InSequence; 44 using ::testing::Return; 45 using ::testing::SaveArg; 46 47 const int kProcessId = 5; 48 const int kRenderId = 6; 49 const int kPageRequestId = 7; 50 51 namespace content { 52 53 class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, 54 public TestContentBrowserClient { 55 public: 56 MockMediaStreamDispatcherHost( 57 const ResourceContext::SaltCallback salt_callback, 58 const scoped_refptr<base::MessageLoopProxy>& message_loop, 59 MediaStreamManager* manager) 60 : MediaStreamDispatcherHost(kProcessId, salt_callback, manager), 61 message_loop_(message_loop), 62 current_ipc_(NULL) {} 63 64 // A list of mock methods. 65 MOCK_METHOD4(OnStreamGenerated, 66 void(int routing_id, int request_id, int audio_array_size, 67 int video_array_size)); 68 MOCK_METHOD3(OnStreamGenerationFailed, void(int routing_id, 69 int request_id, 70 MediaStreamRequestResult result)); 71 MOCK_METHOD1(OnDeviceStopped, void(int routing_id)); 72 MOCK_METHOD2(OnDeviceOpened, void(int routing_id, int request_id)); 73 74 // Accessor to private functions. 75 void OnGenerateStream(int render_frame_id, 76 int page_request_id, 77 const StreamOptions& components, 78 const GURL& security_origin, 79 const base::Closure& quit_closure) { 80 quit_closures_.push(quit_closure); 81 MediaStreamDispatcherHost::OnGenerateStream( 82 render_frame_id, page_request_id, components, security_origin, false); 83 } 84 85 void OnStopStreamDevice(int render_frame_id, 86 const std::string& device_id) { 87 MediaStreamDispatcherHost::OnStopStreamDevice(render_frame_id, device_id); 88 } 89 90 void OnOpenDevice(int render_frame_id, 91 int page_request_id, 92 const std::string& device_id, 93 MediaStreamType type, 94 const GURL& security_origin, 95 const base::Closure& quit_closure) { 96 quit_closures_.push(quit_closure); 97 MediaStreamDispatcherHost::OnOpenDevice( 98 render_frame_id, page_request_id, device_id, type, security_origin); 99 } 100 101 void OnEnumerateDevices(int render_frame_id, 102 int page_request_id, 103 MediaStreamType type, 104 const GURL& security_origin, 105 const base::Closure& quit_closure) { 106 quit_closures_.push(quit_closure); 107 MediaStreamDispatcherHost::OnEnumerateDevices( 108 render_frame_id, page_request_id, type, security_origin); 109 } 110 111 std::string label_; 112 StreamDeviceInfoArray audio_devices_; 113 StreamDeviceInfoArray video_devices_; 114 StreamDeviceInfo opened_device_; 115 StreamDeviceInfoArray enumerated_devices_; 116 117 private: 118 virtual ~MockMediaStreamDispatcherHost() {} 119 120 // This method is used to dispatch IPC messages to the renderer. We intercept 121 // these messages here and dispatch to our mock methods to verify the 122 // conversation between this object and the renderer. 123 virtual bool Send(IPC::Message* message) OVERRIDE { 124 CHECK(message); 125 current_ipc_ = message; 126 127 // In this method we dispatch the messages to the according handlers as if 128 // we are the renderer. 129 bool handled = true; 130 IPC_BEGIN_MESSAGE_MAP(MockMediaStreamDispatcherHost, *message) 131 IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerated, 132 OnStreamGeneratedInternal) 133 IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerationFailed, 134 OnStreamGenerationFailedInternal) 135 IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceStopped, OnDeviceStoppedInternal) 136 IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpened, OnDeviceOpenedInternal) 137 IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerated, OnDevicesEnumerated) 138 IPC_MESSAGE_UNHANDLED(handled = false) 139 IPC_END_MESSAGE_MAP() 140 EXPECT_TRUE(handled); 141 142 delete message; 143 current_ipc_ = NULL; 144 return true; 145 } 146 147 // These handler methods do minimal things and delegate to the mock methods. 148 void OnStreamGeneratedInternal( 149 int request_id, 150 std::string label, 151 StreamDeviceInfoArray audio_device_list, 152 StreamDeviceInfoArray video_device_list) { 153 OnStreamGenerated(current_ipc_->routing_id(), request_id, 154 audio_device_list.size(), video_device_list.size()); 155 // Notify that the event have occurred. 156 base::Closure quit_closure = quit_closures_.front(); 157 quit_closures_.pop(); 158 message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure)); 159 160 label_ = label; 161 audio_devices_ = audio_device_list; 162 video_devices_ = video_device_list; 163 } 164 165 void OnStreamGenerationFailedInternal( 166 int request_id, 167 content::MediaStreamRequestResult result) { 168 OnStreamGenerationFailed(current_ipc_->routing_id(), request_id, result); 169 if (!quit_closures_.empty()) { 170 base::Closure quit_closure = quit_closures_.front(); 171 quit_closures_.pop(); 172 message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure)); 173 } 174 175 label_= ""; 176 } 177 178 void OnDeviceStoppedInternal(const std::string& label, 179 const content::StreamDeviceInfo& device) { 180 if (IsVideoMediaType(device.device.type)) 181 EXPECT_TRUE(StreamDeviceInfo::IsEqual(device, video_devices_[0])); 182 if (IsAudioInputMediaType(device.device.type)) 183 EXPECT_TRUE(StreamDeviceInfo::IsEqual(device, audio_devices_[0])); 184 185 OnDeviceStopped(current_ipc_->routing_id()); 186 } 187 188 void OnDeviceOpenedInternal(int request_id, 189 const std::string& label, 190 const StreamDeviceInfo& device) { 191 base::Closure quit_closure = quit_closures_.front(); 192 quit_closures_.pop(); 193 message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure)); 194 label_ = label; 195 opened_device_ = device; 196 } 197 198 void OnDevicesEnumerated(int request_id, 199 const StreamDeviceInfoArray& devices) { 200 base::Closure quit_closure = quit_closures_.front(); 201 quit_closures_.pop(); 202 message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure)); 203 enumerated_devices_ = devices; 204 } 205 206 scoped_refptr<base::MessageLoopProxy> message_loop_; 207 IPC::Message* current_ipc_; 208 std::queue<base::Closure> quit_closures_; 209 }; 210 211 class MockMediaStreamUIProxy : public FakeMediaStreamUIProxy { 212 public: 213 MOCK_METHOD2( 214 OnStarted, 215 void(const base::Closure& stop, 216 const MediaStreamUIProxy::WindowIdCallback& window_id_callback)); 217 }; 218 219 class MediaStreamDispatcherHostTest : public testing::Test { 220 public: 221 MediaStreamDispatcherHostTest() 222 : old_browser_client_(NULL), 223 thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), 224 origin_("https://test.com") { 225 audio_manager_.reset( 226 new media::MockAudioManager(base::MessageLoopProxy::current())); 227 // Make sure we use fake devices to avoid long delays. 228 base::CommandLine::ForCurrentProcess()->AppendSwitch( 229 switches::kUseFakeDeviceForMediaStream); 230 // Create our own MediaStreamManager. 231 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); 232 video_capture_device_factory_ = 233 static_cast<media::FakeVideoCaptureDeviceFactory*>( 234 media_stream_manager_->video_capture_manager() 235 ->video_capture_device_factory()); 236 DCHECK(video_capture_device_factory_); 237 238 MockResourceContext* mock_resource_context = 239 static_cast<MockResourceContext*>( 240 browser_context_.GetResourceContext()); 241 242 host_ = new MockMediaStreamDispatcherHost( 243 mock_resource_context->GetMediaDeviceIDSalt(), 244 base::MessageLoopProxy::current(), 245 media_stream_manager_.get()); 246 247 // Use the fake content client and browser. 248 content_client_.reset(new TestContentClient()); 249 SetContentClient(content_client_.get()); 250 old_browser_client_ = SetBrowserClientForTesting(host_.get()); 251 252 #if defined(OS_CHROMEOS) 253 chromeos::CrasAudioHandler::InitializeForTesting(); 254 #endif 255 } 256 257 virtual ~MediaStreamDispatcherHostTest() { 258 #if defined(OS_CHROMEOS) 259 chromeos::CrasAudioHandler::Shutdown(); 260 #endif 261 } 262 263 virtual void SetUp() OVERRIDE { 264 video_capture_device_factory_->GetDeviceNames(&physical_video_devices_); 265 ASSERT_GT(physical_video_devices_.size(), 0u); 266 267 media_stream_manager_->audio_input_device_manager()->GetFakeDeviceNames( 268 &physical_audio_devices_); 269 ASSERT_GT(physical_audio_devices_.size(), 0u); 270 } 271 272 virtual void TearDown() OVERRIDE { 273 host_->OnChannelClosing(); 274 } 275 276 protected: 277 virtual void SetupFakeUI(bool expect_started) { 278 stream_ui_ = new MockMediaStreamUIProxy(); 279 if (expect_started) { 280 EXPECT_CALL(*stream_ui_, OnStarted(_, _)); 281 } 282 media_stream_manager_->UseFakeUI( 283 scoped_ptr<FakeMediaStreamUIProxy>(stream_ui_)); 284 } 285 286 void GenerateStreamAndWaitForResult(int render_frame_id, 287 int page_request_id, 288 const StreamOptions& options) { 289 base::RunLoop run_loop; 290 int expected_audio_array_size = 291 (options.audio_requested && 292 physical_audio_devices_.size() > 0) ? 1 : 0; 293 int expected_video_array_size = 294 (options.video_requested && 295 physical_video_devices_.size() > 0) ? 1 : 0; 296 EXPECT_CALL(*host_.get(), OnStreamGenerated(render_frame_id, 297 page_request_id, 298 expected_audio_array_size, 299 expected_video_array_size)); 300 host_->OnGenerateStream(render_frame_id, page_request_id, options, origin_, 301 run_loop.QuitClosure()); 302 run_loop.Run(); 303 EXPECT_FALSE(DoesContainRawIds(host_->audio_devices_)); 304 EXPECT_FALSE(DoesContainRawIds(host_->video_devices_)); 305 EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->audio_devices_, origin_)); 306 EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->video_devices_, origin_)); 307 } 308 309 void GenerateStreamAndWaitForFailure( 310 int render_frame_id, 311 int page_request_id, 312 const StreamOptions& options, 313 MediaStreamRequestResult expected_result) { 314 base::RunLoop run_loop; 315 EXPECT_CALL(*host_.get(), 316 OnStreamGenerationFailed(render_frame_id, 317 page_request_id, 318 expected_result)); 319 host_->OnGenerateStream(render_frame_id, page_request_id, options, 320 origin_, run_loop.QuitClosure()); 321 run_loop.Run(); 322 } 323 324 void OpenVideoDeviceAndWaitForResult(int render_frame_id, 325 int page_request_id, 326 const std::string& device_id) { 327 base::RunLoop run_loop; 328 host_->OnOpenDevice(render_frame_id, page_request_id, device_id, 329 MEDIA_DEVICE_VIDEO_CAPTURE, origin_, 330 run_loop.QuitClosure()); 331 run_loop.Run(); 332 EXPECT_FALSE(DoesContainRawIds(host_->video_devices_)); 333 EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->video_devices_, origin_)); 334 } 335 336 void EnumerateDevicesAndWaitForResult(int render_frame_id, 337 int page_request_id, 338 MediaStreamType type) { 339 base::RunLoop run_loop; 340 host_->OnEnumerateDevices(render_frame_id, page_request_id, type, origin_, 341 run_loop.QuitClosure()); 342 run_loop.Run(); 343 ASSERT_FALSE(host_->enumerated_devices_.empty()); 344 EXPECT_FALSE(DoesContainRawIds(host_->enumerated_devices_)); 345 EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->enumerated_devices_, origin_)); 346 } 347 348 bool DoesContainRawIds(const StreamDeviceInfoArray& devices) { 349 for (size_t i = 0; i < devices.size(); ++i) { 350 media::AudioDeviceNames::const_iterator audio_it = 351 physical_audio_devices_.begin(); 352 for (; audio_it != physical_audio_devices_.end(); ++audio_it) { 353 if (audio_it->unique_id == devices[i].device.id) 354 return true; 355 } 356 media::VideoCaptureDevice::Names::const_iterator video_it = 357 physical_video_devices_.begin(); 358 for (; video_it != physical_video_devices_.end(); ++video_it) { 359 if (video_it->id() == devices[i].device.id) 360 return true; 361 } 362 } 363 return false; 364 } 365 366 bool DoesEveryDeviceMapToRawId(const StreamDeviceInfoArray& devices, 367 const GURL& origin) { 368 for (size_t i = 0; i < devices.size(); ++i) { 369 bool found_match = false; 370 media::AudioDeviceNames::const_iterator audio_it = 371 physical_audio_devices_.begin(); 372 for (; audio_it != physical_audio_devices_.end(); ++audio_it) { 373 if (content::DoesMediaDeviceIDMatchHMAC( 374 browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), 375 origin, 376 devices[i].device.id, 377 audio_it->unique_id)) { 378 EXPECT_FALSE(found_match); 379 found_match = true; 380 } 381 } 382 media::VideoCaptureDevice::Names::const_iterator video_it = 383 physical_video_devices_.begin(); 384 for (; video_it != physical_video_devices_.end(); ++video_it) { 385 if (content::DoesMediaDeviceIDMatchHMAC( 386 browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), 387 origin, 388 devices[i].device.id, 389 video_it->id())) { 390 EXPECT_FALSE(found_match); 391 found_match = true; 392 } 393 } 394 if (!found_match) 395 return false; 396 } 397 return true; 398 } 399 400 // Returns true if all devices have labels, false otherwise. 401 bool DoesContainLabels(const StreamDeviceInfoArray& devices) { 402 for (size_t i = 0; i < devices.size(); ++i) { 403 if (devices[i].device.name.empty()) 404 return false; 405 } 406 return true; 407 } 408 409 // Returns true if no devices have labels, false otherwise. 410 bool DoesNotContainLabels(const StreamDeviceInfoArray& devices) { 411 for (size_t i = 0; i < devices.size(); ++i) { 412 if (!devices[i].device.name.empty()) 413 return false; 414 } 415 return true; 416 } 417 418 void AddSourceIdConstraint(const std::string& source_id, 419 StreamOptions::Constraints* constraints) { 420 constraints->push_back(StreamOptions::Constraint(kMediaStreamSourceInfoId, 421 source_id)); 422 } 423 424 scoped_refptr<MockMediaStreamDispatcherHost> host_; 425 scoped_ptr<media::AudioManager> audio_manager_; 426 scoped_ptr<MediaStreamManager> media_stream_manager_; 427 MockMediaStreamUIProxy* stream_ui_; 428 ContentBrowserClient* old_browser_client_; 429 scoped_ptr<ContentClient> content_client_; 430 content::TestBrowserThreadBundle thread_bundle_; 431 content::TestBrowserContext browser_context_; 432 media::AudioDeviceNames physical_audio_devices_; 433 media::VideoCaptureDevice::Names physical_video_devices_; 434 GURL origin_; 435 media::FakeVideoCaptureDeviceFactory* video_capture_device_factory_; 436 }; 437 438 TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithVideoOnly) { 439 StreamOptions options(false, true); 440 441 SetupFakeUI(true); 442 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 443 444 EXPECT_EQ(host_->audio_devices_.size(), 0u); 445 EXPECT_EQ(host_->video_devices_.size(), 1u); 446 } 447 448 TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioOnly) { 449 StreamOptions options(true, false); 450 451 SetupFakeUI(true); 452 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 453 454 EXPECT_EQ(host_->audio_devices_.size(), 1u); 455 EXPECT_EQ(host_->video_devices_.size(), 0u); 456 } 457 458 // This test simulates a shutdown scenario: we don't setup a fake UI proxy for 459 // MediaStreamManager, so it will create an ordinary one which will not find 460 // a RenderFrameHostDelegate. This normally should only be the case at shutdown. 461 TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithNothing) { 462 StreamOptions options(false, false); 463 464 GenerateStreamAndWaitForFailure( 465 kRenderId, 466 kPageRequestId, 467 options, 468 MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN); 469 } 470 471 TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioAndVideo) { 472 StreamOptions options(true, true); 473 474 SetupFakeUI(true); 475 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 476 477 EXPECT_EQ(host_->audio_devices_.size(), 1u); 478 EXPECT_EQ(host_->video_devices_.size(), 1u); 479 } 480 481 // This test generates two streams with video only using the same render frame 482 // id. The same capture device with the same device and session id is expected 483 // to be used. 484 TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsFromSameRenderId) { 485 StreamOptions options(false, true); 486 487 // Generate first stream. 488 SetupFakeUI(true); 489 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 490 491 // Check the latest generated stream. 492 EXPECT_EQ(host_->audio_devices_.size(), 0u); 493 EXPECT_EQ(host_->video_devices_.size(), 1u); 494 const std::string label1 = host_->label_; 495 const std::string device_id1 = host_->video_devices_.front().device.id; 496 const int session_id1 = host_->video_devices_.front().session_id; 497 498 // Generate second stream. 499 SetupFakeUI(true); 500 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId + 1, options); 501 502 // Check the latest generated stream. 503 EXPECT_EQ(host_->audio_devices_.size(), 0u); 504 EXPECT_EQ(host_->video_devices_.size(), 1u); 505 const std::string label2 = host_->label_; 506 const std::string device_id2 = host_->video_devices_.front().device.id; 507 int session_id2 = host_->video_devices_.front().session_id; 508 EXPECT_EQ(device_id1, device_id2); 509 EXPECT_EQ(session_id1, session_id2); 510 EXPECT_NE(label1, label2); 511 } 512 513 TEST_F(MediaStreamDispatcherHostTest, 514 GenerateStreamAndOpenDeviceFromSameRenderId) { 515 StreamOptions options(false, true); 516 517 // Generate first stream. 518 SetupFakeUI(true); 519 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 520 521 EXPECT_EQ(host_->audio_devices_.size(), 0u); 522 EXPECT_EQ(host_->video_devices_.size(), 1u); 523 const std::string label1 = host_->label_; 524 const std::string device_id1 = host_->video_devices_.front().device.id; 525 const int session_id1 = host_->video_devices_.front().session_id; 526 527 // Generate second stream. 528 OpenVideoDeviceAndWaitForResult(kRenderId, kPageRequestId, device_id1); 529 530 const std::string device_id2 = host_->opened_device_.device.id; 531 const int session_id2 = host_->opened_device_.session_id; 532 const std::string label2 = host_->label_; 533 534 EXPECT_EQ(device_id1, device_id2); 535 EXPECT_NE(session_id1, session_id2); 536 EXPECT_NE(label1, label2); 537 } 538 539 540 // This test generates two streams with video only using two separate render 541 // frame ids. The same device id but different session ids are expected. 542 TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsDifferentRenderId) { 543 StreamOptions options(false, true); 544 545 // Generate first stream. 546 SetupFakeUI(true); 547 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 548 549 // Check the latest generated stream. 550 EXPECT_EQ(host_->audio_devices_.size(), 0u); 551 EXPECT_EQ(host_->video_devices_.size(), 1u); 552 const std::string label1 = host_->label_; 553 const std::string device_id1 = host_->video_devices_.front().device.id; 554 const int session_id1 = host_->video_devices_.front().session_id; 555 556 // Generate second stream from another render frame. 557 SetupFakeUI(true); 558 GenerateStreamAndWaitForResult(kRenderId+1, kPageRequestId + 1, options); 559 560 // Check the latest generated stream. 561 EXPECT_EQ(host_->audio_devices_.size(), 0u); 562 EXPECT_EQ(host_->video_devices_.size(), 1u); 563 const std::string label2 = host_->label_; 564 const std::string device_id2 = host_->video_devices_.front().device.id; 565 const int session_id2 = host_->video_devices_.front().session_id; 566 EXPECT_EQ(device_id1, device_id2); 567 EXPECT_NE(session_id1, session_id2); 568 EXPECT_NE(label1, label2); 569 } 570 571 // This test request two streams with video only without waiting for the first 572 // stream to be generated before requesting the second. 573 // The same device id and session ids are expected. 574 TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithoutWaiting) { 575 StreamOptions options(false, true); 576 577 // Generate first stream. 578 SetupFakeUI(true); 579 { 580 InSequence s; 581 EXPECT_CALL(*host_.get(), 582 OnStreamGenerated(kRenderId, kPageRequestId, 0, 1)); 583 584 // Generate second stream. 585 EXPECT_CALL(*host_.get(), 586 OnStreamGenerated(kRenderId, kPageRequestId + 1, 0, 1)); 587 } 588 base::RunLoop run_loop1; 589 base::RunLoop run_loop2; 590 host_->OnGenerateStream(kRenderId, kPageRequestId, options, origin_, 591 run_loop1.QuitClosure()); 592 host_->OnGenerateStream(kRenderId, kPageRequestId + 1, options, origin_, 593 run_loop2.QuitClosure()); 594 595 run_loop1.Run(); 596 run_loop2.Run(); 597 } 598 599 // Test that we can generate streams where a mandatory sourceId is specified in 600 // the request. 601 TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithMandatorySourceId) { 602 ASSERT_GE(physical_audio_devices_.size(), 1u); 603 ASSERT_GE(physical_video_devices_.size(), 1u); 604 605 media::AudioDeviceNames::const_iterator audio_it = 606 physical_audio_devices_.begin(); 607 for (; audio_it != physical_audio_devices_.end(); ++audio_it) { 608 std::string source_id = content::GetHMACForMediaDeviceID( 609 browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), 610 origin_, 611 audio_it->unique_id); 612 ASSERT_FALSE(source_id.empty()); 613 StreamOptions options(true, true); 614 AddSourceIdConstraint(source_id, &options.mandatory_audio); 615 616 SetupFakeUI(true); 617 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 618 EXPECT_EQ(host_->audio_devices_[0].device.id, source_id); 619 } 620 621 media::VideoCaptureDevice::Names::const_iterator video_it = 622 physical_video_devices_.begin(); 623 for (; video_it != physical_video_devices_.end(); ++video_it) { 624 std::string source_id = content::GetHMACForMediaDeviceID( 625 browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), 626 origin_, 627 video_it->id()); 628 ASSERT_FALSE(source_id.empty()); 629 StreamOptions options(true, true); 630 AddSourceIdConstraint(source_id, &options.mandatory_video); 631 632 SetupFakeUI(true); 633 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 634 EXPECT_EQ(host_->video_devices_[0].device.id, source_id); 635 } 636 } 637 638 // Test that we can generate streams where a optional sourceId is specified in 639 // the request. 640 TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithOptionalSourceId) { 641 ASSERT_GE(physical_audio_devices_.size(), 1u); 642 ASSERT_GE(physical_video_devices_.size(), 1u); 643 644 media::AudioDeviceNames::const_iterator audio_it = 645 physical_audio_devices_.begin(); 646 for (; audio_it != physical_audio_devices_.end(); ++audio_it) { 647 std::string source_id = content::GetHMACForMediaDeviceID( 648 browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), 649 origin_, 650 audio_it->unique_id); 651 ASSERT_FALSE(source_id.empty()); 652 StreamOptions options(true, true); 653 AddSourceIdConstraint(source_id, &options.optional_audio); 654 655 SetupFakeUI(true); 656 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 657 EXPECT_EQ(host_->audio_devices_[0].device.id, source_id); 658 } 659 660 media::VideoCaptureDevice::Names::const_iterator video_it = 661 physical_video_devices_.begin(); 662 for (; video_it != physical_video_devices_.end(); ++video_it) { 663 std::string source_id = content::GetHMACForMediaDeviceID( 664 browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), 665 origin_, 666 video_it->id()); 667 ASSERT_FALSE(source_id.empty()); 668 StreamOptions options(true, true); 669 AddSourceIdConstraint(source_id, &options.optional_video); 670 671 SetupFakeUI(true); 672 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 673 EXPECT_EQ(host_->video_devices_[0].device.id, source_id); 674 } 675 } 676 677 // Test that generating a stream with an invalid mandatory video source id fail. 678 TEST_F(MediaStreamDispatcherHostTest, 679 GenerateStreamsWithInvalidMandatoryVideoSourceId) { 680 StreamOptions options(true, true); 681 AddSourceIdConstraint("invalid source id", &options.mandatory_video); 682 683 GenerateStreamAndWaitForFailure( 684 kRenderId, 685 kPageRequestId, 686 options, 687 MEDIA_DEVICE_NO_HARDWARE); 688 } 689 690 // Test that generating a stream with an invalid mandatory audio source id fail. 691 TEST_F(MediaStreamDispatcherHostTest, 692 GenerateStreamsWithInvalidMandatoryAudioSourceId) { 693 StreamOptions options(true, true); 694 AddSourceIdConstraint("invalid source id", &options.mandatory_audio); 695 696 GenerateStreamAndWaitForFailure( 697 kRenderId, 698 kPageRequestId, 699 options, 700 MEDIA_DEVICE_NO_HARDWARE); 701 } 702 703 // Test that generating a stream with an invalid optional video source id 704 // succeed. 705 TEST_F(MediaStreamDispatcherHostTest, 706 GenerateStreamsWithInvalidOptionalVideoSourceId) { 707 StreamOptions options(true, true); 708 AddSourceIdConstraint("invalid source id", &options.optional_video); 709 710 SetupFakeUI(true); 711 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 712 } 713 714 // Test that generating a stream with an invalid optional audio source id 715 // succeed. 716 TEST_F(MediaStreamDispatcherHostTest, 717 GenerateStreamsWithInvalidOptionalAudioSourceId) { 718 StreamOptions options(true, true); 719 AddSourceIdConstraint("invalid source id", &options.optional_audio); 720 721 SetupFakeUI(true); 722 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 723 } 724 725 TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsNoAvailableVideoDevice) { 726 physical_video_devices_.clear(); 727 video_capture_device_factory_->set_number_of_devices(0); 728 video_capture_device_factory_->GetDeviceNames(&physical_video_devices_); 729 StreamOptions options(true, true); 730 731 SetupFakeUI(false); 732 GenerateStreamAndWaitForFailure(kRenderId, kPageRequestId, options, 733 MEDIA_DEVICE_NO_HARDWARE); 734 } 735 736 // Test that if a OnStopStreamDevice message is received for a device that has 737 // been opened in a MediaStream and by pepper, the device is only stopped for 738 // the MediaStream. 739 TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStream) { 740 StreamOptions options(false, true); 741 742 SetupFakeUI(true); 743 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 744 745 std::string stream_request_label = host_->label_; 746 StreamDeviceInfo video_device_info = host_->video_devices_.front(); 747 ASSERT_EQ(1u, media_stream_manager_->GetDevicesOpenedByRequest( 748 stream_request_label).size()); 749 750 // Open the same device by Pepper. 751 OpenVideoDeviceAndWaitForResult(kRenderId, kPageRequestId, 752 video_device_info.device.id); 753 std::string open_device_request_label = host_->label_; 754 755 // Stop the device in the MediaStream. 756 host_->OnStopStreamDevice(kRenderId, video_device_info.device.id); 757 758 EXPECT_EQ(0u, media_stream_manager_->GetDevicesOpenedByRequest( 759 stream_request_label).size()); 760 EXPECT_EQ(1u, media_stream_manager_->GetDevicesOpenedByRequest( 761 open_device_request_label).size()); 762 } 763 764 TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStreamAndRestart) { 765 StreamOptions options(true, true); 766 767 SetupFakeUI(true); 768 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 769 770 std::string request_label1 = host_->label_; 771 StreamDeviceInfo video_device_info = host_->video_devices_.front(); 772 // Expect that 1 audio and 1 video device has been opened. 773 EXPECT_EQ(2u, media_stream_manager_->GetDevicesOpenedByRequest( 774 request_label1).size()); 775 776 host_->OnStopStreamDevice(kRenderId, video_device_info.device.id); 777 EXPECT_EQ(1u, media_stream_manager_->GetDevicesOpenedByRequest( 778 request_label1).size()); 779 780 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 781 std::string request_label2 = host_->label_; 782 783 StreamDeviceInfoArray request1_devices = 784 media_stream_manager_->GetDevicesOpenedByRequest(request_label1); 785 StreamDeviceInfoArray request2_devices = 786 media_stream_manager_->GetDevicesOpenedByRequest(request_label2); 787 788 ASSERT_EQ(1u, request1_devices.size()); 789 ASSERT_EQ(2u, request2_devices.size()); 790 791 // Test that the same audio device has been opened in both streams. 792 EXPECT_TRUE(StreamDeviceInfo::IsEqual(request1_devices[0], 793 request2_devices[0]) || 794 StreamDeviceInfo::IsEqual(request1_devices[0], 795 request2_devices[1])); 796 } 797 798 TEST_F(MediaStreamDispatcherHostTest, 799 GenerateTwoStreamsAndStopDeviceWhileWaitingForSecondStream) { 800 StreamOptions options(false, true); 801 802 SetupFakeUI(true); 803 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 804 EXPECT_EQ(host_->video_devices_.size(), 1u); 805 806 // Generate a second stream. 807 EXPECT_CALL(*host_.get(), 808 OnStreamGenerated(kRenderId, kPageRequestId + 1, 0, 1)); 809 810 base::RunLoop run_loop1; 811 host_->OnGenerateStream(kRenderId, kPageRequestId + 1, options, origin_, 812 run_loop1.QuitClosure()); 813 814 // Stop the video stream device from stream 1 while waiting for the 815 // second stream to be generated. 816 host_->OnStopStreamDevice(kRenderId, host_->video_devices_[0].device.id); 817 run_loop1.Run(); 818 819 EXPECT_EQ(host_->video_devices_.size(), 1u); 820 } 821 822 TEST_F(MediaStreamDispatcherHostTest, CancelPendingStreamsOnChannelClosing) { 823 StreamOptions options(false, true); 824 825 base::RunLoop run_loop; 826 827 // Create multiple GenerateStream requests. 828 size_t streams = 5; 829 for (size_t i = 1; i <= streams; ++i) { 830 host_->OnGenerateStream(kRenderId, kPageRequestId + i, options, origin_, 831 run_loop.QuitClosure()); 832 } 833 834 // Calling OnChannelClosing() to cancel all the pending requests. 835 host_->OnChannelClosing(); 836 run_loop.RunUntilIdle(); 837 } 838 839 TEST_F(MediaStreamDispatcherHostTest, StopGeneratedStreamsOnChannelClosing) { 840 StreamOptions options(false, true); 841 842 // Create first group of streams. 843 size_t generated_streams = 3; 844 for (size_t i = 0; i < generated_streams; ++i) { 845 SetupFakeUI(true); 846 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId + i, options); 847 } 848 849 // Calling OnChannelClosing() to cancel all the pending/generated streams. 850 host_->OnChannelClosing(); 851 base::RunLoop().RunUntilIdle(); 852 } 853 854 TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) { 855 StreamOptions options(false, true); 856 857 base::Closure close_callback; 858 scoped_ptr<MockMediaStreamUIProxy> stream_ui(new MockMediaStreamUIProxy()); 859 EXPECT_CALL(*stream_ui, OnStarted(_, _)) 860 .WillOnce(SaveArg<0>(&close_callback)); 861 media_stream_manager_->UseFakeUI(stream_ui.PassAs<FakeMediaStreamUIProxy>()); 862 863 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 864 865 EXPECT_EQ(host_->audio_devices_.size(), 0u); 866 EXPECT_EQ(host_->video_devices_.size(), 1u); 867 868 ASSERT_FALSE(close_callback.is_null()); 869 EXPECT_CALL(*host_.get(), OnDeviceStopped(kRenderId)); 870 close_callback.Run(); 871 base::RunLoop().RunUntilIdle(); 872 } 873 874 // Test that the dispatcher is notified if a video device that is in use is 875 // being unplugged. 876 TEST_F(MediaStreamDispatcherHostTest, VideoDeviceUnplugged) { 877 StreamOptions options(true, true); 878 SetupFakeUI(true); 879 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 880 EXPECT_EQ(host_->audio_devices_.size(), 1u); 881 EXPECT_EQ(host_->video_devices_.size(), 1u); 882 883 video_capture_device_factory_->set_number_of_devices(0); 884 885 base::RunLoop run_loop; 886 EXPECT_CALL(*host_.get(), OnDeviceStopped(kRenderId)) 887 .WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); 888 media_stream_manager_->OnDevicesChanged( 889 base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE); 890 891 run_loop.Run(); 892 } 893 894 TEST_F(MediaStreamDispatcherHostTest, EnumerateAudioDevices) { 895 SetupFakeUI(false); 896 EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId, 897 MEDIA_DEVICE_AUDIO_CAPTURE); 898 EXPECT_TRUE(DoesContainLabels(host_->enumerated_devices_)); 899 } 900 901 TEST_F(MediaStreamDispatcherHostTest, EnumerateVideoDevices) { 902 SetupFakeUI(false); 903 EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId, 904 MEDIA_DEVICE_VIDEO_CAPTURE); 905 EXPECT_TRUE(DoesContainLabels(host_->enumerated_devices_)); 906 } 907 908 TEST_F(MediaStreamDispatcherHostTest, EnumerateAudioDevicesNoAccess) { 909 SetupFakeUI(false); 910 stream_ui_->SetMicAccess(false); 911 EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId, 912 MEDIA_DEVICE_AUDIO_CAPTURE); 913 EXPECT_TRUE(DoesNotContainLabels(host_->enumerated_devices_)); 914 } 915 916 TEST_F(MediaStreamDispatcherHostTest, EnumerateVideoDevicesNoAccess) { 917 SetupFakeUI(false); 918 stream_ui_->SetCameraAccess(false); 919 EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId, 920 MEDIA_DEVICE_VIDEO_CAPTURE); 921 EXPECT_TRUE(DoesNotContainLabels(host_->enumerated_devices_)); 922 } 923 924 }; // namespace content 925