Home | History | Annotate | Download | only in media
      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