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