Skip to content

Commit b784ef5

Browse files
committed
Return extracted key ids as an optional
https://bugs.webkit.org/show_bug.cgi?id=188303 Reviewed by Darin Adler. An empty list of extracted key ids was being considered a failure case before this patch. In the PSSH boxes from the CENC standard, it's not uncommon for the box to be version 0, meaning it has no embedded key ids, so the case when there's an empty list should not be treated as an error. Given this, the interface should be more general and allow for a sentinel value indicating a parsing error rather than an absence of key ids. Covered by existing tests. * Modules/encryptedmedia/InitDataRegistry.cpp: (WebCore::extractKeyIDsKeyids): Change return type to be wrapped in an optional, and make parsing errors return a nullopt rather than an empty vector. (WebCore::sanitizeKeyids): Use the new optional interface, return a null RefPtr in the case of a parsing error, this method may now return an empty vector. (WebCore::extractKeyIDsCenc): Not implemented, so return an error value rather than an empty vector. (WebCore::extractKeyIDsWebM): Ditto. (WebCore::InitDataRegistry::extractKeyIDs): Ditto. * Modules/encryptedmedia/InitDataRegistry.h: Update the interface to use an optional return type. * platform/graphics/avfoundation/CDMFairPlayStreaming.cpp: (WebCore::CDMPrivateFairPlayStreaming::extractKeyIDsSinf): Update to use the new interface. (WebCore::CDMPrivateFairPlayStreaming::extractKeyIDsSkd): Ditto. * platform/graphics/avfoundation/CDMFairPlayStreaming.h: Ditto. * platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm: (WebCore::CDMInstanceFairPlayStreamingAVFObjC::keyIDs): Convert the optional value into a vector, since it is assumed you can not have an empty vector of key ids in the init datas FPS supports. * testing/MockCDMFactory.cpp: (WebCore::MockCDMInstance::requestLicense): Only return an error if there really was a parsing error, rather than the case of there being zero key ids in the init data payload. Canonical link: https://commits.webkit.org/203450@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@234603 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent 913f8ca commit b784ef5

7 files changed

Lines changed: 73 additions & 25 deletions

File tree

Source/WebCore/ChangeLog

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,47 @@
1+
2018-08-06 Charlie Turner <[email protected]>
2+
3+
Return extracted key ids as an optional
4+
https://bugs.webkit.org/show_bug.cgi?id=188303
5+
6+
Reviewed by Darin Adler.
7+
8+
An empty list of extracted key ids was being considered a failure
9+
case before this patch. In the PSSH boxes from the CENC standard,
10+
it's not uncommon for the box to be version 0, meaning it has no
11+
embedded key ids, so the case when there's an empty list should
12+
not be treated as an error. Given this, the interface should be
13+
more general and allow for a sentinel value indicating a parsing
14+
error rather than an absence of key ids.
15+
16+
Covered by existing tests.
17+
18+
* Modules/encryptedmedia/InitDataRegistry.cpp:
19+
(WebCore::extractKeyIDsKeyids): Change return type to be wrapped
20+
in an optional, and make parsing errors return a nullopt rather
21+
than an empty vector.
22+
(WebCore::sanitizeKeyids): Use the new optional interface, return
23+
a null RefPtr in the case of a parsing error, this method may now
24+
return an empty vector.
25+
(WebCore::extractKeyIDsCenc): Not implemented, so return an error
26+
value rather than an empty vector.
27+
(WebCore::extractKeyIDsWebM): Ditto.
28+
(WebCore::InitDataRegistry::extractKeyIDs): Ditto.
29+
* Modules/encryptedmedia/InitDataRegistry.h: Update the interface
30+
to use an optional return type.
31+
* platform/graphics/avfoundation/CDMFairPlayStreaming.cpp:
32+
(WebCore::CDMPrivateFairPlayStreaming::extractKeyIDsSinf): Update
33+
to use the new interface.
34+
(WebCore::CDMPrivateFairPlayStreaming::extractKeyIDsSkd): Ditto.
35+
* platform/graphics/avfoundation/CDMFairPlayStreaming.h: Ditto.
36+
* platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm:
37+
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::keyIDs): Convert
38+
the optional value into a vector, since it is assumed you can not
39+
have an empty vector of key ids in the init datas FPS supports.
40+
* testing/MockCDMFactory.cpp:
41+
(WebCore::MockCDMInstance::requestLicense): Only return an error
42+
if there really was a parsing error, rather than the case of there
43+
being zero key ids in the init data payload.
44+
145
2018-08-06 Frederic Wang <[email protected]>
246

347
Make two-arguments versions of scrollBy/scrollTo depend on the one-argument versions

Source/WebCore/Modules/encryptedmedia/InitDataRegistry.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,25 +37,25 @@
3737

