chromium/content/browser/renderer_host/media/media_devices_manager.cc

// Copyright 2016 The Chromium Authors
// 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_manager.h"

#include <stddef.h>
#include <stdint.h>

#include <functional>
#include <map>
#include <string>
#include <vector>

#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/metrics/histogram_functions.h"
#include "base/ranges/algorithm.h"
#include "base/sequence_checker.h"
#include "base/strings/stringprintf.h"
#include "base/task/bind_post_task.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "content/browser/media/media_devices_permission_checker.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/common/features.h"
#include "content/public/browser/audio_service.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h"
#include "media/audio/audio_device_description.h"
#include "media/audio/audio_system.h"
#include "media/base/media_switches.h"
#include "media/capture/capture_switches.h"
#include "media/capture/mojom/video_capture_types.mojom-shared.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/audio/public/mojom/device_notifications.mojom.h"
#include "services/video_capture/public/cpp/features.h"
#include "third_party/blink/public/common/mediastream/media_devices.h"
#include "third_party/blink/public/mojom/mediastream/media_devices.mojom.h"

#if BUILDFLAG(IS_MAC)
#include "base/functional/callback_helpers.h"
#include "base/task/single_thread_task_runner.h"
#include "content/browser/browser_main_loop.h"
#include "media/device_monitors/device_monitor_mac.h"
#endif

