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