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

content / browser / media / cdm_registry_impl.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_MEDIA_CDM_REGISTRY_IMPL_H_
#define CONTENT_BROWSER_MEDIA_CDM_REGISTRY_IMPL_H_

#include <vector>

#include "base/callback_list.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/thread_annotations.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
#include "content/public/browser/cdm_registry.h"
#include "content/public/browser/gpu_data_manager_observer.h"
#include "content/public/common/cdm_info.h"
#include "media/base/cdm_capability.h"
#include "media/base/key_system_capability.h"
#include "media/mojo/mojom/key_system_support.mojom.h"

namespace content {

// Map from `key_system` string to `KeySystemCapability`.
using KeySystemCapabilities =
    base::flat_map<std::string, media::KeySystemCapability>;
using KeySystemCapabilitiesUpdateCB =
    base::RepeatingCallback<void(KeySystemCapabilities)>;

class CONTENT_EXPORT CdmRegistryImpl : public CdmRegistry,
                                       public GpuDataManagerObserver {
 public:
  // Returns the CdmRegistryImpl singleton.
  static CdmRegistryImpl* GetInstance();

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

  // CdmRegistry implementation.
  void Init() override;
  void RegisterCdm(const CdmInfo& info) override;
  void SetHardwareSecureCdmStatus(CdmInfo::Status status) override;

  // GpuDataManagerObserver implementation.
  void OnGpuInfoUpdate() override;

  // Returns all registered CDMs. There might be multiple CdmInfo registered for
  // the same `key_system` and `robustness`. Notes:
  // - Only the first registered one will be used in playback.
  // - The returned CdmInfo's capability might not have been finalized.
  const std::vector<CdmInfo>& GetRegisteredCdms() const;

  // Returns CdmInfo registered for `key_system` and `robustness`. Returns null
  // if no CdmInfo is registered, or if the CdmInfo registered is invalid. There
  // might be multiple CdmInfo registered for the same `key_system` and
  // `robustness`, in which case the first registered one will be returned. The
  // returned CdmInfo's capability might not have been finalized.
  std::unique_ptr<CdmInfo> GetCdmInfo(const std::string& key_system,
                                      CdmInfo::Robustness robustness) const;

  // Observes key system capabilities updates. The updated capabilities are
  // guaranteed to be finalized. The `cb` is always called on the original
  // thread this function was called on. If `allow_hw_secure_capability_check`
  // is true, then `this` is allowed to check capability for hardware secure key
  // systems.
  //
  // Returns a `base::CallbackListSubscription` which is owned by the caller. If
  // that is destroyed, the `cb` is cancelled.
  base::CallbackListSubscription ObserveKeySystemCapabilities(
      bool allow_hw_secure_capability_check,
      KeySystemCapabilitiesUpdateCB cb);

 private:
  // Make the test a friend class so it could create CdmRegistryImpl directly,
  // to avoid singleton issues.
  friend class CdmRegistryImplTest;

  // Make constructor/destructor private since this is a singleton.
  CdmRegistryImpl();
  ~CdmRegistryImpl() override;

  // Get the capability for `key_system` with robustness `robustness`
  // synchronously. If lazy initialization is needed, return
  // Status::kUninitialized.
  std::pair<std::optional<media::CdmCapability>, CdmInfo::Status> GetCapability(
      const std::string& key_system,
      CdmInfo::Robustness robustness);

  // Get the capability for `key_system` with robustness `robustness`
  // synchronously. All initialization should have been completed.
  std::pair<std::optional<media::CdmCapability>, CdmInfo::Status>
  GetFinalCapability(const std::string& key_system,
                     CdmInfo::Robustness robustness);

  // Finalizes KeySystemCapabilities. May lazy initialize CDM capabilities
  // asynchronously if needed.
  void FinalizeKeySystemCapabilities();

  // Attempt to finalize KeySystemCapability for `key_system` with robustness
  // `robustness`. May lazy initialize it asynchronously if needed.
  void AttemptToFinalizeKeySystemCapability(const std::string& key_system,
                                            CdmInfo::Robustness robustness);

  // Lazily initialize `key_system` with robustness `robustness`, calling
  // `cdm_capability_cb`. Callback may be called synchronously
  // or asynchronously.
  void LazyInitializeCapability(const std::string& key_system,
                                CdmInfo::Robustness robustness,
                                media::CdmCapabilityCB cdm_capability_cb);

  // Called when initialization of `key_system` with robustness `robustness`
  // is complete. `cdm_capability` will be std::nullopt if the key system
  // with specified robustness isn't supported.
  void OnCapabilityInitialized(
      const std::string& key_system,
      const CdmInfo::Robustness robustness,
      std::optional<media::CdmCapability> cdm_capability);

  // Finalizes the CdmInfo corresponding to `key_system` and `robustness` if its
  // CdmCapability is null (lazy initialization). No-op if the CdmInfo does not
  // exist, or if the CdmInfo's CdmCapability is not null. The CdmInfo will be
  // removed if `cdm_capability` is null, since the CDM does not support any
  // capability.
  void FinalizeCapability(const std::string& key_system,
                          const CdmInfo::Robustness robustness,
                          std::optional<media::CdmCapability> cdm_capability,
                          CdmInfo::Status status);

  // When capabilities for all registered key systems have been determined,
  // notify all observers with the updated values. No notification is done
  // if the capabilities have not changed.
  void UpdateAndNotifyKeySystemCapabilities();

  // Returns the set of all registered key systems.
  std::set<std::string> GetSupportedKeySystems() const;

  // Returns the capabailities for all registered key systems.
  KeySystemCapabilities GetKeySystemCapabilities();

  // Sets callbacks to query for secure capability for testing.
  using CapabilityCB =
      base::RepeatingCallback<void(const std::string&,
                                   const CdmInfo::Robustness robustness,
                                   media::CdmCapabilityCB)>;
  void SetCapabilityCBForTesting(CapabilityCB cb);

  std::vector<CdmInfo> cdms_ GUARDED_BY_CONTEXT(sequence_checker_);

  // Observers for `key_system_capabilities_` updates.
  base::RepeatingCallbackList<KeySystemCapabilitiesUpdateCB::RunType>
      key_system_capabilities_update_callbacks_;

  // Cached current KeySystemCapabilities value.
  std::optional<KeySystemCapabilities> key_system_capabilities_;

  // Key system and robustness pairs pending CdmCapability lazy initialization.
  std::set<std::pair<std::string, CdmInfo::Robustness>>
      pending_lazy_initializations_;

  // Callback for testing to avoid device dependency.
  CapabilityCB capability_cb_for_testing_;

  // Whether HW secure capability checking is allowed.
  bool allow_hw_secure_capability_check_ = false;

  SEQUENCE_CHECKER(sequence_checker_);

  base::WeakPtrFactory<CdmRegistryImpl> weak_ptr_factory_{this};
};

}  // namespace content

#endif  // CONTENT_BROWSER_MEDIA_CDM_REGISTRY_IMPL_H_