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