| /* |
| * Copyright (C) 2017 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| * THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "config.h" |
| #include "InitDataRegistry.h" |
| |
| #if ENABLE(ENCRYPTED_MEDIA) |
| |
| #include "NotImplemented.h" |
| #include "SharedBuffer.h" |
| #include <wtf/JSONValues.h> |
| #include <wtf/NeverDestroyed.h> |
| #include <wtf/text/Base64.h> |
| |
| |
| namespace WebCore { |
| |
| static Vector<Ref<SharedBuffer>> extractKeyIDsKeyids(const SharedBuffer& buffer) |
| { |
| // 1. Format |
| // https://w3c.github.io/encrypted-media/format-registry/initdata/keyids.html#format |
| if (buffer.size() > std::numeric_limits<unsigned>::max()) |
| return { }; |
| String json { buffer.data(), static_cast<unsigned>(buffer.size()) }; |
| |
| RefPtr<JSON::Value> value; |
| if (!JSON::Value::parseJSON(json, value)) |
| return { }; |
| |
| RefPtr<JSON::Object> object; |
| if (!value->asObject(object)) |
| return { }; |
| |
| RefPtr<JSON::Array> kidsArray; |
| if (!object->getArray("kids", kidsArray)) |
| return { }; |
| |
| Vector<Ref<SharedBuffer>> keyIDs; |
| for (auto& value : *kidsArray) { |
| String keyID; |
| if (!value->asString(keyID)) |
| continue; |
| |
| Vector<char> keyIDData; |
| if (!WTF::base64URLDecode(keyID, { keyIDData })) |
| continue; |
| |
| Ref<SharedBuffer> keyIDBuffer = SharedBuffer::create(WTFMove(keyIDData)); |
| keyIDs.append(WTFMove(keyIDBuffer)); |
| } |
| |
| return keyIDs; |
| } |
| |
| static RefPtr<SharedBuffer> sanitizeKeyids(const SharedBuffer& buffer) |
| { |
| // 1. Format |
| // https://w3c.github.io/encrypted-media/format-registry/initdata/keyids.html#format |
| Vector<Ref<SharedBuffer>> keyIDBuffer = extractKeyIDsKeyids(buffer); |
| if (keyIDBuffer.isEmpty()) |
| return nullptr; |
| |
| auto object = JSON::Object::create(); |
| auto kidsArray = JSON::Array::create(); |
| for (auto& buffer : keyIDBuffer) |
| kidsArray->pushString(WTF::base64URLEncode(buffer->data(), buffer->size())); |
| object->setArray("kids", WTFMove(kidsArray)); |
| |
| CString jsonData = object->toJSONString().utf8(); |
| return SharedBuffer::create(jsonData.data(), jsonData.length()); |
| } |
| |
| static RefPtr<SharedBuffer> sanitizeCenc(const SharedBuffer& buffer) |
| { |
| // 4. Common SystemID and PSSH Box Format |
| // https://w3c.github.io/encrypted-media/format-registry/initdata/cenc.html#common-system |
| notImplemented(); |
| return buffer.copy(); |
| } |
| |
| static Vector<Ref<SharedBuffer>> extractKeyIDsCenc(const SharedBuffer&) |
| { |
| // 4. Common SystemID and PSSH Box Format |
| // https://w3c.github.io/encrypted-media/format-registry/initdata/cenc.html#common-system |
| notImplemented(); |
| return { }; |
| } |
| |
| static RefPtr<SharedBuffer> sanitizeWebM(const SharedBuffer& buffer) |
| { |
| // 1. Format |
| // https://w3c.github.io/encrypted-media/format-registry/initdata/webm.html#format |
| notImplemented(); |
| return buffer.copy(); |
| } |
| |
| static Vector<Ref<SharedBuffer>> extractKeyIDsWebM(const SharedBuffer&) |
| { |
| // 1. Format |
| // https://w3c.github.io/encrypted-media/format-registry/initdata/webm.html#format |
| notImplemented(); |
| return { }; |
| } |
| |
| InitDataRegistry& InitDataRegistry::shared() |
| { |
| static NeverDestroyed<InitDataRegistry> registry; |
| return registry.get(); |
| } |
| |
| InitDataRegistry::InitDataRegistry() |
| { |
| registerInitDataType("keyids", { sanitizeKeyids, extractKeyIDsKeyids }); |
| registerInitDataType("cenc", { sanitizeCenc, extractKeyIDsCenc }); |
| registerInitDataType("webm", { sanitizeWebM, extractKeyIDsWebM }); |
| } |
| |
| InitDataRegistry::~InitDataRegistry() = default; |
| |
| RefPtr<SharedBuffer> InitDataRegistry::sanitizeInitData(const AtomicString& initDataType, const SharedBuffer& buffer) |
| { |
| auto iter = m_types.find(initDataType); |
| if (iter == m_types.end() || !iter->value.sanitizeInitData) |
| return nullptr; |
| return iter->value.sanitizeInitData(buffer); |
| } |
| |
| Vector<Ref<SharedBuffer>> InitDataRegistry::extractKeyIDs(const AtomicString& initDataType, const SharedBuffer& buffer) |
| { |
| auto iter = m_types.find(initDataType); |
| if (iter == m_types.end() || !iter->value.sanitizeInitData) |
| return { }; |
| return iter->value.extractKeyIDs(buffer); |
| } |
| |
| void InitDataRegistry::registerInitDataType(const AtomicString& initDataType, InitDataTypeCallbacks&& callbacks) |
| { |
| ASSERT(!m_types.contains(initDataType)); |
| m_types.set(initDataType, WTFMove(callbacks)); |
| } |
| |
| } |
| |
| #endif // ENABLE(ENCRYPTED_MEDIA) |