summaryrefslogtreecommitdiffstats
path: root/dom/media/eme/KeySystemConfig.h
blob: 39027d4401e9de3f4d75b7b26e61fd9108db54ca (plain)
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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef DOM_MEDIA_EME_KEYSYSTEMCONFIG_H_
#define DOM_MEDIA_EME_KEYSYSTEMCONFIG_H_

#include "nsString.h"
#include "nsTArray.h"
#include "mozilla/MozPromise.h"
#include "mozilla/dom/MediaKeysBinding.h"
#include "mozilla/dom/MediaKeySystemAccessBinding.h"

namespace mozilla {

struct KeySystemConfigRequest;

struct KeySystemConfig {
 public:
  using SupportedConfigsPromise =
      MozPromise<nsTArray<KeySystemConfig>, bool /* aIgnored */,
                 /* IsExclusive = */ true>;
  using KeySystemConfigPromise =
      MozPromise<dom::MediaKeySystemConfiguration, bool /* aIgnored */,
                 /* IsExclusive = */ true>;

  // EME MediaKeysRequirement:
  // https://www.w3.org/TR/encrypted-media/#dom-mediakeysrequirement
  enum class Requirement {
    Required = 1,
    Optional = 2,
    NotAllowed = 3,
  };

  // EME MediaKeySessionType:
  // https://www.w3.org/TR/encrypted-media/#dom-mediakeysessiontype
  enum class SessionType {
    Temporary = 1,
    PersistentLicense = 2,
  };

  using EMECodecString = nsCString;
  static constexpr auto EME_CODEC_AAC = "aac"_ns;
  static constexpr auto EME_CODEC_OPUS = "opus"_ns;
  static constexpr auto EME_CODEC_VORBIS = "vorbis"_ns;
  static constexpr auto EME_CODEC_FLAC = "flac"_ns;
  static constexpr auto EME_CODEC_H264 = "h264"_ns;
  static constexpr auto EME_CODEC_AV1 = "av1"_ns;
  static constexpr auto EME_CODEC_VP8 = "vp8"_ns;
  static constexpr auto EME_CODEC_VP9 = "vp9"_ns;
  static constexpr auto EME_CODEC_HEVC = "hevc"_ns;

  using EMEEncryptionSchemeString = nsCString;
  static constexpr auto EME_ENCRYPTION_SCHEME_CENC = "cenc"_ns;
  static constexpr auto EME_ENCRYPTION_SCHEME_CBCS = "cbcs"_ns;

  // A codec can be decrypted-and-decoded by the CDM, or only decrypted
  // by the CDM and decoded by Gecko. Not both.
  struct ContainerSupport {
    ContainerSupport() = default;
    ~ContainerSupport() = default;
    ContainerSupport(const ContainerSupport& aOther) {
      mCodecsDecoded = aOther.mCodecsDecoded.Clone();
      mCodecsDecrypted = aOther.mCodecsDecrypted.Clone();
    }
    ContainerSupport& operator=(const ContainerSupport& aOther) {
      if (this == &aOther) {
        return *this;
      }
      mCodecsDecoded = aOther.mCodecsDecoded.Clone();
      mCodecsDecrypted = aOther.mCodecsDecrypted.Clone();
      return *this;
    }
    ContainerSupport(ContainerSupport&& aOther) = default;
    ContainerSupport& operator=(ContainerSupport&&) = default;

    bool IsSupported() const {
      return !mCodecsDecoded.IsEmpty() || !mCodecsDecrypted.IsEmpty();
    }

    // CDM decrypts and decodes using a DRM robust decoder, and passes decoded
    // samples back to Gecko for rendering.
    bool DecryptsAndDecodes(const EMECodecString& aCodec) const {
      return mCodecsDecoded.Contains(aCodec);
    }

    // CDM decrypts and passes the decrypted samples back to Gecko for decoding.
    bool Decrypts(const EMECodecString& aCodec) const {
      return mCodecsDecrypted.Contains(aCodec);
    }

    void SetCanDecryptAndDecode(const EMECodecString& aCodec) {
      // Can't both decrypt and decrypt-and-decode a codec.
      MOZ_ASSERT(!Decrypts(aCodec));
      // Prevent duplicates.
      MOZ_ASSERT(!DecryptsAndDecodes(aCodec));
      mCodecsDecoded.AppendElement(aCodec);
    }

    void SetCanDecrypt(const EMECodecString& aCodec) {
      // Prevent duplicates.
      MOZ_ASSERT(!Decrypts(aCodec));
      // Can't both decrypt and decrypt-and-decode a codec.
      MOZ_ASSERT(!DecryptsAndDecodes(aCodec));
      mCodecsDecrypted.AppendElement(aCodec);
    }

