media_stream_dispatcher_host_unittest.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
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#include <queue>
7
8#include "base/bind.h"
9#include "base/callback_helpers.h"
10#include "base/command_line.h"
11#include "base/message_loop/message_loop.h"
12#include "base/run_loop.h"
13#include "content/browser/browser_thread_impl.h"
14#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
15#include "content/browser/renderer_host/media/media_stream_manager.h"
16#include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
17#include "content/browser/renderer_host/media/video_capture_manager.h"
18#include "content/common/media/media_stream_messages.h"
19#include "content/common/media/media_stream_options.h"
20#include "content/public/browser/media_device_id.h"
21#include "content/public/common/content_switches.h"
22#include "content/public/test/mock_resource_context.h"
23#include "content/public/test/test_browser_context.h"
24#include "content/public/test/test_browser_thread_bundle.h"
25#include "content/test/test_content_browser_client.h"
26#include "content/test/test_content_client.h"
27#include "ipc/ipc_message_macros.h"
28#include "media/audio/mock_audio_manager.h"
29#include "media/video/capture/fake_video_capture_device_factory.h"
30#include "net/url_request/url_request_context.h"
31#include "testing/gmock/include/gmock/gmock.h"
32#include "testing/gtest/include/gtest/gtest.h"
33
34using ::testing::_;
35using ::testing::DeleteArg;
36using ::testing::DoAll;
37using ::testing::Return;
38using ::testing::SaveArg;
39
40const int kProcessId = 5;
41const int kRenderId = 6;
42const int kPageRequestId = 7;
43
44namespace content {
45
46class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
47                                      public TestContentBrowserClient {
48 public:
49  MockMediaStreamDispatcherHost(
50      const ResourceContext::SaltCallback salt_callback,
51      const scoped_refptr<base::MessageLoopProxy>& message_loop,
52      MediaStreamManager* manager)
53      : MediaStreamDispatcherHost(kProcessId, salt_callback, manager),
54        message_loop_(message_loop) {}
55
56  // A list of mock methods.
57  MOCK_METHOD4(OnStreamGenerated,
58               void(int routing_id, int request_id, int audio_array_size,
59                    int video_array_size));
60  MOCK_METHOD3(OnStreamGenerationFailed, void(int routing_id,
61                                              int request_id,
62                                              MediaStreamRequestResult result));
63  MOCK_METHOD1(OnDeviceStopped, void(int routing_id));
64  MOCK_METHOD2(OnDeviceOpened, void(int routing_id, int request_id));
65
66  // Accessor to private functions.
67  void OnGenerateStream(int render_view_id,
68                        int page_request_id,
69                        const StreamOptions& components,
70                        const GURL& security_origin,
71                        const base::Closure& quit_closure) {
72    quit_closures_.push(quit_closure);
73    MediaStreamDispatcherHost::OnGenerateStream(
74        render_view_id, page_request_id, components, security_origin, false);
75  }
76
77  void OnStopStreamDevice(int render_view_id,
78                          const std::string& device_id) {
79    MediaStreamDispatcherHost::OnStopStreamDevice(render_view_id, device_id);
80  }
81
82  void OnOpenDevice(int render_view_id,
83                    int page_request_id,
84                    const std::string& device_id,
85                    MediaStreamType type,
86                    const GURL& security_origin,
87                    const base::Closure& quit_closure) {
88    quit_closures_.push(quit_closure);
89    MediaStreamDispatcherHost::OnOpenDevice(
90        render_view_id, page_request_id, device_id, type, security_origin);
91  }
92
93  void OnEnumerateDevices(int render_view_id,
94                          int page_request_id,
95                          MediaStreamType type,
96                          const GURL& security_origin,
97                          const base::Closure& quit_closure) {
98    quit_closures_.push(quit_closure);
99    MediaStreamDispatcherHost::OnEnumerateDevices(
100        render_view_id, page_request_id, type, security_origin);
101  }
102
103  std::string label_;
104  StreamDeviceInfoArray audio_devices_;
105  StreamDeviceInfoArray video_devices_;
106  StreamDeviceInfo opened_device_;
107  StreamDeviceInfoArray enumerated_devices_;
108
109 private:
110  virtual ~MockMediaStreamDispatcherHost() {}
111
112  // This method is used to dispatch IPC messages to the renderer. We intercept
113  // these messages here and dispatch to our mock methods to verify the
114  // conversation between this object and the renderer.
115  virtual bool Send(IPC::Message* message) OVERRIDE {
116    CHECK(message);
117
118    // In this method we dispatch the messages to the according handlers as if
119    // we are the renderer.
120    bool handled = true;
121    IPC_BEGIN_MESSAGE_MAP(MockMediaStreamDispatcherHost, *message)
122      IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerated, OnStreamGenerated)
123      IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerationFailed,
124                          OnStreamGenerationFailed)
125      IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceStopped, OnDeviceStopped)
126      IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpened, OnDeviceOpened)
127      IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerated,
128                          OnDevicesEnumerated)
129      IPC_MESSAGE_UNHANDLED(handled = false)
130    IPC_END_MESSAGE_MAP()
131    EXPECT_TRUE(handled);
132
133    delete message;
134    return true;
135  }
136
137  // These handler methods do minimal things and delegate to the mock methods.
138  void OnStreamGenerated(
139      const IPC::Message& msg,
140      int request_id,
141      std::string label,
142      StreamDeviceInfoArray audio_device_list,
143      StreamDeviceInfoArray video_device_list) {
144    OnStreamGenerated(msg.routing_id(), request_id, audio_device_list.size(),
145        video_device_list.size());
146    // Notify that the event have occurred.
147    base::Closure quit_closure = quit_closures_.front();
148    quit_closures_.pop();
149    message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure));
150
151    label_ = label;
152    audio_devices_ = audio_device_list;
153    video_devices_ = video_device_list;
154  }
155
156  void OnStreamGenerationFailed(
157      const IPC::Message& msg,
158      int request_id,
159      content::MediaStreamRequestResult result) {
160    OnStreamGenerationFailed(msg.routing_id(), request_id, result);
161    if (!quit_closures_.empty()) {
162      base::Closure quit_closure = quit_closures_.front();
163      quit_closures_.pop();
164      message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure));
165    }
166
167    label_= "";
168  }
169
170  void OnDeviceStopped(const IPC::Message& msg,
171                       const std::string& label,
172                       const content::StreamDeviceInfo& device) {
173    if (IsVideoMediaType(device.device.type))
174      EXPECT_TRUE(StreamDeviceInfo::IsEqual(device, video_devices_[0]));
175    if (IsAudioMediaType(device.device.type))
176      EXPECT_TRUE(StreamDeviceInfo::IsEqual(device, audio_devices_[0]));
177
178    OnDeviceStopped(msg.routing_id());
179  }
180
181  void OnDeviceOpened(const IPC::Message& msg,
182                      int request_id,
183                      const std::string& label,
184                      const StreamDeviceInfo& device) {
185    base::Closure quit_closure = quit_closures_.front();
186    quit_closures_.pop();
187    message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure));
188    label_ = label;
189    opened_device_ = device;
190  }
191
192  void OnDevicesEnumerated(const IPC::Message& msg,
193                           int request_id,
194                           const StreamDeviceInfoArray& devices) {
195    base::Closure quit_closure = quit_closures_.front();
196    quit_closures_.pop();
197    message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure));
198    enumerated_devices_ = devices;
199  }
200
201  scoped_refptr<base::MessageLoopProxy> message_loop_;
202
203  std::queue<base::Closure> quit_closures_;
204};
205
206class MockMediaStreamUIProxy : public FakeMediaStreamUIProxy {
207 public:
208  MOCK_METHOD2(
209      OnStarted,
210      void(const base::Closure& stop,
211           const MediaStreamUIProxy::WindowIdCallback& window_id_callback));
212};
213
214class MediaStreamDispatcherHostTest : public testing::Test {
215 public:
216  MediaStreamDispatcherHostTest()
217      : old_browser_client_(NULL),
218        thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
219        origin_("https://test.com") {
220    audio_manager_.reset(
221        new media::MockAudioManager(base::MessageLoopProxy::current()));
222    // Make sure we use fake devices to avoid long delays.
223    CommandLine::ForCurrentProcess()->AppendSwitch(
224        switches::kUseFakeDeviceForMediaStream);
225    // Create our own MediaStreamManager.
226    media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
227    video_capture_device_factory_ =
228        static_cast<media::FakeVideoCaptureDeviceFactory*>(
229            media_stream_manager_->video_capture_manager()
230            ->video_capture_device_factory());
231    DCHECK(video_capture_device_factory_);
232
233    host_ = new MockMediaStreamDispatcherHost(
234        browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
235        base::MessageLoopProxy::current(),
236        media_stream_manager_.get());
237
238    // Use the fake content client and browser.
239    content_client_.reset(new TestContentClient());
240    SetContentClient(content_client_.get());
241    old_browser_client_ = SetBrowserClientForTesting(host_.get());
242  }
243
244  virtual ~MediaStreamDispatcherHostTest() {
245  }
246
247  virtual void SetUp() OVERRIDE {
248    video_capture_device_factory_->GetDeviceNames(&physical_video_devices_);
249    ASSERT_GT(physical_video_devices_.size(), 0u);
250
251    audio_manager_->GetAudioInputDeviceNames(&physical_audio_devices_);
252    ASSERT_GT(physical_audio_devices_.size(), 0u);
253  }
254
255  virtual void TearDown() OVERRIDE {
256    host_->OnChannelClosing();
257  }
258
259 protected:
260  virtual void SetupFakeUI(bool expect_started) {
261    scoped_ptr<MockMediaStreamUIProxy> stream_ui(new MockMediaStreamUIProxy());
262    if (expect_started) {
263      EXPECT_CALL(*stream_ui, OnStarted(_, _));
264    }
265    media_stream_manager_->UseFakeUI(
266        stream_ui.PassAs<FakeMediaStreamUIProxy>());
267  }
268
269  void GenerateStreamAndWaitForResult(int render_view_id,
270                                      int page_request_id,
271                                      const StreamOptions& options) {
272    base::RunLoop run_loop;
273    int expected_audio_array_size =
274        (options.audio_requested &&
275         physical_audio_devices_.size() > 0) ? 1 : 0;
276    int expected_video_array_size =
277        (options.video_requested &&
278         physical_video_devices_.size() > 0) ? 1 : 0;
279    EXPECT_CALL(*host_.get(), OnStreamGenerated(render_view_id, page_request_id,
280                                                expected_audio_array_size,
281                                                expected_video_array_size));
282    host_->OnGenerateStream(render_view_id, page_request_id, options, origin_,
283                            run_loop.QuitClosure());
284    run_loop.Run();
285    EXPECT_FALSE(DoesContainRawIds(host_->audio_devices_));
286    EXPECT_FALSE(DoesContainRawIds(host_->video_devices_));
287    EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->audio_devices_, origin_));
288    EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->video_devices_, origin_));
289  }
290
291  void GenerateStreamAndWaitForFailure(
292    int render_view_id,
293    int page_request_id,
294    const StreamOptions& options,
295    MediaStreamRequestResult expected_result) {
296      base::RunLoop run_loop;
297      EXPECT_CALL(*host_.get(),
298                  OnStreamGenerationFailed(render_view_id,
299                                           page_request_id,
300                                           expected_result));
301      host_->OnGenerateStream(render_view_id, page_request_id, options, origin_,
302                              run_loop.QuitClosure());
303      run_loop.Run();
304  }
305
306  void OpenVideoDeviceAndWaitForResult(int render_view_id,
307                                       int page_request_id,
308                                       const std::string& device_id) {
309    base::RunLoop run_loop;
310    host_->OnOpenDevice(render_view_id, page_request_id, device_id,
311                        MEDIA_DEVICE_VIDEO_CAPTURE, origin_,
312                        run_loop.QuitClosure());
313    run_loop.Run();
314    EXPECT_FALSE(DoesContainRawIds(host_->video_devices_));
315    EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->video_devices_, origin_));
316  }
317
318  void EnumerateDevicesAndWaitForResult(int render_view_id,
319                                        int page_request_id,
320                                        MediaStreamType type) {
321    base::RunLoop run_loop;
322    host_->OnEnumerateDevices(render_view_id, page_request_id, type, origin_,
323                              run_loop.QuitClosure());
324    run_loop.Run();
325    ASSERT_FALSE(host_->enumerated_devices_.empty());
326    EXPECT_FALSE(DoesContainRawIds(host_->enumerated_devices_));
327    EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->enumerated_devices_, origin_));
328  }
329
330  bool DoesContainRawIds(const StreamDeviceInfoArray& devices) {
331    for (size_t i = 0; i < devices.size(); ++i) {
332      media::AudioDeviceNames::const_iterator audio_it =
333          physical_audio_devices_.begin();
334      for (; audio_it != physical_audio_devices_.end(); ++audio_it) {
335        if (audio_it->unique_id == devices[i].device.id)
336          return true;
337      }
338      media::VideoCaptureDevice::Names::const_iterator video_it =
339          physical_video_devices_.begin();
340      for (; video_it != physical_video_devices_.end(); ++video_it) {
341        if (video_it->id() == devices[i].device.id)
342          return true;
343      }
344    }
345    return false;
346  }
347
348  bool DoesEveryDeviceMapToRawId(const StreamDeviceInfoArray& devices,
349                                 const GURL& origin) {
350    for (size_t i = 0; i < devices.size(); ++i) {
351      bool found_match = false;
352      media::AudioDeviceNames::const_iterator audio_it =
353          physical_audio_devices_.begin();
354      for (; audio_it != physical_audio_devices_.end(); ++audio_it) {
355        if (content::DoesMediaDeviceIDMatchHMAC(
356                browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
357                origin,
358                devices[i].device.id,
359                audio_it->unique_id)) {
360          EXPECT_FALSE(found_match);
361          found_match = true;
362        }
363      }
364      media::VideoCaptureDevice::Names::const_iterator video_it =
365          physical_video_devices_.begin();
366      for (; video_it != physical_video_devices_.end(); ++video_it) {
367        if (content::DoesMediaDeviceIDMatchHMAC(
368                browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
369                origin,
370                devices[i].device.id,
371                video_it->id())) {
372          EXPECT_FALSE(found_match);
373          found_match = true;
374        }
375      }
376      if (!found_match)
377        return false;
378    }
379    return true;
380  }
381
382  void AddSourceIdConstraint(const std::string& source_id,
383                             StreamOptions::Constraints* constraints) {
384    constraints->push_back(StreamOptions::Constraint(kMediaStreamSourceInfoId,
385                                                     source_id));
386  }
387
388  scoped_refptr<MockMediaStreamDispatcherHost> host_;
389  scoped_ptr<media::AudioManager> audio_manager_;
390  scoped_ptr<MediaStreamManager> media_stream_manager_;
391  ContentBrowserClient* old_browser_client_;
392  scoped_ptr<ContentClient> content_client_;
393  content::TestBrowserThreadBundle thread_bundle_;
394  content::TestBrowserContext browser_context_;
395  media::AudioDeviceNames physical_audio_devices_;
396  media::VideoCaptureDevice::Names physical_video_devices_;
397  GURL origin_;
398  media::FakeVideoCaptureDeviceFactory* video_capture_device_factory_;
399};
400
401TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithVideoOnly) {
402  StreamOptions options(false, true);
403
404  SetupFakeUI(true);
405  GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
406
407  EXPECT_EQ(host_->audio_devices_.size(), 0u);
408  EXPECT_EQ(host_->video_devices_.size(), 1u);
409}
410
411TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioOnly) {
412  StreamOptions options(true, false);
413
414  SetupFakeUI(true);
415  GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
416
417  EXPECT_EQ(host_->audio_devices_.size(), 1u);
418  EXPECT_EQ(host_->video_devices_.size(), 0u);
419}
420
421TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithNothing) {
422  StreamOptions options(false, false);
423
424  GenerateStreamAndWaitForFailure(
425      kRenderId,
426      kPageRequestId,
427      options,
428      MEDIA_DEVICE_INVALID_STATE);
429}
430
431TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioAndVideo) {
432  StreamOptions options(true, true);
433
434  SetupFakeUI(true);
435  GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
436
437  EXPECT_EQ(host_->audio_devices_.size(), 1u);
438  EXPECT_EQ(host_->video_devices_.size(), 1u);
439}
440
441// This test generates two streams with video only using the same render view
442// id. The same capture device  with the same device and session id is expected
443// to be used.
444TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsFromSameRenderId) {
445  StreamOptions options(false, true);
446
447  // Generate first stream.
448  SetupFakeUI(true);
449  GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
450
451  // Check the latest generated stream.
452  EXPECT_EQ(host_->audio_devices_.size(), 0u);
453  EXPECT_EQ(host_->video_devices_.size(), 1u);
454  const std::string label1 = host_->label_;
455  const std::string device_id1 = host_->video_devices_.front().device.id;
456  const int session_id1 = host_->video_devices_.front().session_id;
457
458  // Generate second stream.
459  SetupFakeUI(true);
460  GenerateStreamAndWaitForResult(kRenderId, kPageRequestId + 1, options);
461
462  // Check the latest generated stream.
463  EXPECT_EQ(host_->audio_devices_.size(), 0u);
464  EXPECT_EQ(host_->video_devices_.size(), 1u);
465  const std::string label2 = host_->label_;
466  const std::string device_id2 = host_->video_devices_.front().device.id;
467  int session_id2 = host_->video_devices_.front().session_id;
468  EXPECT_EQ(device_id1, device_id2);
469  EXPECT_EQ(session_id1, session_id2);
470  EXPECT_NE(label1, label2);
471}
472
473TEST_F(MediaStreamDispatcherHostTest,
474       GenerateStreamAndOpenDeviceFromSameRenderId) {
475  StreamOptions options(false, true);
476
477  // Generate first stream.
478  SetupFakeUI(true);
479  GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
480
481  EXPECT_EQ(host_->audio_devices_.size(), 0u);
482  EXPECT_EQ(host_->video_devices_.size(), 1u);
483  const std::string label1 = host_->label_;
484  const std::string device_id1 = host_->video_devices_.front().device.id;
485  const int session_id1 = host_->video_devices_.front().session_id;
486
487  // Generate second stream.
488  OpenVideoDeviceAndWaitForResult(kRenderId, kPageRequestId, device_id1);
489
490  const std::string device_id2 = host_->opened_device_.device.id;
491  const int session_id2 = host_->opened_device_.session_id;
492  const std::string label2 = host_->label_;
493
494  EXPECT_EQ(device_id1, device_id2);
495  EXPECT_NE(session_id1, session_id2);
496  EXPECT_NE(label1, label2);
497}
498
499
500// This test generates two streams with video only using two separate render
501// view ids. The same device id but different session ids are expected.
502TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsDifferentRenderId) {
503  StreamOptions options(false, true);
504
505  // Generate first stream.
506  SetupFakeUI(true);
507  GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
508
509  // Check the latest generated stream.
510  EXPECT_EQ(host_->audio_devices_.size(), 0u);
511  EXPECT_EQ(host_->video_devices_.size(), 1u);
512  const std::string label1 = host_->label_;
513  const std::string device_id1 = host_->video_devices_.front().device.id;
514  const int session_id1 = host_->video_devices_.front().session_id;
515
516  // Generate second stream from another render view.
517  SetupFakeUI(true);
518  GenerateStreamAndWaitForResult(kRenderId+1, kPageRequestId + 1, options);
519
520  // Check the latest generated stream.
521  EXPECT_EQ(host_->audio_devices_.size(), 0u);
522  EXPECT_EQ(host_->video_devices_.size(), 1u);
523  const std::string label2 = host_->label_;
524  const std::string device_id2 = host_->video_devices_.front().device.id;
525  const int session_id2 = host_->video_devices_.front().session_id;
526  EXPECT_EQ(device_id1, device_id2);
527  EXPECT_NE(session_id1, session_id2);
528  EXPECT_NE(label1, label2);
529}
530
531// This test request two streams with video only without waiting for the first
532// stream to be generated before requesting the second.
533// The same device id and session ids are expected.
534TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithoutWaiting) {
535  StreamOptions options(false, true);
536
537  // Generate first stream.
538  SetupFakeUI(true);
539  EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
540
541  // Generate second stream.
542  EXPECT_CALL(*host_.get(),
543              OnStreamGenerated(kRenderId, kPageRequestId + 1, 0, 1));
544
545  base::RunLoop run_loop1;
546  base::RunLoop run_loop2;
547  host_->OnGenerateStream(kRenderId, kPageRequestId, options, origin_,
548                          run_loop1.QuitClosure());
549  host_->OnGenerateStream(kRenderId, kPageRequestId + 1, options, origin_,
550                          run_loop2.QuitClosure());
551
552  run_loop1.Run();
553  run_loop2.Run();
554}
555
556// Test that we can generate streams where a mandatory sourceId is specified in
557// the request.
558TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithMandatorySourceId) {
559  ASSERT_GE(physical_audio_devices_.size(), 1u);
560  ASSERT_GE(physical_video_devices_.size(), 1u);
561
562  media::AudioDeviceNames::const_iterator audio_it =
563      physical_audio_devices_.begin();
564  for (; audio_it != physical_audio_devices_.end(); ++audio_it) {
565    std::string source_id = content::GetHMACForMediaDeviceID(
566        browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
567        origin_,
568        audio_it->unique_id);
569    ASSERT_FALSE(source_id.empty());
570    StreamOptions options(true, true);
571    AddSourceIdConstraint(source_id, &options.mandatory_audio);
572
573    SetupFakeUI(true);
574    GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
575    EXPECT_EQ(host_->audio_devices_[0].device.id, source_id);
576  }
577
578  media::VideoCaptureDevice::Names::const_iterator video_it =
579      physical_video_devices_.begin();
580  for (; video_it != physical_video_devices_.end(); ++video_it) {
581    std::string source_id = content::GetHMACForMediaDeviceID(
582        browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
583        origin_,
584        video_it->id());
585    ASSERT_FALSE(source_id.empty());
586    StreamOptions options(true, true);
587    AddSourceIdConstraint(source_id, &options.mandatory_video);
588
589    SetupFakeUI(true);
590    GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
591    EXPECT_EQ(host_->video_devices_[0].device.id, source_id);
592  }
593}
594
595// Test that we can generate streams where a optional sourceId is specified in
596// the request.
597TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithOptionalSourceId) {
598  ASSERT_GE(physical_audio_devices_.size(), 1u);
599  ASSERT_GE(physical_video_devices_.size(), 1u);
600
601  media::AudioDeviceNames::const_iterator audio_it =
602      physical_audio_devices_.begin();
603  for (; audio_it != physical_audio_devices_.end(); ++audio_it) {
604    std::string source_id = content::GetHMACForMediaDeviceID(
605        browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
606        origin_,
607        audio_it->unique_id);
608    ASSERT_FALSE(source_id.empty());
609    StreamOptions options(true, true);
610    AddSourceIdConstraint(source_id, &options.optional_audio);
611
612    SetupFakeUI(true);
613    GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
614    EXPECT_EQ(host_->audio_devices_[0].device.id, source_id);
615  }
616
617  media::VideoCaptureDevice::Names::const_iterator video_it =
618      physical_video_devices_.begin();
619  for (; video_it != physical_video_devices_.end(); ++video_it) {
620    std::string source_id = content::GetHMACForMediaDeviceID(
621        browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
622        origin_,
623        video_it->id());
624    ASSERT_FALSE(source_id.empty());
625    StreamOptions options(true, true);
626    AddSourceIdConstraint(source_id, &options.optional_video);
627
628    SetupFakeUI(true);
629    GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
630    EXPECT_EQ(host_->video_devices_[0].device.id, source_id);
631  }
632}
633
634// Test that generating a stream with an invalid mandatory video source id fail.
635TEST_F(MediaStreamDispatcherHostTest,
636       GenerateStreamsWithInvalidMandatoryVideoSourceId) {
637  StreamOptions options(true, true);
638  AddSourceIdConstraint("invalid source id", &options.mandatory_video);
639
640  GenerateStreamAndWaitForFailure(
641      kRenderId,
642      kPageRequestId,
643      options,
644      MEDIA_DEVICE_NO_HARDWARE);
645}
646
647// Test that generating a stream with an invalid mandatory audio source id fail.
648TEST_F(MediaStreamDispatcherHostTest,
649       GenerateStreamsWithInvalidMandatoryAudioSourceId) {
650  StreamOptions options(true, true);
651  AddSourceIdConstraint("invalid source id", &options.mandatory_audio);
652
653  GenerateStreamAndWaitForFailure(
654      kRenderId,
655      kPageRequestId,
656      options,
657      MEDIA_DEVICE_NO_HARDWARE);
658}
659
660// Test that generating a stream with an invalid optional video source id
661// succeed.
662TEST_F(MediaStreamDispatcherHostTest,
663       GenerateStreamsWithInvalidOptionalVideoSourceId) {
664  StreamOptions options(true, true);
665  AddSourceIdConstraint("invalid source id", &options.optional_video);
666
667  SetupFakeUI(true);
668  GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
669}
670
671// Test that generating a stream with an invalid optional audio source id
672// succeed.
673TEST_F(MediaStreamDispatcherHostTest,
674       GenerateStreamsWithInvalidOptionalAudioSourceId) {
675  StreamOptions options(true, true);
676  AddSourceIdConstraint("invalid source id", &options.optional_audio);
677
678  SetupFakeUI(true);
679  GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
680}
681
682TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsNoAvailableVideoDevice) {
683  physical_video_devices_.clear();
684  video_capture_device_factory_->set_number_of_devices(0);
685  video_capture_device_factory_->GetDeviceNames(&physical_video_devices_);
686  StreamOptions options(true, true);
687
688  SetupFakeUI(false);
689  GenerateStreamAndWaitForFailure(kRenderId, kPageRequestId, options,
690                                  MEDIA_DEVICE_NO_HARDWARE);
691}
692
693// Test that if a OnStopStreamDevice message is received for a device that has
694// been opened in a MediaStream and by pepper, the device is only stopped for
695// the MediaStream.
696TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStream) {
697  StreamOptions options(false, true);
698
699  SetupFakeUI(true);
700  GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
701
702  std::string stream_request_label = host_->label_;
703  StreamDeviceInfo video_device_info = host_->video_devices_.front();
704  ASSERT_EQ(1u, media_stream_manager_->GetDevicesOpenedByRequest(
705      stream_request_label).size());
706
707  // Open the same device by Pepper.
708  OpenVideoDeviceAndWaitForResult(kRenderId, kPageRequestId,
709                                  video_device_info.device.id);
710  std::string open_device_request_label = host_->label_;
711
712  // Stop the device in the MediaStream.
713  host_->OnStopStreamDevice(kRenderId, video_device_info.device.id);
714
715  EXPECT_EQ(0u, media_stream_manager_->GetDevicesOpenedByRequest(
716      stream_request_label).size());
717  EXPECT_EQ(1u, media_stream_manager_->GetDevicesOpenedByRequest(
718      open_device_request_label).size());
719}
720
721TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStreamAndRestart) {
722  StreamOptions options(true, true);
723
724  SetupFakeUI(true);
725  GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
726
727  std::string request_label1 = host_->label_;
728  StreamDeviceInfo video_device_info = host_->video_devices_.front();
729  // Expect that 1 audio and 1 video device has been opened.
730  EXPECT_EQ(2u, media_stream_manager_->GetDevicesOpenedByRequest(
731      request_label1).size());
732
733  host_->OnStopStreamDevice(kRenderId, video_device_info.device.id);
734  EXPECT_EQ(1u, media_stream_manager_->GetDevicesOpenedByRequest(
735      request_label1).size());
736
737  GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
738  std::string request_label2 = host_->label_;
739
740  StreamDeviceInfoArray request1_devices =
741      media_stream_manager_->GetDevicesOpenedByRequest(request_label1);
742  StreamDeviceInfoArray request2_devices =
743      media_stream_manager_->GetDevicesOpenedByRequest(request_label2);
744
745  ASSERT_EQ(1u, request1_devices.size());
746  ASSERT_EQ(2u, request2_devices.size());
747
748  // Test that the same audio device has been opened in both streams.
749  EXPECT_TRUE(StreamDeviceInfo::IsEqual(request1_devices[0],
750                                        request2_devices[0]) ||
751              StreamDeviceInfo::IsEqual(request1_devices[0],
752                                        request2_devices[1]));
753}
754
755TEST_F(MediaStreamDispatcherHostTest,
756       GenerateTwoStreamsAndStopDeviceWhileWaitingForSecondStream) {
757  StreamOptions options(false, true);
758
759  SetupFakeUI(true);
760  GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
761  EXPECT_EQ(host_->video_devices_.size(), 1u);
762
763  // Generate a second stream.
764  EXPECT_CALL(*host_.get(),
765              OnStreamGenerated(kRenderId, kPageRequestId + 1, 0, 1));
766
767  base::RunLoop run_loop1;
768  host_->OnGenerateStream(kRenderId, kPageRequestId + 1, options, origin_,
769                          run_loop1.QuitClosure());
770
771  // Stop the video stream device from stream 1 while waiting for the
772  // second stream to be generated.
773  host_->OnStopStreamDevice(kRenderId, host_->video_devices_[0].device.id);
774  run_loop1.Run();
775
776  EXPECT_EQ(host_->video_devices_.size(), 1u);
777}
778
779TEST_F(MediaStreamDispatcherHostTest, CancelPendingStreamsOnChannelClosing) {
780  StreamOptions options(false, true);
781
782  base::RunLoop run_loop;
783
784  // Create multiple GenerateStream requests.
785  size_t streams = 5;
786  for (size_t i = 1; i <= streams; ++i) {
787    host_->OnGenerateStream(kRenderId, kPageRequestId + i, options, origin_,
788                            run_loop.QuitClosure());
789  }
790
791  // Calling OnChannelClosing() to cancel all the pending requests.
792  host_->OnChannelClosing();
793  run_loop.RunUntilIdle();
794}
795
796TEST_F(MediaStreamDispatcherHostTest, StopGeneratedStreamsOnChannelClosing) {
797  StreamOptions options(false, true);
798
799  // Create first group of streams.
800  size_t generated_streams = 3;
801  for (size_t i = 0; i < generated_streams; ++i) {
802    SetupFakeUI(true);
803    GenerateStreamAndWaitForResult(kRenderId, kPageRequestId + i, options);
804  }
805
806  // Calling OnChannelClosing() to cancel all the pending/generated streams.
807  host_->OnChannelClosing();
808  base::RunLoop().RunUntilIdle();
809}
810
811TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) {
812  StreamOptions options(false, true);
813
814  base::Closure close_callback;
815  scoped_ptr<MockMediaStreamUIProxy> stream_ui(new MockMediaStreamUIProxy());
816  EXPECT_CALL(*stream_ui, OnStarted(_, _))
817      .WillOnce(SaveArg<0>(&close_callback));
818  media_stream_manager_->UseFakeUI(stream_ui.PassAs<FakeMediaStreamUIProxy>());
819
820  GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
821
822  EXPECT_EQ(host_->audio_devices_.size(), 0u);
823  EXPECT_EQ(host_->video_devices_.size(), 1u);
824
825  ASSERT_FALSE(close_callback.is_null());
826  EXPECT_CALL(*host_.get(), OnDeviceStopped(kRenderId));
827  close_callback.Run();
828  base::RunLoop().RunUntilIdle();
829}
830
831// Test that the dispatcher is notified if a video device that is in use is
832// being unplugged.
833TEST_F(MediaStreamDispatcherHostTest, VideoDeviceUnplugged) {
834  StreamOptions options(true, true);
835  SetupFakeUI(true);
836  GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
837  EXPECT_EQ(host_->audio_devices_.size(), 1u);
838  EXPECT_EQ(host_->video_devices_.size(), 1u);
839
840  video_capture_device_factory_->set_number_of_devices(0);
841
842  base::RunLoop run_loop;
843  EXPECT_CALL(*host_.get(), OnDeviceStopped(kRenderId))
844      .WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
845  media_stream_manager_->OnDevicesChanged(
846      base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
847
848  run_loop.Run();
849}
850
851TEST_F(MediaStreamDispatcherHostTest, EnumerateAudioDevices) {
852  EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId,
853                                   MEDIA_DEVICE_AUDIO_CAPTURE);
854}
855
856TEST_F(MediaStreamDispatcherHostTest, EnumerateVideoDevices) {
857  EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId,
858                                   MEDIA_DEVICE_VIDEO_CAPTURE);
859}
860
861};  // namespace content
862