namespace content {

namespace {
DeviceEnumerationResult;

// Resolutions used if the source doesn't support capability enumeration.
struct {} const kFallbackVideoResolutions[] =;

// Frame rates for sources with no support for capability enumeration.
const uint16_t kFallbackVideoFrameRates[] =;

void SendLogMessage(const std::string& message) {}

const char* DeviceTypeToString(MediaDeviceType device_type) {}

std::string GetDevicesEnumeratedLogString(
    MediaDeviceType device_type,
    const blink::WebMediaDeviceInfoArray& device_infos) {}

blink::WebMediaDeviceInfoArray GetFakeAudioDevices(bool is_input) {}

std::string VideoLabelWithoutModelID(const std::string& label) {}

bool LabelHasUSBModel(const std::string& label) {}

std::string GetUSBModelFromLabel(const std::string& label) {}

bool IsRealAudioDeviceID(const std::string& device_id) {}

bool EqualDeviceExcludingGroupID(const blink::WebMediaDeviceInfo& lhs,
                                 const blink::WebMediaDeviceInfo& rhs) {}

bool EqualDeviceIncludingGroupID(const blink::WebMediaDeviceInfo& lhs,
                                 const blink::WebMediaDeviceInfo& rhs) {}

void ReplaceInvalidFrameRatesWithFallback(media::VideoCaptureFormats* formats) {}

void BindDeviceNotifierFromUIThread(
    mojo::PendingReceiver<audio::mojom::DeviceNotifier> receiver) {}

void ReportVideoEnumerationStart() {}

void ReportVideoEnumerationResult(DeviceEnumerationResult result_code) {}

BrowserContext* GetBrowserContextOnUIThread(
    GlobalRenderFrameHostId render_frame_host_id) {}

// Sort the devices according to user pref. If the pref is unset or
// the render frame host doesn't have a `BrowserContext` the ordering will be
// unmodified.
void RankDevices(
    GlobalRenderFrameHostId render_frame_host_id,
    const MediaDevicesManager::BoolDeviceTypes& requested_types,
    base::OnceCallback<void(const MediaDeviceEnumeration&)> callback,
    const MediaDeviceEnumeration& enumeration) {}

}  // namespace

std::string GuessVideoGroupID(const blink::WebMediaDeviceInfoArray& audio_infos,
                              const blink::WebMediaDeviceInfo& video_info) {}

struct MediaDevicesManager::EnumerationRequest {};

// This class helps manage the consistency of cached enumeration results.
// It uses a sequence number for each invalidation and enumeration.
// A cache is considered valid if the sequence number for the last enumeration
// is greater than the sequence number for the last invalidation.
// The advantage of using invalidations over directly issuing enumerations upon
// each system notification is that some platforms issue multiple notifications
// on each device change. The cost of performing multiple redundant
// invalidations is significantly lower than the cost of issuing multiple
// redundant enumerations.
class MediaDevicesManager::CacheInfo {};

MediaDevicesManager::SubscriptionRequest::SubscriptionRequest(
    GlobalRenderFrameHostId render_frame_host_id,
    const BoolDeviceTypes& subscribe_types,
    mojo::Remote<blink::mojom::MediaDevicesListener> listener)
    :{}

MediaDevicesManager::SubscriptionRequest::SubscriptionRequest(
    SubscriptionRequest&&) = default;

MediaDevicesManager::SubscriptionRequest::~SubscriptionRequest() = default;

MediaDevicesManager::SubscriptionRequest&
MediaDevicesManager::SubscriptionRequest::operator=(SubscriptionRequest&&) =
    default;

class MediaDevicesManager::AudioServiceDeviceListener
    : public audio::mojom::DeviceListener {};

MediaDevicesManager::MediaDevicesManager(
    media::AudioSystem* audio_system,
    const scoped_refptr<VideoCaptureManager>& video_capture_manager,
    StopRemovedInputDeviceCallback stop_removed_input_device_cb,
    UIInputDeviceChangeCallback ui_input_device_change_cb)
    :{}

MediaDevicesManager::~MediaDevicesManager() {}

void MediaDevicesManager::EnumerateDevices(
    const BoolDeviceTypes& requested_types,
    EnumerationCallback callback) {}

void MediaDevicesManager::EnumerateAndRankDevices(
    GlobalRenderFrameHostId render_frame_host_id,
    const BoolDeviceTypes& requested_types,
    EnumerationCallback callback) {}

void MediaDevicesManager::EnumerateAndRankDevices(
    GlobalRenderFrameHostId render_frame_host_id,
    const BoolDeviceTypes& requested_types,
    bool request_video_input_capabilities,
    bool request_audio_input_capabilities,
    EnumerateDevicesCallback callback) {}

uint32_t MediaDevicesManager::SubscribeDeviceChangeNotifications(
    GlobalRenderFrameHostId render_frame_host_id,
    const BoolDeviceTypes& subscribe_types,
    mojo::PendingRemote<blink::mojom::MediaDevicesListener> listener) {}

void MediaDevicesManager::SetSubscriptionLastSeenDeviceIdSalt(
    uint32_t subscription_id,
    const MediaDeviceSaltAndOrigin& salt_and_origin) {}

void MediaDevicesManager::UnsubscribeDeviceChangeNotifications(
    uint32_t subscription_id) {}

void MediaDevicesManager::SetCachePolicy(MediaDeviceType type,
                                         CachePolicy policy) {}

void MediaDevicesManager::StartMonitoring() {}

void MediaDevicesManager::StopMonitoring() {}

void MediaDevicesManager::OnDevicesChanged(
    base::SystemMonitor::DeviceType device_type) {}

media::VideoCaptureFormats MediaDevicesManager::GetVideoInputFormats(
    const std::string& device_id,
    bool try_in_use_first) {}

blink::WebMediaDeviceInfoArray MediaDevicesManager::GetCachedDeviceInfo(
    MediaDeviceType type) const {}

void MediaDevicesManager::RegisterDispatcherHost(
    std::unique_ptr<blink::mojom::MediaDevicesDispatcherHost> dispatcher_host,
    mojo::PendingReceiver<blink::mojom::MediaDevicesDispatcherHost> receiver) {}

void MediaDevicesManager::SetPermissionChecker(
    std::unique_ptr<MediaDevicesPermissionChecker> permission_checker) {}

void MediaDevicesManager::CheckPermissionsForEnumerateDevices(
    GlobalRenderFrameHostId render_frame_host_id,
    const BoolDeviceTypes& requested_types,
    bool request_video_input_capabilities,
    bool request_audio_input_capabilities,
    EnumerateDevicesCallback callback,
    const MediaDeviceSaltAndOrigin& salt_and_origin) {}

void MediaDevicesManager::OnPermissionsCheckDone(
    GlobalRenderFrameHostId render_frame_host_id,
    const MediaDevicesManager::BoolDeviceTypes& requested_types,
    bool request_video_input_capabilities,
    bool request_audio_input_capabilities,
    EnumerateDevicesCallback callback,
    const MediaDeviceSaltAndOrigin& salt_and_origin,
    const MediaDevicesManager::BoolDeviceTypes& has_permissions) {}

void MediaDevicesManager::OnDevicesEnumerated(
    const MediaDevicesManager::BoolDeviceTypes& requested_types,
    bool request_video_input_capabilities,
    bool request_audio_input_capabilities,
    EnumerateDevicesCallback callback,
    const MediaDeviceSaltAndOrigin& salt_and_origin,
    const MediaDevicesManager::BoolDeviceTypes& has_permissions,
    const MediaDeviceEnumeration& enumeration) {}

void MediaDevicesManager::GetAudioInputCapabilities(
    bool request_video_input_capabilities,
    bool request_audio_input_capabilities,
    EnumerateDevicesCallback callback,
    const MediaDeviceEnumeration& raw_enumeration_results,
    const std::vector<blink::WebMediaDeviceInfoArray>&
        hashed_enumeration_results) {}

void MediaDevicesManager::GotAudioInputCapabilities(
    size_t state_id,
    size_t capabilities_index,
    const std::optional<media::AudioParameters>& parameters) {}

void MediaDevicesManager::FinalizeDevicesEnumerated(
    EnumerationState enumeration_state) {}

std::vector<VideoInputDeviceCapabilitiesPtr>
MediaDevicesManager::ComputeVideoInputCapabilities(
    const blink::WebMediaDeviceInfoArray& raw_device_infos,
    const blink::WebMediaDeviceInfoArray& translated_device_infos) {}

void MediaDevicesManager::DoEnumerateDevices(MediaDeviceType type) {}

void MediaDevicesManager::EnumerateAudioDevices(bool is_input) {}

void MediaDevicesManager::VideoInputDevicesEnumerated(
    DeviceEnumerationResult result_code,
    const media::VideoCaptureDeviceDescriptors& descriptors) {}

void MediaDevicesManager::AudioDevicesEnumerated(
    MediaDeviceType type,
    media::AudioDeviceDescriptions device_descriptions) {}

void MediaDevicesManager::DevicesEnumerated(
    MediaDeviceType type,
    const blink::WebMediaDeviceInfoArray& snapshot) {}

void MediaDevicesManager::UpdateSnapshot(
    MediaDeviceType type,
    const blink::WebMediaDeviceInfoArray& new_snapshot,
    bool ignore_group_id) {}

void MediaDevicesManager::ProcessRequests() {}

bool MediaDevicesManager::IsEnumerationRequestReady(
    const EnumerationRequest& request_info) {}

void MediaDevicesManager::HandleDevicesChanged(MediaDeviceType type) {}

void MediaDevicesManager::MaybeStopRemovedInputDevices(
    MediaDeviceType type,
    const blink::WebMediaDeviceInfoArray& new_snapshot) {}

void MediaDevicesManager::OnSaltAndOriginForSubscription(
    uint32_t subscription_id,
    GlobalRenderFrameHostId render_frame_host_id,
    MediaDeviceType type,
    const blink::WebMediaDeviceInfoArray& device_infos,
    bool devices_changed,
    const MediaDeviceSaltAndOrigin& salt_and_origin) {}

void MediaDevicesManager::CheckPermissionForDeviceChange(
    uint32_t subscription_id,
    GlobalRenderFrameHostId render_frame_host_id,
    MediaDeviceType type,
    const blink::WebMediaDeviceInfoArray& device_infos,
    const MediaDeviceSaltAndOrigin& salt_and_origin) {}

void MediaDevicesManager::OnCheckedPermissionForDeviceChange(
    uint32_t subscription_id,
    GlobalRenderFrameHostId render_frame_host_id,
    MediaDeviceType type,
    const blink::WebMediaDeviceInfoArray& device_infos,
    const MediaDeviceSaltAndOrigin& salt_and_origin,
    bool has_permission) {}

void MediaDevicesManager::NotifyDeviceChange(
    uint32_t subscription_id,
    MediaDeviceType type,
    const MediaDeviceSaltAndOrigin& salt_and_origin,
    bool has_permission,
    const MediaDeviceEnumeration& enumeration) {}

#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
void MediaDevicesManager::RegisterVideoCaptureDevicesChangedObserver() {
  CHECK(!video_capture_service_device_changed_observer_);
  if (base::FeatureList::IsEnabled(
          features::kRunVideoCaptureServiceInBrowserProcess)) {
    // Do not create a mojo connection when the video capture service is running
    // in the browser process as the device monitor will send device change
    // notifications directly to the system monitor in the browser process.
    return;
  }
  // base::Unretained(this) is safe here because |this| owns
  // |video_capture_service_device_changed_observer_|.
  video_capture_service_device_changed_observer_ =
      std::make_unique<VideoCaptureDevicesChangedObserver>(
          /*disconnect_cb=*/base::BindRepeating(
              &MediaDevicesManager::HandleDevicesChanged,
              base::Unretained(this), MediaDeviceType::kMediaVideoInput),
          /*listener_cb=*/base::BindRepeating([] {
            if (auto* monitor = base::SystemMonitor::Get()) {
              monitor->ProcessDevicesChanged(
                  base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
            }
          }));
  video_capture_service_device_changed_observer_->ConnectToService();
}
#endif

MediaDevicesManager::EnumerationState::EnumerationState() = default;
MediaDevicesManager::EnumerationState::EnumerationState(
    EnumerationState&& other) = default;
MediaDevicesManager::EnumerationState::~EnumerationState() = default;
MediaDevicesManager::EnumerationState& MediaDevicesManager::EnumerationState::
operator=(EnumerationState&& other) = default;

}  // namespace content