    EMECodecString GetDebugInfo() const {
      EMECodecString info;
      info.AppendLiteral("decoding-and-decrypting:[");
      for (size_t idx = 0; idx < mCodecsDecoded.Length(); idx++) {
        info.Append(mCodecsDecoded[idx]);
        if (idx + 1 < mCodecsDecoded.Length()) {
          info.AppendLiteral(",");
        }
      }
      info.AppendLiteral("],");
      info.AppendLiteral("decrypting-only:[");
      for (size_t idx = 0; idx < mCodecsDecrypted.Length(); idx++) {
        info.Append(mCodecsDecrypted[idx]);
        if (idx + 1 < mCodecsDecrypted.Length()) {
          info.AppendLiteral(",");
        }
      }
      info.AppendLiteral("]");
      return info;
    }

   private:
    nsTArray<EMECodecString> mCodecsDecoded;
    nsTArray<EMECodecString> mCodecsDecrypted;
  };

  // Return true if given key system is supported on the current device.
  static bool Supports(const nsAString& aKeySystem);

  enum class DecryptionInfo : uint8_t {
    Software,
    Hardware,
  };
  static RefPtr<SupportedConfigsPromise> CreateKeySystemConfigs(
      const nsTArray<KeySystemConfigRequest>& aRequests);
  static void GetGMPKeySystemConfigs(dom::Promise* aPromise);

  KeySystemConfig() = default;
  ~KeySystemConfig() = default;
  explicit KeySystemConfig(const KeySystemConfig& aOther) {
    mKeySystem = aOther.mKeySystem;
    mInitDataTypes = aOther.mInitDataTypes.Clone();
    mPersistentState = aOther.mPersistentState;
    mDistinctiveIdentifier = aOther.mDistinctiveIdentifier;
    mSessionTypes = aOther.mSessionTypes.Clone();
    mVideoRobustness = aOther.mVideoRobustness.Clone();
    mAudioRobustness = aOther.mAudioRobustness.Clone();
    mEncryptionSchemes = aOther.mEncryptionSchemes.Clone();
    mMP4 = aOther.mMP4;
    mWebM = aOther.mWebM;
  }
  KeySystemConfig& operator=(const KeySystemConfig& aOther) {
    if (this == &aOther) {
      return *this;
    }
    mKeySystem = aOther.mKeySystem;
    mInitDataTypes = aOther.mInitDataTypes.Clone();
    mPersistentState = aOther.mPersistentState;
    mDistinctiveIdentifier = aOther.mDistinctiveIdentifier;
    mSessionTypes = aOther.mSessionTypes.Clone();
    mVideoRobustness = aOther.mVideoRobustness.Clone();
    mAudioRobustness = aOther.mAudioRobustness.Clone();
    mEncryptionSchemes = aOther.mEncryptionSchemes.Clone();
    mMP4 = aOther.mMP4;
    mWebM = aOther.mWebM;
    return *this;
  }
  KeySystemConfig(KeySystemConfig&&) = default;
  KeySystemConfig& operator=(KeySystemConfig&&) = default;

  nsString GetDebugInfo() const;

  nsString mKeySystem;
  nsTArray<nsString> mInitDataTypes;
  Requirement mPersistentState = Requirement::NotAllowed;
  Requirement mDistinctiveIdentifier = Requirement::NotAllowed;
  nsTArray<SessionType> mSessionTypes;
  nsTArray<nsString> mVideoRobustness;
  nsTArray<nsString> mAudioRobustness;
  nsTArray<nsString> mEncryptionSchemes;
  ContainerSupport mMP4;
  ContainerSupport mWebM;
  bool mIsHDCP22Compatible = false;

 private:
  static void CreateClearKeyKeySystemConfigs(
      const KeySystemConfigRequest& aRequest,
      nsTArray<KeySystemConfig>& aOutConfigs);
  static void CreateWivineL3KeySystemConfigs(
      const KeySystemConfigRequest& aRequest,
      nsTArray<KeySystemConfig>& aOutConfigs);
};

struct KeySystemConfigRequest final {
  KeySystemConfigRequest(const nsAString& aKeySystem,
                         KeySystemConfig::DecryptionInfo aDecryption)
      : mKeySystem(aKeySystem), mDecryption(aDecryption) {}
  const nsString mKeySystem;
  const KeySystemConfig::DecryptionInfo mDecryption;
};

KeySystemConfig::SessionType ConvertToKeySystemConfigSessionType(
    dom::MediaKeySessionType aType);
const char* SessionTypeToStr(KeySystemConfig::SessionType aType);
const char* RequirementToStr(KeySystemConfig::Requirement aRequirement);

}  // namespace mozilla

#endif  // DOM_MEDIA_EME_KEYSYSTEMCONFIG_H_