Index: content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc |
diff --git a/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f980126999dd8d3da854b2ed96b2053323ecc6f6 |
--- /dev/null |
+++ b/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc |
@@ -0,0 +1,255 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/browser/renderer_host/media/media_devices_dispatcher_host.h" |
+ |
+#include <stddef.h> |
+ |
+#include <memory> |
+#include <queue> |
+#include <utility> |
+#include <vector> |
+ |
+#include "base/bind.h" |
+#include "base/command_line.h" |
+#include "base/run_loop.h" |
+#include "base/threading/thread_task_runner_handle.h" |
+#include "content/browser/renderer_host/media/media_stream_manager.h" |
+#include "content/browser/renderer_host/media/media_stream_ui_proxy.h" |
+#include "content/browser/renderer_host/media/video_capture_manager.h" |
+#include "content/public/browser/media_device_id.h" |
+#include "content/public/test/mock_resource_context.h" |
+#include "content/public/test/test_browser_context.h" |
+#include "content/public/test/test_browser_thread_bundle.h" |
+#include "media/audio/audio_device_description.h" |
+#include "media/audio/mock_audio_manager.h" |
+#include "media/base/media_switches.h" |
+#include "media/capture/video/fake_video_capture_device_factory.h" |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "url/origin.h" |
+ |
+namespace content { |
+ |
+namespace { |
+ |
+const int kProcessId = 5; |
+const int kRenderId = 6; |
+ |
+void PhysicalDevicesEnumerated(base::Closure quit_closure, |
+ MediaDeviceEnumeration* out, |
+ const MediaDeviceEnumeration& enumeration) { |
+ *out = enumeration; |
+ quit_closure.Run(); |
+} |
+ |
+} // namespace |
+ |
+class MediaDevicesDispatcherHostTest : public testing::Test { |
+ public: |
+ MediaDevicesDispatcherHostTest() |
+ : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), |
+ origin_(GURL("https://test.com")) { |
+ // Make sure we use fake devices to avoid long delays. |
+ base::CommandLine::ForCurrentProcess()->AppendSwitch( |
+ switches::kUseFakeDeviceForMediaStream); |
+ audio_manager_.reset( |
+ new media::MockAudioManager(base::ThreadTaskRunnerHandle::Get())); |
+ media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); |
+ |
+ MockResourceContext* mock_resource_context = |
+ static_cast<MockResourceContext*>( |
+ browser_context_.GetResourceContext()); |
+ |
+ host_ = base::MakeUnique<MediaDevicesDispatcherHost>( |
+ kProcessId, kRenderId, mock_resource_context->GetMediaDeviceIDSalt(), |
+ media_stream_manager_.get(), true /* use_fake_ui */); |
+ } |
+ |
+ void SetUp() override { |
+ base::RunLoop run_loop; |
+ MediaDevicesManager::BoolDeviceTypes devices_to_enumerate; |
+ devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = true; |
+ devices_to_enumerate[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = true; |
+ devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true; |
+ media_stream_manager_->media_devices_manager()->EnumerateDevices( |
+ devices_to_enumerate, |
+ base::Bind(&PhysicalDevicesEnumerated, run_loop.QuitClosure(), |
+ &physical_devices_)); |
+ run_loop.Run(); |
+ |
+ ASSERT_GT(physical_devices_[MEDIA_DEVICE_TYPE_AUDIO_INPUT].size(), 0u); |
+ ASSERT_GT(physical_devices_[MEDIA_DEVICE_TYPE_VIDEO_INPUT].size(), 0u); |
+ ASSERT_GT(physical_devices_[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT].size(), 0u); |
+ } |
+ |
+ protected: |
+ void DevicesEnumerated( |
+ const base::Closure& closure, |
+ const std::vector<std::vector<MediaDeviceInfo>>& devices) { |
+ enumerated_devices_ = devices; |
+ closure.Run(); |
+ } |
+ |
+ void EnumerateDevicesAndWaitForResult( |
+ bool enumerate_audio_input, |
+ bool enumerate_video_input, |
+ bool enumerate_audio_output, |
+ std::unique_ptr<MediaStreamUIProxy> ui_proxy) { |
+ if (ui_proxy) |
+ host_->SetFakeUIProxyForTesting(std::move(ui_proxy)); |
+ base::RunLoop run_loop; |
+ host_->EnumerateDevices( |
+ enumerate_audio_input, enumerate_video_input, enumerate_audio_output, |
+ origin_, base::Bind(&MediaDevicesDispatcherHostTest::DevicesEnumerated, |
+ base::Unretained(this), run_loop.QuitClosure())); |
+ run_loop.Run(); |
+ |
+ ASSERT_FALSE(enumerated_devices_.empty()); |
+ if (enumerate_audio_input) |
+ EXPECT_FALSE(enumerated_devices_[MEDIA_DEVICE_TYPE_AUDIO_INPUT].empty()); |
+ if (enumerate_video_input) |
+ EXPECT_FALSE(enumerated_devices_[MEDIA_DEVICE_TYPE_VIDEO_INPUT].empty()); |
+ if (enumerate_audio_output) |
+ EXPECT_FALSE(enumerated_devices_[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT].empty()); |
+ |
+ EXPECT_FALSE(DoesContainRawIds(enumerated_devices_)); |
+ EXPECT_TRUE(DoesEveryDeviceMapToRawId(enumerated_devices_, origin_)); |
+ } |
+ |
+ bool DoesContainRawIds( |
+ const std::vector<std::vector<MediaDeviceInfo>>& enumeration) { |
+ for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) { |
+ for (const auto& device_info : enumeration[i]) { |
+ for (const auto& raw_device_info : physical_devices_[i]) { |
+ // Skip default and communications audio devices, whose IDs are not |
+ // translated. |
+ if (device_info.device_id == |
+ media::AudioDeviceDescription::kDefaultDeviceId || |
+ device_info.device_id == |
+ media::AudioDeviceDescription::kCommunicationsDeviceId) { |
+ continue; |
+ } |
+ if (device_info.device_id == raw_device_info.device_id) |
+ return true; |
+ } |
+ } |
+ } |
+ return false; |
+ } |
+ |
+ bool DoesEveryDeviceMapToRawId( |
+ const std::vector<std::vector<MediaDeviceInfo>>& enumeration, |
+ const url::Origin& origin) { |
+ for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) { |
+ for (const auto& device_info : enumeration[i]) { |
+ bool found_match = false; |
+ for (const auto& raw_device_info : physical_devices_[i]) { |
+ if (DoesMediaDeviceIDMatchHMAC( |
+ browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), |
+ origin, device_info.device_id, raw_device_info.device_id)) { |
+ EXPECT_FALSE(found_match); |
+ found_match = true; |
+ } |
+ } |
+ if (!found_match) |
+ return false; |
+ } |
+ } |
+ return true; |
+ } |
+ |
+ // Returns true if all devices have labels, false otherwise. |
+ bool DoesContainLabels( |
+ const std::vector<std::vector<MediaDeviceInfo>>& enumeration) { |
+ for (const auto& device_info_array : enumeration) { |
+ for (const auto& device_info : device_info_array) { |
+ if (device_info.label.empty()) |
+ return false; |
+ } |
+ } |
+ return true; |
+ } |
+ |
+ // Returns true if no devices have labels, false otherwise. |
+ bool DoesNotContainLabels( |
+ const std::vector<std::vector<MediaDeviceInfo>>& enumeration) { |
+ for (const auto& device_info_array : enumeration) { |
+ for (const auto& device_info : device_info_array) { |
+ if (!device_info.label.empty()) |
+ return false; |
+ } |
+ } |
+ return true; |
+ } |
+ |
+ std::unique_ptr<MediaDevicesDispatcherHost> host_; |
+ std::unique_ptr<MediaStreamManager> media_stream_manager_; |
+ content::TestBrowserThreadBundle thread_bundle_; |
+ std::unique_ptr<media::AudioManager, media::AudioManagerDeleter> |
+ audio_manager_; |
+ content::TestBrowserContext browser_context_; |
+ MediaDeviceEnumeration physical_devices_; |
+ url::Origin origin_; |
+ |
+ std::vector<std::vector<MediaDeviceInfo>> enumerated_devices_; |
+}; |
+ |
+TEST_F(MediaDevicesDispatcherHostTest, EnumerateAudioInputDevices) { |
+ EnumerateDevicesAndWaitForResult(true, false, false, nullptr); |
+ EXPECT_TRUE(DoesContainLabels(enumerated_devices_)); |
+} |
+ |
+TEST_F(MediaDevicesDispatcherHostTest, EnumerateVideoInputDevices) { |
+ EnumerateDevicesAndWaitForResult(false, true, false, nullptr); |
+ EXPECT_TRUE(DoesContainLabels(enumerated_devices_)); |
+} |
+ |
+TEST_F(MediaDevicesDispatcherHostTest, EnumerateAudioOutputDevices) { |
+ EnumerateDevicesAndWaitForResult(false, false, true, nullptr); |
+ EXPECT_TRUE(DoesContainLabels(enumerated_devices_)); |
+} |
+ |
+TEST_F(MediaDevicesDispatcherHostTest, EnumerateAllDevices) { |
+ EnumerateDevicesAndWaitForResult(true, true, true, nullptr); |
+ EXPECT_TRUE(DoesContainLabels(enumerated_devices_)); |
+} |
+ |
+TEST_F(MediaDevicesDispatcherHostTest, EnumerateAudioInputDevicesNoAccess) { |
+ std::unique_ptr<FakeMediaStreamUIProxy> fake_ui_proxy = |
+ base::MakeUnique<FakeMediaStreamUIProxy>(); |
+ fake_ui_proxy->SetMicAccess(false); |
+ EnumerateDevicesAndWaitForResult(true, false, false, |
+ std::move(fake_ui_proxy)); |
+ EXPECT_TRUE(DoesNotContainLabels(enumerated_devices_)); |
+} |
+ |
+TEST_F(MediaDevicesDispatcherHostTest, EnumerateVideoInputDevicesNoAccess) { |
+ std::unique_ptr<FakeMediaStreamUIProxy> fake_ui_proxy = |
+ base::MakeUnique<FakeMediaStreamUIProxy>(); |
+ fake_ui_proxy->SetCameraAccess(false); |
+ EnumerateDevicesAndWaitForResult(false, true, false, |
+ std::move(fake_ui_proxy)); |
+ EXPECT_TRUE(DoesNotContainLabels(enumerated_devices_)); |
+} |
+ |
+TEST_F(MediaDevicesDispatcherHostTest, EnumerateAudioOutputDevicesNoAccess) { |
+ std::unique_ptr<FakeMediaStreamUIProxy> fake_ui_proxy = |
+ base::MakeUnique<FakeMediaStreamUIProxy>(); |
+ fake_ui_proxy->SetMicAccess(false); |
+ EnumerateDevicesAndWaitForResult(false, false, true, |
+ std::move(fake_ui_proxy)); |
+ EXPECT_TRUE(DoesNotContainLabels(enumerated_devices_)); |
+} |
+ |
+TEST_F(MediaDevicesDispatcherHostTest, EnumerateAllDevicesNoAccess) { |
+ std::unique_ptr<FakeMediaStreamUIProxy> fake_ui_proxy = |
+ base::MakeUnique<FakeMediaStreamUIProxy>(); |
+ fake_ui_proxy->SetMicAccess(false); |
+ fake_ui_proxy->SetCameraAccess(false); |
+ EnumerateDevicesAndWaitForResult(true, true, true, std::move(fake_ui_proxy)); |
+ EXPECT_TRUE(DoesNotContainLabels(enumerated_devices_)); |
+} |
+ |
+}; // namespace content |