WebKitMediaKeySession.cpp [plain text]
#include "config.h"
#include "WebKitMediaKeySession.h"
#if ENABLE(LEGACY_ENCRYPTED_MEDIA)
#include "Document.h"
#include "EventLoop.h"
#include "EventNames.h"
#include "Page.h"
#include "SecurityOriginData.h"
#include "Settings.h"
#include "WebKitMediaKeyError.h"
#include "WebKitMediaKeyMessageEvent.h"
#include "WebKitMediaKeys.h"
#include <wtf/FileSystem.h>
#include <wtf/IsoMallocInlines.h>
namespace WebCore {
WTF_MAKE_ISO_ALLOCATED_IMPL(WebKitMediaKeySession);
Ref<WebKitMediaKeySession> WebKitMediaKeySession::create(ScriptExecutionContext& context, WebKitMediaKeys& keys, const String& keySystem)
{
auto session = adoptRef(*new WebKitMediaKeySession(context, keys, keySystem));
session->suspendIfNeeded();
return session;
}
WebKitMediaKeySession::WebKitMediaKeySession(ScriptExecutionContext& context, WebKitMediaKeys& keys, const String& keySystem)
: ActiveDOMObject(&context)
, m_keys(&keys)
, m_keySystem(keySystem)
, m_session(keys.cdm().createSession(*this))
, m_keyRequestTimer(*this, &WebKitMediaKeySession::keyRequestTimerFired)
, m_addKeyTimer(*this, &WebKitMediaKeySession::addKeyTimerFired)
{
if (m_session)
m_sessionId = m_session->sessionId();
}
WebKitMediaKeySession::~WebKitMediaKeySession()
{
if (m_session)
m_session->setClient(nullptr);
}
void WebKitMediaKeySession::close()
{
if (m_session) {
m_session->releaseKeys();
m_session = nullptr;
}
}
RefPtr<ArrayBuffer> WebKitMediaKeySession::cachedKeyForKeyId(const String& keyId) const
{
return m_session ? m_session->cachedKeyForKeyID(keyId) : nullptr;
}
void WebKitMediaKeySession::generateKeyRequest(const String& mimeType, Ref<Uint8Array>&& initData)
{
m_pendingKeyRequests.append({ mimeType, WTFMove(initData) });
m_keyRequestTimer.startOneShot(0_s);
}
void WebKitMediaKeySession::keyRequestTimerFired()
{
ASSERT(m_pendingKeyRequests.size());
if (!m_session)
return;
while (!m_pendingKeyRequests.isEmpty()) {
auto request = m_pendingKeyRequests.takeFirst();
String destinationURL;
WebKitMediaKeyError::Code errorCode = 0;
uint32_t systemCode = 0;
auto keyRequest = m_session->generateKeyRequest(request.mimeType, request.initData.ptr(), destinationURL, errorCode, systemCode);
if (errorCode) {
sendError(errorCode, systemCode);
continue;
}
if (keyRequest)
sendMessage(keyRequest.get(), destinationURL);
}
}
ExceptionOr<void> WebKitMediaKeySession::update(Ref<Uint8Array>&& key)
{
if (!key->length())
return Exception { InvalidAccessError };
m_pendingKeys.append(WTFMove(key));
m_addKeyTimer.startOneShot(0_s);
return { };
}
void WebKitMediaKeySession::addKeyTimerFired()
{
ASSERT(m_pendingKeys.size());
if (!m_session)
return;
while (!m_pendingKeys.isEmpty()) {
auto pendingKey = m_pendingKeys.takeFirst();
unsigned short errorCode = 0;
uint32_t systemCode = 0;
bool didStoreKey = false;
RefPtr<Uint8Array> nextMessage;
didStoreKey = m_session->update(pendingKey.ptr(), nextMessage, errorCode, systemCode);
if (nextMessage)
sendMessage(nextMessage.get(), emptyString());
if (didStoreKey) {
auto keyaddedEvent = Event::create(eventNames().webkitkeyaddedEvent, Event::CanBubble::No, Event::IsCancelable::No);
keyaddedEvent->setTarget(this);
queueTaskToDispatchEvent(*this, TaskSource::Networking, WTFMove(keyaddedEvent));
ASSERT(m_keys);
m_keys->keyAdded();
}
if (errorCode) {
sendError(errorCode, systemCode);
}
}
}
void WebKitMediaKeySession::sendMessage(Uint8Array* message, String destinationURL)
{
auto event = WebKitMediaKeyMessageEvent::create(eventNames().webkitkeymessageEvent, message, destinationURL);
event->setTarget(this);
queueTaskToDispatchEvent(*this, TaskSource::Networking, WTFMove(event));
}
void WebKitMediaKeySession::sendError(MediaKeyErrorCode errorCode, uint32_t systemCode)
{
m_error = WebKitMediaKeyError::create(errorCode, systemCode);
auto keyerrorEvent = Event::create(eventNames().webkitkeyerrorEvent, Event::CanBubble::No, Event::IsCancelable::No);
keyerrorEvent->setTarget(this);
queueTaskToDispatchEvent(*this, TaskSource::Networking, WTFMove(keyerrorEvent));
}
String WebKitMediaKeySession::mediaKeysStorageDirectory() const
{
auto* document = downcast<Document>(scriptExecutionContext());
if (!document)
return emptyString();
auto* page = document->page();
if (!page || page->usesEphemeralSession())
return emptyString();
auto storageDirectory = document->settings().mediaKeysStorageDirectory();
if (storageDirectory.isEmpty())
return emptyString();
return FileSystem::pathByAppendingComponent(storageDirectory, document->securityOrigin().data().databaseIdentifier());
}
bool WebKitMediaKeySession::virtualHasPendingActivity() const
{
return m_keys && m_session;
}
void WebKitMediaKeySession::stop()
{
close();
}
const char* WebKitMediaKeySession::activeDOMObjectName() const
{
return "WebKitMediaKeySession";
}
}
#endif