3838
namespace WebCore {
3939

40-
static Vector<Ref<SharedBuffer>> extractKeyIDsKeyids(const SharedBuffer& buffer)
40+
static std::optional<Vector<Ref<SharedBuffer>>> extractKeyIDsKeyids(const SharedBuffer& buffer)
4141
{
4242
// 1. Format
4343
// https://w3c.github.io/encrypted-media/format-registry/initdata/keyids.html#format
4444
if (buffer.size() > std::numeric_limits<unsigned>::max())
45-
return { };
45+
return std::nullopt;
4646
String json { buffer.data(), static_cast<unsigned>(buffer.size()) };
4747

4848
RefPtr<JSON::Value> value;
4949
if (!JSON::Value::parseJSON(json, value))
50-
return { };
50+
return std::nullopt;
5151

5252
RefPtr<JSON::Object> object;
5353
if (!value->asObject(object))
54-
return { };
54+
return std::nullopt;
5555

5656
RefPtr<JSON::Array> kidsArray;
5757
if (!object->getArray("kids", kidsArray))
58-
return { };
58+
return std::nullopt;
5959

6060
Vector<Ref<SharedBuffer>> keyIDs;
6161
for (auto& value : *kidsArray) {
@@ -78,13 +78,13 @@ static RefPtr<SharedBuffer> sanitizeKeyids(const SharedBuffer& buffer)
7878
{
7979
// 1. Format
8080
// https://w3c.github.io/encrypted-media/format-registry/initdata/keyids.html#format
81-
Vector<Ref<SharedBuffer>> keyIDBuffer = extractKeyIDsKeyids(buffer);
82-
if (keyIDBuffer.isEmpty())
81+
auto keyIDBuffer = extractKeyIDsKeyids(buffer);
82+
if (!keyIDBuffer)
8383
return nullptr;
8484

8585
auto object = JSON::Object::create();
8686
auto kidsArray = JSON::Array::create();
87-
for (auto& buffer : keyIDBuffer)
87+
for (auto& buffer : keyIDBuffer.value())
8888
kidsArray->pushString(WTF::base64URLEncode(buffer->data(), buffer->size()));
8989
object->setArray("kids", WTFMove(kidsArray));
9090

@@ -100,12 +100,12 @@ static RefPtr<SharedBuffer> sanitizeCenc(const SharedBuffer& buffer)
100100
return buffer.copy();
101101
}
102102

103-
static Vector<Ref<SharedBuffer>> extractKeyIDsCenc(const SharedBuffer&)
103+
static std::optional<Vector<Ref<SharedBuffer>>> extractKeyIDsCenc(const SharedBuffer&)
104104
{
105105
// 4. Common SystemID and PSSH Box Format
106106
// https://w3c.github.io/encrypted-media/format-registry/initdata/cenc.html#common-system
107107
notImplemented();
108-
return { };
108+
return std::nullopt;
109109
}
110110

111111
static RefPtr<SharedBuffer> sanitizeWebM(const SharedBuffer& buffer)
@@ -116,12 +116,12 @@ static RefPtr<SharedBuffer> sanitizeWebM(const SharedBuffer& buffer)
116116
return buffer.copy();
117117
}
118118

119-
static Vector<Ref<SharedBuffer>> extractKeyIDsWebM(const SharedBuffer&)
119+
static std::optional<Vector<Ref<SharedBuffer>>> extractKeyIDsWebM(const SharedBuffer&)
120120
{
121121
// 1. Format
122122
// https://w3c.github.io/encrypted-media/format-registry/initdata/webm.html#format
123123
notImplemented();
124-
return { };
124+
return std::nullopt;
125125
}
126126

127127
InitDataRegistry& InitDataRegistry::shared()
@@ -147,11 +147,11 @@ RefPtr<SharedBuffer> InitDataRegistry::sanitizeInitData(const AtomicString& init
147147
return iter->value.sanitizeInitData(buffer);
148148
}
149149

150-
Vector<Ref<SharedBuffer>> InitDataRegistry::extractKeyIDs(const AtomicString& initDataType, const SharedBuffer& buffer)
150+
std::optional<Vector<Ref<SharedBuffer>>> InitDataRegistry::extractKeyIDs(const AtomicString& initDataType, const SharedBuffer& buffer)
151151
{
152152
auto iter = m_types.find(initDataType);
153153
if (iter == m_types.end() || !iter->value.sanitizeInitData)
154-
return { };
154+
return std::nullopt;
155155
return iter->value.extractKeyIDs(buffer);
156156
}
157157

Source/WebCore/Modules/encryptedmedia/InitDataRegistry.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
#include <wtf/Function.h>
3131
#include <wtf/HashMap.h>
32+
#include <wtf/Optional.h>
3233
#include <wtf/Ref.h>
3334
#include <wtf/RefPtr.h>
3435
#include <wtf/Vector.h>
@@ -45,11 +46,11 @@ class InitDataRegistry {
4546
friend class NeverDestroyed<InitDataRegistry>;
4647

4748
RefPtr<SharedBuffer> sanitizeInitData(const AtomicString& initDataType, const SharedBuffer&);
48-
WEBCORE_EXPORT Vector<Ref<SharedBuffer>> extractKeyIDs(const AtomicString& initDataType, const SharedBuffer&);
49+
WEBCORE_EXPORT std::optional<Vector<Ref<SharedBuffer>>> extractKeyIDs(const AtomicString& initDataType, const SharedBuffer&);
4950

5051
struct InitDataTypeCallbacks {
5152
using SanitizeInitDataCallback = Function<RefPtr<SharedBuffer>(const SharedBuffer&)>;
52-
using ExtractKeyIDsCallback = Function<Vector<Ref<SharedBuffer>>(const SharedBuffer&)>;
53+
using ExtractKeyIDsCallback = Function<std::optional<Vector<Ref<SharedBuffer>>>(const SharedBuffer&)>;
5354

5455
SanitizeInitDataCallback sanitizeInitData;
5556
ExtractKeyIDsCallback extractKeyIDs;

Source/WebCore/platform/graphics/avfoundation/CDMFairPlayStreaming.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,8 @@ static SchemeAndKeyResult extractSchemeAndKeyIdFromSinf(const SharedBuffer& buff
158158
return result;
159159
}
160160

161-
Vector<Ref<SharedBuffer>> CDMPrivateFairPlayStreaming::extractKeyIDsSinf(const SharedBuffer& buffer)
161+
std::optional<Vector<Ref<SharedBuffer>>> CDMPrivateFairPlayStreaming::extractKeyIDsSinf(const SharedBuffer& buffer)
162162
{
163-
164163
Vector<Ref<SharedBuffer>> keyIDs;
165164
auto results = extractSchemeAndKeyIdFromSinf(buffer);
166165

@@ -187,7 +186,7 @@ RefPtr<SharedBuffer> CDMPrivateFairPlayStreaming::sanitizeSkd(const SharedBuffer
187186
return buffer.copy();
188187
}
189188

190-
Vector<Ref<SharedBuffer>> CDMPrivateFairPlayStreaming::extractKeyIDsSkd(const SharedBuffer& buffer)
189+
std::optional<Vector<Ref<SharedBuffer>>> CDMPrivateFairPlayStreaming::extractKeyIDsSkd(const SharedBuffer& buffer)
191190
{
192191
// In the 'skd' scheme, the init data is the key ID.
193192
Vector<Ref<SharedBuffer>> keyIDs;

Source/WebCore/platform/graphics/avfoundation/CDMFairPlayStreaming.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ class CDMPrivateFairPlayStreaming final : public CDMPrivate {
6868
std::optional<String> sanitizeSessionId(const String&) const override;
6969

7070
static const AtomicString& sinfName();
71-
static Vector<Ref<SharedBuffer>> extractKeyIDsSinf(const SharedBuffer&);
71+
static std::optional<Vector<Ref<SharedBuffer>>> extractKeyIDsSinf(const SharedBuffer&);
7272
static RefPtr<SharedBuffer> sanitizeSinf(const SharedBuffer&);
7373

7474
static const AtomicString& skdName();
75-
static Vector<Ref<SharedBuffer>> extractKeyIDsSkd(const SharedBuffer&);
75+
static std::optional<Vector<Ref<SharedBuffer>>> extractKeyIDsSkd(const SharedBuffer&);
7676
static RefPtr<SharedBuffer> sanitizeSkd(const SharedBuffer&);
7777
};
7878

Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,12 @@ - (void)contentKeySessionContentProtectionSessionIdentifierDidChange:(AVContentK
241241
return Vector<Ref<SharedBuffer>>::from(SharedBuffer::create([(NSString *)m_request.get().identifier dataUsingEncoding:NSUTF8StringEncoding]));
242242
if ([m_request.get().identifier isKindOfClass:[NSData class]])
243243
return Vector<Ref<SharedBuffer>>::from(SharedBuffer::create((NSData *)m_request.get().identifier));
244-
if (m_request.get().initializationData)
245-
return CDMPrivateFairPlayStreaming::extractKeyIDsSinf(SharedBuffer::create(m_request.get().initializationData));
244+
if (m_request.get().initializationData) {
245+
auto sinfKeyIDs = CDMPrivateFairPlayStreaming::extractKeyIDsSinf(SharedBuffer::create(m_request.get().initializationData));
246+
if (!sinfKeyIDs)
247+
return { };
248+
return WTFMove(sinfKeyIDs.value());
249+
}
246250
return { };
247251
}
248252

Source/WebCore/testing/MockCDMFactory.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,13 +283,13 @@ void MockCDMInstance::requestLicense(LicenseType licenseType, const AtomicString
283283
}
284284

285285
auto keyIDs = InitDataRegistry::shared().extractKeyIDs(initDataType, initData);
286-
if (keyIDs.isEmpty()) {
286+
if (!keyIDs || keyIDs.value().isEmpty()) {
287287
callback(SharedBuffer::create(), emptyString(), false, SuccessValue::Failed);
288288
return;
289289
}
290290

291291
String sessionID = createCanonicalUUIDString();
292-
factory->addKeysToSessionWithID(sessionID, WTFMove(keyIDs));
292+
factory->addKeysToSessionWithID(sessionID, WTFMove(keyIDs.value()));
293293

294294
CString license { "license" };
295295
callback(SharedBuffer::create(license.data(), license.length()), sessionID, false, SuccessValue::Succeeded);

0 commit comments

Comments
 (0)