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
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181

content / browser / media / media_devices_util.h [blame]

// Copyright 2017 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_MEDIA_MEDIA_DEVICES_UTIL_H_
#define CONTENT_BROWSER_MEDIA_MEDIA_DEVICES_UTIL_H_

#include <optional>
#include <string>
#include <utility>

#include "base/functional/callback.h"
#include "content/common/content_export.h"
#include "content/common/features.h"
#include "content/public/browser/global_routing_id.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "third_party/blink/public/common/mediastream/media_devices.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
#include "url/origin.h"

namespace content {

using DeviceIdCallback = base::OnceCallback<void(const std::string&)>;

class CONTENT_EXPORT MediaDeviceSaltAndOrigin {
 public:
  MediaDeviceSaltAndOrigin(
      std::string device_id_salt,
      url::Origin origin,
      std::string group_id_salt = std::string(),
      bool has_focus = false,
      bool is_background = false,
      std::optional<ukm::SourceId> ukm_source_id = std::nullopt);

  MediaDeviceSaltAndOrigin(const MediaDeviceSaltAndOrigin& other);
  MediaDeviceSaltAndOrigin& operator=(const MediaDeviceSaltAndOrigin& other);

  MediaDeviceSaltAndOrigin(MediaDeviceSaltAndOrigin&& other);
  MediaDeviceSaltAndOrigin& operator=(MediaDeviceSaltAndOrigin&& other);

  ~MediaDeviceSaltAndOrigin();

  static MediaDeviceSaltAndOrigin Empty();

  const std::string& device_id_salt() const { return device_id_salt_; }
  const std::string& group_id_salt() const { return group_id_salt_; }
  const url::Origin& origin() const { return origin_; }
  const std::optional<ukm::SourceId>& ukm_source_id() const {
    return ukm_source_id_;
  }
  bool has_focus() const { return has_focus_; }
  bool is_background() const { return is_background_; }

  void set_device_id_salt(std::string salt) {
    device_id_salt_ = std::move(salt);
  }
  void set_group_id_salt(std::string salt) { group_id_salt_ = std::move(salt); }
  void set_ukm_source_id(std::optional<ukm::SourceId> ukm_source_id) {
    ukm_source_id_ = std::move(ukm_source_id);
  }
  void set_origin(url::Origin origin) { origin_ = std::move(origin); }
  void set_has_focus(bool has_focus) { has_focus_ = has_focus; }
  void set_is_background(bool is_background) { is_background_ = is_background; }

