1 // Copyright 2013 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/strings/string_number_conversions.h" 6 #include "content/browser/renderer_host/media/device_request_message_filter.h" 7 #include "content/browser/renderer_host/media/media_stream_manager.h" 8 #include "content/common/media/media_stream_messages.h" 9 #include "content/public/test/mock_resource_context.h" 10 #include "content/public/test/test_browser_thread.h" 11 #include "testing/gmock/include/gmock/gmock.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 14 using ::testing::_; 15 using ::testing::Invoke; 16 17 namespace content { 18 19 static const std::string kAudioLabel = "audio_label"; 20 static const std::string kVideoLabel = "video_label"; 21 22 class MockMediaStreamManager : public MediaStreamManager { 23 public: 24 MockMediaStreamManager() {} 25 26 virtual ~MockMediaStreamManager() {} 27 28 MOCK_METHOD7(EnumerateDevices, 29 std::string(MediaStreamRequester* requester, 30 int render_process_id, 31 int render_frame_id, 32 const ResourceContext::SaltCallback& rc, 33 int page_request_id, 34 MediaStreamType type, 35 const GURL& security_origin)); 36 37 std::string DoEnumerateDevices(MediaStreamRequester* requester, 38 int render_process_id, 39 int render_frame_id, 40 const ResourceContext::SaltCallback& rc, 41 int page_request_id, 42 MediaStreamType type, 43 const GURL& security_origin) { 44 if (type == MEDIA_DEVICE_AUDIO_CAPTURE) { 45 return kAudioLabel; 46 } else { 47 return kVideoLabel; 48 } 49 } 50 }; 51 52 class MockDeviceRequestMessageFilter : public DeviceRequestMessageFilter { 53 public: 54 MockDeviceRequestMessageFilter(MockResourceContext* context, 55 MockMediaStreamManager* manager) 56 : DeviceRequestMessageFilter(context, manager, 0), received_id_(-1) {} 57 StreamDeviceInfoArray requested_devices() { return requested_devices_; } 58 int received_id() { return received_id_; } 59 60 private: 61 virtual ~MockDeviceRequestMessageFilter() {} 62 63 // Override the Send() method to intercept the message that we're sending to 64 // the renderer. 65 virtual bool Send(IPC::Message* reply_msg) OVERRIDE { 66 CHECK(reply_msg); 67 68 bool handled = true; 69 IPC_BEGIN_MESSAGE_MAP(MockDeviceRequestMessageFilter, *reply_msg) 70 IPC_MESSAGE_HANDLER(MediaStreamMsg_GetSourcesACK, SaveDevices) 71 IPC_MESSAGE_UNHANDLED(handled = false) 72 IPC_END_MESSAGE_MAP() 73 EXPECT_TRUE(handled); 74 75 delete reply_msg; 76 return true; 77 } 78 79 void SaveDevices(int request_id, const StreamDeviceInfoArray& devices) { 80 received_id_ = request_id; 81 requested_devices_ = devices; 82 } 83 84 int received_id_; 85 StreamDeviceInfoArray requested_devices_; 86 }; 87 88 class DeviceRequestMessageFilterTest : public testing::Test { 89 public: 90 DeviceRequestMessageFilterTest() : next_device_id_(0) {} 91 92 void RunTest(int number_audio_devices, int number_video_devices) { 93 AddAudioDevices(number_audio_devices); 94 AddVideoDevices(number_video_devices); 95 GURL origin("https://test.com"); 96 EXPECT_CALL(*media_stream_manager_, 97 EnumerateDevices(_, _, _, _, _, MEDIA_DEVICE_AUDIO_CAPTURE, 98 _)) 99 .Times(1); 100 EXPECT_CALL(*media_stream_manager_, 101 EnumerateDevices(_, _, _, _, _, MEDIA_DEVICE_VIDEO_CAPTURE, 102 _)) 103 .Times(1); 104 // Send message to get devices. Should trigger 2 EnumerateDevice() requests. 105 const int kRequestId = 123; 106 SendGetSourcesMessage(kRequestId, origin); 107 108 // Run audio callback. Because there's still an outstanding video request, 109 // this should not populate |message|. 110 FireAudioDeviceCallback(); 111 EXPECT_EQ(0u, host_->requested_devices().size()); 112 113 // After the video device callback is fired, |message| should be populated. 114 FireVideoDeviceCallback(); 115 EXPECT_EQ(static_cast<size_t>(number_audio_devices + number_video_devices), 116 host_->requested_devices().size()); 117 118 EXPECT_EQ(kRequestId, host_->received_id()); 119 } 120 121 protected: 122 virtual ~DeviceRequestMessageFilterTest() {} 123 124 virtual void SetUp() OVERRIDE { 125 message_loop_.reset(new base::MessageLoopForIO); 126 io_thread_.reset( 127 new TestBrowserThread(BrowserThread::IO, message_loop_.get())); 128 129 media_stream_manager_.reset(new MockMediaStreamManager()); 130 ON_CALL(*media_stream_manager_, EnumerateDevices(_, _, _, _, _, _, _)) 131 .WillByDefault(Invoke(media_stream_manager_.get(), 132 &MockMediaStreamManager::DoEnumerateDevices)); 133 134 resource_context_.reset(new MockResourceContext(NULL)); 135 host_ = new MockDeviceRequestMessageFilter(resource_context_.get(), 136 media_stream_manager_.get()); 137 } 138 139 scoped_refptr<MockDeviceRequestMessageFilter> host_; 140 scoped_ptr<MockMediaStreamManager> media_stream_manager_; 141 scoped_ptr<MockResourceContext> resource_context_; 142 StreamDeviceInfoArray physical_audio_devices_; 143 StreamDeviceInfoArray physical_video_devices_; 144 scoped_ptr<base::MessageLoop> message_loop_; 145 scoped_ptr<TestBrowserThread> io_thread_; 146 147 private: 148 void AddAudioDevices(int number_of_devices) { 149 for (int i = 0; i < number_of_devices; i++) { 150 physical_audio_devices_.push_back( 151 StreamDeviceInfo( 152 MEDIA_DEVICE_AUDIO_CAPTURE, 153 "/dev/audio/" + base::IntToString(next_device_id_), 154 "Audio Device" + base::IntToString(next_device_id_))); 155 next_device_id_++; 156 } 157 } 158 159 void AddVideoDevices(int number_of_devices) { 160 for (int i = 0; i < number_of_devices; i++) { 161 physical_video_devices_.push_back( 162 StreamDeviceInfo( 163 MEDIA_DEVICE_VIDEO_CAPTURE, 164 "/dev/video/" + base::IntToString(next_device_id_), 165 "Video Device" + base::IntToString(next_device_id_))); 166 next_device_id_++; 167 } 168 } 169 170 void SendGetSourcesMessage(int request_id, const GURL& origin) { 171 host_->OnMessageReceived(MediaStreamHostMsg_GetSources(request_id, origin)); 172 } 173 174 void FireAudioDeviceCallback() { 175 host_->DevicesEnumerated(-1, -1, kAudioLabel, physical_audio_devices_); 176 } 177 178 void FireVideoDeviceCallback() { 179 host_->DevicesEnumerated(-1, -1, kVideoLabel, physical_video_devices_); 180 } 181 182 int next_device_id_; 183 }; 184 185 TEST_F(DeviceRequestMessageFilterTest, TestGetSources_AudioAndVideoDevices) { 186 // Runs through test with 1 audio and 1 video device. 187 RunTest(1, 1); 188 } 189 190 TEST_F(DeviceRequestMessageFilterTest, 191 TestGetSources_MultipleAudioAndVideoDevices) { 192 // Runs through test with 3 audio devices and 2 video devices. 193 RunTest(3, 2); 194 } 195 196 TEST_F(DeviceRequestMessageFilterTest, TestGetSources_NoVideoDevices) { 197 // Runs through test with 4 audio devices and 0 video devices. 198 RunTest(4, 0); 199 } 200 201 TEST_F(DeviceRequestMessageFilterTest, TestGetSources_NoAudioDevices) { 202 // Runs through test with 0 audio devices and 3 video devices. 203 RunTest(0, 3); 204 } 205 206 TEST_F(DeviceRequestMessageFilterTest, TestGetSources_NoDevices) { 207 // Runs through test with no devices. 208 RunTest(0, 0); 209 } 210 211 }; // namespace content 212