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