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 
      7 #include "base/memory/ref_counted.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "base/strings/string_number_conversions.h"
     11 #include "content/common/media/media_stream_messages.h"
     12 #include "content/public/common/media_stream_request.h"
     13 #include "content/renderer/media/media_stream_dispatcher.h"
     14 #include "content/renderer/media/media_stream_dispatcher_eventhandler.h"
     15 #include "media/audio/audio_parameters.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 #include "url/gurl.h"
     18 
     19 namespace content {
     20 namespace {
     21 
     22 const int kRouteId = 0;
     23 const int kAudioSessionId = 3;
     24 const int kVideoSessionId = 5;
     25 const int kRequestId1 = 10;
     26 const int kRequestId2 = 20;
     27 const int kRequestId3 = 30;
     28 const int kRequestId4 = 40;
     29 
     30 const MediaStreamType kAudioType = MEDIA_DEVICE_AUDIO_CAPTURE;
     31 const MediaStreamType kVideoType = MEDIA_DEVICE_VIDEO_CAPTURE;
     32 
     33 class MockMediaStreamDispatcherEventHandler
     34     : public MediaStreamDispatcherEventHandler,
     35       public base::SupportsWeakPtr<MockMediaStreamDispatcherEventHandler> {
     36  public:
     37   MockMediaStreamDispatcherEventHandler()
     38       : request_id_(-1) {}
     39 
     40   virtual void OnStreamGenerated(
     41       int request_id,
     42       const std::string &label,
     43       const StreamDeviceInfoArray& audio_device_array,
     44       const StreamDeviceInfoArray& video_device_array) OVERRIDE {
     45     request_id_ = request_id;
     46     label_ = label;
     47     if (audio_device_array.size()) {
     48       DCHECK(audio_device_array.size() == 1);
     49       audio_device_ = audio_device_array[0];
     50     }
     51     if (video_device_array.size()) {
     52       DCHECK(video_device_array.size() == 1);
     53       video_device_ = video_device_array[0];
     54     }
     55   }
     56 
     57   virtual void OnStreamGenerationFailed(
     58       int request_id,
     59       content::MediaStreamRequestResult result) OVERRIDE {
     60     request_id_ = request_id;
     61   }
     62 
     63   virtual void OnDeviceStopped(const std::string& label,
     64                                const StreamDeviceInfo& device_info) OVERRIDE {
     65     device_stopped_label_ = label;
     66     if (IsVideoMediaType(device_info.device.type)) {
     67       EXPECT_TRUE(StreamDeviceInfo::IsEqual(video_device_, device_info));
     68     }
     69     if (IsAudioInputMediaType(device_info.device.type)) {
     70       EXPECT_TRUE(StreamDeviceInfo::IsEqual(audio_device_, device_info));
     71     }
     72   }
     73 
     74   virtual void OnDevicesEnumerated(
     75       int request_id,
     76       const StreamDeviceInfoArray& device_array) OVERRIDE {
     77     request_id_ = request_id;
     78   }
     79 
     80   virtual void OnDeviceOpened(
     81       int request_id,
     82       const std::string& label,
     83       const StreamDeviceInfo& video_device) OVERRIDE {
     84     request_id_ = request_id;
     85     label_ = label;
     86   }
     87 
     88   virtual void OnDeviceOpenFailed(int request_id) OVERRIDE {
     89     request_id_ = request_id;
     90   }
     91 
     92   void ResetStoredParameters() {
     93     request_id_ = -1;
     94     label_ = "";
     95     device_stopped_label_ = "";
     96     audio_device_ = StreamDeviceInfo();
     97     video_device_ = StreamDeviceInfo();
     98   }
     99 
    100   int request_id_;
    101   std::string label_;
    102   std::string device_stopped_label_;
    103   StreamDeviceInfo audio_device_;
    104   StreamDeviceInfo video_device_;
    105 };
    106 
    107 class MediaStreamDispatcherUnderTest : public MediaStreamDispatcher {
    108  public:
    109   MediaStreamDispatcherUnderTest() : MediaStreamDispatcher(NULL) {}
    110 
    111   using MediaStreamDispatcher::GetNextIpcIdForTest;
    112   using RenderFrameObserver::OnMessageReceived;
    113 };
    114 
    115 class MediaStreamDispatcherTest : public ::testing::Test {
    116  public:
    117   MediaStreamDispatcherTest()
    118       : dispatcher_(new MediaStreamDispatcherUnderTest()),
    119         handler_(new MockMediaStreamDispatcherEventHandler),
    120         security_origin_("http://test.com"),
    121         request_id_(10) {
    122   }
    123 
    124   // Generates a request for a MediaStream and returns the request id that is
    125   // used in IPC. Use this returned id in CompleteGenerateStream to identify
    126   // the request.
    127   int GenerateStream(const StreamOptions& options, int request_id) {
    128     int next_ipc_id = dispatcher_->GetNextIpcIdForTest();
    129     dispatcher_->GenerateStream(request_id, handler_.get()->AsWeakPtr(),
    130                                 options, security_origin_);
    131     return next_ipc_id;
    132   }
    133 
    134   // CompleteGenerateStream create a MediaStreamMsg_StreamGenerated instance
    135   // and call the MediaStreamDispathcer::OnMessageReceived. |ipc_id| must be the
    136   // the id returned by GenerateStream.
    137   std::string CompleteGenerateStream(int ipc_id, const StreamOptions& options,
    138                                      int request_id) {
    139     StreamDeviceInfoArray audio_device_array(options.audio_requested ? 1 : 0);
    140     if (options.audio_requested) {
    141       StreamDeviceInfo audio_device_info;
    142       audio_device_info.device.name = "Microphone";
    143       audio_device_info.device.type = kAudioType;
    144       audio_device_info.session_id = kAudioSessionId;
    145       audio_device_array[0] = audio_device_info;
    146     }
    147 
    148     StreamDeviceInfoArray video_device_array(options.video_requested ? 1 : 0);
    149     if (options.video_requested) {
    150       StreamDeviceInfo video_device_info;
    151       video_device_info.device.name = "Camera";
    152       video_device_info.device.type = kVideoType;
    153       video_device_info.session_id = kVideoSessionId;
    154       video_device_array[0] = video_device_info;
    155     }
    156 
    157     std::string label = "stream" + base::IntToString(ipc_id);
    158 
    159     handler_->ResetStoredParameters();
    160     dispatcher_->OnMessageReceived(MediaStreamMsg_StreamGenerated(
    161         kRouteId, ipc_id, label,
    162         audio_device_array, video_device_array));
    163 
    164     EXPECT_EQ(handler_->request_id_, request_id);
    165     EXPECT_EQ(handler_->label_, label);
    166 
    167     if (options.audio_requested)
    168       EXPECT_EQ(dispatcher_->audio_session_id(label, 0), kAudioSessionId);
    169 
    170     if (options.video_requested)
    171       EXPECT_EQ(dispatcher_->video_session_id(label, 0), kVideoSessionId);
    172 
    173     return label;
    174   }
    175 
    176  protected:
    177   base::MessageLoop message_loop_;
    178   scoped_ptr<MediaStreamDispatcherUnderTest> dispatcher_;
    179   scoped_ptr<MockMediaStreamDispatcherEventHandler> handler_;
    180   GURL security_origin_;
    181   int request_id_;
    182 };
    183 
    184 }  // namespace
    185 
    186 TEST_F(MediaStreamDispatcherTest, GenerateStreamAndStopDevices) {
    187   StreamOptions options(true, true);
    188 
    189   int ipc_request_id1 = GenerateStream(options, kRequestId1);
    190   int ipc_request_id2 = GenerateStream(options, kRequestId2);
    191   EXPECT_NE(ipc_request_id1, ipc_request_id2);
    192 
    193   // Complete the creation of stream1.
    194   const std::string& label1 = CompleteGenerateStream(ipc_request_id1, options,
    195                                                      kRequestId1);
    196 
    197   // Complete the creation of stream2.
    198   const std::string& label2 = CompleteGenerateStream(ipc_request_id2, options,
    199                                                      kRequestId2);
    200 
    201   // Stop the actual audio device and verify that there is no valid
    202   // |session_id|.
    203   dispatcher_->StopStreamDevice(handler_->audio_device_);
    204   EXPECT_EQ(dispatcher_->audio_session_id(label1, 0),
    205             StreamDeviceInfo::kNoId);
    206   EXPECT_EQ(dispatcher_->audio_session_id(label2, 0),
    207             StreamDeviceInfo::kNoId);
    208 
    209   // Stop the actual video device and verify that there is no valid
    210   // |session_id|.
    211   dispatcher_->StopStreamDevice(handler_->video_device_);
    212   EXPECT_EQ(dispatcher_->video_session_id(label1, 0),
    213             StreamDeviceInfo::kNoId);
    214   EXPECT_EQ(dispatcher_->video_session_id(label2, 0),
    215             StreamDeviceInfo::kNoId);
    216 }
    217 
    218 TEST_F(MediaStreamDispatcherTest, BasicVideoDevice) {
    219   scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
    220   scoped_ptr<MockMediaStreamDispatcherEventHandler>
    221       handler1(new MockMediaStreamDispatcherEventHandler);
    222   scoped_ptr<MockMediaStreamDispatcherEventHandler>
    223       handler2(new MockMediaStreamDispatcherEventHandler);
    224   GURL security_origin;
    225 
    226   int ipc_request_id1 = dispatcher->next_ipc_id_;
    227   dispatcher->EnumerateDevices(
    228       kRequestId1, handler1.get()->AsWeakPtr(),
    229       kVideoType,
    230       security_origin);
    231   int ipc_request_id2 = dispatcher->next_ipc_id_;
    232   EXPECT_NE(ipc_request_id1, ipc_request_id2);
    233   dispatcher->EnumerateDevices(
    234       kRequestId2, handler2.get()->AsWeakPtr(),
    235       kVideoType,
    236       security_origin);
    237   EXPECT_EQ(dispatcher->requests_.size(), size_t(2));
    238 
    239   StreamDeviceInfoArray video_device_array(1);
    240   StreamDeviceInfo video_device_info;
    241   video_device_info.device.name = "Camera";
    242   video_device_info.device.id = "device_path";
    243   video_device_info.device.type = kVideoType;
    244   video_device_info.session_id = kVideoSessionId;
    245   video_device_array[0] = video_device_info;
    246 
    247   // Complete the first enumeration request.
    248   dispatcher->OnMessageReceived(MediaStreamMsg_DevicesEnumerated(
    249       kRouteId, ipc_request_id1, video_device_array));
    250   EXPECT_EQ(handler1->request_id_, kRequestId1);
    251 
    252   dispatcher->OnMessageReceived(MediaStreamMsg_DevicesEnumerated(
    253         kRouteId, ipc_request_id2, video_device_array));
    254   EXPECT_EQ(handler2->request_id_, kRequestId2);
    255 
    256   EXPECT_EQ(dispatcher->requests_.size(), size_t(2));
    257   EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0));
    258 
    259   int ipc_request_id3 = dispatcher->next_ipc_id_;
    260   dispatcher->OpenDevice(kRequestId3, handler1.get()->AsWeakPtr(),
    261                          video_device_info.device.id,
    262                          kVideoType,
    263                          security_origin);
    264   int ipc_request_id4 = dispatcher->next_ipc_id_;
    265   EXPECT_NE(ipc_request_id3, ipc_request_id4);
    266   dispatcher->OpenDevice(kRequestId4, handler1.get()->AsWeakPtr(),
    267                          video_device_info.device.id,
    268                          kVideoType,
    269                          security_origin);
    270   EXPECT_EQ(dispatcher->requests_.size(), size_t(4));
    271 
    272   // Complete the OpenDevice of request 1.
    273   std::string stream_label1 = std::string("stream1");
    274   dispatcher->OnMessageReceived(MediaStreamMsg_DeviceOpened(
    275       kRouteId, ipc_request_id3, stream_label1, video_device_info));
    276   EXPECT_EQ(handler1->request_id_, kRequestId3);
    277 
    278   // Complete the OpenDevice of request 2.
    279   std::string stream_label2 = std::string("stream2");
    280   dispatcher->OnMessageReceived(MediaStreamMsg_DeviceOpened(
    281       kRouteId, ipc_request_id4, stream_label2, video_device_info));
    282   EXPECT_EQ(handler1->request_id_, kRequestId4);
    283 
    284   EXPECT_EQ(dispatcher->requests_.size(), size_t(2));
    285   EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(2));
    286 
    287   // Check the video_session_id.
    288   EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0), kVideoSessionId);
    289   EXPECT_EQ(dispatcher->video_session_id(stream_label2, 0), kVideoSessionId);
    290 
    291   // Close the device from request 2.
    292   dispatcher->CloseDevice(stream_label2);
    293   EXPECT_EQ(dispatcher->video_session_id(stream_label2, 0),
    294             StreamDeviceInfo::kNoId);
    295 
    296   // Close the device from request 1.
    297   dispatcher->CloseDevice(stream_label1);
    298   EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0),
    299             StreamDeviceInfo::kNoId);
    300   EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0));
    301 
    302   // Verify that the request have been completed.
    303   EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0));
    304   EXPECT_EQ(dispatcher->requests_.size(), size_t(2));
    305 }
    306 
    307 TEST_F(MediaStreamDispatcherTest, TestFailure) {
    308   scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
    309   scoped_ptr<MockMediaStreamDispatcherEventHandler>
    310       handler(new MockMediaStreamDispatcherEventHandler);
    311   StreamOptions components(true, true);
    312   GURL security_origin;
    313 
    314   // Test failure when creating a stream.
    315   int ipc_request_id1 = dispatcher->next_ipc_id_;
    316   dispatcher->GenerateStream(kRequestId1, handler.get()->AsWeakPtr(),
    317                              components, security_origin);
    318   dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerationFailed(
    319       kRouteId, ipc_request_id1, MEDIA_DEVICE_PERMISSION_DENIED));
    320 
    321   // Verify that the request have been completed.
    322   EXPECT_EQ(handler->request_id_, kRequestId1);
    323   EXPECT_EQ(dispatcher->requests_.size(), size_t(0));
    324 
    325   // Create a new stream.
    326   ipc_request_id1 = dispatcher->next_ipc_id_;
    327   dispatcher->GenerateStream(kRequestId1, handler.get()->AsWeakPtr(),
    328                              components, security_origin);
    329 
    330   StreamDeviceInfoArray audio_device_array(1);
    331   StreamDeviceInfo audio_device_info;
    332   audio_device_info.device.name = "Microphone";
    333   audio_device_info.device.type = kAudioType;
    334   audio_device_info.session_id = kAudioSessionId;
    335   audio_device_array[0] = audio_device_info;
    336 
    337   StreamDeviceInfoArray video_device_array(1);
    338   StreamDeviceInfo video_device_info;
    339   video_device_info.device.name = "Camera";
    340   video_device_info.device.type = kVideoType;
    341   video_device_info.session_id = kVideoSessionId;
    342   video_device_array[0] = video_device_info;
    343 
    344   // Complete the creation of stream1.
    345   std::string stream_label1 = std::string("stream1");
    346   dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated(
    347       kRouteId, ipc_request_id1, stream_label1,
    348       audio_device_array, video_device_array));
    349   EXPECT_EQ(handler->request_id_, kRequestId1);
    350   EXPECT_EQ(handler->label_, stream_label1);
    351   EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0), kVideoSessionId);
    352 }
    353 
    354 TEST_F(MediaStreamDispatcherTest, CancelGenerateStream) {
    355   scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
    356   scoped_ptr<MockMediaStreamDispatcherEventHandler>
    357       handler(new MockMediaStreamDispatcherEventHandler);
    358   StreamOptions components(true, true);
    359   int ipc_request_id1 = dispatcher->next_ipc_id_;
    360 
    361   dispatcher->GenerateStream(kRequestId1, handler.get()->AsWeakPtr(),
    362                              components, GURL());
    363   dispatcher->GenerateStream(kRequestId2, handler.get()->AsWeakPtr(),
    364                              components, GURL());
    365 
    366   EXPECT_EQ(2u, dispatcher->requests_.size());
    367   dispatcher->CancelGenerateStream(kRequestId2, handler.get()->AsWeakPtr());
    368   EXPECT_EQ(1u, dispatcher->requests_.size());
    369 
    370   // Complete the creation of stream1.
    371   StreamDeviceInfo audio_device_info;
    372   audio_device_info.device.name = "Microphone";
    373   audio_device_info.device.type = kAudioType;
    374   audio_device_info.session_id = kAudioSessionId;
    375   StreamDeviceInfoArray audio_device_array(1);
    376   audio_device_array[0] = audio_device_info;
    377 
    378   StreamDeviceInfo video_device_info;
    379   video_device_info.device.name = "Camera";
    380   video_device_info.device.type = kVideoType;
    381   video_device_info.session_id = kVideoSessionId;
    382   StreamDeviceInfoArray video_device_array(1);
    383   video_device_array[0] = video_device_info;
    384 
    385   std::string stream_label1 = "stream1";
    386   dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated(
    387       kRouteId, ipc_request_id1, stream_label1,
    388       audio_device_array, video_device_array));
    389   EXPECT_EQ(handler->request_id_, kRequestId1);
    390   EXPECT_EQ(handler->label_, stream_label1);
    391   EXPECT_EQ(0u, dispatcher->requests_.size());
    392 }
    393 
    394 // Test that the MediaStreamDispatcherEventHandler is notified when the message
    395 // MediaStreamMsg_DeviceStopped is received.
    396 TEST_F(MediaStreamDispatcherTest, DeviceClosed) {
    397   StreamOptions options(true, true);
    398 
    399   int ipc_request_id = GenerateStream(options, kRequestId1);
    400   const std::string& label = CompleteGenerateStream(ipc_request_id, options,
    401                                                     kRequestId1);
    402 
    403   dispatcher_->OnMessageReceived(
    404       MediaStreamMsg_DeviceStopped(kRouteId, label, handler_->video_device_));
    405   // Verify that MediaStreamDispatcherEventHandler::OnDeviceStopped has been
    406   // called.
    407   EXPECT_EQ(label, handler_->device_stopped_label_);
    408   EXPECT_EQ(dispatcher_->video_session_id(label, 0),
    409             StreamDeviceInfo::kNoId);
    410 }
    411 
    412 TEST_F(MediaStreamDispatcherTest, CheckDuckingState) {
    413   scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
    414   scoped_ptr<MockMediaStreamDispatcherEventHandler>
    415       handler(new MockMediaStreamDispatcherEventHandler);
    416   StreamOptions components(true, false);  // audio only.
    417   int ipc_request_id1 = dispatcher->next_ipc_id_;
    418 
    419   dispatcher->GenerateStream(kRequestId1, handler.get()->AsWeakPtr(),
    420                              components, GURL());
    421   EXPECT_EQ(1u, dispatcher->requests_.size());
    422 
    423   // Ducking isn't active at this point.
    424   EXPECT_FALSE(dispatcher->IsAudioDuckingActive());
    425 
    426   // Complete the creation of stream1 with a single audio track that has
    427   // ducking enabled.
    428   StreamDeviceInfoArray audio_device_array(1);
    429   StreamDeviceInfo& audio_device_info = audio_device_array[0];
    430   audio_device_info.device.name = "Microphone";
    431   audio_device_info.device.type = kAudioType;
    432   audio_device_info.session_id = kAudioSessionId;
    433   audio_device_info.device.input.effects = media::AudioParameters::DUCKING;
    434 
    435   StreamDeviceInfoArray video_device_array;  // Empty for this test.
    436 
    437   const char kStreamLabel[] = "stream1";
    438   dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated(
    439       kRouteId, ipc_request_id1, kStreamLabel,
    440       audio_device_array, video_device_array));
    441   EXPECT_EQ(handler->request_id_, kRequestId1);
    442   EXPECT_EQ(0u, dispatcher->requests_.size());
    443 
    444   // Ducking should now be reported as active.
    445   EXPECT_TRUE(dispatcher->IsAudioDuckingActive());
    446 
    447   // Stop the device (removes the stream).
    448   dispatcher->OnMessageReceived(
    449       MediaStreamMsg_DeviceStopped(kRouteId, kStreamLabel,
    450             handler->audio_device_));
    451 
    452   // Ducking should now be reported as inactive again.
    453   EXPECT_FALSE(dispatcher->IsAudioDuckingActive());
    454 
    455   // Now do the same sort of test with the DUCKING flag off.
    456   audio_device_info.device.input.effects =
    457       media::AudioParameters::ECHO_CANCELLER;
    458 
    459   dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated(
    460       kRouteId, ipc_request_id1, kStreamLabel,
    461       audio_device_array, video_device_array));
    462   EXPECT_EQ(handler->request_id_, kRequestId1);
    463   EXPECT_EQ(0u, dispatcher->requests_.size());
    464 
    465   // Ducking should still be reported as not active.
    466   EXPECT_FALSE(dispatcher->IsAudioDuckingActive());
    467 
    468   // Stop the device (removes the stream).
    469   dispatcher->OnMessageReceived(
    470       MediaStreamMsg_DeviceStopped(kRouteId, kStreamLabel,
    471             handler->audio_device_));
    472 }
    473 
    474 }  // namespace content
    475