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 "base/memory/scoped_ptr.h"
      6 #include "base/message_loop/message_loop.h"
      7 #include "base/strings/utf_string_conversions.h"
      8 #include "content/child/child_process.h"
      9 #include "content/renderer/media/media_stream.h"
     10 #include "content/renderer/media/media_stream_track.h"
     11 #include "content/renderer/media/mock_media_stream_dispatcher.h"
     12 #include "content/renderer/media/mock_media_stream_video_source.h"
     13 #include "content/renderer/media/user_media_client_impl.h"
     14 #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 #include "third_party/WebKit/public/platform/WebMediaDeviceInfo.h"
     17 #include "third_party/WebKit/public/platform/WebMediaStream.h"
     18 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
     19 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
     20 #include "third_party/WebKit/public/platform/WebMediaStreamTrackSourcesRequest.h"
     21 #include "third_party/WebKit/public/platform/WebString.h"
     22 #include "third_party/WebKit/public/platform/WebVector.h"
     23 #include "third_party/WebKit/public/web/WebHeap.h"
     24 
     25 namespace content {
     26 
     27 class MockMediaStreamVideoCapturerSource : public MockMediaStreamVideoSource {
     28  public:
     29   MockMediaStreamVideoCapturerSource(
     30       const StreamDeviceInfo& device,
     31       const SourceStoppedCallback& stop_callback,
     32       PeerConnectionDependencyFactory* factory)
     33   : MockMediaStreamVideoSource(false) {
     34     SetDeviceInfo(device);
     35     SetStopCallback(stop_callback);
     36   }
     37 };
     38 
     39 class UserMediaClientImplUnderTest : public UserMediaClientImpl {
     40  public:
     41   enum RequestState {
     42     REQUEST_NOT_STARTED,
     43     REQUEST_NOT_COMPLETE,
     44     REQUEST_SUCCEEDED,
     45     REQUEST_FAILED,
     46   };
     47 
     48   UserMediaClientImplUnderTest(
     49       PeerConnectionDependencyFactory* dependency_factory,
     50       scoped_ptr<MediaStreamDispatcher> media_stream_dispatcher)
     51       : UserMediaClientImpl(
     52             NULL, dependency_factory, media_stream_dispatcher.Pass()),
     53         state_(REQUEST_NOT_STARTED),
     54         result_(NUM_MEDIA_REQUEST_RESULTS),
     55         result_name_(""),
     56         factory_(dependency_factory),
     57         video_source_(NULL) {
     58   }
     59 
     60   void RequestUserMedia() {
     61     blink::WebUserMediaRequest user_media_request;
     62     state_ = REQUEST_NOT_COMPLETE;
     63     requestUserMedia(user_media_request);
     64   }
     65 
     66   void RequestMediaDevices() {
     67     blink::WebMediaDevicesRequest media_devices_request;
     68     state_ = REQUEST_NOT_COMPLETE;
     69     requestMediaDevices(media_devices_request);
     70   }
     71 
     72   void RequestSources() {
     73     blink::WebMediaStreamTrackSourcesRequest sources_request;
     74     state_ = REQUEST_NOT_COMPLETE;
     75     requestSources(sources_request);
     76   }
     77 
     78   virtual void GetUserMediaRequestSucceeded(
     79       const blink::WebMediaStream& stream,
     80       blink::WebUserMediaRequest* request_info) OVERRIDE {
     81     last_generated_stream_ = stream;
     82     state_ = REQUEST_SUCCEEDED;
     83   }
     84 
     85   virtual void GetUserMediaRequestFailed(
     86       blink::WebUserMediaRequest* request_info,
     87       content::MediaStreamRequestResult result) OVERRIDE {
     88     last_generated_stream_.reset();
     89     state_ = REQUEST_FAILED;
     90     result_ = result;
     91   }
     92 
     93   virtual void GetUserMediaRequestTrackStartedFailed(
     94       blink::WebUserMediaRequest* request_info,
     95       MediaStreamRequestResult result,
     96       const blink::WebString& result_name) OVERRIDE {
     97     last_generated_stream_.reset();
     98     state_ = REQUEST_FAILED;
     99     result_ = result;
    100     result_name_ = result_name;
    101   }
    102 
    103   virtual void EnumerateDevicesSucceded(
    104       blink::WebMediaDevicesRequest* request,
    105       blink::WebVector<blink::WebMediaDeviceInfo>& devices) OVERRIDE {
    106     state_ = REQUEST_SUCCEEDED;
    107     last_devices_ = devices;
    108   }
    109 
    110   virtual void EnumerateSourcesSucceded(
    111       blink::WebMediaStreamTrackSourcesRequest* request,
    112       blink::WebVector<blink::WebSourceInfo>& sources) OVERRIDE {
    113     state_ = REQUEST_SUCCEEDED;
    114     last_sources_ = sources;
    115   }
    116 
    117   virtual MediaStreamVideoSource* CreateVideoSource(
    118       const StreamDeviceInfo& device,
    119       const MediaStreamSource::SourceStoppedCallback& stop_callback) OVERRIDE {
    120     video_source_ = new MockMediaStreamVideoCapturerSource(device,
    121                                                            stop_callback,
    122                                                            factory_);
    123     return video_source_;
    124   }
    125 
    126   const blink::WebMediaStream& last_generated_stream() {
    127     return last_generated_stream_;
    128   }
    129 
    130   const blink::WebVector<blink::WebMediaDeviceInfo>& last_devices() {
    131     return last_devices_;
    132   }
    133 
    134   const blink::WebVector<blink::WebSourceInfo>& last_sources() {
    135     return last_sources_;
    136   }
    137 
    138   void ClearLastGeneratedStream() {
    139     last_generated_stream_.reset();
    140   }
    141 
    142   MockMediaStreamVideoCapturerSource* last_created_video_source() const {
    143     return video_source_;
    144   }
    145 
    146   RequestState request_state() const { return state_; }
    147   content::MediaStreamRequestResult error_reason() const { return result_; }
    148   blink::WebString error_name() const { return result_name_; }
    149 
    150  private:
    151   blink::WebMediaStream last_generated_stream_;
    152   RequestState state_;
    153   content::MediaStreamRequestResult result_;
    154   blink::WebString result_name_;
    155   blink::WebVector<blink::WebMediaDeviceInfo> last_devices_;
    156   blink::WebVector<blink::WebSourceInfo> last_sources_;
    157   PeerConnectionDependencyFactory* factory_;
    158   MockMediaStreamVideoCapturerSource* video_source_;
    159 };
    160 
    161 class UserMediaClientImplTest : public ::testing::Test {
    162  public:
    163   virtual void SetUp() {
    164     // Create our test object.
    165     child_process_.reset(new ChildProcess());
    166     dependency_factory_.reset(new MockPeerConnectionDependencyFactory());
    167     ms_dispatcher_ = new MockMediaStreamDispatcher();
    168     used_media_impl_.reset(new UserMediaClientImplUnderTest(
    169         dependency_factory_.get(),
    170         scoped_ptr<MediaStreamDispatcher>(ms_dispatcher_).Pass()));
    171   }
    172 
    173   virtual void TearDown() OVERRIDE {
    174     used_media_impl_.reset();
    175     blink::WebHeap::collectAllGarbageForTesting();
    176   }
    177 
    178   blink::WebMediaStream RequestLocalMediaStream() {
    179     used_media_impl_->RequestUserMedia();
    180     FakeMediaStreamDispatcherRequestUserMediaComplete();
    181     StartMockedVideoSource();
    182 
    183     EXPECT_EQ(UserMediaClientImplUnderTest::REQUEST_SUCCEEDED,
    184               used_media_impl_->request_state());
    185 
    186     blink::WebMediaStream desc = used_media_impl_->last_generated_stream();
    187     content::MediaStream* native_stream =
    188         content::MediaStream::GetMediaStream(desc);
    189     if (!native_stream) {
    190       ADD_FAILURE();
    191       return desc;
    192     }
    193 
    194     blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
    195     desc.audioTracks(audio_tracks);
    196     blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
    197     desc.videoTracks(video_tracks);
    198 
    199     EXPECT_EQ(1u, audio_tracks.size());
    200     EXPECT_EQ(1u, video_tracks.size());
    201     EXPECT_NE(audio_tracks[0].id(), video_tracks[0].id());
    202     return desc;
    203   }
    204 
    205   void FakeMediaStreamDispatcherRequestUserMediaComplete() {
    206     // Audio request ID is used as the shared request ID.
    207     used_media_impl_->OnStreamGenerated(
    208         ms_dispatcher_->audio_input_request_id(),
    209         ms_dispatcher_->stream_label(),
    210         ms_dispatcher_->audio_input_array(),
    211         ms_dispatcher_->video_array());
    212   }
    213 
    214   void FakeMediaStreamDispatcherRequestMediaDevicesComplete() {
    215     used_media_impl_->OnDevicesEnumerated(
    216         ms_dispatcher_->audio_input_request_id(),
    217         ms_dispatcher_->audio_input_array());
    218     used_media_impl_->OnDevicesEnumerated(
    219         ms_dispatcher_->audio_output_request_id(),
    220         ms_dispatcher_->audio_output_array());
    221     used_media_impl_->OnDevicesEnumerated(
    222         ms_dispatcher_->video_request_id(),
    223         ms_dispatcher_->video_array());
    224   }
    225 
    226   void FakeMediaStreamDispatcherRequestSourcesComplete() {
    227     used_media_impl_->OnDevicesEnumerated(
    228         ms_dispatcher_->audio_input_request_id(),
    229         ms_dispatcher_->audio_input_array());
    230     used_media_impl_->OnDevicesEnumerated(
    231         ms_dispatcher_->video_request_id(),
    232         ms_dispatcher_->video_array());
    233   }
    234 
    235   void StartMockedVideoSource() {
    236     MockMediaStreamVideoCapturerSource* video_source =
    237         used_media_impl_->last_created_video_source();
    238     if (video_source->SourceHasAttemptedToStart())
    239       video_source->StartMockedSource();
    240   }
    241 
    242   void FailToStartMockedVideoSource() {
    243     MockMediaStreamVideoCapturerSource* video_source =
    244         used_media_impl_->last_created_video_source();
    245     if (video_source->SourceHasAttemptedToStart())
    246       video_source->FailToStartMockedSource();
    247     blink::WebHeap::collectGarbageForTesting();
    248   }
    249 
    250   void FailToCreateNextAudioCapturer() {
    251     dependency_factory_->FailToCreateNextAudioCapturer();
    252     blink::WebHeap::collectGarbageForTesting();
    253   }
    254 
    255  protected:
    256   base::MessageLoop message_loop_;
    257   scoped_ptr<ChildProcess> child_process_;
    258   MockMediaStreamDispatcher* ms_dispatcher_;  // Owned by |used_media_impl_|.
    259   scoped_ptr<UserMediaClientImplUnderTest> used_media_impl_;
    260   scoped_ptr<MockPeerConnectionDependencyFactory> dependency_factory_;
    261 };
    262 
    263 TEST_F(UserMediaClientImplTest, GenerateMediaStream) {
    264   // Generate a stream with both audio and video.
    265   blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
    266 }
    267 
    268 // Test that the same source object is used if two MediaStreams are generated
    269 // using the same source.
    270 TEST_F(UserMediaClientImplTest, GenerateTwoMediaStreamsWithSameSource) {
    271   blink::WebMediaStream desc1 = RequestLocalMediaStream();
    272   blink::WebMediaStream desc2 = RequestLocalMediaStream();
    273 
    274   blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks;
    275   desc1.videoTracks(desc1_video_tracks);
    276   blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks;
    277   desc2.videoTracks(desc2_video_tracks);
    278   EXPECT_EQ(desc1_video_tracks[0].source().id(),
    279             desc2_video_tracks[0].source().id());
    280 
    281   EXPECT_EQ(desc1_video_tracks[0].source().extraData(),
    282             desc2_video_tracks[0].source().extraData());
    283 
    284   blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks;
    285   desc1.audioTracks(desc1_audio_tracks);
    286   blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks;
    287   desc2.audioTracks(desc2_audio_tracks);
    288   EXPECT_EQ(desc1_audio_tracks[0].source().id(),
    289             desc2_audio_tracks[0].source().id());
    290 
    291   EXPECT_EQ(desc1_audio_tracks[0].source().extraData(),
    292             desc2_audio_tracks[0].source().extraData());
    293 }
    294 
    295 // Test that the same source object is not used if two MediaStreams are
    296 // generated using different sources.
    297 TEST_F(UserMediaClientImplTest, GenerateTwoMediaStreamsWithDifferentSources) {
    298   blink::WebMediaStream desc1 = RequestLocalMediaStream();
    299   // Make sure another device is selected (another |session_id|) in  the next
    300   // gUM request.
    301   ms_dispatcher_->IncrementSessionId();
    302   blink::WebMediaStream desc2 = RequestLocalMediaStream();
    303 
    304   blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks;
    305   desc1.videoTracks(desc1_video_tracks);
    306   blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks;
    307   desc2.videoTracks(desc2_video_tracks);
    308   EXPECT_NE(desc1_video_tracks[0].source().id(),
    309             desc2_video_tracks[0].source().id());
    310 
    311   EXPECT_NE(desc1_video_tracks[0].source().extraData(),
    312             desc2_video_tracks[0].source().extraData());
    313 
    314   blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks;
    315   desc1.audioTracks(desc1_audio_tracks);
    316   blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks;
    317   desc2.audioTracks(desc2_audio_tracks);
    318   EXPECT_NE(desc1_audio_tracks[0].source().id(),
    319             desc2_audio_tracks[0].source().id());
    320 
    321   EXPECT_NE(desc1_audio_tracks[0].source().extraData(),
    322             desc2_audio_tracks[0].source().extraData());
    323 }
    324 
    325 TEST_F(UserMediaClientImplTest, StopLocalTracks) {
    326   // Generate a stream with both audio and video.
    327   blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
    328 
    329   blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
    330   mixed_desc.audioTracks(audio_tracks);
    331   MediaStreamTrack* audio_track = MediaStreamTrack::GetTrack(audio_tracks[0]);
    332   audio_track->Stop();
    333   EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
    334 
    335   blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
    336   mixed_desc.videoTracks(video_tracks);
    337   MediaStreamTrack* video_track = MediaStreamTrack::GetTrack(video_tracks[0]);
    338   video_track->Stop();
    339   EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
    340 }
    341 
    342 // This test that a source is not stopped even if the tracks in a
    343 // MediaStream is stopped if there are two MediaStreams with tracks using the
    344 // same device. The source is stopped
    345 // if there are no more MediaStream tracks using the device.
    346 TEST_F(UserMediaClientImplTest, StopLocalTracksWhenTwoStreamUseSameDevices) {
    347   // Generate a stream with both audio and video.
    348   blink::WebMediaStream desc1 = RequestLocalMediaStream();
    349   blink::WebMediaStream desc2 = RequestLocalMediaStream();
    350 
    351   blink::WebVector<blink::WebMediaStreamTrack> audio_tracks1;
    352   desc1.audioTracks(audio_tracks1);
    353   MediaStreamTrack* audio_track1 = MediaStreamTrack::GetTrack(audio_tracks1[0]);
    354   audio_track1->Stop();
    355   EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter());
    356 
    357   blink::WebVector<blink::WebMediaStreamTrack> audio_tracks2;
    358   desc2.audioTracks(audio_tracks2);
    359   MediaStreamTrack* audio_track2 = MediaStreamTrack::GetTrack(audio_tracks2[0]);
    360   audio_track2->Stop();
    361   EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
    362 
    363   blink::WebVector<blink::WebMediaStreamTrack> video_tracks1;
    364   desc1.videoTracks(video_tracks1);
    365   MediaStreamTrack* video_track1 = MediaStreamTrack::GetTrack(video_tracks1[0]);
    366   video_track1->Stop();
    367   EXPECT_EQ(0, ms_dispatcher_->stop_video_device_counter());
    368 
    369   blink::WebVector<blink::WebMediaStreamTrack> video_tracks2;
    370   desc2.videoTracks(video_tracks2);
    371   MediaStreamTrack* video_track2 = MediaStreamTrack::GetTrack(video_tracks2[0]);
    372   video_track2->Stop();
    373   EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
    374 }
    375 
    376 TEST_F(UserMediaClientImplTest, StopSourceWhenMediaStreamGoesOutOfScope) {
    377   // Generate a stream with both audio and video.
    378   RequestLocalMediaStream();
    379   // Makes sure the test itself don't hold a reference to the created
    380   // MediaStream.
    381   used_media_impl_->ClearLastGeneratedStream();
    382   blink::WebHeap::collectGarbageForTesting();
    383 
    384   // Expect the sources to be stopped when the MediaStream goes out of scope.
    385   EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
    386   EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
    387 }
    388 
    389 // Test that the MediaStreams are deleted if the owning WebFrame is closing.
    390 // In the unit test the owning frame is NULL.
    391 TEST_F(UserMediaClientImplTest, FrameWillClose) {
    392   // Test a stream with both audio and video.
    393   blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
    394   blink::WebMediaStream desc2 = RequestLocalMediaStream();
    395   used_media_impl_->FrameWillClose();
    396   EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
    397   EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
    398 }
    399 
    400 // This test what happens if a video source to a MediaSteam fails to start.
    401 TEST_F(UserMediaClientImplTest, MediaVideoSourceFailToStart) {
    402   used_media_impl_->RequestUserMedia();
    403   FakeMediaStreamDispatcherRequestUserMediaComplete();
    404   FailToStartMockedVideoSource();
    405   EXPECT_EQ(UserMediaClientImplUnderTest::REQUEST_FAILED,
    406             used_media_impl_->request_state());
    407   EXPECT_EQ(MEDIA_DEVICE_TRACK_START_FAILURE,
    408             used_media_impl_->error_reason());
    409   blink::WebHeap::collectGarbageForTesting();
    410   EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
    411   EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
    412   EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
    413 }
    414 
    415 // This test what happens if an audio source fail to initialize.
    416 TEST_F(UserMediaClientImplTest, MediaAudioSourceFailToInitialize) {
    417   FailToCreateNextAudioCapturer();
    418   used_media_impl_->RequestUserMedia();
    419   FakeMediaStreamDispatcherRequestUserMediaComplete();
    420   StartMockedVideoSource();
    421   EXPECT_EQ(UserMediaClientImplUnderTest::REQUEST_FAILED,
    422             used_media_impl_->request_state());
    423   EXPECT_EQ(MEDIA_DEVICE_TRACK_START_FAILURE,
    424             used_media_impl_->error_reason());
    425   blink::WebHeap::collectGarbageForTesting();
    426   EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
    427   EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
    428   EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
    429 }
    430 
    431 // This test what happens if UserMediaClientImpl is deleted before a source has
    432 // started.
    433 TEST_F(UserMediaClientImplTest, MediaStreamImplShutDown) {
    434   used_media_impl_->RequestUserMedia();
    435   FakeMediaStreamDispatcherRequestUserMediaComplete();
    436   EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
    437   EXPECT_EQ(UserMediaClientImplUnderTest::REQUEST_NOT_COMPLETE,
    438             used_media_impl_->request_state());
    439   used_media_impl_.reset();
    440 }
    441 
    442 // This test what happens if the WebFrame is closed while the MediaStream is
    443 // being generated by the MediaStreamDispatcher.
    444 TEST_F(UserMediaClientImplTest, ReloadFrameWhileGeneratingStream) {
    445   used_media_impl_->RequestUserMedia();
    446   used_media_impl_->FrameWillClose();
    447   EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
    448   EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter());
    449   EXPECT_EQ(0, ms_dispatcher_->stop_video_device_counter());
    450   EXPECT_EQ(UserMediaClientImplUnderTest::REQUEST_NOT_COMPLETE,
    451             used_media_impl_->request_state());
    452 }
    453 
    454 // This test what happens if the WebFrame is closed while the sources are being
    455 // started.
    456 TEST_F(UserMediaClientImplTest, ReloadFrameWhileGeneratingSources) {
    457   used_media_impl_->RequestUserMedia();
    458   FakeMediaStreamDispatcherRequestUserMediaComplete();
    459   EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
    460   used_media_impl_->FrameWillClose();
    461   EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
    462   EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
    463   EXPECT_EQ(UserMediaClientImplUnderTest::REQUEST_NOT_COMPLETE,
    464             used_media_impl_->request_state());
    465 }
    466 
    467 // This test what happens if stop is called on a track after the frame has
    468 // been reloaded.
    469 TEST_F(UserMediaClientImplTest, StopTrackAfterReload) {
    470   blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
    471   EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
    472   used_media_impl_->FrameWillClose();
    473   EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
    474   EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
    475 
    476   blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
    477   mixed_desc.audioTracks(audio_tracks);
    478   MediaStreamTrack* audio_track = MediaStreamTrack::GetTrack(audio_tracks[0]);
    479   audio_track->Stop();
    480   EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
    481 
    482   blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
    483   mixed_desc.videoTracks(video_tracks);
    484   MediaStreamTrack* video_track = MediaStreamTrack::GetTrack(video_tracks[0]);
    485   video_track->Stop();
    486   EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
    487 }
    488 
    489 TEST_F(UserMediaClientImplTest, EnumerateMediaDevices) {
    490   used_media_impl_->RequestMediaDevices();
    491   FakeMediaStreamDispatcherRequestMediaDevicesComplete();
    492 
    493   EXPECT_EQ(UserMediaClientImplUnderTest::REQUEST_SUCCEEDED,
    494             used_media_impl_->request_state());
    495   EXPECT_EQ(static_cast<size_t>(5), used_media_impl_->last_devices().size());
    496 
    497   // Audio input device with matched output ID.
    498   const blink::WebMediaDeviceInfo* device =
    499       &used_media_impl_->last_devices()[0];
    500   EXPECT_FALSE(device->deviceId().isEmpty());
    501   EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindAudioInput,
    502             device->kind());
    503   EXPECT_FALSE(device->label().isEmpty());
    504   EXPECT_FALSE(device->groupId().isEmpty());
    505 
    506   // Audio input device without matched output ID.
    507   device = &used_media_impl_->last_devices()[1];
    508   EXPECT_FALSE(device->deviceId().isEmpty());
    509   EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindAudioInput,
    510             device->kind());
    511   EXPECT_FALSE(device->label().isEmpty());
    512   EXPECT_FALSE(device->groupId().isEmpty());
    513 
    514   // Video input devices.
    515   device = &used_media_impl_->last_devices()[2];
    516   EXPECT_FALSE(device->deviceId().isEmpty());
    517   EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindVideoInput,
    518             device->kind());
    519   EXPECT_FALSE(device->label().isEmpty());
    520   EXPECT_TRUE(device->groupId().isEmpty());
    521 
    522   device = &used_media_impl_->last_devices()[3];
    523   EXPECT_FALSE(device->deviceId().isEmpty());
    524   EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindVideoInput,
    525             device->kind());
    526   EXPECT_FALSE(device->label().isEmpty());
    527   EXPECT_TRUE(device->groupId().isEmpty());
    528 
    529   // Audio output device.
    530   device = &used_media_impl_->last_devices()[4];
    531   EXPECT_FALSE(device->deviceId().isEmpty());
    532   EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindAudioOutput,
    533             device->kind());
    534   EXPECT_FALSE(device->label().isEmpty());
    535   EXPECT_FALSE(device->groupId().isEmpty());
    536 
    537   // Verfify group IDs.
    538   EXPECT_TRUE(used_media_impl_->last_devices()[0].groupId().equals(
    539                   used_media_impl_->last_devices()[4].groupId()));
    540   EXPECT_FALSE(used_media_impl_->last_devices()[1].groupId().equals(
    541                    used_media_impl_->last_devices()[4].groupId()));
    542 }
    543 
    544 TEST_F(UserMediaClientImplTest, EnumerateSources) {
    545   used_media_impl_->RequestSources();
    546   FakeMediaStreamDispatcherRequestSourcesComplete();
    547 
    548   EXPECT_EQ(UserMediaClientImplUnderTest::REQUEST_SUCCEEDED,
    549             used_media_impl_->request_state());
    550   EXPECT_EQ(static_cast<size_t>(4), used_media_impl_->last_sources().size());
    551 
    552   // Audio input devices.
    553   const blink::WebSourceInfo* source = &used_media_impl_->last_sources()[0];
    554   EXPECT_FALSE(source->id().isEmpty());
    555   EXPECT_EQ(blink::WebSourceInfo::SourceKindAudio, source->kind());
    556   EXPECT_FALSE(source->label().isEmpty());
    557   EXPECT_EQ(blink::WebSourceInfo::VideoFacingModeNone, source->facing());
    558 
    559   source = &used_media_impl_->last_sources()[1];
    560   EXPECT_FALSE(source->id().isEmpty());
    561   EXPECT_EQ(blink::WebSourceInfo::SourceKindAudio, source->kind());
    562   EXPECT_FALSE(source->label().isEmpty());
    563   EXPECT_EQ(blink::WebSourceInfo::VideoFacingModeNone, source->facing());
    564 
    565   // Video input device user facing.
    566   source = &used_media_impl_->last_sources()[2];
    567   EXPECT_FALSE(source->id().isEmpty());
    568   EXPECT_EQ(blink::WebSourceInfo::SourceKindVideo, source->kind());
    569   EXPECT_FALSE(source->label().isEmpty());
    570   EXPECT_EQ(blink::WebSourceInfo::VideoFacingModeUser, source->facing());
    571 
    572   // Video input device environment facing.
    573   source = &used_media_impl_->last_sources()[3];
    574   EXPECT_FALSE(source->id().isEmpty());
    575   EXPECT_EQ(blink::WebSourceInfo::SourceKindVideo, source->kind());
    576   EXPECT_FALSE(source->label().isEmpty());
    577   EXPECT_EQ(blink::WebSourceInfo::VideoFacingModeEnvironment, source->facing());
    578 }
    579 
    580 }  // namespace content
    581