 private:
  std::string device_id_salt_;
  std::string group_id_salt_;
  // Last committed origin of the frame making a media device request.
  url::Origin origin_;
  // ukm::SourceId of the main frame making the media device request.
  std::optional<ukm::SourceId> ukm_source_id_;
  bool has_focus_;
  bool is_background_;
};

// Returns the current media device ID salt and security origin for the given
// `render_frame_host_id`. The returned value can be used to produce unique
// media-device IDs for the origin associated with `render_frame_host_id` and
// it should not be cached since the user can explicitly change it at any time.
// This function must run on the UI thread.
using MediaDeviceSaltAndOriginCallback =
    base::OnceCallback<void(const MediaDeviceSaltAndOrigin&)>;
CONTENT_EXPORT void GetMediaDeviceSaltAndOrigin(
    GlobalRenderFrameHostId render_frame_host_id,
    MediaDeviceSaltAndOriginCallback callback);

// Type definition to make it easier to use mock alternatives to
// GetMediaDeviceSaltAndOrigin.
using GetMediaDeviceSaltAndOriginCallback =
    base::RepeatingCallback<void(GlobalRenderFrameHostId,
                                 MediaDeviceSaltAndOriginCallback)>;

// Returns a translated (HMAC) version of (raw) `device_info` suitable for use
// in a renderer process.
// The `device_id` field is hashed using the `device_id_salt` and `origin` in
// `salt_and_origin`.
// The `group_id` field is hashed using the `group_id_salt` and `origin` in
// `salt_and_origin`.
// If `has_permission` is false all fields in the returned value are empty.
CONTENT_EXPORT blink::WebMediaDeviceInfo TranslateMediaDeviceInfo(
    bool has_permission,
    const MediaDeviceSaltAndOrigin& salt_and_origin,
    const blink::WebMediaDeviceInfo& device_info);

// Returns a translated (HMAC) version of raw `device_infos`, with each element
// translated using TranslateMediaDeviceInfo(). If `has_permission` is false,
// the output will contain at most one element per device type with empty values
// for all fields, as per
// https://w3c.github.io/mediacapture-main/#access-control-model
CONTENT_EXPORT blink::WebMediaDeviceInfoArray TranslateMediaDeviceInfoArray(
    bool has_permission,
    const MediaDeviceSaltAndOrigin& salt_and_origin,
    const blink::WebMediaDeviceInfoArray& device_infos);

// Creates a random salt that can be used to generate media device IDs that can
// be sent to the renderer process.
CONTENT_EXPORT std::string CreateRandomMediaDeviceIDSalt();

// Returns via `hmac_device_id_callback` an HMAC-translated version of
//`raw_device_id` suitable for use by the given `render_frame_host_id`.
CONTENT_EXPORT void GetHMACFromRawDeviceId(
    GlobalRenderFrameHostId render_frame_host_id,
    const std::string& raw_device_id,
    DeviceIdCallback hmac_device_id_callback);

using OptionalDeviceIdCallback =
    base::OnceCallback<void(const std::optional<std::string>&)>;
// Returns via `raw_device_id_callback` the raw version of `hmac_device_id`.
// The salt for the given `render_frame_host_id` is used to translate
// `hmac_device_id`. If no device of type `media_device_type` which corresponds
// to the given `hmac_device_id` is found in the system, this function returns
// `std::nullopt`.
CONTENT_EXPORT void GetRawDeviceIdFromHMAC(
    GlobalRenderFrameHostId render_frame_host_id,
    const std::string& hmac_device_id,
    blink::mojom::MediaDeviceType media_device_type,
    OptionalDeviceIdCallback raw_device_id_callback);

// Generates an HMAC device ID for `raw_device_id` using the given
// `salt_and_origin`. If `use_group_salt` is true,
// `salt_and_origin.group_id_salt()` will be used as salt. Otherwise,
// `salt_and_origin.device_id_salt()` is used as salt.
CONTENT_EXPORT std::string GetHMACForRawMediaDeviceID(
    const MediaDeviceSaltAndOrigin& salt_and_origin,
    const std::string& raw_device_id,
    bool use_group_salt = false);

// Checks if `hmac_device_id` is an HMAC of |raw_device_id| for the given
// `salt_and_origin`.
CONTENT_EXPORT bool DoesRawMediaDeviceIDMatchHMAC(
    const MediaDeviceSaltAndOrigin& salt_and_origin,
    const std::string& hmac_device_id,
    const std::string& raw_unique_id);

// Returns the raw device ID for `hmac_device_id` for the given
// `salt_and_origin`. `stream_type` must be
// blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE or
// blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE. The result will
// be returned via `callback` on the given `task_runner`.
// Must be called on the IO thread.
CONTENT_EXPORT void GetRawDeviceIDForMediaStreamHMAC(
    blink::mojom::MediaStreamType stream_type,
    MediaDeviceSaltAndOrigin salt_and_origin,
    std::string hmac_device_id,
    scoped_refptr<base::SequencedTaskRunner> task_runner,
    OptionalDeviceIdCallback callback);

// Returns the raw device ID of type `device_type` for `hmac_device_id` for the
// given `salt_and_origin`. The result will be returned via `callback` on the
// given `task_runner`.
// Must be called on the IO thread.
CONTENT_EXPORT void GetRawDeviceIDForMediaDeviceHMAC(
    blink::mojom::MediaDeviceType device_type,
    MediaDeviceSaltAndOrigin salt_and_origin,
    std::string hmac_device_id,
    scoped_refptr<base::SequencedTaskRunner> task_runner,
    OptionalDeviceIdCallback callback);

}  // namespace content

#endif  // CONTENT_BROWSER_MEDIA_MEDIA_DEVICES_UTIL_H_