1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130

content / browser / renderer_host / media / audio_output_authorization_handler.h [blame]

// 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.

#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_OUTPUT_AUTHORIZATION_HANDLER_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_OUTPUT_AUTHORIZATION_HANDLER_H_

#include <memory>
#include <string>
#include <utility>

#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "content/browser/media/media_devices_util.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/common/content_export.h"
#include "media/audio/audio_device_description.h"
#include "media/base/audio_parameters.h"
#include "media/base/output_device_info.h"

namespace media {
class AudioSystem;
}

namespace content {

// This class, which lives on the IO thread, handles the logic of an IPC device
// request from the renderer. It checks which device to use (in case of using
// |session_id| to select device), verifies that the renderer is authorized to
// use the device, and gets the default device parameters for the selected audio
// device.
class CONTENT_EXPORT AudioOutputAuthorizationHandler {
 public:
  // Convention: Something named |device_id| is hashed and something named
  // |raw_device_id| is not hashed.

  // The result of an authorization check. In addition to the status, it
  // provides the default parameters of the device and the raw device id.
  // |device_id_for_renderer| is either the hashed device id, if it should be
  // sent to the renderer, or "", if it shouldn't.
  using AuthorizationCompletedCallback =
      base::OnceCallback<void(media::OutputDeviceStatus status,
                              const media::AudioParameters& params,
                              const std::string& raw_device_id,
                              const std::string& device_id_for_renderer)>;

  AudioOutputAuthorizationHandler(media::AudioSystem* audio_system,
                                  MediaStreamManager* media_stream_manager,
                                  int render_process_id_);

  AudioOutputAuthorizationHandler(const AudioOutputAuthorizationHandler&) =
      delete;
  AudioOutputAuthorizationHandler& operator=(
      const AudioOutputAuthorizationHandler&) = delete;

  ~AudioOutputAuthorizationHandler();

  // Checks authorization of the device with the hashed id |device_id| for the
  // given render frame id, or uses |session_id| for authorization. Looks up
  // device id (if |session_id| is used for device selection) and default
  // device parameters. This function will always call |cb|.
  void RequestDeviceAuthorization(int render_frame_id,
                                  const base::UnguessableToken& session_id,
                                  const std::string& device_id,
                                  AuthorizationCompletedCallback cb) const;

  // Calling this method will make the checks for permission from the user
  // always return |override_value|.
  void OverridePermissionsForTesting(bool override_value);

  // Calling this method will grant authorization to the device with the given
  // hashed id until this method is called again with a different id. If
  // |hashed_device_id| is the empty string, then this permission will be unset.
  // |hashed_device_id| is a hash of the raw device id that is usable only on
  // one origin.
  void SetAuthorizedDeviceIdForGlobalMediaControls(
      std::string hashed_device_id);

  static void UMALogDeviceAuthorizationTime(base::TimeTicks auth_start_time);

 private:
  // Helper class for recording traces.
  class TraceScope;

  void HashDeviceId(std::unique_ptr<TraceScope> trace_scope,
                    AuthorizationCompletedCallback cb,
                    const std::string& raw_device_id,
                    const MediaDeviceSaltAndOrigin& salt_and_origin) const;

  void AccessChecked(std::unique_ptr<TraceScope> trace_scope,
                     AuthorizationCompletedCallback cb,
                     const std::string& device_id,
                     MediaDeviceSaltAndOrigin salt_and_origin,
                     bool has_access) const;

  void TranslateDeviceID(std::unique_ptr<TraceScope> trace_scope,
                         AuthorizationCompletedCallback cb,
                         const std::string& device_id,
                         const MediaDeviceSaltAndOrigin& salt_and_origin,
                         const MediaDeviceEnumeration& enumeration) const;

  void GetDeviceParameters(std::unique_ptr<TraceScope> trace_scope,
                           AuthorizationCompletedCallback cb,
                           const std::string& raw_device_id) const;

  void DeviceParametersReceived(
      std::unique_ptr<TraceScope> trace_scope,
      AuthorizationCompletedCallback cb,
      const std::string& device_id_for_renderer,
      const std::string& raw_device_id,
      const std::optional<media::AudioParameters>& params) const;

  const raw_ptr<media::AudioSystem> audio_system_;
  const raw_ptr<MediaStreamManager> media_stream_manager_;
  const int render_process_id_;
  bool override_permissions_ = false;
  bool permissions_override_value_ = false;
  std::string hashed_device_id_for_global_media_controls_;

  // All access is on the IO thread, and taking a weak pointer to const looks
  // const, so this can be mutable.
  mutable base::WeakPtrFactory<const AudioOutputAuthorizationHandler>
      weak_factory_{this};
};

}  // namespace content

#endif  // CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_OUTPUT_AUTHORIZATION_HANDLER_H_