• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
MockMediaStreamDispatcherEventHandler()37   MockMediaStreamDispatcherEventHandler()
38       : request_id_(-1) {}
39 
OnStreamGenerated(int request_id,const std::string & label,const StreamDeviceInfoArray & audio_device_array,const StreamDeviceInfoArray & video_device_array)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 
OnStreamGenerationFailed(int request_id,content::MediaStreamRequestResult result)57   virtual void OnStreamGenerationFailed(
58       int request_id,
59       content::MediaStreamRequestResult result) OVERRIDE {
60     request_id_ = request_id;
61   }
62 
OnDeviceStopped(const std::string & label,const StreamDeviceInfo & device_info)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 
OnDevicesEnumerated(int request_id,const StreamDeviceInfoArray & device_array)74   virtual void OnDevicesEnumerated(
75       int request_id,
76       const StreamDeviceInfoArray& device_array) OVERRIDE {
77     request_id_ = request_id;
78   }
79 
OnDeviceOpened(int request_id,const std::string & label,const StreamDeviceInfo & video_device)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 
OnDeviceOpenFailed(int request_id)88   virtual void OnDeviceOpenFailed(int request_id) OVERRIDE {
89     request_id_ = request_id;
90   }
91 
ResetStoredParameters()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:
MediaStreamDispatcherUnderTest()109   MediaStreamDispatcherUnderTest() : MediaStreamDispatcher(NULL) {}
110 
111   using MediaStreamDispatcher::GetNextIpcIdForTest;
112   using RenderFrameObserver::OnMessageReceived;
113 };
114 
115 class MediaStreamDispatcherTest : public ::testing::Test {
116  public:
MediaStreamDispatcherTest()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.
GenerateStream(const StreamOptions & options,int request_id)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.
CompleteGenerateStream(int ipc_id,const StreamOptions & options,int request_id)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 
TEST_F(MediaStreamDispatcherTest,GenerateStreamAndStopDevices)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 
TEST_F(MediaStreamDispatcherTest,BasicVideoDevice)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 
TEST_F(MediaStreamDispatcherTest,TestFailure)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 
TEST_F(MediaStreamDispatcherTest,CancelGenerateStream)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.
TEST_F(MediaStreamDispatcherTest,DeviceClosed)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 
TEST_F(MediaStreamDispatcherTest,CheckDuckingState)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